diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..82203984c --- /dev/null +++ b/.gitignore @@ -0,0 +1,111 @@ +#### +# Binary build product files + +**/out +**/Payload/ +**/PrebidMobileDemo.app/ +#**/Products +**/screenshot* + +######################################################################################## +# macOS.gitignore +# https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +######################################################################################## + +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +######################################################################################## +# Xcode.gitignore +# https://github.com/github/gitignore/blob/master/Global/Xcode.gitignore +######################################################################################## + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +######################################################################################## +# Objective-C.gitignore +# https://github.com/github/gitignore/blob/master/Objective-C.gitignore +######################################################################################## + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xcuserstate + +## Obj-C/Swift specific +*.hmap +#*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..72ff93033 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: objective-c +osx_image: xcode8 +script: +- ./scripts/buildPrebidMobile.sh +- ./scripts/testPrebidMobile.sh \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..55517b8fd --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Prebid Mobile iOS SDK + +Get started with Prebid Mobile by creating a Prebid Server account [here](http://prebid.org/prebid-mobile/prebid-mobile-pbs.html) + +## Use Cocoapods? + +Easily include the Prebid Mobile SDK for your priamy ad server in your Podfile/ + +``` +platform :ios, '8.0' + +target 'MyAmazingApp' do + pod 'PrebidMobile' +end +``` + +## Build framework from source + +Build Prebid Mobile from source code. After cloning the repo, from the root directory run + +``` +./scripts/buildPrebidMobile.sh +``` + +to output the PrebidMobileForDFP & PrebidMobileForMoPub frameworks. + + +## Test Prebid Mobile + +Run the test script to run unit tests and integration tests. + +``` +./scripts/testPrebidMobile.sh +``` diff --git a/examples/PrebidMobileDemo/Gemfile b/examples/PrebidMobileDemo/Gemfile new file mode 100644 index 000000000..f3f8ce97b --- /dev/null +++ b/examples/PrebidMobileDemo/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "calabash-cucumber", ">= 0.20.4", "< 2.0" +gem 'rspec' + diff --git a/examples/PrebidMobileDemo/Gemfile.lock b/examples/PrebidMobileDemo/Gemfile.lock new file mode 100644 index 000000000..0d04a23fb --- /dev/null +++ b/examples/PrebidMobileDemo/Gemfile.lock @@ -0,0 +1,73 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.5) + awesome_print (1.7.0) + builder (3.2.3) + calabash-cucumber (0.20.4) + awesome_print + bundler (~> 1.3) + clipboard (~> 1.0) + cucumber + edn (>= 1.0.6, < 2.0) + geocoder (>= 1.1.8, < 2.0) + httpclient (>= 2.7.1, < 3.0) + json + run_loop (>= 2.2.4, < 3.0) + slowhandcuke (~> 0.0.3) + clipboard (1.1.1) + command_runner_ng (0.1.0) + cucumber (2.4.0) + builder (>= 2.1.2) + cucumber-core (~> 1.5.0) + cucumber-wire (~> 0.0.1) + diff-lcs (>= 1.1.3) + gherkin (~> 4.0) + multi_json (>= 1.7.5, < 2.0) + multi_test (>= 0.1.2) + cucumber-core (1.5.0) + gherkin (~> 4.0) + cucumber-wire (0.0.1) + diff-lcs (1.3) + edn (1.1.1) + geocoder (1.4.3) + gherkin (4.1.1) + httpclient (2.8.3) + i18n (0.8.1) + json (1.8.6) + multi_json (1.12.1) + multi_test (0.1.2) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + run_loop (2.3.1) + CFPropertyList (~> 2.2) + awesome_print (~> 1.2) + command_runner_ng (>= 0.0.2) + httpclient (>= 2.7.1, < 3.0) + i18n (>= 0.7.0, < 1.0) + json (~> 1.8) + thor (>= 0.18.1, < 1.0) + slowhandcuke (0.0.3) + cucumber + thor (0.19.4) + +PLATFORMS + ruby + +DEPENDENCIES + calabash-cucumber (>= 0.20.4, < 2.0) + rspec + +BUNDLED WITH + 1.14.6 diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/GoogleMobileAds b/examples/PrebidMobileDemo/GoogleMobileAds.framework/GoogleMobileAds new file mode 100755 index 000000000..e5a9958b0 Binary files /dev/null and b/examples/PrebidMobileDemo/GoogleMobileAds.framework/GoogleMobileAds differ diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPBannerView.h new file mode 100755 index 000000000..95e0f7c0b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPBannerView.h @@ -0,0 +1,94 @@ +// +// DFPBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays DoubleClick For Publishers banner ads. +@interface DFPBannerView : GADBannerView + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and statistics. +/// +/// Example DFP ad unit ID: @"/6499/example/banner" +@property(nonatomic, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id appEventDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +/// Optional array of NSValue encoded GADAdSize structs, specifying all valid sizes that are +/// appropriate for this slot. Never create your own GADAdSize directly. Use one of the predefined +/// standard ad sizes (such as kGADAdSizeBanner), or create one using the GADAdSizeFromCGSize +/// method. +/// +/// Example: +/// +///
+///   NSArray *validSizes = @[
+///     NSValueFromGADAdSize(kGADAdSizeBanner),
+///     NSValueFromGADAdSize(kGADAdSizeLargeBanner)
+///   ];
+///
+///   bannerView.validAdSizes = validSizes;
+///   
+@property(nonatomic, copy, GAD_NULLABLE) NSArray *validAdSizes; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Indicates that the publisher will record impressions manually when the ad becomes visible to the +/// user. +@property(nonatomic, assign) BOOL enableManualImpressions; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id customRenderedBannerViewDelegate; + +/// Video controller for controlling video rendered by this ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +/// If you've set enableManualImpressions to YES, call this method when the ad is visible. +- (void)recordImpression; + +/// Use this function to resize the banner view without launching a new ad request. +- (void)resize:(GADAdSize)size; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark Deprecated + +/// Deprecated. Use the validAdSizes property. +/// Sets the receiver's valid ad sizes to the values pointed to by the provided NULL terminated list +/// of GADAdSize pointers. +/// +/// Example: +/// +///
+///   GADAdSize size1 = kGADAdSizeBanner;
+///   GADAdSize size2 = kGADAdSizeLargeBanner;
+///   [bannerView setValidAdSizesWithSizes:&size1, &size2, NULL];
+///   
+- (void)setValidAdSizesWithSizes:(GADAdSize *)firstSize, ... NS_REQUIRES_NIL_TERMINATION + GAD_DEPRECATED_MSG_ATTRIBUTE("Use validAdSizes property."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedAd.h new file mode 100755 index 000000000..5c2b0abb4 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedAd.h @@ -0,0 +1,34 @@ +// +// DFPCustomRenderedAd.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Custom rendered ad. Your application renders the ad. +@interface DFPCustomRenderedAd : NSObject + +/// The ad's HTML. +@property(nonatomic, readonly, copy) NSString *adHTML; + +/// The base URL of the ad's HTML. +@property(nonatomic, readonly, copy) NSURL *adBaseURL; + +/// Call this method when the user clicks the ad. +- (void)recordClick; + +/// Call this method when the ad is visible to the user. +- (void)recordImpression; + +/// Call this method after the ad has been rendered in a UIView object. +- (void)finishedRenderingAdView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedBannerViewDelegate.h new file mode 100755 index 000000000..e15b89ebd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedBannerViewDelegate.h @@ -0,0 +1,28 @@ +// +// DFPCustomRenderedBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPBannerView; +@class DFPCustomRenderedAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd banner view delegate protocol for notifying the delegate of changes to +/// custom rendered banners. +@protocol DFPCustomRenderedBannerViewDelegate + +/// Called after ad data has been received. You must construct a banner from |customRenderedAd| and +/// call the |customRenderedAd| object's finishedRenderingAdView: when the ad has been rendered. +- (void)bannerView:(DFPBannerView *)bannerView + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedInterstitialDelegate.h new file mode 100755 index 000000000..0f1f4a8a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPCustomRenderedInterstitialDelegate.h @@ -0,0 +1,29 @@ +// +// DFPCustomRenderedInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPCustomRenderedAd; +@class DFPInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd interstitial delegate protocol for notifying the delegate of changes to +/// custom rendered interstitials. +@protocol DFPCustomRenderedInterstitialDelegate + +/// Called after ad data has been received. You must construct an interstitial from +/// |customRenderedAd| and call the |customRenderedAd| object's finishedRenderingAdView: method when +/// the ad has been rendered. +- (void)interstitial:(DFPInterstitial *)interstitial + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPInterstitial.h new file mode 100755 index 000000000..e3af0d210 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPInterstitial.h @@ -0,0 +1,39 @@ +// +// DFPInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// DoubleClick For Publishers interstitial ad, a full-screen advertisement shown at natural +/// transition points in your application such as between game levels or news stories. +@interface DFPInterstitial : GADInterstitial + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and stats. +/// +/// Example DFP ad unit ID: @"/6499/example/interstitial" +@property(nonatomic, readonly, copy) NSString *adUnitID; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) id appEventDelegate; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + id customRenderedInterstitialDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPRequest.h new file mode 100755 index 000000000..08f070f1b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/DFPRequest.h @@ -0,0 +1,37 @@ +// +// DFPRequest.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kDFPSimulatorID; + +/// Specifies optional parameters for ad requests. +@interface DFPRequest : GADRequest + +/// Publisher provided user ID. +@property(nonatomic, copy, GAD_NULLABLE) NSString *publisherProvidedID; + +/// Array of strings used to exclude specified categories in ad results. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *categoryExclusions; + +/// Key-value pairs used for custom targeting. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *customTargeting; + +/// This API is deprecated and a no-op, use an instance of GADCorrelator set on DFPInterstitial or +/// DFPBannerView objects to correlate requests. ++ (void)updateCorrelator GAD_DEPRECATED_MSG_ATTRIBUTE( + "Set GADCorrelator objects on your ads instead. This method no longer affects ad correlation."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdChoicesView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdChoicesView.h new file mode 100755 index 000000000..c05aeb537 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdChoicesView.h @@ -0,0 +1,23 @@ +// +// GADAdChoicesView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays AdChoices content. +/// +/// If a GADAdChoicesView is set on GADNativeAppInstallAdView or GADNativeContentAdView prior to +/// calling -setNativeAppInstallAd: or -setNativeContentAd:, AdChoices content will render inside +/// the GADAdChoicesView. By default, AdChoices is placed in the top right corner of +/// GADNativeAppInstallAdView and GADNativeContentAdView. +@interface GADAdChoicesView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdDelegate.h new file mode 100755 index 000000000..27cdda03d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdDelegate.h @@ -0,0 +1,28 @@ +// +// GADAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Audio Control Notifications + +/// Delegate methods common to multiple ad types. +@protocol GADAdDelegate + +@optional + +#pragma mark Audio Control Methods + +/// Asks the delegate if the audio session category can be changed while displaying an ad. Return NO +/// to prevent the Google Mobile Ads SDK from changing the audio session category. The default +/// behavior if unimplemented is to return YES. +- (BOOL)ad:(id)ad shouldChangeAudioSessionToCategory:(NSString *)audioSessionCategory; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoader.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoader.h new file mode 100755 index 000000000..44ee5c576 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoader.h @@ -0,0 +1,49 @@ +// +// GADAdLoader.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Loads ads. See GADAdLoaderAdTypes.h for available ad types. +@interface GADAdLoader : NSObject + +/// Object notified when an ad request succeeds or fails. Must conform to requested ad types' +/// delegate protocols. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// The ad loader's ad unit ID. +@property(nonatomic, readonly) NSString *adUnitID; + +/// Returns an initialized ad loader configured to load the specified ad types. +/// +/// @param rootViewController The root view controller is used to present ad click actions. +/// @param adTypes An array of ad types. See GADAdLoaderAdTypes.h for available ad types. +/// @param options An array of GADAdLoaderOptions objects to configure how ads are loaded, or nil to +/// use default options. See each ad type's header for available GADAdLoaderOptions subclasses. +- (instancetype)initWithAdUnitID:(NSString *)adUnitID + rootViewController:(UIViewController *GAD_NULLABLE_TYPE)rootViewController + adTypes:(NSArray *)adTypes + options:(NSArray *GAD_NULLABLE_TYPE)options; + +/// Loads the ad and informs the delegate of the outcome. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +@end + +/// Ad loader options base class. See each ad type's header for available GADAdLoaderOptions +/// subclasses. +@interface GADAdLoaderOptions : NSObject +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderAdTypes.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderAdTypes.h new file mode 100755 index 000000000..76d176236 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderAdTypes.h @@ -0,0 +1,31 @@ +// +// GADAdLoaderAdTypes.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use with GADAdLoader to request native app install ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeAppInstallAdRequestDelegate protocol. See GADNativeAppInstallAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeAppInstall; + +/// Use with GADAdLoader to request native content ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeContentAdRequestDelegate protocol. See GADNativeContentAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeContent; + +/// Use with GADAdLoader to request native custom template ads. To receive ads, the ad loader's +/// delegate must conform to the GADNativeCustomTemplateAdLoaderDelegate protocol. See +/// GADNativeCustomTemplateAd.h. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeCustomTemplate; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderDelegate.h new file mode 100755 index 000000000..dec90b784 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdLoaderDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdLoaderDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADAdLoader; + +GAD_ASSUME_NONNULL_BEGIN + +/// Base ad loader delegate protocol. Ad types provide extended protocols that declare methods to +/// handle successful ad loads. +@protocol GADAdLoaderDelegate + +/// Called when adLoader fails to load an ad. +- (void)adLoader:(GADAdLoader *)adLoader didFailToReceiveAdWithError:(GADRequestError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdNetworkExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdNetworkExtras.h new file mode 100755 index 000000000..55c62f134 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdNetworkExtras.h @@ -0,0 +1,22 @@ +// +// GADAdNetworkExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An object implementing this protocol contains information set by the publisher on the client +/// device for a particular ad network. +/// +/// Ad networks should create an 'extras' object implementing this protocol for their publishers to +/// use. +@protocol GADAdNetworkExtras +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdReward.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdReward.h new file mode 100755 index 000000000..38aeefb55 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdReward.h @@ -0,0 +1,30 @@ +// +// GADAdReward.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Reward information for GADRewardBasedVideoAd ads. +@interface GADAdReward : NSObject + +/// Type of the reward. +@property(nonatomic, readonly, copy) NSString *type; + +/// Amount rewarded to the user. +@property(nonatomic, readonly, copy) NSDecimalNumber *amount; + +/// Returns an initialized GADAdReward with the provided reward type and reward amount. rewardType +/// and rewardAmount must not be nil. +- (instancetype)initWithRewardType:(NSString *)rewardType + rewardAmount:(NSDecimalNumber *)rewardAmount NS_DESIGNATED_INITIALIZER; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSize.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSize.h new file mode 100755 index 000000000..c92b767d2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSize.h @@ -0,0 +1,117 @@ +// +// GADAdSize.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A valid GADAdSize is considered to be one of the predefined GADAdSize constants or a GADAdSize +/// constructed by GADAdSizeFromCGSize, GADAdSizeFullWidthPortraitWithHeight, +/// GADAdSizeFullWidthLandscapeWithHeight. +/// +/// Do not create a GADAdSize manually. Use one of the kGADAdSize constants. Treat GADAdSize as an +/// opaque type. Do not access any fields directly. To obtain a concrete CGSize, use the function +/// CGSizeFromGADAdSize(). +typedef struct GAD_BOXABLE GADAdSize GADAdSize; + +/// Ad size. +/// +/// @see typedef GADAdSize +struct GAD_BOXABLE GADAdSize { + CGSize size; ///< The ad size. Don't modify this value directly. + NSUInteger flags; ///< Reserved. +}; + +#pragma mark Standard Sizes + +/// iPhone and iPod Touch ad size. Typically 320x50. +GAD_EXTERN GADAdSize const kGADAdSizeBanner; + +/// Taller version of kGADAdSizeBanner. Typically 320x100. +GAD_EXTERN GADAdSize const kGADAdSizeLargeBanner; + +/// Medium Rectangle size for the iPad (especially in a UISplitView's left pane). Typically 300x250. +GAD_EXTERN GADAdSize const kGADAdSizeMediumRectangle; + +/// Full Banner size for the iPad (especially in a UIPopoverController or in +/// UIModalPresentationFormSheet). Typically 468x60. +GAD_EXTERN GADAdSize const kGADAdSizeFullBanner; + +/// Leaderboard size for the iPad. Typically 728x90. +GAD_EXTERN GADAdSize const kGADAdSizeLeaderboard; + +/// Skyscraper size for the iPad. Mediation only. AdMob/Google does not offer this size. Typically +/// 120x600. +GAD_EXTERN GADAdSize const kGADAdSizeSkyscraper; + +/// An ad size that spans the full width of the application in portrait orientation. The height is +/// typically 50 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerPortrait; + +/// An ad size that spans the full width of the application in landscape orientation. The height is +/// typically 32 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerLandscape; + +/// An ad size that spans the full width of its container, with a height dynamically determined by +/// the ad. +GAD_EXTERN GADAdSize const kGADAdSizeFluid; + +/// Invalid ad size marker. +GAD_EXTERN GADAdSize const kGADAdSizeInvalid; + +#pragma mark Custom Sizes + +/// Returns a custom GADAdSize for the provided CGSize. Use this only if you require a non-standard +/// size. Otherwise, use one of the standard size constants above. +GAD_EXTERN GADAdSize GADAdSizeFromCGSize(CGSize size); + +/// Returns a custom GADAdSize that spans the full width of the application in portrait orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthPortraitWithHeight(CGFloat height); + +/// Returns a custom GADAdSize that spans the full width of the application in landscape orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthLandscapeWithHeight(CGFloat height); + +#pragma mark Convenience Functions + +/// Returns YES if the two GADAdSizes are equal, otherwise returns NO. +GAD_EXTERN BOOL GADAdSizeEqualToSize(GADAdSize size1, GADAdSize size2); + +/// Returns a CGSize for the provided a GADAdSize constant. If the GADAdSize is unknown, returns +/// CGSizeZero. +GAD_EXTERN CGSize CGSizeFromGADAdSize(GADAdSize size); + +/// Returns YES if |size| is one of the predefined constants or is a custom GADAdSize generated by +/// GADAdSizeFromCGSize. +GAD_EXTERN BOOL IsGADAdSizeValid(GADAdSize size); + +/// Returns YES if |size| is a fluid ad size. +GAD_EXTERN BOOL GADAdSizeIsFluid(GADAdSize size); + +/// Returns a NSString describing the provided GADAdSize. +GAD_EXTERN NSString *NSStringFromGADAdSize(GADAdSize size); + +/// Returns an NSValue representing the GADAdSize. +GAD_EXTERN NSValue *NSValueFromGADAdSize(GADAdSize size); + +/// Returns a GADAdSize from an NSValue. Returns kGADAdSizeInvalid if the value is not a GADAdSize. +GAD_EXTERN GADAdSize GADAdSizeFromNSValue(NSValue *value); + +#pragma mark Deprecated Macros + +#define GAD_SIZE_320x50 CGSizeFromGADAdSize(kGADAdSizeBanner) +#define GAD_SIZE_320x100 CGSizeFromGADAdSize(kGADAdSizeLargeBanner) +#define GAD_SIZE_300x250 CGSizeFromGADAdSize(kGADAdSizeMediumRectangle) +#define GAD_SIZE_468x60 CGSizeFromGADAdSize(kGADAdSizeFullBanner) +#define GAD_SIZE_728x90 CGSizeFromGADAdSize(kGADAdSizeLeaderboard) +#define GAD_SIZE_120x600 CGSizeFromGADAdSize(kGADAdSizeSkyscraper) + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSizeDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSizeDelegate.h new file mode 100755 index 000000000..ce82adceb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAdSizeDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdSizeDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; + +GAD_ASSUME_NONNULL_BEGIN + +/// The class implementing this protocol will be notified when the DFPBannerView changes ad size. +/// Any views that may be affected by the banner size change will have time to adjust. +@protocol GADAdSizeDelegate + +/// Called before the ad view changes to the new size. +- (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAppEventDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAppEventDelegate.h new file mode 100755 index 000000000..a9f79cf14 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADAppEventDelegate.h @@ -0,0 +1,35 @@ +// +// GADAppEventDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADBannerView; +@class GADInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// Implement your app event within these methods. The delegate will be notified when the SDK +/// receives an app event message from the ad. +@protocol GADAppEventDelegate + +@optional + +/// Called when the banner receives an app event. +- (void)adView:(GADBannerView *)banner + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +/// Called when the interstitial receives an app event. +- (void)interstitial:(GADInterstitial *)interstitial + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerView.h new file mode 100755 index 000000000..a93a71b10 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerView.h @@ -0,0 +1,108 @@ +// +// GADBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays banner ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADBannerView *adView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADBannerView : UIView + +#pragma mark Initialization + +/// Initializes and returns a banner view with the specified ad size and origin relative to the +/// banner's superview. +- (instancetype)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Initializes and returns a banner view with the specified ad size placed at its superview's +/// origin. +- (instancetype)initWithAdSize:(GADAdSize)adSize; + +#pragma mark Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example the root view controller in +/// tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this banner view to a proper size. Never create your own GADAdSize directly. Use +/// one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If not using mediation, then changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If using mediation, +/// then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this GADBannerView. +/// Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id inAppPurchaseDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +#pragma mark Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +#pragma mark Mediation + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +#pragma mark Deprecated + +/// Indicates if the currently displayed ad (or most recent failure) was a result of auto refreshing +/// as specified on server. This property is set to NO after each loadRequest: method. +@property(nonatomic, readonly, assign) BOOL hasAutoRefreshed GAD_DEPRECATED_ATTRIBUTE; + +/// The mediated ad network's underlying ad view. You may use this property to read the ad's actual +/// size and adjust this banner view's frame origin. However, modifying the banner view's frame size +/// triggers the Mobile Ads SDK to request a new ad. Only update the banner view's frame origin. +@property(nonatomic, readonly, weak, GAD_NULLABLE) + UIView *mediatedAdView GAD_DEPRECATED_MSG_ATTRIBUTE("Use adNetworkClassName."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerViewDelegate.h new file mode 100755 index 000000000..f977bc479 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADBannerViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADBannerView state change messages such as ad request status +/// and ad click lifecycle. +@protocol GADBannerViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that an ad request successfully received an ad. The delegate may want to add +/// the banner view to the view hierarchy if it hasn't been added yet. +- (void)adViewDidReceiveAd:(GADBannerView *)bannerView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)adView:(GADBannerView *)bannerView didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)adViewWillPresentScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)adViewWillDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)adViewDidDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)adViewWillLeaveApplication:(GADBannerView *)bannerView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelator.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelator.h new file mode 100755 index 000000000..909f0f4cf --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelator.h @@ -0,0 +1,23 @@ +// +// GADCorrelator.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Represents a correlation between multiple ads. Set an instance of this object on multiple ads to +/// indicate they are being used in a common context. +@interface GADCorrelator : NSObject + +/// Resets the correlator to force a new set of correlated ads. +- (void)reset; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelatorAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelatorAdLoaderOptions.h new file mode 100755 index 000000000..b10d60757 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCorrelatorAdLoaderOptions.h @@ -0,0 +1,22 @@ +// +// GADCorrelatorAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad loader options for adding a correlator to a native ad request. +@interface GADCorrelatorAdLoaderOptions : GADAdLoaderOptions + +/// Correlator object for correlating ads loaded by an ad loader to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBanner.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBanner.h new file mode 100755 index 000000000..53317d909 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBanner.h @@ -0,0 +1,40 @@ +// +// GADCustomEventBanner.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The banner custom event protocol. Your banner custom event handler must implement this protocol. +@protocol GADCustomEventBanner + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Report execution results +/// to the delegate. +/// +/// @param adSize The size of the ad as configured in the mediation UI for the mediation placement. +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestBannerAd:(GADAdSize)adSize + parameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBannerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBannerDelegate.h new file mode 100755 index 000000000..8ec685c5c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventBannerDelegate.h @@ -0,0 +1,68 @@ +// +// GADCustomEventBannerDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventBanner; + +/// Call back to this delegate in your custom event. You must call customEventBanner:didReceiveAd: +/// when there is an ad to show, or customEventBanner:didFailAd: when there is no ad to show. +/// Otherwise, if enough time passed (several seconds) after the SDK called the requestBannerAd: +/// method of your custom event, the mediation SDK will consider the request timed out, and move on +/// to the next ad network. +@protocol GADCustomEventBannerDelegate + +/// Your Custom Event object must call this when it receives or creates an ad view. +- (void)customEventBanner:(id)customEvent didReceiveAd:(UIView *)view; + +/// Your Custom Event object must call this when it fails to receive or create the ad view. Pass +/// along any error object sent from the ad network's SDK, or an NSError describing the error. Pass +/// nil if not available. +- (void)customEventBanner:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventBannerWasClicked:(id)customEvent; + +/// The rootViewController that you set in GADBannerView. Use this UIViewController to show a modal +/// view when a user taps on the ad. +@property(nonatomic, readonly) UIViewController *viewControllerForPresentingModalView; + +/// When you call the following methods, the call will be propagated back to the +/// GADBannerViewDelegate that you implemented and passed to GADBannerView. + +/// Your Custom Event should call this when the user taps an ad and a modal view appears. +- (void)customEventBannerWillPresentModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view is +/// about to go away. +- (void)customEventBannerWillDismissModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view has +/// gone away. +- (void)customEventBannerDidDismissModal:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in App switching. +- (void)customEventBannerWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventBannerWasClicked:. +- (void)customEventBanner:(id)customEvent + clickDidOccurInAd:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventBannerWasClicked:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventExtras.h new file mode 100755 index 000000000..a42a35cc1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventExtras.h @@ -0,0 +1,35 @@ +// +// GADCustomEventExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Create an instance of this class to set additional parameters for each custom event object. The +/// additional parameters for a custom event are keyed by the custom event label. These extras are +/// passed to your implementation of GADCustomEventBanner or GADCustomEventInterstitial. +@interface GADCustomEventExtras : NSObject + +/// Set additional parameters for the custom event with label |label|. To remove additional +/// parameters associated with |label|, pass in nil for |extras|. +- (void)setExtras:(NSDictionary *GAD_NULLABLE_TYPE)extras forLabel:(NSString *)label; + +/// Retrieve the extras for |label|. +- (NSDictionary *GAD_NULLABLE_TYPE)extrasForLabel:(NSString *)label; + +/// Removes all the extras set on this instance. +- (void)removeAllExtras; + +/// Returns all the extras set on this instance. +- (NSDictionary *)allExtras; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitial.h new file mode 100755 index 000000000..7a05e3bd6 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitial.h @@ -0,0 +1,43 @@ +// +// GADCustomEventInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The interstitial custom event protocol. Your interstitial custom event handler must implement +/// this protocol. +@protocol GADCustomEventInterstitial + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Your implementation +/// should start retrieving the interstitial ad. Report execution results to the delegate. You must +/// wait until -presentFromRootViewController is called before displaying the interstitial ad. +/// +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestInterstitialAdWithParameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +/// Present the interstitial ad as a modal view using the provided view controller. Called only +/// after your class calls -customEventInterstitialDidReceiveAd: on its custom event delegate. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitialDelegate.h new file mode 100755 index 000000000..97219d3e5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventInterstitialDelegate.h @@ -0,0 +1,62 @@ +// +// GADCustomEventInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventInterstitial; + +/// Call back to this delegate in your custom event. You must call +/// customEventInterstitialDidReceiveAd: when there is an ad to show, or +/// customEventInterstitial:didFailAd: when there is no ad to show. Otherwise, if enough time passed +/// (several seconds) after the SDK called the requestInterstitialAdWithParameter: method of your +/// custom event, the mediation SDK will consider the request timed out, and move on to the next ad +/// network. +@protocol GADCustomEventInterstitialDelegate + +/// Your Custom Event object must call this when it receives or creates an interstitial ad. +- (void)customEventInterstitialDidReceiveAd:(id)customEvent; + +/// Your Custom Event object must call this when it fails to receive or create the ad. Pass along +/// any error object sent from the ad network's SDK, or an NSError describing the error. Pass nil if +/// not available. +- (void)customEventInterstitial:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventInterstitialWasClicked:(id)customEvent; + +// When you call any of the following methods, the call will be propagated back to the +// GADInterstitialDelegate that you implemented and passed to GADInterstitial. + +/// Your Custom Event should call this when the interstitial is being displayed. +- (void)customEventInterstitialWillPresent:(id)customEvent; + +/// Your Custom Event should call this when the interstitial is about to be dismissed. +- (void)customEventInterstitialWillDismiss:(id)customEvent; + +/// Your Custom Event should call this when the interstitial has been dismissed. +- (void)customEventInterstitialDidDismiss:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in app switching. +- (void)customEventInterstitialWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventInterstitialDidReceiveAd:. +- (void)customEventInterstitial:(id)customEvent + didReceiveAd:(NSObject *)ad + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventInterstitialDidReceiveAd:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAd.h new file mode 100755 index 000000000..9a99c7e42 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAd.h @@ -0,0 +1,58 @@ +// +// GADCustomEventNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventNativeAdDelegate; + +/// Native ad custom event protocol. Your native ad custom event handler class must conform to this +/// protocol. +@protocol GADCustomEventNativeAd + +/// Called when the custom event is scheduled to be executed. +/// +/// @param serverParameter A value configured in the mediation UI for the custom event. +/// @param request Ad targeting information. +/// @param adTypes List of requested native ad types. See GADAdLoaderAdTypes.h for available ad +/// types. +/// @param options Additional options configured by the publisher for requesting a native ad. See +/// GADNativeAdImageAdLoaderOptions.h for available image options. +/// @param rootViewController Publisher-provided view controller. +- (void)requestNativeAdWithParameter:(NSString *)serverParameter + request:(GADCustomEventRequest *)request + adTypes:(NSArray *)adTypes + options:(NSArray *)options + rootViewController:(UIViewController *)rootViewController; + +/// Indicates if the custom event handles user clicks. Return YES if the custom event should handle +/// user clicks. In this case, the Google Mobile Ads SDK doesn't track user clicks and the custom +/// event must notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. Return NO if the +/// custom event doesn't handles user clicks. In this case, the Google Mobile Ads SDK tracks user +/// clicks itself and the custom event is notified of user clicks via -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the custom event handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the custom event must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the custom event of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// Delegate object used for receiving custom native ad load request progress. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAdDelegate.h new file mode 100755 index 000000000..19029a3c8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventNativeAdDelegate.h @@ -0,0 +1,31 @@ +// +// GADCustomEventNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The delegate of the GADCustomEventNativeAd object must adopt the GADCustomEventNativeAdDelegate +/// protocol. Methods in this protocol are used for native ad's custom event communication with the +/// Google Mobile Ads SDK. +@protocol GADCustomEventNativeAdDelegate + +/// Tells the delegate that the custom event ad request succeeded and loaded a native ad. +- (void)customEventNativeAd:(id)customEventNativeAd + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +/// Tells the delegate that the custom event ad request failed. +- (void)customEventNativeAd:(id)customEventNativeAd + didFailToLoadWithError:(NSError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventParameters.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventParameters.h new file mode 100755 index 000000000..084155d69 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventParameters.h @@ -0,0 +1,19 @@ +// +// GADCustomEventParameters.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Key for getting the server parameter configured in AdMob when mediating to a custom event +/// adapter. +/// Example: NSString *serverParameter = connector.credentials[GADCustomEventParametersServer]. +extern NSString *const GADCustomEventParametersServer; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventRequest.h new file mode 100755 index 000000000..cf48be3a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADCustomEventRequest.h @@ -0,0 +1,59 @@ +// +// GADCustomEventRequest.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADCustomEventExtras; + +GAD_ASSUME_NONNULL_BEGIN + +/// Specifies optional ad request targeting parameters that are provided by the publisher and are +/// forwarded to custom events for purposes of populating an ad request to a 3rd party ad network. +@interface GADCustomEventRequest : NSObject + +/// User's gender set in GADRequest. If not specified, returns kGADGenderUnknown. +@property(nonatomic, readonly, assign) GADGender userGender; + +/// User's birthday set in GADRequest. If not specified, returns nil. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDate *userBirthday; + +/// If the user's latitude, longitude, and accuracy are not specified, userHasLocation returns NO, +/// and userLatitude, userLongitude, and userLocationAccuracyInMeters return 0. +@property(nonatomic, readonly, assign) BOOL userHasLocation; + +/// User's latitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLatitude; + +/// User's longitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLongitude; + +/// The accuracy, in meters, of the user's location data. +@property(nonatomic, readonly, assign) CGFloat userLocationAccuracyInMeters; + +/// Description of the user's location, in free form text, set in GADRequest. If not available, +/// returns nil. This may be set even if userHasLocation is NO. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *userLocationDescription; + +/// Keywords set in GADRequest. Returns nil if no keywords are set. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *userKeywords; + +/// The additional parameters set by the application. This property allows you to pass additional +/// information from your application to your Custom Event object. To do so, create an instance of +/// GADCustomEventExtras to pass to GADRequest -registerAdNetworkExtras:. The instance should have +/// an NSDictionary set for a particular custom event label. That NSDictionary becomes the +/// additionalParameters here. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +/// Indicates if the testing property has been set in GADRequest. +@property(nonatomic, readonly, assign) BOOL isTesting; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDebugOptionsViewController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDebugOptionsViewController.h new file mode 100755 index 000000000..acc98dc3f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDebugOptionsViewController.h @@ -0,0 +1,36 @@ +// +// GADDebugOptionsViewController.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +@class GADDebugOptionsViewController; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for the GADDebugOptionsViewController. +@protocol GADDebugOptionsViewControllerDelegate +/// Called when the debug options flow is finished. +- (void)debugOptionsViewControllerDidDismiss:(GADDebugOptionsViewController *)controller; +@end + +/// Displays debug options to the user. +@interface GADDebugOptionsViewController : UIViewController + +/// Creates and returns a GADDebugOptionsViewController object initialized with the ad unit ID. +/// @param adUnitID An ad unit ID for the DFP account that is being configured with debug options. ++ (instancetype)debugOptionsViewControllerWithAdUnitID:(NSString *)adUnitID; + +/// Delegate for the debug options view controller. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDynamicHeightSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDynamicHeightSearchRequest.h new file mode 100755 index 000000000..4fefe66fd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADDynamicHeightSearchRequest.h @@ -0,0 +1,165 @@ +// +// GADDynamicHeightSearchRequest.h +// GoogleMobileAds +// +// Copyright © 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use to configure Custom Search Ad (CSA) ad requests. A dynamic height search banner can contain +/// multiple ads and the height is set dynamically based on the ad contents. Please cross-reference +/// the property sections and properties with the official reference document: +/// https://developers.google.com/custom-search-ads/docs/reference +@interface GADDynamicHeightSearchRequest : GADRequest + +#pragma mark - Page Level Parameters + +#pragma mark Required + +/// The CSA "query" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; + +/// The CSA "adPage" parameter. +@property(nonatomic, assign) NSInteger adPage; + +#pragma mark Configuration Settings + +/// Indicates if the CSA "adTest" parameter is enabled. +@property(nonatomic, assign) BOOL adTestEnabled; + +/// The CSA "channel" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *channel; + +/// The CSA "hl" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *hostLanguage; + +#pragma mark Layout and Styling + +/// The CSA "colorLocation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *locationExtensionTextColor; + +/// The CSA "fontSizeLocation" parameter. +@property(nonatomic, assign) CGFloat locationExtensionFontSize; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "clickToCall" parameter is enabled. +@property(nonatomic, assign) BOOL clickToCallExtensionEnabled; + +/// Indicates if the CSA "location" parameter is enabled. +@property(nonatomic, assign) BOOL locationExtensionEnabled; + +/// Indicates if the CSA "plusOnes" parameter is enabled. +@property(nonatomic, assign) BOOL plusOnesExtensionEnabled; + +/// Indicates if the CSA "sellerRatings" parameter is enabled. +@property(nonatomic, assign) BOOL sellerRatingsExtensionEnabled; + +/// Indicates if the CSA "siteLinks" parameter is enabled. +@property(nonatomic, assign) BOOL siteLinksExtensionEnabled; + +#pragma mark - Unit Level Parameters + +#pragma mark Required + +/// The CSA "width" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *CSSWidth; + +/// Configuration Settings + +/// The CSA "number" parameter. +@property(nonatomic, assign) NSInteger numberOfAds; + +#pragma mark Font + +/// The CSA "fontFamily" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; + +/// The CSA "fontFamilyAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionFontFamily; + +/// The CSA "fontSizeAnnotation" parameter. +@property(nonatomic, assign) CGFloat annotationFontSize; + +/// The CSA "fontSizeAttribution" parameter. +@property(nonatomic, assign) CGFloat attributionFontSize; + +/// The CSA "fontSizeDescription" parameter. +@property(nonatomic, assign) CGFloat descriptionFontSize; + +/// The CSA "fontSizeDomainLink" parameter. +@property(nonatomic, assign) CGFloat domainLinkFontSize; + +/// The CSA "fontSizeTitle" parameter. +@property(nonatomic, assign) CGFloat titleFontSize; + +#pragma mark Color + +/// The CSA "colorAdBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderColor; + +/// The CSA "colorAdSeparator" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adSeparatorColor; + +/// The CSA "colorAnnotation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *annotationTextColor; + +/// The CSA "colorAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionTextColor; + +/// The CSA "colorBackground" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *backgroundColor; + +/// The CSA "colorBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderColor; + +/// The CSA "colorDomainLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *domainLinkColor; + +/// The CSA "colorText" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *textColor; + +/// The CSA "colorTitleLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *titleLinkColor; + +#pragma mark General Formatting + +/// The CSA "adBorderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderCSSSelections; + +/// The CSA "adjustableLineHeight" parameter. +@property(nonatomic, assign) CGFloat adjustableLineHeight; + +/// The CSA "attributionSpacingBelow" parameter. +@property(nonatomic, assign) CGFloat attributionBottomSpacing; + +/// The CSA "borderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderCSSSelections; + +/// Indicates if the CSA "noTitleUnderline" parameter is enabled. +@property(nonatomic, assign) BOOL titleUnderlineHidden; + +/// Indicates if the CSA "titleBold" parameter is enabled. +@property(nonatomic, assign) BOOL boldTitleEnabled; + +/// The CSA "verticalSpacing" parameter. +@property(nonatomic, assign) CGFloat verticalSpacing; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "detailedAttribution" parameter is enabled. +@property(nonatomic, assign) BOOL detailedAttributionExtensionEnabled; + +/// Indicates if the CSA "longerHeadlines" parameter is enabled. +@property(nonatomic, assign) BOOL longerHeadlinesExtensionEnabled; + +/// Sets an advanced option value for a specified key. The value must be an NSString or NSNumber. +- (void)setAdvancedOptionValue:(id)value forKey:(NSString *)key; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADExtras.h new file mode 100755 index 000000000..3ca160fa0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADExtras.h @@ -0,0 +1,23 @@ +// +// GADExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad network extras sent to Google networks. +@interface GADExtras : NSObject + +/// Additional parameters to be sent to Google networks. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchase.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchase.h new file mode 100755 index 000000000..07fc206fa --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchase.h @@ -0,0 +1,86 @@ +// +// GADInAppPurchase.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADDefaultInAppPurchaseDelegate; + +#pragma mark - Default Purchase Flow + +/// The consumable in-app purchase item that has been purchased by the user. The purchase flow is +/// handled by the Google Mobile Ads SDK. +/// Instances of this class are created and passed to your in-app purchase delegate after the user +/// has successfully paid for a product. Your code must correctly deliver the product to the user +/// and then call the didCompletePurchase method to finish the transaction. +@interface GADDefaultInAppPurchase : NSObject + +/// Enables the default consumable product in-app purchase flow handled by the Google Mobile Ads +/// SDK. The GADDefaultInAppPurchaseDelegate object is retained while the default purchase flow is +/// enabled. This method adds a SKPaymentTransactionObserver to the default SKPaymentQueue. +/// +/// Call this method early in your application to handle unfinished transactions from previous +/// application sessions. For example, call this method in your application delegate's +/// application:didFinishLaunchingWithOptions: method. ++ (void)enableDefaultPurchaseFlowWithDelegate:(id)delegate; + +/// Disables the default in-app purchase flow handled by the Google Mobile Ads SDK and releases the +/// associated GADDefaultInAppPurchaseDelegate object. ++ (void)disableDefaultPurchaseFlow; + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The purchased item's completed payment transaction. Your application can use this property's +/// data to save a permanent record of the completed payment. The default purchase flow will finish +/// the transaction on your behalf. Do not finish the transaction yourself. +@property(nonatomic, readonly, strong) SKPaymentTransaction *paymentTransaction; + +/// The in-app purchase delegate object must first deliver the user's item and then call this +/// method. Failure to call this method will result in duplicate purchase notifications. +- (void)finishTransaction; + +@end + +#pragma mark - Custom Purchase Flow + +/// Enum of the different statuses resulting from processing a purchase. +typedef NS_ENUM(NSInteger, GADInAppPurchaseStatus) { + kGADInAppPurchaseStatusError = 0, ///< Error occured while processing the purchase. + kGADInAppPurchaseStatusSuccessful = 1, ///< Purchase was completed successfully. + kGADInAppPurchaseStatusCancel = 2, ///< Purchase was cancelled by the user. + kGADInAppPurchaseStatusInvalidProduct = 3 ///< Error occured while looking up the product. +}; + +/// The in-app purchase item to be purchased with the purchase flow handled by you, the +/// application developer. +/// Instances of this class are created and passed to your GADInAppPurchaseDelegate object when +/// users click a buy button. It is important to report the result of the purchase back to the SDK +/// in order to track metrics about the transaction. +@interface GADInAppPurchase : NSObject + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The GADInAppPurchaseDelegate object must call this method after handling the in-app purchase for +/// both successful and unsuccessful purchase attempts. This method reports ad conversion and +/// purchase status information to Google. +- (void)reportPurchaseStatus:(GADInAppPurchaseStatus)purchaseStatus; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchaseDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchaseDelegate.h new file mode 100755 index 000000000..fe1d8f941 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInAppPurchaseDelegate.h @@ -0,0 +1,48 @@ +// +// GADInAppPurchaseDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADDefaultInAppPurchase; +@class GADInAppPurchase; + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Default Purchase Flow + +/// In-app purchase delegate protocol for default purchase handling. The delegate must deliver +/// the purchased item then call the GADDefaultInAppPurchase object's finishTransaction method. +@protocol GADDefaultInAppPurchaseDelegate + +/// Called when the user successfully paid for a purchase. You must first deliver the purchased +/// item to the user, then call defaultInAppPurchase's finishTransaction method. +- (void)userDidPayForPurchase:(GADDefaultInAppPurchase *)defaultInAppPurchase; + +@optional + +/// Called when the user clicks on the buy button of an in-app purchase ad. Return YES if the +/// default purchase flow should be started to purchase the item, otherwise return NO. If not +/// implemented, defaults to YES. +- (BOOL)shouldStartPurchaseForProductID:(NSString *)productID quantity:(NSInteger)quantity; + +@end + +#pragma mark - Custom Purchase Flow + +/// In-app purchase delegate protocol for custom purchase handling. The delegate must handle the +/// product purchase flow then call the GADInAppPurchase object's reportPurchaseStatus: method. +@protocol GADInAppPurchaseDelegate + +/// Called when the user clicks on the buy button of an in-app purchase ad. After the receiver +/// handles the purchase, it must call the GADInAppPurchase object's reportPurchaseStatus: method. +- (void)didReceiveInAppPurchase:(GADInAppPurchase *)purchase; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitial.h new file mode 100755 index 000000000..cb17be99d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitial.h @@ -0,0 +1,88 @@ +// +// GADInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An interstitial ad. This is a full-screen advertisement shown at natural transition points in +/// your application such as between game levels or news stories. +@interface GADInterstitial : NSObject + +/// Initializes an interstitial with an ad unit created on the AdMob website. Create a new ad unit +/// for every unique placement of an ad in your application. Set this to the ID assigned for this +/// placement. Ad units are important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +- (instancetype)initWithAdUnitID:(NSString *)adUnitID NS_DESIGNATED_INITIALIZER; + +#pragma mark Pre-Request + +/// Required value passed in with initWithAdUnitID:. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate object that receives state change notifications from this GADInterstitalAd. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) id inAppPurchaseDelegate; + +#pragma mark Making an Ad Request + +/// Makes an interstitial ad request. Additional targeting options can be supplied with a request +/// object. Only one interstitial request is allowed at a time. +/// +/// This is best to do several seconds before the interstitial is needed to preload its content. +/// Then when transitioning between view controllers show the interstital with +/// presentFromViewController. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark Post-Request + +/// Returns YES if the interstitial is ready to be displayed. The delegate's +/// interstitialAdDidReceiveAd: will be called after this property switches from NO to YES. +@property(nonatomic, readonly, assign) BOOL isReady; + +/// Returns YES if this object has already been presented. Interstitial objects can only be used +/// once even with different requests. +@property(nonatomic, readonly, assign) BOOL hasBeenUsed; + +/// Returns the ad network class name that fetched the current ad. Returns nil while the latest ad +/// request is in progress or if the latest ad request failed. For both standard and mediated Google +/// AdMob ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Presents the interstitial ad which takes over the entire screen until the user dismisses it. +/// This has no effect unless isReady returns YES and/or the delegate's interstitialDidReceiveAd: +/// has been received. +/// +/// Set rootViewController to the current view controller at the time this method is called. If your +/// application does not use view controllers pass in nil and your views will be removed from the +/// window to show the interstitial and restored when done. After the interstitial has been removed, +/// the delegate's interstitialDidDismissScreen: will be called. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +#pragma mark Deprecated + +/// Deprecated intializer. Use initWithAdUnitID: instead. +- (instancetype)init GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID:."); + +/// Deprecated setter, use initWithAdUnitID: instead. +- (void)setAdUnitID:(NSString *GAD_NULLABLE_TYPE)adUnitID + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID: instead of setting the ad unit ID."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitialDelegate.h new file mode 100755 index 000000000..e83fcf9c0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADInterstitialDelegate.h @@ -0,0 +1,59 @@ +// +// GADInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADInterstitial; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADInterstitial such as interstitial ad +/// requests succeeding/failing. +@protocol GADInterstitialDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Called when an interstitial ad request succeeded. Show it at the next transition point in your +/// application such as when transitioning between view controllers. +- (void)interstitialDidReceiveAd:(GADInterstitial *)ad; + +/// Called when an interstitial ad request completed without an interstitial to +/// show. This is common since interstitials are shown sparingly to users. +- (void)interstitial:(GADInterstitial *)ad didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Display-Time Lifecycle Notifications + +/// Called just before presenting an interstitial. After this method finishes the interstitial will +/// animate onto the screen. Use this opportunity to stop animations and save the state of your +/// application in case the user leaves while the interstitial is on screen (e.g. to visit the App +/// Store from a link on the interstitial). +- (void)interstitialWillPresentScreen:(GADInterstitial *)ad; + +/// Called when |ad| fails to present. +- (void)interstitialDidFailToPresentScreen:(GADInterstitial *)ad; + +/// Called before the interstitial is to be animated off the screen. +- (void)interstitialWillDismissScreen:(GADInterstitial *)ad; + +/// Called just after dismissing an interstitial and it has animated off the screen. +- (void)interstitialDidDismissScreen:(GADInterstitial *)ad; + +/// Called just before the application will background or terminate because the user clicked on an +/// ad that will launch another application (such as the App Store). The normal +/// UIApplicationDelegate methods, like applicationDidEnterBackground:, will be called immediately +/// before this. +- (void)interstitialWillLeaveApplication:(GADInterstitial *)ad; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediaView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediaView.h new file mode 100755 index 000000000..d08b4e78e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediaView.h @@ -0,0 +1,27 @@ +// +// GADMediaView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays native ad media assets. +/// +/// To display media assets in GADNativeAppInstallAdView instances, add a GADMediaView subview and +/// assign the native ad view's mediaView property. +/// +/// If the native ad doesn't contain a video and image loading is enabled, the GADMediaView displays +/// the native ad's |images| asset's first image. +/// +/// If the native ad doesn't contain a video and image loading is disabled, the GADMediaView object +/// is empty. +@interface GADMediaView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAd.h new file mode 100755 index 000000000..7f37ae26f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAd.h @@ -0,0 +1,27 @@ +// +// GADMediatedNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Base protocol for mediated native ads. +@protocol GADMediatedNativeAd + +/// Returns a delegate object that receives state change notifications. +- (nullable id)mediatedNativeAdDelegate; + +/// Returns a dictionary of asset names and object pairs for assets that are not handled by +/// properties of the GADMediatedNativeAd subclass. +- (NSDictionary *GAD_NULLABLE_TYPE)extraAssets; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdDelegate.h new file mode 100755 index 000000000..b705652e1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdDelegate.h @@ -0,0 +1,47 @@ +// +// GADMediatedNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADMediatedNativeAd; + +/// GADMediatedNativeAdDelegate objects handle mediated native ad events. +@protocol GADMediatedNativeAdDelegate + +@optional + +/// Tells the delegate that the mediated native ad has rendered in |view|, a subview of +/// |viewController|. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRenderInView:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has recorded an impression. This method is called +/// only once per mediated native ad. +- (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Tells the delegate that the mediated native ad has recorded a user click on the asset named +/// |assetName|. Full screen actions should be presented from |viewController|. This method is +/// called only if -[GADMAdNetworkAdapter handlesUserClicks] returns NO. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRecordClickOnAssetWithName:(NSString *)assetName + view:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has untracked |view|. This method is called +/// when the mediatedNativeAd is no longer rendered in the provided view and the delegate should +/// stop tracking the view's impressions and clicks. +- (void)mediatedNativeAd:(id)mediatedNativeAd didUntrackView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdNotificationSource.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdNotificationSource.h new file mode 100755 index 000000000..3a3cfe6f8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAdNotificationSource.h @@ -0,0 +1,45 @@ +// +// GADMediatedNativeAdNotificationSource.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Notifies the Google Mobile Ads SDK about the events performed by adapters. Adapters may perform +/// some action (e.g. opening an in app browser or open the iTunes store) when handling callbacks +/// from GADMediatedNativeAdDelegate. Adapters in such case should notify the Google Mobile Ads SDK +/// by calling the relevant methods from this class. +@interface GADMediatedNativeAdNotificationSource : NSObject + +/// Called by the adapter when it has registered an impression on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserImpressions] returns YES. ++ (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Called by the adapter when it has registered a user click on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserClicks] returns YES. ++ (void)mediatedNativeAdDidRecordClick:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has opened an in app modal screen. ++ (void)mediatedNativeAdWillPresentScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdWillDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter after the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdDidDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has left the application. ++ (void)mediatedNativeAdWillLeaveApplication:(id)mediatedNativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAppInstallAd.h new file mode 100755 index 000000000..9475d35d5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeAppInstallAd.h @@ -0,0 +1,51 @@ +// +// GADMediatedNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native app install ads. The adapter must return an object +/// conforming to this protocol for native app install ad requests. +@protocol GADMediatedNativeAppInstallAd + +/// App title. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Array of GADNativeAdImage objects related to the advertised application. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// App description. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// Application icon. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)icon; + +/// Text that encourages user to take some action with the ad. For example "Install". +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// App store rating (0 to 5). +- (NSDecimalNumber *GAD_NULLABLE_TYPE)starRating; + +/// The app store name. For example, "App Store". +- (NSString *GAD_NULLABLE_TYPE)store; + +/// String representation of the app's price. +- (NSString *GAD_NULLABLE_TYPE)price; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeContentAd.h new file mode 100755 index 000000000..068da5845 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMediatedNativeContentAd.h @@ -0,0 +1,44 @@ +// +// GADMediatedNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native content ads. +@protocol GADMediatedNativeContentAd + +/// Primary text headline. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Secondary text. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// List of large images. Each object is an instance of GADNativeAdImage. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// Small logo image. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)logo; + +/// Text that encourages user to take some action with the ad. +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +- (NSString *GAD_NULLABLE_TYPE)advertiser; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMobileAds.h new file mode 100755 index 000000000..5c7abfbef --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADMobileAds.h @@ -0,0 +1,55 @@ +// +// GADMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Google Mobile Ads SDK settings. +@interface GADMobileAds : NSObject + +/// Returns the shared GADMobileAds instance. ++ (GADMobileAds *)sharedInstance; + +/// Configures the SDK using the settings associated with the given application ID. ++ (void)configureWithApplicationID:(NSString *)applicationID; + +/// Disables automated in app purchase (IAP) reporting. Must be called before any IAP transaction is +/// initiated. IAP reporting is used to track IAP ad conversions. Do not disable reporting if you +/// use IAP ads. ++ (void)disableAutomatedInAppPurchaseReporting; + +/// Disables automated SDK crash reporting. If not called, the SDK records the original exception +/// handler if available and registers a new exception handler. The new exception handler only +/// reports SDK related exceptions and calls the recorded original exception handler. ++ (void)disableSDKCrashReporting; + +/// The application's audio volume. Affects audio volumes of all ads relative to other audio output. +/// Valid ad volume values range from 0.0 (silent) to 1.0 (current device volume). Use this method +/// only if your application has its own volume controls (e.g., custom music or sound effect +/// volumes). Defaults to 1.0. +@property(nonatomic, assign) float applicationVolume; + +/// Indicates if the application's audio is muted. Affects initial mute state for all ads. Use this +/// method only if your application has its own volume controls (e.g., custom music or sound effect +/// muting). Defaults to NO. +@property(nonatomic, assign) BOOL applicationMuted; + +/// Returns YES if the current SDK version is at least |major|.|minor|.|patch|. This method can be +/// used by libraries that depend on a specific minimum version of the Google Mobile Ads SDK to warn +/// developers if they have an incompatible version. +/// +/// Available in Google Mobile Ads SDK 7.10 and onwards. Before calling this method check if the +/// GADMobileAds's shared instance responds to this method. Calling this method on a Google Mobile +/// Ads SDK lower than 7.10 can crash the app. +- (BOOL)isSDKVersionAtLeastMajor:(NSInteger)major minor:(NSInteger)minor patch:(NSInteger)patch; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAd.h new file mode 100755 index 000000000..c454404f3 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAd.h @@ -0,0 +1,36 @@ +// +// GADNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADNativeAdDelegate; + +/// Native ad base class. All native ad types are subclasses of this class. +@interface GADNativeAd : NSObject + +/// Optional delegate to receive state change notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Root view controller for handling ad actions. +@property(nonatomic, weak, GAD_NULLABLE) UIViewController *rootViewController; + +/// Dictionary of assets which aren't processed by the receiver. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *extraAssets; + +/// The ad network class name that fetched the current ad. For both standard and mediated Google +/// AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdDelegate.h new file mode 100755 index 000000000..e1b3ba3e0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdDelegate.h @@ -0,0 +1,57 @@ +// +// GADNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// Identifies native ad assets. +@protocol GADNativeAdDelegate + +@optional + +#pragma mark Ad Lifecycle Events + +/// Called when an impression is recorded for an ad. Only called for Google ads and is not supported +/// for mediation ads. +- (void)nativeAdDidRecordImpression:(GADNativeAd *)nativeAd; + +/// Called when a click is recorded for an ad. Only called for Google ads and is not supported for +/// mediation ads. +- (void)nativeAdDidRecordClick:(GADNativeAd *)nativeAd; + +#pragma mark Click-Time Lifecycle Notifications + +/// Called just before presenting the user a full screen view, such as a browser, in response to +/// clicking on an ad. Use this opportunity to stop animations, time sensitive interactions, etc. +/// +/// Normally the user looks at the ad, dismisses it, and control returns to your application with +/// the nativeAdDidDismissScreen: message. However, if the user hits the Home button or clicks on an +/// App Store link, your application will end. The next method called will be the +/// applicationWillResignActive: of your UIApplicationDelegate object.Immediately after that, +/// nativeAdWillLeaveApplication: is called. +- (void)nativeAdWillPresentScreen:(GADNativeAd *)nativeAd; + +/// Called just before dismissing a full screen view. +- (void)nativeAdWillDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just after dismissing a full screen view. Use this opportunity to restart anything you +/// may have stopped as part of nativeAdWillPresentScreen:. +- (void)nativeAdDidDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just before the application will go to the background or terminate due to an ad action +/// that will launch another application (such as the App Store). The normal UIApplicationDelegate +/// methods, like applicationDidEnterBackground:, will be called immediately before this. +- (void)nativeAdWillLeaveApplication:(GADNativeAd *)nativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage+Mediation.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage+Mediation.h new file mode 100755 index 000000000..971b71467 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage+Mediation.h @@ -0,0 +1,24 @@ +// +// GADNativeAdImage+Mediation.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides additional GADNativeAdImage initializers. +@interface GADNativeAdImage (MediationAdditions) + +/// Initializes and returns a native ad image object with the provided image. +- (instancetype)initWithImage:(UIImage *)image; + +/// Initializes and returns a native ad image object with the provided image URL and image scale. +- (instancetype)initWithURL:(NSURL *)URL scale:(CGFloat)scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage.h new file mode 100755 index 000000000..df4b48684 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImage.h @@ -0,0 +1,29 @@ +// +// GADNativeAdImage.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image. +@interface GADNativeAdImage : NSObject + +/// The image. If image autoloading is disabled, this property will be nil. +@property(nonatomic, readonly, strong, GAD_NULLABLE) UIImage *image; + +/// The image's URL. +@property(nonatomic, readonly, copy) NSURL *imageURL; + +/// The image's scale. +@property(nonatomic, readonly, assign) CGFloat scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImageAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImageAdLoaderOptions.h new file mode 100755 index 000000000..c2c9ea19c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdImageAdLoaderOptions.h @@ -0,0 +1,37 @@ +// +// GADNativeAdImageAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image orientation preference. +typedef NS_ENUM(NSInteger, GADNativeAdImageAdLoaderOptionsOrientation) { + GADNativeAdImageAdLoaderOptionsOrientationAny, ///< No orientation preference. + GADNativeAdImageAdLoaderOptionsOrientationPortrait, ///< Prefer portrait images. + GADNativeAdImageAdLoaderOptionsOrientationLandscape ///< Prefer landscape images. +}; + +/// Ad loader options for native ad image settings. +@interface GADNativeAdImageAdLoaderOptions : GADAdLoaderOptions + +/// Indicates if image asset content should be loaded by the SDK. If set to YES, the SDK will not +/// load image asset content and native ad image URLs can be used to fetch content. Defaults to NO, +/// image assets are loaded by the SDK. +@property(nonatomic, assign) BOOL disableImageLoading; + +/// Indicates if multiple images should be loaded for each asset. Defaults to NO. +@property(nonatomic, assign) BOOL shouldRequestMultipleImages; + +/// Indicates preferred image orientation. Defaults to +/// GADNativeAdImageAdLoaderOptionsOrientationAny. +@property(nonatomic, assign) GADNativeAdImageAdLoaderOptionsOrientation preferredImageOrientation; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdViewAdOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdViewAdOptions.h new file mode 100755 index 000000000..cd22062c1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAdViewAdOptions.h @@ -0,0 +1,29 @@ +// +// GADNativeAdViewAdOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Position of the AdChoices icon in the containing ad. +typedef NS_ENUM(NSInteger, GADAdChoicesPosition) { + GADAdChoicesPositionTopRightCorner, ///< Top right corner. + GADAdChoicesPositionTopLeftCorner, ///< Top left corner. + GADAdChoicesPositionBottomRightCorner, ///< Bottom right corner. + GADAdChoicesPositionBottomLeftCorner ///< Bottom Left Corner. +}; + +/// Ad loader options for configuring the view of native ads. +@interface GADNativeAdViewAdOptions : GADAdLoaderOptions + +/// Indicates preferred location of AdChoices icon. Default is GADAdChoicesPositionTopRightCorner. +@property(nonatomic, assign) GADAdChoicesPosition preferredAdChoicesPosition; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAppInstallAd.h new file mode 100755 index 000000000..1f442c3fc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeAppInstallAd.h @@ -0,0 +1,97 @@ +// +// GADNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native app install ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeAppInstall (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeAppInstallAdRequestDelegate protocol. +@interface GADNativeAppInstallAd : GADNativeAd + +#pragma mark - Must be displayed + +/// App title. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Text that encourages user to take some action with the ad. For example "Install". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Application icon. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *icon; + +#pragma mark - Recommended to display + +/// App description. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; +/// The app store name. For example, "App Store". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *store; +/// String representation of the app's price. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *price; +/// Array of GADNativeAdImage objects related to the advertised application. +@property(nonatomic, readonly, strong, GAD_NULLABLE) NSArray *images; +/// App store rating (0 to 5). +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDecimalNumber *starRating; +/// Video controller for controlling video playback in GADNativeAppInstallAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeAppInstallAd +/// ads. +@protocol GADNativeAppInstallAdLoaderDelegate +/// Called when a native app install ad is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeAppInstallAd:(GADNativeAppInstallAd *)nativeAppInstallAd; +@end + +#pragma mark - Native App Install Ad View + +/// Base class for app install ad views. Your app install ad view must be a subclass of this class +/// and must call superclass methods for all overriden methods. +@interface GADNativeAppInstallAdView : UIView + +/// This property must point to the native app install ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeAppInstallAd *nativeAppInstallAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's icon asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *iconView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's store asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *storeView; +/// Weak reference to your ad view's price asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *priceView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's star rating asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *starRatingView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeAppInstallAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeContentAd.h new file mode 100755 index 000000000..fcb87cd65 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeContentAd.h @@ -0,0 +1,89 @@ +// +// GADNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Native Content Ad Assets + +/// Native content ad. To request this ad type, you need to pass kGADAdLoaderAdTypeNativeContent +/// (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in GADAdLoader's initializer method. If +/// you request this ad type, your delegate must conform to the GADNativeContentAdRequestDelegate +/// protocol. +@interface GADNativeContentAd : GADNativeAd + +#pragma mark - Must be displayed + +/// Primary text headline. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Secondary text. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; + +#pragma mark - Recommended to display + +/// Large images. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *images; +/// Small logo image. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *logo; +/// Text that encourages user to take some action with the ad. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *advertiser; +/// Video controller for controlling video playback in GADNativeContentAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeContentAd ads. +@protocol GADNativeContentAdLoaderDelegate +/// Called when native content is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeContentAd:(GADNativeContentAd *)nativeContentAd; +@end + +#pragma mark - Native Content Ad View + +/// Base class for content ad views. Your content ad view must be a subclass of this class and must +/// call superclass methods for all overriden methods. +@interface GADNativeContentAdView : UIView + +/// This property must point to the native content ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeContentAd *nativeContentAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's logo asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *logoView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's advertiser asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *advertiserView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeContentAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeCustomTemplateAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeCustomTemplateAd.h new file mode 100755 index 000000000..fef98aca9 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeCustomTemplateAd.h @@ -0,0 +1,74 @@ +// +// GADNativeCustomTemplateAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native custom template ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeCustomTemplate (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeCustomTemplateAdLoaderDelegate protocol. +@interface GADNativeCustomTemplateAd : GADNativeAd + +/// The ad's custom template ID. +@property(nonatomic, readonly) NSString *templateID; + +/// Array of available asset keys. +@property(nonatomic, readonly) NSArray *availableAssetKeys; + +/// Returns video controller for controlling receiver's video. +@property(nonatomic, readonly, strong) GADVideoController *videoController; + +/// Returns media view for rendering video loaded by the receiver. Returns nil if receiver doesn't +/// has a video. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADMediaView *mediaView; + +/// Returns the native ad image corresponding to the specified key or nil if the image is not +/// available. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)imageForKey:(NSString *)key; + +/// Returns the string corresponding to the specified key or nil if the string is not available. +- (NSString *GAD_NULLABLE_TYPE)stringForKey:(NSString *)key; + +/// Call when the user clicks on the ad. Provide the asset key that best matches the asset the user +/// interacted with. Provide |customClickHandler| only if this template is configured with a custom +/// click action, otherwise pass in nil. If a block is provided, the ad's built-in click actions are +/// ignored and |customClickHandler| is executed after recording the click. +- (void)performClickOnAssetWithKey:(NSString *)assetKey + customClickHandler:(dispatch_block_t GAD_NULLABLE_TYPE)customClickHandler; + +/// Call when the ad is displayed on screen to the user. Can be called multiple times. Only the +/// first impression is recorded. +- (void)recordImpression; + +@end + +#pragma mark - Loading Protocol + +/// The delegate of a GADAdLoader object implements this protocol to receive +/// GADNativeCustomTemplateAd ads. +@protocol GADNativeCustomTemplateAdLoaderDelegate + +/// Called when requesting an ad. Asks the delegate for an array of custom template ID strings. +- (NSArray *)nativeCustomTemplateIDsForAdLoader:(GADAdLoader *)adLoader; + +/// Tells the delegate that a native custom template ad was received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeCustomTemplateAd:(GADNativeCustomTemplateAd *)nativeCustomTemplateAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdView.h new file mode 100755 index 000000000..2eeb67c9b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdView.h @@ -0,0 +1,96 @@ +// +// GADNativeExpressAdView.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays native ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADNativeExpressAdView *adView =
+///       [[GADNativeExpressAdView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADNativeExpressAdView : UIView + +#pragma mark - Initialization + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at +/// |origin| relative to its superview bounds. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at the top +/// left of its superview. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize; + +/// Video controller for controlling video rendered by this native express ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +#pragma mark - Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example, the root view controller in +/// a tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this native ad view to a proper size. Never create your own GADAdSize directly. +/// Use one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If you are not using mediation, changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If you are using +/// mediation, then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this +/// GADNativeExpressAdView. Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark - Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark - Mediation + +/// The name of the ad network adapter class that fetched the current ad. Returns nil while the +/// latest ad request is in progress or if the latest ad request failed. For both standard and +/// mediated Google AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via +/// mediation custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, weak, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdViewDelegate.h new file mode 100755 index 000000000..73bd5e0bb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADNativeExpressAdViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADNativeExpressAdViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeExpressAdView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADNativeExpressAdView state change messages such as ad request +/// status and ad click lifecycle. +@protocol GADNativeExpressAdViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that the native express ad view successfully received an ad. The delegate may +/// want to add the native express ad view to the view hierarchy if it hasn't been added yet. +- (void)nativeExpressAdViewDidReceiveAd:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)nativeExpressAdView:(GADNativeExpressAdView *)nativeExpressAdView + didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)nativeExpressAdViewWillPresentScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)nativeExpressAdViewWillDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)nativeExpressAdViewDidDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)nativeExpressAdViewWillLeaveApplication:(GADNativeExpressAdView *)nativeExpressAdView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequest.h new file mode 100755 index 000000000..422ba55ae --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequest.h @@ -0,0 +1,127 @@ +// +// GADRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kGADSimulatorID; + +/// Genders to help deliver more relevant ads. +typedef NS_ENUM(NSInteger, GADGender) { + kGADGenderUnknown, ///< Unknown gender. + kGADGenderMale, ///< Male gender. + kGADGenderFemale ///< Female gender. +}; + +/// Specifies optional parameters for ad requests. +@interface GADRequest : NSObject + +/// Returns a default request. ++ (instancetype)request; + +#pragma mark Additional Parameters For Ad Networks + +/// Ad networks may have additional parameters they accept. To pass these parameters to them, create +/// the ad network extras object for that network, fill in the parameters, and register it here. The +/// ad network should have a header defining the interface for the 'extras' object to create. All +/// networks will have access to the basic settings you've set in this GADRequest (gender, birthday, +/// testing mode, etc.). If you register an extras object that is the same class as one you have +/// registered before, the previous extras will be overwritten. +- (void)registerAdNetworkExtras:(id)extras; + +/// Returns the network extras defined for an ad network. +- (id GAD_NULLABLE_TYPE)adNetworkExtrasFor:(Class)aClass; + +/// Removes the extras for an ad network. |aClass| is the class which represents that network's +/// extras type. +- (void)removeAdNetworkExtrasFor:(Class)aClass; + +#pragma mark Collecting SDK Information + +/// Returns the version of the SDK. ++ (NSString *)sdkVersion; + +#pragma mark Testing + +/// Test ads will be returned for devices with device IDs specified in this array. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *testDevices; + +#pragma mark User Information + +/// Provide the user's gender to increase ad relevancy. +@property(nonatomic, assign) GADGender gender; + +/// Provide the user's birthday to increase ad relevancy. +@property(nonatomic, copy, GAD_NULLABLE) NSDate *birthday; + +/// The user's current location may be used to deliver more relevant ads. However do not use Core +/// Location just for advertising, make sure it is used for more beneficial reasons as well. It is +/// both a good idea and part of Apple's guidelines. +- (void)setLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + accuracy:(CGFloat)accuracyInMeters; + +/// [Optional] This method allows you to specify whether you would like your app to be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA), +/// http:///business.ftc.gov/privacy-and-security/childrens-privacy. +/// +/// If you call this method with YES, you are indicating that your app should be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA). If you call +/// this method with NO, you are indicating that your app should not be treated as child-directed +/// for purposes of the Children’s Online Privacy Protection Act (COPPA). If you do not call this +/// method, ad requests will include no indication of how you would like your app treated with +/// respect to COPPA. +/// +/// By setting this method, you certify that this notification is accurate and you are authorized to +/// act on behalf of the owner of the app. You understand that abuse of this setting may result in +/// termination of your Google account. +/// +/// It may take some time for this designation to be fully implemented in applicable Google +/// services. This designation will only apply to ad requests for which you have set this method. +- (void)tagForChildDirectedTreatment:(BOOL)childDirectedTreatment; + +#pragma mark Contextual Information + +/// Array of keyword strings. Keywords are words or phrases describing the current user activity +/// such as @"Sports Scores" or @"Football". Set this property to nil to clear the keywords. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *keywords; + +/// URL string for a webpage whose content matches the app content. This webpage content is used for +/// targeting purposes. +@property(nonatomic, copy, GAD_NULLABLE) NSString *contentURL; + +#pragma mark Request Agent Information + +/// String that identifies the ad request's origin. Third party libraries that reference the Mobile +/// Ads SDK should set this property to denote the platform from which the ad request originated. +/// For example, a third party ad network called "CoolAds network" that is mediating requests to the +/// Mobile Ads SDK should set this property as "CoolAds". +@property(nonatomic, copy, GAD_NULLABLE) NSString *requestAgent; + +#pragma mark Deprecated Methods + +/// Provide the user's birthday to increase ad relevancy. +- (void)setBirthdayWithMonth:(NSInteger)month + day:(NSInteger)day + year:(NSInteger)year + GAD_DEPRECATED_MSG_ATTRIBUTE(" use the birthday property."); + +/// When Core Location isn't available but the user's location is known supplying it here may +/// deliver more relevant ads. It can be any free-form text such as @"Champs-Elysees Paris" or +/// @"94041 US". +- (void)setLocationWithDescription:(NSString *GAD_NULLABLE_TYPE)locationDescription + GAD_DEPRECATED_MSG_ATTRIBUTE(" use setLocationWithLatitude:longitude:accuracy:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequestError.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequestError.h new file mode 100755 index 000000000..b38dcbe89 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRequestError.h @@ -0,0 +1,70 @@ +// +// GADRequestError.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADRequest; + +GAD_ASSUME_NONNULL_BEGIN + +/// Google AdMob Ads error domain. +GAD_EXTERN NSString *const kGADErrorDomain; + +/// NSError codes for GAD error domain. +typedef NS_ENUM(NSInteger, GADErrorCode) { + /// The ad request is invalid. The localizedFailureReason error description will have more + /// details. Typically this is because the ad did not have the ad unit ID or root view + /// controller set. + kGADErrorInvalidRequest, + + /// The ad request was successful, but no ad was returned. + kGADErrorNoFill, + + /// There was an error loading data from the network. + kGADErrorNetworkError, + + /// The ad server experienced a failure processing the request. + kGADErrorServerError, + + /// The current device's OS is below the minimum required version. + kGADErrorOSVersionTooLow, + + /// The request was unable to be loaded before being timed out. + kGADErrorTimeout, + + /// Will not send request because the interstitial object has already been used. + kGADErrorInterstitialAlreadyUsed, + + /// The mediation response was invalid. + kGADErrorMediationDataError, + + /// Error finding or creating a mediation ad network adapter. + kGADErrorMediationAdapterError, + + /// The mediation request was successful, but no ad was returned from any ad networks. + kGADErrorMediationNoFill, + + /// Attempting to pass an invalid ad size to an adapter. + kGADErrorMediationInvalidAdSize, + + /// Internal error. + kGADErrorInternalError, + + /// Invalid argument error. + kGADErrorInvalidArgument, + + /// Received invalid response. + kGADErrorReceivedInvalidResponse +}; + +/// Represents the error generated due to invalid request parameters. +@interface GADRequestError : NSError +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAd.h new file mode 100755 index 000000000..806f80bec --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAd.h @@ -0,0 +1,47 @@ +// +// GADRewardBasedVideoAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +@protocol GADRewardBasedVideoAdDelegate; + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADRewardBasedVideoAd class is used for requesting and presenting a reward based video ad. +/// This class isn't thread safe. +@interface GADRewardBasedVideoAd : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Indicates if the receiver is ready to be presented full screen. +@property(nonatomic, readonly, getter=isReady) BOOL ready; + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns the mediated custom event adapter. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Returns the shared GADRewardBasedVideoAd instance. ++ (GADRewardBasedVideoAd *)sharedInstance; + +/// Initiates the request to fetch the reward based video ad. The |request| object supplies ad +/// targeting information and must not be nil. The adUnitID is the ad unit id used for fetching an +/// ad and must not be nil. +- (void)loadRequest:(GADRequest *)request withAdUnitID:(NSString *)adUnitID; + +/// Presents the reward based video ad with the provided view controller. +- (void)presentFromRootViewController:(UIViewController *)viewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAdDelegate.h new file mode 100755 index 000000000..f81dd5922 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADRewardBasedVideoAdDelegate.h @@ -0,0 +1,49 @@ +// +// GADRewardBasedVideoAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADRewardBasedVideoAd such as ad requests +/// succeeding/failing. +@protocol GADRewardBasedVideoAdDelegate + +@required + +/// Tells the delegate that the reward based video ad has rewarded the user. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +@optional + +/// Tells the delegate that the reward based video ad failed to load. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didFailToLoadWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was received. +- (void)rewardBasedVideoAdDidReceiveAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad opened. +- (void)rewardBasedVideoAdDidOpen:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad started playing. +- (void)rewardBasedVideoAdDidStartPlaying:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad closed. +- (void)rewardBasedVideoAdDidClose:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad will leave the application. +- (void)rewardBasedVideoAdWillLeaveApplication:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchBannerView.h new file mode 100755 index 000000000..590b2770e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchBannerView.h @@ -0,0 +1,27 @@ +// +// GADSearchBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A view that displays search ads. +/// To show search ads: +/// 1) Create a GADSearchBannerView and add it to your view controller's view hierarchy. +/// 2) Create a GADSearchRequest ad request object to hold the search query and other search data. +/// 3) Call GADSearchBannerView's -loadRequest: method with the GADSearchRequest object. +@interface GADSearchBannerView : GADBannerView + +/// If the banner view is initialized with kGADAdSizeFluid and the corresponding request is created +/// with dynamic height parameters, this delegate will be called when the ad size changes. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchRequest.h new file mode 100755 index 000000000..34fb68bd0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADSearchRequest.h @@ -0,0 +1,77 @@ +// +// GADSearchRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Search ad border types. +typedef NS_ENUM(NSUInteger, GADSearchBorderType) { + kGADSearchBorderTypeNone, ///< No border. + kGADSearchBorderTypeDashed, ///< Dashed line border. + kGADSearchBorderTypeDotted, ///< Dotted line border. + kGADSearchBorderTypeSolid ///< Solid line border. +}; + +/// Search ad call button color types. +typedef NS_ENUM(NSUInteger, GADSearchCallButtonColor) { + kGADSearchCallButtonLight, ///< Light button color. + kGADSearchCallButtonMedium, ///< Medium button color. + kGADSearchCallButtonDark ///< Dark button color. +}; + +/// Specifies parameters for search ads. +@interface GADSearchRequest : GADRequest + +/// The search ad query. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; +/// The search ad background color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *backgroundColor; +/// The search ad gradient "from" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientFrom; +/// The search ad gradient "to" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientTo; +/// The search ad header color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *headerColor; +/// The search ad description text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *descriptionTextColor; +/// The search ad anchor text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *anchorTextColor; +/// The search ad text font family. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; +/// The search ad header text size. +@property(nonatomic, assign) NSUInteger headerTextSize; +/// The search ad border color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *borderColor; +/// The search ad border type. +@property(nonatomic, assign) GADSearchBorderType borderType; +/// The search ad border thickness. +@property(nonatomic, assign) NSUInteger borderThickness; +/// The search ad custom channels. +@property(nonatomic, copy, GAD_NULLABLE) NSString *customChannels; +/// The search ad call button color. +@property(nonatomic, assign) GADSearchCallButtonColor callButtonColor; + +/// A solid background color for rendering the ad. The background of the ad +/// can either be a solid color, or a gradient, which can be specified through +/// setBackgroundGradientFrom:toColor: method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundSolid:(UIColor *)color; + +/// A linear gradient background color for rendering the ad. The background of +/// the ad can either be a linear gradient, or a solid color, which can be +/// specified through setBackgroundSolid method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundGradientFrom:(UIColor *)from toColor:(UIColor *)toColor; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoController.h new file mode 100755 index 000000000..a3d3e66cc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoController.h @@ -0,0 +1,35 @@ +// +// GADVideoController.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADVideoControllerDelegate; + +/// The video controller class provides a way to get the video metadata and also manages video +/// content of the ad rendered by the Google Mobile Ads SDK. You don't need to create an instance of +/// this class. When the ad rendered by the Google Mobile Ads SDK loads video content, you may be +/// able to get an instance of this class from the rendered ad object. Currently only native express +/// ad view class exposes video controller. +@interface GADVideoController : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Returns a Boolean indicating if the receiver has video content. +- (BOOL)hasVideoContent; + +/// Returns the video's aspect ratio (width/height) or 0 if no video is present. +- (double)aspectRatio; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoControllerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoControllerDelegate.h new file mode 100755 index 000000000..cd5c0487e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoControllerDelegate.h @@ -0,0 +1,25 @@ +// +// GADVideoControllerDelegate.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADVideoControllerDelegate protocol defines methods that are called by the video controller +/// object in response to the video events that occured throught the lifetime of the video rendered +/// by an ad. +@protocol GADVideoControllerDelegate + +@optional + +/// Tells the delegate that the video controller's video playback has ended. +- (void)videoControllerDidEndVideoPlayback:(GADVideoController *)videoController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoOptions.h new file mode 100755 index 000000000..2f75a37d7 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GADVideoOptions.h @@ -0,0 +1,21 @@ +// +// GADVideoOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Video ad options. +@interface GADVideoOptions : GADAdLoaderOptions + +/// Indicates if videos should start muted. +@property(nonatomic, assign) BOOL startMuted; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAds.h new file mode 100755 index 000000000..7c0df6121 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAds.h @@ -0,0 +1,96 @@ +// +// GoogleMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. + +#import +#import + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0 +#error The Google Mobile Ads SDK requires a deployment target of iOS 6.0 or later. +#endif + +/// Project version string for GoogleMobileAds. +FOUNDATION_EXPORT const unsigned char GoogleMobileAdsVersionString[]; + +// Header files. +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAdsDefines.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAdsDefines.h new file mode 100755 index 000000000..229ffd898 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/GoogleMobileAdsDefines.h @@ -0,0 +1,56 @@ +// +// GoogleMobileAdsDefines.h +// Google Mobile Ads SDK +// +// Copyright (c) 2015 Google Inc. All rights reserved. +// + +#import + +#if defined(__cplusplus) +#define GAD_EXTERN extern "C" __attribute__((visibility("default"))) +#else +#define GAD_EXTERN extern __attribute__((visibility("default"))) +#endif // defined(__cplusplus) + +#if defined(__has_feature) && defined(__has_attribute) +#if __has_feature(attribute_GAD_DEPRECATED_with_message) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated(s))) +#elif __has_attribute(deprecated) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // __has_feature(attribute_GAD_DEPRECATED_with_message) +#if __has_attribute(deprecated) +#define GAD_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#endif // __has_attribute(deprecated) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // defined(__has_feature) && defined(__has_attribute) + +#ifndef IBInspectable +#define IBInspectable +#endif + +#if __has_feature(nullability) // Available starting in Xcode 6.3. +#define GAD_NULLABLE_TYPE __nullable +#define GAD_NONNULL_TYPE __nonnull +#define GAD_NULLABLE nullable +#define GAD_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +#else +#define GAD_NULLABLE_TYPE +#define GAD_NONNULL_TYPE +#define GAD_NULLABLE +#define GAD_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END +#endif // __has_feature(nullability) + +#if __has_attribute(objc_boxable) // Available starting in Xcode 7.3. +#define GAD_BOXABLE __attribute__((objc_boxable)) +#else +#define GAD_BOXABLE +#endif // __has_attribute(objc_boxable) diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..f5ee207cb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkAdapterProtocol.h @@ -0,0 +1,104 @@ +// +// GADMAdNetworkAdapterProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +#import "GADMAdNetworkConnectorProtocol.h" +#import "GADMEnums.h" + +/// Subclasses should prefix their name with "GADMAdapter" example: GADMAdapterGoogleAdMobAds +#define kGADMAdapterClassNamePrefix @"GADMAdapter" + +@protocol GADMAdNetworkConnector; + +/// Ad network adapter protocol. +@protocol GADMAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Designated initializer. Implementing classes can and should keep the connector in an instance +/// variable. However you must never retain the connector, as doing so will create a circular +/// reference and cause memory leaks. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector; + +/// Asks the adapter to initiate a banner ad request. The adapter does not need to return anything. +/// The assumption is that the adapter will start an asynchronous ad fetch over the network. Your +/// adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does not support +/// the given ad size, or does not support banner ads, call back to the adapter:didFailAd: method of +/// the connector. +- (void)getBannerWithSize:(GADAdSize)adSize; + +/// Asks the adapter to initiate an interstitial ad request. The adapter does not need to return +/// anything. The assumption is that the adapter will start an asynchronous ad fetch over the +/// network. Your adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does +/// not support interstitials, call back to the adapter:didFailInterstitial: method of the +/// connector. +- (void)getInterstitial; + +/// When called, the adapter must remove itself as a delegate or notification observer from the +/// underlying ad network SDK. You should also call this method in your adapter dealloc, so when +/// your adapter goes away, your SDK will not call a freed object. This function should be +/// idempotent and should not crash regardless of when or how many times the method is called. +- (void)stopBeingDelegate; + +/// Some ad transition types may cause issues with particular Ad SDKs. The adapter may decide +/// whether the given animation type is OK. Defaults to YES. +- (BOOL)isBannerAnimationOK:(GADMBannerAnimationType)animType; + +/// Present an interstitial using the supplied UIViewController, by calling +/// presentViewController:animated:completion:. +/// +/// Your interstitial should not immediately present itself when it is received. Instead, you should +/// wait until this method is called on your adapter to present the interstitial. +/// +/// Make sure to call adapterWillPresentInterstitial: on the connector when the interstitial is +/// about to be presented, and adapterWillDismissInterstitial: and adapterDidDismissInterstitial: +/// when the interstitial is being dismissed. +- (void)presentInterstitialFromRootViewController:(UIViewController *)rootViewController; + +@optional + +/// Starts request for a native ad. |adTypes| contains the list of native ad types requested. See +/// GADAdLoaderAdTypes.h for available ad types. |options| are any additional options configured by +/// the publisher for requesting a native ad. See GADNativeAdImageAdLoaderOptions.h for available +/// image options. When this method is called the receiver may start native ad request +/// asynchronously. On completion the receiver should notify the Google Mobile Ads SDK with a native +/// ad object using the receiver's connector method +/// adapter:didReceiveNativeAdDataSource:mediationDelegate or adapter:didFailAd: if the ad request +/// encountered an error. +- (void)getNativeAdWithAdTypes:(NSArray *)adTypes options:(NSArray *)options; + +/// Indicates if the adapter handles user clicks. If this method returns YES, the adapter must +/// handle user clicks and notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. If this method returns +/// NO, the Google Mobile Ads SDK handles user clicks and notifies the adapter of clicks using +/// -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the adapter handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the adapter must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the adapter of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// If your ad network handles multiple ad sizes for the same banner ad, implement this method to +/// know when the user changes the banner size. This is typically changing from +/// kGADAdSizeSmartBannerPortrait to kGADAdSizeSmartBannerLandscape, or vice versa. If this method +/// is not implemented, every time the user changes the ad size, a new ad will be requested with the +/// new size by calling your getBannerWithSize: method. +- (void)changeAdSizeTo:(GADAdSize)adSize; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..075ca3cea --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMAdNetworkConnectorProtocol.h @@ -0,0 +1,87 @@ +// +// GADMAdNetworkConnectorProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import +#import + +#import "GADMediationAdRequest.h" + +@protocol GADMAdNetworkAdapter; + +/// Ad network adapters interact with the mediation SDK using an object that implements the +/// GADMAdNetworkConnector protocol. The connector object can be used to obtain necessary +/// information for ad requests, and to call back to the mediation SDK on ad request returns and +/// user interactions. +@protocol GADMAdNetworkConnector + +/// When you need to show a landing page or any other modal view, such as when a user clicks or when +/// your Ads SDK needs to show an interstitial, use this method to obtain a UIViewController that +/// you can use to show your modal view. Call the -presentViewController:animated:completion: method +/// of the returned UIViewController . +- (UIViewController *)viewControllerForPresentingModalView; + +#pragma mark - Adapter Callbacks + +/// Tells the connector that the adapter failed to receive an ad. +- (void)adapter:(id)adapter didFailAd:(NSError *)error; + +/// Tells the connector that the adapter received a banner ad. +- (void)adapter:(id)adapter didReceiveAdView:(UIView *)view; + +/// Tells the connector that the adapter received an interstitial. +- (void)adapterDidReceiveInterstitial:(id)adapter; + +/// Tells the connector that the adapter has received a mediated native ad. |mediatedNativeAd| is +/// used by the Google Mobile Ads SDK for constructing a native ad object. +- (void)adapter:(id)adapter + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +#pragma mark Ad events + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner or +// interstitial ad. + +/// Tells the connector that the adapter recorded a user click. +- (void)adapterDidGetAdClick:(id)adapter; +/// Tells the connector that the adapter will leave the application because of a user action. +- (void)adapterWillLeaveApplication:(id)adapter; + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner ad. + +/// Tells the connector that the adapter will present a full screen modal. +- (void)adapterWillPresentFullScreenModal:(id)adapter; +/// Tells the connector that the adapter will dismiss a full screen modal. +- (void)adapterWillDismissFullScreenModal:(id)adapter; +/// Tells the connector that the adapter dismissed a full screen modal. +- (void)adapterDidDismissFullScreenModal:(id)adapter; + +// Adapter should call these methods during the lifecycle of the loaded interstitial ad. + +/// Tells the connector that the adapter will present an interstitial. +- (void)adapterWillPresentInterstitial:(id)adapter; +/// Tells the connector that the adapter will dismiss an interstitial. +- (void)adapterWillDismissInterstitial:(id)adapter; +/// Tells the connector that the adapter did dismiss an interstitial. +- (void)adapterDidDismissInterstitial:(id)adapter; + +#pragma mark Deprecated + +/// Deprecated. Use -adapterDidReceiveInterstitial:. +- (void)adapter:(id)adapter + didReceiveInterstitial:(NSObject *)interstitial + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidReceiveInterstitial:."); + +/// Deprecated. Use -adapterDidGetAdClick:. +- (void)adapter:(id)adapter + clickDidOccurInBanner:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidGetAdClick:."); + +/// Deprecated. Use -adapter:didFailAd:. +- (void)adapter:(id)adapter + didFailInterstitial:(NSError *)error GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapter:didFailAd:"); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMEnums.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMEnums.h new file mode 100755 index 000000000..1802598c2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMEnums.h @@ -0,0 +1,21 @@ +// +// GADMEnums.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +/// These are the types of animation we employ for transitions between two mediated ads. +typedef NS_ENUM(NSInteger, GADMBannerAnimationType) { + kGADMBannerAnimationTypeNone = 0, ///< No animation. + kGADMBannerAnimationTypeFlipFromLeft = 1, ///< Flip from left. + kGADMBannerAnimationTypeFlipFromRight = 2, ///< Flip from right. + kGADMBannerAnimationTypeCurlUp = 3, ///< Curl up. + kGADMBannerAnimationTypeCurlDown = 4, ///< Curl down. + kGADMBannerAnimationTypeSlideFromLeft = 5, ///< Slide from left. + kGADMBannerAnimationTypeSlideFromRight = 6, ///< Slide from right. + kGADMBannerAnimationTypeFadeIn = 7, ///< Fade in. + kGADMBannerAnimationTypeRandom = 8, ///< Random animation. +}; diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..63eb5072e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h @@ -0,0 +1,59 @@ +// +// GADMRewardBasedVideoAdNetworkAdapter.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMRewardBasedVideoAdNetworkConnector; + +/// Your adapter must conform to this protocol to provide reward based video ads. +@protocol GADMRewardBasedVideoAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithRewardBasedVideoAdNetworkConnector: + (id)connector; + +/// Tells the adapter to set up reward based video ads. The adapter should notify the Google Mobile +/// Ads SDK whether set up has succeeded or failed using callbacks provided in the connector. When +/// set up fails, the Google Mobile Ads SDK may try to set up the adapter again. +- (void)setUp; + +/// Tells the adapter to request a reward based video ad. This method is called after the adapter +/// has been set up. The adapter should notify the Google Mobile Ads SDK if the request succeeds or +/// fails using callbacks provided in the connector. +- (void)requestRewardBasedVideoAd; + +/// Tells the adapter to present the reward based video ad with the provided view controller. This +/// method is only called after the adapter successfully requested an ad. +- (void)presentRewardBasedVideoAdWithRootViewController:(UIViewController *)viewController; + +/// Tells the adapter to remove itself as a delegate or notification observer from the underlying ad +/// network SDK. +- (void)stopBeingDelegate; + +@optional + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithRewardBasedVideoAdNetworkConnector:."); + +/// Tells the adapter to set up reward based video ads with the provided user ID. The adapter should +/// notify the Google Mobile Ads SDK whether set up has succeeded or failed using callbacks provided +/// in the connector. When set up fails, the Google Mobile Ads SDK may try to set up the adapter +/// again. +- (void)setUpWithUserID:(NSString *)userID GAD_DEPRECATED_MSG_ATTRIBUTE("Use setUp."); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..82b8d4520 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h @@ -0,0 +1,58 @@ +// +// GADMRewardBasedVideoAdNetworkConnector.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMediationAdRequest; +@protocol GADMRewardBasedVideoAdNetworkAdapter; + +/// Reward based video ad network adapters interact with the mediation SDK using an object that +/// conforms to the GADMRewardBasedVideoAdNetworkConnector protocol. The connector object can be +/// used to obtain information for ad requests and to call back to the mediation SDK on ad responses +/// and user interactions. +@protocol GADMRewardBasedVideoAdNetworkConnector + +/// Tells the delegate that the adapter successfully set up a reward based video ad. +- (void)adapterDidSetUpRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter failed to set up a reward based video ad. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToSetUpRewardBasedVideoAdWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was clicked. +- (void)adapterDidGetAdClick:(id)adapter; + +/// Tells the delegate that a reward based video ad has loaded. +- (void)adapterDidReceiveRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has opened. +- (void)adapterDidOpenRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has started playing. +- (void)adapterDidStartPlayingRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has closed. +- (void)adapterDidCloseRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter has rewarded the user. +- (void)adapter:(id)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +/// Tells the delegate that a reward based video ad's action will leave the application. +- (void)adapterWillLeaveApplication: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad failed to load. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToLoadRewardBasedVideoAdwithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMediationAdRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMediationAdRequest.h new file mode 100755 index 000000000..104ea5a2b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Headers/Mediation/GADMediationAdRequest.h @@ -0,0 +1,56 @@ +// +// GADMediationAdRequest.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +/// Provides information which can be used for making ad requests during mediation. +@protocol GADMediationAdRequest + +/// Publisher ID set by the publisher on the AdMob frontend. +- (NSString *)publisherId; + +/// Mediation configurations set by the publisher on the AdMob frontend. +- (NSDictionary *)credentials; + +/// Returns YES if the publisher is requesting test ads. +- (BOOL)testMode; + +/// The adapter's ad network extras specified in GADRequest. +- (id)networkExtras; + +/// Returns the value of childDirectedTreatment supplied by the publisher. Returns nil if the +/// publisher hasn't specified child directed treatment. Returns @YES if child directed treatment is +/// enabled. +- (NSNumber *)childDirectedTreatment; + +/// The end user's gender set by the publisher in GADRequest. Returns kGADGenderUnknown if it has +/// not been specified. +- (GADGender)userGender; + +/// The end user's birthday set by the publisher. Returns nil if it has not been specified. +- (NSDate *)userBirthday; + +/// Returns YES if the publisher has specified latitude and longitude location. +- (BOOL)userHasLocation; + +/// Returns the user's latitude or 0 if location isn't specified. +- (CGFloat)userLatitude; + +/// Returns the user's longitude or 0 if location isn't specified. +- (CGFloat)userLongitude; + +/// Returns the user's location accuracy or 0 if location isn't specified. +- (CGFloat)userLocationAccuracyInMeters; + +/// Returns user's location description. May return a value even if userHasLocation is NO. +- (NSString *)userLocationDescription; + +/// Keywords describing the user's current activity. Example: @"Sport Scores". +- (NSArray *)userKeywords; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Modules/module.modulemap b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Modules/module.modulemap new file mode 100755 index 000000000..f3af92b4b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Modules/module.modulemap @@ -0,0 +1,107 @@ +framework module GoogleMobileAds { + umbrella header "GoogleMobileAds.h" + + export * + module * { export * } + + link framework "AdSupport" + link framework "AudioToolbox" + link framework "AVFoundation" + link framework "CoreGraphics" + link framework "CoreMedia" + link framework "CoreMotion" + link framework "CoreTelephony" + link framework "CoreVideo" + link framework "Foundation" + link framework "GLKit" + link framework "JavaScriptCore" + link framework "MediaPlayer" + link framework "MessageUI" + link framework "MobileCoreServices" + link framework "OpenGLES" + link framework "SafariServices" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" + link framework "WebKit" + + header "GoogleMobileAdsDefines.h" + + header "GADAdDelegate.h" + header "GADAdNetworkExtras.h" + header "GADAdSize.h" + header "GADBannerView.h" + header "GADBannerViewDelegate.h" + header "GADCorrelator.h" + header "GADCorrelatorAdLoaderOptions.h" + header "GADDebugOptionsViewController.h" + header "GADExtras.h" + header "GADInAppPurchase.h" + header "GADInAppPurchaseDelegate.h" + header "GADInterstitial.h" + header "GADInterstitialDelegate.h" + header "GADMediaView.h" + header "GADMobileAds.h" + header "GADNativeExpressAdView.h" + header "GADNativeExpressAdViewDelegate.h" + header "GADRequest.h" + header "GADRequestError.h" + header "GADVideoController.h" + header "GADVideoControllerDelegate.h" + header "GADVideoOptions.h" + + header "DFPBannerView.h" + header "DFPCustomRenderedAd.h" + header "DFPCustomRenderedBannerViewDelegate.h" + header "DFPCustomRenderedInterstitialDelegate.h" + header "DFPInterstitial.h" + header "DFPRequest.h" + header "GADAdSizeDelegate.h" + header "GADAppEventDelegate.h" + + header "GADAdLoader.h" + header "GADAdLoaderAdTypes.h" + header "GADAdLoaderDelegate.h" + + header "GADAdChoicesView.h" + header "GADNativeAd.h" + header "GADNativeAdDelegate.h" + header "GADNativeAdImage.h" + header "GADNativeAdImage+Mediation.h" + header "GADNativeAppInstallAd.h" + header "GADNativeContentAd.h" + header "GADNativeCustomTemplateAd.h" + + header "GADNativeAdImageAdLoaderOptions.h" + header "GADNativeAdViewAdOptions.h" + + header "GADCustomEventBanner.h" + header "GADCustomEventBannerDelegate.h" + header "GADCustomEventExtras.h" + header "GADCustomEventInterstitial.h" + header "GADCustomEventInterstitialDelegate.h" + header "GADCustomEventNativeAd.h" + header "GADCustomEventNativeAdDelegate.h" + header "GADCustomEventParameters.h" + header "GADCustomEventRequest.h" + header "GADMediatedNativeAd.h" + header "GADMediatedNativeAdDelegate.h" + header "GADMediatedNativeAdNotificationSource.h" + header "GADMediatedNativeAppInstallAd.h" + header "GADMediatedNativeContentAd.h" + + header "GADDynamicHeightSearchRequest.h" + header "GADSearchBannerView.h" + header "GADSearchRequest.h" + + header "GADAdReward.h" + header "GADRewardBasedVideoAd.h" + header "GADRewardBasedVideoAdDelegate.h" + + header "Mediation/GADMAdNetworkAdapterProtocol.h" + header "Mediation/GADMAdNetworkConnectorProtocol.h" + header "Mediation/GADMediationAdRequest.h" + header "Mediation/GADMEnums.h" + header "Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h" + header "Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h" +} diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/GoogleMobileAds b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/GoogleMobileAds new file mode 100755 index 000000000..e5a9958b0 Binary files /dev/null and b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/GoogleMobileAds differ diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPBannerView.h new file mode 100755 index 000000000..95e0f7c0b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPBannerView.h @@ -0,0 +1,94 @@ +// +// DFPBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays DoubleClick For Publishers banner ads. +@interface DFPBannerView : GADBannerView + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and statistics. +/// +/// Example DFP ad unit ID: @"/6499/example/banner" +@property(nonatomic, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id appEventDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +/// Optional array of NSValue encoded GADAdSize structs, specifying all valid sizes that are +/// appropriate for this slot. Never create your own GADAdSize directly. Use one of the predefined +/// standard ad sizes (such as kGADAdSizeBanner), or create one using the GADAdSizeFromCGSize +/// method. +/// +/// Example: +/// +///
+///   NSArray *validSizes = @[
+///     NSValueFromGADAdSize(kGADAdSizeBanner),
+///     NSValueFromGADAdSize(kGADAdSizeLargeBanner)
+///   ];
+///
+///   bannerView.validAdSizes = validSizes;
+///   
+@property(nonatomic, copy, GAD_NULLABLE) NSArray *validAdSizes; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Indicates that the publisher will record impressions manually when the ad becomes visible to the +/// user. +@property(nonatomic, assign) BOOL enableManualImpressions; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id customRenderedBannerViewDelegate; + +/// Video controller for controlling video rendered by this ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +/// If you've set enableManualImpressions to YES, call this method when the ad is visible. +- (void)recordImpression; + +/// Use this function to resize the banner view without launching a new ad request. +- (void)resize:(GADAdSize)size; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark Deprecated + +/// Deprecated. Use the validAdSizes property. +/// Sets the receiver's valid ad sizes to the values pointed to by the provided NULL terminated list +/// of GADAdSize pointers. +/// +/// Example: +/// +///
+///   GADAdSize size1 = kGADAdSizeBanner;
+///   GADAdSize size2 = kGADAdSizeLargeBanner;
+///   [bannerView setValidAdSizesWithSizes:&size1, &size2, NULL];
+///   
+- (void)setValidAdSizesWithSizes:(GADAdSize *)firstSize, ... NS_REQUIRES_NIL_TERMINATION + GAD_DEPRECATED_MSG_ATTRIBUTE("Use validAdSizes property."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedAd.h new file mode 100755 index 000000000..5c2b0abb4 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedAd.h @@ -0,0 +1,34 @@ +// +// DFPCustomRenderedAd.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Custom rendered ad. Your application renders the ad. +@interface DFPCustomRenderedAd : NSObject + +/// The ad's HTML. +@property(nonatomic, readonly, copy) NSString *adHTML; + +/// The base URL of the ad's HTML. +@property(nonatomic, readonly, copy) NSURL *adBaseURL; + +/// Call this method when the user clicks the ad. +- (void)recordClick; + +/// Call this method when the ad is visible to the user. +- (void)recordImpression; + +/// Call this method after the ad has been rendered in a UIView object. +- (void)finishedRenderingAdView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedBannerViewDelegate.h new file mode 100755 index 000000000..e15b89ebd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedBannerViewDelegate.h @@ -0,0 +1,28 @@ +// +// DFPCustomRenderedBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPBannerView; +@class DFPCustomRenderedAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd banner view delegate protocol for notifying the delegate of changes to +/// custom rendered banners. +@protocol DFPCustomRenderedBannerViewDelegate + +/// Called after ad data has been received. You must construct a banner from |customRenderedAd| and +/// call the |customRenderedAd| object's finishedRenderingAdView: when the ad has been rendered. +- (void)bannerView:(DFPBannerView *)bannerView + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedInterstitialDelegate.h new file mode 100755 index 000000000..0f1f4a8a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPCustomRenderedInterstitialDelegate.h @@ -0,0 +1,29 @@ +// +// DFPCustomRenderedInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPCustomRenderedAd; +@class DFPInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd interstitial delegate protocol for notifying the delegate of changes to +/// custom rendered interstitials. +@protocol DFPCustomRenderedInterstitialDelegate + +/// Called after ad data has been received. You must construct an interstitial from +/// |customRenderedAd| and call the |customRenderedAd| object's finishedRenderingAdView: method when +/// the ad has been rendered. +- (void)interstitial:(DFPInterstitial *)interstitial + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPInterstitial.h new file mode 100755 index 000000000..e3af0d210 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPInterstitial.h @@ -0,0 +1,39 @@ +// +// DFPInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// DoubleClick For Publishers interstitial ad, a full-screen advertisement shown at natural +/// transition points in your application such as between game levels or news stories. +@interface DFPInterstitial : GADInterstitial + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and stats. +/// +/// Example DFP ad unit ID: @"/6499/example/interstitial" +@property(nonatomic, readonly, copy) NSString *adUnitID; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) id appEventDelegate; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + id customRenderedInterstitialDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPRequest.h new file mode 100755 index 000000000..08f070f1b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/DFPRequest.h @@ -0,0 +1,37 @@ +// +// DFPRequest.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kDFPSimulatorID; + +/// Specifies optional parameters for ad requests. +@interface DFPRequest : GADRequest + +/// Publisher provided user ID. +@property(nonatomic, copy, GAD_NULLABLE) NSString *publisherProvidedID; + +/// Array of strings used to exclude specified categories in ad results. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *categoryExclusions; + +/// Key-value pairs used for custom targeting. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *customTargeting; + +/// This API is deprecated and a no-op, use an instance of GADCorrelator set on DFPInterstitial or +/// DFPBannerView objects to correlate requests. ++ (void)updateCorrelator GAD_DEPRECATED_MSG_ATTRIBUTE( + "Set GADCorrelator objects on your ads instead. This method no longer affects ad correlation."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdChoicesView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdChoicesView.h new file mode 100755 index 000000000..c05aeb537 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdChoicesView.h @@ -0,0 +1,23 @@ +// +// GADAdChoicesView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays AdChoices content. +/// +/// If a GADAdChoicesView is set on GADNativeAppInstallAdView or GADNativeContentAdView prior to +/// calling -setNativeAppInstallAd: or -setNativeContentAd:, AdChoices content will render inside +/// the GADAdChoicesView. By default, AdChoices is placed in the top right corner of +/// GADNativeAppInstallAdView and GADNativeContentAdView. +@interface GADAdChoicesView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdDelegate.h new file mode 100755 index 000000000..27cdda03d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdDelegate.h @@ -0,0 +1,28 @@ +// +// GADAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Audio Control Notifications + +/// Delegate methods common to multiple ad types. +@protocol GADAdDelegate + +@optional + +#pragma mark Audio Control Methods + +/// Asks the delegate if the audio session category can be changed while displaying an ad. Return NO +/// to prevent the Google Mobile Ads SDK from changing the audio session category. The default +/// behavior if unimplemented is to return YES. +- (BOOL)ad:(id)ad shouldChangeAudioSessionToCategory:(NSString *)audioSessionCategory; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoader.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoader.h new file mode 100755 index 000000000..44ee5c576 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoader.h @@ -0,0 +1,49 @@ +// +// GADAdLoader.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Loads ads. See GADAdLoaderAdTypes.h for available ad types. +@interface GADAdLoader : NSObject + +/// Object notified when an ad request succeeds or fails. Must conform to requested ad types' +/// delegate protocols. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// The ad loader's ad unit ID. +@property(nonatomic, readonly) NSString *adUnitID; + +/// Returns an initialized ad loader configured to load the specified ad types. +/// +/// @param rootViewController The root view controller is used to present ad click actions. +/// @param adTypes An array of ad types. See GADAdLoaderAdTypes.h for available ad types. +/// @param options An array of GADAdLoaderOptions objects to configure how ads are loaded, or nil to +/// use default options. See each ad type's header for available GADAdLoaderOptions subclasses. +- (instancetype)initWithAdUnitID:(NSString *)adUnitID + rootViewController:(UIViewController *GAD_NULLABLE_TYPE)rootViewController + adTypes:(NSArray *)adTypes + options:(NSArray *GAD_NULLABLE_TYPE)options; + +/// Loads the ad and informs the delegate of the outcome. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +@end + +/// Ad loader options base class. See each ad type's header for available GADAdLoaderOptions +/// subclasses. +@interface GADAdLoaderOptions : NSObject +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderAdTypes.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderAdTypes.h new file mode 100755 index 000000000..76d176236 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderAdTypes.h @@ -0,0 +1,31 @@ +// +// GADAdLoaderAdTypes.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use with GADAdLoader to request native app install ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeAppInstallAdRequestDelegate protocol. See GADNativeAppInstallAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeAppInstall; + +/// Use with GADAdLoader to request native content ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeContentAdRequestDelegate protocol. See GADNativeContentAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeContent; + +/// Use with GADAdLoader to request native custom template ads. To receive ads, the ad loader's +/// delegate must conform to the GADNativeCustomTemplateAdLoaderDelegate protocol. See +/// GADNativeCustomTemplateAd.h. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeCustomTemplate; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderDelegate.h new file mode 100755 index 000000000..dec90b784 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdLoaderDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdLoaderDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADAdLoader; + +GAD_ASSUME_NONNULL_BEGIN + +/// Base ad loader delegate protocol. Ad types provide extended protocols that declare methods to +/// handle successful ad loads. +@protocol GADAdLoaderDelegate + +/// Called when adLoader fails to load an ad. +- (void)adLoader:(GADAdLoader *)adLoader didFailToReceiveAdWithError:(GADRequestError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdNetworkExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdNetworkExtras.h new file mode 100755 index 000000000..55c62f134 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdNetworkExtras.h @@ -0,0 +1,22 @@ +// +// GADAdNetworkExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An object implementing this protocol contains information set by the publisher on the client +/// device for a particular ad network. +/// +/// Ad networks should create an 'extras' object implementing this protocol for their publishers to +/// use. +@protocol GADAdNetworkExtras +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdReward.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdReward.h new file mode 100755 index 000000000..38aeefb55 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdReward.h @@ -0,0 +1,30 @@ +// +// GADAdReward.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Reward information for GADRewardBasedVideoAd ads. +@interface GADAdReward : NSObject + +/// Type of the reward. +@property(nonatomic, readonly, copy) NSString *type; + +/// Amount rewarded to the user. +@property(nonatomic, readonly, copy) NSDecimalNumber *amount; + +/// Returns an initialized GADAdReward with the provided reward type and reward amount. rewardType +/// and rewardAmount must not be nil. +- (instancetype)initWithRewardType:(NSString *)rewardType + rewardAmount:(NSDecimalNumber *)rewardAmount NS_DESIGNATED_INITIALIZER; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSize.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSize.h new file mode 100755 index 000000000..c92b767d2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSize.h @@ -0,0 +1,117 @@ +// +// GADAdSize.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A valid GADAdSize is considered to be one of the predefined GADAdSize constants or a GADAdSize +/// constructed by GADAdSizeFromCGSize, GADAdSizeFullWidthPortraitWithHeight, +/// GADAdSizeFullWidthLandscapeWithHeight. +/// +/// Do not create a GADAdSize manually. Use one of the kGADAdSize constants. Treat GADAdSize as an +/// opaque type. Do not access any fields directly. To obtain a concrete CGSize, use the function +/// CGSizeFromGADAdSize(). +typedef struct GAD_BOXABLE GADAdSize GADAdSize; + +/// Ad size. +/// +/// @see typedef GADAdSize +struct GAD_BOXABLE GADAdSize { + CGSize size; ///< The ad size. Don't modify this value directly. + NSUInteger flags; ///< Reserved. +}; + +#pragma mark Standard Sizes + +/// iPhone and iPod Touch ad size. Typically 320x50. +GAD_EXTERN GADAdSize const kGADAdSizeBanner; + +/// Taller version of kGADAdSizeBanner. Typically 320x100. +GAD_EXTERN GADAdSize const kGADAdSizeLargeBanner; + +/// Medium Rectangle size for the iPad (especially in a UISplitView's left pane). Typically 300x250. +GAD_EXTERN GADAdSize const kGADAdSizeMediumRectangle; + +/// Full Banner size for the iPad (especially in a UIPopoverController or in +/// UIModalPresentationFormSheet). Typically 468x60. +GAD_EXTERN GADAdSize const kGADAdSizeFullBanner; + +/// Leaderboard size for the iPad. Typically 728x90. +GAD_EXTERN GADAdSize const kGADAdSizeLeaderboard; + +/// Skyscraper size for the iPad. Mediation only. AdMob/Google does not offer this size. Typically +/// 120x600. +GAD_EXTERN GADAdSize const kGADAdSizeSkyscraper; + +/// An ad size that spans the full width of the application in portrait orientation. The height is +/// typically 50 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerPortrait; + +/// An ad size that spans the full width of the application in landscape orientation. The height is +/// typically 32 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerLandscape; + +/// An ad size that spans the full width of its container, with a height dynamically determined by +/// the ad. +GAD_EXTERN GADAdSize const kGADAdSizeFluid; + +/// Invalid ad size marker. +GAD_EXTERN GADAdSize const kGADAdSizeInvalid; + +#pragma mark Custom Sizes + +/// Returns a custom GADAdSize for the provided CGSize. Use this only if you require a non-standard +/// size. Otherwise, use one of the standard size constants above. +GAD_EXTERN GADAdSize GADAdSizeFromCGSize(CGSize size); + +/// Returns a custom GADAdSize that spans the full width of the application in portrait orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthPortraitWithHeight(CGFloat height); + +/// Returns a custom GADAdSize that spans the full width of the application in landscape orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthLandscapeWithHeight(CGFloat height); + +#pragma mark Convenience Functions + +/// Returns YES if the two GADAdSizes are equal, otherwise returns NO. +GAD_EXTERN BOOL GADAdSizeEqualToSize(GADAdSize size1, GADAdSize size2); + +/// Returns a CGSize for the provided a GADAdSize constant. If the GADAdSize is unknown, returns +/// CGSizeZero. +GAD_EXTERN CGSize CGSizeFromGADAdSize(GADAdSize size); + +/// Returns YES if |size| is one of the predefined constants or is a custom GADAdSize generated by +/// GADAdSizeFromCGSize. +GAD_EXTERN BOOL IsGADAdSizeValid(GADAdSize size); + +/// Returns YES if |size| is a fluid ad size. +GAD_EXTERN BOOL GADAdSizeIsFluid(GADAdSize size); + +/// Returns a NSString describing the provided GADAdSize. +GAD_EXTERN NSString *NSStringFromGADAdSize(GADAdSize size); + +/// Returns an NSValue representing the GADAdSize. +GAD_EXTERN NSValue *NSValueFromGADAdSize(GADAdSize size); + +/// Returns a GADAdSize from an NSValue. Returns kGADAdSizeInvalid if the value is not a GADAdSize. +GAD_EXTERN GADAdSize GADAdSizeFromNSValue(NSValue *value); + +#pragma mark Deprecated Macros + +#define GAD_SIZE_320x50 CGSizeFromGADAdSize(kGADAdSizeBanner) +#define GAD_SIZE_320x100 CGSizeFromGADAdSize(kGADAdSizeLargeBanner) +#define GAD_SIZE_300x250 CGSizeFromGADAdSize(kGADAdSizeMediumRectangle) +#define GAD_SIZE_468x60 CGSizeFromGADAdSize(kGADAdSizeFullBanner) +#define GAD_SIZE_728x90 CGSizeFromGADAdSize(kGADAdSizeLeaderboard) +#define GAD_SIZE_120x600 CGSizeFromGADAdSize(kGADAdSizeSkyscraper) + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSizeDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSizeDelegate.h new file mode 100755 index 000000000..ce82adceb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAdSizeDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdSizeDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; + +GAD_ASSUME_NONNULL_BEGIN + +/// The class implementing this protocol will be notified when the DFPBannerView changes ad size. +/// Any views that may be affected by the banner size change will have time to adjust. +@protocol GADAdSizeDelegate + +/// Called before the ad view changes to the new size. +- (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAppEventDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAppEventDelegate.h new file mode 100755 index 000000000..a9f79cf14 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADAppEventDelegate.h @@ -0,0 +1,35 @@ +// +// GADAppEventDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADBannerView; +@class GADInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// Implement your app event within these methods. The delegate will be notified when the SDK +/// receives an app event message from the ad. +@protocol GADAppEventDelegate + +@optional + +/// Called when the banner receives an app event. +- (void)adView:(GADBannerView *)banner + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +/// Called when the interstitial receives an app event. +- (void)interstitial:(GADInterstitial *)interstitial + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerView.h new file mode 100755 index 000000000..a93a71b10 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerView.h @@ -0,0 +1,108 @@ +// +// GADBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays banner ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADBannerView *adView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADBannerView : UIView + +#pragma mark Initialization + +/// Initializes and returns a banner view with the specified ad size and origin relative to the +/// banner's superview. +- (instancetype)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Initializes and returns a banner view with the specified ad size placed at its superview's +/// origin. +- (instancetype)initWithAdSize:(GADAdSize)adSize; + +#pragma mark Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example the root view controller in +/// tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this banner view to a proper size. Never create your own GADAdSize directly. Use +/// one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If not using mediation, then changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If using mediation, +/// then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this GADBannerView. +/// Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id inAppPurchaseDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +#pragma mark Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +#pragma mark Mediation + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +#pragma mark Deprecated + +/// Indicates if the currently displayed ad (or most recent failure) was a result of auto refreshing +/// as specified on server. This property is set to NO after each loadRequest: method. +@property(nonatomic, readonly, assign) BOOL hasAutoRefreshed GAD_DEPRECATED_ATTRIBUTE; + +/// The mediated ad network's underlying ad view. You may use this property to read the ad's actual +/// size and adjust this banner view's frame origin. However, modifying the banner view's frame size +/// triggers the Mobile Ads SDK to request a new ad. Only update the banner view's frame origin. +@property(nonatomic, readonly, weak, GAD_NULLABLE) + UIView *mediatedAdView GAD_DEPRECATED_MSG_ATTRIBUTE("Use adNetworkClassName."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerViewDelegate.h new file mode 100755 index 000000000..f977bc479 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADBannerViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADBannerView state change messages such as ad request status +/// and ad click lifecycle. +@protocol GADBannerViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that an ad request successfully received an ad. The delegate may want to add +/// the banner view to the view hierarchy if it hasn't been added yet. +- (void)adViewDidReceiveAd:(GADBannerView *)bannerView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)adView:(GADBannerView *)bannerView didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)adViewWillPresentScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)adViewWillDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)adViewDidDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)adViewWillLeaveApplication:(GADBannerView *)bannerView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelator.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelator.h new file mode 100755 index 000000000..909f0f4cf --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelator.h @@ -0,0 +1,23 @@ +// +// GADCorrelator.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Represents a correlation between multiple ads. Set an instance of this object on multiple ads to +/// indicate they are being used in a common context. +@interface GADCorrelator : NSObject + +/// Resets the correlator to force a new set of correlated ads. +- (void)reset; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelatorAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelatorAdLoaderOptions.h new file mode 100755 index 000000000..b10d60757 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCorrelatorAdLoaderOptions.h @@ -0,0 +1,22 @@ +// +// GADCorrelatorAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad loader options for adding a correlator to a native ad request. +@interface GADCorrelatorAdLoaderOptions : GADAdLoaderOptions + +/// Correlator object for correlating ads loaded by an ad loader to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBanner.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBanner.h new file mode 100755 index 000000000..53317d909 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBanner.h @@ -0,0 +1,40 @@ +// +// GADCustomEventBanner.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The banner custom event protocol. Your banner custom event handler must implement this protocol. +@protocol GADCustomEventBanner + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Report execution results +/// to the delegate. +/// +/// @param adSize The size of the ad as configured in the mediation UI for the mediation placement. +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestBannerAd:(GADAdSize)adSize + parameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBannerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBannerDelegate.h new file mode 100755 index 000000000..8ec685c5c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventBannerDelegate.h @@ -0,0 +1,68 @@ +// +// GADCustomEventBannerDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventBanner; + +/// Call back to this delegate in your custom event. You must call customEventBanner:didReceiveAd: +/// when there is an ad to show, or customEventBanner:didFailAd: when there is no ad to show. +/// Otherwise, if enough time passed (several seconds) after the SDK called the requestBannerAd: +/// method of your custom event, the mediation SDK will consider the request timed out, and move on +/// to the next ad network. +@protocol GADCustomEventBannerDelegate + +/// Your Custom Event object must call this when it receives or creates an ad view. +- (void)customEventBanner:(id)customEvent didReceiveAd:(UIView *)view; + +/// Your Custom Event object must call this when it fails to receive or create the ad view. Pass +/// along any error object sent from the ad network's SDK, or an NSError describing the error. Pass +/// nil if not available. +- (void)customEventBanner:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventBannerWasClicked:(id)customEvent; + +/// The rootViewController that you set in GADBannerView. Use this UIViewController to show a modal +/// view when a user taps on the ad. +@property(nonatomic, readonly) UIViewController *viewControllerForPresentingModalView; + +/// When you call the following methods, the call will be propagated back to the +/// GADBannerViewDelegate that you implemented and passed to GADBannerView. + +/// Your Custom Event should call this when the user taps an ad and a modal view appears. +- (void)customEventBannerWillPresentModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view is +/// about to go away. +- (void)customEventBannerWillDismissModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view has +/// gone away. +- (void)customEventBannerDidDismissModal:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in App switching. +- (void)customEventBannerWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventBannerWasClicked:. +- (void)customEventBanner:(id)customEvent + clickDidOccurInAd:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventBannerWasClicked:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventExtras.h new file mode 100755 index 000000000..a42a35cc1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventExtras.h @@ -0,0 +1,35 @@ +// +// GADCustomEventExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Create an instance of this class to set additional parameters for each custom event object. The +/// additional parameters for a custom event are keyed by the custom event label. These extras are +/// passed to your implementation of GADCustomEventBanner or GADCustomEventInterstitial. +@interface GADCustomEventExtras : NSObject + +/// Set additional parameters for the custom event with label |label|. To remove additional +/// parameters associated with |label|, pass in nil for |extras|. +- (void)setExtras:(NSDictionary *GAD_NULLABLE_TYPE)extras forLabel:(NSString *)label; + +/// Retrieve the extras for |label|. +- (NSDictionary *GAD_NULLABLE_TYPE)extrasForLabel:(NSString *)label; + +/// Removes all the extras set on this instance. +- (void)removeAllExtras; + +/// Returns all the extras set on this instance. +- (NSDictionary *)allExtras; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitial.h new file mode 100755 index 000000000..7a05e3bd6 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitial.h @@ -0,0 +1,43 @@ +// +// GADCustomEventInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The interstitial custom event protocol. Your interstitial custom event handler must implement +/// this protocol. +@protocol GADCustomEventInterstitial + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Your implementation +/// should start retrieving the interstitial ad. Report execution results to the delegate. You must +/// wait until -presentFromRootViewController is called before displaying the interstitial ad. +/// +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestInterstitialAdWithParameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +/// Present the interstitial ad as a modal view using the provided view controller. Called only +/// after your class calls -customEventInterstitialDidReceiveAd: on its custom event delegate. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitialDelegate.h new file mode 100755 index 000000000..97219d3e5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventInterstitialDelegate.h @@ -0,0 +1,62 @@ +// +// GADCustomEventInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventInterstitial; + +/// Call back to this delegate in your custom event. You must call +/// customEventInterstitialDidReceiveAd: when there is an ad to show, or +/// customEventInterstitial:didFailAd: when there is no ad to show. Otherwise, if enough time passed +/// (several seconds) after the SDK called the requestInterstitialAdWithParameter: method of your +/// custom event, the mediation SDK will consider the request timed out, and move on to the next ad +/// network. +@protocol GADCustomEventInterstitialDelegate + +/// Your Custom Event object must call this when it receives or creates an interstitial ad. +- (void)customEventInterstitialDidReceiveAd:(id)customEvent; + +/// Your Custom Event object must call this when it fails to receive or create the ad. Pass along +/// any error object sent from the ad network's SDK, or an NSError describing the error. Pass nil if +/// not available. +- (void)customEventInterstitial:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventInterstitialWasClicked:(id)customEvent; + +// When you call any of the following methods, the call will be propagated back to the +// GADInterstitialDelegate that you implemented and passed to GADInterstitial. + +/// Your Custom Event should call this when the interstitial is being displayed. +- (void)customEventInterstitialWillPresent:(id)customEvent; + +/// Your Custom Event should call this when the interstitial is about to be dismissed. +- (void)customEventInterstitialWillDismiss:(id)customEvent; + +/// Your Custom Event should call this when the interstitial has been dismissed. +- (void)customEventInterstitialDidDismiss:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in app switching. +- (void)customEventInterstitialWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventInterstitialDidReceiveAd:. +- (void)customEventInterstitial:(id)customEvent + didReceiveAd:(NSObject *)ad + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventInterstitialDidReceiveAd:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAd.h new file mode 100755 index 000000000..9a99c7e42 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAd.h @@ -0,0 +1,58 @@ +// +// GADCustomEventNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventNativeAdDelegate; + +/// Native ad custom event protocol. Your native ad custom event handler class must conform to this +/// protocol. +@protocol GADCustomEventNativeAd + +/// Called when the custom event is scheduled to be executed. +/// +/// @param serverParameter A value configured in the mediation UI for the custom event. +/// @param request Ad targeting information. +/// @param adTypes List of requested native ad types. See GADAdLoaderAdTypes.h for available ad +/// types. +/// @param options Additional options configured by the publisher for requesting a native ad. See +/// GADNativeAdImageAdLoaderOptions.h for available image options. +/// @param rootViewController Publisher-provided view controller. +- (void)requestNativeAdWithParameter:(NSString *)serverParameter + request:(GADCustomEventRequest *)request + adTypes:(NSArray *)adTypes + options:(NSArray *)options + rootViewController:(UIViewController *)rootViewController; + +/// Indicates if the custom event handles user clicks. Return YES if the custom event should handle +/// user clicks. In this case, the Google Mobile Ads SDK doesn't track user clicks and the custom +/// event must notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. Return NO if the +/// custom event doesn't handles user clicks. In this case, the Google Mobile Ads SDK tracks user +/// clicks itself and the custom event is notified of user clicks via -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the custom event handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the custom event must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the custom event of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// Delegate object used for receiving custom native ad load request progress. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAdDelegate.h new file mode 100755 index 000000000..19029a3c8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventNativeAdDelegate.h @@ -0,0 +1,31 @@ +// +// GADCustomEventNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The delegate of the GADCustomEventNativeAd object must adopt the GADCustomEventNativeAdDelegate +/// protocol. Methods in this protocol are used for native ad's custom event communication with the +/// Google Mobile Ads SDK. +@protocol GADCustomEventNativeAdDelegate + +/// Tells the delegate that the custom event ad request succeeded and loaded a native ad. +- (void)customEventNativeAd:(id)customEventNativeAd + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +/// Tells the delegate that the custom event ad request failed. +- (void)customEventNativeAd:(id)customEventNativeAd + didFailToLoadWithError:(NSError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventParameters.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventParameters.h new file mode 100755 index 000000000..084155d69 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventParameters.h @@ -0,0 +1,19 @@ +// +// GADCustomEventParameters.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Key for getting the server parameter configured in AdMob when mediating to a custom event +/// adapter. +/// Example: NSString *serverParameter = connector.credentials[GADCustomEventParametersServer]. +extern NSString *const GADCustomEventParametersServer; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventRequest.h new file mode 100755 index 000000000..cf48be3a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADCustomEventRequest.h @@ -0,0 +1,59 @@ +// +// GADCustomEventRequest.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADCustomEventExtras; + +GAD_ASSUME_NONNULL_BEGIN + +/// Specifies optional ad request targeting parameters that are provided by the publisher and are +/// forwarded to custom events for purposes of populating an ad request to a 3rd party ad network. +@interface GADCustomEventRequest : NSObject + +/// User's gender set in GADRequest. If not specified, returns kGADGenderUnknown. +@property(nonatomic, readonly, assign) GADGender userGender; + +/// User's birthday set in GADRequest. If not specified, returns nil. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDate *userBirthday; + +/// If the user's latitude, longitude, and accuracy are not specified, userHasLocation returns NO, +/// and userLatitude, userLongitude, and userLocationAccuracyInMeters return 0. +@property(nonatomic, readonly, assign) BOOL userHasLocation; + +/// User's latitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLatitude; + +/// User's longitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLongitude; + +/// The accuracy, in meters, of the user's location data. +@property(nonatomic, readonly, assign) CGFloat userLocationAccuracyInMeters; + +/// Description of the user's location, in free form text, set in GADRequest. If not available, +/// returns nil. This may be set even if userHasLocation is NO. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *userLocationDescription; + +/// Keywords set in GADRequest. Returns nil if no keywords are set. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *userKeywords; + +/// The additional parameters set by the application. This property allows you to pass additional +/// information from your application to your Custom Event object. To do so, create an instance of +/// GADCustomEventExtras to pass to GADRequest -registerAdNetworkExtras:. The instance should have +/// an NSDictionary set for a particular custom event label. That NSDictionary becomes the +/// additionalParameters here. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +/// Indicates if the testing property has been set in GADRequest. +@property(nonatomic, readonly, assign) BOOL isTesting; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDebugOptionsViewController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDebugOptionsViewController.h new file mode 100755 index 000000000..acc98dc3f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDebugOptionsViewController.h @@ -0,0 +1,36 @@ +// +// GADDebugOptionsViewController.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +@class GADDebugOptionsViewController; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for the GADDebugOptionsViewController. +@protocol GADDebugOptionsViewControllerDelegate +/// Called when the debug options flow is finished. +- (void)debugOptionsViewControllerDidDismiss:(GADDebugOptionsViewController *)controller; +@end + +/// Displays debug options to the user. +@interface GADDebugOptionsViewController : UIViewController + +/// Creates and returns a GADDebugOptionsViewController object initialized with the ad unit ID. +/// @param adUnitID An ad unit ID for the DFP account that is being configured with debug options. ++ (instancetype)debugOptionsViewControllerWithAdUnitID:(NSString *)adUnitID; + +/// Delegate for the debug options view controller. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDynamicHeightSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDynamicHeightSearchRequest.h new file mode 100755 index 000000000..4fefe66fd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADDynamicHeightSearchRequest.h @@ -0,0 +1,165 @@ +// +// GADDynamicHeightSearchRequest.h +// GoogleMobileAds +// +// Copyright © 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use to configure Custom Search Ad (CSA) ad requests. A dynamic height search banner can contain +/// multiple ads and the height is set dynamically based on the ad contents. Please cross-reference +/// the property sections and properties with the official reference document: +/// https://developers.google.com/custom-search-ads/docs/reference +@interface GADDynamicHeightSearchRequest : GADRequest + +#pragma mark - Page Level Parameters + +#pragma mark Required + +/// The CSA "query" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; + +/// The CSA "adPage" parameter. +@property(nonatomic, assign) NSInteger adPage; + +#pragma mark Configuration Settings + +/// Indicates if the CSA "adTest" parameter is enabled. +@property(nonatomic, assign) BOOL adTestEnabled; + +/// The CSA "channel" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *channel; + +/// The CSA "hl" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *hostLanguage; + +#pragma mark Layout and Styling + +/// The CSA "colorLocation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *locationExtensionTextColor; + +/// The CSA "fontSizeLocation" parameter. +@property(nonatomic, assign) CGFloat locationExtensionFontSize; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "clickToCall" parameter is enabled. +@property(nonatomic, assign) BOOL clickToCallExtensionEnabled; + +/// Indicates if the CSA "location" parameter is enabled. +@property(nonatomic, assign) BOOL locationExtensionEnabled; + +/// Indicates if the CSA "plusOnes" parameter is enabled. +@property(nonatomic, assign) BOOL plusOnesExtensionEnabled; + +/// Indicates if the CSA "sellerRatings" parameter is enabled. +@property(nonatomic, assign) BOOL sellerRatingsExtensionEnabled; + +/// Indicates if the CSA "siteLinks" parameter is enabled. +@property(nonatomic, assign) BOOL siteLinksExtensionEnabled; + +#pragma mark - Unit Level Parameters + +#pragma mark Required + +/// The CSA "width" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *CSSWidth; + +/// Configuration Settings + +/// The CSA "number" parameter. +@property(nonatomic, assign) NSInteger numberOfAds; + +#pragma mark Font + +/// The CSA "fontFamily" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; + +/// The CSA "fontFamilyAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionFontFamily; + +/// The CSA "fontSizeAnnotation" parameter. +@property(nonatomic, assign) CGFloat annotationFontSize; + +/// The CSA "fontSizeAttribution" parameter. +@property(nonatomic, assign) CGFloat attributionFontSize; + +/// The CSA "fontSizeDescription" parameter. +@property(nonatomic, assign) CGFloat descriptionFontSize; + +/// The CSA "fontSizeDomainLink" parameter. +@property(nonatomic, assign) CGFloat domainLinkFontSize; + +/// The CSA "fontSizeTitle" parameter. +@property(nonatomic, assign) CGFloat titleFontSize; + +#pragma mark Color + +/// The CSA "colorAdBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderColor; + +/// The CSA "colorAdSeparator" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adSeparatorColor; + +/// The CSA "colorAnnotation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *annotationTextColor; + +/// The CSA "colorAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionTextColor; + +/// The CSA "colorBackground" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *backgroundColor; + +/// The CSA "colorBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderColor; + +/// The CSA "colorDomainLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *domainLinkColor; + +/// The CSA "colorText" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *textColor; + +/// The CSA "colorTitleLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *titleLinkColor; + +#pragma mark General Formatting + +/// The CSA "adBorderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderCSSSelections; + +/// The CSA "adjustableLineHeight" parameter. +@property(nonatomic, assign) CGFloat adjustableLineHeight; + +/// The CSA "attributionSpacingBelow" parameter. +@property(nonatomic, assign) CGFloat attributionBottomSpacing; + +/// The CSA "borderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderCSSSelections; + +/// Indicates if the CSA "noTitleUnderline" parameter is enabled. +@property(nonatomic, assign) BOOL titleUnderlineHidden; + +/// Indicates if the CSA "titleBold" parameter is enabled. +@property(nonatomic, assign) BOOL boldTitleEnabled; + +/// The CSA "verticalSpacing" parameter. +@property(nonatomic, assign) CGFloat verticalSpacing; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "detailedAttribution" parameter is enabled. +@property(nonatomic, assign) BOOL detailedAttributionExtensionEnabled; + +/// Indicates if the CSA "longerHeadlines" parameter is enabled. +@property(nonatomic, assign) BOOL longerHeadlinesExtensionEnabled; + +/// Sets an advanced option value for a specified key. The value must be an NSString or NSNumber. +- (void)setAdvancedOptionValue:(id)value forKey:(NSString *)key; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADExtras.h new file mode 100755 index 000000000..3ca160fa0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADExtras.h @@ -0,0 +1,23 @@ +// +// GADExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad network extras sent to Google networks. +@interface GADExtras : NSObject + +/// Additional parameters to be sent to Google networks. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchase.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchase.h new file mode 100755 index 000000000..07fc206fa --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchase.h @@ -0,0 +1,86 @@ +// +// GADInAppPurchase.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADDefaultInAppPurchaseDelegate; + +#pragma mark - Default Purchase Flow + +/// The consumable in-app purchase item that has been purchased by the user. The purchase flow is +/// handled by the Google Mobile Ads SDK. +/// Instances of this class are created and passed to your in-app purchase delegate after the user +/// has successfully paid for a product. Your code must correctly deliver the product to the user +/// and then call the didCompletePurchase method to finish the transaction. +@interface GADDefaultInAppPurchase : NSObject + +/// Enables the default consumable product in-app purchase flow handled by the Google Mobile Ads +/// SDK. The GADDefaultInAppPurchaseDelegate object is retained while the default purchase flow is +/// enabled. This method adds a SKPaymentTransactionObserver to the default SKPaymentQueue. +/// +/// Call this method early in your application to handle unfinished transactions from previous +/// application sessions. For example, call this method in your application delegate's +/// application:didFinishLaunchingWithOptions: method. ++ (void)enableDefaultPurchaseFlowWithDelegate:(id)delegate; + +/// Disables the default in-app purchase flow handled by the Google Mobile Ads SDK and releases the +/// associated GADDefaultInAppPurchaseDelegate object. ++ (void)disableDefaultPurchaseFlow; + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The purchased item's completed payment transaction. Your application can use this property's +/// data to save a permanent record of the completed payment. The default purchase flow will finish +/// the transaction on your behalf. Do not finish the transaction yourself. +@property(nonatomic, readonly, strong) SKPaymentTransaction *paymentTransaction; + +/// The in-app purchase delegate object must first deliver the user's item and then call this +/// method. Failure to call this method will result in duplicate purchase notifications. +- (void)finishTransaction; + +@end + +#pragma mark - Custom Purchase Flow + +/// Enum of the different statuses resulting from processing a purchase. +typedef NS_ENUM(NSInteger, GADInAppPurchaseStatus) { + kGADInAppPurchaseStatusError = 0, ///< Error occured while processing the purchase. + kGADInAppPurchaseStatusSuccessful = 1, ///< Purchase was completed successfully. + kGADInAppPurchaseStatusCancel = 2, ///< Purchase was cancelled by the user. + kGADInAppPurchaseStatusInvalidProduct = 3 ///< Error occured while looking up the product. +}; + +/// The in-app purchase item to be purchased with the purchase flow handled by you, the +/// application developer. +/// Instances of this class are created and passed to your GADInAppPurchaseDelegate object when +/// users click a buy button. It is important to report the result of the purchase back to the SDK +/// in order to track metrics about the transaction. +@interface GADInAppPurchase : NSObject + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The GADInAppPurchaseDelegate object must call this method after handling the in-app purchase for +/// both successful and unsuccessful purchase attempts. This method reports ad conversion and +/// purchase status information to Google. +- (void)reportPurchaseStatus:(GADInAppPurchaseStatus)purchaseStatus; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchaseDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchaseDelegate.h new file mode 100755 index 000000000..fe1d8f941 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInAppPurchaseDelegate.h @@ -0,0 +1,48 @@ +// +// GADInAppPurchaseDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADDefaultInAppPurchase; +@class GADInAppPurchase; + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Default Purchase Flow + +/// In-app purchase delegate protocol for default purchase handling. The delegate must deliver +/// the purchased item then call the GADDefaultInAppPurchase object's finishTransaction method. +@protocol GADDefaultInAppPurchaseDelegate + +/// Called when the user successfully paid for a purchase. You must first deliver the purchased +/// item to the user, then call defaultInAppPurchase's finishTransaction method. +- (void)userDidPayForPurchase:(GADDefaultInAppPurchase *)defaultInAppPurchase; + +@optional + +/// Called when the user clicks on the buy button of an in-app purchase ad. Return YES if the +/// default purchase flow should be started to purchase the item, otherwise return NO. If not +/// implemented, defaults to YES. +- (BOOL)shouldStartPurchaseForProductID:(NSString *)productID quantity:(NSInteger)quantity; + +@end + +#pragma mark - Custom Purchase Flow + +/// In-app purchase delegate protocol for custom purchase handling. The delegate must handle the +/// product purchase flow then call the GADInAppPurchase object's reportPurchaseStatus: method. +@protocol GADInAppPurchaseDelegate + +/// Called when the user clicks on the buy button of an in-app purchase ad. After the receiver +/// handles the purchase, it must call the GADInAppPurchase object's reportPurchaseStatus: method. +- (void)didReceiveInAppPurchase:(GADInAppPurchase *)purchase; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitial.h new file mode 100755 index 000000000..cb17be99d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitial.h @@ -0,0 +1,88 @@ +// +// GADInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An interstitial ad. This is a full-screen advertisement shown at natural transition points in +/// your application such as between game levels or news stories. +@interface GADInterstitial : NSObject + +/// Initializes an interstitial with an ad unit created on the AdMob website. Create a new ad unit +/// for every unique placement of an ad in your application. Set this to the ID assigned for this +/// placement. Ad units are important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +- (instancetype)initWithAdUnitID:(NSString *)adUnitID NS_DESIGNATED_INITIALIZER; + +#pragma mark Pre-Request + +/// Required value passed in with initWithAdUnitID:. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate object that receives state change notifications from this GADInterstitalAd. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) id inAppPurchaseDelegate; + +#pragma mark Making an Ad Request + +/// Makes an interstitial ad request. Additional targeting options can be supplied with a request +/// object. Only one interstitial request is allowed at a time. +/// +/// This is best to do several seconds before the interstitial is needed to preload its content. +/// Then when transitioning between view controllers show the interstital with +/// presentFromViewController. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark Post-Request + +/// Returns YES if the interstitial is ready to be displayed. The delegate's +/// interstitialAdDidReceiveAd: will be called after this property switches from NO to YES. +@property(nonatomic, readonly, assign) BOOL isReady; + +/// Returns YES if this object has already been presented. Interstitial objects can only be used +/// once even with different requests. +@property(nonatomic, readonly, assign) BOOL hasBeenUsed; + +/// Returns the ad network class name that fetched the current ad. Returns nil while the latest ad +/// request is in progress or if the latest ad request failed. For both standard and mediated Google +/// AdMob ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Presents the interstitial ad which takes over the entire screen until the user dismisses it. +/// This has no effect unless isReady returns YES and/or the delegate's interstitialDidReceiveAd: +/// has been received. +/// +/// Set rootViewController to the current view controller at the time this method is called. If your +/// application does not use view controllers pass in nil and your views will be removed from the +/// window to show the interstitial and restored when done. After the interstitial has been removed, +/// the delegate's interstitialDidDismissScreen: will be called. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +#pragma mark Deprecated + +/// Deprecated intializer. Use initWithAdUnitID: instead. +- (instancetype)init GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID:."); + +/// Deprecated setter, use initWithAdUnitID: instead. +- (void)setAdUnitID:(NSString *GAD_NULLABLE_TYPE)adUnitID + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID: instead of setting the ad unit ID."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitialDelegate.h new file mode 100755 index 000000000..e83fcf9c0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADInterstitialDelegate.h @@ -0,0 +1,59 @@ +// +// GADInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADInterstitial; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADInterstitial such as interstitial ad +/// requests succeeding/failing. +@protocol GADInterstitialDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Called when an interstitial ad request succeeded. Show it at the next transition point in your +/// application such as when transitioning between view controllers. +- (void)interstitialDidReceiveAd:(GADInterstitial *)ad; + +/// Called when an interstitial ad request completed without an interstitial to +/// show. This is common since interstitials are shown sparingly to users. +- (void)interstitial:(GADInterstitial *)ad didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Display-Time Lifecycle Notifications + +/// Called just before presenting an interstitial. After this method finishes the interstitial will +/// animate onto the screen. Use this opportunity to stop animations and save the state of your +/// application in case the user leaves while the interstitial is on screen (e.g. to visit the App +/// Store from a link on the interstitial). +- (void)interstitialWillPresentScreen:(GADInterstitial *)ad; + +/// Called when |ad| fails to present. +- (void)interstitialDidFailToPresentScreen:(GADInterstitial *)ad; + +/// Called before the interstitial is to be animated off the screen. +- (void)interstitialWillDismissScreen:(GADInterstitial *)ad; + +/// Called just after dismissing an interstitial and it has animated off the screen. +- (void)interstitialDidDismissScreen:(GADInterstitial *)ad; + +/// Called just before the application will background or terminate because the user clicked on an +/// ad that will launch another application (such as the App Store). The normal +/// UIApplicationDelegate methods, like applicationDidEnterBackground:, will be called immediately +/// before this. +- (void)interstitialWillLeaveApplication:(GADInterstitial *)ad; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediaView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediaView.h new file mode 100755 index 000000000..d08b4e78e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediaView.h @@ -0,0 +1,27 @@ +// +// GADMediaView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays native ad media assets. +/// +/// To display media assets in GADNativeAppInstallAdView instances, add a GADMediaView subview and +/// assign the native ad view's mediaView property. +/// +/// If the native ad doesn't contain a video and image loading is enabled, the GADMediaView displays +/// the native ad's |images| asset's first image. +/// +/// If the native ad doesn't contain a video and image loading is disabled, the GADMediaView object +/// is empty. +@interface GADMediaView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAd.h new file mode 100755 index 000000000..7f37ae26f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAd.h @@ -0,0 +1,27 @@ +// +// GADMediatedNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Base protocol for mediated native ads. +@protocol GADMediatedNativeAd + +/// Returns a delegate object that receives state change notifications. +- (nullable id)mediatedNativeAdDelegate; + +/// Returns a dictionary of asset names and object pairs for assets that are not handled by +/// properties of the GADMediatedNativeAd subclass. +- (NSDictionary *GAD_NULLABLE_TYPE)extraAssets; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdDelegate.h new file mode 100755 index 000000000..b705652e1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdDelegate.h @@ -0,0 +1,47 @@ +// +// GADMediatedNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADMediatedNativeAd; + +/// GADMediatedNativeAdDelegate objects handle mediated native ad events. +@protocol GADMediatedNativeAdDelegate + +@optional + +/// Tells the delegate that the mediated native ad has rendered in |view|, a subview of +/// |viewController|. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRenderInView:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has recorded an impression. This method is called +/// only once per mediated native ad. +- (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Tells the delegate that the mediated native ad has recorded a user click on the asset named +/// |assetName|. Full screen actions should be presented from |viewController|. This method is +/// called only if -[GADMAdNetworkAdapter handlesUserClicks] returns NO. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRecordClickOnAssetWithName:(NSString *)assetName + view:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has untracked |view|. This method is called +/// when the mediatedNativeAd is no longer rendered in the provided view and the delegate should +/// stop tracking the view's impressions and clicks. +- (void)mediatedNativeAd:(id)mediatedNativeAd didUntrackView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdNotificationSource.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdNotificationSource.h new file mode 100755 index 000000000..3a3cfe6f8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAdNotificationSource.h @@ -0,0 +1,45 @@ +// +// GADMediatedNativeAdNotificationSource.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Notifies the Google Mobile Ads SDK about the events performed by adapters. Adapters may perform +/// some action (e.g. opening an in app browser or open the iTunes store) when handling callbacks +/// from GADMediatedNativeAdDelegate. Adapters in such case should notify the Google Mobile Ads SDK +/// by calling the relevant methods from this class. +@interface GADMediatedNativeAdNotificationSource : NSObject + +/// Called by the adapter when it has registered an impression on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserImpressions] returns YES. ++ (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Called by the adapter when it has registered a user click on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserClicks] returns YES. ++ (void)mediatedNativeAdDidRecordClick:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has opened an in app modal screen. ++ (void)mediatedNativeAdWillPresentScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdWillDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter after the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdDidDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has left the application. ++ (void)mediatedNativeAdWillLeaveApplication:(id)mediatedNativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAppInstallAd.h new file mode 100755 index 000000000..9475d35d5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeAppInstallAd.h @@ -0,0 +1,51 @@ +// +// GADMediatedNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native app install ads. The adapter must return an object +/// conforming to this protocol for native app install ad requests. +@protocol GADMediatedNativeAppInstallAd + +/// App title. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Array of GADNativeAdImage objects related to the advertised application. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// App description. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// Application icon. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)icon; + +/// Text that encourages user to take some action with the ad. For example "Install". +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// App store rating (0 to 5). +- (NSDecimalNumber *GAD_NULLABLE_TYPE)starRating; + +/// The app store name. For example, "App Store". +- (NSString *GAD_NULLABLE_TYPE)store; + +/// String representation of the app's price. +- (NSString *GAD_NULLABLE_TYPE)price; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeContentAd.h new file mode 100755 index 000000000..068da5845 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMediatedNativeContentAd.h @@ -0,0 +1,44 @@ +// +// GADMediatedNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native content ads. +@protocol GADMediatedNativeContentAd + +/// Primary text headline. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Secondary text. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// List of large images. Each object is an instance of GADNativeAdImage. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// Small logo image. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)logo; + +/// Text that encourages user to take some action with the ad. +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +- (NSString *GAD_NULLABLE_TYPE)advertiser; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMobileAds.h new file mode 100755 index 000000000..5c7abfbef --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADMobileAds.h @@ -0,0 +1,55 @@ +// +// GADMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Google Mobile Ads SDK settings. +@interface GADMobileAds : NSObject + +/// Returns the shared GADMobileAds instance. ++ (GADMobileAds *)sharedInstance; + +/// Configures the SDK using the settings associated with the given application ID. ++ (void)configureWithApplicationID:(NSString *)applicationID; + +/// Disables automated in app purchase (IAP) reporting. Must be called before any IAP transaction is +/// initiated. IAP reporting is used to track IAP ad conversions. Do not disable reporting if you +/// use IAP ads. ++ (void)disableAutomatedInAppPurchaseReporting; + +/// Disables automated SDK crash reporting. If not called, the SDK records the original exception +/// handler if available and registers a new exception handler. The new exception handler only +/// reports SDK related exceptions and calls the recorded original exception handler. ++ (void)disableSDKCrashReporting; + +/// The application's audio volume. Affects audio volumes of all ads relative to other audio output. +/// Valid ad volume values range from 0.0 (silent) to 1.0 (current device volume). Use this method +/// only if your application has its own volume controls (e.g., custom music or sound effect +/// volumes). Defaults to 1.0. +@property(nonatomic, assign) float applicationVolume; + +/// Indicates if the application's audio is muted. Affects initial mute state for all ads. Use this +/// method only if your application has its own volume controls (e.g., custom music or sound effect +/// muting). Defaults to NO. +@property(nonatomic, assign) BOOL applicationMuted; + +/// Returns YES if the current SDK version is at least |major|.|minor|.|patch|. This method can be +/// used by libraries that depend on a specific minimum version of the Google Mobile Ads SDK to warn +/// developers if they have an incompatible version. +/// +/// Available in Google Mobile Ads SDK 7.10 and onwards. Before calling this method check if the +/// GADMobileAds's shared instance responds to this method. Calling this method on a Google Mobile +/// Ads SDK lower than 7.10 can crash the app. +- (BOOL)isSDKVersionAtLeastMajor:(NSInteger)major minor:(NSInteger)minor patch:(NSInteger)patch; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAd.h new file mode 100755 index 000000000..c454404f3 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAd.h @@ -0,0 +1,36 @@ +// +// GADNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADNativeAdDelegate; + +/// Native ad base class. All native ad types are subclasses of this class. +@interface GADNativeAd : NSObject + +/// Optional delegate to receive state change notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Root view controller for handling ad actions. +@property(nonatomic, weak, GAD_NULLABLE) UIViewController *rootViewController; + +/// Dictionary of assets which aren't processed by the receiver. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *extraAssets; + +/// The ad network class name that fetched the current ad. For both standard and mediated Google +/// AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdDelegate.h new file mode 100755 index 000000000..e1b3ba3e0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdDelegate.h @@ -0,0 +1,57 @@ +// +// GADNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// Identifies native ad assets. +@protocol GADNativeAdDelegate + +@optional + +#pragma mark Ad Lifecycle Events + +/// Called when an impression is recorded for an ad. Only called for Google ads and is not supported +/// for mediation ads. +- (void)nativeAdDidRecordImpression:(GADNativeAd *)nativeAd; + +/// Called when a click is recorded for an ad. Only called for Google ads and is not supported for +/// mediation ads. +- (void)nativeAdDidRecordClick:(GADNativeAd *)nativeAd; + +#pragma mark Click-Time Lifecycle Notifications + +/// Called just before presenting the user a full screen view, such as a browser, in response to +/// clicking on an ad. Use this opportunity to stop animations, time sensitive interactions, etc. +/// +/// Normally the user looks at the ad, dismisses it, and control returns to your application with +/// the nativeAdDidDismissScreen: message. However, if the user hits the Home button or clicks on an +/// App Store link, your application will end. The next method called will be the +/// applicationWillResignActive: of your UIApplicationDelegate object.Immediately after that, +/// nativeAdWillLeaveApplication: is called. +- (void)nativeAdWillPresentScreen:(GADNativeAd *)nativeAd; + +/// Called just before dismissing a full screen view. +- (void)nativeAdWillDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just after dismissing a full screen view. Use this opportunity to restart anything you +/// may have stopped as part of nativeAdWillPresentScreen:. +- (void)nativeAdDidDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just before the application will go to the background or terminate due to an ad action +/// that will launch another application (such as the App Store). The normal UIApplicationDelegate +/// methods, like applicationDidEnterBackground:, will be called immediately before this. +- (void)nativeAdWillLeaveApplication:(GADNativeAd *)nativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage+Mediation.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage+Mediation.h new file mode 100755 index 000000000..971b71467 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage+Mediation.h @@ -0,0 +1,24 @@ +// +// GADNativeAdImage+Mediation.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides additional GADNativeAdImage initializers. +@interface GADNativeAdImage (MediationAdditions) + +/// Initializes and returns a native ad image object with the provided image. +- (instancetype)initWithImage:(UIImage *)image; + +/// Initializes and returns a native ad image object with the provided image URL and image scale. +- (instancetype)initWithURL:(NSURL *)URL scale:(CGFloat)scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage.h new file mode 100755 index 000000000..df4b48684 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImage.h @@ -0,0 +1,29 @@ +// +// GADNativeAdImage.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image. +@interface GADNativeAdImage : NSObject + +/// The image. If image autoloading is disabled, this property will be nil. +@property(nonatomic, readonly, strong, GAD_NULLABLE) UIImage *image; + +/// The image's URL. +@property(nonatomic, readonly, copy) NSURL *imageURL; + +/// The image's scale. +@property(nonatomic, readonly, assign) CGFloat scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImageAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImageAdLoaderOptions.h new file mode 100755 index 000000000..c2c9ea19c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdImageAdLoaderOptions.h @@ -0,0 +1,37 @@ +// +// GADNativeAdImageAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image orientation preference. +typedef NS_ENUM(NSInteger, GADNativeAdImageAdLoaderOptionsOrientation) { + GADNativeAdImageAdLoaderOptionsOrientationAny, ///< No orientation preference. + GADNativeAdImageAdLoaderOptionsOrientationPortrait, ///< Prefer portrait images. + GADNativeAdImageAdLoaderOptionsOrientationLandscape ///< Prefer landscape images. +}; + +/// Ad loader options for native ad image settings. +@interface GADNativeAdImageAdLoaderOptions : GADAdLoaderOptions + +/// Indicates if image asset content should be loaded by the SDK. If set to YES, the SDK will not +/// load image asset content and native ad image URLs can be used to fetch content. Defaults to NO, +/// image assets are loaded by the SDK. +@property(nonatomic, assign) BOOL disableImageLoading; + +/// Indicates if multiple images should be loaded for each asset. Defaults to NO. +@property(nonatomic, assign) BOOL shouldRequestMultipleImages; + +/// Indicates preferred image orientation. Defaults to +/// GADNativeAdImageAdLoaderOptionsOrientationAny. +@property(nonatomic, assign) GADNativeAdImageAdLoaderOptionsOrientation preferredImageOrientation; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdViewAdOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdViewAdOptions.h new file mode 100755 index 000000000..cd22062c1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAdViewAdOptions.h @@ -0,0 +1,29 @@ +// +// GADNativeAdViewAdOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Position of the AdChoices icon in the containing ad. +typedef NS_ENUM(NSInteger, GADAdChoicesPosition) { + GADAdChoicesPositionTopRightCorner, ///< Top right corner. + GADAdChoicesPositionTopLeftCorner, ///< Top left corner. + GADAdChoicesPositionBottomRightCorner, ///< Bottom right corner. + GADAdChoicesPositionBottomLeftCorner ///< Bottom Left Corner. +}; + +/// Ad loader options for configuring the view of native ads. +@interface GADNativeAdViewAdOptions : GADAdLoaderOptions + +/// Indicates preferred location of AdChoices icon. Default is GADAdChoicesPositionTopRightCorner. +@property(nonatomic, assign) GADAdChoicesPosition preferredAdChoicesPosition; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAppInstallAd.h new file mode 100755 index 000000000..1f442c3fc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeAppInstallAd.h @@ -0,0 +1,97 @@ +// +// GADNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native app install ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeAppInstall (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeAppInstallAdRequestDelegate protocol. +@interface GADNativeAppInstallAd : GADNativeAd + +#pragma mark - Must be displayed + +/// App title. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Text that encourages user to take some action with the ad. For example "Install". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Application icon. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *icon; + +#pragma mark - Recommended to display + +/// App description. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; +/// The app store name. For example, "App Store". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *store; +/// String representation of the app's price. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *price; +/// Array of GADNativeAdImage objects related to the advertised application. +@property(nonatomic, readonly, strong, GAD_NULLABLE) NSArray *images; +/// App store rating (0 to 5). +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDecimalNumber *starRating; +/// Video controller for controlling video playback in GADNativeAppInstallAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeAppInstallAd +/// ads. +@protocol GADNativeAppInstallAdLoaderDelegate +/// Called when a native app install ad is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeAppInstallAd:(GADNativeAppInstallAd *)nativeAppInstallAd; +@end + +#pragma mark - Native App Install Ad View + +/// Base class for app install ad views. Your app install ad view must be a subclass of this class +/// and must call superclass methods for all overriden methods. +@interface GADNativeAppInstallAdView : UIView + +/// This property must point to the native app install ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeAppInstallAd *nativeAppInstallAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's icon asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *iconView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's store asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *storeView; +/// Weak reference to your ad view's price asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *priceView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's star rating asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *starRatingView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeAppInstallAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeContentAd.h new file mode 100755 index 000000000..fcb87cd65 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeContentAd.h @@ -0,0 +1,89 @@ +// +// GADNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Native Content Ad Assets + +/// Native content ad. To request this ad type, you need to pass kGADAdLoaderAdTypeNativeContent +/// (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in GADAdLoader's initializer method. If +/// you request this ad type, your delegate must conform to the GADNativeContentAdRequestDelegate +/// protocol. +@interface GADNativeContentAd : GADNativeAd + +#pragma mark - Must be displayed + +/// Primary text headline. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Secondary text. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; + +#pragma mark - Recommended to display + +/// Large images. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *images; +/// Small logo image. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *logo; +/// Text that encourages user to take some action with the ad. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *advertiser; +/// Video controller for controlling video playback in GADNativeContentAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeContentAd ads. +@protocol GADNativeContentAdLoaderDelegate +/// Called when native content is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeContentAd:(GADNativeContentAd *)nativeContentAd; +@end + +#pragma mark - Native Content Ad View + +/// Base class for content ad views. Your content ad view must be a subclass of this class and must +/// call superclass methods for all overriden methods. +@interface GADNativeContentAdView : UIView + +/// This property must point to the native content ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeContentAd *nativeContentAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's logo asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *logoView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's advertiser asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *advertiserView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeContentAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeCustomTemplateAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeCustomTemplateAd.h new file mode 100755 index 000000000..fef98aca9 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeCustomTemplateAd.h @@ -0,0 +1,74 @@ +// +// GADNativeCustomTemplateAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native custom template ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeCustomTemplate (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeCustomTemplateAdLoaderDelegate protocol. +@interface GADNativeCustomTemplateAd : GADNativeAd + +/// The ad's custom template ID. +@property(nonatomic, readonly) NSString *templateID; + +/// Array of available asset keys. +@property(nonatomic, readonly) NSArray *availableAssetKeys; + +/// Returns video controller for controlling receiver's video. +@property(nonatomic, readonly, strong) GADVideoController *videoController; + +/// Returns media view for rendering video loaded by the receiver. Returns nil if receiver doesn't +/// has a video. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADMediaView *mediaView; + +/// Returns the native ad image corresponding to the specified key or nil if the image is not +/// available. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)imageForKey:(NSString *)key; + +/// Returns the string corresponding to the specified key or nil if the string is not available. +- (NSString *GAD_NULLABLE_TYPE)stringForKey:(NSString *)key; + +/// Call when the user clicks on the ad. Provide the asset key that best matches the asset the user +/// interacted with. Provide |customClickHandler| only if this template is configured with a custom +/// click action, otherwise pass in nil. If a block is provided, the ad's built-in click actions are +/// ignored and |customClickHandler| is executed after recording the click. +- (void)performClickOnAssetWithKey:(NSString *)assetKey + customClickHandler:(dispatch_block_t GAD_NULLABLE_TYPE)customClickHandler; + +/// Call when the ad is displayed on screen to the user. Can be called multiple times. Only the +/// first impression is recorded. +- (void)recordImpression; + +@end + +#pragma mark - Loading Protocol + +/// The delegate of a GADAdLoader object implements this protocol to receive +/// GADNativeCustomTemplateAd ads. +@protocol GADNativeCustomTemplateAdLoaderDelegate + +/// Called when requesting an ad. Asks the delegate for an array of custom template ID strings. +- (NSArray *)nativeCustomTemplateIDsForAdLoader:(GADAdLoader *)adLoader; + +/// Tells the delegate that a native custom template ad was received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeCustomTemplateAd:(GADNativeCustomTemplateAd *)nativeCustomTemplateAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdView.h new file mode 100755 index 000000000..2eeb67c9b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdView.h @@ -0,0 +1,96 @@ +// +// GADNativeExpressAdView.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays native ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADNativeExpressAdView *adView =
+///       [[GADNativeExpressAdView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADNativeExpressAdView : UIView + +#pragma mark - Initialization + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at +/// |origin| relative to its superview bounds. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at the top +/// left of its superview. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize; + +/// Video controller for controlling video rendered by this native express ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +#pragma mark - Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example, the root view controller in +/// a tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this native ad view to a proper size. Never create your own GADAdSize directly. +/// Use one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If you are not using mediation, changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If you are using +/// mediation, then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this +/// GADNativeExpressAdView. Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark - Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark - Mediation + +/// The name of the ad network adapter class that fetched the current ad. Returns nil while the +/// latest ad request is in progress or if the latest ad request failed. For both standard and +/// mediated Google AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via +/// mediation custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, weak, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdViewDelegate.h new file mode 100755 index 000000000..73bd5e0bb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADNativeExpressAdViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADNativeExpressAdViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeExpressAdView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADNativeExpressAdView state change messages such as ad request +/// status and ad click lifecycle. +@protocol GADNativeExpressAdViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that the native express ad view successfully received an ad. The delegate may +/// want to add the native express ad view to the view hierarchy if it hasn't been added yet. +- (void)nativeExpressAdViewDidReceiveAd:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)nativeExpressAdView:(GADNativeExpressAdView *)nativeExpressAdView + didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)nativeExpressAdViewWillPresentScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)nativeExpressAdViewWillDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)nativeExpressAdViewDidDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)nativeExpressAdViewWillLeaveApplication:(GADNativeExpressAdView *)nativeExpressAdView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequest.h new file mode 100755 index 000000000..422ba55ae --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequest.h @@ -0,0 +1,127 @@ +// +// GADRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kGADSimulatorID; + +/// Genders to help deliver more relevant ads. +typedef NS_ENUM(NSInteger, GADGender) { + kGADGenderUnknown, ///< Unknown gender. + kGADGenderMale, ///< Male gender. + kGADGenderFemale ///< Female gender. +}; + +/// Specifies optional parameters for ad requests. +@interface GADRequest : NSObject + +/// Returns a default request. ++ (instancetype)request; + +#pragma mark Additional Parameters For Ad Networks + +/// Ad networks may have additional parameters they accept. To pass these parameters to them, create +/// the ad network extras object for that network, fill in the parameters, and register it here. The +/// ad network should have a header defining the interface for the 'extras' object to create. All +/// networks will have access to the basic settings you've set in this GADRequest (gender, birthday, +/// testing mode, etc.). If you register an extras object that is the same class as one you have +/// registered before, the previous extras will be overwritten. +- (void)registerAdNetworkExtras:(id)extras; + +/// Returns the network extras defined for an ad network. +- (id GAD_NULLABLE_TYPE)adNetworkExtrasFor:(Class)aClass; + +/// Removes the extras for an ad network. |aClass| is the class which represents that network's +/// extras type. +- (void)removeAdNetworkExtrasFor:(Class)aClass; + +#pragma mark Collecting SDK Information + +/// Returns the version of the SDK. ++ (NSString *)sdkVersion; + +#pragma mark Testing + +/// Test ads will be returned for devices with device IDs specified in this array. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *testDevices; + +#pragma mark User Information + +/// Provide the user's gender to increase ad relevancy. +@property(nonatomic, assign) GADGender gender; + +/// Provide the user's birthday to increase ad relevancy. +@property(nonatomic, copy, GAD_NULLABLE) NSDate *birthday; + +/// The user's current location may be used to deliver more relevant ads. However do not use Core +/// Location just for advertising, make sure it is used for more beneficial reasons as well. It is +/// both a good idea and part of Apple's guidelines. +- (void)setLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + accuracy:(CGFloat)accuracyInMeters; + +/// [Optional] This method allows you to specify whether you would like your app to be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA), +/// http:///business.ftc.gov/privacy-and-security/childrens-privacy. +/// +/// If you call this method with YES, you are indicating that your app should be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA). If you call +/// this method with NO, you are indicating that your app should not be treated as child-directed +/// for purposes of the Children’s Online Privacy Protection Act (COPPA). If you do not call this +/// method, ad requests will include no indication of how you would like your app treated with +/// respect to COPPA. +/// +/// By setting this method, you certify that this notification is accurate and you are authorized to +/// act on behalf of the owner of the app. You understand that abuse of this setting may result in +/// termination of your Google account. +/// +/// It may take some time for this designation to be fully implemented in applicable Google +/// services. This designation will only apply to ad requests for which you have set this method. +- (void)tagForChildDirectedTreatment:(BOOL)childDirectedTreatment; + +#pragma mark Contextual Information + +/// Array of keyword strings. Keywords are words or phrases describing the current user activity +/// such as @"Sports Scores" or @"Football". Set this property to nil to clear the keywords. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *keywords; + +/// URL string for a webpage whose content matches the app content. This webpage content is used for +/// targeting purposes. +@property(nonatomic, copy, GAD_NULLABLE) NSString *contentURL; + +#pragma mark Request Agent Information + +/// String that identifies the ad request's origin. Third party libraries that reference the Mobile +/// Ads SDK should set this property to denote the platform from which the ad request originated. +/// For example, a third party ad network called "CoolAds network" that is mediating requests to the +/// Mobile Ads SDK should set this property as "CoolAds". +@property(nonatomic, copy, GAD_NULLABLE) NSString *requestAgent; + +#pragma mark Deprecated Methods + +/// Provide the user's birthday to increase ad relevancy. +- (void)setBirthdayWithMonth:(NSInteger)month + day:(NSInteger)day + year:(NSInteger)year + GAD_DEPRECATED_MSG_ATTRIBUTE(" use the birthday property."); + +/// When Core Location isn't available but the user's location is known supplying it here may +/// deliver more relevant ads. It can be any free-form text such as @"Champs-Elysees Paris" or +/// @"94041 US". +- (void)setLocationWithDescription:(NSString *GAD_NULLABLE_TYPE)locationDescription + GAD_DEPRECATED_MSG_ATTRIBUTE(" use setLocationWithLatitude:longitude:accuracy:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequestError.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequestError.h new file mode 100755 index 000000000..b38dcbe89 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRequestError.h @@ -0,0 +1,70 @@ +// +// GADRequestError.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADRequest; + +GAD_ASSUME_NONNULL_BEGIN + +/// Google AdMob Ads error domain. +GAD_EXTERN NSString *const kGADErrorDomain; + +/// NSError codes for GAD error domain. +typedef NS_ENUM(NSInteger, GADErrorCode) { + /// The ad request is invalid. The localizedFailureReason error description will have more + /// details. Typically this is because the ad did not have the ad unit ID or root view + /// controller set. + kGADErrorInvalidRequest, + + /// The ad request was successful, but no ad was returned. + kGADErrorNoFill, + + /// There was an error loading data from the network. + kGADErrorNetworkError, + + /// The ad server experienced a failure processing the request. + kGADErrorServerError, + + /// The current device's OS is below the minimum required version. + kGADErrorOSVersionTooLow, + + /// The request was unable to be loaded before being timed out. + kGADErrorTimeout, + + /// Will not send request because the interstitial object has already been used. + kGADErrorInterstitialAlreadyUsed, + + /// The mediation response was invalid. + kGADErrorMediationDataError, + + /// Error finding or creating a mediation ad network adapter. + kGADErrorMediationAdapterError, + + /// The mediation request was successful, but no ad was returned from any ad networks. + kGADErrorMediationNoFill, + + /// Attempting to pass an invalid ad size to an adapter. + kGADErrorMediationInvalidAdSize, + + /// Internal error. + kGADErrorInternalError, + + /// Invalid argument error. + kGADErrorInvalidArgument, + + /// Received invalid response. + kGADErrorReceivedInvalidResponse +}; + +/// Represents the error generated due to invalid request parameters. +@interface GADRequestError : NSError +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAd.h new file mode 100755 index 000000000..806f80bec --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAd.h @@ -0,0 +1,47 @@ +// +// GADRewardBasedVideoAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +@protocol GADRewardBasedVideoAdDelegate; + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADRewardBasedVideoAd class is used for requesting and presenting a reward based video ad. +/// This class isn't thread safe. +@interface GADRewardBasedVideoAd : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Indicates if the receiver is ready to be presented full screen. +@property(nonatomic, readonly, getter=isReady) BOOL ready; + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns the mediated custom event adapter. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Returns the shared GADRewardBasedVideoAd instance. ++ (GADRewardBasedVideoAd *)sharedInstance; + +/// Initiates the request to fetch the reward based video ad. The |request| object supplies ad +/// targeting information and must not be nil. The adUnitID is the ad unit id used for fetching an +/// ad and must not be nil. +- (void)loadRequest:(GADRequest *)request withAdUnitID:(NSString *)adUnitID; + +/// Presents the reward based video ad with the provided view controller. +- (void)presentFromRootViewController:(UIViewController *)viewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAdDelegate.h new file mode 100755 index 000000000..f81dd5922 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADRewardBasedVideoAdDelegate.h @@ -0,0 +1,49 @@ +// +// GADRewardBasedVideoAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADRewardBasedVideoAd such as ad requests +/// succeeding/failing. +@protocol GADRewardBasedVideoAdDelegate + +@required + +/// Tells the delegate that the reward based video ad has rewarded the user. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +@optional + +/// Tells the delegate that the reward based video ad failed to load. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didFailToLoadWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was received. +- (void)rewardBasedVideoAdDidReceiveAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad opened. +- (void)rewardBasedVideoAdDidOpen:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad started playing. +- (void)rewardBasedVideoAdDidStartPlaying:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad closed. +- (void)rewardBasedVideoAdDidClose:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad will leave the application. +- (void)rewardBasedVideoAdWillLeaveApplication:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchBannerView.h new file mode 100755 index 000000000..590b2770e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchBannerView.h @@ -0,0 +1,27 @@ +// +// GADSearchBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A view that displays search ads. +/// To show search ads: +/// 1) Create a GADSearchBannerView and add it to your view controller's view hierarchy. +/// 2) Create a GADSearchRequest ad request object to hold the search query and other search data. +/// 3) Call GADSearchBannerView's -loadRequest: method with the GADSearchRequest object. +@interface GADSearchBannerView : GADBannerView + +/// If the banner view is initialized with kGADAdSizeFluid and the corresponding request is created +/// with dynamic height parameters, this delegate will be called when the ad size changes. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchRequest.h new file mode 100755 index 000000000..34fb68bd0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADSearchRequest.h @@ -0,0 +1,77 @@ +// +// GADSearchRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Search ad border types. +typedef NS_ENUM(NSUInteger, GADSearchBorderType) { + kGADSearchBorderTypeNone, ///< No border. + kGADSearchBorderTypeDashed, ///< Dashed line border. + kGADSearchBorderTypeDotted, ///< Dotted line border. + kGADSearchBorderTypeSolid ///< Solid line border. +}; + +/// Search ad call button color types. +typedef NS_ENUM(NSUInteger, GADSearchCallButtonColor) { + kGADSearchCallButtonLight, ///< Light button color. + kGADSearchCallButtonMedium, ///< Medium button color. + kGADSearchCallButtonDark ///< Dark button color. +}; + +/// Specifies parameters for search ads. +@interface GADSearchRequest : GADRequest + +/// The search ad query. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; +/// The search ad background color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *backgroundColor; +/// The search ad gradient "from" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientFrom; +/// The search ad gradient "to" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientTo; +/// The search ad header color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *headerColor; +/// The search ad description text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *descriptionTextColor; +/// The search ad anchor text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *anchorTextColor; +/// The search ad text font family. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; +/// The search ad header text size. +@property(nonatomic, assign) NSUInteger headerTextSize; +/// The search ad border color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *borderColor; +/// The search ad border type. +@property(nonatomic, assign) GADSearchBorderType borderType; +/// The search ad border thickness. +@property(nonatomic, assign) NSUInteger borderThickness; +/// The search ad custom channels. +@property(nonatomic, copy, GAD_NULLABLE) NSString *customChannels; +/// The search ad call button color. +@property(nonatomic, assign) GADSearchCallButtonColor callButtonColor; + +/// A solid background color for rendering the ad. The background of the ad +/// can either be a solid color, or a gradient, which can be specified through +/// setBackgroundGradientFrom:toColor: method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundSolid:(UIColor *)color; + +/// A linear gradient background color for rendering the ad. The background of +/// the ad can either be a linear gradient, or a solid color, which can be +/// specified through setBackgroundSolid method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundGradientFrom:(UIColor *)from toColor:(UIColor *)toColor; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoController.h new file mode 100755 index 000000000..a3d3e66cc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoController.h @@ -0,0 +1,35 @@ +// +// GADVideoController.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADVideoControllerDelegate; + +/// The video controller class provides a way to get the video metadata and also manages video +/// content of the ad rendered by the Google Mobile Ads SDK. You don't need to create an instance of +/// this class. When the ad rendered by the Google Mobile Ads SDK loads video content, you may be +/// able to get an instance of this class from the rendered ad object. Currently only native express +/// ad view class exposes video controller. +@interface GADVideoController : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Returns a Boolean indicating if the receiver has video content. +- (BOOL)hasVideoContent; + +/// Returns the video's aspect ratio (width/height) or 0 if no video is present. +- (double)aspectRatio; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoControllerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoControllerDelegate.h new file mode 100755 index 000000000..cd5c0487e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoControllerDelegate.h @@ -0,0 +1,25 @@ +// +// GADVideoControllerDelegate.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADVideoControllerDelegate protocol defines methods that are called by the video controller +/// object in response to the video events that occured throught the lifetime of the video rendered +/// by an ad. +@protocol GADVideoControllerDelegate + +@optional + +/// Tells the delegate that the video controller's video playback has ended. +- (void)videoControllerDidEndVideoPlayback:(GADVideoController *)videoController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoOptions.h new file mode 100755 index 000000000..2f75a37d7 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GADVideoOptions.h @@ -0,0 +1,21 @@ +// +// GADVideoOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Video ad options. +@interface GADVideoOptions : GADAdLoaderOptions + +/// Indicates if videos should start muted. +@property(nonatomic, assign) BOOL startMuted; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAds.h new file mode 100755 index 000000000..7c0df6121 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAds.h @@ -0,0 +1,96 @@ +// +// GoogleMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. + +#import +#import + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0 +#error The Google Mobile Ads SDK requires a deployment target of iOS 6.0 or later. +#endif + +/// Project version string for GoogleMobileAds. +FOUNDATION_EXPORT const unsigned char GoogleMobileAdsVersionString[]; + +// Header files. +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAdsDefines.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAdsDefines.h new file mode 100755 index 000000000..229ffd898 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/GoogleMobileAdsDefines.h @@ -0,0 +1,56 @@ +// +// GoogleMobileAdsDefines.h +// Google Mobile Ads SDK +// +// Copyright (c) 2015 Google Inc. All rights reserved. +// + +#import + +#if defined(__cplusplus) +#define GAD_EXTERN extern "C" __attribute__((visibility("default"))) +#else +#define GAD_EXTERN extern __attribute__((visibility("default"))) +#endif // defined(__cplusplus) + +#if defined(__has_feature) && defined(__has_attribute) +#if __has_feature(attribute_GAD_DEPRECATED_with_message) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated(s))) +#elif __has_attribute(deprecated) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // __has_feature(attribute_GAD_DEPRECATED_with_message) +#if __has_attribute(deprecated) +#define GAD_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#endif // __has_attribute(deprecated) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // defined(__has_feature) && defined(__has_attribute) + +#ifndef IBInspectable +#define IBInspectable +#endif + +#if __has_feature(nullability) // Available starting in Xcode 6.3. +#define GAD_NULLABLE_TYPE __nullable +#define GAD_NONNULL_TYPE __nonnull +#define GAD_NULLABLE nullable +#define GAD_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +#else +#define GAD_NULLABLE_TYPE +#define GAD_NONNULL_TYPE +#define GAD_NULLABLE +#define GAD_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END +#endif // __has_feature(nullability) + +#if __has_attribute(objc_boxable) // Available starting in Xcode 7.3. +#define GAD_BOXABLE __attribute__((objc_boxable)) +#else +#define GAD_BOXABLE +#endif // __has_attribute(objc_boxable) diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..f5ee207cb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkAdapterProtocol.h @@ -0,0 +1,104 @@ +// +// GADMAdNetworkAdapterProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +#import "GADMAdNetworkConnectorProtocol.h" +#import "GADMEnums.h" + +/// Subclasses should prefix their name with "GADMAdapter" example: GADMAdapterGoogleAdMobAds +#define kGADMAdapterClassNamePrefix @"GADMAdapter" + +@protocol GADMAdNetworkConnector; + +/// Ad network adapter protocol. +@protocol GADMAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Designated initializer. Implementing classes can and should keep the connector in an instance +/// variable. However you must never retain the connector, as doing so will create a circular +/// reference and cause memory leaks. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector; + +/// Asks the adapter to initiate a banner ad request. The adapter does not need to return anything. +/// The assumption is that the adapter will start an asynchronous ad fetch over the network. Your +/// adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does not support +/// the given ad size, or does not support banner ads, call back to the adapter:didFailAd: method of +/// the connector. +- (void)getBannerWithSize:(GADAdSize)adSize; + +/// Asks the adapter to initiate an interstitial ad request. The adapter does not need to return +/// anything. The assumption is that the adapter will start an asynchronous ad fetch over the +/// network. Your adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does +/// not support interstitials, call back to the adapter:didFailInterstitial: method of the +/// connector. +- (void)getInterstitial; + +/// When called, the adapter must remove itself as a delegate or notification observer from the +/// underlying ad network SDK. You should also call this method in your adapter dealloc, so when +/// your adapter goes away, your SDK will not call a freed object. This function should be +/// idempotent and should not crash regardless of when or how many times the method is called. +- (void)stopBeingDelegate; + +/// Some ad transition types may cause issues with particular Ad SDKs. The adapter may decide +/// whether the given animation type is OK. Defaults to YES. +- (BOOL)isBannerAnimationOK:(GADMBannerAnimationType)animType; + +/// Present an interstitial using the supplied UIViewController, by calling +/// presentViewController:animated:completion:. +/// +/// Your interstitial should not immediately present itself when it is received. Instead, you should +/// wait until this method is called on your adapter to present the interstitial. +/// +/// Make sure to call adapterWillPresentInterstitial: on the connector when the interstitial is +/// about to be presented, and adapterWillDismissInterstitial: and adapterDidDismissInterstitial: +/// when the interstitial is being dismissed. +- (void)presentInterstitialFromRootViewController:(UIViewController *)rootViewController; + +@optional + +/// Starts request for a native ad. |adTypes| contains the list of native ad types requested. See +/// GADAdLoaderAdTypes.h for available ad types. |options| are any additional options configured by +/// the publisher for requesting a native ad. See GADNativeAdImageAdLoaderOptions.h for available +/// image options. When this method is called the receiver may start native ad request +/// asynchronously. On completion the receiver should notify the Google Mobile Ads SDK with a native +/// ad object using the receiver's connector method +/// adapter:didReceiveNativeAdDataSource:mediationDelegate or adapter:didFailAd: if the ad request +/// encountered an error. +- (void)getNativeAdWithAdTypes:(NSArray *)adTypes options:(NSArray *)options; + +/// Indicates if the adapter handles user clicks. If this method returns YES, the adapter must +/// handle user clicks and notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. If this method returns +/// NO, the Google Mobile Ads SDK handles user clicks and notifies the adapter of clicks using +/// -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the adapter handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the adapter must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the adapter of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// If your ad network handles multiple ad sizes for the same banner ad, implement this method to +/// know when the user changes the banner size. This is typically changing from +/// kGADAdSizeSmartBannerPortrait to kGADAdSizeSmartBannerLandscape, or vice versa. If this method +/// is not implemented, every time the user changes the ad size, a new ad will be requested with the +/// new size by calling your getBannerWithSize: method. +- (void)changeAdSizeTo:(GADAdSize)adSize; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..075ca3cea --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMAdNetworkConnectorProtocol.h @@ -0,0 +1,87 @@ +// +// GADMAdNetworkConnectorProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import +#import + +#import "GADMediationAdRequest.h" + +@protocol GADMAdNetworkAdapter; + +/// Ad network adapters interact with the mediation SDK using an object that implements the +/// GADMAdNetworkConnector protocol. The connector object can be used to obtain necessary +/// information for ad requests, and to call back to the mediation SDK on ad request returns and +/// user interactions. +@protocol GADMAdNetworkConnector + +/// When you need to show a landing page or any other modal view, such as when a user clicks or when +/// your Ads SDK needs to show an interstitial, use this method to obtain a UIViewController that +/// you can use to show your modal view. Call the -presentViewController:animated:completion: method +/// of the returned UIViewController . +- (UIViewController *)viewControllerForPresentingModalView; + +#pragma mark - Adapter Callbacks + +/// Tells the connector that the adapter failed to receive an ad. +- (void)adapter:(id)adapter didFailAd:(NSError *)error; + +/// Tells the connector that the adapter received a banner ad. +- (void)adapter:(id)adapter didReceiveAdView:(UIView *)view; + +/// Tells the connector that the adapter received an interstitial. +- (void)adapterDidReceiveInterstitial:(id)adapter; + +/// Tells the connector that the adapter has received a mediated native ad. |mediatedNativeAd| is +/// used by the Google Mobile Ads SDK for constructing a native ad object. +- (void)adapter:(id)adapter + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +#pragma mark Ad events + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner or +// interstitial ad. + +/// Tells the connector that the adapter recorded a user click. +- (void)adapterDidGetAdClick:(id)adapter; +/// Tells the connector that the adapter will leave the application because of a user action. +- (void)adapterWillLeaveApplication:(id)adapter; + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner ad. + +/// Tells the connector that the adapter will present a full screen modal. +- (void)adapterWillPresentFullScreenModal:(id)adapter; +/// Tells the connector that the adapter will dismiss a full screen modal. +- (void)adapterWillDismissFullScreenModal:(id)adapter; +/// Tells the connector that the adapter dismissed a full screen modal. +- (void)adapterDidDismissFullScreenModal:(id)adapter; + +// Adapter should call these methods during the lifecycle of the loaded interstitial ad. + +/// Tells the connector that the adapter will present an interstitial. +- (void)adapterWillPresentInterstitial:(id)adapter; +/// Tells the connector that the adapter will dismiss an interstitial. +- (void)adapterWillDismissInterstitial:(id)adapter; +/// Tells the connector that the adapter did dismiss an interstitial. +- (void)adapterDidDismissInterstitial:(id)adapter; + +#pragma mark Deprecated + +/// Deprecated. Use -adapterDidReceiveInterstitial:. +- (void)adapter:(id)adapter + didReceiveInterstitial:(NSObject *)interstitial + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidReceiveInterstitial:."); + +/// Deprecated. Use -adapterDidGetAdClick:. +- (void)adapter:(id)adapter + clickDidOccurInBanner:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidGetAdClick:."); + +/// Deprecated. Use -adapter:didFailAd:. +- (void)adapter:(id)adapter + didFailInterstitial:(NSError *)error GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapter:didFailAd:"); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMEnums.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMEnums.h new file mode 100755 index 000000000..1802598c2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMEnums.h @@ -0,0 +1,21 @@ +// +// GADMEnums.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +/// These are the types of animation we employ for transitions between two mediated ads. +typedef NS_ENUM(NSInteger, GADMBannerAnimationType) { + kGADMBannerAnimationTypeNone = 0, ///< No animation. + kGADMBannerAnimationTypeFlipFromLeft = 1, ///< Flip from left. + kGADMBannerAnimationTypeFlipFromRight = 2, ///< Flip from right. + kGADMBannerAnimationTypeCurlUp = 3, ///< Curl up. + kGADMBannerAnimationTypeCurlDown = 4, ///< Curl down. + kGADMBannerAnimationTypeSlideFromLeft = 5, ///< Slide from left. + kGADMBannerAnimationTypeSlideFromRight = 6, ///< Slide from right. + kGADMBannerAnimationTypeFadeIn = 7, ///< Fade in. + kGADMBannerAnimationTypeRandom = 8, ///< Random animation. +}; diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..63eb5072e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h @@ -0,0 +1,59 @@ +// +// GADMRewardBasedVideoAdNetworkAdapter.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMRewardBasedVideoAdNetworkConnector; + +/// Your adapter must conform to this protocol to provide reward based video ads. +@protocol GADMRewardBasedVideoAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithRewardBasedVideoAdNetworkConnector: + (id)connector; + +/// Tells the adapter to set up reward based video ads. The adapter should notify the Google Mobile +/// Ads SDK whether set up has succeeded or failed using callbacks provided in the connector. When +/// set up fails, the Google Mobile Ads SDK may try to set up the adapter again. +- (void)setUp; + +/// Tells the adapter to request a reward based video ad. This method is called after the adapter +/// has been set up. The adapter should notify the Google Mobile Ads SDK if the request succeeds or +/// fails using callbacks provided in the connector. +- (void)requestRewardBasedVideoAd; + +/// Tells the adapter to present the reward based video ad with the provided view controller. This +/// method is only called after the adapter successfully requested an ad. +- (void)presentRewardBasedVideoAdWithRootViewController:(UIViewController *)viewController; + +/// Tells the adapter to remove itself as a delegate or notification observer from the underlying ad +/// network SDK. +- (void)stopBeingDelegate; + +@optional + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithRewardBasedVideoAdNetworkConnector:."); + +/// Tells the adapter to set up reward based video ads with the provided user ID. The adapter should +/// notify the Google Mobile Ads SDK whether set up has succeeded or failed using callbacks provided +/// in the connector. When set up fails, the Google Mobile Ads SDK may try to set up the adapter +/// again. +- (void)setUpWithUserID:(NSString *)userID GAD_DEPRECATED_MSG_ATTRIBUTE("Use setUp."); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..82b8d4520 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h @@ -0,0 +1,58 @@ +// +// GADMRewardBasedVideoAdNetworkConnector.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMediationAdRequest; +@protocol GADMRewardBasedVideoAdNetworkAdapter; + +/// Reward based video ad network adapters interact with the mediation SDK using an object that +/// conforms to the GADMRewardBasedVideoAdNetworkConnector protocol. The connector object can be +/// used to obtain information for ad requests and to call back to the mediation SDK on ad responses +/// and user interactions. +@protocol GADMRewardBasedVideoAdNetworkConnector + +/// Tells the delegate that the adapter successfully set up a reward based video ad. +- (void)adapterDidSetUpRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter failed to set up a reward based video ad. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToSetUpRewardBasedVideoAdWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was clicked. +- (void)adapterDidGetAdClick:(id)adapter; + +/// Tells the delegate that a reward based video ad has loaded. +- (void)adapterDidReceiveRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has opened. +- (void)adapterDidOpenRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has started playing. +- (void)adapterDidStartPlayingRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has closed. +- (void)adapterDidCloseRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter has rewarded the user. +- (void)adapter:(id)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +/// Tells the delegate that a reward based video ad's action will leave the application. +- (void)adapterWillLeaveApplication: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad failed to load. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToLoadRewardBasedVideoAdwithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMediationAdRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMediationAdRequest.h new file mode 100755 index 000000000..104ea5a2b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/A/Headers/Mediation/GADMediationAdRequest.h @@ -0,0 +1,56 @@ +// +// GADMediationAdRequest.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +/// Provides information which can be used for making ad requests during mediation. +@protocol GADMediationAdRequest + +/// Publisher ID set by the publisher on the AdMob frontend. +- (NSString *)publisherId; + +/// Mediation configurations set by the publisher on the AdMob frontend. +- (NSDictionary *)credentials; + +/// Returns YES if the publisher is requesting test ads. +- (BOOL)testMode; + +/// The adapter's ad network extras specified in GADRequest. +- (id)networkExtras; + +/// Returns the value of childDirectedTreatment supplied by the publisher. Returns nil if the +/// publisher hasn't specified child directed treatment. Returns @YES if child directed treatment is +/// enabled. +- (NSNumber *)childDirectedTreatment; + +/// The end user's gender set by the publisher in GADRequest. Returns kGADGenderUnknown if it has +/// not been specified. +- (GADGender)userGender; + +/// The end user's birthday set by the publisher. Returns nil if it has not been specified. +- (NSDate *)userBirthday; + +/// Returns YES if the publisher has specified latitude and longitude location. +- (BOOL)userHasLocation; + +/// Returns the user's latitude or 0 if location isn't specified. +- (CGFloat)userLatitude; + +/// Returns the user's longitude or 0 if location isn't specified. +- (CGFloat)userLongitude; + +/// Returns the user's location accuracy or 0 if location isn't specified. +- (CGFloat)userLocationAccuracyInMeters; + +/// Returns user's location description. May return a value even if userHasLocation is NO. +- (NSString *)userLocationDescription; + +/// Keywords describing the user's current activity. Example: @"Sport Scores". +- (NSArray *)userKeywords; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/GoogleMobileAds b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/GoogleMobileAds new file mode 100755 index 000000000..e5a9958b0 Binary files /dev/null and b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/GoogleMobileAds differ diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPBannerView.h new file mode 100755 index 000000000..95e0f7c0b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPBannerView.h @@ -0,0 +1,94 @@ +// +// DFPBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays DoubleClick For Publishers banner ads. +@interface DFPBannerView : GADBannerView + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and statistics. +/// +/// Example DFP ad unit ID: @"/6499/example/banner" +@property(nonatomic, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id appEventDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +/// Optional array of NSValue encoded GADAdSize structs, specifying all valid sizes that are +/// appropriate for this slot. Never create your own GADAdSize directly. Use one of the predefined +/// standard ad sizes (such as kGADAdSizeBanner), or create one using the GADAdSizeFromCGSize +/// method. +/// +/// Example: +/// +///
+///   NSArray *validSizes = @[
+///     NSValueFromGADAdSize(kGADAdSizeBanner),
+///     NSValueFromGADAdSize(kGADAdSizeLargeBanner)
+///   ];
+///
+///   bannerView.validAdSizes = validSizes;
+///   
+@property(nonatomic, copy, GAD_NULLABLE) NSArray *validAdSizes; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Indicates that the publisher will record impressions manually when the ad becomes visible to the +/// user. +@property(nonatomic, assign) BOOL enableManualImpressions; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id customRenderedBannerViewDelegate; + +/// Video controller for controlling video rendered by this ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +/// If you've set enableManualImpressions to YES, call this method when the ad is visible. +- (void)recordImpression; + +/// Use this function to resize the banner view without launching a new ad request. +- (void)resize:(GADAdSize)size; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark Deprecated + +/// Deprecated. Use the validAdSizes property. +/// Sets the receiver's valid ad sizes to the values pointed to by the provided NULL terminated list +/// of GADAdSize pointers. +/// +/// Example: +/// +///
+///   GADAdSize size1 = kGADAdSizeBanner;
+///   GADAdSize size2 = kGADAdSizeLargeBanner;
+///   [bannerView setValidAdSizesWithSizes:&size1, &size2, NULL];
+///   
+- (void)setValidAdSizesWithSizes:(GADAdSize *)firstSize, ... NS_REQUIRES_NIL_TERMINATION + GAD_DEPRECATED_MSG_ATTRIBUTE("Use validAdSizes property."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedAd.h new file mode 100755 index 000000000..5c2b0abb4 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedAd.h @@ -0,0 +1,34 @@ +// +// DFPCustomRenderedAd.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Custom rendered ad. Your application renders the ad. +@interface DFPCustomRenderedAd : NSObject + +/// The ad's HTML. +@property(nonatomic, readonly, copy) NSString *adHTML; + +/// The base URL of the ad's HTML. +@property(nonatomic, readonly, copy) NSURL *adBaseURL; + +/// Call this method when the user clicks the ad. +- (void)recordClick; + +/// Call this method when the ad is visible to the user. +- (void)recordImpression; + +/// Call this method after the ad has been rendered in a UIView object. +- (void)finishedRenderingAdView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedBannerViewDelegate.h new file mode 100755 index 000000000..e15b89ebd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedBannerViewDelegate.h @@ -0,0 +1,28 @@ +// +// DFPCustomRenderedBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPBannerView; +@class DFPCustomRenderedAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd banner view delegate protocol for notifying the delegate of changes to +/// custom rendered banners. +@protocol DFPCustomRenderedBannerViewDelegate + +/// Called after ad data has been received. You must construct a banner from |customRenderedAd| and +/// call the |customRenderedAd| object's finishedRenderingAdView: when the ad has been rendered. +- (void)bannerView:(DFPBannerView *)bannerView + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedInterstitialDelegate.h new file mode 100755 index 000000000..0f1f4a8a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPCustomRenderedInterstitialDelegate.h @@ -0,0 +1,29 @@ +// +// DFPCustomRenderedInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import + +@class DFPCustomRenderedAd; +@class DFPInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// The DFPCustomRenderedAd interstitial delegate protocol for notifying the delegate of changes to +/// custom rendered interstitials. +@protocol DFPCustomRenderedInterstitialDelegate + +/// Called after ad data has been received. You must construct an interstitial from +/// |customRenderedAd| and call the |customRenderedAd| object's finishedRenderingAdView: method when +/// the ad has been rendered. +- (void)interstitial:(DFPInterstitial *)interstitial + didReceiveCustomRenderedAd:(DFPCustomRenderedAd *)customRenderedAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPInterstitial.h new file mode 100755 index 000000000..e3af0d210 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPInterstitial.h @@ -0,0 +1,39 @@ +// +// DFPInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// DoubleClick For Publishers interstitial ad, a full-screen advertisement shown at natural +/// transition points in your application such as between game levels or news stories. +@interface DFPInterstitial : GADInterstitial + +/// Required value created on the DFP website. Create a new ad unit for every unique placement of an +/// ad in your application. Set this to the ID assigned for this placement. Ad units are important +/// for targeting and stats. +/// +/// Example DFP ad unit ID: @"/6499/example/interstitial" +@property(nonatomic, readonly, copy) NSString *adUnitID; + +/// Correlator object for correlating this object to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +/// Optional delegate that is notified when creatives send app events. +@property(nonatomic, weak, GAD_NULLABLE) id appEventDelegate; + +/// Optional delegate object for custom rendered ads. +@property(nonatomic, weak, GAD_NULLABLE) + id customRenderedInterstitialDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPRequest.h new file mode 100755 index 000000000..08f070f1b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/DFPRequest.h @@ -0,0 +1,37 @@ +// +// DFPRequest.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kDFPSimulatorID; + +/// Specifies optional parameters for ad requests. +@interface DFPRequest : GADRequest + +/// Publisher provided user ID. +@property(nonatomic, copy, GAD_NULLABLE) NSString *publisherProvidedID; + +/// Array of strings used to exclude specified categories in ad results. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *categoryExclusions; + +/// Key-value pairs used for custom targeting. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *customTargeting; + +/// This API is deprecated and a no-op, use an instance of GADCorrelator set on DFPInterstitial or +/// DFPBannerView objects to correlate requests. ++ (void)updateCorrelator GAD_DEPRECATED_MSG_ATTRIBUTE( + "Set GADCorrelator objects on your ads instead. This method no longer affects ad correlation."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdChoicesView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdChoicesView.h new file mode 100755 index 000000000..c05aeb537 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdChoicesView.h @@ -0,0 +1,23 @@ +// +// GADAdChoicesView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays AdChoices content. +/// +/// If a GADAdChoicesView is set on GADNativeAppInstallAdView or GADNativeContentAdView prior to +/// calling -setNativeAppInstallAd: or -setNativeContentAd:, AdChoices content will render inside +/// the GADAdChoicesView. By default, AdChoices is placed in the top right corner of +/// GADNativeAppInstallAdView and GADNativeContentAdView. +@interface GADAdChoicesView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdDelegate.h new file mode 100755 index 000000000..27cdda03d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdDelegate.h @@ -0,0 +1,28 @@ +// +// GADAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Audio Control Notifications + +/// Delegate methods common to multiple ad types. +@protocol GADAdDelegate + +@optional + +#pragma mark Audio Control Methods + +/// Asks the delegate if the audio session category can be changed while displaying an ad. Return NO +/// to prevent the Google Mobile Ads SDK from changing the audio session category. The default +/// behavior if unimplemented is to return YES. +- (BOOL)ad:(id)ad shouldChangeAudioSessionToCategory:(NSString *)audioSessionCategory; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoader.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoader.h new file mode 100755 index 000000000..44ee5c576 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoader.h @@ -0,0 +1,49 @@ +// +// GADAdLoader.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Loads ads. See GADAdLoaderAdTypes.h for available ad types. +@interface GADAdLoader : NSObject + +/// Object notified when an ad request succeeds or fails. Must conform to requested ad types' +/// delegate protocols. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// The ad loader's ad unit ID. +@property(nonatomic, readonly) NSString *adUnitID; + +/// Returns an initialized ad loader configured to load the specified ad types. +/// +/// @param rootViewController The root view controller is used to present ad click actions. +/// @param adTypes An array of ad types. See GADAdLoaderAdTypes.h for available ad types. +/// @param options An array of GADAdLoaderOptions objects to configure how ads are loaded, or nil to +/// use default options. See each ad type's header for available GADAdLoaderOptions subclasses. +- (instancetype)initWithAdUnitID:(NSString *)adUnitID + rootViewController:(UIViewController *GAD_NULLABLE_TYPE)rootViewController + adTypes:(NSArray *)adTypes + options:(NSArray *GAD_NULLABLE_TYPE)options; + +/// Loads the ad and informs the delegate of the outcome. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +@end + +/// Ad loader options base class. See each ad type's header for available GADAdLoaderOptions +/// subclasses. +@interface GADAdLoaderOptions : NSObject +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderAdTypes.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderAdTypes.h new file mode 100755 index 000000000..76d176236 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderAdTypes.h @@ -0,0 +1,31 @@ +// +// GADAdLoaderAdTypes.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use with GADAdLoader to request native app install ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeAppInstallAdRequestDelegate protocol. See GADNativeAppInstallAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeAppInstall; + +/// Use with GADAdLoader to request native content ads. To receive ads, the ad loader's delegate +/// must conform to the GADNativeContentAdRequestDelegate protocol. See GADNativeContentAd.h. +/// +/// See GADNativeAdImageAdLoaderOptions.h for ad loader image options. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeContent; + +/// Use with GADAdLoader to request native custom template ads. To receive ads, the ad loader's +/// delegate must conform to the GADNativeCustomTemplateAdLoaderDelegate protocol. See +/// GADNativeCustomTemplateAd.h. +GAD_EXTERN NSString *const kGADAdLoaderAdTypeNativeCustomTemplate; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderDelegate.h new file mode 100755 index 000000000..dec90b784 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdLoaderDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdLoaderDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADAdLoader; + +GAD_ASSUME_NONNULL_BEGIN + +/// Base ad loader delegate protocol. Ad types provide extended protocols that declare methods to +/// handle successful ad loads. +@protocol GADAdLoaderDelegate + +/// Called when adLoader fails to load an ad. +- (void)adLoader:(GADAdLoader *)adLoader didFailToReceiveAdWithError:(GADRequestError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdNetworkExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdNetworkExtras.h new file mode 100755 index 000000000..55c62f134 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdNetworkExtras.h @@ -0,0 +1,22 @@ +// +// GADAdNetworkExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An object implementing this protocol contains information set by the publisher on the client +/// device for a particular ad network. +/// +/// Ad networks should create an 'extras' object implementing this protocol for their publishers to +/// use. +@protocol GADAdNetworkExtras +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdReward.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdReward.h new file mode 100755 index 000000000..38aeefb55 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdReward.h @@ -0,0 +1,30 @@ +// +// GADAdReward.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Reward information for GADRewardBasedVideoAd ads. +@interface GADAdReward : NSObject + +/// Type of the reward. +@property(nonatomic, readonly, copy) NSString *type; + +/// Amount rewarded to the user. +@property(nonatomic, readonly, copy) NSDecimalNumber *amount; + +/// Returns an initialized GADAdReward with the provided reward type and reward amount. rewardType +/// and rewardAmount must not be nil. +- (instancetype)initWithRewardType:(NSString *)rewardType + rewardAmount:(NSDecimalNumber *)rewardAmount NS_DESIGNATED_INITIALIZER; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSize.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSize.h new file mode 100755 index 000000000..c92b767d2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSize.h @@ -0,0 +1,117 @@ +// +// GADAdSize.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A valid GADAdSize is considered to be one of the predefined GADAdSize constants or a GADAdSize +/// constructed by GADAdSizeFromCGSize, GADAdSizeFullWidthPortraitWithHeight, +/// GADAdSizeFullWidthLandscapeWithHeight. +/// +/// Do not create a GADAdSize manually. Use one of the kGADAdSize constants. Treat GADAdSize as an +/// opaque type. Do not access any fields directly. To obtain a concrete CGSize, use the function +/// CGSizeFromGADAdSize(). +typedef struct GAD_BOXABLE GADAdSize GADAdSize; + +/// Ad size. +/// +/// @see typedef GADAdSize +struct GAD_BOXABLE GADAdSize { + CGSize size; ///< The ad size. Don't modify this value directly. + NSUInteger flags; ///< Reserved. +}; + +#pragma mark Standard Sizes + +/// iPhone and iPod Touch ad size. Typically 320x50. +GAD_EXTERN GADAdSize const kGADAdSizeBanner; + +/// Taller version of kGADAdSizeBanner. Typically 320x100. +GAD_EXTERN GADAdSize const kGADAdSizeLargeBanner; + +/// Medium Rectangle size for the iPad (especially in a UISplitView's left pane). Typically 300x250. +GAD_EXTERN GADAdSize const kGADAdSizeMediumRectangle; + +/// Full Banner size for the iPad (especially in a UIPopoverController or in +/// UIModalPresentationFormSheet). Typically 468x60. +GAD_EXTERN GADAdSize const kGADAdSizeFullBanner; + +/// Leaderboard size for the iPad. Typically 728x90. +GAD_EXTERN GADAdSize const kGADAdSizeLeaderboard; + +/// Skyscraper size for the iPad. Mediation only. AdMob/Google does not offer this size. Typically +/// 120x600. +GAD_EXTERN GADAdSize const kGADAdSizeSkyscraper; + +/// An ad size that spans the full width of the application in portrait orientation. The height is +/// typically 50 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerPortrait; + +/// An ad size that spans the full width of the application in landscape orientation. The height is +/// typically 32 pixels on an iPhone/iPod UI, and 90 pixels tall on an iPad UI. +GAD_EXTERN GADAdSize const kGADAdSizeSmartBannerLandscape; + +/// An ad size that spans the full width of its container, with a height dynamically determined by +/// the ad. +GAD_EXTERN GADAdSize const kGADAdSizeFluid; + +/// Invalid ad size marker. +GAD_EXTERN GADAdSize const kGADAdSizeInvalid; + +#pragma mark Custom Sizes + +/// Returns a custom GADAdSize for the provided CGSize. Use this only if you require a non-standard +/// size. Otherwise, use one of the standard size constants above. +GAD_EXTERN GADAdSize GADAdSizeFromCGSize(CGSize size); + +/// Returns a custom GADAdSize that spans the full width of the application in portrait orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthPortraitWithHeight(CGFloat height); + +/// Returns a custom GADAdSize that spans the full width of the application in landscape orientation +/// with the height provided. +GAD_EXTERN GADAdSize GADAdSizeFullWidthLandscapeWithHeight(CGFloat height); + +#pragma mark Convenience Functions + +/// Returns YES if the two GADAdSizes are equal, otherwise returns NO. +GAD_EXTERN BOOL GADAdSizeEqualToSize(GADAdSize size1, GADAdSize size2); + +/// Returns a CGSize for the provided a GADAdSize constant. If the GADAdSize is unknown, returns +/// CGSizeZero. +GAD_EXTERN CGSize CGSizeFromGADAdSize(GADAdSize size); + +/// Returns YES if |size| is one of the predefined constants or is a custom GADAdSize generated by +/// GADAdSizeFromCGSize. +GAD_EXTERN BOOL IsGADAdSizeValid(GADAdSize size); + +/// Returns YES if |size| is a fluid ad size. +GAD_EXTERN BOOL GADAdSizeIsFluid(GADAdSize size); + +/// Returns a NSString describing the provided GADAdSize. +GAD_EXTERN NSString *NSStringFromGADAdSize(GADAdSize size); + +/// Returns an NSValue representing the GADAdSize. +GAD_EXTERN NSValue *NSValueFromGADAdSize(GADAdSize size); + +/// Returns a GADAdSize from an NSValue. Returns kGADAdSizeInvalid if the value is not a GADAdSize. +GAD_EXTERN GADAdSize GADAdSizeFromNSValue(NSValue *value); + +#pragma mark Deprecated Macros + +#define GAD_SIZE_320x50 CGSizeFromGADAdSize(kGADAdSizeBanner) +#define GAD_SIZE_320x100 CGSizeFromGADAdSize(kGADAdSizeLargeBanner) +#define GAD_SIZE_300x250 CGSizeFromGADAdSize(kGADAdSizeMediumRectangle) +#define GAD_SIZE_468x60 CGSizeFromGADAdSize(kGADAdSizeFullBanner) +#define GAD_SIZE_728x90 CGSizeFromGADAdSize(kGADAdSizeLeaderboard) +#define GAD_SIZE_120x600 CGSizeFromGADAdSize(kGADAdSizeSkyscraper) + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSizeDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSizeDelegate.h new file mode 100755 index 000000000..ce82adceb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAdSizeDelegate.h @@ -0,0 +1,26 @@ +// +// GADAdSizeDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; + +GAD_ASSUME_NONNULL_BEGIN + +/// The class implementing this protocol will be notified when the DFPBannerView changes ad size. +/// Any views that may be affected by the banner size change will have time to adjust. +@protocol GADAdSizeDelegate + +/// Called before the ad view changes to the new size. +- (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAppEventDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAppEventDelegate.h new file mode 100755 index 000000000..a9f79cf14 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADAppEventDelegate.h @@ -0,0 +1,35 @@ +// +// GADAppEventDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADBannerView; +@class GADInterstitial; + +GAD_ASSUME_NONNULL_BEGIN + +/// Implement your app event within these methods. The delegate will be notified when the SDK +/// receives an app event message from the ad. +@protocol GADAppEventDelegate + +@optional + +/// Called when the banner receives an app event. +- (void)adView:(GADBannerView *)banner + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +/// Called when the interstitial receives an app event. +- (void)interstitial:(GADInterstitial *)interstitial + didReceiveAppEvent:(NSString *)name + withInfo:(NSString *GAD_NULLABLE_TYPE)info; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerView.h new file mode 100755 index 000000000..a93a71b10 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerView.h @@ -0,0 +1,108 @@ +// +// GADBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays banner ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADBannerView *adView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADBannerView : UIView + +#pragma mark Initialization + +/// Initializes and returns a banner view with the specified ad size and origin relative to the +/// banner's superview. +- (instancetype)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Initializes and returns a banner view with the specified ad size placed at its superview's +/// origin. +- (instancetype)initWithAdSize:(GADAdSize)adSize; + +#pragma mark Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example the root view controller in +/// tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this banner view to a proper size. Never create your own GADAdSize directly. Use +/// one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If not using mediation, then changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If using mediation, +/// then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this GADBannerView. +/// Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id inAppPurchaseDelegate; + +/// Optional delegate that is notified when creatives cause the banner to change size. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +#pragma mark Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +#pragma mark Mediation + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +#pragma mark Deprecated + +/// Indicates if the currently displayed ad (or most recent failure) was a result of auto refreshing +/// as specified on server. This property is set to NO after each loadRequest: method. +@property(nonatomic, readonly, assign) BOOL hasAutoRefreshed GAD_DEPRECATED_ATTRIBUTE; + +/// The mediated ad network's underlying ad view. You may use this property to read the ad's actual +/// size and adjust this banner view's frame origin. However, modifying the banner view's frame size +/// triggers the Mobile Ads SDK to request a new ad. Only update the banner view's frame origin. +@property(nonatomic, readonly, weak, GAD_NULLABLE) + UIView *mediatedAdView GAD_DEPRECATED_MSG_ATTRIBUTE("Use adNetworkClassName."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerViewDelegate.h new file mode 100755 index 000000000..f977bc479 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADBannerViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADBannerViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADBannerView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADBannerView state change messages such as ad request status +/// and ad click lifecycle. +@protocol GADBannerViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that an ad request successfully received an ad. The delegate may want to add +/// the banner view to the view hierarchy if it hasn't been added yet. +- (void)adViewDidReceiveAd:(GADBannerView *)bannerView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)adView:(GADBannerView *)bannerView didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)adViewWillPresentScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)adViewWillDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)adViewDidDismissScreen:(GADBannerView *)bannerView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)adViewWillLeaveApplication:(GADBannerView *)bannerView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelator.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelator.h new file mode 100755 index 000000000..909f0f4cf --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelator.h @@ -0,0 +1,23 @@ +// +// GADCorrelator.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Represents a correlation between multiple ads. Set an instance of this object on multiple ads to +/// indicate they are being used in a common context. +@interface GADCorrelator : NSObject + +/// Resets the correlator to force a new set of correlated ads. +- (void)reset; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelatorAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelatorAdLoaderOptions.h new file mode 100755 index 000000000..b10d60757 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCorrelatorAdLoaderOptions.h @@ -0,0 +1,22 @@ +// +// GADCorrelatorAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad loader options for adding a correlator to a native ad request. +@interface GADCorrelatorAdLoaderOptions : GADAdLoaderOptions + +/// Correlator object for correlating ads loaded by an ad loader to other ad objects. +@property(nonatomic, strong, GAD_NULLABLE) GADCorrelator *correlator; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBanner.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBanner.h new file mode 100755 index 000000000..53317d909 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBanner.h @@ -0,0 +1,40 @@ +// +// GADCustomEventBanner.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The banner custom event protocol. Your banner custom event handler must implement this protocol. +@protocol GADCustomEventBanner + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Report execution results +/// to the delegate. +/// +/// @param adSize The size of the ad as configured in the mediation UI for the mediation placement. +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestBannerAd:(GADAdSize)adSize + parameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBannerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBannerDelegate.h new file mode 100755 index 000000000..8ec685c5c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventBannerDelegate.h @@ -0,0 +1,68 @@ +// +// GADCustomEventBannerDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventBanner; + +/// Call back to this delegate in your custom event. You must call customEventBanner:didReceiveAd: +/// when there is an ad to show, or customEventBanner:didFailAd: when there is no ad to show. +/// Otherwise, if enough time passed (several seconds) after the SDK called the requestBannerAd: +/// method of your custom event, the mediation SDK will consider the request timed out, and move on +/// to the next ad network. +@protocol GADCustomEventBannerDelegate + +/// Your Custom Event object must call this when it receives or creates an ad view. +- (void)customEventBanner:(id)customEvent didReceiveAd:(UIView *)view; + +/// Your Custom Event object must call this when it fails to receive or create the ad view. Pass +/// along any error object sent from the ad network's SDK, or an NSError describing the error. Pass +/// nil if not available. +- (void)customEventBanner:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventBannerWasClicked:(id)customEvent; + +/// The rootViewController that you set in GADBannerView. Use this UIViewController to show a modal +/// view when a user taps on the ad. +@property(nonatomic, readonly) UIViewController *viewControllerForPresentingModalView; + +/// When you call the following methods, the call will be propagated back to the +/// GADBannerViewDelegate that you implemented and passed to GADBannerView. + +/// Your Custom Event should call this when the user taps an ad and a modal view appears. +- (void)customEventBannerWillPresentModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view is +/// about to go away. +- (void)customEventBannerWillDismissModal:(id)customEvent; + +/// Your Custom Event should call this when the user dismisses the modal view and the modal view has +/// gone away. +- (void)customEventBannerDidDismissModal:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in App switching. +- (void)customEventBannerWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventBannerWasClicked:. +- (void)customEventBanner:(id)customEvent + clickDidOccurInAd:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventBannerWasClicked:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventExtras.h new file mode 100755 index 000000000..a42a35cc1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventExtras.h @@ -0,0 +1,35 @@ +// +// GADCustomEventExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Create an instance of this class to set additional parameters for each custom event object. The +/// additional parameters for a custom event are keyed by the custom event label. These extras are +/// passed to your implementation of GADCustomEventBanner or GADCustomEventInterstitial. +@interface GADCustomEventExtras : NSObject + +/// Set additional parameters for the custom event with label |label|. To remove additional +/// parameters associated with |label|, pass in nil for |extras|. +- (void)setExtras:(NSDictionary *GAD_NULLABLE_TYPE)extras forLabel:(NSString *)label; + +/// Retrieve the extras for |label|. +- (NSDictionary *GAD_NULLABLE_TYPE)extrasForLabel:(NSString *)label; + +/// Removes all the extras set on this instance. +- (void)removeAllExtras; + +/// Returns all the extras set on this instance. +- (NSDictionary *)allExtras; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitial.h new file mode 100755 index 000000000..7a05e3bd6 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitial.h @@ -0,0 +1,43 @@ +// +// GADCustomEventInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The interstitial custom event protocol. Your interstitial custom event handler must implement +/// this protocol. +@protocol GADCustomEventInterstitial + +/// Inform |delegate| with the custom event execution results to ensure mediation behaves correctly. +/// +/// In your class, define the -delegate and -setDelegate: methods or use "@synthesize delegate". The +/// Google Mobile Ads SDK sets this property on instances of your class. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Called by mediation when your custom event is scheduled to be executed. Your implementation +/// should start retrieving the interstitial ad. Report execution results to the delegate. You must +/// wait until -presentFromRootViewController is called before displaying the interstitial ad. +/// +/// @param serverParameter Parameter configured in the mediation UI. +/// @param serverLabel Label configured in the mediation UI. +/// @param request Contains ad request information. +- (void)requestInterstitialAdWithParameter:(NSString *GAD_NULLABLE_TYPE)serverParameter + label:(NSString *GAD_NULLABLE_TYPE)serverLabel + request:(GADCustomEventRequest *)request; + +/// Present the interstitial ad as a modal view using the provided view controller. Called only +/// after your class calls -customEventInterstitialDidReceiveAd: on its custom event delegate. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitialDelegate.h new file mode 100755 index 000000000..97219d3e5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventInterstitialDelegate.h @@ -0,0 +1,62 @@ +// +// GADCustomEventInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventInterstitial; + +/// Call back to this delegate in your custom event. You must call +/// customEventInterstitialDidReceiveAd: when there is an ad to show, or +/// customEventInterstitial:didFailAd: when there is no ad to show. Otherwise, if enough time passed +/// (several seconds) after the SDK called the requestInterstitialAdWithParameter: method of your +/// custom event, the mediation SDK will consider the request timed out, and move on to the next ad +/// network. +@protocol GADCustomEventInterstitialDelegate + +/// Your Custom Event object must call this when it receives or creates an interstitial ad. +- (void)customEventInterstitialDidReceiveAd:(id)customEvent; + +/// Your Custom Event object must call this when it fails to receive or create the ad. Pass along +/// any error object sent from the ad network's SDK, or an NSError describing the error. Pass nil if +/// not available. +- (void)customEventInterstitial:(id)customEvent + didFailAd:(NSError *GAD_NULLABLE_TYPE)error; + +/// Your Custom Event object should call this when the user touches or "clicks" the ad to initiate +/// an action. When the SDK receives this callback, it reports the click back to the mediation +/// server. +- (void)customEventInterstitialWasClicked:(id)customEvent; + +// When you call any of the following methods, the call will be propagated back to the +// GADInterstitialDelegate that you implemented and passed to GADInterstitial. + +/// Your Custom Event should call this when the interstitial is being displayed. +- (void)customEventInterstitialWillPresent:(id)customEvent; + +/// Your Custom Event should call this when the interstitial is about to be dismissed. +- (void)customEventInterstitialWillDismiss:(id)customEvent; + +/// Your Custom Event should call this when the interstitial has been dismissed. +- (void)customEventInterstitialDidDismiss:(id)customEvent; + +/// Your Custom Event should call this method when a user action will result in app switching. +- (void)customEventInterstitialWillLeaveApplication:(id)customEvent; + +#pragma mark Deprecated + +/// Deprecated. Use customEventInterstitialDidReceiveAd:. +- (void)customEventInterstitial:(id)customEvent + didReceiveAd:(NSObject *)ad + GAD_DEPRECATED_MSG_ATTRIBUTE("Use customEventInterstitialDidReceiveAd:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAd.h new file mode 100755 index 000000000..9a99c7e42 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAd.h @@ -0,0 +1,58 @@ +// +// GADCustomEventNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADCustomEventNativeAdDelegate; + +/// Native ad custom event protocol. Your native ad custom event handler class must conform to this +/// protocol. +@protocol GADCustomEventNativeAd + +/// Called when the custom event is scheduled to be executed. +/// +/// @param serverParameter A value configured in the mediation UI for the custom event. +/// @param request Ad targeting information. +/// @param adTypes List of requested native ad types. See GADAdLoaderAdTypes.h for available ad +/// types. +/// @param options Additional options configured by the publisher for requesting a native ad. See +/// GADNativeAdImageAdLoaderOptions.h for available image options. +/// @param rootViewController Publisher-provided view controller. +- (void)requestNativeAdWithParameter:(NSString *)serverParameter + request:(GADCustomEventRequest *)request + adTypes:(NSArray *)adTypes + options:(NSArray *)options + rootViewController:(UIViewController *)rootViewController; + +/// Indicates if the custom event handles user clicks. Return YES if the custom event should handle +/// user clicks. In this case, the Google Mobile Ads SDK doesn't track user clicks and the custom +/// event must notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. Return NO if the +/// custom event doesn't handles user clicks. In this case, the Google Mobile Ads SDK tracks user +/// clicks itself and the custom event is notified of user clicks via -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the custom event handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the custom event must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the custom event of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// Delegate object used for receiving custom native ad load request progress. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAdDelegate.h new file mode 100755 index 000000000..19029a3c8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventNativeAdDelegate.h @@ -0,0 +1,31 @@ +// +// GADCustomEventNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The delegate of the GADCustomEventNativeAd object must adopt the GADCustomEventNativeAdDelegate +/// protocol. Methods in this protocol are used for native ad's custom event communication with the +/// Google Mobile Ads SDK. +@protocol GADCustomEventNativeAdDelegate + +/// Tells the delegate that the custom event ad request succeeded and loaded a native ad. +- (void)customEventNativeAd:(id)customEventNativeAd + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +/// Tells the delegate that the custom event ad request failed. +- (void)customEventNativeAd:(id)customEventNativeAd + didFailToLoadWithError:(NSError *)error; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventParameters.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventParameters.h new file mode 100755 index 000000000..084155d69 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventParameters.h @@ -0,0 +1,19 @@ +// +// GADCustomEventParameters.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Key for getting the server parameter configured in AdMob when mediating to a custom event +/// adapter. +/// Example: NSString *serverParameter = connector.credentials[GADCustomEventParametersServer]. +extern NSString *const GADCustomEventParametersServer; + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventRequest.h new file mode 100755 index 000000000..cf48be3a2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADCustomEventRequest.h @@ -0,0 +1,59 @@ +// +// GADCustomEventRequest.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADCustomEventExtras; + +GAD_ASSUME_NONNULL_BEGIN + +/// Specifies optional ad request targeting parameters that are provided by the publisher and are +/// forwarded to custom events for purposes of populating an ad request to a 3rd party ad network. +@interface GADCustomEventRequest : NSObject + +/// User's gender set in GADRequest. If not specified, returns kGADGenderUnknown. +@property(nonatomic, readonly, assign) GADGender userGender; + +/// User's birthday set in GADRequest. If not specified, returns nil. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDate *userBirthday; + +/// If the user's latitude, longitude, and accuracy are not specified, userHasLocation returns NO, +/// and userLatitude, userLongitude, and userLocationAccuracyInMeters return 0. +@property(nonatomic, readonly, assign) BOOL userHasLocation; + +/// User's latitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLatitude; + +/// User's longitude set in GADRequest. +@property(nonatomic, readonly, assign) CGFloat userLongitude; + +/// The accuracy, in meters, of the user's location data. +@property(nonatomic, readonly, assign) CGFloat userLocationAccuracyInMeters; + +/// Description of the user's location, in free form text, set in GADRequest. If not available, +/// returns nil. This may be set even if userHasLocation is NO. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *userLocationDescription; + +/// Keywords set in GADRequest. Returns nil if no keywords are set. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *userKeywords; + +/// The additional parameters set by the application. This property allows you to pass additional +/// information from your application to your Custom Event object. To do so, create an instance of +/// GADCustomEventExtras to pass to GADRequest -registerAdNetworkExtras:. The instance should have +/// an NSDictionary set for a particular custom event label. That NSDictionary becomes the +/// additionalParameters here. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +/// Indicates if the testing property has been set in GADRequest. +@property(nonatomic, readonly, assign) BOOL isTesting; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDebugOptionsViewController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDebugOptionsViewController.h new file mode 100755 index 000000000..acc98dc3f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDebugOptionsViewController.h @@ -0,0 +1,36 @@ +// +// GADDebugOptionsViewController.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +@class GADDebugOptionsViewController; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for the GADDebugOptionsViewController. +@protocol GADDebugOptionsViewControllerDelegate +/// Called when the debug options flow is finished. +- (void)debugOptionsViewControllerDidDismiss:(GADDebugOptionsViewController *)controller; +@end + +/// Displays debug options to the user. +@interface GADDebugOptionsViewController : UIViewController + +/// Creates and returns a GADDebugOptionsViewController object initialized with the ad unit ID. +/// @param adUnitID An ad unit ID for the DFP account that is being configured with debug options. ++ (instancetype)debugOptionsViewControllerWithAdUnitID:(NSString *)adUnitID; + +/// Delegate for the debug options view controller. +@property(nonatomic, weak, GAD_NULLABLE) + IBOutlet id delegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDynamicHeightSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDynamicHeightSearchRequest.h new file mode 100755 index 000000000..4fefe66fd --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADDynamicHeightSearchRequest.h @@ -0,0 +1,165 @@ +// +// GADDynamicHeightSearchRequest.h +// GoogleMobileAds +// +// Copyright © 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Use to configure Custom Search Ad (CSA) ad requests. A dynamic height search banner can contain +/// multiple ads and the height is set dynamically based on the ad contents. Please cross-reference +/// the property sections and properties with the official reference document: +/// https://developers.google.com/custom-search-ads/docs/reference +@interface GADDynamicHeightSearchRequest : GADRequest + +#pragma mark - Page Level Parameters + +#pragma mark Required + +/// The CSA "query" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; + +/// The CSA "adPage" parameter. +@property(nonatomic, assign) NSInteger adPage; + +#pragma mark Configuration Settings + +/// Indicates if the CSA "adTest" parameter is enabled. +@property(nonatomic, assign) BOOL adTestEnabled; + +/// The CSA "channel" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *channel; + +/// The CSA "hl" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *hostLanguage; + +#pragma mark Layout and Styling + +/// The CSA "colorLocation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *locationExtensionTextColor; + +/// The CSA "fontSizeLocation" parameter. +@property(nonatomic, assign) CGFloat locationExtensionFontSize; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "clickToCall" parameter is enabled. +@property(nonatomic, assign) BOOL clickToCallExtensionEnabled; + +/// Indicates if the CSA "location" parameter is enabled. +@property(nonatomic, assign) BOOL locationExtensionEnabled; + +/// Indicates if the CSA "plusOnes" parameter is enabled. +@property(nonatomic, assign) BOOL plusOnesExtensionEnabled; + +/// Indicates if the CSA "sellerRatings" parameter is enabled. +@property(nonatomic, assign) BOOL sellerRatingsExtensionEnabled; + +/// Indicates if the CSA "siteLinks" parameter is enabled. +@property(nonatomic, assign) BOOL siteLinksExtensionEnabled; + +#pragma mark - Unit Level Parameters + +#pragma mark Required + +/// The CSA "width" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *CSSWidth; + +/// Configuration Settings + +/// The CSA "number" parameter. +@property(nonatomic, assign) NSInteger numberOfAds; + +#pragma mark Font + +/// The CSA "fontFamily" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; + +/// The CSA "fontFamilyAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionFontFamily; + +/// The CSA "fontSizeAnnotation" parameter. +@property(nonatomic, assign) CGFloat annotationFontSize; + +/// The CSA "fontSizeAttribution" parameter. +@property(nonatomic, assign) CGFloat attributionFontSize; + +/// The CSA "fontSizeDescription" parameter. +@property(nonatomic, assign) CGFloat descriptionFontSize; + +/// The CSA "fontSizeDomainLink" parameter. +@property(nonatomic, assign) CGFloat domainLinkFontSize; + +/// The CSA "fontSizeTitle" parameter. +@property(nonatomic, assign) CGFloat titleFontSize; + +#pragma mark Color + +/// The CSA "colorAdBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderColor; + +/// The CSA "colorAdSeparator" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adSeparatorColor; + +/// The CSA "colorAnnotation" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *annotationTextColor; + +/// The CSA "colorAttribution" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *attributionTextColor; + +/// The CSA "colorBackground" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *backgroundColor; + +/// The CSA "colorBorder" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderColor; + +/// The CSA "colorDomainLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *domainLinkColor; + +/// The CSA "colorText" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *textColor; + +/// The CSA "colorTitleLink" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *titleLinkColor; + +#pragma mark General Formatting + +/// The CSA "adBorderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *adBorderCSSSelections; + +/// The CSA "adjustableLineHeight" parameter. +@property(nonatomic, assign) CGFloat adjustableLineHeight; + +/// The CSA "attributionSpacingBelow" parameter. +@property(nonatomic, assign) CGFloat attributionBottomSpacing; + +/// The CSA "borderSelections" parameter. +@property(nonatomic, copy, GAD_NULLABLE) NSString *borderCSSSelections; + +/// Indicates if the CSA "noTitleUnderline" parameter is enabled. +@property(nonatomic, assign) BOOL titleUnderlineHidden; + +/// Indicates if the CSA "titleBold" parameter is enabled. +@property(nonatomic, assign) BOOL boldTitleEnabled; + +/// The CSA "verticalSpacing" parameter. +@property(nonatomic, assign) CGFloat verticalSpacing; + +#pragma mark Ad Extensions + +/// Indicates if the CSA "detailedAttribution" parameter is enabled. +@property(nonatomic, assign) BOOL detailedAttributionExtensionEnabled; + +/// Indicates if the CSA "longerHeadlines" parameter is enabled. +@property(nonatomic, assign) BOOL longerHeadlinesExtensionEnabled; + +/// Sets an advanced option value for a specified key. The value must be an NSString or NSNumber. +- (void)setAdvancedOptionValue:(id)value forKey:(NSString *)key; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADExtras.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADExtras.h new file mode 100755 index 000000000..3ca160fa0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADExtras.h @@ -0,0 +1,23 @@ +// +// GADExtras.h +// Google Mobile Ads SDK +// +// Copyright 2012 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Ad network extras sent to Google networks. +@interface GADExtras : NSObject + +/// Additional parameters to be sent to Google networks. +@property(nonatomic, copy, GAD_NULLABLE) NSDictionary *additionalParameters; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchase.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchase.h new file mode 100755 index 000000000..07fc206fa --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchase.h @@ -0,0 +1,86 @@ +// +// GADInAppPurchase.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADDefaultInAppPurchaseDelegate; + +#pragma mark - Default Purchase Flow + +/// The consumable in-app purchase item that has been purchased by the user. The purchase flow is +/// handled by the Google Mobile Ads SDK. +/// Instances of this class are created and passed to your in-app purchase delegate after the user +/// has successfully paid for a product. Your code must correctly deliver the product to the user +/// and then call the didCompletePurchase method to finish the transaction. +@interface GADDefaultInAppPurchase : NSObject + +/// Enables the default consumable product in-app purchase flow handled by the Google Mobile Ads +/// SDK. The GADDefaultInAppPurchaseDelegate object is retained while the default purchase flow is +/// enabled. This method adds a SKPaymentTransactionObserver to the default SKPaymentQueue. +/// +/// Call this method early in your application to handle unfinished transactions from previous +/// application sessions. For example, call this method in your application delegate's +/// application:didFinishLaunchingWithOptions: method. ++ (void)enableDefaultPurchaseFlowWithDelegate:(id)delegate; + +/// Disables the default in-app purchase flow handled by the Google Mobile Ads SDK and releases the +/// associated GADDefaultInAppPurchaseDelegate object. ++ (void)disableDefaultPurchaseFlow; + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The purchased item's completed payment transaction. Your application can use this property's +/// data to save a permanent record of the completed payment. The default purchase flow will finish +/// the transaction on your behalf. Do not finish the transaction yourself. +@property(nonatomic, readonly, strong) SKPaymentTransaction *paymentTransaction; + +/// The in-app purchase delegate object must first deliver the user's item and then call this +/// method. Failure to call this method will result in duplicate purchase notifications. +- (void)finishTransaction; + +@end + +#pragma mark - Custom Purchase Flow + +/// Enum of the different statuses resulting from processing a purchase. +typedef NS_ENUM(NSInteger, GADInAppPurchaseStatus) { + kGADInAppPurchaseStatusError = 0, ///< Error occured while processing the purchase. + kGADInAppPurchaseStatusSuccessful = 1, ///< Purchase was completed successfully. + kGADInAppPurchaseStatusCancel = 2, ///< Purchase was cancelled by the user. + kGADInAppPurchaseStatusInvalidProduct = 3 ///< Error occured while looking up the product. +}; + +/// The in-app purchase item to be purchased with the purchase flow handled by you, the +/// application developer. +/// Instances of this class are created and passed to your GADInAppPurchaseDelegate object when +/// users click a buy button. It is important to report the result of the purchase back to the SDK +/// in order to track metrics about the transaction. +@interface GADInAppPurchase : NSObject + +/// The in-app purchase product ID. +@property(nonatomic, readonly, copy) NSString *productID; + +/// The product quantity. +@property(nonatomic, readonly, assign) NSInteger quantity; + +/// The GADInAppPurchaseDelegate object must call this method after handling the in-app purchase for +/// both successful and unsuccessful purchase attempts. This method reports ad conversion and +/// purchase status information to Google. +- (void)reportPurchaseStatus:(GADInAppPurchaseStatus)purchaseStatus; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchaseDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchaseDelegate.h new file mode 100755 index 000000000..fe1d8f941 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInAppPurchaseDelegate.h @@ -0,0 +1,48 @@ +// +// GADInAppPurchaseDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2013 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADDefaultInAppPurchase; +@class GADInAppPurchase; + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Default Purchase Flow + +/// In-app purchase delegate protocol for default purchase handling. The delegate must deliver +/// the purchased item then call the GADDefaultInAppPurchase object's finishTransaction method. +@protocol GADDefaultInAppPurchaseDelegate + +/// Called when the user successfully paid for a purchase. You must first deliver the purchased +/// item to the user, then call defaultInAppPurchase's finishTransaction method. +- (void)userDidPayForPurchase:(GADDefaultInAppPurchase *)defaultInAppPurchase; + +@optional + +/// Called when the user clicks on the buy button of an in-app purchase ad. Return YES if the +/// default purchase flow should be started to purchase the item, otherwise return NO. If not +/// implemented, defaults to YES. +- (BOOL)shouldStartPurchaseForProductID:(NSString *)productID quantity:(NSInteger)quantity; + +@end + +#pragma mark - Custom Purchase Flow + +/// In-app purchase delegate protocol for custom purchase handling. The delegate must handle the +/// product purchase flow then call the GADInAppPurchase object's reportPurchaseStatus: method. +@protocol GADInAppPurchaseDelegate + +/// Called when the user clicks on the buy button of an in-app purchase ad. After the receiver +/// handles the purchase, it must call the GADInAppPurchase object's reportPurchaseStatus: method. +- (void)didReceiveInAppPurchase:(GADInAppPurchase *)purchase; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitial.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitial.h new file mode 100755 index 000000000..cb17be99d --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitial.h @@ -0,0 +1,88 @@ +// +// GADInterstitial.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// An interstitial ad. This is a full-screen advertisement shown at natural transition points in +/// your application such as between game levels or news stories. +@interface GADInterstitial : NSObject + +/// Initializes an interstitial with an ad unit created on the AdMob website. Create a new ad unit +/// for every unique placement of an ad in your application. Set this to the ID assigned for this +/// placement. Ad units are important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +- (instancetype)initWithAdUnitID:(NSString *)adUnitID NS_DESIGNATED_INITIALIZER; + +#pragma mark Pre-Request + +/// Required value passed in with initWithAdUnitID:. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adUnitID; + +/// Optional delegate object that receives state change notifications from this GADInterstitalAd. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Optional delegate object that receives in-app purchase notifications from this ad. Required for +/// the custom in-app purchase flow, but ignored when using the default in-app purchase flow. +@property(nonatomic, weak, GAD_NULLABLE) id inAppPurchaseDelegate; + +#pragma mark Making an Ad Request + +/// Makes an interstitial ad request. Additional targeting options can be supplied with a request +/// object. Only one interstitial request is allowed at a time. +/// +/// This is best to do several seconds before the interstitial is needed to preload its content. +/// Then when transitioning between view controllers show the interstital with +/// presentFromViewController. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark Post-Request + +/// Returns YES if the interstitial is ready to be displayed. The delegate's +/// interstitialAdDidReceiveAd: will be called after this property switches from NO to YES. +@property(nonatomic, readonly, assign) BOOL isReady; + +/// Returns YES if this object has already been presented. Interstitial objects can only be used +/// once even with different requests. +@property(nonatomic, readonly, assign) BOOL hasBeenUsed; + +/// Returns the ad network class name that fetched the current ad. Returns nil while the latest ad +/// request is in progress or if the latest ad request failed. For both standard and mediated Google +/// AdMob ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this property returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Presents the interstitial ad which takes over the entire screen until the user dismisses it. +/// This has no effect unless isReady returns YES and/or the delegate's interstitialDidReceiveAd: +/// has been received. +/// +/// Set rootViewController to the current view controller at the time this method is called. If your +/// application does not use view controllers pass in nil and your views will be removed from the +/// window to show the interstitial and restored when done. After the interstitial has been removed, +/// the delegate's interstitialDidDismissScreen: will be called. +- (void)presentFromRootViewController:(UIViewController *)rootViewController; + +#pragma mark Deprecated + +/// Deprecated intializer. Use initWithAdUnitID: instead. +- (instancetype)init GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID:."); + +/// Deprecated setter, use initWithAdUnitID: instead. +- (void)setAdUnitID:(NSString *GAD_NULLABLE_TYPE)adUnitID + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithAdUnitID: instead of setting the ad unit ID."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitialDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitialDelegate.h new file mode 100755 index 000000000..e83fcf9c0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADInterstitialDelegate.h @@ -0,0 +1,59 @@ +// +// GADInterstitialDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import +#import + +@class GADInterstitial; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADInterstitial such as interstitial ad +/// requests succeeding/failing. +@protocol GADInterstitialDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Called when an interstitial ad request succeeded. Show it at the next transition point in your +/// application such as when transitioning between view controllers. +- (void)interstitialDidReceiveAd:(GADInterstitial *)ad; + +/// Called when an interstitial ad request completed without an interstitial to +/// show. This is common since interstitials are shown sparingly to users. +- (void)interstitial:(GADInterstitial *)ad didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Display-Time Lifecycle Notifications + +/// Called just before presenting an interstitial. After this method finishes the interstitial will +/// animate onto the screen. Use this opportunity to stop animations and save the state of your +/// application in case the user leaves while the interstitial is on screen (e.g. to visit the App +/// Store from a link on the interstitial). +- (void)interstitialWillPresentScreen:(GADInterstitial *)ad; + +/// Called when |ad| fails to present. +- (void)interstitialDidFailToPresentScreen:(GADInterstitial *)ad; + +/// Called before the interstitial is to be animated off the screen. +- (void)interstitialWillDismissScreen:(GADInterstitial *)ad; + +/// Called just after dismissing an interstitial and it has animated off the screen. +- (void)interstitialDidDismissScreen:(GADInterstitial *)ad; + +/// Called just before the application will background or terminate because the user clicked on an +/// ad that will launch another application (such as the App Store). The normal +/// UIApplicationDelegate methods, like applicationDidEnterBackground:, will be called immediately +/// before this. +- (void)interstitialWillLeaveApplication:(GADInterstitial *)ad; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediaView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediaView.h new file mode 100755 index 000000000..d08b4e78e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediaView.h @@ -0,0 +1,27 @@ +// +// GADMediaView.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Displays native ad media assets. +/// +/// To display media assets in GADNativeAppInstallAdView instances, add a GADMediaView subview and +/// assign the native ad view's mediaView property. +/// +/// If the native ad doesn't contain a video and image loading is enabled, the GADMediaView displays +/// the native ad's |images| asset's first image. +/// +/// If the native ad doesn't contain a video and image loading is disabled, the GADMediaView object +/// is empty. +@interface GADMediaView : UIView +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAd.h new file mode 100755 index 000000000..7f37ae26f --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAd.h @@ -0,0 +1,27 @@ +// +// GADMediatedNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Base protocol for mediated native ads. +@protocol GADMediatedNativeAd + +/// Returns a delegate object that receives state change notifications. +- (nullable id)mediatedNativeAdDelegate; + +/// Returns a dictionary of asset names and object pairs for assets that are not handled by +/// properties of the GADMediatedNativeAd subclass. +- (NSDictionary *GAD_NULLABLE_TYPE)extraAssets; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdDelegate.h new file mode 100755 index 000000000..b705652e1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdDelegate.h @@ -0,0 +1,47 @@ +// +// GADMediatedNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADMediatedNativeAd; + +/// GADMediatedNativeAdDelegate objects handle mediated native ad events. +@protocol GADMediatedNativeAdDelegate + +@optional + +/// Tells the delegate that the mediated native ad has rendered in |view|, a subview of +/// |viewController|. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRenderInView:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has recorded an impression. This method is called +/// only once per mediated native ad. +- (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Tells the delegate that the mediated native ad has recorded a user click on the asset named +/// |assetName|. Full screen actions should be presented from |viewController|. This method is +/// called only if -[GADMAdNetworkAdapter handlesUserClicks] returns NO. +- (void)mediatedNativeAd:(id)mediatedNativeAd + didRecordClickOnAssetWithName:(NSString *)assetName + view:(UIView *)view + viewController:(UIViewController *)viewController; + +/// Tells the delegate that the mediated native ad has untracked |view|. This method is called +/// when the mediatedNativeAd is no longer rendered in the provided view and the delegate should +/// stop tracking the view's impressions and clicks. +- (void)mediatedNativeAd:(id)mediatedNativeAd didUntrackView:(UIView *)view; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdNotificationSource.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdNotificationSource.h new file mode 100755 index 000000000..3a3cfe6f8 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAdNotificationSource.h @@ -0,0 +1,45 @@ +// +// GADMediatedNativeAdNotificationSource.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Notifies the Google Mobile Ads SDK about the events performed by adapters. Adapters may perform +/// some action (e.g. opening an in app browser or open the iTunes store) when handling callbacks +/// from GADMediatedNativeAdDelegate. Adapters in such case should notify the Google Mobile Ads SDK +/// by calling the relevant methods from this class. +@interface GADMediatedNativeAdNotificationSource : NSObject + +/// Called by the adapter when it has registered an impression on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserImpressions] returns YES. ++ (void)mediatedNativeAdDidRecordImpression:(id)mediatedNativeAd; + +/// Called by the adapter when it has registered a user click on the tracked view. Adapter should +/// only call this method if -[GADMAdNetworkAdapter handlesUserClicks] returns YES. ++ (void)mediatedNativeAdDidRecordClick:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has opened an in app modal screen. ++ (void)mediatedNativeAdWillPresentScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdWillDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter after the in app modal screen opened by mediatedNativeAd is +/// dismissed. ++ (void)mediatedNativeAdDidDismissScreen:(id)mediatedNativeAd; + +/// Must be called by the adapter just before mediatedNativeAd has left the application. ++ (void)mediatedNativeAdWillLeaveApplication:(id)mediatedNativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAppInstallAd.h new file mode 100755 index 000000000..9475d35d5 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeAppInstallAd.h @@ -0,0 +1,51 @@ +// +// GADMediatedNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native app install ads. The adapter must return an object +/// conforming to this protocol for native app install ad requests. +@protocol GADMediatedNativeAppInstallAd + +/// App title. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Array of GADNativeAdImage objects related to the advertised application. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// App description. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// Application icon. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)icon; + +/// Text that encourages user to take some action with the ad. For example "Install". +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// App store rating (0 to 5). +- (NSDecimalNumber *GAD_NULLABLE_TYPE)starRating; + +/// The app store name. For example, "App Store". +- (NSString *GAD_NULLABLE_TYPE)store; + +/// String representation of the app's price. +- (NSString *GAD_NULLABLE_TYPE)price; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeContentAd.h new file mode 100755 index 000000000..068da5845 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMediatedNativeContentAd.h @@ -0,0 +1,44 @@ +// +// GADMediatedNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides methods used for constructing native content ads. +@protocol GADMediatedNativeContentAd + +/// Primary text headline. +- (NSString *GAD_NULLABLE_TYPE)headline; + +/// Secondary text. +- (NSString *GAD_NULLABLE_TYPE)body; + +/// List of large images. Each object is an instance of GADNativeAdImage. +- (NSArray *GAD_NULLABLE_TYPE)images; + +/// Small logo image. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)logo; + +/// Text that encourages user to take some action with the ad. +- (NSString *GAD_NULLABLE_TYPE)callToAction; + +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +- (NSString *GAD_NULLABLE_TYPE)advertiser; + +@optional + +/// AdChoices view. +- (UIView *GAD_NULLABLE_TYPE)adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMobileAds.h new file mode 100755 index 000000000..5c7abfbef --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADMobileAds.h @@ -0,0 +1,55 @@ +// +// GADMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Google Mobile Ads SDK settings. +@interface GADMobileAds : NSObject + +/// Returns the shared GADMobileAds instance. ++ (GADMobileAds *)sharedInstance; + +/// Configures the SDK using the settings associated with the given application ID. ++ (void)configureWithApplicationID:(NSString *)applicationID; + +/// Disables automated in app purchase (IAP) reporting. Must be called before any IAP transaction is +/// initiated. IAP reporting is used to track IAP ad conversions. Do not disable reporting if you +/// use IAP ads. ++ (void)disableAutomatedInAppPurchaseReporting; + +/// Disables automated SDK crash reporting. If not called, the SDK records the original exception +/// handler if available and registers a new exception handler. The new exception handler only +/// reports SDK related exceptions and calls the recorded original exception handler. ++ (void)disableSDKCrashReporting; + +/// The application's audio volume. Affects audio volumes of all ads relative to other audio output. +/// Valid ad volume values range from 0.0 (silent) to 1.0 (current device volume). Use this method +/// only if your application has its own volume controls (e.g., custom music or sound effect +/// volumes). Defaults to 1.0. +@property(nonatomic, assign) float applicationVolume; + +/// Indicates if the application's audio is muted. Affects initial mute state for all ads. Use this +/// method only if your application has its own volume controls (e.g., custom music or sound effect +/// muting). Defaults to NO. +@property(nonatomic, assign) BOOL applicationMuted; + +/// Returns YES if the current SDK version is at least |major|.|minor|.|patch|. This method can be +/// used by libraries that depend on a specific minimum version of the Google Mobile Ads SDK to warn +/// developers if they have an incompatible version. +/// +/// Available in Google Mobile Ads SDK 7.10 and onwards. Before calling this method check if the +/// GADMobileAds's shared instance responds to this method. Calling this method on a Google Mobile +/// Ads SDK lower than 7.10 can crash the app. +- (BOOL)isSDKVersionAtLeastMajor:(NSInteger)major minor:(NSInteger)minor patch:(NSInteger)patch; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAd.h new file mode 100755 index 000000000..c454404f3 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAd.h @@ -0,0 +1,36 @@ +// +// GADNativeAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADNativeAdDelegate; + +/// Native ad base class. All native ad types are subclasses of this class. +@interface GADNativeAd : NSObject + +/// Optional delegate to receive state change notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Root view controller for handling ad actions. +@property(nonatomic, weak, GAD_NULLABLE) UIViewController *rootViewController; + +/// Dictionary of assets which aren't processed by the receiver. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDictionary *extraAssets; + +/// The ad network class name that fetched the current ad. For both standard and mediated Google +/// AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation +/// custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdDelegate.h new file mode 100755 index 000000000..e1b3ba3e0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdDelegate.h @@ -0,0 +1,57 @@ +// +// GADNativeAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeAd; + +GAD_ASSUME_NONNULL_BEGIN + +/// Identifies native ad assets. +@protocol GADNativeAdDelegate + +@optional + +#pragma mark Ad Lifecycle Events + +/// Called when an impression is recorded for an ad. Only called for Google ads and is not supported +/// for mediation ads. +- (void)nativeAdDidRecordImpression:(GADNativeAd *)nativeAd; + +/// Called when a click is recorded for an ad. Only called for Google ads and is not supported for +/// mediation ads. +- (void)nativeAdDidRecordClick:(GADNativeAd *)nativeAd; + +#pragma mark Click-Time Lifecycle Notifications + +/// Called just before presenting the user a full screen view, such as a browser, in response to +/// clicking on an ad. Use this opportunity to stop animations, time sensitive interactions, etc. +/// +/// Normally the user looks at the ad, dismisses it, and control returns to your application with +/// the nativeAdDidDismissScreen: message. However, if the user hits the Home button or clicks on an +/// App Store link, your application will end. The next method called will be the +/// applicationWillResignActive: of your UIApplicationDelegate object.Immediately after that, +/// nativeAdWillLeaveApplication: is called. +- (void)nativeAdWillPresentScreen:(GADNativeAd *)nativeAd; + +/// Called just before dismissing a full screen view. +- (void)nativeAdWillDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just after dismissing a full screen view. Use this opportunity to restart anything you +/// may have stopped as part of nativeAdWillPresentScreen:. +- (void)nativeAdDidDismissScreen:(GADNativeAd *)nativeAd; + +/// Called just before the application will go to the background or terminate due to an ad action +/// that will launch another application (such as the App Store). The normal UIApplicationDelegate +/// methods, like applicationDidEnterBackground:, will be called immediately before this. +- (void)nativeAdWillLeaveApplication:(GADNativeAd *)nativeAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage+Mediation.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage+Mediation.h new file mode 100755 index 000000000..971b71467 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage+Mediation.h @@ -0,0 +1,24 @@ +// +// GADNativeAdImage+Mediation.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Provides additional GADNativeAdImage initializers. +@interface GADNativeAdImage (MediationAdditions) + +/// Initializes and returns a native ad image object with the provided image. +- (instancetype)initWithImage:(UIImage *)image; + +/// Initializes and returns a native ad image object with the provided image URL and image scale. +- (instancetype)initWithURL:(NSURL *)URL scale:(CGFloat)scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage.h new file mode 100755 index 000000000..df4b48684 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImage.h @@ -0,0 +1,29 @@ +// +// GADNativeAdImage.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image. +@interface GADNativeAdImage : NSObject + +/// The image. If image autoloading is disabled, this property will be nil. +@property(nonatomic, readonly, strong, GAD_NULLABLE) UIImage *image; + +/// The image's URL. +@property(nonatomic, readonly, copy) NSURL *imageURL; + +/// The image's scale. +@property(nonatomic, readonly, assign) CGFloat scale; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImageAdLoaderOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImageAdLoaderOptions.h new file mode 100755 index 000000000..c2c9ea19c --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdImageAdLoaderOptions.h @@ -0,0 +1,37 @@ +// +// GADNativeAdImageAdLoaderOptions.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native ad image orientation preference. +typedef NS_ENUM(NSInteger, GADNativeAdImageAdLoaderOptionsOrientation) { + GADNativeAdImageAdLoaderOptionsOrientationAny, ///< No orientation preference. + GADNativeAdImageAdLoaderOptionsOrientationPortrait, ///< Prefer portrait images. + GADNativeAdImageAdLoaderOptionsOrientationLandscape ///< Prefer landscape images. +}; + +/// Ad loader options for native ad image settings. +@interface GADNativeAdImageAdLoaderOptions : GADAdLoaderOptions + +/// Indicates if image asset content should be loaded by the SDK. If set to YES, the SDK will not +/// load image asset content and native ad image URLs can be used to fetch content. Defaults to NO, +/// image assets are loaded by the SDK. +@property(nonatomic, assign) BOOL disableImageLoading; + +/// Indicates if multiple images should be loaded for each asset. Defaults to NO. +@property(nonatomic, assign) BOOL shouldRequestMultipleImages; + +/// Indicates preferred image orientation. Defaults to +/// GADNativeAdImageAdLoaderOptionsOrientationAny. +@property(nonatomic, assign) GADNativeAdImageAdLoaderOptionsOrientation preferredImageOrientation; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdViewAdOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdViewAdOptions.h new file mode 100755 index 000000000..cd22062c1 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAdViewAdOptions.h @@ -0,0 +1,29 @@ +// +// GADNativeAdViewAdOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Position of the AdChoices icon in the containing ad. +typedef NS_ENUM(NSInteger, GADAdChoicesPosition) { + GADAdChoicesPositionTopRightCorner, ///< Top right corner. + GADAdChoicesPositionTopLeftCorner, ///< Top left corner. + GADAdChoicesPositionBottomRightCorner, ///< Bottom right corner. + GADAdChoicesPositionBottomLeftCorner ///< Bottom Left Corner. +}; + +/// Ad loader options for configuring the view of native ads. +@interface GADNativeAdViewAdOptions : GADAdLoaderOptions + +/// Indicates preferred location of AdChoices icon. Default is GADAdChoicesPositionTopRightCorner. +@property(nonatomic, assign) GADAdChoicesPosition preferredAdChoicesPosition; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAppInstallAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAppInstallAd.h new file mode 100755 index 000000000..1f442c3fc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeAppInstallAd.h @@ -0,0 +1,97 @@ +// +// GADNativeAppInstallAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native app install ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeAppInstall (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeAppInstallAdRequestDelegate protocol. +@interface GADNativeAppInstallAd : GADNativeAd + +#pragma mark - Must be displayed + +/// App title. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Text that encourages user to take some action with the ad. For example "Install". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Application icon. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *icon; + +#pragma mark - Recommended to display + +/// App description. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; +/// The app store name. For example, "App Store". +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *store; +/// String representation of the app's price. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *price; +/// Array of GADNativeAdImage objects related to the advertised application. +@property(nonatomic, readonly, strong, GAD_NULLABLE) NSArray *images; +/// App store rating (0 to 5). +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSDecimalNumber *starRating; +/// Video controller for controlling video playback in GADNativeAppInstallAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeAppInstallAd +/// ads. +@protocol GADNativeAppInstallAdLoaderDelegate +/// Called when a native app install ad is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeAppInstallAd:(GADNativeAppInstallAd *)nativeAppInstallAd; +@end + +#pragma mark - Native App Install Ad View + +/// Base class for app install ad views. Your app install ad view must be a subclass of this class +/// and must call superclass methods for all overriden methods. +@interface GADNativeAppInstallAdView : UIView + +/// This property must point to the native app install ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeAppInstallAd *nativeAppInstallAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's icon asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *iconView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's store asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *storeView; +/// Weak reference to your ad view's price asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *priceView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's star rating asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *starRatingView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeAppInstallAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeContentAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeContentAd.h new file mode 100755 index 000000000..fcb87cd65 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeContentAd.h @@ -0,0 +1,89 @@ +// +// GADNativeContentAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +#pragma mark - Native Content Ad Assets + +/// Native content ad. To request this ad type, you need to pass kGADAdLoaderAdTypeNativeContent +/// (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in GADAdLoader's initializer method. If +/// you request this ad type, your delegate must conform to the GADNativeContentAdRequestDelegate +/// protocol. +@interface GADNativeContentAd : GADNativeAd + +#pragma mark - Must be displayed + +/// Primary text headline. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *headline; +/// Secondary text. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *body; + +#pragma mark - Recommended to display + +/// Large images. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSArray *images; +/// Small logo image. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADNativeAdImage *logo; +/// Text that encourages user to take some action with the ad. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *callToAction; +/// Identifies the advertiser. For example, the advertiser’s name or visible URL. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *advertiser; +/// Video controller for controlling video playback in GADNativeContentAdView's mediaView. +@property(nonatomic, strong, readonly) GADVideoController *videoController; +@end + +#pragma mark - Protocol and constants + +/// The delegate of a GADAdLoader object implements this protocol to receive GADNativeContentAd ads. +@protocol GADNativeContentAdLoaderDelegate +/// Called when native content is received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeContentAd:(GADNativeContentAd *)nativeContentAd; +@end + +#pragma mark - Native Content Ad View + +/// Base class for content ad views. Your content ad view must be a subclass of this class and must +/// call superclass methods for all overriden methods. +@interface GADNativeContentAdView : UIView + +/// This property must point to the native content ad object rendered by this ad view. +@property(nonatomic, strong, GAD_NULLABLE) GADNativeContentAd *nativeContentAd; + +/// Weak reference to your ad view's headline asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *headlineView; +/// Weak reference to your ad view's body asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *bodyView; +/// Weak reference to your ad view's image asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *imageView; +/// Weak reference to your ad view's logo asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *logoView; +/// Weak reference to your ad view's call to action asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *callToActionView; +/// Weak reference to your ad view's advertiser asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIView *advertiserView; +/// Weak reference to your ad view's media asset view. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADMediaView *mediaView; +/// Weak reference to your ad view's AdChoices view. Must set adChoicesView before setting +/// nativeContentAd, otherwise AdChoices will be rendered in the publisher's +/// preferredAdChoicesPosition as defined in GADNativeAdViewAdOptions. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet GADAdChoicesView *adChoicesView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeCustomTemplateAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeCustomTemplateAd.h new file mode 100755 index 000000000..fef98aca9 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeCustomTemplateAd.h @@ -0,0 +1,74 @@ +// +// GADNativeCustomTemplateAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Native custom template ad. To request this ad type, you need to pass +/// kGADAdLoaderAdTypeNativeCustomTemplate (see GADAdLoaderAdTypes.h) to the |adTypes| parameter in +/// GADAdLoader's initializer method. If you request this ad type, your delegate must conform to the +/// GADNativeCustomTemplateAdLoaderDelegate protocol. +@interface GADNativeCustomTemplateAd : GADNativeAd + +/// The ad's custom template ID. +@property(nonatomic, readonly) NSString *templateID; + +/// Array of available asset keys. +@property(nonatomic, readonly) NSArray *availableAssetKeys; + +/// Returns video controller for controlling receiver's video. +@property(nonatomic, readonly, strong) GADVideoController *videoController; + +/// Returns media view for rendering video loaded by the receiver. Returns nil if receiver doesn't +/// has a video. +@property(nonatomic, readonly, strong, GAD_NULLABLE) GADMediaView *mediaView; + +/// Returns the native ad image corresponding to the specified key or nil if the image is not +/// available. +- (GADNativeAdImage *GAD_NULLABLE_TYPE)imageForKey:(NSString *)key; + +/// Returns the string corresponding to the specified key or nil if the string is not available. +- (NSString *GAD_NULLABLE_TYPE)stringForKey:(NSString *)key; + +/// Call when the user clicks on the ad. Provide the asset key that best matches the asset the user +/// interacted with. Provide |customClickHandler| only if this template is configured with a custom +/// click action, otherwise pass in nil. If a block is provided, the ad's built-in click actions are +/// ignored and |customClickHandler| is executed after recording the click. +- (void)performClickOnAssetWithKey:(NSString *)assetKey + customClickHandler:(dispatch_block_t GAD_NULLABLE_TYPE)customClickHandler; + +/// Call when the ad is displayed on screen to the user. Can be called multiple times. Only the +/// first impression is recorded. +- (void)recordImpression; + +@end + +#pragma mark - Loading Protocol + +/// The delegate of a GADAdLoader object implements this protocol to receive +/// GADNativeCustomTemplateAd ads. +@protocol GADNativeCustomTemplateAdLoaderDelegate + +/// Called when requesting an ad. Asks the delegate for an array of custom template ID strings. +- (NSArray *)nativeCustomTemplateIDsForAdLoader:(GADAdLoader *)adLoader; + +/// Tells the delegate that a native custom template ad was received. +- (void)adLoader:(GADAdLoader *)adLoader + didReceiveNativeCustomTemplateAd:(GADNativeCustomTemplateAd *)nativeCustomTemplateAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdView.h new file mode 100755 index 000000000..2eeb67c9b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdView.h @@ -0,0 +1,96 @@ +// +// GADNativeExpressAdView.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The view that displays native ads. A minimum implementation to get an ad from within a +/// UIViewController class is: +/// +///
+///   // Create and setup the ad view, specifying the size and origin at {0, 0}.
+///   GADNativeExpressAdView *adView =
+///       [[GADNativeExpressAdView alloc] initWithAdSize:kGADAdSizeBanner];
+///   adView.rootViewController = self;
+///   adView.adUnitID = @"ID created when registering your app";
+///   // Place the ad view onto the screen.
+///   [self.view addSubview:adView];
+///   // Request an ad without any additional targeting information.
+///   [adView loadRequest:[GADRequest request]];
+///   
+@interface GADNativeExpressAdView : UIView + +#pragma mark - Initialization + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at +/// |origin| relative to its superview bounds. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize origin:(CGPoint)origin; + +/// Returns an initialized GADNativeExpressAdView instance set to |adSize| and positioned at the top +/// left of its superview. Returns nil if |adSize| is an invalid ad size. +- (instancetype GAD_NULLABLE_TYPE)initWithAdSize:(GADAdSize)adSize; + +/// Video controller for controlling video rendered by this native express ad view. +@property(nonatomic, strong, readonly) GADVideoController *videoController; + +#pragma mark - Pre-Request + +/// Required value created on the AdMob website. Create a new ad unit for every unique placement of +/// an ad in your application. Set this to the ID assigned for this placement. Ad units are +/// important for targeting and statistics. +/// +/// Example AdMob ad unit ID: @"ca-app-pub-0123456789012345/0123456789" +@property(nonatomic, copy, GAD_NULLABLE) IBInspectable NSString *adUnitID; + +/// Required reference to the current root view controller. For example, the root view controller in +/// a tab-based application would be the UITabViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet UIViewController *rootViewController; + +/// Required to set this native ad view to a proper size. Never create your own GADAdSize directly. +/// Use one of the predefined standard ad sizes (such as kGADAdSizeBanner), or create one using the +/// GADAdSizeFromCGSize method. If you are not using mediation, changing the adSize after an ad has +/// been shown will cause a new request (for an ad of the new size) to be sent. If you are using +/// mediation, then a new request may not be sent. +@property(nonatomic, assign) GADAdSize adSize; + +/// Optional delegate object that receives state change notifications from this +/// GADNativeExpressAdView. Typically this is a UIViewController. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id delegate; + +/// A Boolean value that determines whether autoloading of ads in the receiver is enabled. If +/// enabled, you do not need to call the loadRequest: method to load ads. +@property(nonatomic, assign, getter=isAutoloadEnabled) IBInspectable BOOL autoloadEnabled; + +/// Sets options that configure ad loading. +/// +/// @param adOptions An array of GADAdLoaderOptions objects. The array is deep copied and option +/// objects cannot be modified after calling this method. +- (void)setAdOptions:(NSArray *)adOptions; + +#pragma mark - Making an Ad Request + +/// Makes an ad request. The request object supplies targeting information. +- (void)loadRequest:(GADRequest *GAD_NULLABLE_TYPE)request; + +#pragma mark - Mediation + +/// The name of the ad network adapter class that fetched the current ad. Returns nil while the +/// latest ad request is in progress or if the latest ad request failed. For both standard and +/// mediated Google AdMob ads, this method returns @"GADMAdapterGoogleAdMobAds". For ads fetched via +/// mediation custom events, this method returns @"GADMAdapterCustomEvents". +@property(nonatomic, readonly, weak, GAD_NULLABLE) NSString *adNetworkClassName; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdViewDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdViewDelegate.h new file mode 100755 index 000000000..73bd5e0bb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADNativeExpressAdViewDelegate.h @@ -0,0 +1,54 @@ +// +// GADNativeExpressAdViewDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADNativeExpressAdView; +@class GADRequestError; + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate methods for receiving GADNativeExpressAdView state change messages such as ad request +/// status and ad click lifecycle. +@protocol GADNativeExpressAdViewDelegate + +@optional + +#pragma mark Ad Request Lifecycle Notifications + +/// Tells the delegate that the native express ad view successfully received an ad. The delegate may +/// want to add the native express ad view to the view hierarchy if it hasn't been added yet. +- (void)nativeExpressAdViewDidReceiveAd:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that an ad request failed. The failure is normally due to network +/// connectivity or ad availablility (i.e., no fill). +- (void)nativeExpressAdView:(GADNativeExpressAdView *)nativeExpressAdView + didFailToReceiveAdWithError:(GADRequestError *)error; + +#pragma mark Click-Time Lifecycle Notifications + +/// Tells the delegate that a full screen view will be presented in response to the user clicking on +/// an ad. The delegate may want to pause animations and time sensitive interactions. +- (void)nativeExpressAdViewWillPresentScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view will be dismissed. +- (void)nativeExpressAdViewWillDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the full screen view has been dismissed. The delegate should restart +/// anything paused while handling adViewWillPresentScreen:. +- (void)nativeExpressAdViewDidDismissScreen:(GADNativeExpressAdView *)nativeExpressAdView; + +/// Tells the delegate that the user click will open another app, backgrounding the current +/// application. The standard UIApplicationDelegate methods, like applicationDidEnterBackground:, +/// are called immediately before this method is called. +- (void)nativeExpressAdViewWillLeaveApplication:(GADNativeExpressAdView *)nativeExpressAdView; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequest.h new file mode 100755 index 000000000..422ba55ae --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequest.h @@ -0,0 +1,127 @@ +// +// GADRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Add this constant to the testDevices property's array to receive test ads on the simulator. +GAD_EXTERN const id kGADSimulatorID; + +/// Genders to help deliver more relevant ads. +typedef NS_ENUM(NSInteger, GADGender) { + kGADGenderUnknown, ///< Unknown gender. + kGADGenderMale, ///< Male gender. + kGADGenderFemale ///< Female gender. +}; + +/// Specifies optional parameters for ad requests. +@interface GADRequest : NSObject + +/// Returns a default request. ++ (instancetype)request; + +#pragma mark Additional Parameters For Ad Networks + +/// Ad networks may have additional parameters they accept. To pass these parameters to them, create +/// the ad network extras object for that network, fill in the parameters, and register it here. The +/// ad network should have a header defining the interface for the 'extras' object to create. All +/// networks will have access to the basic settings you've set in this GADRequest (gender, birthday, +/// testing mode, etc.). If you register an extras object that is the same class as one you have +/// registered before, the previous extras will be overwritten. +- (void)registerAdNetworkExtras:(id)extras; + +/// Returns the network extras defined for an ad network. +- (id GAD_NULLABLE_TYPE)adNetworkExtrasFor:(Class)aClass; + +/// Removes the extras for an ad network. |aClass| is the class which represents that network's +/// extras type. +- (void)removeAdNetworkExtrasFor:(Class)aClass; + +#pragma mark Collecting SDK Information + +/// Returns the version of the SDK. ++ (NSString *)sdkVersion; + +#pragma mark Testing + +/// Test ads will be returned for devices with device IDs specified in this array. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *testDevices; + +#pragma mark User Information + +/// Provide the user's gender to increase ad relevancy. +@property(nonatomic, assign) GADGender gender; + +/// Provide the user's birthday to increase ad relevancy. +@property(nonatomic, copy, GAD_NULLABLE) NSDate *birthday; + +/// The user's current location may be used to deliver more relevant ads. However do not use Core +/// Location just for advertising, make sure it is used for more beneficial reasons as well. It is +/// both a good idea and part of Apple's guidelines. +- (void)setLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + accuracy:(CGFloat)accuracyInMeters; + +/// [Optional] This method allows you to specify whether you would like your app to be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA), +/// http:///business.ftc.gov/privacy-and-security/childrens-privacy. +/// +/// If you call this method with YES, you are indicating that your app should be treated as +/// child-directed for purposes of the Children’s Online Privacy Protection Act (COPPA). If you call +/// this method with NO, you are indicating that your app should not be treated as child-directed +/// for purposes of the Children’s Online Privacy Protection Act (COPPA). If you do not call this +/// method, ad requests will include no indication of how you would like your app treated with +/// respect to COPPA. +/// +/// By setting this method, you certify that this notification is accurate and you are authorized to +/// act on behalf of the owner of the app. You understand that abuse of this setting may result in +/// termination of your Google account. +/// +/// It may take some time for this designation to be fully implemented in applicable Google +/// services. This designation will only apply to ad requests for which you have set this method. +- (void)tagForChildDirectedTreatment:(BOOL)childDirectedTreatment; + +#pragma mark Contextual Information + +/// Array of keyword strings. Keywords are words or phrases describing the current user activity +/// such as @"Sports Scores" or @"Football". Set this property to nil to clear the keywords. +@property(nonatomic, copy, GAD_NULLABLE) NSArray *keywords; + +/// URL string for a webpage whose content matches the app content. This webpage content is used for +/// targeting purposes. +@property(nonatomic, copy, GAD_NULLABLE) NSString *contentURL; + +#pragma mark Request Agent Information + +/// String that identifies the ad request's origin. Third party libraries that reference the Mobile +/// Ads SDK should set this property to denote the platform from which the ad request originated. +/// For example, a third party ad network called "CoolAds network" that is mediating requests to the +/// Mobile Ads SDK should set this property as "CoolAds". +@property(nonatomic, copy, GAD_NULLABLE) NSString *requestAgent; + +#pragma mark Deprecated Methods + +/// Provide the user's birthday to increase ad relevancy. +- (void)setBirthdayWithMonth:(NSInteger)month + day:(NSInteger)day + year:(NSInteger)year + GAD_DEPRECATED_MSG_ATTRIBUTE(" use the birthday property."); + +/// When Core Location isn't available but the user's location is known supplying it here may +/// deliver more relevant ads. It can be any free-form text such as @"Champs-Elysees Paris" or +/// @"94041 US". +- (void)setLocationWithDescription:(NSString *GAD_NULLABLE_TYPE)locationDescription + GAD_DEPRECATED_MSG_ATTRIBUTE(" use setLocationWithLatitude:longitude:accuracy:."); + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequestError.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequestError.h new file mode 100755 index 000000000..b38dcbe89 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRequestError.h @@ -0,0 +1,70 @@ +// +// GADRequestError.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import + +#import + +@class GADRequest; + +GAD_ASSUME_NONNULL_BEGIN + +/// Google AdMob Ads error domain. +GAD_EXTERN NSString *const kGADErrorDomain; + +/// NSError codes for GAD error domain. +typedef NS_ENUM(NSInteger, GADErrorCode) { + /// The ad request is invalid. The localizedFailureReason error description will have more + /// details. Typically this is because the ad did not have the ad unit ID or root view + /// controller set. + kGADErrorInvalidRequest, + + /// The ad request was successful, but no ad was returned. + kGADErrorNoFill, + + /// There was an error loading data from the network. + kGADErrorNetworkError, + + /// The ad server experienced a failure processing the request. + kGADErrorServerError, + + /// The current device's OS is below the minimum required version. + kGADErrorOSVersionTooLow, + + /// The request was unable to be loaded before being timed out. + kGADErrorTimeout, + + /// Will not send request because the interstitial object has already been used. + kGADErrorInterstitialAlreadyUsed, + + /// The mediation response was invalid. + kGADErrorMediationDataError, + + /// Error finding or creating a mediation ad network adapter. + kGADErrorMediationAdapterError, + + /// The mediation request was successful, but no ad was returned from any ad networks. + kGADErrorMediationNoFill, + + /// Attempting to pass an invalid ad size to an adapter. + kGADErrorMediationInvalidAdSize, + + /// Internal error. + kGADErrorInternalError, + + /// Invalid argument error. + kGADErrorInvalidArgument, + + /// Received invalid response. + kGADErrorReceivedInvalidResponse +}; + +/// Represents the error generated due to invalid request parameters. +@interface GADRequestError : NSError +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAd.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAd.h new file mode 100755 index 000000000..806f80bec --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAd.h @@ -0,0 +1,47 @@ +// +// GADRewardBasedVideoAd.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +@protocol GADRewardBasedVideoAdDelegate; + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADRewardBasedVideoAd class is used for requesting and presenting a reward based video ad. +/// This class isn't thread safe. +@interface GADRewardBasedVideoAd : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Indicates if the receiver is ready to be presented full screen. +@property(nonatomic, readonly, getter=isReady) BOOL ready; + +/// The ad network class name that fetched the current ad. Returns nil while the latest ad request +/// is in progress or if the latest ad request failed. For both standard and mediated Google AdMob +/// ads, this property returns @"GADMAdapterGoogleAdMobAds". For ads fetched via mediation custom +/// events, this property returns the mediated custom event adapter. +@property(nonatomic, readonly, copy, GAD_NULLABLE) NSString *adNetworkClassName; + +/// Returns the shared GADRewardBasedVideoAd instance. ++ (GADRewardBasedVideoAd *)sharedInstance; + +/// Initiates the request to fetch the reward based video ad. The |request| object supplies ad +/// targeting information and must not be nil. The adUnitID is the ad unit id used for fetching an +/// ad and must not be nil. +- (void)loadRequest:(GADRequest *)request withAdUnitID:(NSString *)adUnitID; + +/// Presents the reward based video ad with the provided view controller. +- (void)presentFromRootViewController:(UIViewController *)viewController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAdDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAdDelegate.h new file mode 100755 index 000000000..f81dd5922 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADRewardBasedVideoAdDelegate.h @@ -0,0 +1,49 @@ +// +// GADRewardBasedVideoAdDelegate.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google Inc. All rights reserved. +// + +#import + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Delegate for receiving state change messages from a GADRewardBasedVideoAd such as ad requests +/// succeeding/failing. +@protocol GADRewardBasedVideoAdDelegate + +@required + +/// Tells the delegate that the reward based video ad has rewarded the user. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +@optional + +/// Tells the delegate that the reward based video ad failed to load. +- (void)rewardBasedVideoAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd + didFailToLoadWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was received. +- (void)rewardBasedVideoAdDidReceiveAd:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad opened. +- (void)rewardBasedVideoAdDidOpen:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad started playing. +- (void)rewardBasedVideoAdDidStartPlaying:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad closed. +- (void)rewardBasedVideoAdDidClose:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +/// Tells the delegate that the reward based video ad will leave the application. +- (void)rewardBasedVideoAdWillLeaveApplication:(GADRewardBasedVideoAd *)rewardBasedVideoAd; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchBannerView.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchBannerView.h new file mode 100755 index 000000000..590b2770e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchBannerView.h @@ -0,0 +1,27 @@ +// +// GADSearchBannerView.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// A view that displays search ads. +/// To show search ads: +/// 1) Create a GADSearchBannerView and add it to your view controller's view hierarchy. +/// 2) Create a GADSearchRequest ad request object to hold the search query and other search data. +/// 3) Call GADSearchBannerView's -loadRequest: method with the GADSearchRequest object. +@interface GADSearchBannerView : GADBannerView + +/// If the banner view is initialized with kGADAdSizeFluid and the corresponding request is created +/// with dynamic height parameters, this delegate will be called when the ad size changes. +@property(nonatomic, weak, GAD_NULLABLE) IBOutlet id adSizeDelegate; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchRequest.h new file mode 100755 index 000000000..34fb68bd0 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADSearchRequest.h @@ -0,0 +1,77 @@ +// +// GADSearchRequest.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google Inc. All rights reserved. +// + +#import +#import + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Search ad border types. +typedef NS_ENUM(NSUInteger, GADSearchBorderType) { + kGADSearchBorderTypeNone, ///< No border. + kGADSearchBorderTypeDashed, ///< Dashed line border. + kGADSearchBorderTypeDotted, ///< Dotted line border. + kGADSearchBorderTypeSolid ///< Solid line border. +}; + +/// Search ad call button color types. +typedef NS_ENUM(NSUInteger, GADSearchCallButtonColor) { + kGADSearchCallButtonLight, ///< Light button color. + kGADSearchCallButtonMedium, ///< Medium button color. + kGADSearchCallButtonDark ///< Dark button color. +}; + +/// Specifies parameters for search ads. +@interface GADSearchRequest : GADRequest + +/// The search ad query. +@property(nonatomic, copy, GAD_NULLABLE) NSString *query; +/// The search ad background color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *backgroundColor; +/// The search ad gradient "from" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientFrom; +/// The search ad gradient "to" color. +@property(nonatomic, readonly, copy, GAD_NULLABLE) UIColor *gradientTo; +/// The search ad header color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *headerColor; +/// The search ad description text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *descriptionTextColor; +/// The search ad anchor text color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *anchorTextColor; +/// The search ad text font family. +@property(nonatomic, copy, GAD_NULLABLE) NSString *fontFamily; +/// The search ad header text size. +@property(nonatomic, assign) NSUInteger headerTextSize; +/// The search ad border color. +@property(nonatomic, copy, GAD_NULLABLE) UIColor *borderColor; +/// The search ad border type. +@property(nonatomic, assign) GADSearchBorderType borderType; +/// The search ad border thickness. +@property(nonatomic, assign) NSUInteger borderThickness; +/// The search ad custom channels. +@property(nonatomic, copy, GAD_NULLABLE) NSString *customChannels; +/// The search ad call button color. +@property(nonatomic, assign) GADSearchCallButtonColor callButtonColor; + +/// A solid background color for rendering the ad. The background of the ad +/// can either be a solid color, or a gradient, which can be specified through +/// setBackgroundGradientFrom:toColor: method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundSolid:(UIColor *)color; + +/// A linear gradient background color for rendering the ad. The background of +/// the ad can either be a linear gradient, or a solid color, which can be +/// specified through setBackgroundSolid method. If both solid and gradient +/// background is requested, only the latter is considered. +- (void)setBackgroundGradientFrom:(UIColor *)from toColor:(UIColor *)toColor; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoController.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoController.h new file mode 100755 index 000000000..a3d3e66cc --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoController.h @@ -0,0 +1,35 @@ +// +// GADVideoController.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +#import + +GAD_ASSUME_NONNULL_BEGIN + +@protocol GADVideoControllerDelegate; + +/// The video controller class provides a way to get the video metadata and also manages video +/// content of the ad rendered by the Google Mobile Ads SDK. You don't need to create an instance of +/// this class. When the ad rendered by the Google Mobile Ads SDK loads video content, you may be +/// able to get an instance of this class from the rendered ad object. Currently only native express +/// ad view class exposes video controller. +@interface GADVideoController : NSObject + +/// Delegate for receiving video notifications. +@property(nonatomic, weak, GAD_NULLABLE) id delegate; + +/// Returns a Boolean indicating if the receiver has video content. +- (BOOL)hasVideoContent; + +/// Returns the video's aspect ratio (width/height) or 0 if no video is present. +- (double)aspectRatio; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoControllerDelegate.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoControllerDelegate.h new file mode 100755 index 000000000..cd5c0487e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoControllerDelegate.h @@ -0,0 +1,25 @@ +// +// GADVideoControllerDelegate.h +// Google Mobile Ads SDK +// +// Copyright (c) 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// The GADVideoControllerDelegate protocol defines methods that are called by the video controller +/// object in response to the video events that occured throught the lifetime of the video rendered +/// by an ad. +@protocol GADVideoControllerDelegate + +@optional + +/// Tells the delegate that the video controller's video playback has ended. +- (void)videoControllerDidEndVideoPlayback:(GADVideoController *)videoController; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoOptions.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoOptions.h new file mode 100755 index 000000000..2f75a37d7 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GADVideoOptions.h @@ -0,0 +1,21 @@ +// +// GADVideoOptions.h +// Google Mobile Ads SDK +// +// Copyright 2016 Google Inc. All rights reserved. +// + +#import +#import + +GAD_ASSUME_NONNULL_BEGIN + +/// Video ad options. +@interface GADVideoOptions : GADAdLoaderOptions + +/// Indicates if videos should start muted. +@property(nonatomic, assign) BOOL startMuted; + +@end + +GAD_ASSUME_NONNULL_END diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAds.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAds.h new file mode 100755 index 000000000..7c0df6121 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAds.h @@ -0,0 +1,96 @@ +// +// GoogleMobileAds.h +// Google Mobile Ads SDK +// +// Copyright 2014 Google Inc. All rights reserved. + +#import +#import + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0 +#error The Google Mobile Ads SDK requires a deployment target of iOS 6.0 or later. +#endif + +/// Project version string for GoogleMobileAds. +FOUNDATION_EXPORT const unsigned char GoogleMobileAdsVersionString[]; + +// Header files. +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import + +#import +#import +#import + +#import +#import +#import +#import +#import +#import diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAdsDefines.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAdsDefines.h new file mode 100755 index 000000000..229ffd898 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/GoogleMobileAdsDefines.h @@ -0,0 +1,56 @@ +// +// GoogleMobileAdsDefines.h +// Google Mobile Ads SDK +// +// Copyright (c) 2015 Google Inc. All rights reserved. +// + +#import + +#if defined(__cplusplus) +#define GAD_EXTERN extern "C" __attribute__((visibility("default"))) +#else +#define GAD_EXTERN extern __attribute__((visibility("default"))) +#endif // defined(__cplusplus) + +#if defined(__has_feature) && defined(__has_attribute) +#if __has_feature(attribute_GAD_DEPRECATED_with_message) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated(s))) +#elif __has_attribute(deprecated) +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // __has_feature(attribute_GAD_DEPRECATED_with_message) +#if __has_attribute(deprecated) +#define GAD_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#endif // __has_attribute(deprecated) +#else +#define GAD_DEPRECATED_ATTRIBUTE +#define GAD_DEPRECATED_MSG_ATTRIBUTE(s) +#endif // defined(__has_feature) && defined(__has_attribute) + +#ifndef IBInspectable +#define IBInspectable +#endif + +#if __has_feature(nullability) // Available starting in Xcode 6.3. +#define GAD_NULLABLE_TYPE __nullable +#define GAD_NONNULL_TYPE __nonnull +#define GAD_NULLABLE nullable +#define GAD_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +#else +#define GAD_NULLABLE_TYPE +#define GAD_NONNULL_TYPE +#define GAD_NULLABLE +#define GAD_ASSUME_NONNULL_BEGIN +#define GAD_ASSUME_NONNULL_END +#endif // __has_feature(nullability) + +#if __has_attribute(objc_boxable) // Available starting in Xcode 7.3. +#define GAD_BOXABLE __attribute__((objc_boxable)) +#else +#define GAD_BOXABLE +#endif // __has_attribute(objc_boxable) diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..f5ee207cb --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkAdapterProtocol.h @@ -0,0 +1,104 @@ +// +// GADMAdNetworkAdapterProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +#import "GADMAdNetworkConnectorProtocol.h" +#import "GADMEnums.h" + +/// Subclasses should prefix their name with "GADMAdapter" example: GADMAdapterGoogleAdMobAds +#define kGADMAdapterClassNamePrefix @"GADMAdapter" + +@protocol GADMAdNetworkConnector; + +/// Ad network adapter protocol. +@protocol GADMAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Designated initializer. Implementing classes can and should keep the connector in an instance +/// variable. However you must never retain the connector, as doing so will create a circular +/// reference and cause memory leaks. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector; + +/// Asks the adapter to initiate a banner ad request. The adapter does not need to return anything. +/// The assumption is that the adapter will start an asynchronous ad fetch over the network. Your +/// adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does not support +/// the given ad size, or does not support banner ads, call back to the adapter:didFailAd: method of +/// the connector. +- (void)getBannerWithSize:(GADAdSize)adSize; + +/// Asks the adapter to initiate an interstitial ad request. The adapter does not need to return +/// anything. The assumption is that the adapter will start an asynchronous ad fetch over the +/// network. Your adapter may act as a delegate to your SDK to listen to callbacks. If your SDK does +/// not support interstitials, call back to the adapter:didFailInterstitial: method of the +/// connector. +- (void)getInterstitial; + +/// When called, the adapter must remove itself as a delegate or notification observer from the +/// underlying ad network SDK. You should also call this method in your adapter dealloc, so when +/// your adapter goes away, your SDK will not call a freed object. This function should be +/// idempotent and should not crash regardless of when or how many times the method is called. +- (void)stopBeingDelegate; + +/// Some ad transition types may cause issues with particular Ad SDKs. The adapter may decide +/// whether the given animation type is OK. Defaults to YES. +- (BOOL)isBannerAnimationOK:(GADMBannerAnimationType)animType; + +/// Present an interstitial using the supplied UIViewController, by calling +/// presentViewController:animated:completion:. +/// +/// Your interstitial should not immediately present itself when it is received. Instead, you should +/// wait until this method is called on your adapter to present the interstitial. +/// +/// Make sure to call adapterWillPresentInterstitial: on the connector when the interstitial is +/// about to be presented, and adapterWillDismissInterstitial: and adapterDidDismissInterstitial: +/// when the interstitial is being dismissed. +- (void)presentInterstitialFromRootViewController:(UIViewController *)rootViewController; + +@optional + +/// Starts request for a native ad. |adTypes| contains the list of native ad types requested. See +/// GADAdLoaderAdTypes.h for available ad types. |options| are any additional options configured by +/// the publisher for requesting a native ad. See GADNativeAdImageAdLoaderOptions.h for available +/// image options. When this method is called the receiver may start native ad request +/// asynchronously. On completion the receiver should notify the Google Mobile Ads SDK with a native +/// ad object using the receiver's connector method +/// adapter:didReceiveNativeAdDataSource:mediationDelegate or adapter:didFailAd: if the ad request +/// encountered an error. +- (void)getNativeAdWithAdTypes:(NSArray *)adTypes options:(NSArray *)options; + +/// Indicates if the adapter handles user clicks. If this method returns YES, the adapter must +/// handle user clicks and notify the Google Mobile Ads SDK of clicks using +/// +[GADMediatedNativeAdNotificationSource mediatedNativeAdDidRecordClick:]. If this method returns +/// NO, the Google Mobile Ads SDK handles user clicks and notifies the adapter of clicks using +/// -[GADMediatedNativeAdDelegate +/// mediatedNativeAd:didRecordClickOnAssetWithName:view:viewController:]. +- (BOOL)handlesUserClicks; + +/// Indicates if the adapter handles user impressions tracking. If this method returns YES, the +/// Google Mobile Ads SDK will not track user impressions and the adapter must notify the +/// Google Mobile Ads SDK of impressions using +[GADMediatedNativeAdNotificationSource +/// mediatedNativeAdDidRecordImpression:]. If this method returns NO, +/// the Google Mobile Ads SDK tracks user impressions and notifies the adapter of impressions +/// using -[GADMediatedNativeAdDelegate mediatedNativeAdDidRecordImpression:]. +- (BOOL)handlesUserImpressions; + +/// If your ad network handles multiple ad sizes for the same banner ad, implement this method to +/// know when the user changes the banner size. This is typically changing from +/// kGADAdSizeSmartBannerPortrait to kGADAdSizeSmartBannerLandscape, or vice versa. If this method +/// is not implemented, every time the user changes the ad size, a new ad will be requested with the +/// new size by calling your getBannerWithSize: method. +- (void)changeAdSizeTo:(GADAdSize)adSize; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..075ca3cea --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMAdNetworkConnectorProtocol.h @@ -0,0 +1,87 @@ +// +// GADMAdNetworkConnectorProtocol.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import +#import + +#import "GADMediationAdRequest.h" + +@protocol GADMAdNetworkAdapter; + +/// Ad network adapters interact with the mediation SDK using an object that implements the +/// GADMAdNetworkConnector protocol. The connector object can be used to obtain necessary +/// information for ad requests, and to call back to the mediation SDK on ad request returns and +/// user interactions. +@protocol GADMAdNetworkConnector + +/// When you need to show a landing page or any other modal view, such as when a user clicks or when +/// your Ads SDK needs to show an interstitial, use this method to obtain a UIViewController that +/// you can use to show your modal view. Call the -presentViewController:animated:completion: method +/// of the returned UIViewController . +- (UIViewController *)viewControllerForPresentingModalView; + +#pragma mark - Adapter Callbacks + +/// Tells the connector that the adapter failed to receive an ad. +- (void)adapter:(id)adapter didFailAd:(NSError *)error; + +/// Tells the connector that the adapter received a banner ad. +- (void)adapter:(id)adapter didReceiveAdView:(UIView *)view; + +/// Tells the connector that the adapter received an interstitial. +- (void)adapterDidReceiveInterstitial:(id)adapter; + +/// Tells the connector that the adapter has received a mediated native ad. |mediatedNativeAd| is +/// used by the Google Mobile Ads SDK for constructing a native ad object. +- (void)adapter:(id)adapter + didReceiveMediatedNativeAd:(id)mediatedNativeAd; + +#pragma mark Ad events + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner or +// interstitial ad. + +/// Tells the connector that the adapter recorded a user click. +- (void)adapterDidGetAdClick:(id)adapter; +/// Tells the connector that the adapter will leave the application because of a user action. +- (void)adapterWillLeaveApplication:(id)adapter; + +// Adapter should call as many of these as possible, during the lifecycle of the loaded banner ad. + +/// Tells the connector that the adapter will present a full screen modal. +- (void)adapterWillPresentFullScreenModal:(id)adapter; +/// Tells the connector that the adapter will dismiss a full screen modal. +- (void)adapterWillDismissFullScreenModal:(id)adapter; +/// Tells the connector that the adapter dismissed a full screen modal. +- (void)adapterDidDismissFullScreenModal:(id)adapter; + +// Adapter should call these methods during the lifecycle of the loaded interstitial ad. + +/// Tells the connector that the adapter will present an interstitial. +- (void)adapterWillPresentInterstitial:(id)adapter; +/// Tells the connector that the adapter will dismiss an interstitial. +- (void)adapterWillDismissInterstitial:(id)adapter; +/// Tells the connector that the adapter did dismiss an interstitial. +- (void)adapterDidDismissInterstitial:(id)adapter; + +#pragma mark Deprecated + +/// Deprecated. Use -adapterDidReceiveInterstitial:. +- (void)adapter:(id)adapter + didReceiveInterstitial:(NSObject *)interstitial + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidReceiveInterstitial:."); + +/// Deprecated. Use -adapterDidGetAdClick:. +- (void)adapter:(id)adapter + clickDidOccurInBanner:(UIView *)view + GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapterDidGetAdClick:."); + +/// Deprecated. Use -adapter:didFailAd:. +- (void)adapter:(id)adapter + didFailInterstitial:(NSError *)error GAD_DEPRECATED_MSG_ATTRIBUTE("Use -adapter:didFailAd:"); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMEnums.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMEnums.h new file mode 100755 index 000000000..1802598c2 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMEnums.h @@ -0,0 +1,21 @@ +// +// GADMEnums.h +// Google Mobile Ads SDK +// +// Copyright 2011 Google. All rights reserved. +// + +#import + +/// These are the types of animation we employ for transitions between two mediated ads. +typedef NS_ENUM(NSInteger, GADMBannerAnimationType) { + kGADMBannerAnimationTypeNone = 0, ///< No animation. + kGADMBannerAnimationTypeFlipFromLeft = 1, ///< Flip from left. + kGADMBannerAnimationTypeFlipFromRight = 2, ///< Flip from right. + kGADMBannerAnimationTypeCurlUp = 3, ///< Curl up. + kGADMBannerAnimationTypeCurlDown = 4, ///< Curl down. + kGADMBannerAnimationTypeSlideFromLeft = 5, ///< Slide from left. + kGADMBannerAnimationTypeSlideFromRight = 6, ///< Slide from right. + kGADMBannerAnimationTypeFadeIn = 7, ///< Fade in. + kGADMBannerAnimationTypeRandom = 8, ///< Random animation. +}; diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h new file mode 100755 index 000000000..63eb5072e --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkAdapterProtocol.h @@ -0,0 +1,59 @@ +// +// GADMRewardBasedVideoAdNetworkAdapter.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMRewardBasedVideoAdNetworkConnector; + +/// Your adapter must conform to this protocol to provide reward based video ads. +@protocol GADMRewardBasedVideoAdNetworkAdapter + +/// Returns a version string for the adapter. It can be any string that uniquely identifies the +/// version of your adapter. For example, "1.0", or simply a date such as "20110915". ++ (NSString *)adapterVersion; + +/// The extras class that is used to specify additional parameters for a request to this ad network. +/// Returns Nil if the network does not have extra settings for publishers to send. ++ (Class)networkExtrasClass; + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithRewardBasedVideoAdNetworkConnector: + (id)connector; + +/// Tells the adapter to set up reward based video ads. The adapter should notify the Google Mobile +/// Ads SDK whether set up has succeeded or failed using callbacks provided in the connector. When +/// set up fails, the Google Mobile Ads SDK may try to set up the adapter again. +- (void)setUp; + +/// Tells the adapter to request a reward based video ad. This method is called after the adapter +/// has been set up. The adapter should notify the Google Mobile Ads SDK if the request succeeds or +/// fails using callbacks provided in the connector. +- (void)requestRewardBasedVideoAd; + +/// Tells the adapter to present the reward based video ad with the provided view controller. This +/// method is only called after the adapter successfully requested an ad. +- (void)presentRewardBasedVideoAdWithRootViewController:(UIViewController *)viewController; + +/// Tells the adapter to remove itself as a delegate or notification observer from the underlying ad +/// network SDK. +- (void)stopBeingDelegate; + +@optional + +/// Returns an initialized instance of the adapter. The adapter must only maintain a weak reference +/// to the provided connector. +- (instancetype)initWithGADMAdNetworkConnector:(id)connector + GAD_DEPRECATED_MSG_ATTRIBUTE("Use initWithRewardBasedVideoAdNetworkConnector:."); + +/// Tells the adapter to set up reward based video ads with the provided user ID. The adapter should +/// notify the Google Mobile Ads SDK whether set up has succeeded or failed using callbacks provided +/// in the connector. When set up fails, the Google Mobile Ads SDK may try to set up the adapter +/// again. +- (void)setUpWithUserID:(NSString *)userID GAD_DEPRECATED_MSG_ATTRIBUTE("Use setUp."); + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h new file mode 100755 index 000000000..82b8d4520 --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMRewardBasedVideoAdNetworkConnectorProtocol.h @@ -0,0 +1,58 @@ +// +// GADMRewardBasedVideoAdNetworkConnector.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import + +@protocol GADMediationAdRequest; +@protocol GADMRewardBasedVideoAdNetworkAdapter; + +/// Reward based video ad network adapters interact with the mediation SDK using an object that +/// conforms to the GADMRewardBasedVideoAdNetworkConnector protocol. The connector object can be +/// used to obtain information for ad requests and to call back to the mediation SDK on ad responses +/// and user interactions. +@protocol GADMRewardBasedVideoAdNetworkConnector + +/// Tells the delegate that the adapter successfully set up a reward based video ad. +- (void)adapterDidSetUpRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter failed to set up a reward based video ad. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToSetUpRewardBasedVideoAdWithError:(NSError *)error; + +/// Tells the delegate that a reward based video ad was clicked. +- (void)adapterDidGetAdClick:(id)adapter; + +/// Tells the delegate that a reward based video ad has loaded. +- (void)adapterDidReceiveRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has opened. +- (void)adapterDidOpenRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has started playing. +- (void)adapterDidStartPlayingRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad has closed. +- (void)adapterDidCloseRewardBasedVideoAd: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that the adapter has rewarded the user. +- (void)adapter:(id)rewardBasedVideoAd + didRewardUserWithReward:(GADAdReward *)reward; + +/// Tells the delegate that a reward based video ad's action will leave the application. +- (void)adapterWillLeaveApplication: + (id)rewardBasedVideoAdAdapter; + +/// Tells the delegate that a reward based video ad failed to load. +- (void)adapter:(id)rewardBasedVideoAdAdapter + didFailToLoadRewardBasedVideoAdwithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMediationAdRequest.h b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMediationAdRequest.h new file mode 100755 index 000000000..104ea5a2b --- /dev/null +++ b/examples/PrebidMobileDemo/GoogleMobileAds.framework/Versions/Current/Headers/Mediation/GADMediationAdRequest.h @@ -0,0 +1,56 @@ +// +// GADMediationAdRequest.h +// Google Mobile Ads SDK +// +// Copyright 2015 Google. All rights reserved. +// + +#import +#import + +/// Provides information which can be used for making ad requests during mediation. +@protocol GADMediationAdRequest + +/// Publisher ID set by the publisher on the AdMob frontend. +- (NSString *)publisherId; + +/// Mediation configurations set by the publisher on the AdMob frontend. +- (NSDictionary *)credentials; + +/// Returns YES if the publisher is requesting test ads. +- (BOOL)testMode; + +/// The adapter's ad network extras specified in GADRequest. +- (id)networkExtras; + +/// Returns the value of childDirectedTreatment supplied by the publisher. Returns nil if the +/// publisher hasn't specified child directed treatment. Returns @YES if child directed treatment is +/// enabled. +- (NSNumber *)childDirectedTreatment; + +/// The end user's gender set by the publisher in GADRequest. Returns kGADGenderUnknown if it has +/// not been specified. +- (GADGender)userGender; + +/// The end user's birthday set by the publisher. Returns nil if it has not been specified. +- (NSDate *)userBirthday; + +/// Returns YES if the publisher has specified latitude and longitude location. +- (BOOL)userHasLocation; + +/// Returns the user's latitude or 0 if location isn't specified. +- (CGFloat)userLatitude; + +/// Returns the user's longitude or 0 if location isn't specified. +- (CGFloat)userLongitude; + +/// Returns the user's location accuracy or 0 if location isn't specified. +- (CGFloat)userLocationAccuracyInMeters; + +/// Returns user's location description. May return a value even if userHasLocation is NO. +- (NSString *)userLocationDescription; + +/// Keywords describing the user's current activity. Example: @"Sport Scores". +- (NSArray *)userKeywords; + +@end diff --git a/examples/PrebidMobileDemo/Makefile b/examples/PrebidMobileDemo/Makefile new file mode 100644 index 000000000..f47c97863 --- /dev/null +++ b/examples/PrebidMobileDemo/Makefile @@ -0,0 +1,24 @@ +all: + $(MAKE) ipa + +clean: + rm -rf build + rm -rf Products + + # Legacy + #rm -rf CalSmoke*.ipa + #rm -rf CalSmoke*.app.dSYM + #rm -rf CalSmoke*.app + #rm -rf xtc-staging + +# Builds an ipa with no Calabash server. +ipa: + bin/make/ipa.sh + +# Builds an app with no Calabash server. +#app: + #bin/make/app.sh + +# Run the XCTest (unit) tests +#xct: + #bundle exec bin/make/xctest.rb \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.h new file mode 100644 index 000000000..40dbdcc57 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.h @@ -0,0 +1,26 @@ +// +// MPBannerAdManager.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPAdServerCommunicator.h" +#import "MPBaseBannerAdapter.h" + +@protocol MPBannerAdManagerDelegate; + +@interface MPBannerAdManager : NSObject + +@property (nonatomic, weak) id delegate; + +- (id)initWithDelegate:(id)delegate; + +- (void)loadAd; +- (void)forceRefreshAd; +- (void)stopAutomaticallyRefreshingContents; +- (void)startAutomaticallyRefreshingContents; +- (void)rotateToOrientation:(UIInterfaceOrientation)orientation; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.m new file mode 100644 index 000000000..73d6fa19c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManager.m @@ -0,0 +1,363 @@ +// +// MPBannerAdManager.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPBannerAdManager.h" +#import "MPAdServerURLBuilder.h" +#import "MPInstanceProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPBannerAdManagerDelegate.h" +#import "MPError.h" +#import "MPTimer.h" +#import "MPConstants.h" +#import "MPLogging.h" + +@interface MPBannerAdManager () + +@property (nonatomic, strong) MPAdServerCommunicator *communicator; +@property (nonatomic, strong) MPBaseBannerAdapter *onscreenAdapter; +@property (nonatomic, strong) MPBaseBannerAdapter *requestingAdapter; +@property (nonatomic, strong) UIView *requestingAdapterAdContentView; +@property (nonatomic, strong) MPAdConfiguration *requestingConfiguration; +@property (nonatomic, strong) MPTimer *refreshTimer; +@property (nonatomic, assign) BOOL adActionInProgress; +@property (nonatomic, assign) BOOL automaticallyRefreshesContents; +@property (nonatomic, assign) BOOL hasRequestedAtLeastOneAd; +@property (nonatomic, assign) UIInterfaceOrientation currentOrientation; + +- (void)loadAdWithURL:(NSURL *)URL; +- (void)applicationWillEnterForeground; +- (void)scheduleRefreshTimer; +- (void)refreshTimerDidFire; + +@end + +@implementation MPBannerAdManager + +@synthesize delegate = _delegate; +@synthesize communicator = _communicator; +@synthesize onscreenAdapter = _onscreenAdapter; +@synthesize requestingAdapter = _requestingAdapter; +@synthesize refreshTimer = _refreshTimer; +@synthesize adActionInProgress = _adActionInProgress; +@synthesize currentOrientation = _currentOrientation; + +- (id)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + self.delegate = delegate; + + self.communicator = [[MPCoreInstanceProvider sharedProvider] buildMPAdServerCommunicatorWithDelegate:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationWillEnterForeground) + name:UIApplicationWillEnterForegroundNotification + object:[UIApplication sharedApplication]]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationDidEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:[UIApplication sharedApplication]]; + + self.automaticallyRefreshesContents = YES; + self.currentOrientation = MPInterfaceOrientation(); + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [self.communicator cancel]; + [self.communicator setDelegate:nil]; + + [self.refreshTimer invalidate]; + + [self.onscreenAdapter unregisterDelegate]; + + [self.requestingAdapter unregisterDelegate]; + +} + +- (BOOL)loading +{ + return self.communicator.loading || self.requestingAdapter; +} + +- (void)loadAd +{ + if (!self.hasRequestedAtLeastOneAd) { + self.hasRequestedAtLeastOneAd = YES; + } + + if (self.loading) { + MPLogWarn(@"Banner view (%@) is already loading an ad. Wait for previous load to finish.", [self.delegate adUnitId]); + return; + } + + [self loadAdWithURL:nil]; +} + +- (void)forceRefreshAd +{ + [self loadAdWithURL:nil]; +} + +- (void)applicationWillEnterForeground +{ + if (self.automaticallyRefreshesContents && self.hasRequestedAtLeastOneAd) { + [self loadAdWithURL:nil]; + } +} + +- (void)applicationDidEnterBackground +{ + [self pauseRefreshTimer]; +} + +- (void)pauseRefreshTimer +{ + if ([self.refreshTimer isValid]) { + [self.refreshTimer pause]; + } +} + +- (void)stopAutomaticallyRefreshingContents +{ + self.automaticallyRefreshesContents = NO; + + [self pauseRefreshTimer]; +} + +- (void)startAutomaticallyRefreshingContents +{ + self.automaticallyRefreshesContents = YES; + + if ([self.refreshTimer isValid]) { + [self.refreshTimer resume]; + } else if (self.refreshTimer) { + [self scheduleRefreshTimer]; + } +} + +- (void)loadAdWithURL:(NSURL *)URL +{ + URL = [URL copy]; //if this is the URL from the requestingConfiguration, it's about to die... + // Cancel the current request/requesting adapter + self.requestingConfiguration = nil; + [self.requestingAdapter unregisterDelegate]; + self.requestingAdapter = nil; + self.requestingAdapterAdContentView = nil; + + [self.communicator cancel]; + + URL = (URL) ? URL : [MPAdServerURLBuilder URLWithAdUnitID:[self.delegate adUnitId] + keywords:[self.delegate keywords] + location:[self.delegate location] + testing:[self.delegate isTesting]]; + + MPLogInfo(@"Banner view (%@) loading ad with MoPub server URL: %@", [self.delegate adUnitId], URL); + + [self.communicator loadURL:URL]; +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)orientation +{ + self.currentOrientation = orientation; + [self.requestingAdapter rotateToOrientation:orientation]; + [self.onscreenAdapter rotateToOrientation:orientation]; +} + +#pragma mark - Internal + +- (void)scheduleRefreshTimer +{ + [self.refreshTimer invalidate]; + NSTimeInterval timeInterval = self.requestingConfiguration ? self.requestingConfiguration.refreshInterval : DEFAULT_BANNER_REFRESH_INTERVAL; + + if (timeInterval > 0) { + self.refreshTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:timeInterval + target:self + selector:@selector(refreshTimerDidFire) + repeats:NO]; + [self.refreshTimer scheduleNow]; + MPLogDebug(@"Scheduled the autorefresh timer to fire in %.1f seconds (%p).", timeInterval, self.refreshTimer); + } +} + +- (void)refreshTimerDidFire +{ + if (!self.loading && self.automaticallyRefreshesContents) { + [self loadAd]; + } +} + +#pragma mark - + +- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration +{ + self.requestingConfiguration = configuration; + + MPLogInfo(@"Banner ad view is fetching ad network type: %@", self.requestingConfiguration.networkType); + + if (configuration.adType == MPAdTypeUnknown) { + [self didFailToLoadAdapterWithError:[MOPUBError errorWithCode:MOPUBErrorServerError]]; + return; + } + + if (configuration.adType == MPAdTypeInterstitial) { + MPLogWarn(@"Could not load ad: banner object received an interstitial ad unit ID."); + [self didFailToLoadAdapterWithError:[MOPUBError errorWithCode:MOPUBErrorAdapterInvalid]]; + return; + } + + if (configuration.adUnitWarmingUp) { + MPLogInfo(kMPWarmingUpErrorLogFormatWithAdUnitID, self.delegate.adUnitId); + [self didFailToLoadAdapterWithError:[MOPUBError errorWithCode:MOPUBErrorAdUnitWarmingUp]]; + return; + } + + if ([configuration.networkType isEqualToString:kAdTypeClear]) { + MPLogInfo(kMPClearErrorLogFormatWithAdUnitID, self.delegate.adUnitId); + [self didFailToLoadAdapterWithError:[MOPUBError errorWithCode:MOPUBErrorNoInventory]]; + return; + } + + self.requestingAdapter = [[MPInstanceProvider sharedProvider] buildBannerAdapterForConfiguration:configuration + delegate:self]; + if (!self.requestingAdapter) { + [self loadAdWithURL:self.requestingConfiguration.failoverURL]; + return; + } + + [self.requestingAdapter _getAdWithConfiguration:configuration containerSize:self.delegate.containerSize]; +} + +- (void)communicatorDidFailWithError:(NSError *)error +{ + [self didFailToLoadAdapterWithError:error]; +} + +- (void)didFailToLoadAdapterWithError:(NSError *)error +{ + [self.delegate managerDidFailToLoadAd]; + [self scheduleRefreshTimer]; + + MPLogError(@"Banner view (%@) failed. Error: %@", [self.delegate adUnitId], error); +} + +#pragma mark - + +- (MPAdView *)banner +{ + return [self.delegate banner]; +} + +- (id)bannerDelegate +{ + return [self.delegate bannerDelegate]; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (MPNativeAdOrientation)allowedNativeAdsOrientation +{ + return [self.delegate allowedNativeAdsOrientation]; +} + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (BOOL)requestingAdapterIsReadyToBePresented +{ + return !!self.requestingAdapterAdContentView; +} + +- (void)presentRequestingAdapter +{ + if (!self.adActionInProgress && self.requestingAdapterIsReadyToBePresented) { + [self.onscreenAdapter unregisterDelegate]; + self.onscreenAdapter = self.requestingAdapter; + self.requestingAdapter = nil; + + [self.onscreenAdapter rotateToOrientation:self.currentOrientation]; + [self.delegate managerDidLoadAd:self.requestingAdapterAdContentView]; + [self.onscreenAdapter didDisplayAd]; + + self.requestingAdapterAdContentView = nil; + [self scheduleRefreshTimer]; + } +} + +- (void)adapter:(MPBaseBannerAdapter *)adapter didFinishLoadingAd:(UIView *)ad +{ + if (self.requestingAdapter == adapter) { + self.requestingAdapterAdContentView = ad; + [self presentRequestingAdapter]; + } +} + +- (void)adapter:(MPBaseBannerAdapter *)adapter didFailToLoadAdWithError:(NSError *)error +{ + if (self.requestingAdapter == adapter) { + [self loadAdWithURL:self.requestingConfiguration.failoverURL]; + } + + if (self.onscreenAdapter == adapter) { + // the onscreen adapter has failed. we need to: + // 1) remove it + // 2) tell the delegate + // 3) and note that there can't possibly be a modal on display any more + [self.delegate managerDidFailToLoadAd]; + [self.delegate invalidateContentView]; + [self.onscreenAdapter unregisterDelegate]; + self.onscreenAdapter = nil; + if (self.adActionInProgress) { + [self.delegate userActionDidFinish]; + self.adActionInProgress = NO; + } + if (self.requestingAdapterIsReadyToBePresented) { + [self presentRequestingAdapter]; + } else { + [self loadAd]; + } + } +} + +- (void)userActionWillBeginForAdapter:(MPBaseBannerAdapter *)adapter +{ + if (self.onscreenAdapter == adapter) { + self.adActionInProgress = YES; + [self.delegate userActionWillBegin]; + } +} + +- (void)userActionDidFinishForAdapter:(MPBaseBannerAdapter *)adapter +{ + if (self.onscreenAdapter == adapter) { + [self.delegate userActionDidFinish]; + self.adActionInProgress = NO; + [self presentRequestingAdapter]; + } +} + +- (void)userWillLeaveApplicationFromAdapter:(MPBaseBannerAdapter *)adapter +{ + if (self.onscreenAdapter == adapter) { + [self.delegate userWillLeaveApplication]; + } +} + +@end + + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManagerDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManagerDelegate.h new file mode 100644 index 000000000..406d99dbb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerAdManagerDelegate.h @@ -0,0 +1,33 @@ +// +// MPBannerAdManagerDelegate.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@class MPAdView; +@protocol MPAdViewDelegate; + +@protocol MPBannerAdManagerDelegate + +- (NSString *)adUnitId; +- (MPNativeAdOrientation)allowedNativeAdsOrientation; +- (MPAdView *)banner; +- (id)bannerDelegate; +- (CGSize)containerSize; +- (NSString *)keywords; +- (CLLocation *)location; +- (BOOL)isTesting; +- (UIViewController *)viewControllerForPresentingModalView; + +- (void)invalidateContentView; + +- (void)managerDidLoadAd:(UIView *)ad; +- (void)managerDidFailToLoadAd; +- (void)userActionWillBegin; +- (void)userActionDidFinish; +- (void)userWillLeaveApplication; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.h new file mode 100644 index 000000000..d8c5dea8b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.h @@ -0,0 +1,16 @@ +// +// MPBannerCustomEventAdapter.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPBaseBannerAdapter.h" + +#import "MPPrivateBannerCustomEventDelegate.h" + +@class MPBannerCustomEvent; + +@interface MPBannerCustomEventAdapter : MPBaseBannerAdapter + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.m new file mode 100644 index 000000000..e3a35ffe2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBannerCustomEventAdapter.m @@ -0,0 +1,141 @@ +// +// MPBannerCustomEventAdapter.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPBannerCustomEventAdapter.h" + +#import "MPAdConfiguration.h" +#import "MPBannerCustomEvent.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" + +@interface MPBannerCustomEventAdapter () + +@property (nonatomic, strong) MPBannerCustomEvent *bannerCustomEvent; +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, assign) BOOL hasTrackedImpression; +@property (nonatomic, assign) BOOL hasTrackedClick; + +- (void)trackClickOnce; + +@end + +@implementation MPBannerCustomEventAdapter +@synthesize hasTrackedImpression = _hasTrackedImpression; +@synthesize hasTrackedClick = _hasTrackedClick; + +- (void)unregisterDelegate +{ + if ([self.bannerCustomEvent respondsToSelector:@selector(invalidate)]) { + // Secret API to allow us to detach the custom event from (shared instance) routers synchronously + [self.bannerCustomEvent performSelector:@selector(invalidate)]; + } + self.bannerCustomEvent.delegate = nil; + + // make sure the custom event isn't released synchronously as objects owned by the custom event + // may do additional work after a callback that results in unregisterDelegate being called + [[MPCoreInstanceProvider sharedProvider] keepObjectAliveForCurrentRunLoopIteration:_bannerCustomEvent]; + + [super unregisterDelegate]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration containerSize:(CGSize)size +{ + MPLogInfo(@"Looking for custom event class named %@.", configuration.customEventClass); + self.configuration = configuration; + + self.bannerCustomEvent = [[MPInstanceProvider sharedProvider] buildBannerCustomEventFromCustomClass:configuration.customEventClass + delegate:self]; + if (self.bannerCustomEvent) { + [self.bannerCustomEvent requestAdWithSize:size customEventInfo:configuration.customEventClassData]; + } else { + [self.delegate adapter:self didFailToLoadAdWithError:nil]; + } +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation +{ + [self.bannerCustomEvent rotateToOrientation:newOrientation]; +} + +- (void)didDisplayAd +{ + if ([self.bannerCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedImpression) { + self.hasTrackedImpression = YES; + [self trackImpression]; + } + + [self.bannerCustomEvent didDisplayAd]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark - MPPrivateBannerCustomEventDelegate + +- (NSString *)adUnitId +{ + return [self.delegate banner].adUnitId; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (id)bannerDelegate +{ + return [self.delegate bannerDelegate]; +} + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (void)bannerCustomEvent:(MPBannerCustomEvent *)event didLoadAd:(UIView *)ad +{ + [self didStopLoading]; + if (ad) { + [self.delegate adapter:self didFinishLoadingAd:ad]; + } else { + [self.delegate adapter:self didFailToLoadAdWithError:nil]; + } +} + +- (void)bannerCustomEvent:(MPBannerCustomEvent *)event didFailToLoadAdWithError:(NSError *)error +{ + [self didStopLoading]; + [self.delegate adapter:self didFailToLoadAdWithError:error]; +} + +- (void)bannerCustomEventWillBeginAction:(MPBannerCustomEvent *)event +{ + [self trackClickOnce]; + [self.delegate userActionWillBeginForAdapter:self]; +} + +- (void)bannerCustomEventDidFinishAction:(MPBannerCustomEvent *)event +{ + [self.delegate userActionDidFinishForAdapter:self]; +} + +- (void)bannerCustomEventWillLeaveApplication:(MPBannerCustomEvent *)event +{ + [self trackClickOnce]; + [self.delegate userWillLeaveApplicationFromAdapter:self]; +} + +- (void)trackClickOnce +{ + if ([self.bannerCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedClick) { + self.hasTrackedClick = YES; + [self trackClick]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.h new file mode 100644 index 000000000..bc978eafc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.h @@ -0,0 +1,83 @@ +// +// MPBaseBannerAdapter.h +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import +#import +#import "MPAdView.h" + +@protocol MPBannerAdapterDelegate; +@class MPAdConfiguration; + +@interface MPBaseBannerAdapter : NSObject +{ + id __weak _delegate; +} + +@property (nonatomic, weak) id delegate; +@property (nonatomic, copy) NSURL *impressionTrackingURL; +@property (nonatomic, copy) NSURL *clickTrackingURL; + +- (id)initWithDelegate:(id)delegate; + +/* + * Sets the adapter's delegate to nil. + */ +- (void)unregisterDelegate; + +/* + * -_getAdWithConfiguration creates a strong reference to self before calling + * -getAdWithConfiguration to prevent the adapter from being prematurely deallocated. + */ +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration containerSize:(CGSize)size; +- (void)_getAdWithConfiguration:(MPAdConfiguration *)configuration containerSize:(CGSize)size; + +- (void)didStopLoading; +- (void)didDisplayAd; + +/* + * Your subclass should implement this method if your native ads vary depending on orientation. + */ +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation; + +- (void)trackImpression; + +- (void)trackClick; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPBannerAdapterDelegate + +@required + +- (MPAdView *)banner; +- (id)bannerDelegate; +- (UIViewController *)viewControllerForPresentingModalView; +- (MPNativeAdOrientation)allowedNativeAdsOrientation; +- (CLLocation *)location; + +/* + * These callbacks notify you that the adapter (un)successfully loaded an ad. + */ +- (void)adapter:(MPBaseBannerAdapter *)adapter didFailToLoadAdWithError:(NSError *)error; +- (void)adapter:(MPBaseBannerAdapter *)adapter didFinishLoadingAd:(UIView *)ad; + +/* + * These callbacks notify you that the user interacted (or stopped interacting) with the native ad. + */ +- (void)userActionWillBeginForAdapter:(MPBaseBannerAdapter *)adapter; +- (void)userActionDidFinishForAdapter:(MPBaseBannerAdapter *)adapter; + +/* + * This callback notifies you that user has tapped on an ad which will cause them to leave the + * current application (e.g. the ad action opens the iTunes store, Mobile Safari, etc). + */ +- (void)userWillLeaveApplicationFromAdapter:(MPBaseBannerAdapter *)adapter; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.m new file mode 100644 index 000000000..6520564d9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPBaseBannerAdapter.m @@ -0,0 +1,123 @@ +// +// MPBaseBannerAdapter.m +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPBaseBannerAdapter.h" +#import "MPConstants.h" + +#import "MPAdConfiguration.h" +#import "MPLogging.h" +#import "MPCoreInstanceProvider.h" +#import "MPAnalyticsTracker.h" +#import "MPTimer.h" + +@interface MPBaseBannerAdapter () + +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, strong) MPTimer *timeoutTimer; + +- (void)startTimeoutTimer; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPBaseBannerAdapter + +@synthesize delegate = _delegate; +@synthesize configuration = _configuration; +@synthesize timeoutTimer = _timeoutTimer; + +- (id)initWithDelegate:(id)delegate +{ + if (self = [super init]) { + self.delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [self unregisterDelegate]; + [self.timeoutTimer invalidate]; +} + +- (void)unregisterDelegate +{ + self.delegate = nil; +} + +#pragma mark - Requesting Ads + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration containerSize:(CGSize)size +{ + // To be implemented by subclasses. + [self doesNotRecognizeSelector:_cmd]; +} + +- (void)_getAdWithConfiguration:(MPAdConfiguration *)configuration containerSize:(CGSize)size +{ + self.configuration = configuration; + + [self startTimeoutTimer]; + + MPBaseBannerAdapter *strongSelf = self; + [strongSelf getAdWithConfiguration:configuration containerSize:size]; +} + +- (void)didStopLoading +{ + [self.timeoutTimer invalidate]; +} + +- (void)didDisplayAd +{ + [self trackImpression]; +} + +- (void)startTimeoutTimer +{ + NSTimeInterval timeInterval = (self.configuration && self.configuration.adTimeoutInterval >= 0) ? + self.configuration.adTimeoutInterval : BANNER_TIMEOUT_INTERVAL; + + if (timeInterval > 0) { + self.timeoutTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:timeInterval + target:self + selector:@selector(timeout) + repeats:NO]; + + [self.timeoutTimer scheduleNow]; + } +} + +- (void)timeout +{ + [self.delegate adapter:self didFailToLoadAdWithError:nil]; +} + +#pragma mark - Rotation + +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation +{ + // Do nothing by default. Subclasses can override. + MPLogDebug(@"rotateToOrientation %d called for adapter %@ (%p)", + newOrientation, NSStringFromClass([self class]), self); +} + +#pragma mark - Metrics + +- (void)trackImpression +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackImpressionForConfiguration:self.configuration]; +} + +- (void)trackClick +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackClickForConfiguration:self.configuration]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPPrivateBannerCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPPrivateBannerCustomEventDelegate.h new file mode 100644 index 000000000..ed97e6ccf --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Banners/MPPrivateBannerCustomEventDelegate.h @@ -0,0 +1,19 @@ +// +// MPPrivateBannerCustomEventDelegate.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPBannerCustomEventDelegate.h" + +@class MPAdConfiguration; + +@protocol MPPrivateBannerCustomEventDelegate + +- (NSString *)adUnitId; +- (MPAdConfiguration *)configuration; +- (id)bannerDelegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.h new file mode 100644 index 000000000..2f34ebddd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.h @@ -0,0 +1,32 @@ +// +// MPAdAlertGestureRecognizer.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +extern NSInteger const kMPAdAlertGestureMaxAllowedYAxisMovement; + +typedef enum +{ + MPAdAlertGestureRecognizerState_ZigRight1, + MPAdAlertGestureRecognizerState_ZagLeft2, + MPAdAlertGestureRecognizerState_Recognized +} MPAdAlertGestureRecognizerState; + +@interface MPAdAlertGestureRecognizer : UIGestureRecognizer + +// default is 4 +@property (nonatomic, assign) NSInteger numZigZagsForRecognition; + +// default is 100 +@property (nonatomic, assign) CGFloat minTrackedDistanceForZigZag; + +@property (nonatomic, readonly) MPAdAlertGestureRecognizerState currentAlertGestureState; +@property (nonatomic, readonly) CGPoint inflectionPoint; +@property (nonatomic, readonly) BOOL thresholdReached; +@property (nonatomic, readonly) NSInteger curNumZigZags; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.m new file mode 100644 index 000000000..30ab00002 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertGestureRecognizer.m @@ -0,0 +1,229 @@ +// +// MPAdAlertGestureRecognizer.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPAdAlertGestureRecognizer.h" + +#import + +#define kMaxRequiredTrackedDistance 100 +#define kDefaultMinTrackedDistance 100 +#define kDefaultNumZigZagsForRecognition 4 + +NSInteger const kMPAdAlertGestureMaxAllowedYAxisMovement = 50; + +@interface MPAdAlertGestureRecognizer () + +@property (nonatomic, assign) MPAdAlertGestureRecognizerState currentAlertGestureState; +@property (nonatomic, assign) CGPoint inflectionPoint; +@property (nonatomic, assign) CGPoint startingPoint; +@property (nonatomic, assign) BOOL thresholdReached; +@property (nonatomic, assign) NSInteger curNumZigZags; + +@end + +@implementation MPAdAlertGestureRecognizer + +@synthesize currentAlertGestureState = _currentAlertGestureState; +@synthesize inflectionPoint = _inflectionPoint; +@synthesize thresholdReached = _thresholdReached; +@synthesize curNumZigZags = _curNumZigZags; +@synthesize numZigZagsForRecognition = _numZigZagsForRecognition; +@synthesize minTrackedDistanceForZigZag = _minTrackedDistanceForZigZag; + +- (id)init +{ + self = [super init]; + if (self != nil) { + [self commonInit]; + } + + return self; +} + +- (id)initWithTarget:(id)target action:(SEL)action +{ + self = [super initWithTarget:target action:action]; + if (self != nil) { + [self commonInit]; + } + + return self; +} + +- (void)commonInit +{ + self.minTrackedDistanceForZigZag = kDefaultMinTrackedDistance; + self.numZigZagsForRecognition = kDefaultNumZigZagsForRecognition; + [self resetToInitialState]; +} + +- (void)setMinTrackedDistanceForZigZag:(CGFloat)minTrackedDistanceForZigZag +{ + if (_minTrackedDistanceForZigZag != minTrackedDistanceForZigZag) { + _minTrackedDistanceForZigZag = MIN(minTrackedDistanceForZigZag, kMaxRequiredTrackedDistance); + } +} + +#pragma mark Required Overrides + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesBegan:touches withEvent:event]; + if ([touches count] != 1) { + self.state = UIGestureRecognizerStateFailed; + return; + } + + CGPoint nowPoint = [touches.anyObject locationInView:self.view]; + self.inflectionPoint = nowPoint; + self.startingPoint = nowPoint; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesMoved:touches withEvent:event]; + + if (self.state == UIGestureRecognizerStateFailed) { + return; + } + + [self updateAlertGestureStateWithTouches:touches]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesEnded:touches withEvent:event]; + + if ((self.state == UIGestureRecognizerStatePossible) && self.currentAlertGestureState == MPAdAlertGestureRecognizerState_Recognized) { + self.state = UIGestureRecognizerStateRecognized; + } + + [self resetToInitialState]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesCancelled:touches withEvent:event]; + + [self resetToInitialState]; + + self.state = UIGestureRecognizerStateFailed; +} + +- (void)reset +{ + [super reset]; + + [self resetToInitialState]; +} + +- (void)resetToInitialState +{ + self.currentAlertGestureState = MPAdAlertGestureRecognizerState_ZigRight1; + self.inflectionPoint = CGPointZero; + self.startingPoint = CGPointZero; + self.thresholdReached = NO; + self.curNumZigZags = 0; +} + +#pragma mark State Transitions + +- (void)handleZigRightGestureStateWithTouches:(NSSet *)touches +{ + CGPoint nowPoint = [touches.anyObject locationInView:self.view]; + CGPoint prevPoint = [touches.anyObject previousLocationInView:self.view]; + + // first zig must be to the right, x must increase + // if the touch has covered enough distance, then we're ready to move on to the next state + if (nowPoint.x > prevPoint.x && nowPoint.x - self.inflectionPoint.x >= self.minTrackedDistanceForZigZag) { + self.thresholdReached = YES; + } else if (nowPoint.x < prevPoint.x) { + // user has changed touch direction + if (self.thresholdReached) { + self.inflectionPoint = nowPoint; + self.currentAlertGestureState = MPAdAlertGestureRecognizerState_ZagLeft2; + self.thresholdReached = NO; + } else { + // the user changed directions before covering the required distance, fail + self.state = UIGestureRecognizerStateFailed; + } + } + // else remain in the current state and continue tracking finger movement +} + +- (void)handleZagLeftGestureStateWithTouches:(NSSet *)touches +{ + CGPoint nowPoint = [touches.anyObject locationInView:self.view]; + CGPoint prevPoint = [touches.anyObject previousLocationInView:self.view]; + + // zag to the left, x must decrease + // if the touch has covered enough distance, then we're ready to move on to the next state + if (nowPoint.x < prevPoint.x && self.inflectionPoint.x - nowPoint.x >= self.minTrackedDistanceForZigZag) { + BOOL prevThresholdState = self.thresholdReached; + self.thresholdReached = YES; + + // increment once, and only once, after we hit the threshold for the zag + if (prevThresholdState != self.thresholdReached) { + self.curNumZigZags++; + } + + if (self.curNumZigZags >= self.numZigZagsForRecognition) { + self.currentAlertGestureState = MPAdAlertGestureRecognizerState_Recognized; + } + } else if (nowPoint.x > prevPoint.x) { + // user has changed touch direction + if (self.thresholdReached) { + self.inflectionPoint = nowPoint; + self.currentAlertGestureState = MPAdAlertGestureRecognizerState_ZigRight1; + self.thresholdReached = NO; + } else { + // the user changed directions before covering the required distance, fail + self.state = UIGestureRecognizerStateFailed; + } + } + // else remain in the current state and continue tracking finger movement +} + +- (void)updateAlertGestureStateWithTouches:(NSSet *)touches +{ + // fail gesture recognition if the touch moves outside of our defined bounds + if (![self touchIsWithinBoundsForTouches:touches] && self.currentAlertGestureState != MPAdAlertGestureRecognizerState_Recognized) { + self.state = UIGestureRecognizerStateFailed; + return; + } + + switch (self.currentAlertGestureState) { + case MPAdAlertGestureRecognizerState_ZigRight1: + [self handleZigRightGestureStateWithTouches:touches]; + + break; + case MPAdAlertGestureRecognizerState_ZagLeft2: + [self handleZagLeftGestureStateWithTouches:touches]; + + break; + default: + break; + } +} + +- (BOOL)validYAxisMovementForTouches:(NSSet *)touches +{ + CGPoint nowPoint = [touches.anyObject locationInView:self.view]; + + return fabs(nowPoint.y - self.startingPoint.y) <= kMPAdAlertGestureMaxAllowedYAxisMovement; +} + +- (BOOL)touchIsWithinBoundsForTouches:(NSSet *)touches +{ + CGPoint nowPoint = [touches.anyObject locationInView:self.view]; + + // 1. use self.view.bounds because locationInView converts to self.view's coordinate system + // 2. ensure user doesn't stray too far in the Y-axis + return CGRectContainsPoint(self.view.bounds, nowPoint) && [self validYAxisMovementForTouches:touches]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.h new file mode 100644 index 000000000..0caa34cca --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.h @@ -0,0 +1,30 @@ +// +// MPAdAlertManager.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import +#import "MPGlobal.h" + +@class CLLocation; +@protocol MPAdAlertManagerDelegate; + +@class MPAdConfiguration; + +@interface MPAdAlertManager : NSObject + +@end + +@protocol MPAdAlertManagerDelegate + +@required +- (UIViewController *)viewControllerForPresentingMailVC; +- (void)adAlertManagerDidTriggerAlert:(MPAdAlertManager *)manager; + +@optional +- (void)adAlertManagerDidProcessAlert:(MPAdAlertManager *)manager; + +@end \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.m new file mode 100644 index 000000000..7342fde46 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/AdAlerts/MPAdAlertManager.m @@ -0,0 +1,231 @@ +// +// MPAdAlertManager.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPAdAlertManager.h" +#import "MPAdConfiguration.h" +#import "MPAdAlertGestureRecognizer.h" +#import "MPLogging.h" +#import "MPIdentityProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPLastResortDelegate.h" + +#import +#import +#import + +#define kTimestampParamKey @"timestamp" + +@interface MPAdAlertManager () + +@property (nonatomic, assign) BOOL processedAlert; +@property (nonatomic, strong) MPAdAlertGestureRecognizer *adAlertGestureRecognizer; +@property (nonatomic, strong) MFMailComposeViewController *currentOpenMailVC; + +@end + +@implementation MPAdAlertManager + +@synthesize delegate = _delegate; +@synthesize adConfiguration = _adConfiguration; +@synthesize processedAlert = _processedAlert; +@synthesize adAlertGestureRecognizer = _adAlertGestureRecognizer; +@synthesize adUnitId = _adUnitId; +@synthesize targetAdView = _targetAdView; +@synthesize location = _location; +@synthesize currentOpenMailVC = _currentOpenMailVC; + +- (id)init +{ + self = [super init]; + if (self != nil) { + self.adAlertGestureRecognizer = [[MPCoreInstanceProvider sharedProvider] buildMPAdAlertGestureRecognizerWithTarget:self + action:@selector(handleAdAlertGesture)]; + self.adAlertGestureRecognizer.delegate = self; + self.processedAlert = NO; + } + + return self; +} + +- (void)dealloc +{ + [_targetAdView removeGestureRecognizer:_adAlertGestureRecognizer]; + [_adAlertGestureRecognizer removeTarget:self action:nil]; + _adAlertGestureRecognizer.delegate = nil; + _currentOpenMailVC.mailComposeDelegate = [MPLastResortDelegate sharedDelegate]; +} + +- (void)processAdAlert +{ + static NSDateFormatter *dateFormatter = nil; + + MPLogInfo(@"MPAdAlertManager processing ad alert"); + + // don't even try if this device can't send emails + if (![MFMailComposeViewController canSendMail]) { + if ([self.delegate respondsToSelector:@selector(adAlertManagerDidProcessAlert:)]) { + [self.delegate adAlertManagerDidProcessAlert:self]; + } + + return; + } + + // since iOS 4, drawing an image to a graphics context is thread-safe + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // take screenshot of the ad + UIGraphicsBeginImageContextWithOptions(self.targetAdView.bounds.size, YES, 0.0); + [self.targetAdView.layer renderInContext:UIGraphicsGetCurrentContext()]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + dispatch_async(dispatch_get_main_queue(), ^{ + // package additional ad data + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + + [params setValue:@"iOS" forKey:@"platform"]; + [params setValue:[UIDevice currentDevice].systemVersion forKey:@"platform_version"]; + [params setValue:[MPIdentityProvider identifier] forKey:@"device_id"]; + [params setValue:[UIDevice currentDevice].model forKey:@"device_model"]; + [params setValue:[NSNumber numberWithInteger:self.adConfiguration.adType] forKey:@"ad_type"]; + [params setValue:self.adUnitId forKey:@"ad_unit_id"]; + [params setValue:self.adConfiguration.dspCreativeId forKey:@"creative_id"]; + [params setValue:self.adConfiguration.networkType forKey:@"network_type"]; + [params setValue:[[NSLocale currentLocale] localeIdentifier] forKey:@"device_locale"]; + [params setValue:[self.location description] forKey:@"location"]; + [params setValue:MP_SDK_VERSION forKey:@"sdk_version"]; + + if (self.adConfiguration.hasPreferredSize) { + [params setValue:NSStringFromCGSize(self.adConfiguration.preferredSize) forKey:@"ad_size"]; + } + + if (dateFormatter == nil) { + dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setTimeStyle:NSDateFormatterLongStyle]; + [dateFormatter setDateStyle:NSDateFormatterShortStyle]; + } + [params setValue:[dateFormatter stringFromDate:self.adConfiguration.creationTimestamp] forKey:kTimestampParamKey]; + + [self processAdParams:params andScreenshot:image]; + + MPLogInfo(@"MPAdAlertManager finished processing ad alert"); + }); + }); +} + +- (void)handleAdAlertGesture +{ + MPLogInfo(@"MPAdAlertManager alert gesture recognized"); + + [self.delegate adAlertManagerDidTriggerAlert:self]; +} + +- (void)processAdParams:(NSDictionary *)params andScreenshot:(UIImage *)screenshot +{ + NSData *imageData = UIImagePNGRepresentation(screenshot); + NSData *paramData =[[self stringFromDictionary:params] dataUsingEncoding:NSUTF8StringEncoding]; + NSData *markupData = self.adConfiguration.adResponseData; + + self.currentOpenMailVC = [[MFMailComposeViewController alloc] init]; + self.currentOpenMailVC.mailComposeDelegate = self; + + [self.currentOpenMailVC setToRecipients:[NSArray arrayWithObject:@"creative-review@mopub.com"]]; + [self.currentOpenMailVC setSubject:[NSString stringWithFormat:@"New creative violation report - %@", [params objectForKey:kTimestampParamKey]]]; + [self.currentOpenMailVC setMessageBody:@"" isHTML:YES]; + + if (imageData != nil) { + [self.currentOpenMailVC addAttachmentData:imageData mimeType:@"image/png" fileName:@"mp_adalert_screenshot.png"]; + } + + if (paramData != nil) { + [self.currentOpenMailVC addAttachmentData:paramData mimeType:@"text/plain" fileName:@"mp_adalert_parameters.txt"]; + } + + if (markupData != nil) { + [self.currentOpenMailVC addAttachmentData:markupData mimeType:@"text/html" fileName:@"mp_adalert_markup.html"]; + } + + [[self.delegate viewControllerForPresentingMailVC] presentViewController:self.currentOpenMailVC animated:MP_ANIMATED completion:nil]; + + if ([self.delegate respondsToSelector:@selector(adAlertManagerDidProcessAlert:)]) { + [self.delegate adAlertManagerDidProcessAlert:self]; + } +} + +// could just use [dictionary description], but this gives us more control over the output +- (NSString *)stringFromDictionary:(NSDictionary *)dictionary +{ + NSMutableString *result = [NSMutableString string]; + + for (NSString *key in [dictionary allKeys]) { + [result appendFormat:@"%@ : %@\n", key, [dictionary objectForKey:key]]; + } + + return result; +} + +#pragma mark - + +- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error +{ + self.currentOpenMailVC = nil; + + // reset processed state to allow the user to alert on this ad again + if (result == MFMailComposeResultCancelled || result == MFMailComposeResultFailed) { + self.processedAlert = NO; + } + + [[self.delegate viewControllerForPresentingMailVC] dismissViewControllerAnimated:MP_ANIMATED completion:nil]; +} + +#pragma mark - Public + +- (void)beginMonitoringAlerts +{ + [self endMonitoringAlerts]; + + [self.targetAdView addGestureRecognizer:self.adAlertGestureRecognizer]; + + // dynamically set minimum tracking distance to account for all ad sizes + self.adAlertGestureRecognizer.minTrackedDistanceForZigZag = self.targetAdView.bounds.size.width / 3; + + self.processedAlert = NO; +} + +- (void)endMonitoringAlerts +{ + [self.targetAdView removeGestureRecognizer:self.adAlertGestureRecognizer]; +} + +- (void)processAdAlertOnce +{ + if (self.processedAlert) { + return; + } + + self.processedAlert = YES; + + [self processAdAlert]; +} + +#pragma mark - + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch +{ + if ([touch.view isKindOfClass:[UIButton class]]) { + // we touched a button + return NO; // ignore the touch + } + return YES; // handle the touch +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +{ + return YES; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.h new file mode 100644 index 000000000..0b53eb3f7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.h @@ -0,0 +1,24 @@ +// +// MPAPIEndpoints.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +#define MOPUB_BASE_HOSTNAME @"ads.mopub.com" +#define MOPUB_BASE_HOSTNAME_FOR_TESTING @"testing.ads.mopub.com" + +#define MOPUB_API_PATH_AD_REQUEST @"/m/ad" +#define MOPUB_API_PATH_CONVERSION @"/m/open" +#define MOPUB_API_PATH_NATIVE_POSITIONING @"/m/pos" +#define MOPUB_API_PATH_SESSION @"/m/open" + +@interface MPAPIEndpoints : NSObject + ++ (void)setUsesHTTPS:(BOOL)usesHTTPS; ++ (NSString *)baseURL; ++ (NSString *)baseURLStringWithPath:(NSString *)path testing:(BOOL)testing; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.m new file mode 100644 index 000000000..7ec017683 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAPIEndpoints.m @@ -0,0 +1,43 @@ +// +// MPAPIEndpoints.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPAPIEndpoints.h" +#import "MPConstants.h" +#import "MPCoreInstanceProvider.h" + +@implementation MPAPIEndpoints + +static BOOL sUsesHTTPS = YES; + ++ (void)setUsesHTTPS:(BOOL)usesHTTPS +{ + sUsesHTTPS = usesHTTPS; +} + ++ (NSString *)baseURL +{ + if ([[MPCoreInstanceProvider sharedProvider] appTransportSecuritySettings] == MPATSSettingEnabled) { + return [@"https://" stringByAppendingString:MOPUB_BASE_HOSTNAME]; + } + + return [@"http://" stringByAppendingString:MOPUB_BASE_HOSTNAME]; +} + ++ (NSString *)baseURLScheme +{ + return sUsesHTTPS ? @"https://" : @"http://"; +} + ++ (NSString *)baseURLStringWithPath:(NSString *)path testing:(BOOL)testing +{ + return [NSString stringWithFormat:@"%@%@%@", + [[self class] baseURLScheme], + testing ? MOPUB_BASE_HOSTNAME_FOR_TESTING : MOPUB_BASE_HOSTNAME, + path]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.h new file mode 100644 index 000000000..9d8c7341a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.h @@ -0,0 +1,31 @@ +// +// MPActivityViewControllerHelper+TweetShare.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPActivityViewControllerHelper.h" + +/** + * `TweetShare` category added to MPActivityViewController to add functionality + * for sharing a tweet. + */ + +@interface MPActivityViewControllerHelper (TweetShare) + +/** + * Present the UIActivityViewController as specified by the + * provided URL. + * + * @param URL Instance of NSURL to be used for generating + * the share sheet. Should be of the format: + * mopubshare://tweet?screen_name=&tweet_id= + * + * @return a BOOL indicating whether or not the tweet share url was successfully shown + */ + +- (BOOL)presentActivityViewControllerWithTweetShareURL:(NSURL *)URL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.m new file mode 100644 index 000000000..dfcfe70c4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper+TweetShare.m @@ -0,0 +1,71 @@ +// +// MPActivityViewControllerHelper+TweetShare.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPActivityViewControllerHelper+TweetShare.h" +#import "MPLogging.h" +#import "NSURL+MPAdditions.h" + +static NSString * const kShareTweetScreenName = @"screen_name"; +static NSString * const kShareTweetId = @"tweet_id"; +static NSString * const kShareTweetURLTemplate = @"https://twitter.com/%@/status/%@"; +static NSString * const kShareTweetMessageTemplate = @"Check out @%@'s Tweet: %@"; + +/** + * MPSharedTweet parses an NSURL and stores the specified screenName and tweetURL. + */ + +@interface MPSharedTweet : NSObject + +@property (nonatomic, readonly) NSString *screenName; +@property (nonatomic, readonly) NSString *tweetURL; + +- (instancetype)initWithShareURL:(NSURL *)URL; + +@end + +@implementation MPSharedTweet + +- (instancetype)initWithShareURL:(NSURL *)URL +{ + self = [super init]; + if (self) { + NSDictionary *queryParamDict = [URL mp_queryAsDictionary]; + id screenName = [queryParamDict objectForKey:kShareTweetScreenName]; + id tweetId = [queryParamDict objectForKey:kShareTweetId]; + + // Fail initialization if the provided URL is not of the correct format. + // Both parameters are required. + if (screenName && tweetId) { + _screenName = screenName; + _tweetURL = [NSString stringWithFormat:kShareTweetURLTemplate, screenName, tweetId]; + } else { + MPLogDebug(@"MPActivityViewControllerHelper+TweetShare - \ + unable to initWithShareURL for share URL: %@. \ + screen_name or tweet_id missing or of the wrong \ + format", [URL absoluteString]); + return nil; + } + } + return self; +} + +@end + +@implementation MPActivityViewControllerHelper (TweetShare) + +- (BOOL)presentActivityViewControllerWithTweetShareURL:(NSURL *)URL +{ + MPSharedTweet *sharedTweet = [[MPSharedTweet alloc] initWithShareURL:URL]; + if (sharedTweet) { + NSString *tweetMessage = [NSString stringWithFormat:kShareTweetMessageTemplate, + sharedTweet.screenName, sharedTweet.tweetURL]; + return [self presentActivityViewControllerWithSubject:tweetMessage body:tweetMessage]; + } + return NO; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.h new file mode 100644 index 000000000..8b865316c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.h @@ -0,0 +1,80 @@ +// +// MPActivityViewControllerHelper.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPActivityViewControllerHelperDelegate; + +/** + * The MPActivityViewControllerHelper provides a wrapper around a UIActvityViewController + * and provides hooks via the MPActivityViewControllerHelperDelegate to handle the + * lifecycle of the underlying UIActivityViewController. + */ + +@interface MPActivityViewControllerHelper : NSObject + +/** + * The delegate (`MPActivityViewControllerHelperDelegate`) of the + * MPActivityViewControllerHelper. + */ + +@property (nonatomic, weak) id delegate; + +/** + * Initializes the MPActivityViewControllerHelper and stores a weak reference + * to the supplied delegate. + * + * @param delegate + */ +- (instancetype)initWithDelegate:(id)delegate; + +/** + * Instantiates and displays the underlying UIActivityViewController with the + * the specified `subject` and `body`. + * + * @param subject The subject to be displayed in the UIActivityViewController. + * @param body The body to be displayed in the UIActivityViewController. + * + * @return a BOOL indicating whether or not the UIActivityViewController was successfully shown. + */ +- (BOOL)presentActivityViewControllerWithSubject:(NSString *)subject body:(NSString *)body; + +@end + + +/** + * The delegate of a `MPActivityViewController` must adopt the `MPActivityViewController` + * protocol. It must implement `viewControllerForPresentingActivityViewController` to + * provide a root view controller from which to display content. + * + * Optional methods of this protocol allow the delegate to be notified before + * presenting and after dismissal. + */ +@protocol MPActivityViewControllerHelperDelegate + +@required + +/** + * Asks the delegate for a view controller to use for presenting content. + * + * @return A view controller that should be used for presenting content. + */ +- (UIViewController *)viewControllerForPresentingActivityViewController; + +@optional + +/** + * Sent before the UIActivityViewController is presented. + */ +- (void)activityViewControllerWillPresent; + +/** + * Sent after the UIActivityViewController has been dismissed. + */ +- (void)activityViewControllerDidDismiss; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.m new file mode 100644 index 000000000..ea8731c1e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPActivityViewControllerHelper.m @@ -0,0 +1,123 @@ +// +// MPActivityViewControllerHelper.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPActivityViewControllerHelper.h" +#import "MPInstanceProvider.h" + + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +/** + * MPActivityItemProviderWithSubject subclasses UIActivityItemProvider + * to provide a subject for email activity types. + */ + +@interface MPActivityItemProviderWithSubject : UIActivityItemProvider + +@property (nonatomic, readonly) NSString *subject; +@property (nonatomic, readonly) NSString *body; + +- (instancetype)initWithSubject:(NSString *)subject body:(NSString *)body; + +@end + +@implementation MPActivityItemProviderWithSubject + +- (instancetype)initWithSubject:(NSString *)subject body:(NSString *)body +{ + self = [super initWithPlaceholderItem:body]; + if (self) { + _subject = [subject copy]; + _body = [body copy]; + } + return self; +} + +- (id)item +{ + return self.body; +} + +- (NSString *)activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(NSString *)activityType +{ + return self.subject; +} + +@end +#endif + +@interface MPActivityViewControllerHelper() + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +- (UIActivityViewController *)initializeActivityViewControllerWithSubject:(NSString *)subject body:(NSString *)body; +#endif + +@end + +@implementation MPActivityViewControllerHelper + +- (instancetype)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + _delegate = delegate; + } + return self; +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +- (UIActivityViewController *)initializeActivityViewControllerWithSubject:(NSString *)subject body:(NSString *)body +{ + if (NSClassFromString(@"UIActivityViewController") && NSClassFromString(@"UIActivityItemProvider")) { + MPActivityItemProviderWithSubject *activityItemProvider = + [[MPActivityItemProviderWithSubject alloc] initWithSubject:subject body:body]; + UIActivityViewController *activityViewController = + [[UIActivityViewController alloc] initWithActivityItems:@[activityItemProvider] applicationActivities:nil]; + activityViewController.completionHandler = ^ + (NSString* activityType, BOOL completed) { + if ([self.delegate respondsToSelector:@selector(activityViewControllerDidDismiss)]) { + [self.delegate activityViewControllerDidDismiss]; + } + }; + return activityViewController; + } else { + return nil; + } +} +#endif + +- (BOOL)presentActivityViewControllerWithSubject:(NSString *)subject body:(NSString *)body +{ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 + if (NSClassFromString(@"UIActivityViewController")) { + UIActivityViewController *activityViewController = [self initializeActivityViewControllerWithSubject:subject body:body]; + if (activityViewController) { + if ([self.delegate respondsToSelector:@selector(activityViewControllerWillPresent)]) { + [self.delegate activityViewControllerWillPresent]; + } +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + UIUserInterfaceIdiom userInterfaceIdiom = [[[MPCoreInstanceProvider sharedProvider] + sharedCurrentDevice] userInterfaceIdiom]; + // iPad must present as popover on iOS >= 8 + if (userInterfaceIdiom == UIUserInterfaceIdiomPad) { + if ([activityViewController respondsToSelector:@selector(popoverPresentationController)]) { + activityViewController.popoverPresentationController.sourceView = + [self.delegate viewControllerForPresentingActivityViewController].view; + } + } +#endif + UIViewController *viewController = [self.delegate viewControllerForPresentingActivityViewController]; + [viewController presentViewController:activityViewController + animated:YES + completion:nil]; + return YES; + } + } +#endif + return NO; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.h new file mode 100644 index 000000000..931d5c2a7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.h @@ -0,0 +1,65 @@ +// +// MPAdBrowserController.h +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import +#import "MPWebView.h" + +#ifndef CF_RETURNS_RETAINED +#if __has_feature(attribute_cf_returns_retained) +#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) +#else +#define CF_RETURNS_RETAINED +#endif +#endif + +@class MPAdConfiguration; + +@protocol MPAdBrowserControllerDelegate; + +@interface MPAdBrowserController : UIViewController + +@property (nonatomic, strong) IBOutlet MPWebView *webView; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *backButton; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *forwardButton; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *refreshButton; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *safariButton; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton; +@property (nonatomic, strong) IBOutlet UIBarButtonItem *spinnerItem; +@property (nonatomic, strong) UIActivityIndicatorView *spinner; + +@property (nonatomic, weak) id delegate; +@property (nonatomic, copy) NSURL *URL; + +- (instancetype)initWithURL:(NSURL *)URL HTMLString:(NSString *)HTMLString delegate:(id)delegate; +- (instancetype)initWithURL:(NSURL *)URL delegate:(id)delegate; + +// Navigation methods. +- (IBAction)back; +- (IBAction)forward; +- (IBAction)refresh; +- (IBAction)safari; +- (IBAction)done; + +// Drawing methods. +- (CGContextRef)createContext CF_RETURNS_RETAINED; +- (UIImage *)backArrowImage; +- (UIImage *)forwardArrowImage; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPAdBrowserControllerDelegate + +- (void)dismissBrowserController:(MPAdBrowserController *)browserController animated:(BOOL)animated; + +@optional + +- (MPAdConfiguration *)adConfiguration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.m new file mode 100644 index 000000000..2392c7ccd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.m @@ -0,0 +1,354 @@ +// +// MPAdBrowserController.m +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPAdBrowserController.h" +#import "MPLogging.h" +#import "MPLogEvent.h" +#import "MPLogEventRecorder.h" +#import "MPAdConfiguration.h" +#import "MPAPIEndPoints.h" +#import "NSBundle+MPAdditions.h" + +static NSString * const kAdBrowserControllerNibName = @"MPAdBrowserController"; + +@interface MPAdBrowserController () + +@property (nonatomic, strong) UIActionSheet *actionSheet; +@property (nonatomic, strong) NSString *HTMLString; +@property (nonatomic, assign) int webViewLoadCount; +@property (nonatomic) MPLogEvent *dwellEvent; +@property (nonatomic) BOOL hasAppeared; + +- (void)dismissActionSheet; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPAdBrowserController + +@synthesize webView = _webView; +@synthesize backButton = _backButton; +@synthesize forwardButton = _forwardButton; +@synthesize refreshButton = _refreshButton; +@synthesize safariButton = _safariButton; +@synthesize doneButton = _doneButton; +@synthesize spinnerItem = _spinnerItem; +@synthesize spinner = _spinner; +@synthesize actionSheet = _actionSheet; +@synthesize delegate = _delegate; +@synthesize URL = _URL; +@synthesize webViewLoadCount = _webViewLoadCount; +@synthesize HTMLString = _HTMLString; + +#pragma mark - +#pragma mark Lifecycle + +- (instancetype)initWithURL:(NSURL *)URL HTMLString:(NSString *)HTMLString delegate:(id)delegate +{ + if (self = [super initWithNibName:kAdBrowserControllerNibName bundle:[NSBundle resourceBundleForClass:self.class]]) + { + self.delegate = delegate; + self.URL = URL; + self.HTMLString = HTMLString; + + MPLogDebug(@"Ad browser (%p) initialized with URL: %@", self, self.URL); + + self.webView = [[MPWebView alloc] initWithFrame:CGRectZero]; + self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + + self.spinner = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero]; + [self.spinner sizeToFit]; + self.spinner.hidesWhenStopped = YES; + + self.webViewLoadCount = 0; + + _hasAppeared = NO; + } + return self; +} + +- (instancetype)initWithURL:(NSURL *)URL delegate:(id)delegate { + return [self initWithURL:URL + HTMLString:nil + delegate:delegate]; +} + +- (void)dealloc +{ + self.webView.delegate = nil; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Set web view delegate + self.webView.delegate = self; + self.webView.scalesPageToFit = YES; + + // Set up toolbar buttons + self.backButton.image = [self backArrowImage]; + self.backButton.title = nil; + self.forwardButton.image = [self forwardArrowImage]; + self.forwardButton.title = nil; + self.spinnerItem.customView = self.spinner; + self.spinnerItem.title = nil; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + // Set button enabled status. + self.backButton.enabled = self.webView.canGoBack; + self.forwardButton.enabled = self.webView.canGoForward; + self.refreshButton.enabled = NO; + self.safariButton.enabled = NO; +} + +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; + + // Track when this view first appears so we can log the time the user stays in the view controller. Creating the event will mark the start of the dwell time. + // Make sure we don't create the event twice. + if (!self.hasAppeared) { + self.dwellEvent = [[MPLogEvent alloc] initWithEventCategory:MPLogEventCategoryAdInteractions eventName:MPLogEventNameClickthroughDwellTime]; + } + + self.hasAppeared = YES; + + NSURL *baseURL = (self.URL != nil) ? self.URL : [NSURL URLWithString:[MPAPIEndpoints baseURL]]; + + if (self.HTMLString) { + [self.webView loadHTMLString:self.HTMLString baseURL:baseURL]; + } else { + [self.webView loadRequest:[NSURLRequest requestWithURL:self.URL]]; + } +} + +- (void)viewWillDisappear:(BOOL)animated +{ + [self.webView stopLoading]; + [super viewWillDisappear:animated]; +} + +#pragma mark - Hidding status bar (iOS 7 and above) + +- (BOOL)prefersStatusBarHidden +{ + return YES; +} + +#pragma mark - +#pragma mark Navigation + +- (IBAction)refresh +{ + [self dismissActionSheet]; + [self.webView reload]; +} + +- (IBAction)done +{ + [self dismissActionSheet]; + if (self.delegate) { + [self.delegate dismissBrowserController:self animated:MP_ANIMATED]; + } else { + [self dismissViewControllerAnimated:MP_ANIMATED completion:nil]; + } + + if ([self.delegate respondsToSelector:@selector(adConfiguration)]) { + MPAdConfiguration *configuration = [self.delegate adConfiguration]; + + if (configuration) { + MPAdConfigurationLogEventProperties *logProperties = [[MPAdConfigurationLogEventProperties alloc] initWithConfiguration:configuration]; + [self.dwellEvent setLogEventProperties:logProperties]; + [self.dwellEvent recordEndTime]; + + MPAddLogEvent(self.dwellEvent); + } + } +} + +- (IBAction)back +{ + [self dismissActionSheet]; + [self.webView goBack]; + self.backButton.enabled = self.webView.canGoBack; + self.forwardButton.enabled = self.webView.canGoForward; +} + +- (IBAction)forward +{ + [self dismissActionSheet]; + [self.webView goForward]; + self.backButton.enabled = self.webView.canGoBack; + self.forwardButton.enabled = self.webView.canGoForward; +} + +- (IBAction)safari +{ + if (self.actionSheet) { + [self dismissActionSheet]; + } else { + self.actionSheet = [[UIActionSheet alloc] initWithTitle:nil + delegate:self + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@"Open in Safari", nil]; + + if ([UIActionSheet instancesRespondToSelector:@selector(showFromBarButtonItem:animated:)]) { + [self.actionSheet showFromBarButtonItem:self.safariButton animated:YES]; + } else { + [self.actionSheet showInView:self.webView]; + } + } +} + +- (void)dismissActionSheet +{ + [self.actionSheet dismissWithClickedButtonIndex:0 animated:YES]; + +} + +#pragma mark - +#pragma mark UIActionSheetDelegate + +- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex +{ + self.actionSheet = nil; + if (buttonIndex == 0) { + // Open in Safari. + [[UIApplication sharedApplication] openURL:self.URL]; + } +} + +#pragma mark - +#pragma mark MPWebViewDelegate + +- (BOOL)webView:(MPWebView *)webView +shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType +{ + MPLogDebug(@"Ad browser (%p) starting to load URL: %@", self, request.URL); + self.URL = request.URL; + + BOOL appShouldOpenURL = ![self.URL.scheme isEqualToString:@"http"] && ![self.URL.scheme isEqualToString:@"https"]; + + if (appShouldOpenURL) { + [[UIApplication sharedApplication] openURL:self.URL]; + } + + return !appShouldOpenURL; +} + +- (void)webViewDidStartLoad:(MPWebView *)webView +{ + self.refreshButton.enabled = YES; + self.safariButton.enabled = YES; + [self.spinner startAnimating]; + + self.webViewLoadCount++; +} + +- (void)webViewDidFinishLoad:(MPWebView *)webView +{ + self.webViewLoadCount--; + if (self.webViewLoadCount > 0) return; + + self.refreshButton.enabled = YES; + self.safariButton.enabled = YES; + self.backButton.enabled = self.webView.canGoBack; + self.forwardButton.enabled = self.webView.canGoForward; + [self.spinner stopAnimating]; +} + +- (void)webView:(MPWebView *)webView didFailLoadWithError:(NSError *)error +{ + self.webViewLoadCount--; + + self.refreshButton.enabled = YES; + self.safariButton.enabled = YES; + self.backButton.enabled = self.webView.canGoBack; + self.forwardButton.enabled = self.webView.canGoForward; + [self.spinner stopAnimating]; + + // Ignore NSURLErrorDomain error (-999). + if (error.code == NSURLErrorCancelled) return; + + // Ignore "Frame Load Interrupted" errors after navigating to iTunes or the App Store. + if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return; + + MPLogError(@"Ad browser (%p) experienced an error: %@.", self, [error localizedDescription]); +} + +#pragma mark - +#pragma mark Drawing + +- (CGContextRef)createContext +{ + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(nil,27,27,8,0, + colorSpace,(CGBitmapInfo)kCGImageAlphaPremultipliedLast); + CFRelease(colorSpace); + return context; +} + +- (UIImage *)backArrowImage +{ + CGContextRef context = [self createContext]; + CGColorRef fillColor = [[UIColor blackColor] CGColor]; + CGContextSetFillColor(context, CGColorGetComponents(fillColor)); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, 8.0f, 13.0f); + CGContextAddLineToPoint(context, 24.0f, 4.0f); + CGContextAddLineToPoint(context, 24.0f, 22.0f); + CGContextClosePath(context); + CGContextFillPath(context); + + CGImageRef imageRef = CGBitmapContextCreateImage(context); + CGContextRelease(context); + + UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; + CGImageRelease(imageRef); + return image; +} + +- (UIImage *)forwardArrowImage +{ + CGContextRef context = [self createContext]; + CGColorRef fillColor = [[UIColor blackColor] CGColor]; + CGContextSetFillColor(context, CGColorGetComponents(fillColor)); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, 24.0f, 13.0f); + CGContextAddLineToPoint(context, 8.0f, 4.0f); + CGContextAddLineToPoint(context, 8.0f, 22.0f); + CGContextClosePath(context); + CGContextFillPath(context); + + CGImageRef imageRef = CGBitmapContextCreateImage(context); + CGContextRelease(context); + + UIImage *image = [[UIImage alloc] initWithCGImage:imageRef]; + CGImageRelease(imageRef); + return image; +} + +#pragma mark - + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.xib b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.xib new file mode 100644 index 000000000..661f11519 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdBrowserController.xib @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.h new file mode 100644 index 000000000..19d725d43 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.h @@ -0,0 +1,102 @@ +// +// MPAdConfiguration.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import "MPGlobal.h" + +@class MPRewardedVideoReward; + +enum { + MPAdTypeUnknown = -1, + MPAdTypeBanner = 0, + MPAdTypeInterstitial = 1 +}; +typedef NSUInteger MPAdType; + +extern NSString * const kAdTypeHeaderKey; +extern NSString * const kAdUnitWarmingUpHeaderKey; +extern NSString * const kClickthroughHeaderKey; +extern NSString * const kCreativeIdHeaderKey; +extern NSString * const kCustomSelectorHeaderKey; +extern NSString * const kCustomEventClassNameHeaderKey; +extern NSString * const kCustomEventClassDataHeaderKey; +extern NSString * const kFailUrlHeaderKey; +extern NSString * const kHeightHeaderKey; +extern NSString * const kImpressionTrackerHeaderKey; +extern NSString * const kInterceptLinksHeaderKey; +extern NSString * const kLaunchpageHeaderKey; +extern NSString * const kNativeSDKParametersHeaderKey; +extern NSString * const kNetworkTypeHeaderKey; +extern NSString * const kRefreshTimeHeaderKey; +extern NSString * const kAdTimeoutHeaderKey; +extern NSString * const kScrollableHeaderKey; +extern NSString * const kWidthHeaderKey; +extern NSString * const kDspCreativeIdKey; +extern NSString * const kPrecacheRequiredKey; +extern NSString * const kIsVastVideoPlayerKey; +extern NSString * const kRewardedVideoCurrencyNameHeaderKey; +extern NSString * const kRewardedVideoCurrencyAmountHeaderKey; +extern NSString * const kRewardedVideoCompletionUrlHeaderKey; +extern NSString * const kRewardedPlayableDurationHeaderKey; +extern NSString * const kRewardedPlayableRewardOnClickHeaderKey; + +extern NSString * const kInterstitialAdTypeHeaderKey; +extern NSString * const kOrientationTypeHeaderKey; + +extern NSString * const kAdTypeHtml; +extern NSString * const kAdTypeInterstitial; +extern NSString * const kAdTypeMraid; +extern NSString * const kAdTypeClear; +extern NSString * const kAdTypeNative; +extern NSString * const kAdTypeNativeVideo; + +@interface MPAdConfiguration : NSObject + +@property (nonatomic, assign) MPAdType adType; +@property (nonatomic, assign) BOOL adUnitWarmingUp; +@property (nonatomic, copy) NSString *networkType; +@property (nonatomic, assign) CGSize preferredSize; +@property (nonatomic, strong) NSURL *clickTrackingURL; +@property (nonatomic, strong) NSURL *impressionTrackingURL; +@property (nonatomic, strong) NSURL *failoverURL; +@property (nonatomic, strong) NSURL *interceptURLPrefix; +@property (nonatomic, assign) BOOL shouldInterceptLinks; +@property (nonatomic, assign) BOOL scrollable; +@property (nonatomic, assign) NSTimeInterval refreshInterval; +@property (nonatomic, assign) NSTimeInterval adTimeoutInterval; +@property (nonatomic, copy) NSData *adResponseData; +@property (nonatomic, strong) NSDictionary *nativeSDKParameters; +@property (nonatomic, copy) NSString *customSelectorName; +@property (nonatomic, assign) Class customEventClass; +@property (nonatomic, strong) NSDictionary *customEventClassData; +@property (nonatomic, assign) MPInterstitialOrientationType orientationType; +@property (nonatomic, copy) NSString *dspCreativeId; +@property (nonatomic, assign) BOOL precacheRequired; +@property (nonatomic, assign) BOOL isVastVideoPlayer; +@property (nonatomic, strong) NSDate *creationTimestamp; +@property (nonatomic, copy) NSString *creativeId; +@property (nonatomic, copy) NSString *headerAdType; +@property (nonatomic, assign) NSInteger nativeVideoPlayVisiblePercent; +@property (nonatomic, assign) NSInteger nativeVideoPauseVisiblePercent; +@property (nonatomic, assign) NSInteger nativeVideoImpressionMinVisiblePercent; +@property (nonatomic, assign) NSTimeInterval nativeVideoImpressionVisible; +@property (nonatomic, assign) NSTimeInterval nativeVideoMaxBufferingTime; +@property (nonatomic) NSDictionary *nativeVideoTrackers; +@property (nonatomic) MPRewardedVideoReward *rewardedVideoReward; +@property (nonatomic, copy) NSString *rewardedVideoCompletionUrl; +@property (nonatomic, assign) NSTimeInterval rewardedPlayableDuration; +@property (nonatomic, assign) BOOL rewardedPlayableShouldRewardOnClick; +//TODO: Remove `forceUIWebView` once WKWebView is proven +@property (nonatomic, assign) BOOL forceUIWebView; + +- (id)initWithHeaders:(NSDictionary *)headers data:(NSData *)data; + +- (BOOL)hasPreferredSize; +- (NSString *)adResponseHTMLString; +- (NSString *)clickDetectionURLPrefix; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.m new file mode 100644 index 000000000..459f98902 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdConfiguration.m @@ -0,0 +1,413 @@ +// +// MPAdConfiguration.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPAdConfiguration.h" + +#import "MPConstants.h" +#import "MPLogging.h" +#import "math.h" +#import "NSJSONSerialization+MPAdditions.h" +#import "MPRewardedVideoReward.h" +#import "MPVASTTrackingEvent.h" + +NSString * const kAdTypeHeaderKey = @"X-Adtype"; +NSString * const kAdUnitWarmingUpHeaderKey = @"X-Warmup"; +NSString * const kClickthroughHeaderKey = @"X-Clickthrough"; +NSString * const kCreativeIdHeaderKey = @"X-CreativeId"; +NSString * const kCustomSelectorHeaderKey = @"X-Customselector"; +NSString * const kCustomEventClassNameHeaderKey = @"X-Custom-Event-Class-Name"; +NSString * const kCustomEventClassDataHeaderKey = @"X-Custom-Event-Class-Data"; +NSString * const kFailUrlHeaderKey = @"X-Failurl"; +NSString * const kHeightHeaderKey = @"X-Height"; +NSString * const kImpressionTrackerHeaderKey = @"X-Imptracker"; +NSString * const kInterceptLinksHeaderKey = @"X-Interceptlinks"; +NSString * const kLaunchpageHeaderKey = @"X-Launchpage"; +NSString * const kNativeSDKParametersHeaderKey = @"X-Nativeparams"; +NSString * const kNetworkTypeHeaderKey = @"X-Networktype"; +NSString * const kRefreshTimeHeaderKey = @"X-Refreshtime"; +NSString * const kAdTimeoutHeaderKey = @"X-AdTimeout"; +NSString * const kScrollableHeaderKey = @"X-Scrollable"; +NSString * const kWidthHeaderKey = @"X-Width"; +NSString * const kDspCreativeIdKey = @"X-DspCreativeid"; +NSString * const kPrecacheRequiredKey = @"X-PrecacheRequired"; +NSString * const kIsVastVideoPlayerKey = @"X-VastVideoPlayer"; +//TODO: Remove `kForceUIWebViewKey` once WKWebView is proven +NSString * const kForceUIWebViewKey = @"X-ForceUIWebView"; + +NSString * const kInterstitialAdTypeHeaderKey = @"X-Fulladtype"; +NSString * const kOrientationTypeHeaderKey = @"X-Orientation"; + +NSString * const kNativeVideoPlayVisiblePercentHeaderKey = @"X-Play-Visible-Percent"; +NSString * const kNativeVideoPauseVisiblePercentHeaderKey = @"X-Pause-Visible-Percent"; +NSString * const kNativeVideoImpressionMinVisiblePercentHeaderKey = @"X-Impression-Min-Visible-Percent"; +NSString * const kNativeVideoImpressionVisibleMsHeaderKey = @"X-Impression-Visible-Ms"; +NSString * const kNativeVideoMaxBufferingTimeMsHeaderKey = @"X-Max-Buffer-Ms"; +NSString * const kNativeVideoTrackersHeaderKey = @"X-Video-Trackers"; + +NSString * const kAdTypeHtml = @"html"; +NSString * const kAdTypeInterstitial = @"interstitial"; +NSString * const kAdTypeMraid = @"mraid"; +NSString * const kAdTypeClear = @"clear"; +NSString * const kAdTypeNative = @"json"; +NSString * const kAdTypeNativeVideo = @"json_video"; + +// rewarded video +NSString * const kRewardedVideoCurrencyNameHeaderKey = @"X-Rewarded-Video-Currency-Name"; +NSString * const kRewardedVideoCurrencyAmountHeaderKey = @"X-Rewarded-Video-Currency-Amount"; +NSString * const kRewardedVideoCompletionUrlHeaderKey = @"X-Rewarded-Video-Completion-Url"; + +// rewarded playables +NSString * const kRewardedPlayableDurationHeaderKey = @"X-Rewarded-Duration"; +NSString * const kRewardedPlayableRewardOnClickHeaderKey = @"X-Should-Reward-On-Click"; + +// native video +NSString * const kNativeVideoTrackerUrlMacro = @"%%VIDEO_EVENT%%"; +NSString * const kNativeVideoTrackerEventsHeaderKey = @"events"; +NSString * const kNativeVideoTrackerUrlsHeaderKey = @"urls"; +NSString * const kNativeVideoTrackerEventDictionaryKey = @"event"; +NSString * const kNativeVideoTrackerTextDictionaryKey = @"text"; + + +@interface MPAdConfiguration () + +@property (nonatomic, copy) NSString *adResponseHTMLString; + +- (MPAdType)adTypeFromHeaders:(NSDictionary *)headers; +- (NSString *)networkTypeFromHeaders:(NSDictionary *)headers; +- (NSTimeInterval)refreshIntervalFromHeaders:(NSDictionary *)headers; +- (NSDictionary *)dictionaryFromHeaders:(NSDictionary *)headers forKey:(NSString *)key; +- (NSURL *)URLFromHeaders:(NSDictionary *)headers forKey:(NSString *)key; +- (Class)setUpCustomEventClassFromHeaders:(NSDictionary *)headers; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPAdConfiguration + +- (id)initWithHeaders:(NSDictionary *)headers data:(NSData *)data +{ + self = [super init]; + if (self) { + self.adResponseData = data; + + self.adType = [self adTypeFromHeaders:headers]; + + self.adUnitWarmingUp = [[headers objectForKey:kAdUnitWarmingUpHeaderKey] boolValue]; + + self.networkType = [self networkTypeFromHeaders:headers]; + self.networkType = self.networkType ? self.networkType : @""; + + self.preferredSize = CGSizeMake([[headers objectForKey:kWidthHeaderKey] floatValue], + [[headers objectForKey:kHeightHeaderKey] floatValue]); + + self.clickTrackingURL = [self URLFromHeaders:headers + forKey:kClickthroughHeaderKey]; + self.impressionTrackingURL = [self URLFromHeaders:headers + forKey:kImpressionTrackerHeaderKey]; + self.failoverURL = [self URLFromHeaders:headers + forKey:kFailUrlHeaderKey]; + self.interceptURLPrefix = [self URLFromHeaders:headers + forKey:kLaunchpageHeaderKey]; + + NSNumber *shouldInterceptLinks = [headers objectForKey:kInterceptLinksHeaderKey]; + self.shouldInterceptLinks = shouldInterceptLinks ? [shouldInterceptLinks boolValue] : YES; + self.scrollable = [[headers objectForKey:kScrollableHeaderKey] boolValue]; + self.refreshInterval = [self refreshIntervalFromHeaders:headers]; + self.adTimeoutInterval = [self timeIntervalFromHeaders:headers forKey:kAdTimeoutHeaderKey]; + + + self.nativeSDKParameters = [self dictionaryFromHeaders:headers + forKey:kNativeSDKParametersHeaderKey]; + self.customSelectorName = [headers objectForKey:kCustomSelectorHeaderKey]; + + self.orientationType = [self orientationTypeFromHeaders:headers]; + + self.customEventClass = [self setUpCustomEventClassFromHeaders:headers]; + + self.customEventClassData = [self customEventClassDataFromHeaders:headers]; + + self.dspCreativeId = [headers objectForKey:kDspCreativeIdKey]; + + self.precacheRequired = [[headers objectForKey:kPrecacheRequiredKey] boolValue]; + + self.isVastVideoPlayer = [[headers objectForKey:kIsVastVideoPlayerKey] boolValue]; + + self.forceUIWebView = [[headers objectForKey:kForceUIWebViewKey] boolValue]; + + self.creationTimestamp = [NSDate date]; + + self.creativeId = [headers objectForKey:kCreativeIdHeaderKey]; + + self.headerAdType = [headers objectForKey:kAdTypeHeaderKey]; + + self.nativeVideoPlayVisiblePercent = [self percentFromHeaders:headers forKey:kNativeVideoPlayVisiblePercentHeaderKey]; + + self.nativeVideoPauseVisiblePercent = [self percentFromHeaders:headers forKey:kNativeVideoPauseVisiblePercentHeaderKey]; + + self.nativeVideoImpressionMinVisiblePercent = [self percentFromHeaders:headers forKey:kNativeVideoImpressionMinVisiblePercentHeaderKey]; + + self.nativeVideoImpressionVisible = [self timeIntervalFromMsHeaders:headers forKey:kNativeVideoImpressionVisibleMsHeaderKey]; + + self.nativeVideoMaxBufferingTime = [self timeIntervalFromMsHeaders:headers forKey:kNativeVideoMaxBufferingTimeMsHeaderKey]; + + self.nativeVideoTrackers = [self nativeVideoTrackersFromHeaders:headers key:kNativeVideoTrackersHeaderKey]; + + + // rewarded video + NSString *currencyName = [headers objectForKey:kRewardedVideoCurrencyNameHeaderKey]; + NSNumber *currencyAmount = [self adAmountFromHeaders:headers key:kRewardedVideoCurrencyAmountHeaderKey]; + if (!currencyName) { + currencyName = kMPRewardedVideoRewardCurrencyTypeUnspecified; + } + if (currencyAmount.integerValue > 0 ) { + self.rewardedVideoReward = [[MPRewardedVideoReward alloc] initWithCurrencyType:currencyName amount:currencyAmount]; + } else { + self.rewardedVideoReward = [[MPRewardedVideoReward alloc] initWithCurrencyType:currencyName amount:@(kMPRewardedVideoRewardCurrencyAmountUnspecified)]; + } + + self.rewardedVideoCompletionUrl = [headers objectForKey:kRewardedVideoCompletionUrlHeaderKey]; + + // rewarded playables + self.rewardedPlayableDuration = [self timeIntervalFromHeaders:headers forKey:kRewardedPlayableDurationHeaderKey]; + self.rewardedPlayableShouldRewardOnClick = [[headers objectForKey:kRewardedPlayableRewardOnClickHeaderKey] boolValue]; + } + return self; +} + +- (Class)setUpCustomEventClassFromHeaders:(NSDictionary *)headers +{ + NSString *customEventClassName = [headers objectForKey:kCustomEventClassNameHeaderKey]; + + NSMutableDictionary *convertedCustomEvents = [NSMutableDictionary dictionary]; + if (self.adType == MPAdTypeBanner) { + [convertedCustomEvents setObject:@"MPGoogleAdMobBannerCustomEvent" forKey:@"admob_native"]; + [convertedCustomEvents setObject:@"MPMillennialBannerCustomEvent" forKey:@"millennial_native"]; + [convertedCustomEvents setObject:@"MPHTMLBannerCustomEvent" forKey:@"html"]; + [convertedCustomEvents setObject:@"MPMRAIDBannerCustomEvent" forKey:@"mraid"]; + [convertedCustomEvents setObject:@"MOPUBNativeVideoCustomEvent" forKey:@"json_video"]; + [convertedCustomEvents setObject:@"MPMoPubNativeCustomEvent" forKey:@"json"]; + } else if (self.adType == MPAdTypeInterstitial) { + [convertedCustomEvents setObject:@"MPGoogleAdMobInterstitialCustomEvent" forKey:@"admob_full"]; + [convertedCustomEvents setObject:@"MPMillennialInterstitialCustomEvent" forKey:@"millennial_full"]; + [convertedCustomEvents setObject:@"MPHTMLInterstitialCustomEvent" forKey:@"html"]; + [convertedCustomEvents setObject:@"MPMRAIDInterstitialCustomEvent" forKey:@"mraid"]; + [convertedCustomEvents setObject:@"MPMoPubRewardedVideoCustomEvent" forKey:@"rewarded_video"]; + [convertedCustomEvents setObject:@"MPMoPubRewardedPlayableCustomEvent" forKey:@"rewarded_playable"]; + } + if ([convertedCustomEvents objectForKey:self.networkType]) { + customEventClassName = [convertedCustomEvents objectForKey:self.networkType]; + } + + Class customEventClass = NSClassFromString(customEventClassName); + + if (customEventClassName && !customEventClass) { + MPLogWarn(@"Could not find custom event class named %@", customEventClassName); + } + + return customEventClass; +} + + + +- (NSDictionary *)customEventClassDataFromHeaders:(NSDictionary *)headers +{ + NSDictionary *result = [self dictionaryFromHeaders:headers forKey:kCustomEventClassDataHeaderKey]; + if (!result) { + result = [self dictionaryFromHeaders:headers forKey:kNativeSDKParametersHeaderKey]; + } + return result; +} + + +- (BOOL)hasPreferredSize +{ + return (self.preferredSize.width > 0 && self.preferredSize.height > 0); +} + +- (NSString *)adResponseHTMLString +{ + if (!_adResponseHTMLString) { + self.adResponseHTMLString = [[NSString alloc] initWithData:self.adResponseData + encoding:NSUTF8StringEncoding]; + } + + return _adResponseHTMLString; +} + +- (NSString *)clickDetectionURLPrefix +{ + return self.interceptURLPrefix.absoluteString ? self.interceptURLPrefix.absoluteString : @""; +} + +#pragma mark - Private + +- (MPAdType)adTypeFromHeaders:(NSDictionary *)headers +{ + NSString *adTypeString = [headers objectForKey:kAdTypeHeaderKey]; + + if ([adTypeString isEqualToString:@"interstitial"] || [adTypeString isEqualToString:@"rewarded_video"] || [adTypeString isEqualToString:@"rewarded_playable"]) { + return MPAdTypeInterstitial; + } else if (adTypeString && + [headers objectForKey:kOrientationTypeHeaderKey]) { + return MPAdTypeInterstitial; + } else if (adTypeString) { + return MPAdTypeBanner; + } else { + return MPAdTypeUnknown; + } +} + +- (NSString *)networkTypeFromHeaders:(NSDictionary *)headers +{ + NSString *adTypeString = [headers objectForKey:kAdTypeHeaderKey]; + if ([adTypeString isEqualToString:@"interstitial"]) { + return [headers objectForKey:kInterstitialAdTypeHeaderKey]; + } else { + return adTypeString; + } +} + +- (NSURL *)URLFromHeaders:(NSDictionary *)headers forKey:(NSString *)key +{ + NSString *URLString = [headers objectForKey:key]; + return URLString ? [NSURL URLWithString:URLString] : nil; +} + +- (NSDictionary *)dictionaryFromHeaders:(NSDictionary *)headers forKey:(NSString *)key +{ + NSData *data = [(NSString *)[headers objectForKey:key] dataUsingEncoding:NSUTF8StringEncoding]; + NSDictionary *JSONFromHeaders = nil; + if (data) { + JSONFromHeaders = [NSJSONSerialization mp_JSONObjectWithData:data options:NSJSONReadingMutableContainers clearNullObjects:YES error:nil]; + } + return JSONFromHeaders; +} + +- (NSTimeInterval)refreshIntervalFromHeaders:(NSDictionary *)headers +{ + NSString *intervalString = [headers objectForKey:kRefreshTimeHeaderKey]; + NSTimeInterval interval = -1; + if (intervalString) { + interval = [intervalString doubleValue]; + if (interval < MINIMUM_REFRESH_INTERVAL) { + interval = MINIMUM_REFRESH_INTERVAL; + } + } + return interval; +} + +- (NSTimeInterval)timeIntervalFromHeaders:(NSDictionary *)headers forKey:(NSString *)key +{ + NSString *intervalString = [headers objectForKey:key]; + NSTimeInterval interval = -1; + if (intervalString) { + int parsedInt = -1; + BOOL isNumber = [[NSScanner scannerWithString:intervalString] scanInt:&parsedInt]; + if (isNumber && parsedInt >= 0) { + interval = parsedInt; + } + } + + return interval; +} + +- (NSTimeInterval)timeIntervalFromMsHeaders:(NSDictionary *)headers forKey:(NSString *)key +{ + NSString *msString = [headers objectForKey:key]; + NSTimeInterval interval = -1; + if (msString) { + int parsedInt = -1; + BOOL isNumber = [[NSScanner scannerWithString:msString] scanInt:&parsedInt]; + if (isNumber && parsedInt >= 0) { + interval = parsedInt / 1000.0f; + } + } + + return interval; +} + +- (NSInteger)percentFromHeaders:(NSDictionary *)headers forKey:(NSString *)key +{ + NSString *percentString = [headers objectForKey:key]; + NSInteger percent = -1; + if (percentString) { + int parsedInt = -1; + BOOL isNumber = [[NSScanner scannerWithString:percentString] scanInt:&parsedInt]; + if (isNumber && parsedInt >= 0 && parsedInt <= 100) { + percent = parsedInt; + } + } + + return percent; +} + +- (NSNumber *)adAmountFromHeaders:(NSDictionary *)headers key:(NSString *)key +{ + NSString *amountString = [headers objectForKey:key]; + NSNumber *amount = @(-1); + if (amountString) { + int parsedInt = -1; + BOOL isNumber = [[NSScanner scannerWithString:amountString] scanInt:&parsedInt]; + if (isNumber && parsedInt >= 0) { + amount = @(parsedInt); + } + } + + return amount; +} + +- (MPInterstitialOrientationType)orientationTypeFromHeaders:(NSDictionary *)headers +{ + NSString *orientation = [headers objectForKey:kOrientationTypeHeaderKey]; + if ([orientation isEqualToString:@"p"]) { + return MPInterstitialOrientationTypePortrait; + } else if ([orientation isEqualToString:@"l"]) { + return MPInterstitialOrientationTypeLandscape; + } else { + return MPInterstitialOrientationTypeAll; + } +} + +- (NSDictionary *)nativeVideoTrackersFromHeaders:(NSDictionary *)headers key:(NSString *)key +{ + NSDictionary *dictFromHeader = [self dictionaryFromHeaders:headers forKey:key]; + if (!dictFromHeader) { + return nil; + } + NSMutableDictionary *videoTrackerDict = [NSMutableDictionary new]; + NSArray *events = dictFromHeader[kNativeVideoTrackerEventsHeaderKey]; + NSArray *urls = dictFromHeader[kNativeVideoTrackerUrlsHeaderKey]; + NSSet *supportedEvents = [NSSet setWithObjects:MPVASTTrackingEventTypeStart, MPVASTTrackingEventTypeFirstQuartile, MPVASTTrackingEventTypeMidpoint, MPVASTTrackingEventTypeThirdQuartile, MPVASTTrackingEventTypeComplete, nil]; + for (NSString *event in events) { + if (![supportedEvents containsObject:event]) { + continue; + } + [self setVideoTrackers:videoTrackerDict event:event urls:urls]; + } + if (videoTrackerDict.count == 0) { + return nil; + } + return videoTrackerDict; +} + +- (void)setVideoTrackers:(NSMutableDictionary *)videoTrackerDict event:(NSString *)event urls:(NSArray *)urls { + NSMutableArray *trackers = [NSMutableArray new]; + for (NSString *url in urls) { + if ([url rangeOfString:kNativeVideoTrackerUrlMacro].location != NSNotFound) { + NSString *trackerUrl = [url stringByReplacingOccurrencesOfString:kNativeVideoTrackerUrlMacro withString:event]; + NSDictionary *dict = @{kNativeVideoTrackerEventDictionaryKey:event, kNativeVideoTrackerTextDictionaryKey:trackerUrl}; + MPVASTTrackingEvent *tracker = [[MPVASTTrackingEvent alloc] initWithDictionary:dict]; + [trackers addObject:tracker]; + } + } + if (trackers.count > 0) { + videoTrackerDict[event] = trackers; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.h new file mode 100644 index 000000000..ff7b3fb54 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.h @@ -0,0 +1,41 @@ +// +// MPAdDestinationDisplayAgent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPActivityViewControllerHelper+TweetShare.h" +#import "MPURLResolver.h" +#import "MPProgressOverlayView.h" +#import "MPAdBrowserController.h" +#import "MPStoreKitProvider.h" + +@protocol MPAdDestinationDisplayAgentDelegate; + +@interface MPAdDestinationDisplayAgent : NSObject + +@property (nonatomic, weak) id delegate; + ++ (MPAdDestinationDisplayAgent *)agentWithDelegate:(id)delegate; +- (void)displayDestinationForURL:(NSURL *)URL; +- (void)cancel; + +@end + +@protocol MPAdDestinationDisplayAgentDelegate + +- (UIViewController *)viewControllerForPresentingModalView; +- (void)displayAgentWillPresentModal; +- (void)displayAgentWillLeaveApplication; +- (void)displayAgentDidDismissModal; + +@optional + +- (MPAdConfiguration *)adConfiguration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.m new file mode 100644 index 000000000..4ef1a35aa --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdDestinationDisplayAgent.m @@ -0,0 +1,372 @@ +// +// MPAdDestinationDisplayAgent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPAdDestinationDisplayAgent.h" +#import "MPCoreInstanceProvider.h" +#import "MPLastResortDelegate.h" +#import "MPLogging.h" +#import "NSURL+MPAdditions.h" +#import "MPCoreInstanceProvider.h" +#import "MPAnalyticsTracker.h" + +static NSString * const kDisplayAgentErrorDomain = @"com.mopub.displayagent"; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPAdDestinationDisplayAgent () + +@property (nonatomic, strong) MPURLResolver *resolver; +@property (nonatomic, strong) MPURLResolver *enhancedDeeplinkFallbackResolver; +@property (nonatomic, strong) MPProgressOverlayView *overlayView; +@property (nonatomic, assign) BOOL isLoadingDestination; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 +@property (nonatomic, strong) SKStoreProductViewController *storeKitController; +#endif + +@property (nonatomic, strong) MPAdBrowserController *browserController; +@property (nonatomic, strong) MPTelephoneConfirmationController *telephoneConfirmationController; +@property (nonatomic, strong) MPActivityViewControllerHelper *activityViewControllerHelper; + +- (void)presentStoreKitControllerWithItemIdentifier:(NSString *)identifier fallbackURL:(NSURL *)URL; +- (void)hideOverlay; +- (void)hideModalAndNotifyDelegate; +- (void)dismissAllModalContent; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPAdDestinationDisplayAgent + +@synthesize delegate = _delegate; +@synthesize resolver = _resolver; +@synthesize isLoadingDestination = _isLoadingDestination; + ++ (MPAdDestinationDisplayAgent *)agentWithDelegate:(id)delegate +{ + MPAdDestinationDisplayAgent *agent = [[MPAdDestinationDisplayAgent alloc] init]; + agent.delegate = delegate; + agent.overlayView = [[MPProgressOverlayView alloc] initWithDelegate:agent]; + agent.activityViewControllerHelper = [[MPActivityViewControllerHelper alloc] initWithDelegate:agent]; + return agent; +} + +- (void)dealloc +{ + [self dismissAllModalContent]; + + self.overlayView.delegate = nil; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 + // XXX: If this display agent is deallocated while a StoreKit controller is still on-screen, + // nil-ing out the controller's delegate would leave us with no way to dismiss the controller + // in the future. Therefore, we change the controller's delegate to a singleton object which + // implements SKStoreProductViewControllerDelegate and is always around. + self.storeKitController.delegate = [MPLastResortDelegate sharedDelegate]; +#endif + self.browserController.delegate = nil; + +} + +- (void)dismissAllModalContent +{ + [self.overlayView hide]; +} + +- (void)displayDestinationForURL:(NSURL *)URL +{ + if (self.isLoadingDestination) return; + self.isLoadingDestination = YES; + + [self.delegate displayAgentWillPresentModal]; + [self.overlayView show]; + + [self.resolver cancel]; + [self.enhancedDeeplinkFallbackResolver cancel]; + + __weak typeof(self) weakSelf = self; + self.resolver = [[MPCoreInstanceProvider sharedProvider] buildMPURLResolverWithURL:URL completion:^(MPURLActionInfo *suggestedAction, NSError *error) { + typeof(self) strongSelf = weakSelf; + if (strongSelf) { + if (error) { + [strongSelf failedToResolveURLWithError:error]; + } else { + [strongSelf handleSuggestedURLAction:suggestedAction isResolvingEnhancedDeeplink:NO]; + } + } + }]; + + [self.resolver start]; +} + +- (void)cancel +{ + if (self.isLoadingDestination) { + [self.resolver cancel]; + [self.enhancedDeeplinkFallbackResolver cancel]; + [self hideOverlay]; + [self completeDestinationLoading]; + } +} + +- (BOOL)handleSuggestedURLAction:(MPURLActionInfo *)actionInfo isResolvingEnhancedDeeplink:(BOOL)isResolvingEnhancedDeeplink +{ + if (actionInfo == nil) { + [self failedToResolveURLWithError:[NSError errorWithDomain:kDisplayAgentErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Invalid URL action"}]]; + return NO; + } + + BOOL success = YES; + + switch (actionInfo.actionType) { + case MPURLActionTypeStoreKit: + [self showStoreKitProductWithParameter:actionInfo.iTunesItemIdentifier + fallbackURL:actionInfo.iTunesStoreFallbackURL]; + break; + case MPURLActionTypeGenericDeeplink: + [self openURLInApplication:actionInfo.deeplinkURL]; + break; + case MPURLActionTypeEnhancedDeeplink: + if (isResolvingEnhancedDeeplink) { + // We end up here if we encounter a nested enhanced deeplink. We'll simply disallow + // this to avoid getting into cycles. + [self failedToResolveURLWithError:[NSError errorWithDomain:kDisplayAgentErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"Cannot resolve an enhanced deeplink that is nested within another enhanced deeplink."}]]; + success = NO; + } else { + [self handleEnhancedDeeplinkRequest:actionInfo.enhancedDeeplinkRequest]; + } + break; + case MPURLActionTypeOpenInSafari: + [self openURLInApplication:actionInfo.safariDestinationURL]; + break; + case MPURLActionTypeOpenInWebView: + [self showWebViewWithHTMLString:actionInfo.HTTPResponseString + baseURL:actionInfo.webViewBaseURL]; + break; + case MPURLActionTypeOpenURLInWebView: + [self showWebViewWithURL:actionInfo.originalURL]; + break; + case MPURLActionTypeShare: + [self openShareURL:actionInfo.shareURL]; + break; + default: + [self failedToResolveURLWithError:[NSError errorWithDomain:kDisplayAgentErrorDomain code:-2 userInfo:@{NSLocalizedDescriptionKey: @"Unrecognized URL action type."}]]; + success = NO; + break; + } + + return success; +} + +- (void)handleEnhancedDeeplinkRequest:(MPEnhancedDeeplinkRequest *)request +{ + BOOL didOpenSuccessfully = [[UIApplication sharedApplication] openURL:request.primaryURL]; + if (didOpenSuccessfully) { + [self hideOverlay]; + [self.delegate displayAgentWillLeaveApplication]; + [self completeDestinationLoading]; + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] sendTrackingRequestForURLs:request.primaryTrackingURLs]; + } else if (request.fallbackURL) { + [self handleEnhancedDeeplinkFallbackForRequest:request]; + } else { + [self openURLInApplication:request.originalURL]; + } +} + +- (void)handleEnhancedDeeplinkFallbackForRequest:(MPEnhancedDeeplinkRequest *)request; +{ + __weak typeof(self) weakSelf = self; + [self.enhancedDeeplinkFallbackResolver cancel]; + self.enhancedDeeplinkFallbackResolver = [[MPCoreInstanceProvider sharedProvider] buildMPURLResolverWithURL:request.fallbackURL completion:^(MPURLActionInfo *actionInfo, NSError *error) { + typeof(self) strongSelf = weakSelf; + if (strongSelf) { + if (error) { + // If the resolver fails, just treat the entire original URL as a regular deeplink. + [strongSelf openURLInApplication:request.originalURL]; + } else { + // Otherwise, the resolver will return us a URL action. We process that action + // normally with one exception: we don't follow any nested enhanced deeplinks. + BOOL success = [strongSelf handleSuggestedURLAction:actionInfo isResolvingEnhancedDeeplink:YES]; + if (success) { + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] sendTrackingRequestForURLs:request.fallbackTrackingURLs]; + } + } + } + }]; + [self.enhancedDeeplinkFallbackResolver start]; +} + +- (void)showWebViewWithHTMLString:(NSString *)HTMLString baseURL:(NSURL *)URL +{ + self.browserController = [[MPAdBrowserController alloc] initWithURL:URL + HTMLString:HTMLString + delegate:self]; + [self showAdBrowserController:self.browserController]; +} + +- (void)showWebViewWithURL:(NSURL *)URL { + self.browserController = [[MPAdBrowserController alloc] initWithURL:URL + delegate:self]; + [self showAdBrowserController:self.browserController]; +} + +- (void)showAdBrowserController:(MPAdBrowserController *)adBrowserController { + [self hideOverlay]; + + self.browserController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + [[self.delegate viewControllerForPresentingModalView] presentViewController:self.browserController + animated:MP_ANIMATED + completion:nil]; +} + +- (void)showStoreKitProductWithParameter:(NSString *)parameter fallbackURL:(NSURL *)URL +{ + if ([MPStoreKitProvider deviceHasStoreKit]) { + [self presentStoreKitControllerWithItemIdentifier:parameter fallbackURL:URL]; + } else { + [self openURLInApplication:URL]; + } +} + +- (void)openURLInApplication:(NSURL *)URL +{ + [self hideOverlay]; + + if ([URL mp_hasTelephoneScheme] || [URL mp_hasTelephonePromptScheme]) { + [self interceptTelephoneURL:URL]; + } else { + BOOL didOpenSuccessfully = [[UIApplication sharedApplication] openURL:URL]; + if (didOpenSuccessfully) { + [self.delegate displayAgentWillLeaveApplication]; + } + [self completeDestinationLoading]; + } +} + +- (BOOL)openShareURL:(NSURL *)URL +{ + MPLogDebug(@"MPAdDestinationDisplayAgent - loading Share URL: %@", URL); + MPMoPubShareHostCommand command = [URL mp_MoPubShareHostCommand]; + switch (command) { + case MPMoPubShareHostCommandTweet: + return [self.activityViewControllerHelper presentActivityViewControllerWithTweetShareURL:URL]; + default: + MPLogWarn(@"MPAdDestinationDisplayAgent - unsupported Share URL: %@", [URL absoluteString]); + return NO; + } +} + +- (void)interceptTelephoneURL:(NSURL *)URL +{ + __weak MPAdDestinationDisplayAgent *weakSelf = self; + self.telephoneConfirmationController = [[MPTelephoneConfirmationController alloc] initWithURL:URL clickHandler:^(NSURL *targetTelephoneURL, BOOL confirmed) { + MPAdDestinationDisplayAgent *strongSelf = weakSelf; + if (strongSelf) { + if (confirmed) { + [strongSelf.delegate displayAgentWillLeaveApplication]; + [[UIApplication sharedApplication] openURL:targetTelephoneURL]; + } + [strongSelf completeDestinationLoading]; + } + }]; + + [self.telephoneConfirmationController show]; +} + +- (void)failedToResolveURLWithError:(NSError *)error +{ + [self hideOverlay]; + [self completeDestinationLoading]; +} + +- (void)completeDestinationLoading +{ + self.isLoadingDestination = NO; + [self.delegate displayAgentDidDismissModal]; +} + +- (void)presentStoreKitControllerWithItemIdentifier:(NSString *)identifier fallbackURL:(NSURL *)URL +{ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 + self.storeKitController = [MPStoreKitProvider buildController]; + self.storeKitController.delegate = self; + + NSDictionary *parameters = [NSDictionary dictionaryWithObject:identifier + forKey:SKStoreProductParameterITunesItemIdentifier]; + [self.storeKitController loadProductWithParameters:parameters completionBlock:nil]; + + [self hideOverlay]; + [[self.delegate viewControllerForPresentingModalView] presentViewController:self.storeKitController animated:MP_ANIMATED completion:nil]; +#endif +} + +#pragma mark - + +- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController +{ + self.isLoadingDestination = NO; + [self hideModalAndNotifyDelegate]; +} + +#pragma mark - + +- (void)dismissBrowserController:(MPAdBrowserController *)browserController animated:(BOOL)animated +{ + self.isLoadingDestination = NO; + [self hideModalAndNotifyDelegate]; +} + +- (MPAdConfiguration *)adConfiguration +{ + if ([self.delegate respondsToSelector:@selector(adConfiguration)]) { + return [self.delegate adConfiguration]; + } + + return nil; +} + +#pragma mark - + +- (void)overlayCancelButtonPressed +{ + [self cancel]; +} + +#pragma mark - Convenience Methods + +- (void)hideModalAndNotifyDelegate +{ + [[self.delegate viewControllerForPresentingModalView] dismissViewControllerAnimated:MP_ANIMATED completion:^{ + [self.delegate displayAgentDidDismissModal]; + }]; +} + +- (void)hideOverlay +{ + [self.overlayView hide]; +} + +#pragma mark + +- (UIViewController *)viewControllerForPresentingActivityViewController +{ + return self.delegate.viewControllerForPresentingModalView; +} + +- (void)activityViewControllerWillPresent +{ + [self hideOverlay]; + self.isLoadingDestination = NO; + [self.delegate displayAgentWillPresentModal]; +} + +- (void)activityViewControllerDidDismiss +{ + [self.delegate displayAgentDidDismissModal]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.h new file mode 100644 index 000000000..ce4bdf016 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.h @@ -0,0 +1,37 @@ +// +// MPAdServerCommunicator.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import + +#import "MPAdConfiguration.h" +#import "MPGlobal.h" + +@protocol MPAdServerCommunicatorDelegate; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPAdServerCommunicator : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign, readonly) BOOL loading; + +- (id)initWithDelegate:(id)delegate; + +- (void)loadURL:(NSURL *)URL; +- (void)cancel; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPAdServerCommunicatorDelegate + +@required +- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration; +- (void)communicatorDidFailWithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.m new file mode 100644 index 000000000..74837e168 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerCommunicator.m @@ -0,0 +1,165 @@ +// +// MPAdServerCommunicator.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPAdServerCommunicator.h" + +#import "MPAdConfiguration.h" +#import "MPLogging.h" +#import "MPCoreInstanceProvider.h" +#import "MPLogEvent.h" +#import "MPLogEventRecorder.h" + +const NSTimeInterval kRequestTimeoutInterval = 10.0; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPAdServerCommunicator () + +@property (nonatomic, assign, readwrite) BOOL loading; +@property (nonatomic, copy) NSURL *URL; +@property (nonatomic, strong) NSURLConnection *connection; +@property (nonatomic, strong) NSMutableData *responseData; +@property (nonatomic, strong) NSDictionary *responseHeaders; +@property (nonatomic, strong) MPLogEvent *adRequestLatencyEvent; + +- (NSError *)errorForStatusCode:(NSInteger)statusCode; +- (NSURLRequest *)adRequestForURL:(NSURL *)URL; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPAdServerCommunicator + +@synthesize delegate = _delegate; +@synthesize URL = _URL; +@synthesize connection = _connection; +@synthesize responseData = _responseData; +@synthesize responseHeaders = _responseHeaders; +@synthesize loading = _loading; + +- (id)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + self.delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [self.connection cancel]; + +} + +#pragma mark - Public + +- (void)loadURL:(NSURL *)URL +{ + [self cancel]; + self.URL = URL; + + // Start tracking how long it takes to successfully or unsuccessfully retrieve an ad. + self.adRequestLatencyEvent = [[MPLogEvent alloc] initWithEventCategory:MPLogEventCategoryRequests eventName:MPLogEventNameAdRequest]; + self.adRequestLatencyEvent.requestURI = URL.absoluteString; + + self.connection = [NSURLConnection connectionWithRequest:[self adRequestForURL:URL] + delegate:self]; + self.loading = YES; +} + +- (void)cancel +{ + self.adRequestLatencyEvent = nil; + self.loading = NO; + [self.connection cancel]; + self.connection = nil; + self.responseData = nil; + self.responseHeaders = nil; +} + +#pragma mark - NSURLConnection delegate (NSURLConnectionDataDelegate in iOS 5.0+) + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + if ([response respondsToSelector:@selector(statusCode)]) { + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + if (statusCode >= 400) { + // Do not record a logging event if we failed to make a connection. + self.adRequestLatencyEvent = nil; + + [connection cancel]; + self.loading = NO; + [self.delegate communicatorDidFailWithError:[self errorForStatusCode:statusCode]]; + return; + } + } + + self.responseData = [NSMutableData data]; + self.responseHeaders = [(NSHTTPURLResponse *)response allHeaderFields]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + [self.responseData appendData:data]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + // Do not record a logging event if we failed to make a connection. + self.adRequestLatencyEvent = nil; + + self.loading = NO; + [self.delegate communicatorDidFailWithError:error]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + [self.adRequestLatencyEvent recordEndTime]; + self.adRequestLatencyEvent.requestStatusCode = 200; + + MPAdConfiguration *configuration = [[MPAdConfiguration alloc] + initWithHeaders:self.responseHeaders + data:self.responseData]; + MPAdConfigurationLogEventProperties *logEventProperties = + [[MPAdConfigurationLogEventProperties alloc] initWithConfiguration:configuration]; + + // Do not record ads that are warming up. + if (configuration.adUnitWarmingUp) { + self.adRequestLatencyEvent = nil; + } else { + [self.adRequestLatencyEvent setLogEventProperties:logEventProperties]; + MPAddLogEvent(self.adRequestLatencyEvent); + } + + self.loading = NO; + [self.delegate communicatorDidReceiveAdConfiguration:configuration]; +} + +#pragma mark - Internal + +- (NSError *)errorForStatusCode:(NSInteger)statusCode +{ + NSString *errorMessage = [NSString stringWithFormat: + NSLocalizedString(@"MoPub returned status code %d.", + @"Status code error"), + statusCode]; + NSDictionary *errorInfo = [NSDictionary dictionaryWithObject:errorMessage + forKey:NSLocalizedDescriptionKey]; + return [NSError errorWithDomain:@"mopub.com" code:statusCode userInfo:errorInfo]; +} + +- (NSURLRequest *)adRequestForURL:(NSURL *)URL +{ + NSMutableURLRequest *request = [[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:URL]; + [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; + [request setTimeoutInterval:kRequestTimeoutInterval]; + return request; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.h new file mode 100644 index 000000000..2e11954ea --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.h @@ -0,0 +1,35 @@ +// +// MPAdServerURLBuilder.h +// MoPub +// +// Copyright (c) 2012 MoPub. All rights reserved. +// + +#import +#import + +@interface MPAdServerURLBuilder : NSObject + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + testing:(BOOL)testing; + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + versionParameterName:(NSString *)versionParameterName + version:(NSString *)version + testing:(BOOL)testing + desiredAssets:(NSArray *)assets; + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + versionParameterName:(NSString *)versionParameterName + version:(NSString *)version + testing:(BOOL)testing + desiredAssets:(NSArray *)assets + adSequence:(NSInteger)adSequence; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.m new file mode 100644 index 000000000..a98646223 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPAdServerURLBuilder.m @@ -0,0 +1,306 @@ +// +// MPAdServerURLBuilder.m +// MoPub +// +// Copyright (c) 2012 MoPub. All rights reserved. +// + +#import "MPAdServerURLBuilder.h" + +#import "MPConstants.h" +#import "MPGeolocationProvider.h" +#import "MPGlobal.h" +#import "MPKeywordProvider.h" +#import "MPIdentityProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPReachability.h" +#import "MPAPIEndpoints.h" + +static NSString * const kMoPubInterfaceOrientationPortrait = @"p"; +static NSString * const kMoPubInterfaceOrientationLandscape = @"l"; +static NSInteger const kAdSequenceNone = -1; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPAdServerURLBuilder () + ++ (NSString *)queryParameterForKeywords:(NSString *)keywords; ++ (NSString *)queryParameterForOrientation; ++ (NSString *)queryParameterForScaleFactor; ++ (NSString *)queryParameterForTimeZone; ++ (NSString *)queryParameterForLocation:(CLLocation *)location; ++ (NSString *)queryParameterForMRAID; ++ (NSString *)queryParameterForDNT; ++ (NSString *)queryParameterForConnectionType; ++ (NSString *)queryParameterForApplicationVersion; ++ (NSString *)queryParameterForCarrierName; ++ (NSString *)queryParameterForISOCountryCode; ++ (NSString *)queryParameterForMobileNetworkCode; ++ (NSString *)queryParameterForMobileCountryCode; ++ (NSString *)queryParameterForDeviceName; ++ (NSString *)queryParameterForDesiredAdAssets:(NSArray *)assets; ++ (NSString *)queryParameterForAdSequence:(NSInteger)adSequence; ++ (NSString *)queryParameterForPhysicalScreenSize; ++ (NSString *)queryParameterForBundleIdentifier; ++ (NSString *)queryParameterForAppTransportSecurity; ++ (BOOL)advertisingTrackingEnabled; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPAdServerURLBuilder + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + testing:(BOOL)testing +{ + return [self URLWithAdUnitID:adUnitID + keywords:keywords + location:location + versionParameterName:@"nv" + version:MP_SDK_VERSION + testing:testing + desiredAssets:nil]; +} + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + versionParameterName:(NSString *)versionParameterName + version:(NSString *)version + testing:(BOOL)testing + desiredAssets:(NSArray *)assets +{ + + + return [self URLWithAdUnitID:adUnitID + keywords:keywords + location:location + versionParameterName:versionParameterName + version:version + testing:testing + desiredAssets:assets + adSequence:kAdSequenceNone]; +} + ++ (NSURL *)URLWithAdUnitID:(NSString *)adUnitID + keywords:(NSString *)keywords + location:(CLLocation *)location + versionParameterName:(NSString *)versionParameterName + version:(NSString *)version + testing:(BOOL)testing + desiredAssets:(NSArray *)assets + adSequence:(NSInteger)adSequence +{ + NSString *URLString = [NSString stringWithFormat:@"%@?v=%@&udid=%@&id=%@&%@=%@", + [MPAPIEndpoints baseURLStringWithPath:MOPUB_API_PATH_AD_REQUEST testing:testing], + MP_SERVER_VERSION, + [MPIdentityProvider identifier], + [adUnitID stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + versionParameterName, version]; + + URLString = [URLString stringByAppendingString:[self queryParameterForKeywords:keywords]]; + URLString = [URLString stringByAppendingString:[self queryParameterForOrientation]]; + URLString = [URLString stringByAppendingString:[self queryParameterForScaleFactor]]; + URLString = [URLString stringByAppendingString:[self queryParameterForTimeZone]]; + URLString = [URLString stringByAppendingString:[self queryParameterForLocation:location]]; + URLString = [URLString stringByAppendingString:[self queryParameterForMRAID]]; + URLString = [URLString stringByAppendingString:[self queryParameterForDNT]]; + URLString = [URLString stringByAppendingString:[self queryParameterForConnectionType]]; + URLString = [URLString stringByAppendingString:[self queryParameterForApplicationVersion]]; + URLString = [URLString stringByAppendingString:[self queryParameterForCarrierName]]; + URLString = [URLString stringByAppendingString:[self queryParameterForISOCountryCode]]; + URLString = [URLString stringByAppendingString:[self queryParameterForMobileNetworkCode]]; + URLString = [URLString stringByAppendingString:[self queryParameterForMobileCountryCode]]; + URLString = [URLString stringByAppendingString:[self queryParameterForDeviceName]]; + URLString = [URLString stringByAppendingString:[self queryParameterForDesiredAdAssets:assets]]; + URLString = [URLString stringByAppendingString:[self queryParameterForAdSequence:adSequence]]; + URLString = [URLString stringByAppendingString:[self queryParameterForPhysicalScreenSize]]; + URLString = [URLString stringByAppendingString:[self queryParameterForBundleIdentifier]]; + URLString = [URLString stringByAppendingString:[self queryParameterForAppTransportSecurity]]; + + return [NSURL URLWithString:URLString]; +} + + ++ (NSString *)queryParameterForKeywords:(NSString *)keywords +{ + NSMutableArray *keywordsArray = [NSMutableArray array]; + NSString *trimmedKeywords = [keywords stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceCharacterSet]]; + if ([trimmedKeywords length] > 0) { + [keywordsArray addObject:trimmedKeywords]; + } + + // Append the Facebook attribution keyword (if available). + Class fbKeywordProviderClass = NSClassFromString(@"MPFacebookKeywordProvider"); + if ([fbKeywordProviderClass conformsToProtocol:@protocol(MPKeywordProvider)]) + { + NSString *fbAttributionKeyword = [(Class) fbKeywordProviderClass keyword]; + if ([fbAttributionKeyword length] > 0) { + [keywordsArray addObject:fbAttributionKeyword]; + } + } + + if ([keywordsArray count] == 0) { + return @""; + } else { + NSString *keywords = [[keywordsArray componentsJoinedByString:@","] + stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return [NSString stringWithFormat:@"&q=%@", keywords]; + } +} + ++ (NSString *)queryParameterForOrientation +{ + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + NSString *orientString = UIInterfaceOrientationIsPortrait(orientation) ? + kMoPubInterfaceOrientationPortrait : kMoPubInterfaceOrientationLandscape; + return [NSString stringWithFormat:@"&o=%@", orientString]; +} + ++ (NSString *)queryParameterForScaleFactor +{ + return [NSString stringWithFormat:@"&sc=%.1f", MPDeviceScaleFactor()]; +} + ++ (NSString *)queryParameterForTimeZone +{ + static NSDateFormatter *formatter; + @synchronized(self) + { + if (!formatter) formatter = [[NSDateFormatter alloc] init]; + } + [formatter setDateFormat:@"Z"]; + NSDate *today = [NSDate date]; + return [NSString stringWithFormat:@"&z=%@", [formatter stringFromDate:today]]; +} + ++ (NSString *)queryParameterForLocation:(CLLocation *)location +{ + NSString *result = @""; + + CLLocation *bestLocation = location; + CLLocation *locationFromProvider = [[[MPCoreInstanceProvider sharedProvider] sharedMPGeolocationProvider] lastKnownLocation]; + + if (locationFromProvider) { + bestLocation = locationFromProvider; + } + + if (bestLocation && bestLocation.horizontalAccuracy >= 0) { + result = [NSString stringWithFormat:@"&ll=%@,%@", + [NSNumber numberWithDouble:bestLocation.coordinate.latitude], + [NSNumber numberWithDouble:bestLocation.coordinate.longitude]]; + + if (bestLocation.horizontalAccuracy) { + result = [result stringByAppendingFormat:@"&lla=%@", + [NSNumber numberWithDouble:bestLocation.horizontalAccuracy]]; + } + + if (bestLocation == locationFromProvider) { + result = [result stringByAppendingString:@"&llsdk=1"]; + } + + NSTimeInterval locationLastUpdatedMillis = [[NSDate date] timeIntervalSinceDate:bestLocation.timestamp] * 1000.0; + + result = [result stringByAppendingFormat:@"&llf=%.0f", locationLastUpdatedMillis]; + } + + return result; +} + ++ (NSString *)queryParameterForMRAID +{ + if (NSClassFromString(@"MPMRAIDBannerCustomEvent") && + NSClassFromString(@"MPMRAIDInterstitialCustomEvent")) { + return @"&mr=1"; + } else { + return @""; + } +} + ++ (NSString *)queryParameterForDNT +{ + return [self advertisingTrackingEnabled] ? @"" : @"&dnt=1"; +} + ++ (NSString *)queryParameterForConnectionType +{ + return [[[MPCoreInstanceProvider sharedProvider] sharedMPReachability] hasWifi] ? @"&ct=2" : @"&ct=3"; +} + ++ (NSString *)queryParameterForApplicationVersion +{ + NSString *applicationVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; + return [NSString stringWithFormat:@"&av=%@", + [applicationVersion mp_URLEncodedString]]; +} + ++ (NSString *)queryParameterForCarrierName +{ + NSString *carrierName = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"carrierName"]; + return carrierName ? [NSString stringWithFormat:@"&cn=%@", + [carrierName mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForISOCountryCode +{ + NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"isoCountryCode"]; + return code ? [NSString stringWithFormat:@"&iso=%@", [code mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForMobileNetworkCode +{ + NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"mobileNetworkCode"]; + return code ? [NSString stringWithFormat:@"&mnc=%@", [code mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForMobileCountryCode +{ + NSString *code = [[[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo] objectForKey:@"mobileCountryCode"]; + return code ? [NSString stringWithFormat:@"&mcc=%@", [code mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForDeviceName +{ + NSString *deviceName = [[UIDevice currentDevice] mp_hardwareDeviceName]; + return deviceName ? [NSString stringWithFormat:@"&dn=%@", [deviceName mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForDesiredAdAssets:(NSArray *)assets +{ + NSString *concatenatedAssets = [assets componentsJoinedByString:@","]; + return [concatenatedAssets length] ? [NSString stringWithFormat:@"&assets=%@", concatenatedAssets] : @""; +} + ++ (NSString *)queryParameterForAdSequence:(NSInteger)adSequence +{ + return (adSequence >= 0) ? [NSString stringWithFormat:@"&seq=%ld", (long)adSequence] : @""; +} + ++ (NSString *)queryParameterForPhysicalScreenSize +{ + CGSize screenSize = MPScreenResolution(); + + return [NSString stringWithFormat:@"&w=%.0f&h=%.0f", screenSize.width, screenSize.height]; +} + ++ (NSString *)queryParameterForBundleIdentifier +{ + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + return bundleIdentifier ? [NSString stringWithFormat:@"&bundle=%@", [bundleIdentifier mp_URLEncodedString]] : @""; +} + ++ (NSString *)queryParameterForAppTransportSecurity +{ + return [NSString stringWithFormat:@"&ats=%@", @([[MPCoreInstanceProvider sharedProvider] appTransportSecuritySettings])]; +} + ++ (BOOL)advertisingTrackingEnabled +{ + return [MPIdentityProvider advertisingTrackingEnabled]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.h new file mode 100644 index 000000000..d683d1abd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.h @@ -0,0 +1,62 @@ +// +// MPClosableView.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +enum { + MPClosableViewCloseButtonLocationTopRight, + MPClosableViewCloseButtonLocationTopLeft, + MPClosableViewCloseButtonLocationTopCenter, + MPClosableViewCloseButtonLocationBottomRight, + MPClosableViewCloseButtonLocationBottomLeft, + MPClosableViewCloseButtonLocationBottomCenter, + MPClosableViewCloseButtonLocationCenter +}; +typedef NSInteger MPClosableViewCloseButtonLocation; + +enum { + MPClosableViewCloseButtonTypeNone, + MPClosableViewCloseButtonTypeTappableWithoutImage, + MPClosableViewCloseButtonTypeTappableWithImage, +}; +typedef NSInteger MPClosableViewCloseButtonType; + +CGRect MPClosableViewCustomCloseButtonFrame(CGSize size, MPClosableViewCloseButtonLocation closeButtonLocation); + +@protocol MPClosableViewDelegate; + +/** + * `MPClosableView` is composed of a content view and a close button. The close button can + * be positioned at any corner, the center of top and bottom edges, and the center of the view. + * The close button can either be a button that is tappable with image, tappable without an image, + * and completely disabled altogether. Finally, `MPClosableView` keeps track as to whether or not + * it has been tapped. + */ +@interface MPClosableView : UIView + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) MPClosableViewCloseButtonType closeButtonType; +@property (nonatomic, assign) MPClosableViewCloseButtonLocation closeButtonLocation; +@property (nonatomic, readonly) BOOL wasTapped; + +- (instancetype)initWithFrame:(CGRect)frame closeButtonType:(MPClosableViewCloseButtonType)closeButtonType; + +@end + +/** + * `MPClosableViewDelegate` allows an object that implements `MPClosableViewDelegate` to + * be notified when the close button of the `MPClosableView` has been tapped. + */ +@protocol MPClosableViewDelegate + +- (void)closeButtonPressed:(MPClosableView *)closableView; + +@optional + +- (void)closableView:(MPClosableView *)closableView didMoveToWindow:(UIWindow *)window; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.m new file mode 100644 index 000000000..0b7719ab5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPClosableView.m @@ -0,0 +1,163 @@ +// +// MPClosableView.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPClosableView.h" +#import "MPInstanceProvider.h" +#import "MPUserInteractionGestureRecognizer.h" + +static CGFloat kCloseRegionWidth = 50.0f; +static CGFloat kCloseRegionHeight = 50.0f; +static NSString *const kExpandableCloseButtonImageName = @"MPCloseButtonX.png"; + +CGRect MPClosableViewCustomCloseButtonFrame(CGSize size, MPClosableViewCloseButtonLocation closeButtonLocation) +{ + CGFloat width = size.width; + CGFloat height = size.height; + CGRect closeButtonFrame = CGRectMake(0.0f, 0.0f, kCloseRegionWidth, kCloseRegionHeight); + + switch (closeButtonLocation) { + case MPClosableViewCloseButtonLocationTopRight: + closeButtonFrame.origin = CGPointMake(width-kCloseRegionWidth, 0.0f); + break; + case MPClosableViewCloseButtonLocationTopLeft: + closeButtonFrame.origin = CGPointMake(0.0f, 0.0f); + break; + case MPClosableViewCloseButtonLocationTopCenter: + closeButtonFrame.origin = CGPointMake((width-kCloseRegionWidth) / 2.0f, 0.0f); + break; + case MPClosableViewCloseButtonLocationBottomRight: + closeButtonFrame.origin = CGPointMake(width-kCloseRegionWidth, height-kCloseRegionHeight); + break; + case MPClosableViewCloseButtonLocationBottomLeft: + closeButtonFrame.origin = CGPointMake(0.0f, height-kCloseRegionHeight); + break; + case MPClosableViewCloseButtonLocationBottomCenter: + closeButtonFrame.origin = CGPointMake((width-kCloseRegionWidth) / 2.0f, height-kCloseRegionHeight); + break; + case MPClosableViewCloseButtonLocationCenter: + closeButtonFrame.origin = CGPointMake((width-kCloseRegionWidth) / 2.0f, (height-kCloseRegionHeight) / 2.0f); + break; + default: + closeButtonFrame.origin = CGPointMake(width-kCloseRegionWidth, 0.0f); + break; + } + + return closeButtonFrame; +} + +@interface MPClosableView () + +@property (nonatomic, strong) UIButton *closeButton; +@property (nonatomic, strong) UIImage *closeButtonImage; +@property (nonatomic, strong) MPUserInteractionGestureRecognizer *userInteractionRecognizer; +@property (nonatomic, assign) BOOL wasTapped; + +@end + +@implementation MPClosableView + +- (instancetype)initWithFrame:(CGRect)frame closeButtonType:(MPClosableViewCloseButtonType)closeButtonType +{ + self = [super initWithFrame:frame]; + + if (self) { + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + + _closeButtonLocation = MPClosableViewCloseButtonLocationTopRight; + + _userInteractionRecognizer = [[MPUserInteractionGestureRecognizer alloc] initWithTarget:self action:@selector(handleInteraction:)]; + _userInteractionRecognizer.cancelsTouchesInView = NO; + [self addGestureRecognizer:_userInteractionRecognizer]; + _userInteractionRecognizer.delegate = self; + + _closeButtonImage = [UIImage imageNamed:MPResourcePathForResource(kExpandableCloseButtonImageName)]; + + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _closeButton.backgroundColor = [UIColor clearColor]; + _closeButton.accessibilityLabel = @"Close Interstitial Ad"; + + [_closeButton addTarget:self action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside]; + + [self setCloseButtonType:closeButtonType]; + + [self addSubview:_closeButton]; + } + + return self; +} + +- (void)dealloc +{ + _userInteractionRecognizer.delegate = nil; + [self.userInteractionRecognizer removeTarget:self action:nil]; +} + +- (void)layoutSubviews +{ + self.closeButton.frame = MPClosableViewCustomCloseButtonFrame(self.bounds.size, self.closeButtonLocation); + [self bringSubviewToFront:self.closeButton]; +} + +- (void)didMoveToWindow +{ + if ([self.delegate respondsToSelector:@selector(closableView:didMoveToWindow:)]) { + [self.delegate closableView:self didMoveToWindow:self.window]; + } +} + +- (void)setCloseButtonType:(MPClosableViewCloseButtonType)closeButtonType +{ + _closeButtonType = closeButtonType; + + switch (closeButtonType) { + case MPClosableViewCloseButtonTypeNone: + self.closeButton.hidden = YES; + break; + case MPClosableViewCloseButtonTypeTappableWithoutImage: + self.closeButton.hidden = NO; + [self.closeButton setImage:nil forState:UIControlStateNormal]; + break; + case MPClosableViewCloseButtonTypeTappableWithImage: + self.closeButton.hidden = NO; + [self.closeButton setImage:self.closeButtonImage forState:UIControlStateNormal]; + break; + default: + self.closeButton.hidden = NO; + [self.closeButton setImage:self.closeButtonImage forState:UIControlStateNormal]; + break; + } +} + +- (void)setCloseButtonLocation:(MPClosableViewCloseButtonLocation)closeButtonLocation +{ + _closeButtonLocation = closeButtonLocation; + [self setNeedsLayout]; +} + +- (void)handleInteraction:(UIGestureRecognizer *)gestureRecognizer +{ + if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { + self.wasTapped = YES; + } +} + +#pragma mark - + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +{ + return YES; +} + +#pragma mark - + +- (void)closeButtonPressed +{ + [self.delegate closeButtonPressed:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.h new file mode 100644 index 000000000..c4a6aff68 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.h @@ -0,0 +1,58 @@ +// +// MPCountdownTimerView.h +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import + +/** + * A view that will display a countdown timer and invoke a completion block once + * the timer has elapsed. + */ +@interface MPCountdownTimerView : UIView + +/** + * Flag indicating if the timer is active. + */ +@property (nonatomic, readonly) BOOL isActive; + +/** + * Flag indicating if the timer is currently paused. + */ +@property (nonatomic, readonly) BOOL isPaused; + +/** + * Initializes a countdown timer view. The timer is not automatically started. + * + * @param frame Frame of the view. + * @param seconds Duration of the timer in seconds. This value must be greater than zero. + * @returns An initialized timer if successful; otherwise nil. + */ +- (instancetype)initWithFrame:(CGRect)frame duration:(NSTimeInterval)seconds; + +/** + * Starts the countdown timer. If the timer has already started, calling this method again will do nothing. + * + * @param completion Completion block that is fired when the timer elapses or is stopped. + */ +- (void)startWithTimerCompletion:(void(^)(BOOL hasElapsed))completion; + +/** + * Stops the timer and optionally invokes the completion block from `startWithTimerCompletion:`. + * If the timer hasn't started, calling this method will do nothing. + */ +- (void)stopAndSignalCompletion:(BOOL)shouldSignalCompletion; + +/** + * Pauses the timer. If the timer hasn't started, calling this method will do nothing. + */ +- (void)pause; + +/** + * Resumes the timer. If the timer isn't paused, calling this method will do nothing. + */ +- (void)resume; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.m new file mode 100644 index 000000000..f0df837d5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPCountdownTimerView.m @@ -0,0 +1,195 @@ +// +// MPCountdownTimerView.m +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPCountdownTimerView.h" +#import "MPLogging.h" +#import "MPTimer.h" +#import "NSBundle+MPAdditions.h" + +// The frequency at which the internal timer is fired in seconds. +// This value matches the step size of the jQuery knob in MPCountdownTimer.html. +static const NSTimeInterval kCountdownTimerInterval = 0.05; + +@interface MPCountdownTimerView() +@property (nonatomic, assign, readwrite) BOOL isPaused; + +@property (nonatomic, copy) void(^completionBlock)(BOOL); +@property (nonatomic, assign) NSTimeInterval currentSeconds; +@property (nonatomic, strong) MPTimer * timer; +@property (nonatomic, strong) UIWebView * timerView; +@end + +@implementation MPCountdownTimerView + +#pragma mark - Initialization + +- (instancetype)initWithFrame:(CGRect)frame duration:(NSTimeInterval)seconds { + if (self = [super initWithFrame:frame]) { + // Duration should be non-negative. + if (seconds < 0) { + MPLogDebug(@"Attempted to initialize MPCountdownTimerView with a negative duration. No timer will be created."); + return nil; + } + + _completionBlock = nil; + _currentSeconds = seconds; + _isPaused = NO; + _timer = nil; + _timerView = ({ + UIWebView * view = [[UIWebView alloc] initWithFrame:self.bounds]; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + view.backgroundColor = [UIColor clearColor]; + view.delegate = self; + view.opaque = NO; + view.userInteractionEnabled = NO; + view; + }); + self.userInteractionEnabled = NO; + + [self addSubview:_timerView]; + [_timerView loadHTMLString:self.timerHtml baseURL:self.timerBaseUrl]; + } + + return self; +} + +- (void)dealloc { + // Stop the timer if the view is going away, but do not notify the completion block + // if there is one. + _completionBlock = nil; + [self stopAndSignalCompletion:NO]; +} + +#pragma mark - Timer + +- (BOOL)isActive { + return (self.timer != nil); +} + +- (void)startWithTimerCompletion:(void(^)(BOOL hasElapsed))completion { + if (self.isActive) { + return; + } + + // Reset any internal state that may be dirty from a previous timer run. + self.isPaused = NO; + + // Copy the completion block and set up the initial state of the timer. + self.completionBlock = completion; + + // Start the timer now. + self.timer = [MPTimer timerWithTimeInterval:kCountdownTimerInterval + target:self + selector:@selector(onTimerUpdate:) + repeats:YES]; + [self.timer scheduleNow]; + + MPLogInfo(@"MPCountdownTimerView started"); +} + +- (void)stopAndSignalCompletion:(BOOL)shouldSignalCompletion { + if (!self.isActive) { + return; + } + + // Invalidate and clear the timer to stop it completely. + [self.timer invalidate]; + self.timer = nil; + + MPLogInfo(@"MPCountdownTimerView stopped"); + + // Notify the completion block and clear it out once it's handling has finished. + if (shouldSignalCompletion && self.completionBlock != nil) { + BOOL hasElapsed = (self.currentSeconds <= 0); + self.completionBlock(hasElapsed); + + MPLogInfo(@"MPCountdownTimerView completion block notified"); + } + + // Clear out the completion block since the timer has stopped and it is + // no longer needed for this instance. + self.completionBlock = nil; +} + +- (void)pause { + if (!self.isActive) { + return; + } + + self.isPaused = [self.timer pause]; + if (self.isPaused) { + MPLogInfo(@"MPCountdownTimerView paused"); + } +} + +- (void)resume { + if (!self.isActive) { + return; + } + + if ([self.timer resume]) { + self.isPaused = NO; + MPLogInfo(@"MPCountdownTimerView resumed"); + } +} + +#pragma mark - Resources + +- (NSString *)timerHtml { + // Save the contents of the HTML into a static string since it will not change + // across instances. + static NSString * html = nil; + + if (html == nil) { + NSBundle * parentBundle = [NSBundle resourceBundleForClass:self.class]; + NSString * filepath = [parentBundle pathForResource:@"MPCountdownTimer" ofType:@"html"]; + html = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil]; + + if (html == nil) { + MPLogError(@"Could not find MPCountdownTimer.html in bundle %@", parentBundle.bundlePath); + } + } + + return html; +} + +- (NSURL *)timerBaseUrl { + // Save the base URL into a static string since it will not change + // across instances. + static NSURL * baseUrl = nil; + + if (baseUrl == nil) { + NSBundle * parentBundle = [NSBundle resourceBundleForClass:self.class]; + baseUrl = [NSURL fileURLWithPath:parentBundle.bundlePath]; + } + + return baseUrl; +} + +#pragma mark - MPTimer + +- (void)onTimerUpdate:(MPTimer *)sender { + // Update the count. + self.currentSeconds -= kCountdownTimerInterval; + + NSString * jsToEvaluate = [NSString stringWithFormat:@"setCounterValue(%f);", self.currentSeconds]; + [self.timerView stringByEvaluatingJavaScriptFromString:jsToEvaluate]; + + // Stop the timer and notify the completion block. + if (self.currentSeconds <= 0) { + [self stopAndSignalCompletion:YES]; + } +} + +#pragma mark - UIWebViewDelegate + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + NSString * jsToEvaluate = [NSString stringWithFormat:@"setMaxCounterValue(%f); setCounterValue(%f);", self.currentSeconds, self.currentSeconds]; + [self.timerView stringByEvaluatingJavaScriptFromString:jsToEvaluate]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.h new file mode 100644 index 000000000..d8c12311e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.h @@ -0,0 +1,22 @@ +// +// MPEnhancedDeeplinkRequest.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPEnhancedDeeplinkRequest : NSObject + +@property (copy) NSURL *originalURL; + +// Request components derived from the original URL. +@property (copy) NSURL *primaryURL; +@property (strong) NSArray *primaryTrackingURLs; +@property (copy) NSURL *fallbackURL; +@property (strong) NSArray *fallbackTrackingURLs; + +- (instancetype)initWithURL:(NSURL *)URL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.m new file mode 100644 index 000000000..317eb52df --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPEnhancedDeeplinkRequest.m @@ -0,0 +1,56 @@ +// +// MPEnhancedDeeplinkRequest.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPEnhancedDeeplinkRequest.h" +#import "NSURL+MPAdditions.h" + +static NSString * const kRequiredHostname = @"navigate"; +static NSString * const kPrimaryURLKey = @"primaryUrl"; +static NSString * const kPrimaryTrackingURLKey = @"primaryTrackingUrl"; +static NSString * const kFallbackURLKey = @"fallbackUrl"; +static NSString * const kFallbackTrackingURLKey = @"fallbackTrackingUrl"; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPEnhancedDeeplinkRequest + +- (instancetype)initWithURL:(NSURL *)URL +{ + self = [super init]; + if (self) { + if (![[[URL host] lowercaseString] isEqualToString:kRequiredHostname]) { + return nil; + } + + NSString *primaryURLString = [URL mp_queryParameterForKey:kPrimaryURLKey]; + if (![primaryURLString length]) { + return nil; + } + _primaryURL = [NSURL URLWithString:primaryURLString]; + _originalURL = [URL copy]; + + NSMutableArray *primaryTrackingURLs = [NSMutableArray array]; + NSArray *primaryTrackingURLStrings = [URL mp_queryParametersForKey:kPrimaryTrackingURLKey]; + for (NSString *URLString in primaryTrackingURLStrings) { + [primaryTrackingURLs addObject:[NSURL URLWithString:URLString]]; + } + _primaryTrackingURLs = [NSArray arrayWithArray:primaryTrackingURLs]; + + NSString *fallbackURLString = [URL mp_queryParameterForKey:kFallbackURLKey]; + _fallbackURL = [NSURL URLWithString:fallbackURLString]; + + NSMutableArray *fallbackTrackingURLs = [NSMutableArray array]; + NSArray *fallbackTrackingURLStrings = [URL mp_queryParametersForKey:kFallbackTrackingURLKey]; + for (NSString *URLString in fallbackTrackingURLStrings) { + [fallbackTrackingURLs addObject:[NSURL URLWithString:URLString]]; + } + _fallbackTrackingURLs = [NSArray arrayWithArray:fallbackTrackingURLs]; + } + return self; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.h new file mode 100644 index 000000000..7e92b65a1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.h @@ -0,0 +1,21 @@ +// +// MPFacebookAttributionIdProvider.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import "MPKeywordProvider.h" + +/* + * This class enables the MoPub SDK to deliver targeted ads from Facebook via MoPub Marketplace + * (MoPub's real-time bidding ad exchange) as part of a test program. This class sends an identifier + * to Facebook so Facebook can select the ad MoPub will serve in your app through MoPub Marketplace. + * If this class is removed from the SDK, your application will not receive targeted ads from + * Facebook. + */ + +@interface MPFacebookKeywordProvider : NSObject + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.m new file mode 100644 index 000000000..de1a01f37 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPFacebookKeywordProvider.m @@ -0,0 +1,28 @@ +// +// MPFacebookAttributionIdProvider.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPFacebookKeywordProvider.h" +#import + +static NSString *kFacebookAttributionIdPasteboardKey = @"fb_app_attribution"; +static NSString *kFacebookAttributionIdPrefix = @"FBATTRID:"; + +@implementation MPFacebookKeywordProvider + +#pragma mark - MPKeywordProvider + ++ (NSString *)keyword { + NSString *facebookAttributionId = [[UIPasteboard pasteboardWithName:kFacebookAttributionIdPasteboardKey + create:NO] string]; + if (!facebookAttributionId) { + return nil; + } + + return [NSString stringWithFormat:@"%@%@", kFacebookAttributionIdPrefix, facebookAttributionId]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPKeywordProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPKeywordProvider.h new file mode 100644 index 000000000..fa96647c6 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPKeywordProvider.h @@ -0,0 +1,14 @@ +// +// MPKeywordProvider.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import + +@protocol MPKeywordProvider + ++ (NSString *)keyword; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.h new file mode 100644 index 000000000..8f277d806 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.h @@ -0,0 +1,18 @@ +// +// MPLastResortDelegate.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import + +@interface MPLastResortDelegate : NSObject +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 + +#endif + ++ (id)sharedDelegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.m new file mode 100644 index 000000000..dfaacc8e3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPLastResortDelegate.m @@ -0,0 +1,37 @@ +// +// MPLastResortDelegate.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPLastResortDelegate.h" +#import "MPGlobal.h" + +@class MFMailComposeViewController; + +@implementation MPLastResortDelegate + ++ (id)sharedDelegate +{ + static MPLastResortDelegate *lastResortDelegate; + static dispatch_once_t once; + dispatch_once(&once, ^{ + lastResortDelegate = [[self alloc] init]; + }); + return lastResortDelegate; +} + +- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(NSInteger)result error:(NSError*)error +{ + [(UIViewController *)controller dismissViewControllerAnimated:MP_ANIMATED completion:nil]; +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000 +- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController +{ + [viewController dismissViewControllerAnimated:MP_ANIMATED completion:nil]; +} +#endif + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.h new file mode 100644 index 000000000..3d3692f5a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.h @@ -0,0 +1,39 @@ +// +// MPProgressOverlayView.h +// MoPub +// +// Created by Andrew He on 7/18/12. +// Copyright 2012 MoPub, Inc. All rights reserved. +// + +#import + +@protocol MPProgressOverlayViewDelegate; + +@interface MPProgressOverlayView : UIView { + id __weak _delegate; + UIView *_outerContainer; + UIView *_innerContainer; + UIActivityIndicatorView *_activityIndicator; + UIButton *_closeButton; + CGPoint _closeButtonPortraitCenter; +} + +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) UIButton *closeButton; + +- (id)initWithDelegate:(id)delegate; +- (void)show; +- (void)hide; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPProgressOverlayViewDelegate + +@optional +- (void)overlayCancelButtonPressed; +- (void)overlayDidAppear; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.m new file mode 100644 index 000000000..803996c26 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPProgressOverlayView.m @@ -0,0 +1,325 @@ +// +// MPProgressOverlayView.m +// MoPub +// +// Created by Andrew He on 7/18/12. +// Copyright 2012 MoPub, Inc. All rights reserved. +// + +#import "MPProgressOverlayView.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import + +static NSString * const kCloseButtonXImageName = @"MPCloseButtonX.png"; + +@interface MPProgressOverlayView () + +- (void)updateCloseButtonPosition; +- (void)registerForDeviceOrientationNotifications; +- (void)unregisterForDeviceOrientationNotifications; +- (void)deviceOrientationDidChange:(NSNotification *)notification; +- (void)setTransformForCurrentOrientationAnimated:(BOOL)animated; +- (void)setTransformForAllSubviews:(CGAffineTransform)transform; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define kProgressOverlaySide 60.0 +#define kProgressOverlayBorderWidth 1.0 +#define kProgressOverlayCornerRadius 8.0 +#define kProgressOverlayShadowOpacity 0.8 +#define kProgressOverlayShadowRadius 8.0 +#define kProgressOverlayCloseButtonDelay 4.0 + +static void exponentialDecayInterpolation(void *info, const CGFloat *input, CGFloat *output); + +@implementation MPProgressOverlayView + +@synthesize delegate = _delegate; +@synthesize closeButton = _closeButton; + +- (id)initWithDelegate:(id)delegate +{ + self = [self initWithFrame:MPKeyWindow().bounds]; + if (self) { + self.delegate = delegate; + } + return self; +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.alpha = 0.0; + self.opaque = NO; + + // Close button. + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _closeButton.alpha = 0.0; + _closeButton.hidden = YES; + [_closeButton addTarget:self + action:@selector(closeButtonPressed) + forControlEvents:UIControlEventTouchUpInside]; + UIImage *image = [UIImage imageNamed:MPResourcePathForResource(kCloseButtonXImageName)]; + [_closeButton setImage:image forState:UIControlStateNormal]; + [_closeButton sizeToFit]; + + _closeButtonPortraitCenter = + CGPointMake(self.bounds.size.width - 6.0 - CGRectGetMidX(_closeButton.bounds), + 6.0 + CGRectGetMidY(_closeButton.bounds)); + + _closeButton.center = _closeButtonPortraitCenter; + [self addSubview:_closeButton]; + + // Progress indicator container. + CGRect outerFrame = CGRectMake(0, 0, kProgressOverlaySide, kProgressOverlaySide); + _outerContainer = [[UIView alloc] initWithFrame:outerFrame]; + _outerContainer.alpha = 0.6; + _outerContainer.backgroundColor = [UIColor whiteColor]; + _outerContainer.center = self.center; + _outerContainer.frame = CGRectIntegral(_outerContainer.frame); + _outerContainer.opaque = NO; + _outerContainer.layer.cornerRadius = kProgressOverlayCornerRadius; + if ([_outerContainer.layer respondsToSelector:@selector(setShadowColor:)]) { + _outerContainer.layer.shadowColor = [UIColor blackColor].CGColor; + _outerContainer.layer.shadowOffset = CGSizeMake(0.0f, kProgressOverlayShadowRadius - 2.0f); + _outerContainer.layer.shadowOpacity = kProgressOverlayShadowOpacity; + _outerContainer.layer.shadowRadius = kProgressOverlayShadowRadius; + } + [self addSubview:_outerContainer]; + + CGFloat innerSide = kProgressOverlaySide - 2 * kProgressOverlayBorderWidth; + CGRect innerFrame = CGRectMake(0, 0, innerSide, innerSide); + _innerContainer = [[UIView alloc] initWithFrame:innerFrame]; + _innerContainer.backgroundColor = [UIColor blackColor]; + _innerContainer.center = CGPointMake(CGRectGetMidX(_outerContainer.bounds), + CGRectGetMidY(_outerContainer.bounds)); + _innerContainer.frame = CGRectIntegral(_innerContainer.frame); + _innerContainer.layer.cornerRadius = + kProgressOverlayCornerRadius - kProgressOverlayBorderWidth; + _innerContainer.opaque = NO; + [_outerContainer addSubview:_innerContainer]; + + // Progress indicator. + + _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: + UIActivityIndicatorViewStyleWhiteLarge]; + [_activityIndicator sizeToFit]; + [_activityIndicator startAnimating]; + _activityIndicator.center = self.center; + _activityIndicator.frame = CGRectIntegral(_activityIndicator.frame); + [self addSubview:_activityIndicator]; + + [self registerForDeviceOrientationNotifications]; + } + return self; +} + +- (void)dealloc +{ + [self unregisterForDeviceOrientationNotifications]; +} + +#pragma mark - Public Methods + +- (void)show +{ + [MPKeyWindow() addSubview:self]; + + [self setTransformForCurrentOrientationAnimated:NO]; + + if (MP_ANIMATED) { + [UIView animateWithDuration:0.2 animations:^{ + self.alpha = 1.0; + } completion:^(BOOL finished) { + if ([self.delegate respondsToSelector:@selector(overlayDidAppear)]) { + [self.delegate overlayDidAppear]; + } + }]; + } else { + self.alpha = 1.0; + if ([self.delegate respondsToSelector:@selector(overlayDidAppear)]) { + [self.delegate overlayDidAppear]; + } + } + + [self performSelector:@selector(enableCloseButton) + withObject:nil + afterDelay:kProgressOverlayCloseButtonDelay]; +} + +- (void)hide +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(enableCloseButton) object:nil]; + + self.closeButton.hidden = YES; + self.closeButton.alpha = 0.0f; + + if (MP_ANIMATED) { + [UIView animateWithDuration:0.2 animations:^{ + self.alpha = 0.0; + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; + } else { + self.alpha = 0.0; + [self removeFromSuperview]; + } +} + +#pragma mark - Drawing and Layout + +- (void)drawRect:(CGRect)rect +{ + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + static const CGFloat input_value_range[2] = {0, 1}; + static const CGFloat output_value_range[8] = {0, 1, 0, 1, 0, 1, 0, 1}; + CGFunctionCallbacks callbacks = {0, exponentialDecayInterpolation, NULL}; + + CGFunctionRef shadingFunction = CGFunctionCreate((__bridge void *)(self), 1, input_value_range, 4, + output_value_range, &callbacks); + + CGPoint startPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); + CGFloat startRadius = 0.0; + CGPoint endPoint = startPoint; + CGFloat endRadius = MAX(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) / 2; + + CGShadingRef shading = CGShadingCreateRadial(colorSpace, startPoint, startRadius, endPoint, + endRadius, shadingFunction, + YES, // extend shading beyond starting circle + YES); // extend shading beyond ending circle + CGContextDrawShading(context, shading); + + CGShadingRelease(shading); + CGFunctionRelease(shadingFunction); + CGColorSpaceRelease(colorSpace); +} + +#define kGradientMaximumAlphaValue 0.90 +#define kGradientAlphaDecayFactor 1.1263 + +static void exponentialDecayInterpolation(void *info, const CGFloat *input, CGFloat *output) +{ + // output is an RGBA array corresponding to the color black with an alpha value somewhere on + // our exponential decay curve. + CGFloat progress = *input; + output[0] = 0.0; + output[1] = 0.0; + output[2] = 0.0; + output[3] = kGradientMaximumAlphaValue - exp(-progress / kGradientAlphaDecayFactor); +} + +- (void)layoutSubviews +{ + [self updateCloseButtonPosition]; +} + +- (void)updateCloseButtonPosition +{ + // Ensure that the close button is anchored to the top-right corner of the screen. + + CGPoint originalCenter = _closeButtonPortraitCenter; + CGPoint center = originalCenter; + BOOL statusBarHidden = [UIApplication sharedApplication].statusBarHidden; + CGFloat statusBarOffset = (statusBarHidden) ? 0.0 : 20.0; + + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + switch (orientation) { + case UIInterfaceOrientationLandscapeLeft: + center.x = CGRectGetMaxX(self.bounds) - originalCenter.x + statusBarOffset; + center.y = originalCenter.y; + break; + case UIInterfaceOrientationLandscapeRight: + center.x = originalCenter.x - statusBarOffset; + center.y = CGRectGetMaxY(self.bounds) - originalCenter.y; + break; + case UIInterfaceOrientationPortraitUpsideDown: + center.x = CGRectGetMaxX(self.bounds) - originalCenter.x; + center.y = CGRectGetMaxY(self.bounds) - originalCenter.y - statusBarOffset; + break; + default: + center.y = originalCenter.y + statusBarOffset; + break; + } + + _closeButton.center = center; +} + +#pragma mark - Internal + +- (void)registerForDeviceOrientationNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(deviceOrientationDidChange:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; +} + +- (void)unregisterForDeviceOrientationNotifications +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIDeviceOrientationDidChangeNotification + object:nil]; +} + +- (void)deviceOrientationDidChange:(NSNotification *)notification +{ + [self setTransformForCurrentOrientationAnimated:YES]; + [self setNeedsLayout]; +} + +- (void)enableCloseButton +{ + _closeButton.hidden = NO; + + [UIView beginAnimations:nil context:nil]; + _closeButton.alpha = 1.0; + [UIView commitAnimations]; +} + +- (void)closeButtonPressed +{ + if ([_delegate respondsToSelector:@selector(overlayCancelButtonPressed)]) { + [_delegate overlayCancelButtonPressed]; + } +} + +- (void)setTransformForCurrentOrientationAnimated:(BOOL)animated +{ + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + float angle = 0; + if (UIInterfaceOrientationIsPortrait(orientation)) { + if (orientation == UIInterfaceOrientationPortraitUpsideDown) { + angle = M_PI; + } + } else { + if (orientation == UIInterfaceOrientationLandscapeLeft) { + angle = -M_PI_2; + } else { + angle = M_PI_2; + } + } + + if (animated) { + [UIView beginAnimations:nil context:nil]; + [self setTransformForAllSubviews:CGAffineTransformMakeRotation(angle)]; + [UIView commitAnimations]; + } else { + [self setTransformForAllSubviews:CGAffineTransformMakeRotation(angle)]; + } +} + +- (void)setTransformForAllSubviews:(CGAffineTransform)transform +{ + for (UIView *view in self.subviews) { + view.transform = transform; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.h new file mode 100644 index 000000000..a487bc4d2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.h @@ -0,0 +1,47 @@ +// +// MPURLActionInfo.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +#import "MPEnhancedDeeplinkRequest.h" + +#ifndef NS_ENUM +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#endif + +typedef NS_ENUM(NSUInteger, MPURLActionType) { + MPURLActionTypeStoreKit, + MPURLActionTypeGenericDeeplink, + MPURLActionTypeEnhancedDeeplink, + MPURLActionTypeOpenInSafari, + MPURLActionTypeOpenURLInWebView, + MPURLActionTypeOpenInWebView, + MPURLActionTypeShare +}; + +@interface MPURLActionInfo : NSObject + +@property (nonatomic, readonly) MPURLActionType actionType; +@property (nonatomic, readonly, copy) NSURL *originalURL; +@property (nonatomic, readonly, copy) NSString *iTunesItemIdentifier; +@property (nonatomic, readonly, copy) NSURL *iTunesStoreFallbackURL; +@property (nonatomic, readonly, copy) NSURL *safariDestinationURL; +@property (nonatomic, readonly, copy) NSString *HTTPResponseString; +@property (nonatomic, readonly, copy) NSURL *webViewBaseURL; +@property (nonatomic, readonly, copy) NSURL *deeplinkURL; +@property (nonatomic, readonly, strong) MPEnhancedDeeplinkRequest *enhancedDeeplinkRequest; +@property (nonatomic, readonly, copy) NSURL *shareURL; + ++ (instancetype)infoWithURL:(NSURL *)URL iTunesItemIdentifier:(NSString *)identifier iTunesStoreFallbackURL:(NSURL *)URL; ++ (instancetype)infoWithURL:(NSURL *)URL safariDestinationURL:(NSURL *)safariDestinationURL; ++ (instancetype)infoWithURL:(NSURL *)URL HTTPResponseString:(NSString *)responseString webViewBaseURL:(NSURL *)baseURL; ++ (instancetype)infoWithURL:(NSURL *)URL webViewBaseURL:(NSURL *)baseURL; ++ (instancetype)infoWithURL:(NSURL *)URL deeplinkURL:(NSURL *)deeplinkURL; ++ (instancetype)infoWithURL:(NSURL *)URL enhancedDeeplinkRequest:(MPEnhancedDeeplinkRequest *)request; ++ (instancetype)infoWithURL:(NSURL *)URL shareURL:(NSURL *)shareURL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.m new file mode 100644 index 000000000..228eb488d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLActionInfo.m @@ -0,0 +1,94 @@ +// +// MPURLActionInfo.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPURLActionInfo.h" + +@interface MPURLActionInfo () + +@property (nonatomic, readwrite) MPURLActionType actionType; +@property (nonatomic, readwrite, copy) NSURL *originalURL; +@property (nonatomic, readwrite, copy) NSString *iTunesItemIdentifier; +@property (nonatomic, readwrite, copy) NSURL *iTunesStoreFallbackURL; +@property (nonatomic, readwrite, copy) NSURL *safariDestinationURL; +@property (nonatomic, readwrite, copy) NSString *HTTPResponseString; +@property (nonatomic, readwrite, copy) NSURL *webViewBaseURL; +@property (nonatomic, readwrite, copy) NSURL *deeplinkURL; +@property (nonatomic, readwrite, strong) MPEnhancedDeeplinkRequest *enhancedDeeplinkRequest; +@property (nonatomic, readwrite, copy) NSURL *shareURL; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPURLActionInfo + ++ (instancetype)infoWithURL:(NSURL *)URL iTunesItemIdentifier:(NSString *)identifier iTunesStoreFallbackURL:(NSURL *)fallbackURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeStoreKit; + info.originalURL = URL; + info.iTunesItemIdentifier = identifier; + info.iTunesStoreFallbackURL = fallbackURL; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL safariDestinationURL:(NSURL *)safariDestinationURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeOpenInSafari; + info.originalURL = URL; + info.safariDestinationURL = safariDestinationURL; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL HTTPResponseString:(NSString *)responseString webViewBaseURL:(NSURL *)baseURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeOpenInWebView; + info.originalURL = URL; + info.HTTPResponseString = responseString; + info.webViewBaseURL = baseURL; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL webViewBaseURL:(NSURL *)baseURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeOpenURLInWebView; + info.originalURL = URL; + info.webViewBaseURL = baseURL; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL deeplinkURL:(NSURL *)deeplinkURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeGenericDeeplink; + info.originalURL = URL; + info.deeplinkURL = deeplinkURL; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL enhancedDeeplinkRequest:(MPEnhancedDeeplinkRequest *)request +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeEnhancedDeeplink; + info.originalURL = URL; + info.enhancedDeeplinkRequest = request; + return info; +} + ++ (instancetype)infoWithURL:(NSURL *)URL shareURL:(NSURL *)shareURL +{ + MPURLActionInfo *info = [[[self class] alloc] init]; + info.actionType = MPURLActionTypeShare; + info.originalURL = URL; + info.shareURL = shareURL; + return info; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.h new file mode 100644 index 000000000..a162b42a2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.h @@ -0,0 +1,20 @@ +// +// MPURLResolver.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPGlobal.h" +#import "MPURLActionInfo.h" + +typedef void (^MPURLResolverCompletionBlock)(MPURLActionInfo *actionInfo, NSError *error); + +@interface MPURLResolver : NSObject + ++ (instancetype)resolverWithURL:(NSURL *)URL completion:(MPURLResolverCompletionBlock)completion; +- (void)start; +- (void)cancel; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.m new file mode 100644 index 000000000..141bd1f1a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPURLResolver.m @@ -0,0 +1,286 @@ +// +// MPURLResolver.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPURLResolver.h" +#import "NSURL+MPAdditions.h" +#import "NSHTTPURLResponse+MPAdditions.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPCoreInstanceProvider.h" + +static NSString * const kMoPubSafariScheme = @"mopubnativebrowser"; +static NSString * const kMoPubSafariNavigateHost = @"navigate"; +static NSString * const kResolverErrorDomain = @"com.mopub.resolver"; + +@interface MPURLResolver () + +@property (nonatomic, strong) NSURL *originalURL; +@property (nonatomic, strong) NSURL *currentURL; +@property (nonatomic, strong) NSURLConnection *connection; +@property (nonatomic, strong) NSMutableData *responseData; +@property (nonatomic, assign) NSStringEncoding responseEncoding; +@property (nonatomic, copy) MPURLResolverCompletionBlock completion; + +- (MPURLActionInfo *)actionInfoFromURL:(NSURL *)URL error:(NSError **)error; +- (NSString *)storeItemIdentifierForURL:(NSURL *)URL; +- (BOOL)URLShouldOpenInApplication:(NSURL *)URL; +- (BOOL)URLIsHTTPOrHTTPS:(NSURL *)URL; +- (BOOL)URLPointsToAMap:(NSURL *)URL; +- (NSStringEncoding)stringEncodingFromContentType:(NSString *)contentType; + +@end + +@implementation MPURLResolver + +@synthesize originalURL = _originalURL; +@synthesize currentURL = _currentURL; +@synthesize connection = _connection; +@synthesize responseData = _responseData; +@synthesize completion = _completion; + ++ (instancetype)resolverWithURL:(NSURL *)URL completion:(MPURLResolverCompletionBlock)completion +{ + return [[MPURLResolver alloc] initWithURL:URL completion:completion]; +} + +- (instancetype)initWithURL:(NSURL *)URL completion:(MPURLResolverCompletionBlock)completion +{ + self = [super init]; + if (self) { + _originalURL = [URL copy]; + _completion = [completion copy]; + } + return self; +} + +- (void)start +{ + [self.connection cancel]; + self.currentURL = self.originalURL; + + NSError *error = nil; + MPURLActionInfo *info = [self actionInfoFromURL:self.originalURL error:&error]; + + if (info) { + [self safeInvokeAndNilCompletionBlock:info error:nil]; + } else if (error) { + [self safeInvokeAndNilCompletionBlock:nil error:error]; + } else { + NSURLRequest *request = [[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:self.originalURL]; + self.responseData = [NSMutableData data]; + self.responseEncoding = NSUTF8StringEncoding; + self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; + } +} + +- (void)cancel +{ + [self.connection cancel]; + self.connection = nil; + self.completion = nil; +} + +- (void)safeInvokeAndNilCompletionBlock:(MPURLActionInfo *)info error:(NSError *)error +{ + if (self.completion != nil) { + self.completion(info, error); + self.completion = nil; + } +} + +#pragma mark - Handling Application/StoreKit URLs + +/* + * Parses the provided URL for actions to perform (opening StoreKit, opening Safari, etc.). + * If the URL represents an action, this method will return an info object containing data that is + * relevant to the suggested action. + */ +- (MPURLActionInfo *)actionInfoFromURL:(NSURL *)URL error:(NSError **)error; +{ + MPURLActionInfo *actionInfo = nil; + + if (URL == nil) { + if (error) { + *error = [NSError errorWithDomain:kResolverErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey: @"URL is nil"}]; + } + return nil; + } + + if ([self storeItemIdentifierForURL:URL]) { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL iTunesItemIdentifier:[self storeItemIdentifierForURL:URL] iTunesStoreFallbackURL:URL]; + } else if ([self URLHasDeeplinkPlusScheme:URL]) { + MPEnhancedDeeplinkRequest *request = [[MPEnhancedDeeplinkRequest alloc] initWithURL:URL]; + if (request) { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL enhancedDeeplinkRequest:request]; + } else { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL deeplinkURL:URL]; + } + } else if ([self safariURLForURL:URL]) { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL safariDestinationURL:[NSURL URLWithString:[self safariURLForURL:URL]]]; + } else if ([URL mp_isMoPubShareScheme]) { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL shareURL:URL]; + } else if ([self URLShouldOpenInApplication:URL]) { + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL deeplinkURL:URL]; + } else if ([URL.scheme isEqualToString:@"http"]) { // handle HTTP requests in particular to get around ATS settings + // As a note: `appTransportSecuritySettings` returns what makes sense for the iOS version. I.e., if the device + // is running iOS 8, this method will always return `MPATSSettingAllowsArbitraryLoads`. If the device is running + // iOS 9, this method will never give us `MPATSSettingAllowsArbitraryLoadsInWebContent`. As a result, we don't + // have to do OS checks here; we can just trust these settings. + MPATSSetting settings = [[MPCoreInstanceProvider sharedProvider] appTransportSecuritySettings]; + + if ((settings & MPATSSettingAllowsArbitraryLoads) != 0) { // opens as normal if ATS is disabled + // don't do anything + } else if ((settings & MPATSSettingAllowsArbitraryLoadsInWebContent) != 0) { // opens in WKWebView if ATS is disabled for arbitrary web content + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL + webViewBaseURL:self.currentURL]; + } else { // opens in Mobile Safari if no other option is available + actionInfo = [MPURLActionInfo infoWithURL:self.originalURL + safariDestinationURL:self.currentURL]; + } + } + + return actionInfo; +} + +#pragma mark Identifying Application URLs + +- (BOOL)URLShouldOpenInApplication:(NSURL *)URL +{ + return ![self URLIsHTTPOrHTTPS:URL] || [self URLPointsToAMap:URL]; +} + +- (BOOL)URLIsHTTPOrHTTPS:(NSURL *)URL +{ + return [URL.scheme isEqualToString:@"http"] || [URL.scheme isEqualToString:@"https"]; +} + +- (BOOL)URLHasDeeplinkPlusScheme:(NSURL *)URL +{ + return [[URL.scheme lowercaseString] isEqualToString:@"deeplink+"]; +} + +- (BOOL)URLPointsToAMap:(NSURL *)URL +{ + return [URL.host hasSuffix:@"maps.google.com"] || [URL.host hasSuffix:@"maps.apple.com"]; +} + +#pragma mark Extracting StoreItem Identifiers + +- (NSString *)storeItemIdentifierForURL:(NSURL *)URL +{ + NSString *itemIdentifier = nil; + if ([URL.host hasSuffix:@"itunes.apple.com"]) { + NSString *lastPathComponent = [[URL path] lastPathComponent]; + if ([lastPathComponent hasPrefix:@"id"]) { + itemIdentifier = [lastPathComponent substringFromIndex:2]; + } else { + itemIdentifier = [URL.mp_queryAsDictionary objectForKey:@"id"]; + } + } else if ([URL.host hasSuffix:@"phobos.apple.com"]) { + itemIdentifier = [URL.mp_queryAsDictionary objectForKey:@"id"]; + } + + NSCharacterSet *nonIntegers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + if (itemIdentifier && itemIdentifier.length > 0 && [itemIdentifier rangeOfCharacterFromSet:nonIntegers].location == NSNotFound) { + return itemIdentifier; + } + + return nil; +} + +#pragma mark - Identifying URLs to open in Safari + +- (NSString *)safariURLForURL:(NSURL *)URL +{ + NSString *safariURL = nil; + + if ([[URL scheme] isEqualToString:kMoPubSafariScheme] && + [[URL host] isEqualToString:kMoPubSafariNavigateHost]) { + safariURL = [URL.mp_queryAsDictionary objectForKey:@"url"]; + } + + return safariURL; +} + +#pragma mark - Identifying NSStringEncoding from NSURLResponse Content-Type header + +- (NSStringEncoding)stringEncodingFromContentType:(NSString *)contentType +{ + NSStringEncoding encoding = NSUTF8StringEncoding; + + if (![contentType length]) { + MPLogWarn(@"Attempting to set string encoding from nil %@", kMoPubHTTPHeaderContentType); + return encoding; + } + + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=charset=)[^;]*" options:kNilOptions error:nil]; + + NSTextCheckingResult *charsetResult = [regex firstMatchInString:contentType options:kNilOptions range:NSMakeRange(0, [contentType length])]; + if (charsetResult && charsetResult.range.location != NSNotFound) { + NSString *charset = [contentType substringWithRange:[charsetResult range]]; + + // ensure that charset is not deallocated early + CFStringRef cfCharset = CFBridgingRetain(charset); + CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding(cfCharset); + CFBridgingRelease(cfCharset); + + if (cfEncoding == kCFStringEncodingInvalidId) { + return encoding; + } + encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); + } + + return encoding; +} + +#pragma mark - + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + [self.responseData appendData:data]; +} + +- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response +{ + // First, check to see if the redirect URL matches any of our suggested actions. + NSError *error = nil; + MPURLActionInfo *info = [self actionInfoFromURL:request.URL error:&error]; + + if (info) { + [connection cancel]; + [self safeInvokeAndNilCompletionBlock:info error:nil]; + return nil; + } else { + // The redirected URL didn't match any actions, so we should continue with loading the URL. + self.currentURL = request.URL; + return request; + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + NSDictionary *headers = [httpResponse allHeaderFields]; + NSString *contentType = [headers objectForKey:kMoPubHTTPHeaderContentType]; + self.responseEncoding = [httpResponse stringEncodingFromContentType:contentType]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + NSString *responseString = [[NSString alloc] initWithData:self.responseData encoding:self.responseEncoding]; + MPURLActionInfo *info = [MPURLActionInfo infoWithURL:self.originalURL HTTPResponseString:responseString webViewBaseURL:self.currentURL]; + [self safeInvokeAndNilCompletionBlock:info error:nil]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + [self safeInvokeAndNilCompletionBlock:nil error:error]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.h new file mode 100644 index 000000000..7a2e23ef7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.h @@ -0,0 +1,49 @@ +// +// MPVideoConfig.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTResponse.h" + +@interface MPVideoConfig : NSObject + +@property (nonatomic, readonly) NSURL *mediaURL; +@property (nonatomic, readonly) NSURL *clickThroughURL; +@property (nonatomic, readonly) NSArray *clickTrackingURLs; +@property (nonatomic, readonly) NSArray *errorURLs; +@property (nonatomic, readonly) NSArray *impressionURLs; + +/** @name Tracking Events */ + +@property (nonatomic, readonly) NSArray *creativeViewTrackers; +@property (nonatomic, readonly) NSArray *startTrackers; +@property (nonatomic, readonly) NSArray *firstQuartileTrackers; +@property (nonatomic, readonly) NSArray *midpointTrackers; +@property (nonatomic, readonly) NSArray *thirdQuartileTrackers; +@property (nonatomic, readonly) NSArray *completionTrackers; +@property (nonatomic, readonly) NSArray *muteTrackers; +@property (nonatomic, readonly) NSArray *unmuteTrackers; +@property (nonatomic, readonly) NSArray *pauseTrackers; +@property (nonatomic, readonly) NSArray *rewindTrackers; +@property (nonatomic, readonly) NSArray *resumeTrackers; +@property (nonatomic, readonly) NSArray *fullscreenTrackers; +@property (nonatomic, readonly) NSArray *exitFullscreenTrackers; +@property (nonatomic, readonly) NSArray *expandTrackers; +@property (nonatomic, readonly) NSArray *collapseTrackers; +@property (nonatomic, readonly) NSArray *acceptInvitationLinearTrackers; +@property (nonatomic, readonly) NSArray *closeLinearTrackers; +@property (nonatomic, readonly) NSArray *skipTrackers; +@property (nonatomic, readonly) NSArray *otherProgressTrackers; + +/** @name Viewability */ + +@property (nonatomic, readonly) NSTimeInterval minimumViewabilityTimeInterval; +@property (nonatomic, readonly) double minimumFractionOfVideoVisible; +@property (nonatomic, readonly) NSURL *viewabilityTrackingURL; + +- (instancetype)initWithVASTResponse:(MPVASTResponse *)response additionalTrackers:(NSDictionary *)additionalTrackers; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.m new file mode 100644 index 000000000..f5c2c4b9a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPVideoConfig.m @@ -0,0 +1,300 @@ +// +// MPVideoConfig.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVideoConfig.h" +#import "MPLogging.h" +#import "MPVASTStringUtilities.h" + +@interface MPVideoPlaybackCandidate : NSObject + +@property (nonatomic, readwrite) MPVASTLinearAd *linearAd; +@property (nonatomic, readwrite) NSArray *errorURLs; +@property (nonatomic, readwrite) NSArray *impressionURLs; +@property (nonatomic, readwrite) NSTimeInterval minimumViewabilityTimeInterval; +@property (nonatomic, readwrite) double minimumFractionOfVideoVisible; +@property (nonatomic, readwrite) NSURL *viewabilityTrackingURL; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVideoPlaybackCandidate + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPVideoConfig () + +@property (nonatomic, readwrite) NSURL *mediaURL; +@property (nonatomic, readwrite) NSURL *clickThroughURL; +@property (nonatomic, readwrite) NSArray *clickTrackingURLs; +@property (nonatomic, readwrite) NSArray *errorURLs; +@property (nonatomic, readwrite) NSArray *impressionURLs; +@property (nonatomic, readwrite) NSArray *startTrackers; +@property (nonatomic, readwrite) NSArray *firstQuartileTrackers; +@property (nonatomic, readwrite) NSArray *midpointTrackers; +@property (nonatomic, readwrite) NSArray *thirdQuartileTrackers; +@property (nonatomic, readwrite) NSArray *completionTrackers; +@property (nonatomic, readwrite) NSArray *muteTrackers; +@property (nonatomic, readwrite) NSArray *unmuteTrackers; +@property (nonatomic, readwrite) NSArray *pauseTrackers; +@property (nonatomic, readwrite) NSArray *rewindTrackers; +@property (nonatomic, readwrite) NSArray *resumeTrackers; +@property (nonatomic, readwrite) NSArray *fullscreenTrackers; +@property (nonatomic, readwrite) NSArray *exitFullscreenTrackers; +@property (nonatomic, readwrite) NSArray *expandTrackers; +@property (nonatomic, readwrite) NSArray *collapseTrackers; +@property (nonatomic, readwrite) NSArray *acceptInvitationLinearTrackers; +@property (nonatomic, readwrite) NSArray *closeLinearTrackers; +@property (nonatomic, readwrite) NSArray *skipTrackers; +@property (nonatomic, readwrite) NSArray *otherProgressTrackers; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPVASTLinearAd (MPVideoConfig) + +@property (nonatomic, readwrite) NSArray *clickTrackingURLs; +@property (nonatomic, readwrite) NSArray *customClickURLs; +@property (nonatomic, readwrite) NSArray *industryIcons; +@property (nonatomic, readwrite) NSDictionary *trackingEvents; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVideoConfig + +- (instancetype)initWithVASTResponse:(MPVASTResponse *)response additionalTrackers:(NSDictionary *)additionalTrackers +{ + self = [super init]; + if (self) { + [self commonInit:response additionalTrackers:additionalTrackers]; + } + return self; +} + +- (void)commonInit:(MPVASTResponse *)response additionalTrackers:(NSDictionary *)additionalTrackers +{ + NSArray *candidates = [self playbackCandidatesFromVASTResponse:response]; + + if (candidates.count == 0) { + return; + } + + MPVideoPlaybackCandidate *candidate = candidates[0]; + MPVASTMediaFile *mediaFile = candidate.linearAd.highestBitrateMediaFile; + + _mediaURL = mediaFile.URL; + _clickThroughURL = candidate.linearAd.clickThroughURL; + _clickTrackingURLs = candidate.linearAd.clickTrackingURLs; + _errorURLs = candidate.errorURLs; + _impressionURLs = candidate.impressionURLs; + + NSDictionary *trackingEvents = candidate.linearAd.trackingEvents; + _creativeViewTrackers = trackingEvents[MPVASTTrackingEventTypeCreativeView]; + _startTrackers = [self trackersByMergingOriginalTrackers:trackingEvents additionalTrackers:additionalTrackers name:MPVASTTrackingEventTypeStart]; + _firstQuartileTrackers = [self trackersByMergingOriginalTrackers:trackingEvents additionalTrackers:additionalTrackers name:MPVASTTrackingEventTypeFirstQuartile]; + _midpointTrackers = [self trackersByMergingOriginalTrackers:trackingEvents additionalTrackers:additionalTrackers name:MPVASTTrackingEventTypeMidpoint]; + _thirdQuartileTrackers = [self trackersByMergingOriginalTrackers:trackingEvents additionalTrackers:additionalTrackers name:MPVASTTrackingEventTypeThirdQuartile]; + _completionTrackers = [self trackersByMergingOriginalTrackers:trackingEvents additionalTrackers:additionalTrackers name:MPVASTTrackingEventTypeComplete]; + _muteTrackers = trackingEvents[MPVASTTrackingEventTypeMute]; + _unmuteTrackers = trackingEvents[MPVASTTrackingEventTypeUnmute]; + _pauseTrackers = trackingEvents[MPVASTTrackingEventTypePause]; + _rewindTrackers = trackingEvents[MPVASTTrackingEventTypeRewind]; + _resumeTrackers = trackingEvents[MPVASTTrackingEventTypeResume]; + _fullscreenTrackers = trackingEvents[MPVASTTrackingEventTypeFullscreen]; + _exitFullscreenTrackers = trackingEvents[MPVASTTrackingEventTypeExitFullscreen]; + _expandTrackers = trackingEvents[MPVASTTrackingEventTypeExpand]; + _collapseTrackers = trackingEvents[MPVASTTrackingEventTypeCollapse]; + _acceptInvitationLinearTrackers = trackingEvents[MPVASTTrackingEventTypeAcceptInvitationLinear]; + _closeLinearTrackers = trackingEvents[MPVASTTrackingEventTypeCloseLinear]; + _skipTrackers = trackingEvents[MPVASTTrackingEventTypeSkip]; + _otherProgressTrackers = trackingEvents[MPVASTTrackingEventTypeProgress]; + + _minimumViewabilityTimeInterval = candidate.minimumViewabilityTimeInterval; + _minimumFractionOfVideoVisible = candidate.minimumFractionOfVideoVisible; + _viewabilityTrackingURL = candidate.viewabilityTrackingURL; +} + +- (NSArray *)playbackCandidatesFromVASTResponse:(MPVASTResponse *)response +{ + NSMutableArray *candidates = [NSMutableArray array]; + + for (MPVASTAd *ad in response.ads) { + if (ad.inlineAd) { + MPVASTInline *inlineAd = ad.inlineAd; + NSArray *creatives = inlineAd.creatives; + for (MPVASTCreative *creative in creatives) { + if (creative.linearAd && [creative.linearAd.mediaFiles count]) { + MPVideoPlaybackCandidate *candidate = [[MPVideoPlaybackCandidate alloc] init]; + candidate.linearAd = creative.linearAd; + candidate.errorURLs = inlineAd.errorURLs; + candidate.impressionURLs = inlineAd.impressionURLs; + + NSDictionary *viewabilityExt = [self extensionFromInlineAd:inlineAd forKey:@"MoPubViewabilityTracker"]; + if (viewabilityExt) { + NSURL *viewabilityTrackingURL = [NSURL URLWithString:viewabilityExt[@"text"]]; + BOOL valid = [MPVASTStringUtilities stringRepresentsNonNegativeDuration:viewabilityExt[@"viewablePlaytime"]]&& + [MPVASTStringUtilities stringRepresentsNonNegativePercentage:viewabilityExt[@"percentViewable"]] && + viewabilityTrackingURL; + + if (valid) { + candidate.minimumViewabilityTimeInterval = [MPVASTStringUtilities timeIntervalFromString:viewabilityExt[@"viewablePlaytime"]]; + candidate.minimumFractionOfVideoVisible = [MPVASTStringUtilities percentageFromString:viewabilityExt[@"percentViewable"]] / 100.0; + candidate.viewabilityTrackingURL = viewabilityTrackingURL; + } + } + + [candidates addObject:candidate]; + } + } + } else if (ad.wrapper) { + NSArray *candidatesFromWrapper = [self playbackCandidatesFromVASTResponse:ad.wrapper.wrappedVASTResponse]; + + // Merge any wrapper-level tracking URLs into each of the candidates. + for (MPVideoPlaybackCandidate *candidate in candidatesFromWrapper) { + candidate.errorURLs = [candidate.errorURLs arrayByAddingObjectsFromArray:ad.wrapper.errorURLs]; + candidate.impressionURLs = [candidate.impressionURLs arrayByAddingObjectsFromArray:ad.wrapper.impressionURLs]; + + candidate.linearAd.trackingEvents = [self dictionaryByMergingTrackingDictionaries:@[candidate.linearAd.trackingEvents, [self trackingEventsFromWrapper:ad.wrapper]]]; + candidate.linearAd.clickTrackingURLs = [candidate.linearAd.clickTrackingURLs arrayByAddingObjectsFromArray:[self clickTrackingURLsFromWrapper:ad.wrapper]]; + candidate.linearAd.customClickURLs = [candidate.linearAd.customClickURLs arrayByAddingObjectsFromArray:[self customClickURLsFromWrapper:ad.wrapper]]; + candidate.linearAd.industryIcons = [candidate.linearAd.industryIcons arrayByAddingObjectsFromArray:[self industryIconsFromWrapper:ad.wrapper]]; + } + + [candidates addObjectsFromArray:candidatesFromWrapper]; + } + } + + return candidates; +} + +- (NSDictionary *)trackingEventsFromWrapper:(MPVASTWrapper *)wrapper +{ + NSMutableArray *trackingEventDictionaries = [NSMutableArray array]; + + for (MPVASTCreative *creative in wrapper.creatives) { + [trackingEventDictionaries addObject:creative.linearAd.trackingEvents]; + } + + return [self dictionaryByMergingTrackingDictionaries:trackingEventDictionaries]; +} + +- (NSArray *)clickTrackingURLsFromWrapper:(MPVASTWrapper *)wrapper +{ + NSMutableArray *clickTrackingURLs = [NSMutableArray array]; + for (MPVASTCreative *creative in wrapper.creatives) { + [clickTrackingURLs addObjectsFromArray:creative.linearAd.clickTrackingURLs]; + } + + return clickTrackingURLs; +} + +- (NSArray *)customClickURLsFromWrapper:(MPVASTWrapper *)wrapper +{ + NSMutableArray *customClickURLs = [NSMutableArray array]; + for (MPVASTCreative *creative in wrapper.creatives) { + [customClickURLs addObjectsFromArray:creative.linearAd.customClickURLs]; + } + + return customClickURLs; +} + +- (NSArray *)industryIconsFromWrapper:(MPVASTWrapper *)wrapper +{ + NSMutableArray *industryIcons = [NSMutableArray array]; + for (MPVASTCreative *creative in wrapper.creatives) { + [industryIcons addObjectsFromArray:creative.linearAd.industryIcons]; + } + + return industryIcons; +} + +- (NSDictionary *)extensionFromInlineAd:(MPVASTInline *)inlineAd forKey:(NSString *)key +{ + NSDictionary *extensions = inlineAd.extensions; + id extensionObject = [extensions objectForKey:@"Extension"]; + + if ([extensionObject isKindOfClass:[NSDictionary class]]) { + // Case 1: "Extensions" element with only one "Extension" child. + NSDictionary *extensionChildNode = extensionObject; + id extension = [self firstObjectForKey:key inDictionary:extensionChildNode]; + if ([extension isKindOfClass:[NSDictionary class]]) { + return extension; + } + } else if ([extensionObject isKindOfClass:[NSArray class]]) { + // Case 2: "Extensions" element with multiple "Extension" children. + NSArray *extensionChildNodes = extensionObject; + for (id node in extensionChildNodes) { + if (![node isKindOfClass:[NSDictionary class]]) { + continue; + } + + id extension = [self firstObjectForKey:key inDictionary:node]; + if ([extension isKindOfClass:[NSDictionary class]]) { + return extension; + } + } + } + + return nil; +} + +// When dealing with VAST, we will often have dictionaries where a key can map either to a single +// value or an array of values. For example, the dictionary containing VAST extensions might contain +// one or more nodes. This method is useful when we simply want the first value matching +// a given key. It is equivalent to calling [dictionary objectForKey:key] when the key maps to a +// single value. When the key maps to an NSArray, it returns the first value in the array. +- (id)firstObjectForKey:(NSString *)key inDictionary:(NSDictionary *)dictionary +{ + id value = [dictionary objectForKey:key]; + if ([value isKindOfClass:[NSArray class]]) { + return [value firstObject]; + } else { + return value; + } +} + +- (NSArray *)trackersByMergingOriginalTrackers:(NSDictionary *)originalTrackers additionalTrackers:(NSDictionary *)additionalTrackers name:(NSString *)trackerName +{ + if (![originalTrackers[trackerName] isKindOfClass:[NSArray class]]) { + return additionalTrackers[trackerName]; + } + if (![additionalTrackers[trackerName] isKindOfClass:[NSArray class]]) { + return originalTrackers[trackerName]; + } + NSMutableArray *mergedTrackers = [NSMutableArray new]; + [mergedTrackers addObjectsFromArray:originalTrackers[trackerName]]; + [mergedTrackers addObjectsFromArray:additionalTrackers[trackerName]]; + return mergedTrackers; +} + +- (NSDictionary *)dictionaryByMergingTrackingDictionaries:(NSArray *)dictionaries +{ + NSMutableDictionary *mergedDictionary = [NSMutableDictionary dictionary]; + for (NSDictionary *dictionary in dictionaries) { + for (NSString *key in [dictionary allKeys]) { + if ([dictionary[key] isKindOfClass:[NSArray class]]) { + if (!mergedDictionary[key]) { + mergedDictionary[key] = [NSMutableArray array]; + } + + [mergedDictionary[key] addObjectsFromArray:dictionary[key]]; + } else { + MPLogError(@"TrackingEvents dictionary expected an array object for key '%@' " + @"but got an instance of %@ instead.", + key, NSStringFromClass([dictionary[key] class])); + } + } + } + return mergedDictionary; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.h new file mode 100644 index 000000000..c246979f6 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.h @@ -0,0 +1,14 @@ +// +// MPXMLParser.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPXMLParser : NSObject + +- (NSDictionary *)dictionaryWithData:(NSData *)data error:(NSError **)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.m new file mode 100644 index 000000000..c38b62089 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Common/MPXMLParser.m @@ -0,0 +1,88 @@ +// +// MPXMLParser.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPXMLParser.h" + +@interface MPXMLParser () + +@property (nonatomic) NSMutableArray *elementStack; +@property (nonatomic) NSMutableString *currentTextContent; +@property (nonatomic) NSError *parseError; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPXMLParser + +- (instancetype)init +{ + if (self = [super init]) { + _elementStack = [NSMutableArray array]; + + // Create a "root" dictionary. + [_elementStack addObject:[NSMutableDictionary dictionary]]; + + _currentTextContent = [NSMutableString string]; + } + return self; +} + +- (NSDictionary *)dictionaryWithData:(NSData *)data error:(NSError *__autoreleasing *)error +{ + NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; + [parser setDelegate:self]; + [parser parse]; + return self.elementStack[0]; +} + +#pragma mark - + +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict +{ + NSMutableDictionary *parentElement = [self.elementStack lastObject]; + NSMutableDictionary *currentElement = [NSMutableDictionary dictionary]; + [currentElement addEntriesFromDictionary:attributeDict]; + + if (parentElement[elementName] && [parentElement[elementName] isKindOfClass:[NSArray class]]) { + [parentElement[elementName] addObject:currentElement]; + } else if (parentElement[elementName]) { + NSMutableDictionary *previousElement = parentElement[elementName]; + NSMutableArray *elementsArray = [NSMutableArray array]; + [elementsArray addObject:previousElement]; + [elementsArray addObject:currentElement]; + parentElement[elementName] = elementsArray; + } else { + parentElement[elementName] = currentElement; + } + + [self.elementStack addObject:currentElement]; +} + +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName +{ + NSMutableDictionary *currentElement = [self.elementStack lastObject]; + NSString *trimmedContent = [self.currentTextContent stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if ([trimmedContent length]) { + currentElement[@"text"] = trimmedContent; + } + + self.currentTextContent = [NSMutableString string]; + [self.elementStack removeLastObject]; +} + +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string +{ + [self.currentTextContent appendString:string]; +} + +- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError +{ + self.parseError = parseError; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.h new file mode 100644 index 000000000..28ec39602 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.h @@ -0,0 +1,25 @@ +// +// MPLogEvent+NativeVideo.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +#import "MPLogEvent.h" + +typedef NS_ENUM(NSInteger, MPNativeVideoEventType) { + MPNativeVideoEventTypeDownloadStart, + MPNativeVideoEventTypeVideoReady, + MPNativeVideoEventTypeBuffering, + MPNativeVideoEventTypeDownloadFinished, + MPNativeVideoEventTypeErrorFailedToPlay, + MPNativeVideoEventTypeErrorDuringPlayback, +}; + +@interface MPLogEvent (NativeVideo) + +- (instancetype)initWithLogEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties nativeVideoEventType:(MPNativeVideoEventType)nativeVideoEventType; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.m new file mode 100644 index 000000000..9fd1281b8 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent+NativeVideo.m @@ -0,0 +1,39 @@ +// +// MPLogEvent+NativeVideo.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPLogEvent+NativeVideo.h" + +static NSDictionary *nativeVideoLogEventTypeToString = nil; + +NSString *const MPNativeVideoEventTypeDownloadStartString = @"download_start"; +NSString *const MPNativeVideoEventTypeVideoReadyString = @"download_video_ready"; +NSString *const MPNativeVideoEventTypeBufferingString = @"download_buffering"; +NSString *const MPNativeVideoEventTypeDownloadFinishedString = @"download_finished"; +NSString *const MPNativeVideoEventTypeErrorFailedToPlayString = @"error_failed_to_play"; +NSString *const MPNativeVideoEventTypeErrorDuringPlaybackString = @"error_during_playback"; + +@implementation MPLogEvent (NativeVideo) + +- (instancetype)initWithLogEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties nativeVideoEventType:(MPNativeVideoEventType)nativeVideoEventType +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + nativeVideoLogEventTypeToString = @{@(MPNativeVideoEventTypeDownloadStart): MPNativeVideoEventTypeDownloadStartString, + @(MPNativeVideoEventTypeVideoReady): MPNativeVideoEventTypeVideoReadyString, + @(MPNativeVideoEventTypeBuffering): MPNativeVideoEventTypeBufferingString, + @(MPNativeVideoEventTypeDownloadFinished): MPNativeVideoEventTypeDownloadFinishedString, + @(MPNativeVideoEventTypeErrorDuringPlayback): MPNativeVideoEventTypeErrorDuringPlaybackString, + @(MPNativeVideoEventTypeErrorFailedToPlay): MPNativeVideoEventTypeErrorFailedToPlayString}; + }); + + if (self = [[MPLogEvent alloc] initWithEventCategory:MPLogEventCategoryNativeVideo eventName:[nativeVideoLogEventTypeToString objectForKey:@(nativeVideoEventType)]]) { + [self setLogEventProperties:logEventProperties]; + } + return self; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.h new file mode 100644 index 000000000..20ce150e1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.h @@ -0,0 +1,260 @@ +// +// MPLogEvent.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPAdConfiguration.h" + +#ifndef NS_ENUM +#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type +#endif + +typedef NS_ENUM(NSInteger, MPLogEventScribeCategory) { + MPExchangeClientEventCategory, + MPExchangeClientErrorCategory, +}; + +typedef NS_ENUM(NSInteger, MPLogEventNetworkType) { + MPLogEventNetworkTypeUnknown, + MPLogEventNetworkTypeEthernet, + MPLogEventNetworkTypeWifi, + MPLogEventNetworkTypeMobile, +}; + +/* + * Event names. + */ +extern NSString *const MPLogEventNameAdRequest; +extern NSString *const MPLogEventNameClickthroughDwellTime; + +/* + * Event categories. + */ +extern NSString *const MPLogEventCategoryRequests; +extern NSString *const MPLogEventCategoryNativeVideo; +extern NSString *const MPLogEventCategoryAdInteractions; + +/* MPAdConfigurationLogEventProperties + * + * Convenience struct class for keeping track of the log event properties + * that are parsed off the MPAdConfiguration. + */ +@interface MPAdConfigurationLogEventProperties : NSObject + +@property (nonatomic, copy) NSString *adType; +@property (nonatomic, copy) NSString *adCreativeId; +@property (nonatomic, copy) NSString *dspCreativeId; +@property (nonatomic, copy) NSString *adNetworkType; +@property (nonatomic) CGSize adSize; +@property (nonatomic, copy) NSString *requestId; +@property (nonatomic, copy) NSString *adUnitId; + +- (instancetype)initWithConfiguration:(MPAdConfiguration *)configuration; + +@end + +@interface MPLogEvent : NSObject + +#pragma mark - Public properties + +/* Event details */ + +/** + * The event or error name. Examples include "ad_request", "ad_impression", "ad_click", + * "json_missing_required_fields", "invalid_url", "invalid_positioning_data". + */ +@property (nonatomic, copy) NSString *eventName; + +/** + * The event or error category. This is typically set to the component in which the event + * or error occurred. Examples include "network", "mraid_video", "mopub_native", "facebook_banner", + * "server_positioning", "client_positioning". + */ +@property (nonatomic, copy) NSString *eventCategory; + +/** + * Creation time of the object. + */ +@property (nonatomic, readonly) NSDate *timestamp; + +/** + * The scribe category that the log event will be bucketed into. + */ +@property (nonatomic, readonly) MPLogEventScribeCategory scribeCategory; + + +/* Ad details */ + +/** + * The MoPub AdUnit ID string that is associated with the event. + */ +@property (nonatomic, copy) NSString *adUnitId; + +/** + * The MoPub Creative ID string that is associated with the event. + */ +@property (nonatomic, copy) NSString *adCreativeId; + +/** + * The DSP Creative ID string that is associated with the event. + */ +@property (nonatomic, copy) NSString *dspCreativeId; + +/** + * Identifier for a class of ad. Examples include "html", "mraid", "interstitial", "json", + * "custom", "clear". + */ +@property (nonatomic, copy) NSString *adType; + +/** + * Identifier for an ad network type. Examples include "admob", "custom", "custom_native", "mojiva", + * "huntmads", "millennial". + */ +@property (nonatomic, copy) NSString *adNetworkType; + +/** + * The ad's size in device independent pixels (dips). + */ +@property (nonatomic) CGSize adSize; + +/* App details */ + +/** + * The name of the app the SDK is being included in + */ +@property (nonatomic, copy) NSString *appName; + +/** + * The app store identifier for the app the SDK is being included in + */ +@property (nonatomic, copy) NSString *appStoreId; + +/** + * The app store identifier for the app the SDK is being included in + */ +@property (nonatomic, copy) NSString *appBundleId; + +/** + * The version of the client app the SDK is included in + */ +@property (nonatomic, copy) NSString *appVersion; + + +/* Performance details */ + +/** + * Time taken in ms to perform a request or action + */ +@property (nonatomic, readonly) NSUInteger performanceDurationMs; + + +/* Request details */ + +/** + * The unique ID created by the MoPub ad server for the ad request + */ +@property (nonatomic, copy) NSString *requestId; + +/** + * The status code of the request from the MoPub ad server + */ +@property (nonatomic) NSUInteger requestStatusCode; + +/** + * The full URI for the request to the adserver + */ +@property (nonatomic, copy) NSString *requestURI; + +/** + * The number of retries made in the request. + */ +@property (nonatomic) NSUInteger requestRetries; + + +/** SDK details */ + +/** + * The current MoPub SDK version, e.g. "3.1.0" + */ +@property (nonatomic, copy, readonly) NSString *sdkVersion; + + +/* Device details */ + +/** + * The name of the device, e.g. iPhone, iPad, iPod + */ +@property (nonatomic, copy, readonly) NSString *deviceModel; + +/** + * The version of iOS running on the device, e.g. 8.0.1, 6.2.1, etc + */ +@property (nonatomic, copy, readonly) NSString *deviceOSVersion; + +/** + * The device's screen size in device independent pixels (dips). + */ +@property (nonatomic, readonly) CGSize deviceSize; + +/* Geo details */ + +/** + * Latitude and longitude + */ +@property (nonatomic, readonly) double geoLat; +@property (nonatomic, readonly) double geoLon; + +/** + * The radius of the circle in meters of the estimated accuracy of the latitude and longitude + */ +@property (nonatomic, readonly) double geoAccuracy; + + +/* Network/Carrier details */ + +@property (nonatomic, readonly) MPLogEventNetworkType networkType; +@property (nonatomic, copy, readonly) NSString *networkOperatorCode; +@property (nonatomic, copy, readonly) NSString *networkOperatorName; +@property (nonatomic, copy, readonly) NSString *networkISOCountryCode; +@property (nonatomic, copy, readonly) NSString *networkSIMCode; +@property (nonatomic, copy, readonly) NSString *networkSIMOperatorName; +@property (nonatomic, copy, readonly) NSString *networkSimISOCountryCode; + +/* Client details */ + +/** + * User specific, unique, resettable ID for advertising, i.e. IFA. + */ +@property (nonatomic, copy, readonly) NSString *clientAdvertisingId; + +/** + * Whether or not the user has limited ad tracking. + */ + +@property (nonatomic, readonly) BOOL clientDoNotTrack; + +- (instancetype)initWithEventCategory:(NSString *)eventCategory eventName:(NSString *)eventName; + +- (NSString *)serialize; +- (NSDictionary *)asDictionary; + +/** + * Current timestamp in ms since January 1, 1970 00:00:00.0 UTC (aka epoch time) + */ +- (NSUInteger)timestampAsEpoch; + +/** + * Record the end time for a timed event. The start time will be the event's timestamp, which is + * set on object creation. This will set the performanceDurationMs property with the timestamp - end time. + */ +- (void)recordEndTime; + +/** + * Convenience method to set common properties with the MPAdConfigurationLogEventProperties. + */ +- (void)setLogEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.m new file mode 100644 index 000000000..66a8a632e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEvent.m @@ -0,0 +1,294 @@ +// +// MPLogEvent.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPLogEvent.h" +#import "MPIdentityProvider.h" +#import "MPInternalUtils.h" +#import "MPCoreInstanceProvider.h" +#import "MPConstants.h" +#import "MPReachability.h" +#import "MPGeolocationProvider.h" + +NSUInteger const IOS_APP_PLATFORM_ID = 1; +NSUInteger const IOS_SDK_PRODUCT_ID = 0; +NSString * const IOS_MANUFACTURER_NAME = @"Apple"; + +/* + * Event names. + */ +NSString * const MPLogEventNameAdRequest = @"ad_request"; +NSString * const MPLogEventNameClickthroughDwellTime = @"clickthrough_dwell_time"; + +/* + * Event categories. + */ +NSString * const MPLogEventCategoryRequests = @"requests"; +NSString * const MPLogEventCategoryNativeVideo = @"native_video"; +NSString * const MPLogEventCategoryAdInteractions = @"ad_interactions"; + +@interface MPAdConfigurationLogEventProperties () + +@end + +@implementation MPAdConfigurationLogEventProperties + +- (instancetype)initWithConfiguration:(MPAdConfiguration *)configuration +{ + if (self = [super init]) { + _adType = configuration.headerAdType; + _adCreativeId = configuration.creativeId; + _dspCreativeId = configuration.dspCreativeId; + _adNetworkType = configuration.networkType; + _adSize = configuration.preferredSize; + + NSDictionary *failURLQueryParameters = MPDictionaryFromQueryString([configuration.failoverURL query]); + _requestId = failURLQueryParameters[@"request_id"]; + _adUnitId = failURLQueryParameters[@"id"]; + } + return self; +} + +@end + + +#pragma mark - Private properties + +@interface MPLogEvent () + +@property (nonatomic, readwrite) NSDate *timestamp; +@property (nonatomic, readwrite) MPLogEventScribeCategory scribeCategory; +@property (nonatomic, copy, readwrite) NSString *sdkVersion; +@property (nonatomic, copy, readwrite) NSString *deviceModel; +@property (nonatomic, copy, readwrite) NSString *deviceOSVersion; +@property (nonatomic, readwrite) CGSize deviceSize; +@property (nonatomic, readwrite) double geoLat; +@property (nonatomic, readwrite) double geoLon; +@property (nonatomic, readwrite) double geoAccuracy; +@property (nonatomic, readwrite) MPLogEventNetworkType networkType; +@property (nonatomic, copy, readwrite) NSString *networkOperatorCode; +@property (nonatomic, copy, readwrite) NSString *networkOperatorName; +@property (nonatomic, copy, readwrite) NSString *networkISOCountryCode; +@property (nonatomic, readwrite) NSUInteger performanceDurationMs; +@property (nonatomic, copy, readwrite) NSString *networkSIMCode; +@property (nonatomic, copy, readwrite) NSString *networkSIMOperatorName; +@property (nonatomic, copy, readwrite) NSString *networkSimISOCountryCode; +@property (nonatomic, copy, readwrite) NSString *clientAdvertisingId; +@property (nonatomic, readwrite) BOOL clientDoNotTrack; + +@end + + +@implementation MPLogEvent + +- (instancetype)initWithEventCategory:(NSString *)eventCategory eventName:(NSString *)eventName +{ + if (self = [super init]) { + + MPCoreInstanceProvider *provider = [MPCoreInstanceProvider sharedProvider]; + + [self setEventName:eventName]; + [self setEventCategory:eventCategory]; + + [self setTimestamp:[NSDate date]]; + [self setScribeCategory:MPExchangeClientEventCategory]; + + // SDK Info + [self setSdkVersion:MP_SDK_VERSION]; + + // Device info + UIDevice *device = [UIDevice currentDevice]; + [self setDeviceModel:[device model]]; + [self setDeviceOSVersion:[device systemVersion]]; + + [self setDeviceSize:MPScreenBounds().size]; + + // Geolocation info + CLLocation *location = [[[MPCoreInstanceProvider sharedProvider] sharedMPGeolocationProvider] lastKnownLocation]; + [self setGeoLat:location.coordinate.latitude]; + [self setGeoLon:location.coordinate.longitude]; + [self setGeoAccuracy:location.horizontalAccuracy]; + + // Client info + [self setClientDoNotTrack:![MPIdentityProvider advertisingTrackingEnabled]]; + // Note: we've chosen at this time to never send the real IDFA. + [self setClientAdvertisingId:[MPIdentityProvider obfuscatedIdentifier]]; + + + // Network/Carrier info + if ([provider sharedMPReachability].hasWifi) { + [self setNetworkType:MPLogEventNetworkTypeWifi]; + } else if ([provider sharedMPReachability].hasCellular) { + [self setNetworkType:MPLogEventNetworkTypeMobile]; + + NSDictionary *carrierInfo = [[MPCoreInstanceProvider sharedProvider] sharedCarrierInfo]; + NSString *networkOperatorName = carrierInfo[@"carrierName"]; + NSString *mcc = carrierInfo[@"mobileCountryCode"]; + NSString *mnc = carrierInfo[@"mobileNetworkCode"]; + NSString *networkOperatorCode = [NSString stringWithFormat:@"%@%@", mcc, mnc]; + NSString *isoCountryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; + + [self setNetworkOperatorName:networkOperatorName]; + [self setNetworkSIMOperatorName:networkOperatorName]; + + [self setNetworkSIMCode:networkOperatorCode]; + [self setNetworkOperatorCode:networkOperatorCode]; + + [self setNetworkISOCountryCode:isoCountryCode]; + [self setNetworkSimISOCountryCode:isoCountryCode]; + + } else { + [self setNetworkType:MPLogEventNetworkTypeUnknown]; + } + + } + + return self; +} + +- (void)setRequestURI:(NSString *)requestURI +{ + // We don't pass up the advertising identifier so we obfuscate it. + _requestURI = [requestURI stringByReplacingOccurrencesOfString:[MPIdentityProvider identifier] + withString:[MPIdentityProvider obfuscatedIdentifier]]; +} + +- (NSUInteger)appPlatform +{ + return IOS_APP_PLATFORM_ID; +} + +- (NSUInteger)sdkProduct +{ + return IOS_SDK_PRODUCT_ID; +} + +- (NSString *)deviceManufacturer +{ + return IOS_MANUFACTURER_NAME; +} + +/** + * Current timestamp in ms since January 1, 1970 00:00:00.0 UTC (aka epoch time) + */ +- (NSUInteger)timestampAsEpoch +{ + return [[self timestamp] timeIntervalSince1970]; +} + +- (NSString *)eventCategoryAsString +{ + return @"exchange_client_event"; +} + +- (NSUInteger)networkTypeAsInteger +{ + switch ([self networkType]) { + case MPLogEventNetworkTypeUnknown: + return 0; + break; + case MPLogEventNetworkTypeEthernet: + return 1; + break; + case MPLogEventNetworkTypeWifi: + return 2; + break; + case MPLogEventNetworkTypeMobile: + return 3; + break; + default: + return 0; + break; + } +} + +- (NSDictionary *)asDictionary +{ + NSMutableDictionary *d = [[NSMutableDictionary alloc] init]; + + [d mp_safeSetObject:[self eventCategoryAsString] forKey:@"_category_"]; + [d mp_safeSetObject:[self eventName] forKey:@"name"]; + [d mp_safeSetObject:[self eventCategory] forKey:@"name_category"]; + + [d mp_safeSetObject:@([self sdkProduct]) forKey:@"sdk_product"]; + [d mp_safeSetObject:[self sdkVersion] forKey:@"sdk_version"]; + + [d mp_safeSetObject:[self adUnitId] forKey:@"ad_unit_id"]; + [d mp_safeSetObject:[self adCreativeId] forKey:@"ad_creative_id"]; + [d mp_safeSetObject:[self dspCreativeId] forKey:@"dsp_creative_id"]; + [d mp_safeSetObject:[self adType] forKey:@"ad_type"]; + [d mp_safeSetObject:[self adNetworkType] forKey:@"ad_network_type"]; + [d mp_safeSetObject:@(self.adSize.width) forKey:@"ad_width_px"]; + [d mp_safeSetObject:@(self.adSize.height) forKey:@"ad_height_px"]; + + [d mp_safeSetObject:@([self appPlatform]) forKey:@"app_platform"]; + [d mp_safeSetObject:[self appName] forKey:@"app_name"]; + [d mp_safeSetObject:[self appStoreId] forKey:@"app_appstore_id"]; + [d mp_safeSetObject:[self appBundleId] forKey:@"app_bundle_id"]; + [d mp_safeSetObject:[self appVersion] forKey:@"app_version"]; + + [d mp_safeSetObject:[self clientAdvertisingId] forKey:@"client_advertising_id"]; + [d mp_safeSetObject:@([self clientDoNotTrack]) forKey:@"client_do_not_track"]; + + [d mp_safeSetObject:[self deviceManufacturer] forKey:@"device_manufacturer"]; + [d mp_safeSetObject:[self deviceModel] forKey:@"device_model"]; + [d mp_safeSetObject:[self deviceModel] forKey:@"device_product"]; + [d mp_safeSetObject:[self deviceOSVersion] forKey:@"device_os_version"]; + [d mp_safeSetObject:@(self.deviceSize.width) forKey:@"device_screen_width_px"]; + [d mp_safeSetObject:@(self.deviceSize.height) forKey:@"device_screen_height_px"]; + + [d mp_safeSetObject:@([self geoLat]) forKey:@"geo_lat"]; + [d mp_safeSetObject:@([self geoLon]) forKey:@"geo_lon"]; + [d mp_safeSetObject:@([self geoAccuracy]) forKey:@"geo_accuracy_radius_meters"]; + + [d mp_safeSetObject:@([self performanceDurationMs]) forKey:@"perf_duration_ms"]; + + [d mp_safeSetObject:@([self networkType]) forKey:@"network_type"]; + [d mp_safeSetObject:[self networkOperatorCode] forKey:@"network_operator_code"]; + [d mp_safeSetObject:[self networkOperatorName] forKey:@"network_operator_name"]; + [d mp_safeSetObject:[self networkISOCountryCode] forKey:@"network_iso_country_code"]; + [d mp_safeSetObject:[self networkSimISOCountryCode] forKey:@"network_sim_iso_country_code"]; + + [d mp_safeSetObject:[self requestId] forKey:@"req_id"]; + [d mp_safeSetObject:@([self requestStatusCode]) forKey:@"req_status_code"]; + [d mp_safeSetObject:[self requestURI] forKey:@"req_uri"]; + [d mp_safeSetObject:@([self requestRetries]) forKey:@"req_retries"]; + + [d mp_safeSetObject:@([self timestampAsEpoch]) forKey:@"timestamp_client"]; + + return d; +} + +- (NSString *)serialize +{ + NSData *data = [NSJSONSerialization dataWithJSONObject:[self asDictionary] options:0 error:nil]; + NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + return jsonString; +} + +- (void)recordEndTime +{ + NSDate *currentTime = [NSDate date]; + NSTimeInterval durationMs = [currentTime timeIntervalSinceDate:self.timestamp] * 1000.0; + + self.performanceDurationMs = durationMs; +} + +- (void)setLogEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties +{ + if (logEventProperties) { + [self setAdType:logEventProperties.adType]; + [self setAdCreativeId:logEventProperties.adCreativeId]; + [self setDspCreativeId:logEventProperties.dspCreativeId]; + [self setAdNetworkType:logEventProperties.adNetworkType]; + [self setAdSize:logEventProperties.adSize]; + [self setRequestId:logEventProperties.requestId]; + [self setAdUnitId:logEventProperties.adUnitId]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.h new file mode 100644 index 000000000..5f3995a3d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.h @@ -0,0 +1,15 @@ +// +// MPLogEventCommunicator.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPLogEventCommunicator : NSObject + +- (void)sendEvents:(NSArray *)events; +- (BOOL)isOverLimit; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.m new file mode 100644 index 000000000..af9ec75ac --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventCommunicator.m @@ -0,0 +1,94 @@ +// +// MPLogEventCommunicator.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPLogEventCommunicator.h" +#import "MPLogging.h" +#import "MPLogEvent.h" +#import "MPRetryingHTTPOperation.h" +#import "MPNetworkManager.h" +#import "MPCoreInstanceProvider.h" + +static NSString *const kAnalyticsURL = @"https://analytics.mopub.com/i/jot/exchange_client_event"; + +static const NSInteger MAX_CONCURRENT_CONNECTIONS = 1; + +@interface MPLogEventCommunicator () + +#if !OS_OBJECT_USE_OBJC +@property (nonatomic, assign) dispatch_queue_t eventProcessingQueue; +#else +@property (nonatomic, strong) dispatch_queue_t eventProcessingQueue; +#endif + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPLogEventCommunicator + +- (instancetype)init +{ + if (self = [super init]) { + _eventProcessingQueue = dispatch_queue_create("com.mopub.eventProcessingQueue", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (void)dealloc +{ +#if !OS_OBJECT_USE_OBJC + dispatch_release(_eventProcessingQueue); +#endif +} + +- (void)sendEvents:(NSArray *)events +{ + if (events && [events count]) { + dispatch_async(self.eventProcessingQueue, ^{ + NSURLRequest *request = [self buildRequestWithEvents:events]; + MPRetryingHTTPOperation *operation = [[MPRetryingHTTPOperation alloc] initWithRequest:request]; + [[[MPCoreInstanceProvider sharedProvider] sharedNetworkManager] addNetworkTransferOperation:operation]; + }); + } +} + +- (BOOL)isOverLimit +{ + if ([[[MPCoreInstanceProvider sharedProvider] sharedNetworkManager] networkTransferOperationCount] >= MAX_CONCURRENT_CONNECTIONS) { + return YES; + } + return NO; +} + +- (NSURLRequest *)buildRequestWithEvents:(NSArray *)events +{ + NSURL *URL = [NSURL URLWithString:kAnalyticsURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + [request setHTTPMethod:@"POST"]; + + NSString *POSTBodyString = [self makeParamStringForEvents:events]; + [request setHTTPBody:[POSTBodyString dataUsingEncoding:NSUTF8StringEncoding]]; + + return request; +} + +- (NSString *)makeParamStringForEvents:(NSArray *)events +{ + NSMutableArray *serializedEvents = [[NSMutableArray alloc] init]; + for (id event in events) { + [serializedEvents addObject:[event asDictionary]]; + } + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:serializedEvents options:0 error:nil]; + + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + NSString *paramString = [NSString stringWithFormat:@"log=%@", [jsonString mp_URLEncodedString]]; + + return paramString; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.h new file mode 100644 index 000000000..d32f3badd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.h @@ -0,0 +1,18 @@ +// +// MPLogEventRecorder.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MPLogEvent; + +void MPAddLogEvent(MPLogEvent *event); + +@interface MPLogEventRecorder : NSObject + +- (void)addEvent:(MPLogEvent *)event; + +@end \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.m new file mode 100644 index 000000000..164bb06be --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPLogEventRecorder.m @@ -0,0 +1,204 @@ +// +// MPLogEventRecorder.m +// MoPubSDK + +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#include +#import "MPLogEventRecorder.h" +#import "MPLogEvent.h" +#import "MPLogging.h" +#import "MPLogEventCommunicator.h" +#import "MPCoreInstanceProvider.h" +#import "MPTimer.h" + +void MPAddLogEvent(MPLogEvent *event) +{ + [[[MPCoreInstanceProvider sharedProvider] sharedLogEventRecorder] addEvent:event]; +} + +/** + * The max number of events allowed in the event queue. + */ +static const NSInteger QUEUE_LIMIT = 1000; + +/** + * The max number of events sent per request. + */ +static const NSInteger EVENT_SEND_THRESHOLD = 25; + +/** + * A number between 0 and 1 that represents the ratio at which events will be added + * to the event queue. For example, if SAMPLE_RATE is set to 0.2, then 20% of all + * events reported to the MPLogEventRecorder will be communicated to scribe. + */ +static const double SAMPLE_RATE = 0.1; + +/** + * The delay in seconds to wait until sending the next batch of events. + */ +static const NSTimeInterval POLL_DELAY_INTERVAL = 2 * 60; + +/** + * The maximum size of the requestIDLoggingCache. Note: since this is an + * NSCache, this is not a strict limit. + */ +static const NSInteger MAX_REQUEST_ID_CACHE_SIZE = 100; + +/////////////////////////////////////////////////////////////////////////// + +@interface MPLogEventRecorder () + +/** + * IMPORTANT: All access to self.events should be performed inside a block on self.dispatchQueue. + * This is to prevent concurrent access issues to the event array. + */ +@property (nonatomic) dispatch_queue_t dispatchQueue; +@property (nonatomic) NSMutableArray *events; +@property (nonatomic) NSCache *requestIDLoggingCache; + +@property (nonatomic) MPLogEventCommunicator *communicator; +@property (nonatomic) MPTimer *sendTimer; + +@end + +/////////////////////////////////////////////////////////////////////////// + +@implementation MPLogEventRecorder + +#pragma mark - Public methods + +- (instancetype)init +{ + if (self = [super init]) { + _events = [NSMutableArray array]; + _dispatchQueue = dispatch_queue_create("com.mopub.MPLogEventRecorder", NULL); + _communicator = [[MPLogEventCommunicator alloc] init]; + _sendTimer = [MPTimer timerWithTimeInterval:POLL_DELAY_INTERVAL + target:self + selector:@selector(sendEvents) + repeats:YES]; + [_sendTimer scheduleNow]; + _requestIDLoggingCache = [[NSCache alloc] init]; + _requestIDLoggingCache.countLimit = MAX_REQUEST_ID_CACHE_SIZE; + } + + return self; +} + +- (void)dealloc +{ + [self.sendTimer invalidate]; +} + +- (void)addEvent:(MPLogEvent *)event +{ + if (event) { + dispatch_async(self.dispatchQueue, ^{ + + // We only add the event to the queue if it's been selected for sampling. + if (![self sampleWithLogEvent:event]) { + MPLogDebug(@"RECORDER: Skipped adding log event to the queue because it failed the sample test."); + return; + } + + if ([self overQueueLimit]) { + MPLogDebug(@"RECORDER: Skipped adding log event to the queue because the event queue is over its size limit."); + return; + } + + [self.events addObject:event]; + MPLogDebug([NSString stringWithFormat:@"RECORDER: Event added. There are now %lu events in the queue.", (unsigned long)[self.events count]]); + }); + } +} + +#pragma mark - Private methods + +- (void)sendEvents +{ + dispatch_async(self.dispatchQueue, ^{ + MPLogDebug([NSString stringWithFormat:@"RECORDER: -sendEvents dispatched with %lu events in the queue.", (unsigned long)[self.events count]]); + + if ([self.communicator isOverLimit]) { + MPLogDebug(@"RECORDER: Skipped sending events because the communicator has too many active connections."); + return; + } + + if ([self.events count] == 0) { + return; + } + + if ([self.events count] > EVENT_SEND_THRESHOLD) { + MPLogDebug(@"RECORDER: Enqueueing a portion of events to be scribed."); + + // If we have more events than we can send at once, then send only the first slice. + NSRange sendRange; + sendRange.location = 0; + sendRange.length = EVENT_SEND_THRESHOLD; + NSArray *eventsToSend = [self.events subarrayWithRange:sendRange]; + + // Don't flush the event array in this case, because we'll have more to send in the + // future. + NSRange unSentRange; + unSentRange.location = sendRange.length; + unSentRange.length = [self.events count] - sendRange.length; + NSArray *unSentEvents = [self.events subarrayWithRange:unSentRange]; + + [self.communicator sendEvents:eventsToSend]; + self.events = [unSentEvents mutableCopy]; + } else { + MPLogDebug(@"RECORDER: Enqueueing all events to be scribed."); + [self.communicator sendEvents:[NSArray arrayWithArray:self.events]]; + [self.events removeAllObjects]; + } + + MPLogDebug([NSString stringWithFormat:@"RECORDER: There are now %lu events in the queue.", (unsigned long)[self.events count]]); + }); +} + +/** + * IMPORTANT: This method should only be called inside a block on the object's dispatch queue. + */ +- (BOOL)overQueueLimit +{ + return [self.events count] >= QUEUE_LIMIT; +} + +/* + Using this sampling method will ensure sampling decision remains constant for each request id. + */ +- (BOOL)sampleWithLogEvent:(MPLogEvent *)event +{ + BOOL samplingResult; + if (!event.requestId) { + samplingResult = [self sample]; + } else { + NSNumber *existingSampleAsNumber = [self.requestIDLoggingCache objectForKey:event.requestId]; + if (existingSampleAsNumber) { + samplingResult = [existingSampleAsNumber boolValue]; + } else { + samplingResult = [self sample]; + [self.requestIDLoggingCache setObject:[NSNumber numberWithBool:samplingResult] forKey:event.requestId]; + } + } + return samplingResult; +} + +- (BOOL)sample +{ + NSUInteger diceRoll = arc4random_uniform(100); + return [self shouldSampleForRate:SAMPLE_RATE diceRoll:diceRoll]; +} + +/** + * IMPORTANT: This method takes a sample rate between 0 and 1, and the diceRoll is intended to be between 0 and 100. It has been separated from the -(BOOL)sample method for easier testing. + */ +- (BOOL)shouldSampleForRate:(CGFloat)sampleRate diceRoll:(NSUInteger)diceRoll +{ + NSUInteger sample = (NSUInteger)(sampleRate*100); + return diceRoll < sample; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.h new file mode 100644 index 000000000..55e955864 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.h @@ -0,0 +1,35 @@ +// +// MPNetworkManager.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +// Adapted from NetworkManager in Apple's MVCNetworking sample code. + +// The shared instance of this class provides a way for clients to execute network-related +// operations while minimizing the impact to tasks executing on the main thread. In order to do +// this, it manages a single dedicated networking thread. + +@interface MPNetworkManager : NSObject + +@property (assign, readonly) NSUInteger networkTransferOperationCount; + +// Returns the network manager shared instance. ++ (instancetype)sharedNetworkManager; + +// Adds the specified operation object to an internal operation queue reserved for network transfer +// operations. +// +// If the specified operation supports the `runLoopThread` property and the value of that property +// is nil, this method sets the run loop thread of the operation to the dedicated networking thread. +// Any callbacks from an asynchronous network request will then run on the networking thread's +// run loop, rather than the main run loop. +- (void)addNetworkTransferOperation:(NSOperation *)operation; + +// Cancels the specified operation. +- (void)cancelOperation:(NSOperation *)operation; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.m new file mode 100644 index 000000000..478ef6c28 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPNetworkManager.m @@ -0,0 +1,93 @@ +// +// MPNetworkManager.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNetworkManager.h" + +#import "MPCoreInstanceProvider.h" +#import "MPRetryingHTTPOperation.h" + +static const double kNetworkThreadPriority = 0.3; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNetworkManager () + +@property (strong) NSThread *networkThread; +@property (strong, readwrite) NSOperationQueue *networkTransferQueue; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPNetworkManager + ++ (instancetype)sharedNetworkManager +{ + static MPNetworkManager *sNetworkManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sNetworkManager = [[[self class] alloc] init]; + [sNetworkManager startNetworkThread]; + }); + return sNetworkManager; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _networkThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkThreadMain) object:nil]; + _networkThread.name = @"com.mopub.MPNetworkManager"; + _networkThread.threadPriority = kNetworkThreadPriority; + + _networkTransferQueue = [[NSOperationQueue alloc] init]; + _networkTransferQueue.maxConcurrentOperationCount = 1; + } + return self; +} + +- (void)startNetworkThread +{ + [self.networkThread start]; +} + +- (void)networkThreadMain +{ + NSAssert(![NSThread isMainThread], @"The network thread should not be the main thread."); + + @autoreleasepool { + // Add a dummy input source to prevent the run loop from exiting immediately. + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; + [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; + [runLoop run]; + } +} + +#pragma mark - Public + +- (void)addNetworkTransferOperation:(NSOperation *)operation +{ + if ([operation respondsToSelector:@selector(setRunLoopThread:)]) { + if (![(id)operation runLoopThread]) { + [(id)operation setRunLoopThread:self.networkThread]; + } + } + + [self.networkTransferQueue addOperation:operation]; +} + +- (void)cancelOperation:(NSOperation *)operation +{ + [operation cancel]; +} + +- (NSUInteger)networkTransferOperationCount +{ + return [self.networkTransferQueue operationCount]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.h new file mode 100644 index 000000000..f57e4cfa2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.h @@ -0,0 +1,117 @@ +// +// MPQRunLoopOperation.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +/* + File: QRunLoopOperation.h + Contains: An abstract subclass of NSOperation for async run loop based operations. + Written by: DTS + Copyright: Copyright (c) 2010 Apple Inc. All Rights Reserved. + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of + these terms. If you do not agree with these terms, please do + not use, install, modify or redistribute this Apple software. + In consideration of your agreement to abide by the following + terms, and subject to these terms, Apple grants you a personal, + non-exclusive license, under Apple's copyrights in this + original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or + without modifications, in source and/or binary forms; provided + that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the + following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks + or logos of Apple Inc. may be used to endorse or promote + products derived from the Apple Software without specific prior + written permission from Apple. Except as expressly stated in + this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or + by other works in which the Apple Software may be incorporated. + The Apple Software is provided by Apple on an "AS IS" basis. + APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING + THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, + INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY + OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY + OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR + OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#import + +typedef enum { + MPQRunLoopOperationStateInited, + MPQRunLoopOperationStateExecuting, + MPQRunLoopOperationStateFinished +} MPQRunLoopOperationState; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// Adapted from QRunLoopOperation in Apple's MVCNetworking sample code. + +@interface MPQRunLoopOperation : NSOperation + +// Things you can configure before queuing the operation. + +// IMPORTANT: Do not change these after queuing the operation; it's very likely that +// bad things will happen if you do. + +@property (strong) NSThread *runLoopThread; +@property (copy) NSSet *runLoopModes; + +// Things that are only meaningful after the operation is finished. + +@property (copy, readonly) NSError *error; + +// Things you can only alter implicitly. + +@property (assign, readonly) MPQRunLoopOperationState state; +@property (strong, readonly) NSThread *actualRunLoopThread; +@property (assign, readonly) BOOL isActualRunLoopThread; +@property (copy, readonly) NSSet *actualRunLoopModes; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPQRunLoopOperation (SubClassSupport) + +// Override points + +// A subclass will probably need to override -operationDidStart and -operationWillFinish +// to set up and tear down its run loop sources, respectively. These are always called +// on the actual run loop thread. +// +// Note that -operationWillFinish will be called even if the operation is cancelled. +// +// -operationWillFinish can check the error property to see whether the operation was +// successful. error will be NSCocoaErrorDomain/NSUserCancelledError on cancellation. +// +// -operationDidStart is allowed to call -finishWithError:. + +- (void)operationDidStart; +- (void)operationWillFinish; + +// Support methods + +// A subclass should call finishWithError: when the operation is complete, passing nil +// for no error and an error otherwise. It must call this on the actual run loop thread. +// +// Note that this will call -operationWillFinish before returning. + +- (void)finishWithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.m new file mode 100644 index 000000000..e431d9727 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPQRunLoopOperation.m @@ -0,0 +1,265 @@ +// +// MPQRunLoopOperation.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +/* + File: QRunLoopOperation.m + Contains: An abstract subclass of NSOperation for async run loop based operations. + Written by: DTS + Copyright: Copyright (c) 2010 Apple Inc. All Rights Reserved. + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of + these terms. If you do not agree with these terms, please do + not use, install, modify or redistribute this Apple software. + In consideration of your agreement to abide by the following + terms, and subject to these terms, Apple grants you a personal, + non-exclusive license, under Apple's copyrights in this + original Apple software (the "Apple Software"), to use, + reproduce, modify and redistribute the Apple Software, with or + without modifications, in source and/or binary forms; provided + that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the + following text and disclaimers in all such redistributions of + the Apple Software. Neither the name, trademarks, service marks + or logos of Apple Inc. may be used to endorse or promote + products derived from the Apple Software without specific prior + written permission from Apple. Except as expressly stated in + this notice, no other rights or licenses, express or implied, + are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or + by other works in which the Apple Software may be incorporated. + The Apple Software is provided by Apple on an "AS IS" basis. + APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING + THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, + INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY + OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION + OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY + OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR + OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#import "MPQRunLoopOperation.h" + +@interface MPQRunLoopOperation () + +@property (assign, readwrite) MPQRunLoopOperationState state; +@property (copy, readwrite) NSError *error; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPQRunLoopOperation + +// Necessary since auto-synthesize doesn't happen when we manually implement both getter / setter. +@synthesize state = _state; + +- (instancetype)init +{ + self = [super init]; + if (self) { + NSAssert(_state == MPQRunLoopOperationStateInited, @"MPQRunLoopOperation must be in the inited state upon initialization."); + } + return self; +} + +#pragma mark - Properties + +// Returns the effective run loop thread, that is, the one set by the user +// or, if that's not set, the main thread. +- (NSThread *)actualRunLoopThread +{ + return self.runLoopThread ?: [NSThread mainThread]; +} + +// Returns YES if the current thread is the actual run loop thread. +- (BOOL)isActualRunLoopThread +{ + return [[NSThread currentThread] isEqual:[self actualRunLoopThread]]; +} + +// Returns the run loop modes in which this operation can be executed. If the user provides a set +// of run loop modes, this method will return that set; otherwise, it will return a set containing +// the default run loop mode. +- (NSSet *)actualRunLoopModes +{ + return ([self.runLoopModes count] != 0) ? self.runLoopModes : [NSSet setWithObject:NSDefaultRunLoopMode]; +} + +#pragma mark - Core state transitions + +- (MPQRunLoopOperationState)state +{ + return _state; +} + +- (void)setState:(MPQRunLoopOperationState)newState +{ + @synchronized(self) { + MPQRunLoopOperationState oldState; + + // The following check is really important. The state can only go forward, and there + // should be no redundant changes to the state (that is, newState must never be + // equal to _state). + + assert(newState > _state); + + // inited -> executing = update isExecuting + // inited -> finished = update isFinished + // executing -> finished = update both isExecuting and isFinished + + oldState = _state; + + if ((newState == MPQRunLoopOperationStateExecuting) || (oldState == MPQRunLoopOperationStateExecuting)) { + [self willChangeValueForKey:@"isExecuting"]; + } + if (newState == MPQRunLoopOperationStateFinished) { + [self willChangeValueForKey:@"isFinished"]; + } + + _state = newState; + + if (newState == MPQRunLoopOperationStateFinished) { + [self didChangeValueForKey:@"isFinished"]; + } + if ((newState == MPQRunLoopOperationStateExecuting) || (oldState == MPQRunLoopOperationStateExecuting)) { + [self didChangeValueForKey:@"isExecuting"]; + } + } +} + +- (void)startOnRunLoopThread +{ + NSAssert([self isActualRunLoopThread], @"-startOnRunLoopThread must be called on the run loop thread."); + NSAssert(self.state == MPQRunLoopOperationStateExecuting, @"The operation should be in the executing state."); + + if (self.isCancelled) { + // We were cancelled before we even got running. Flip the finished state immediately. + [self finishWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]]; + } else { + [self operationDidStart]; + } +} + +- (void)cancelOnRunLoopThread +{ + NSAssert([self isActualRunLoopThread], @"-cancelOnRunLoopThread must be called on the run loop thread."); + + // We know that a) state was kQRunLoopOperationStateExecuting when we were + // scheduled (that's enforced by -cancel), and b) the state can't go + // backwards (that's enforced by -setState), so we know the state must + // either be kQRunLoopOperationStateExecuting or kQRunLoopOperationStateFinished. + // We also know that the transition from executing to finished always + // happens on the run loop thread. Thus, we don't need to lock here. + // We can look at state and, if we're executing, trigger a cancellation. + + if (self.state == MPQRunLoopOperationStateExecuting) { + [self finishWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]]; + } +} + +- (void)finishWithError:(NSError *)error +{ + NSAssert([self isActualRunLoopThread], @"-finishWithError: must be called on the run loop thread."); + + // `error` may be nil, since this method serves as the "exit" point for the operation and will + // get called in both the success and the failure cases. + + if (!self.error) { + self.error = error; + } + + [self operationWillFinish]; + + self.state = MPQRunLoopOperationStateFinished; +} + +#pragma mark - Subclass override points + +- (void)operationDidStart +{ + NSAssert([self isActualRunLoopThread], @"-operationDidStart must be called on the run loop thread."); +} + +- (void)operationWillFinish +{ + NSAssert([self isActualRunLoopThread], @"-operationWillFinish must be called on the run loop thread."); +} + +#pragma mark - NSOperation overrides + +/* + * All of the following overridden methods must be thread-safe. + */ + +- (BOOL)isConcurrent +{ + return YES; +} + +- (BOOL)isExecuting +{ + return self.state == MPQRunLoopOperationStateExecuting; +} + +- (BOOL)isFinished +{ + return self.state == MPQRunLoopOperationStateFinished; +} + +- (void)start +{ + NSAssert(self.state == MPQRunLoopOperationStateInited, @"-start cannot be called on an executing or finished operation."); + + // We have to change the state here, otherwise isExecuting won't necessarily return + // true by the time we return from -start. Also, we don't test for cancellation + // here because that would a) result in us sending isFinished notifications on a + // thread that isn't our run loop thread, and b) confuse the core cancellation code, + // which expects to run on our run loop thread. Finally, we don't have to worry + // about races with other threads calling -start. Only one thread is allowed to + // start us at a time + + self.state = MPQRunLoopOperationStateExecuting; + [self performSelector:@selector(startOnRunLoopThread) onThread:self.actualRunLoopThread withObject:nil waitUntilDone:NO modes:[self.actualRunLoopModes allObjects]]; +} + +- (void)cancel +{ + BOOL shouldRunCancelOnRunLoopThread; + BOOL wasAlreadyCancelled; + + // We need to synchronise here to avoid state changes to isCancelled and state + // while we're running. + + @synchronized(self) { + wasAlreadyCancelled = self.isCancelled; + + // Call our super class so that isCancelled starts returning true immediately. + [super cancel]; + + // If we were the one to set isCancelled (that is, we won the race with regards + // other threads calling -cancel) and we're actually running (that is, we lost + // the race with other threads calling -start and the run loop thread finishing), + // we schedule to run on the run loop thread. + + shouldRunCancelOnRunLoopThread = !wasAlreadyCancelled && self.state == MPQRunLoopOperationStateExecuting; + } + + if (shouldRunCancelOnRunLoopThread) { + [self performSelector:@selector(cancelOnRunLoopThread) onThread:[self actualRunLoopThread] withObject:nil waitUntilDone:NO modes:[self.actualRunLoopModes allObjects]]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.h new file mode 100644 index 000000000..0cde2fbe9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.h @@ -0,0 +1,34 @@ +// +// MPRetryingHTTPOperation.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +#import "MPQRunLoopOperation.h" + +extern NSString * const MPRetryingHTTPOperationErrorDomain; + +typedef enum { + MPRetryingHTTPOperationReceivedNonRetryResponse = -1000, + MPRetryingHTTPOperationExceededRetryLimit = -1001 +} MPRetryingHTTPOperationErrorCode; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// Adapted from QHTTPOperation / RetryingHTTPOperation in Apple's MVCNetworking sample code. + +@interface MPRetryingHTTPOperation : MPQRunLoopOperation + +// Things that are configured via the init method and can't be changed. +@property (copy, readonly) NSURLRequest *request; + +// Things that are only meaningful after the operation is finished. +@property (copy, readonly) NSHTTPURLResponse *lastResponse; +@property (strong, readonly) NSMutableData *lastReceivedData; + +- (instancetype)initWithRequest:(NSURLRequest *)request; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.m new file mode 100644 index 000000000..49a55c638 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Event Logging/MPRetryingHTTPOperation.m @@ -0,0 +1,147 @@ +// +// MPRetryingHTTPOperation.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRetryingHTTPOperation.h" + +#import "MPLogging.h" + +NSString * const MPRetryingHTTPOperationErrorDomain = @"com.mopub.MPRetryingHTTPOperation"; +static const NSUInteger kMaximumFailedRetryAttempts = 5; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPRetryingHTTPOperation () + +@property (copy, readwrite) NSURLRequest *request; +@property (strong) NSURLConnection *connection; +@property (copy, readwrite) NSHTTPURLResponse *lastResponse; +@property (strong, readwrite) NSMutableData *lastReceivedData; +@property (assign) NSUInteger failedRetryAttempts; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPRetryingHTTPOperation + +- (instancetype)initWithRequest:(NSURLRequest *)request +{ + NSAssert(request != nil, @"-initWithRequest: cannot take a nil request."); + NSAssert([request URL] != nil, @"-initWithRequest: cannot take a request whose URL is nil."); + + NSString *scheme = [[[request URL] scheme] lowercaseString]; + NSAssert([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"], @"-initWithRequest: can only take a request whose URL has an HTTP/HTTPS scheme."); + + self = [super init]; + if (self) { + _request = [request copy]; + _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; + } + return self; +} + +#pragma mark - MPQRunLoopOperation overrides + +- (void)operationDidStart +{ + [super operationDidStart]; + + MPLogDebug(@"Starting request: %@.", self.request); + [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [self.connection start]; +} + +- (void)operationWillFinish +{ + [super operationWillFinish]; + + [self.connection cancel]; + self.connection = nil; +} + +#pragma mark - Internal + +- (BOOL)shouldRetryForResponse:(NSHTTPURLResponse *)response +{ + return response.statusCode == 503 || response.statusCode == 504; +} + +- (NSTimeInterval)retryDelayForFailedAttempts:(NSUInteger)failedAttempts +{ + if (failedAttempts == 0) { + // Return a short delay if this method is called when there have been no failed retries. + return 1; + } else { + return pow(2, failedAttempts - 1) * 60; + } +} + +- (void)retry +{ + NSAssert([self isActualRunLoopThread], @"Retries should occur on the run loop thread."); + + MPLogDebug(@"Retrying request: %@.", self.request); + + [self.lastReceivedData setLength:0]; + + self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO]; + [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [self.connection start]; +} + +#pragma mark - + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + NSAssert([self isActualRunLoopThread], @"NSURLConnection callbacks should occur on the run loop thread."); + NSAssert([response isKindOfClass:[NSHTTPURLResponse class]], @"Response must be of type NSHTTPURLResponse."); + + self.lastResponse = (NSHTTPURLResponse *)response; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + NSAssert([self isActualRunLoopThread], @"NSURLConnection callbacks should occur on the run loop thread."); + + if (!self.lastReceivedData) { + self.lastReceivedData = [NSMutableData data]; + } + + [self.lastReceivedData appendData:data]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + NSAssert([self isActualRunLoopThread], @"NSURLConnection callbacks should occur on the run loop thread."); + + if (self.lastResponse.statusCode == 200) { + MPLogDebug(@"Successful request: %@.", self.request); + [self finishWithError:nil]; + } else if (self.failedRetryAttempts > kMaximumFailedRetryAttempts) { + MPLogDebug(@"Too many failed attempts for this request: %@.", self.request); + [self finishWithError:[NSError errorWithDomain:MPRetryingHTTPOperationErrorDomain code:MPRetryingHTTPOperationExceededRetryLimit userInfo:nil]]; + } else if ([self shouldRetryForResponse:self.lastResponse]) { + self.failedRetryAttempts++; + NSTimeInterval retryDelay = [self retryDelayForFailedAttempts:self.failedRetryAttempts]; + MPLogDebug(@"Server error during attempt #%@ for request: %@.", @(self.failedRetryAttempts), self.request); + MPLogDebug(@"Backing off: %.1f", retryDelay); + [self performSelector:@selector(retry) withObject:nil afterDelay:retryDelay]; + } else { + MPLogDebug(@"%@", [[NSString alloc] initWithData:self.request.HTTPBody encoding:NSUTF8StringEncoding]); + MPLogDebug(@"Failed request: %@, status code: %ld, error: %@.", self.request, self.lastResponse.statusCode, self.error); + [self finishWithError:[NSError errorWithDomain:MPRetryingHTTPOperationErrorDomain code:MPRetryingHTTPOperationReceivedNonRetryResponse userInfo:nil]]; + } +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + NSAssert([self isActualRunLoopThread], @"NSURLConnection callbacks should occur on the run loop thread."); + + [self finishWithError:error]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.h new file mode 100644 index 000000000..1d086166e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.h @@ -0,0 +1,51 @@ +// +// MPAdWebViewAgent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPAdDestinationDisplayAgent.h" +#import "MPWebView.h" + +enum { + MPAdWebViewEventAdDidAppear = 0, + MPAdWebViewEventAdDidDisappear = 1 +}; +typedef NSUInteger MPAdWebViewEvent; + +@protocol MPAdWebViewAgentDelegate; + +@class MPAdConfiguration; +@class CLLocation; + +@interface MPAdWebViewAgent : NSObject + +@property (nonatomic, strong) MPWebView *view; +@property (nonatomic, weak) id delegate; + +- (id)initWithAdWebViewFrame:(CGRect)frame delegate:(id)delegate; +- (void)loadConfiguration:(MPAdConfiguration *)configuration; +- (void)rotateToOrientation:(UIInterfaceOrientation)orientation; +- (void)invokeJavaScriptForEvent:(MPAdWebViewEvent)event; +- (void)forceRedraw; + +- (void)enableRequestHandling; +- (void)disableRequestHandling; + +@end + +@protocol MPAdWebViewAgentDelegate + +- (NSString *)adUnitId; +- (CLLocation *)location; +- (UIViewController *)viewControllerForPresentingModalView; +- (void)adDidClose:(MPWebView *)ad; +- (void)adDidFinishLoadingAd:(MPWebView *)ad; +- (void)adDidFailToLoadAd:(MPWebView *)ad; +- (void)adActionWillBegin:(MPWebView *)ad; +- (void)adActionWillLeaveApplication:(MPWebView *)ad; +- (void)adActionDidFinish:(MPWebView *)ad; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.m new file mode 100644 index 000000000..9e7c5e442 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPAdWebViewAgent.m @@ -0,0 +1,349 @@ +// +// MPAdWebViewAgent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPAdWebViewAgent.h" +#import "MPAdConfiguration.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MPAdDestinationDisplayAgent.h" +#import "NSURL+MPAdditions.h" +#import "UIWebView+MPAdditions.h" +#import "MPWebView.h" +#import "MPInstanceProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPUserInteractionGestureRecognizer.h" +#import "NSJSONSerialization+MPAdditions.h" +#import "NSURL+MPAdditions.h" +#import "MPInternalUtils.h" +#import "MPAPIEndPoints.h" + +#ifndef NSFoundationVersionNumber_iOS_6_1 +#define NSFoundationVersionNumber_iOS_6_1 993.00 +#endif + +#define MPOffscreenWebViewNeedsRenderingWorkaround() (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) + +@interface MPAdWebViewAgent () + +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, strong) MPAdDestinationDisplayAgent *destinationDisplayAgent; +@property (nonatomic, assign) BOOL shouldHandleRequests; +@property (nonatomic, strong) id adAlertManager; +@property (nonatomic, assign) BOOL userInteractedWithWebView; +@property (nonatomic, strong) MPUserInteractionGestureRecognizer *userInteractionRecognizer; +@property (nonatomic, assign) CGRect frame; + +- (void)performActionForMoPubSpecificURL:(NSURL *)URL; +- (BOOL)shouldIntercept:(NSURL *)URL navigationType:(UIWebViewNavigationType)navigationType; +- (void)interceptURL:(NSURL *)URL; + +@end + +@implementation MPAdWebViewAgent + +@synthesize configuration = _configuration; +@synthesize delegate = _delegate; +@synthesize destinationDisplayAgent = _destinationDisplayAgent; +@synthesize shouldHandleRequests = _shouldHandleRequests; +@synthesize view = _view; +@synthesize adAlertManager = _adAlertManager; +@synthesize userInteractedWithWebView = _userInteractedWithWebView; +@synthesize userInteractionRecognizer = _userInteractionRecognizer; + +- (id)initWithAdWebViewFrame:(CGRect)frame delegate:(id)delegate; +{ + self = [super init]; + if (self) { + _frame = frame; + + self.destinationDisplayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + self.delegate = delegate; + self.shouldHandleRequests = YES; + self.adAlertManager = [[MPCoreInstanceProvider sharedProvider] buildMPAdAlertManagerWithDelegate:self]; + + self.userInteractionRecognizer = [[MPUserInteractionGestureRecognizer alloc] initWithTarget:self action:@selector(handleInteraction:)]; + self.userInteractionRecognizer.cancelsTouchesInView = NO; + self.userInteractionRecognizer.delegate = self; + } + return self; +} + +- (void)dealloc +{ + self.userInteractionRecognizer.delegate = nil; + [self.userInteractionRecognizer removeTarget:self action:nil]; + [self.destinationDisplayAgent cancel]; + [self.destinationDisplayAgent setDelegate:nil]; + self.view.delegate = nil; +} + +- (void)handleInteraction:(UITapGestureRecognizer *)sender +{ + if (sender.state == UIGestureRecognizerStateEnded) { + self.userInteractedWithWebView = YES; + } +} + +#pragma mark - + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; +{ + return YES; +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingMailVC +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)adAlertManagerDidTriggerAlert:(MPAdAlertManager *)manager +{ + [self.adAlertManager processAdAlertOnce]; +} + +#pragma mark - Public + +- (void)loadConfiguration:(MPAdConfiguration *)configuration +{ + self.configuration = configuration; + + // Initialize web view + if (self.view != nil) { + self.view.delegate = nil; + [self.view removeFromSuperview]; + self.view = nil; + } + self.view = [[MPWebView alloc] initWithFrame:self.frame forceUIWebView:self.configuration.forceUIWebView]; + self.view.delegate = self; + [self.view addGestureRecognizer:self.userInteractionRecognizer]; + + // Ignore server configuration size for interstitials. At this point our web view + // is sized correctly for the device's screen. Currently the server sends down values for a 3.5in + // screen, and they do not size correctly on a 4in screen. + if (configuration.adType != MPAdTypeInterstitial) { + if ([configuration hasPreferredSize]) { + CGRect frame = self.view.frame; + frame.size.width = configuration.preferredSize.width; + frame.size.height = configuration.preferredSize.height; + self.view.frame = frame; + } + } + + // excuse interstitials from user tapped check since it's already a takeover experience + // and certain videos may delay tap gesture recognition + if (configuration.adType == MPAdTypeInterstitial) { + self.userInteractedWithWebView = YES; + } + + [self.view mp_setScrollable:configuration.scrollable]; + [self.view disableJavaScriptDialogs]; + + [self.view loadHTMLString:[configuration adResponseHTMLString] + baseURL:[NSURL URLWithString:[MPAPIEndpoints baseURL]] + ]; + + [self initAdAlertManager]; +} + +- (void)invokeJavaScriptForEvent:(MPAdWebViewEvent)event +{ + switch (event) { + case MPAdWebViewEventAdDidAppear: + [self.view stringByEvaluatingJavaScriptFromString:@"webviewDidAppear();"]; + break; + case MPAdWebViewEventAdDidDisappear: + [self.view stringByEvaluatingJavaScriptFromString:@"webviewDidClose();"]; + break; + default: + break; + } +} + +- (void)disableRequestHandling +{ + self.shouldHandleRequests = NO; + [self.destinationDisplayAgent cancel]; +} + +- (void)enableRequestHandling +{ + self.shouldHandleRequests = YES; +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)displayAgentWillPresentModal +{ + [self.delegate adActionWillBegin:self.view]; +} + +- (void)displayAgentWillLeaveApplication +{ + [self.delegate adActionWillLeaveApplication:self.view]; +} + +- (void)displayAgentDidDismissModal +{ + [self.delegate adActionDidFinish:self.view]; +} + +- (MPAdConfiguration *)adConfiguration +{ + return self.configuration; +} + +#pragma mark - + +- (BOOL)webView:(MPWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType +{ + if (!self.shouldHandleRequests) { + return NO; + } + + NSURL *URL = [request URL]; + if ([URL mp_isMoPubScheme]) { + [self performActionForMoPubSpecificURL:URL]; + return NO; + } else if ([self shouldIntercept:URL navigationType:navigationType]) { + [self interceptURL:URL]; + return NO; + } else { + // don't handle any deep links without user interaction + return self.userInteractedWithWebView || [URL mp_isSafeForLoadingWithoutUserAction]; + } +} + +- (void)webViewDidStartLoad:(MPWebView *)webView +{ + [self.view disableJavaScriptDialogs]; +} + + +#pragma mark - MoPub-specific URL handlers +- (void)performActionForMoPubSpecificURL:(NSURL *)URL +{ + MPLogDebug(@"MPAdWebView - loading MoPub URL: %@", URL); + MPMoPubHostCommand command = [URL mp_mopubHostCommand]; + switch (command) { + case MPMoPubHostCommandClose: + [self.delegate adDidClose:self.view]; + break; + case MPMoPubHostCommandFinishLoad: + [self.delegate adDidFinishLoadingAd:self.view]; + break; + case MPMoPubHostCommandFailLoad: + [self.delegate adDidFailToLoadAd:self.view]; + break; + default: + MPLogWarn(@"MPAdWebView - unsupported MoPub URL: %@", [URL absoluteString]); + break; + } +} + +#pragma mark - URL Interception +- (BOOL)shouldIntercept:(NSURL *)URL navigationType:(UIWebViewNavigationType)navigationType +{ + if ([URL mp_hasTelephoneScheme] || [URL mp_hasTelephonePromptScheme]) { + return YES; + } else if (!(self.configuration.shouldInterceptLinks)) { + return NO; + } else if (navigationType == UIWebViewNavigationTypeLinkClicked) { + return YES; + } else if (navigationType == UIWebViewNavigationTypeOther) { + return [[URL absoluteString] hasPrefix:[self.configuration clickDetectionURLPrefix]]; + } else { + return NO; + } +} + +- (void)interceptURL:(NSURL *)URL +{ + NSURL *redirectedURL = URL; + if (self.configuration.clickTrackingURL) { + NSString *path = [NSString stringWithFormat:@"%@&r=%@", + self.configuration.clickTrackingURL.absoluteString, + [[URL absoluteString] mp_URLEncodedString]]; + redirectedURL = [NSURL URLWithString:path]; + } + + [self.destinationDisplayAgent displayDestinationForURL:redirectedURL]; +} + +#pragma mark - Utility + +- (void)initAdAlertManager +{ + self.adAlertManager.adConfiguration = self.configuration; + self.adAlertManager.adUnitId = [self.delegate adUnitId]; + self.adAlertManager.targetAdView = self.view; + self.adAlertManager.location = [self.delegate location]; + [self.adAlertManager beginMonitoringAlerts]; +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)orientation +{ + [self forceRedraw]; +} + +- (void)forceRedraw +{ + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + int angle = -1; + switch (orientation) { + case UIInterfaceOrientationPortrait: angle = 0; break; + case UIInterfaceOrientationLandscapeLeft: angle = 90; break; + case UIInterfaceOrientationLandscapeRight: angle = -90; break; + case UIInterfaceOrientationPortraitUpsideDown: angle = 180; break; + default: break; + } + + if (angle == -1) return; + + // UIWebView doesn't seem to fire the 'orientationchange' event upon rotation, so we do it here. + NSString *orientationEventScript = [NSString stringWithFormat: + @"window.__defineGetter__('orientation',function(){return %d;});" + @"(function(){ var evt = document.createEvent('Events');" + @"evt.initEvent('orientationchange',true,true);window.dispatchEvent(evt);})();", + angle]; + [self.view stringByEvaluatingJavaScriptFromString:orientationEventScript]; + + // XXX: If the UIWebView is rotated off-screen (which may happen with interstitials), its + // content may render off-center upon display. We compensate by setting the viewport meta tag's + // 'width' attribute to be the size of the webview. + NSString *viewportUpdateScript = [NSString stringWithFormat: + @"document.querySelector('meta[name=viewport]')" + @".setAttribute('content', 'width=%f;', false);", + self.view.frame.size.width]; + [self.view stringByEvaluatingJavaScriptFromString:viewportUpdateScript]; + + // XXX: In iOS 7, off-screen UIWebViews will fail to render certain image creatives. + // Specifically, creatives that only contain an tag whose src attribute uses a 302 + // redirect will not be rendered at all. One workaround is to temporarily change the web view's + // internal contentInset property; this seems to force the web view to re-draw. + if (MPOffscreenWebViewNeedsRenderingWorkaround()) { + if ([self.view respondsToSelector:@selector(scrollView)]) { + UIScrollView *scrollView = self.view.scrollView; + UIEdgeInsets originalInsets = scrollView.contentInset; + UIEdgeInsets newInsets = UIEdgeInsetsMake(originalInsets.top + 1, + originalInsets.left, + originalInsets.bottom, + originalInsets.right); + scrollView.contentInset = newInsets; + scrollView.contentInset = originalInsets; + } + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.h new file mode 100644 index 000000000..d6784f2b4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.h @@ -0,0 +1,19 @@ +// +// MPHTMLBannerCustomEvent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPBannerCustomEvent.h" +#import "MPAdWebViewAgent.h" +#import "MPPrivateBannerCustomEventDelegate.h" + +@interface MPHTMLBannerCustomEvent : MPBannerCustomEvent + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-property-synthesis" +@property (nonatomic, weak) id delegate; +#pragma clang diagnostic pop + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.m new file mode 100644 index 000000000..af30a10e7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLBannerCustomEvent.m @@ -0,0 +1,103 @@ +// +// MPHTMLBannerCustomEvent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPHTMLBannerCustomEvent.h" +#import "MPWebView.h" +#import "MPLogging.h" +#import "MPAdConfiguration.h" +#import "MPInstanceProvider.h" + +@interface MPHTMLBannerCustomEvent () + +@property (nonatomic, strong) MPAdWebViewAgent *bannerAgent; + +@end + +@implementation MPHTMLBannerCustomEvent + +@synthesize bannerAgent = _bannerAgent; + +- (BOOL)enableAutomaticImpressionAndClickTracking +{ + return NO; +} + +- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info +{ + MPLogInfo(@"Loading MoPub HTML banner"); + MPLogTrace(@"Loading banner with HTML source: %@", [[self.delegate configuration] adResponseHTMLString]); + + CGRect adWebViewFrame = CGRectMake(0, 0, size.width, size.height); + self.bannerAgent = [[MPInstanceProvider sharedProvider] buildMPAdWebViewAgentWithAdWebViewFrame:adWebViewFrame + delegate:self]; + [self.bannerAgent loadConfiguration:[self.delegate configuration]]; +} + +- (void)dealloc +{ + self.bannerAgent.delegate = nil; +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation +{ + [self.bannerAgent rotateToOrientation:newOrientation]; +} + +#pragma mark - MPAdWebViewAgentDelegate + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)adDidFinishLoadingAd:(MPWebView *)ad +{ + MPLogInfo(@"MoPub HTML banner did load"); + [self.delegate bannerCustomEvent:self didLoadAd:ad]; +} + +- (void)adDidFailToLoadAd:(MPWebView *)ad +{ + MPLogInfo(@"MoPub HTML banner did fail"); + [self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil]; +} + +- (void)adDidClose:(MPWebView *)ad +{ + //don't care +} + +- (void)adActionWillBegin:(MPWebView *)ad +{ + MPLogInfo(@"MoPub HTML banner will begin action"); + [self.delegate bannerCustomEventWillBeginAction:self]; +} + +- (void)adActionDidFinish:(MPWebView *)ad +{ + MPLogInfo(@"MoPub HTML banner did finish action"); + [self.delegate bannerCustomEventDidFinishAction:self]; +} + +- (void)adActionWillLeaveApplication:(MPWebView *)ad +{ + MPLogInfo(@"MoPub HTML banner will leave application"); + [self.delegate bannerCustomEventWillLeaveApplication:self]; +} + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.h new file mode 100644 index 000000000..1d767b74d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.h @@ -0,0 +1,19 @@ +// +// MPHTMLInterstitialCustomEvent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPInterstitialCustomEvent.h" +#import "MPHTMLInterstitialViewController.h" +#import "MPPrivateInterstitialCustomEventDelegate.h" + +@interface MPHTMLInterstitialCustomEvent : MPInterstitialCustomEvent + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-property-synthesis" +@property (nonatomic, weak) id delegate; +#pragma clang diagnostic pop + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.m new file mode 100644 index 000000000..bc39e4128 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialCustomEvent.m @@ -0,0 +1,119 @@ +// +// MPHTMLInterstitialCustomEvent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPHTMLInterstitialCustomEvent.h" +#import "MPLogging.h" +#import "MPAdConfiguration.h" +#import "MPInstanceProvider.h" + +@interface MPHTMLInterstitialCustomEvent () + +@property (nonatomic, strong) MPHTMLInterstitialViewController *interstitial; +@property (nonatomic, assign) BOOL trackedImpression; + +@end + +@implementation MPHTMLInterstitialCustomEvent + +@synthesize interstitial = _interstitial; + +- (BOOL)enableAutomaticImpressionAndClickTracking +{ + // An HTML interstitial tracks its own clicks. Turn off automatic tracking to prevent the tap event callback + // from generating an additional click. + // However, an HTML interstitial does not track its own impressions so we must manually do it in this class. + // See interstitialDidAppear: + return NO; +} + +- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info +{ + MPLogInfo(@"Loading MoPub HTML interstitial"); + MPAdConfiguration *configuration = [self.delegate configuration]; + MPLogTrace(@"Loading HTML interstitial with source: %@", [configuration adResponseHTMLString]); + + self.interstitial = [[MPInstanceProvider sharedProvider] buildMPHTMLInterstitialViewControllerWithDelegate:self + orientationType:configuration.orientationType]; + [self.interstitial loadConfiguration:configuration]; +} + +- (void)showInterstitialFromRootViewController:(UIViewController *)rootViewController +{ + [self.interstitial presentInterstitialFromViewController:rootViewController]; +} + +#pragma mark - MPInterstitialViewControllerDelegate + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial did load"); + [self.delegate interstitialCustomEvent:self didLoadAd:self.interstitial]; +} + +- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial did fail"); + [self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil]; +} + +- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial will appear"); + [self.delegate interstitialCustomEventWillAppear:self]; +} + +- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial did appear"); + [self.delegate interstitialCustomEventDidAppear:self]; + + if (!self.trackedImpression) { + self.trackedImpression = YES; + [self.delegate trackImpression]; + } +} + +- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial will disappear"); + [self.delegate interstitialCustomEventWillDisappear:self]; +} + +- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial did disappear"); + [self.delegate interstitialCustomEventDidDisappear:self]; + + // Deallocate the interstitial as we don't need it anymore. If we don't deallocate the interstitial after dismissal, + // then the html in the webview will continue to run which could lead to bugs such as continuing to play the sound of an inline + // video since the app may hold onto the interstitial ad controller. Moreover, we keep an array of controllers around as well. + self.interstitial = nil; +} + +- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial did receive tap event"); + [self.delegate interstitialCustomEventDidReceiveTapEvent:self]; +} + +- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub HTML interstitial will leave application"); + [self.delegate interstitialCustomEventWillLeaveApplication:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.h new file mode 100644 index 000000000..f15ebfe61 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.h @@ -0,0 +1,21 @@ +// +// MPHTMLInterstitialViewController.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import + +#import "MPAdWebViewAgent.h" +#import "MPInterstitialViewController.h" + +@class MPAdConfiguration; + +@interface MPHTMLInterstitialViewController : MPInterstitialViewController + +@property (nonatomic, strong) MPAdWebViewAgent *backingViewAgent; + +- (void)loadConfiguration:(MPAdConfiguration *)configuration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.m new file mode 100644 index 000000000..0c9eae253 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPHTMLInterstitialViewController.m @@ -0,0 +1,150 @@ +// +// MPHTMLInterstitialViewController.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPHTMLInterstitialViewController.h" +#import "MPWebView.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPInstanceProvider.h" + +@interface MPHTMLInterstitialViewController () + +@property (nonatomic, strong) MPWebView *backingView; + +@end + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPHTMLInterstitialViewController + +@synthesize delegate = _delegate; +@synthesize backingViewAgent = _backingViewAgent; +@synthesize backingView = _backingView; + +- (void)dealloc +{ + self.backingViewAgent.delegate = nil; + + self.backingView.delegate = nil; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = [UIColor blackColor]; + self.backingViewAgent = [[MPInstanceProvider sharedProvider] buildMPAdWebViewAgentWithAdWebViewFrame:self.view.bounds + delegate:self]; +} + +#pragma mark - Public + +- (void)loadConfiguration:(MPAdConfiguration *)configuration +{ + [self view]; + [self.backingViewAgent loadConfiguration:configuration]; + + self.backingView = self.backingViewAgent.view; + self.backingView.frame = self.view.bounds; + self.backingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | + UIViewAutoresizingFlexibleHeight; + [self.view addSubview:self.backingView]; +} + +- (void)willPresentInterstitial +{ + self.backingView.alpha = 0.0; + [self.delegate interstitialWillAppear:self]; +} + +- (void)didPresentInterstitial +{ + [self.backingViewAgent enableRequestHandling]; + [self.backingViewAgent invokeJavaScriptForEvent:MPAdWebViewEventAdDidAppear]; + + // XXX: In certain cases, UIWebView's content appears off-center due to rotation / auto- + // resizing while off-screen. -forceRedraw corrects this issue, but there is always a brief + // instant when the old content is visible. We mask this using a short fade animation. + [self.backingViewAgent forceRedraw]; + + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:0.3]; + self.backingView.alpha = 1.0; + [UIView commitAnimations]; + + [self.delegate interstitialDidAppear:self]; +} + +- (void)willDismissInterstitial +{ + [self.backingViewAgent disableRequestHandling]; + [self.delegate interstitialWillDisappear:self]; +} + +- (void)didDismissInterstitial +{ + [self.backingViewAgent invokeJavaScriptForEvent:MPAdWebViewEventAdDidDisappear]; + [self.delegate interstitialDidDisappear:self]; +} + +#pragma mark - Autorotation + +- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation +{ + [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; + + [self.backingViewAgent rotateToOrientation:self.interfaceOrientation]; +} + +#pragma mark - MPAdWebViewAgentDelegate + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return self; +} + +- (void)adDidFinishLoadingAd:(MPWebView *)ad +{ + [self.delegate interstitialDidLoadAd:self]; +} + +- (void)adDidFailToLoadAd:(MPWebView *)ad +{ + [self.delegate interstitialDidFailToLoadAd:self]; +} + +- (void)adActionWillBegin:(MPWebView *)ad +{ + [self.delegate interstitialDidReceiveTapEvent:self]; +} + +- (void)adActionWillLeaveApplication:(MPWebView *)ad +{ + [self.delegate interstitialWillLeaveApplication:self]; + [self dismissInterstitialAnimated:NO]; +} + +- (void)adActionDidFinish:(MPWebView *)ad +{ + //NOOP: the landing page is going away, but not the interstitial. +} + +- (void)adDidClose:(MPWebView *)ad +{ + //NOOP: the ad is going away, but not the interstitial. +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.h new file mode 100644 index 000000000..0bb0ab2cc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.h @@ -0,0 +1,102 @@ +// +// MPWebView.h +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +/*** + * MPWebView + * This class is a wrapper class for WKWebView and UIWebView. Internally, it utilizes WKWebView when possible, and + * falls back on UIWebView only when WKWebView isn't available (i.e., in iOS 7). MPWebView's interface is meant to + * imitate UIWebView, and, in many cases, MPWebView can act as a drop-in replacement for UIWebView. MPWebView also + * blocks all JavaScript text boxes from appearing. + * + * While `stringByEvaluatingJavaScriptFromString:` does exist for UIWebView compatibility reasons, it's highly + * recommended that the caller uses `evaluateJavaScript:completionHandler:` whenever code can be reworked + * to make use of completion blocks to keep the advantages of asynchronicity. It solely fires off the javascript + * execution within WKWebView and does not wait or return. + * + * MPWebView currently does not support a few other features of UIWebView -- such as pagination -- as WKWebView also + * does not contain support. + ***/ + +#import + +@class MPWebView; + +@protocol MPWebViewDelegate + +@optional + +- (BOOL)webView:(MPWebView *)webView +shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType; + +- (void)webViewDidStartLoad:(MPWebView *)webView; + +- (void)webViewDidFinishLoad:(MPWebView *)webView; + +- (void)webView:(MPWebView *)webView +didFailLoadWithError:(NSError *)error; + +@end + +typedef void (^MPWebViewJavascriptEvaluationCompletionHandler)(id result, NSError *error); + +@interface MPWebView : UIView + +// If you -need- UIWebView for some reason, use this method to init and send `YES` to `forceUIWebView` to be sure +// you're using UIWebView regardless of OS. If any other `init` method is used, or if `NO` is used as the forceUIWebView +// parameter, WKWebView will be used when available. +- (instancetype)initWithFrame:(CGRect)frame forceUIWebView:(BOOL)forceUIWebView; + +@property (weak, nonatomic) id delegate; + +@property (nonatomic, readonly, getter=isLoading) BOOL loading; + +// These methods and properties are non-functional below iOS 9. If you call or try to set them, they'll do nothing. +// For the properties, if you try to access them, you'll get `NO` 100% of the time. They are entirely hidden when +// compiling with iOS 8 SDK or below. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +- (void)loadData:(NSData *)data + MIMEType:(NSString *)MIMEType +textEncodingName:(NSString *)encodingName + baseURL:(NSURL *)baseURL; + +@property (nonatomic) BOOL allowsLinkPreview; +@property (nonatomic, readonly) BOOL allowsPictureInPictureMediaPlayback; +#endif + +- (void)loadHTMLString:(NSString *)string + baseURL:(NSURL *)baseURL; + +- (void)loadRequest:(NSURLRequest *)request; +- (void)stopLoading; +- (void)reload; + +@property (nonatomic, readonly) BOOL canGoBack; +@property (nonatomic, readonly) BOOL canGoForward; +- (void)goBack; +- (void)goForward; + +@property (nonatomic) BOOL scalesPageToFit; +@property (nonatomic, readonly) UIScrollView *scrollView; + +- (void)evaluateJavaScript:(NSString *)javaScriptString + completionHandler:(MPWebViewJavascriptEvaluationCompletionHandler)completionHandler; + +// When using WKWebView, always returns @"" and solely fires the javascript execution without waiting on it. +// If you need a guaranteed return value from `stringByEvaluatingJavaScriptFromString:`, please use +// `evaluateJavaScript:completionHandler:` instead. +- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)javaScriptString; + +@property (nonatomic, readonly) BOOL allowsInlineMediaPlayback; +@property (nonatomic, readonly) BOOL mediaPlaybackRequiresUserAction; +@property (nonatomic, readonly) BOOL mediaPlaybackAllowsAirPlay; + +// UIWebView+MPAdditions methods +- (void)mp_setScrollable:(BOOL)scrollable; +- (void)disableJavaScriptDialogs; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.m new file mode 100644 index 000000000..71f45aa05 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/HTML/MPWebView.m @@ -0,0 +1,605 @@ +// +// MPWebView.m +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPWebView.h" + +#import + +static BOOL const kMoPubAllowsInlineMediaPlaybackDefault = YES; +static BOOL const kMoPubRequiresUserActionForMediaPlaybackDefault = NO; + +// Set defaults for this as its default differs between UIWebView and WKWebView +static BOOL const kMoPubAllowsLinkPreviewDefault = NO; + +static NSString *const kMoPubJavaScriptDisableDialogScript = @"window.alert = function() { }; window.prompt = function() { }; window.confirm = function() { };"; +static NSString *const kMoPubScalesPageToFitScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width, initial-scale=1.0, user-scalable=no'); document.getElementsByTagName('head')[0].appendChild(meta);"; + +static NSString *const kMoPubFrameKeyPathString = @"frame"; + +@interface MPWebView () + +@property (weak, nonatomic) WKWebView *wkWebView; +@property (weak, nonatomic) UIWebView *uiWebView; + +@end + +@implementation MPWebView + +- (instancetype)init { + if (self = [super init]) { + [self setUpStepsForceUIWebView:NO]; + } + + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + [self setUpStepsForceUIWebView:NO]; + } + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self setUpStepsForceUIWebView:NO]; + } + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame forceUIWebView:(BOOL)forceUIWebView { + if (self = [super initWithFrame:frame]) { + [self setUpStepsForceUIWebView:forceUIWebView]; + } + + return self; +} + +- (void)setUpStepsForceUIWebView:(BOOL)forceUIWebView { + // set up web view + UIView *webView; + + if (!forceUIWebView && [WKWebView class]) { + WKUserContentController *contentController = [[WKUserContentController alloc] init]; + WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; + config.allowsInlineMediaPlayback = kMoPubAllowsInlineMediaPlaybackDefault; + if ([config respondsToSelector:@selector(requiresUserActionForMediaPlayback)]) { + config.requiresUserActionForMediaPlayback = kMoPubRequiresUserActionForMediaPlaybackDefault; + } else { + config.mediaPlaybackRequiresUserAction = kMoPubRequiresUserActionForMediaPlaybackDefault; + } + config.userContentController = contentController; + + WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:self.bounds configuration:config]; + + wkWebView.UIDelegate = self; + wkWebView.navigationDelegate = self; + + webView = wkWebView; + + self.wkWebView = wkWebView; + + // Put WKWebView onto the offscreen view so any loading will complete correctly; see comment below. + [self retainWKWebViewOffscreen:wkWebView]; + } else { + UIWebView *uiWebView = [[UIWebView alloc] initWithFrame:self.bounds]; + + uiWebView.allowsInlineMediaPlayback = kMoPubAllowsInlineMediaPlaybackDefault; + uiWebView.mediaPlaybackRequiresUserAction = kMoPubRequiresUserActionForMediaPlaybackDefault; + + uiWebView.delegate = self; + + webView = uiWebView; + + self.uiWebView = uiWebView; + + [self addSubview:webView]; + } + + webView.backgroundColor = [UIColor clearColor]; + webView.opaque = NO; + + webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + // set default scalesPageToFit + self.scalesPageToFit = NO; + + // configure like the old MPAdWebView + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; + + // set default for allowsLinkPreview as they're different between WKWebView and UIWebView + self.allowsLinkPreview = kMoPubAllowsLinkPreviewDefault; + + // set up KVO to adjust the frame of the WKWebView to avoid white screens + if (self.wkWebView) { + [self addObserver:self + forKeyPath:kMoPubFrameKeyPathString + options:NSKeyValueObservingOptionOld + context:NULL]; + } +} + +// WKWebView won't load/execute javascript unless it's on the view hierarchy. Because the MoPub SDK uses a lot of +// javascript before adding the view to the hierarchy, let's stick the WKWebView into an offscreen-but-on-the-window +// view, and move it to self when self gets a window. +static UIView *gOffscreenView = nil; + +- (void)retainWKWebViewOffscreen:(WKWebView *)webView { + if (!gOffscreenView) { + gOffscreenView = [self constructOffscreenView]; + } + [gOffscreenView addSubview:webView]; +} + +- (void)cleanUpOffscreenView { + if (gOffscreenView.subviews.count == 0) { + [gOffscreenView removeFromSuperview]; + gOffscreenView = nil; + } +} + +- (UIView *)constructOffscreenView { + UIView *view = [[UIView alloc] initWithFrame:CGRectZero]; + view.clipsToBounds = YES; + + UIWindow *appWindow = [[UIApplication sharedApplication] keyWindow]; + [appWindow addSubview:view]; + + return view; +} + +- (void)didMoveToWindow { + // If using WKWebView, and if MPWebView is in the view hierarchy, and if the WKWebView is in the offscreen view currently, + // move our WKWebView to self and deallocate OffscreenView if no other MPWebView is using it. + if (self.wkWebView + && self.window != nil + && [self.wkWebView.superview isEqual:gOffscreenView]) { + self.wkWebView.frame = self.bounds; + [self addSubview:self.wkWebView]; + + // Don't keep OffscreenView if we don't need it; it can always be re-allocated again later + [self cleanUpOffscreenView]; + } else if (self.wkWebView + && self.window == nil + && [self.wkWebView.superview isEqual:self]) { + [self retainWKWebViewOffscreen:self.wkWebView]; + } +} + +// Occasionally, we encounter an issue where, when MPWebView is initialized at a different frame size than when it's shown, +// the WKWebView shows as all white because it doesn't have a chance to get redrawn at the new size before getting shown. +// This makes sure WKWebView is always already rendered at the correct size when it gets moved to the window. +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + // Only keep the wkWebView up-to-date if its superview is the offscreen view. + // If it's attached to self, the autoresizing mask should come into play & this is just extra work. + if ([keyPath isEqualToString:kMoPubFrameKeyPathString] + && [self.wkWebView.superview isEqual:gOffscreenView]) { + self.wkWebView.frame = self.bounds; + } +} + +- (void)dealloc { + // Remove KVO observer + if (self.wkWebView) { + [self removeObserver:self forKeyPath:kMoPubFrameKeyPathString]; + } + + // Avoids EXC_BAD_INSTRUCTION crash + self.wkWebView.scrollView.delegate = nil; + + // Be sure our WKWebView doesn't stay stuck to the static OffscreenView + [self.wkWebView removeFromSuperview]; + // Deallocate OffscreenView if needed + [self cleanUpOffscreenView]; +} + +- (BOOL)isLoading { + return self.uiWebView ? self.uiWebView.isLoading : self.wkWebView.isLoading; +} + +- (void)loadData:(NSData *)data + MIMEType:(NSString *)MIMEType +textEncodingName:(NSString *)encodingName + baseURL:(NSURL *)baseURL { + if (self.uiWebView) { + [self.uiWebView loadData:data + MIMEType:MIMEType + textEncodingName:encodingName + baseURL:baseURL]; + } else { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 + if ([self.wkWebView respondsToSelector:@selector(loadData:MIMEType:characterEncodingName:baseURL:)]) { + [self.wkWebView loadData:data + MIMEType:MIMEType + characterEncodingName:encodingName + baseURL:baseURL]; + } +#endif + } +} + +- (void)loadHTMLString:(NSString *)string + baseURL:(NSURL *)baseURL { + if (self.uiWebView) { + [self.uiWebView loadHTMLString:string + baseURL:baseURL]; + } else { + [self.wkWebView loadHTMLString:string + baseURL:baseURL]; + } +} + +- (void)loadRequest:(NSURLRequest *)request { + if (self.uiWebView) { + [self.uiWebView loadRequest:request]; + } else { + [self.wkWebView loadRequest:request]; + } +} + +- (void)stopLoading { + if (self.uiWebView) { + [self.uiWebView stopLoading]; + } else { + [self.wkWebView stopLoading]; + } +} + +- (void)reload { + if (self.uiWebView) { + [self.uiWebView reload]; + } else { + [self.wkWebView reload]; + } +} + +- (BOOL)canGoBack { + return self.uiWebView ? self.uiWebView.canGoBack : self.wkWebView.canGoBack; +} + +- (BOOL)canGoForward { + return self.uiWebView ? self.uiWebView.canGoForward : self.wkWebView.canGoForward; +} + +- (void)goBack { + if (self.uiWebView) { + [self.uiWebView goBack]; + } else { + [self.wkWebView goBack]; + } +} + +- (void)goForward { + if (self.uiWebView) { + [self.uiWebView goForward]; + } else { + [self.wkWebView goForward]; + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +- (void)setAllowsLinkPreview:(BOOL)allowsLinkPreview { + if (self.uiWebView) { + if ([self.uiWebView respondsToSelector:@selector(setAllowsLinkPreview:)]) { + self.uiWebView.allowsLinkPreview = allowsLinkPreview; + } + } else { + if ([self.wkWebView respondsToSelector:@selector(setAllowsLinkPreview:)]) { + self.wkWebView.allowsLinkPreview = allowsLinkPreview; + } + } +} + +- (BOOL)allowsLinkPreview { + if (self.uiWebView) { + if ([self.uiWebView respondsToSelector:@selector(allowsLinkPreview)]) { + return self.uiWebView.allowsLinkPreview; + } + } else { + if ([self.wkWebView respondsToSelector:@selector(allowsLinkPreview)]) { + return self.wkWebView.allowsLinkPreview; + } + } + + return NO; +} +#endif + +- (void)setScalesPageToFit:(BOOL)scalesPageToFit { + if (self.uiWebView) { + self.uiWebView.scalesPageToFit = scalesPageToFit; + } else { + if (scalesPageToFit) { + self.wkWebView.scrollView.delegate = nil; + + [self.wkWebView.configuration.userContentController removeAllUserScripts]; + } else { + // Make sure the scroll view can't scroll (prevent double tap to zoom) + self.wkWebView.scrollView.delegate = self; + + // Inject the user script to scale the page if needed + if (self.wkWebView.configuration.userContentController.userScripts.count == 0) { + WKUserScript *viewportScript = [[WKUserScript alloc] initWithSource:kMoPubScalesPageToFitScript + injectionTime:WKUserScriptInjectionTimeAtDocumentEnd + forMainFrameOnly:YES]; + [self.wkWebView.configuration.userContentController addUserScript:viewportScript]; + } + } + } +} + +- (BOOL)scalesPageToFit { + return self.uiWebView ? self.uiWebView.scalesPageToFit : self.scrollView.delegate == nil; +} + +- (UIScrollView *)scrollView { + return self.uiWebView ? self.uiWebView.scrollView : self.wkWebView.scrollView; +} + +- (void)evaluateJavaScript:(NSString *)javaScriptString + completionHandler:(MPWebViewJavascriptEvaluationCompletionHandler)completionHandler { + if (self.uiWebView) { + NSString *resultString = [self.uiWebView stringByEvaluatingJavaScriptFromString:javaScriptString]; + + if (completionHandler) { + completionHandler(resultString, nil); + } + } else { + [self.wkWebView evaluateJavaScript:javaScriptString + completionHandler:completionHandler]; + } +} + +- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)javaScriptString { + if (self.uiWebView) { + return [self.uiWebView stringByEvaluatingJavaScriptFromString:javaScriptString]; + } else { + // There is no way to reliably wait for `evaluateJavaScript:completionHandler:` to finish without risk of + // deadlocking the main thread. This method is called on the main thread and the completion block is also + // called on the main thread. + // Instead of waiting, just fire and return an empty string. + + // Methods attempted: + // libdispatch dispatch groups + // http://stackoverflow.com/questions/17920169/how-to-wait-for-method-that-has-completion-block-all-on-main-thread + + [self.wkWebView evaluateJavaScript:javaScriptString completionHandler:nil]; + return @""; + } +} + +- (BOOL)allowsInlineMediaPlayback { + return self.uiWebView ? self.uiWebView.allowsInlineMediaPlayback : self.wkWebView.configuration.allowsInlineMediaPlayback; +} + +- (BOOL)mediaPlaybackRequiresUserAction { + if (self.uiWebView) { + return self.uiWebView.mediaPlaybackRequiresUserAction; + } else { +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + if (![self.wkWebView.configuration respondsToSelector:@selector(requiresUserActionForMediaPlayback)]) { + return self.wkWebView.configuration.mediaPlaybackRequiresUserAction; + } +#endif + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 + return self.wkWebView.configuration.requiresUserActionForMediaPlayback; +#else + return NO; // avoid compiler error under 8.4 SDK +#endif + } +} + +- (BOOL)mediaPlaybackAllowsAirPlay { + if (self.uiWebView) { + return self.uiWebView.mediaPlaybackAllowsAirPlay; + } else { +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 90000 + if (![self.wkWebView.configuration respondsToSelector:@selector(allowsAirPlayForMediaPlayback)]) { + return self.wkWebView.configuration.mediaPlaybackAllowsAirPlay; + } +#endif + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 + return self.wkWebView.configuration.allowsAirPlayForMediaPlayback; +#else + return NO; // avoid compiler error under 8.4 SDK +#endif + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 +- (BOOL)allowsPictureInPictureMediaPlayback { + if (self.uiWebView) { + if ([self.uiWebView respondsToSelector:@selector(allowsPictureInPictureMediaPlayback)]) { + return self.uiWebView.allowsPictureInPictureMediaPlayback; + } + } else { + if ([self.wkWebView.configuration respondsToSelector:@selector(allowsPictureInPictureMediaPlayback)]) { + return self.wkWebView.configuration.allowsPictureInPictureMediaPlayback; + } + } + + return NO; +} +#endif + +#pragma mark - UIWebViewDelegate + +- (BOOL)webView:(UIWebView *)webView +shouldStartLoadWithRequest:(NSURLRequest *)request + navigationType:(UIWebViewNavigationType)navigationType { + if ([self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { + return [self.delegate webView:self + shouldStartLoadWithRequest:request + navigationType:navigationType]; + } + + return YES; +} + +- (void)webViewDidStartLoad:(UIWebView *)webView { + if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { + [self.delegate webViewDidStartLoad:self]; + } +} + +- (void)webViewDidFinishLoad:(UIWebView *)webView { + if ([self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { + [self.delegate webViewDidFinishLoad:self]; + } +} + +- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { + if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + [self.delegate webView:self didFailLoadWithError:error]; + } +} + +#pragma mark - UIWebView+MPAdditions methods + +/// Find all subviews that are UIScrollViews or subclasses and set their scrolling and bounce. +- (void)mp_setScrollable:(BOOL)scrollable { + UIScrollView *scrollView = self.scrollView; + scrollView.scrollEnabled = scrollable; + scrollView.bounces = scrollable; +} + +/// Redefine alert, prompt, and confirm to do nothing +- (void)disableJavaScriptDialogs +{ + if (self.uiWebView) { // Only redefine on UIWebView, as the WKNavigationDelegate for WKWebView takes care of this. + [self stringByEvaluatingJavaScriptFromString:kMoPubJavaScriptDisableDialogScript]; + } +} + +#pragma mark - WKNavigationDelegate + +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { + if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { + [self.delegate webViewDidStartLoad:self]; + } +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + if ([self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { + [self.delegate webViewDidFinishLoad:self]; + } +} + +- (void)webView:(WKWebView *)webView +didFailNavigation:(WKNavigation *)navigation + withError:(NSError *)error { + if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + [self.delegate webView:self didFailLoadWithError:error]; + } +} + +- (void)webView:(WKWebView *)webView +didFailProvisionalNavigation:(WKNavigation *)navigation + withError:(NSError *)error { + if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { + [self.delegate webView:self didFailLoadWithError:error]; + } +} + +- (void)webView:(WKWebView *)webView +decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction +decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + WKNavigationActionPolicy policy = WKNavigationActionPolicyAllow; + + if ([self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { + NSURLRequest *request = navigationAction.request; + UIWebViewNavigationType navType; + switch (navigationAction.navigationType) { + case WKNavigationTypeLinkActivated: + navType = UIWebViewNavigationTypeLinkClicked; + break; + case WKNavigationTypeFormSubmitted: + navType = UIWebViewNavigationTypeFormSubmitted; + break; + case WKNavigationTypeBackForward: + navType = UIWebViewNavigationTypeBackForward; + break; + case WKNavigationTypeReload: + navType = UIWebViewNavigationTypeReload; + break; + case WKNavigationTypeFormResubmitted: + navType = UIWebViewNavigationTypeFormResubmitted; + break; + default: + navType = UIWebViewNavigationTypeOther; + break; + } + + policy = [self.delegate webView:self + shouldStartLoadWithRequest:request + navigationType:navType] ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel; + } + + decisionHandler(policy); +} + +- (WKWebView *)webView:(WKWebView *)webView +createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration +forNavigationAction:(WKNavigationAction *)navigationAction +windowFeatures:(WKWindowFeatures *)windowFeatures { + // Open any links to new windows in the current WKWebView rather than create a new one + if (!navigationAction.targetFrame.isMainFrame) { + [webView loadRequest:navigationAction.request]; + } + + return nil; +} + +#pragma mark - UIScrollViewDelegate + +// Avoid double tap to zoom in WKWebView +// Delegate is only set when scalesPagesToFit is set to NO +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { + return nil; +} + +#pragma mark - WKUIDelegate + +// WKUIDelegate method implementations makes it so that, if a WKWebView is being used, javascript dialog boxes can +// never show. They're programatically dismissed with the "Cancel" option (if there is any such option) before showing +// a view. + +- (void)webView:(WKWebView *)webView +runJavaScriptAlertPanelWithMessage:(NSString *)message +initiatedByFrame:(WKFrameInfo *)frame +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000 // This pre-processor code is to be sure we can compile under both iOS 8 and 9 SDKs +completionHandler:(void (^)())completionHandler { +#else +completionHandler:(void (^)(void))completionHandler { +#endif + completionHandler(); +} + +- (void)webView:(WKWebView *)webView +runJavaScriptConfirmPanelWithMessage:(NSString *)message +initiatedByFrame:(WKFrameInfo *)frame +completionHandler:(void (^)(BOOL))completionHandler { + completionHandler(NO); +} + +- (void)webView:(WKWebView *)webView +runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt + defaultText:(NSString *)defaultText +initiatedByFrame:(WKFrameInfo *)frame +completionHandler:(void (^)(NSString *result))completionHandler { + completionHandler(nil); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.h new file mode 100644 index 000000000..0807ed304 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.h @@ -0,0 +1,69 @@ +// +// MPBaseInterstitialAdapter.h +// MoPub +// +// Created by Nafis Jamal on 4/27/11. +// Copyright 2011 MoPub. All rights reserved. +// + +#import +#import + +@class MPAdConfiguration, CLLocation; + +@protocol MPInterstitialAdapterDelegate; + +@interface MPBaseInterstitialAdapter : NSObject + +@property (nonatomic, weak) id delegate; + +/* + * Creates an adapter with a reference to an MPInterstitialAdManager. + */ +- (id)initWithDelegate:(id)delegate; + +/* + * Sets the adapter's delegate to nil. + */ +- (void)unregisterDelegate; + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration; +- (void)_getAdWithConfiguration:(MPAdConfiguration *)configuration; + +- (void)didStopLoading; + +/* + * Presents the interstitial from the specified view controller. + */ +- (void)showInterstitialFromViewController:(UIViewController *)controller; + +@end + +@interface MPBaseInterstitialAdapter (ProtectedMethods) + +- (void)trackImpression; +- (void)trackClick; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@class MPInterstitialAdController; + +@protocol MPInterstitialAdapterDelegate + +- (MPInterstitialAdController *)interstitialAdController; +- (id)interstitialDelegate; +- (CLLocation *)location; + +- (void)adapterDidFinishLoadingAd:(MPBaseInterstitialAdapter *)adapter; +- (void)adapter:(MPBaseInterstitialAdapter *)adapter didFailToLoadAdWithError:(NSError *)error; +- (void)interstitialWillAppearForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialDidAppearForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialWillDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialDidDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialDidExpireForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialDidReceiveTapEventForAdapter:(MPBaseInterstitialAdapter *)adapter; +- (void)interstitialWillLeaveApplicationForAdapter:(MPBaseInterstitialAdapter *)adapter; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.m new file mode 100644 index 000000000..d31c8fc54 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPBaseInterstitialAdapter.m @@ -0,0 +1,115 @@ +// +// MPBaseInterstitialAdapter.m +// MoPub +// +// Created by Nafis Jamal on 4/27/11. +// Copyright 2011 MoPub. All rights reserved. +// + +#import "MPBaseInterstitialAdapter.h" +#import "MPAdConfiguration.h" +#import "MPGlobal.h" +#import "MPAnalyticsTracker.h" +#import "MPCoreInstanceProvider.h" +#import "MPTimer.h" +#import "MPConstants.h" + +@interface MPBaseInterstitialAdapter () + +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, strong) MPTimer *timeoutTimer; + +- (void)startTimeoutTimer; + +@end + +@implementation MPBaseInterstitialAdapter + +@synthesize delegate = _delegate; +@synthesize configuration = _configuration; +@synthesize timeoutTimer = _timeoutTimer; + +- (id)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + self.delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [self unregisterDelegate]; + + [self.timeoutTimer invalidate]; + +} + +- (void)unregisterDelegate +{ + self.delegate = nil; +} + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration +{ + // To be implemented by subclasses. + [self doesNotRecognizeSelector:_cmd]; +} + +- (void)_getAdWithConfiguration:(MPAdConfiguration *)configuration +{ + self.configuration = configuration; + + [self startTimeoutTimer]; + + MPBaseInterstitialAdapter *strongSelf = self; + [strongSelf getAdWithConfiguration:configuration]; +} + +- (void)startTimeoutTimer +{ + NSTimeInterval timeInterval = (self.configuration && self.configuration.adTimeoutInterval >= 0) ? + self.configuration.adTimeoutInterval : INTERSTITIAL_TIMEOUT_INTERVAL; + + if (timeInterval > 0) { + self.timeoutTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:timeInterval + target:self + selector:@selector(timeout) + repeats:NO]; + + [self.timeoutTimer scheduleNow]; + } +} + +- (void)didStopLoading +{ + [self.timeoutTimer invalidate]; +} + +- (void)timeout +{ + [self.delegate adapter:self didFailToLoadAdWithError:nil]; +} + +#pragma mark - Presentation + +- (void)showInterstitialFromViewController:(UIViewController *)controller +{ + [self doesNotRecognizeSelector:_cmd]; +} + +#pragma mark - Metrics + +- (void)trackImpression +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackImpressionForConfiguration:self.configuration]; +} + +- (void)trackClick +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackClickForConfiguration:self.configuration]; +} + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.h new file mode 100644 index 000000000..1d044fad9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.h @@ -0,0 +1,28 @@ +// +// MPInterstitialAdManager.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPAdServerCommunicator.h" +#import "MPBaseInterstitialAdapter.h" + +@class CLLocation; +@protocol MPInterstitialAdManagerDelegate; + +@interface MPInterstitialAdManager : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign, readonly) BOOL ready; + +- (id)initWithDelegate:(id)delegate; + +- (void)loadInterstitialWithAdUnitID:(NSString *)ID + keywords:(NSString *)keywords + location:(CLLocation *)location + testing:(BOOL)testing; +- (void)presentInterstitialFromViewController:(UIViewController *)controller; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.m new file mode 100644 index 000000000..a3340b6da --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManager.m @@ -0,0 +1,227 @@ +// +// MPInterstitialAdManager.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import + +#import "MPInterstitialAdManager.h" + +#import "MPAdServerURLBuilder.h" +#import "MPInterstitialAdController.h" +#import "MPInterstitialCustomEventAdapter.h" +#import "MPInstanceProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPInterstitialAdManagerDelegate.h" +#import "MPLogging.h" +#import "MPError.h" + +@interface MPInterstitialAdManager () + +@property (nonatomic, assign) BOOL loading; +@property (nonatomic, assign, readwrite) BOOL ready; +@property (nonatomic, strong) MPBaseInterstitialAdapter *adapter; +@property (nonatomic, strong) MPAdServerCommunicator *communicator; +@property (nonatomic, strong) MPAdConfiguration *configuration; + +- (void)setUpAdapterWithConfiguration:(MPAdConfiguration *)configuration; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPInterstitialAdManager + +@synthesize loading = _loading; +@synthesize ready = _ready; +@synthesize delegate = _delegate; +@synthesize communicator = _communicator; +@synthesize adapter = _adapter; +@synthesize configuration = _configuration; + +- (id)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + self.communicator = [[MPCoreInstanceProvider sharedProvider] buildMPAdServerCommunicatorWithDelegate:self]; + self.delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [self.communicator cancel]; + [self.communicator setDelegate:nil]; + + self.adapter = nil; +} + +- (void)setAdapter:(MPBaseInterstitialAdapter *)adapter +{ + if (self.adapter != adapter) { + [self.adapter unregisterDelegate]; + _adapter = adapter; + } +} + +#pragma mark - Public + +- (void)loadAdWithURL:(NSURL *)URL +{ + if (self.loading) { + MPLogWarn(@"Interstitial controller is already loading an ad. " + @"Wait for previous load to finish."); + return; + } + + MPLogInfo(@"Interstitial controller is loading ad with MoPub server URL: %@", URL); + + self.loading = YES; + [self.communicator loadURL:URL]; +} + + +- (void)loadInterstitialWithAdUnitID:(NSString *)ID keywords:(NSString *)keywords location:(CLLocation *)location testing:(BOOL)testing +{ + if (self.ready) { + [self.delegate managerDidLoadInterstitial:self]; + } else { + [self loadAdWithURL:[MPAdServerURLBuilder URLWithAdUnitID:ID + keywords:keywords + location:location + testing:testing]]; + } +} + +- (void)presentInterstitialFromViewController:(UIViewController *)controller +{ + if (self.ready) { + [self.adapter showInterstitialFromViewController:controller]; + } +} + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (MPInterstitialAdController *)interstitialAdController +{ + return [self.delegate interstitialAdController]; +} + +- (id)interstitialDelegate +{ + return [self.delegate interstitialDelegate]; +} + +#pragma mark - MPAdServerCommunicatorDelegate + +- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration +{ + self.configuration = configuration; + + MPLogInfo(@"Interstitial ad view is fetching ad network type: %@", self.configuration.networkType); + + if (self.configuration.adUnitWarmingUp) { + MPLogInfo(kMPWarmingUpErrorLogFormatWithAdUnitID, self.delegate.interstitialAdController.adUnitId); + self.loading = NO; + [self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorAdUnitWarmingUp]]; + return; + } + + if ([self.configuration.networkType isEqualToString:kAdTypeClear]) { + MPLogInfo(kMPClearErrorLogFormatWithAdUnitID, self.delegate.interstitialAdController.adUnitId); + self.loading = NO; + [self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorNoInventory]]; + return; + } + + if (self.configuration.adType != MPAdTypeInterstitial) { + MPLogWarn(@"Could not load ad: interstitial object received a non-interstitial ad unit ID."); + self.loading = NO; + [self.delegate manager:self didFailToLoadInterstitialWithError:[MOPUBError errorWithCode:MOPUBErrorAdapterInvalid]]; + return; + } + + [self setUpAdapterWithConfiguration:self.configuration]; +} + +- (void)communicatorDidFailWithError:(NSError *)error +{ + self.ready = NO; + self.loading = NO; + + [self.delegate manager:self didFailToLoadInterstitialWithError:error]; +} + +- (void)setUpAdapterWithConfiguration:(MPAdConfiguration *)configuration; +{ + MPBaseInterstitialAdapter *adapter = [[MPInstanceProvider sharedProvider] buildInterstitialAdapterForConfiguration:configuration + delegate:self]; + if (!adapter) { + [self adapter:nil didFailToLoadAdWithError:nil]; + return; + } + + self.adapter = adapter; + [self.adapter _getAdWithConfiguration:configuration]; +} + +#pragma mark - MPInterstitialAdapterDelegate + +- (void)adapterDidFinishLoadingAd:(MPBaseInterstitialAdapter *)adapter +{ + self.ready = YES; + self.loading = NO; + [self.delegate managerDidLoadInterstitial:self]; +} + +- (void)adapter:(MPBaseInterstitialAdapter *)adapter didFailToLoadAdWithError:(NSError *)error +{ + self.ready = NO; + self.loading = NO; + [self loadAdWithURL:self.configuration.failoverURL]; +} + +- (void)interstitialWillAppearForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + [self.delegate managerWillPresentInterstitial:self]; +} + +- (void)interstitialDidAppearForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + [self.delegate managerDidPresentInterstitial:self]; +} + +- (void)interstitialWillDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + [self.delegate managerWillDismissInterstitial:self]; +} + +- (void)interstitialDidDisappearForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + self.ready = NO; + [self.delegate managerDidDismissInterstitial:self]; +} + +- (void)interstitialDidExpireForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + self.ready = NO; + [self.delegate managerDidExpireInterstitial:self]; +} + +- (void)interstitialDidReceiveTapEventForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + [self.delegate managerDidReceiveTapEventFromInterstitial:self]; +} + +- (void)interstitialWillLeaveApplicationForAdapter:(MPBaseInterstitialAdapter *)adapter +{ + //noop +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManagerDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManagerDelegate.h new file mode 100644 index 000000000..b06fb1c1d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialAdManagerDelegate.h @@ -0,0 +1,29 @@ +// +// MPInterstitialAdManagerDelegate.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@class MPInterstitialAdManager; +@class MPInterstitialAdController; +@class CLLocation; + +@protocol MPInterstitialAdManagerDelegate + +- (MPInterstitialAdController *)interstitialAdController; +- (CLLocation *)location; +- (id)interstitialDelegate; +- (void)managerDidLoadInterstitial:(MPInterstitialAdManager *)manager; +- (void)manager:(MPInterstitialAdManager *)manager +didFailToLoadInterstitialWithError:(NSError *)error; +- (void)managerWillPresentInterstitial:(MPInterstitialAdManager *)manager; +- (void)managerDidPresentInterstitial:(MPInterstitialAdManager *)manager; +- (void)managerWillDismissInterstitial:(MPInterstitialAdManager *)manager; +- (void)managerDidDismissInterstitial:(MPInterstitialAdManager *)manager; +- (void)managerDidExpireInterstitial:(MPInterstitialAdManager *)manager; +- (void)managerDidReceiveTapEventFromInterstitial:(MPInterstitialAdManager *)manager; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.h new file mode 100644 index 000000000..71534c94a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.h @@ -0,0 +1,14 @@ +// +// MPInterstitialCustomEventAdapter.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPBaseInterstitialAdapter.h" + +#import "MPPrivateInterstitialCustomEventDelegate.h" + +@interface MPInterstitialCustomEventAdapter : MPBaseInterstitialAdapter + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.m new file mode 100644 index 000000000..293f1a279 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialCustomEventAdapter.m @@ -0,0 +1,139 @@ +// +// MPInterstitialCustomEventAdapter.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPInterstitialCustomEventAdapter.h" + +#import "MPAdConfiguration.h" +#import "MPLogging.h" +#import "MPInstanceProvider.h" +#import "MPInterstitialCustomEvent.h" +#import "MPInterstitialAdController.h" + +@interface MPInterstitialCustomEventAdapter () + +@property (nonatomic, strong) MPInterstitialCustomEvent *interstitialCustomEvent; +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, assign) BOOL hasTrackedImpression; +@property (nonatomic, assign) BOOL hasTrackedClick; + +@end + +@implementation MPInterstitialCustomEventAdapter +@synthesize hasTrackedImpression = _hasTrackedImpression; +@synthesize hasTrackedClick = _hasTrackedClick; + +@synthesize interstitialCustomEvent = _interstitialCustomEvent; + +- (void)dealloc +{ + if ([self.interstitialCustomEvent respondsToSelector:@selector(invalidate)]) { + // Secret API to allow us to detach the custom event from (shared instance) routers synchronously + // See the chartboost interstitial custom event for an example use case. + [self.interstitialCustomEvent performSelector:@selector(invalidate)]; + } + self.interstitialCustomEvent.delegate = nil; + + // make sure the custom event isn't released synchronously as objects owned by the custom event + // may do additional work after a callback that results in dealloc being called + [[MPCoreInstanceProvider sharedProvider] keepObjectAliveForCurrentRunLoopIteration:_interstitialCustomEvent]; +} + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration +{ + MPLogInfo(@"Looking for custom event class named %@.", configuration.customEventClass); + self.configuration = configuration; + + self.interstitialCustomEvent = [[MPInstanceProvider sharedProvider] buildInterstitialCustomEventFromCustomClass:configuration.customEventClass delegate:self]; + + if (self.interstitialCustomEvent) { + [self.interstitialCustomEvent requestInterstitialWithCustomEventInfo:configuration.customEventClassData]; + } else { + [self.delegate adapter:self didFailToLoadAdWithError:nil]; + } +} + +- (void)showInterstitialFromViewController:(UIViewController *)controller +{ + [self.interstitialCustomEvent showInterstitialFromRootViewController:controller]; +} + +#pragma mark - MPInterstitialCustomEventDelegate + +- (NSString *)adUnitId +{ + return [self.delegate interstitialAdController].adUnitId; +} + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (id)interstitialDelegate +{ + return [self.delegate interstitialDelegate]; +} + +- (void)interstitialCustomEvent:(MPInterstitialCustomEvent *)customEvent + didLoadAd:(id)ad +{ + [self didStopLoading]; + [self.delegate adapterDidFinishLoadingAd:self]; +} + +- (void)interstitialCustomEvent:(MPInterstitialCustomEvent *)customEvent + didFailToLoadAdWithError:(NSError *)error +{ + [self didStopLoading]; + [self.delegate adapter:self didFailToLoadAdWithError:error]; +} + +- (void)interstitialCustomEventWillAppear:(MPInterstitialCustomEvent *)customEvent +{ + [self.delegate interstitialWillAppearForAdapter:self]; +} + +- (void)interstitialCustomEventDidAppear:(MPInterstitialCustomEvent *)customEvent +{ + if ([self.interstitialCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedImpression) { + self.hasTrackedImpression = YES; + [self trackImpression]; + } + [self.delegate interstitialDidAppearForAdapter:self]; +} + +- (void)interstitialCustomEventWillDisappear:(MPInterstitialCustomEvent *)customEvent +{ + [self.delegate interstitialWillDisappearForAdapter:self]; +} + +- (void)interstitialCustomEventDidDisappear:(MPInterstitialCustomEvent *)customEvent +{ + [self.delegate interstitialDidDisappearForAdapter:self]; +} + +- (void)interstitialCustomEventDidExpire:(MPInterstitialCustomEvent *)customEvent +{ + [self.delegate interstitialDidExpireForAdapter:self]; +} + +- (void)interstitialCustomEventDidReceiveTapEvent:(MPInterstitialCustomEvent *)customEvent +{ + if ([self.interstitialCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedClick) { + self.hasTrackedClick = YES; + [self trackClick]; + } + + [self.delegate interstitialDidReceiveTapEventForAdapter:self]; +} + +- (void)interstitialCustomEventWillLeaveApplication:(MPInterstitialCustomEvent *)customEvent +{ + [self.delegate interstitialWillLeaveApplicationForAdapter:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.h new file mode 100644 index 000000000..c91e3b1ef --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.h @@ -0,0 +1,53 @@ +// +// MPInterstitialViewController.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import "MPGlobal.h" + +@class CLLocation; + +@protocol MPInterstitialViewControllerDelegate; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPInterstitialViewController : UIViewController + +@property (nonatomic, assign) MPInterstitialCloseButtonStyle closeButtonStyle; +@property (nonatomic, assign) MPInterstitialOrientationType orientationType; +@property (nonatomic, strong) UIButton *closeButton; +@property (nonatomic, weak) id delegate; + +- (void)presentInterstitialFromViewController:(UIViewController *)controller; +- (void)dismissInterstitialAnimated:(BOOL)animated; +- (BOOL)shouldDisplayCloseButton; +- (void)willPresentInterstitial; +- (void)didPresentInterstitial; +- (void)willDismissInterstitial; +- (void)didDismissInterstitial; +- (void)layoutCloseButton; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPInterstitialViewControllerDelegate + +- (NSString *)adUnitId; +- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial; +- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial; +- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial; +- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial; +- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial; +- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial; +- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial; +- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial; + +@optional +- (CLLocation *)location; +- (void)interstitialRewardedVideoEnded; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.m new file mode 100644 index 000000000..d3f8dcbd2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPInterstitialViewController.m @@ -0,0 +1,272 @@ +// +// MPInterstitialViewController.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPInterstitialViewController.h" + +#import "MPGlobal.h" +#import "MPLogging.h" +#import "UIButton+MPAdditions.h" + +static const CGFloat kCloseButtonPadding = 5.0; +static const CGFloat kCloseButtonEdgeInset = 5.0; +static NSString * const kCloseButtonXImageName = @"MPCloseButtonX.png"; + +@interface MPInterstitialViewController () + +@property (nonatomic, assign) BOOL applicationHasStatusBar; + +- (void)setCloseButtonImageWithImageNamed:(NSString *)imageName; +- (void)setCloseButtonStyle:(MPInterstitialCloseButtonStyle)style; +- (void)closeButtonPressed; +- (void)dismissInterstitialAnimated:(BOOL)animated; +- (void)setApplicationStatusBarHidden:(BOOL)hidden; + +@end + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPInterstitialViewController + +@synthesize closeButton = _closeButton; +@synthesize closeButtonStyle = _closeButtonStyle; +@synthesize orientationType = _orientationType; +@synthesize applicationHasStatusBar = _applicationHasStatusBar; +@synthesize delegate = _delegate; + + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = [UIColor blackColor]; +} + +#pragma mark - Public + +- (void)presentInterstitialFromViewController:(UIViewController *)controller +{ + if (self.presentingViewController) { + MPLogWarn(@"Cannot present an interstitial that is already on-screen."); + return; + } + + [self willPresentInterstitial]; + + self.applicationHasStatusBar = !([UIApplication sharedApplication].isStatusBarHidden); + [self setApplicationStatusBarHidden:YES]; + + [self layoutCloseButton]; + + [controller presentViewController:self animated:MP_ANIMATED completion:^{ + [self didPresentInterstitial]; + }]; +} + +- (void)willPresentInterstitial +{ + +} + +- (void)didPresentInterstitial +{ + +} + +- (void)willDismissInterstitial +{ + +} + +- (void)didDismissInterstitial +{ + +} + +- (BOOL)shouldDisplayCloseButton +{ + return YES; +} + +#pragma mark - Close Button + +- (UIButton *)closeButton +{ + if (!_closeButton) { + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _closeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleBottomMargin; + + UIImage *closeButtonImage = [UIImage imageNamed:MPResourcePathForResource(kCloseButtonXImageName)]; + [_closeButton setImage:closeButtonImage forState:UIControlStateNormal]; + [_closeButton sizeToFit]; + + [_closeButton addTarget:self + action:@selector(closeButtonPressed) + forControlEvents:UIControlEventTouchUpInside]; + _closeButton.accessibilityLabel = @"Close Interstitial Ad"; + } + + return _closeButton; +} + +- (void)layoutCloseButton +{ + CGFloat originX = self.view.bounds.size.width - kCloseButtonPadding - + self.closeButton.bounds.size.width; + self.closeButton.frame = CGRectMake(originX, + kCloseButtonPadding, + self.closeButton.bounds.size.width, + self.closeButton.bounds.size.height); + self.closeButton.mp_TouchAreaInsets = UIEdgeInsetsMake(kCloseButtonEdgeInset, kCloseButtonEdgeInset, kCloseButtonEdgeInset, kCloseButtonEdgeInset); + [self setCloseButtonStyle:self.closeButtonStyle]; + [self.view addSubview:self.closeButton]; + [self.view bringSubviewToFront:self.closeButton]; +} + +- (void)setCloseButtonImageWithImageNamed:(NSString *)imageName +{ + UIImage *image = [UIImage imageNamed:imageName]; + [self.closeButton setImage:image forState:UIControlStateNormal]; + [self.closeButton sizeToFit]; +} + +- (void)setCloseButtonStyle:(MPInterstitialCloseButtonStyle)style +{ + _closeButtonStyle = style; + switch (style) { + case MPInterstitialCloseButtonStyleAlwaysVisible: + self.closeButton.hidden = NO; + break; + case MPInterstitialCloseButtonStyleAlwaysHidden: + self.closeButton.hidden = YES; + break; + case MPInterstitialCloseButtonStyleAdControlled: + self.closeButton.hidden = ![self shouldDisplayCloseButton]; + break; + default: + self.closeButton.hidden = NO; + break; + } +} + +- (void)closeButtonPressed +{ + [self dismissInterstitialAnimated:YES]; +} + +- (void)dismissInterstitialAnimated:(BOOL)animated +{ + [self setApplicationStatusBarHidden:!self.applicationHasStatusBar]; + + [self willDismissInterstitial]; + + UIViewController *presentingViewController = self.presentingViewController; + // TODO: Is this check necessary? + if (presentingViewController.presentedViewController == self) { + [presentingViewController dismissViewControllerAnimated:MP_ANIMATED completion:^{ + [self didDismissInterstitial]; + }]; + } else { + [self didDismissInterstitial]; + } +} + +#pragma mark - Hidding status bar (pre-iOS 7) + +- (void)setApplicationStatusBarHidden:(BOOL)hidden +{ + [[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:hidden]; +} + +#pragma mark - Hidding status bar (iOS 7 and above) + +- (BOOL)prefersStatusBarHidden +{ + return YES; +} + +#pragma mark - Autorotation (iOS 6.0 and above) + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 +- (BOOL)shouldAutorotate +{ + return YES; +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_9_0 +- (UIInterfaceOrientationMask)supportedInterfaceOrientations +#else +- (NSUInteger)supportedInterfaceOrientations +#endif +{ + NSUInteger applicationSupportedOrientations = + [[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:MPKeyWindow()]; + NSUInteger interstitialSupportedOrientations = applicationSupportedOrientations; + NSString *orientationDescription = @"any"; + + // Using the _orientationType, narrow down the supported interface orientations. + + if (_orientationType == MPInterstitialOrientationTypePortrait) { + interstitialSupportedOrientations &= + (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown); + orientationDescription = @"portrait"; + } else if (_orientationType == MPInterstitialOrientationTypeLandscape) { + interstitialSupportedOrientations &= UIInterfaceOrientationMaskLandscape; + orientationDescription = @"landscape"; + } + + // If the application does not support any of the orientations given by _orientationType, + // just return the application's supported orientations. + + if (!interstitialSupportedOrientations) { + MPLogError(@"Your application does not support this interstitial's desired orientation " + @"(%@).", orientationDescription); + return applicationSupportedOrientations; + } else { + return interstitialSupportedOrientations; + } +} + +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation +{ + NSUInteger supportedInterfaceOrientations = [self supportedInterfaceOrientations]; + UIInterfaceOrientation currentInterfaceOrientation = MPInterfaceOrientation(); + NSUInteger currentInterfaceOrientationMask = (1 << currentInterfaceOrientation); + + // First, try to display the interstitial using the current interface orientation. If the + // current interface orientation is unsupported, just use any of the supported orientations. + + if (supportedInterfaceOrientations & currentInterfaceOrientationMask) { + return currentInterfaceOrientation; + } else if (supportedInterfaceOrientations & UIInterfaceOrientationMaskPortrait) { + return UIInterfaceOrientationPortrait; + } else if (supportedInterfaceOrientations & UIInterfaceOrientationMaskPortraitUpsideDown) { + return UIInterfaceOrientationPortraitUpsideDown; + } else if (supportedInterfaceOrientations & UIInterfaceOrientationMaskLandscapeLeft) { + return UIInterfaceOrientationLandscapeLeft; + } else { + return UIInterfaceOrientationLandscapeRight; + } +} +#endif + +#pragma mark - Autorotation (before iOS 6.0) + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + if (_orientationType == MPInterstitialOrientationTypePortrait) { + return (interfaceOrientation == UIInterfaceOrientationPortrait || + interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown); + } else if (_orientationType == MPInterstitialOrientationTypeLandscape) { + return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || + interfaceOrientation == UIInterfaceOrientationLandscapeRight); + } else { + return YES; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPPrivateInterstitialCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPPrivateInterstitialCustomEventDelegate.h new file mode 100644 index 000000000..cb12c1d27 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Interstitials/MPPrivateInterstitialCustomEventDelegate.h @@ -0,0 +1,20 @@ +// +// MPPrivateInterstitialcustomEventDelegate.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPInterstitialCustomEventDelegate.h" + +@class MPAdConfiguration; +@class CLLocation; + +@protocol MPPrivateInterstitialCustomEventDelegate + +- (NSString *)adUnitId; +- (MPAdConfiguration *)configuration; +- (id)interstitialDelegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.h new file mode 100644 index 000000000..3d6af00e9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.h @@ -0,0 +1,78 @@ +// +// MPCoreInstanceProvider.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MPGlobal.h" +#import "MPURLResolver.h" + +@class MPAdConfiguration; + +// Fetching Ads +@class MPAdServerCommunicator; +@protocol MPAdServerCommunicatorDelegate; + +// URL Handling +@class MPAdDestinationDisplayAgent; +@protocol MPAdDestinationDisplayAgentDelegate; + +// Utilities +@class MPAdAlertManager, MPAdAlertGestureRecognizer; +@class MPAnalyticsTracker; +@class MPReachability; +@class MPTimer; +@class MPGeolocationProvider; +@class CLLocationManager; +@class MPLogEventRecorder; +@class MPNetworkManager; + +typedef id(^MPSingletonProviderBlock)(); + + +typedef NS_OPTIONS(NSUInteger, MPATSSetting) { + MPATSSettingEnabled = 0, + MPATSSettingAllowsArbitraryLoads = (1 << 0), + MPATSSettingAllowsArbitraryLoadsForMedia = (1 << 1), + MPATSSettingAllowsArbitraryLoadsInWebContent = (1 << 2), + MPATSSettingRequiresCertificateTransparency = (1 << 3), + MPATSSettingAllowsLocalNetworking = (1 << 4), +}; + +@interface MPCoreInstanceProvider : NSObject + ++ (instancetype)sharedProvider; +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider; + +- (void)keepObjectAliveForCurrentRunLoopIteration:(id)anObject; + +#pragma mark - Fetching Ads +- (NSMutableURLRequest *)buildConfiguredURLRequestWithURL:(NSURL *)URL; +- (MPAdServerCommunicator *)buildMPAdServerCommunicatorWithDelegate:(id)delegate; + +#pragma mark - URL Handling +- (MPURLResolver *)buildMPURLResolverWithURL:(NSURL *)URL completion:(MPURLResolverCompletionBlock)completion; +- (MPAdDestinationDisplayAgent *)buildMPAdDestinationDisplayAgentWithDelegate:(id)delegate; + +#pragma mark - Utilities +- (UIDevice *)sharedCurrentDevice; +- (MPGeolocationProvider *)sharedMPGeolocationProvider; +- (CLLocationManager *)buildCLLocationManager; +- (id)buildMPAdAlertManagerWithDelegate:(id)delegate; +- (MPAdAlertGestureRecognizer *)buildMPAdAlertGestureRecognizerWithTarget:(id)target action:(SEL)action; +- (NSOperationQueue *)sharedOperationQueue; +- (MPAnalyticsTracker *)sharedMPAnalyticsTracker; +- (MPReachability *)sharedMPReachability; +- (MPLogEventRecorder *)sharedLogEventRecorder; +- (MPNetworkManager *)sharedNetworkManager; +- (MPATSSetting)appTransportSecuritySettings; + +// This call may return nil and may not update if the user hot-swaps the device's sim card. +- (NSDictionary *)sharedCarrierInfo; + +- (MPTimer *)buildMPTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)selector repeats:(BOOL)repeats; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.m new file mode 100644 index 000000000..3db8b09e4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPCoreInstanceProvider.m @@ -0,0 +1,333 @@ +// +// MPCoreInstanceProvider.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPCoreInstanceProvider.h" + +#import +#import + +#import "MPAdServerCommunicator.h" +#import "MPURLResolver.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPReachability.h" +#import "MPTimer.h" +#import "MPAnalyticsTracker.h" +#import "MPGeolocationProvider.h" +#import "MPLogEventRecorder.h" +#import "MPNetworkManager.h" + +#define MOPUB_CARRIER_INFO_DEFAULTS_KEY @"com.mopub.carrierinfo" + +#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) +#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) + +static NSString *const kMoPubAppTransportSecurityDictionaryKey = @"NSAppTransportSecurity"; +static NSString *const kMoPubAppTransportSecurityAllowsArbitraryLoadsKey = @"NSAllowsArbitraryLoads"; +static NSString *const kMoPubAppTransportSecurityAllowsArbitraryLoadsForMediaKey = @"NSAllowsArbitraryLoadsForMedia"; +static NSString *const kMoPubAppTransportSecurityAllowsArbitraryLoadsInWebContentKey = @"NSAllowsArbitraryLoadsInWebContent"; +static NSString *const kMoPubAppTransportSecurityRequiresCertificateTransparencyKey = @"NSRequiresCertificateTransparency"; +static NSString *const kMoPubAppTransportSecurityAllowsLocalNetworkingKey = @"NSAllowsLocalNetworking"; + +typedef enum +{ + MPTwitterDeepLinkNotChecked, + MPTwitterDeepLinkEnabled, + MPTwitterDeepLinkDisabled +} MPTwitterDeepLink; + +@interface MPCoreInstanceProvider () + +@property (nonatomic, copy) NSString *userAgent; +@property (nonatomic, strong) NSMutableDictionary *singletons; +@property (nonatomic, strong) NSMutableDictionary *carrierInfo; +@property (nonatomic, assign) MPTwitterDeepLink twitterDeepLinkStatus; + +@end + +@implementation MPCoreInstanceProvider + +@synthesize userAgent = _userAgent; +@synthesize singletons = _singletons; +@synthesize carrierInfo = _carrierInfo; +@synthesize twitterDeepLinkStatus = _twitterDeepLinkStatus; + +static MPCoreInstanceProvider *sharedProvider = nil; + ++ (instancetype)sharedProvider +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + sharedProvider = [[self alloc] init]; + }); + + return sharedProvider; +} + +- (id)init +{ + self = [super init]; + if (self) { + self.singletons = [NSMutableDictionary dictionary]; + + [self initializeCarrierInfo]; + } + return self; +} + + +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider +{ + id singleton = [self.singletons objectForKey:klass]; + if (!singleton) { + singleton = provider(); + [self.singletons setObject:singleton forKey:(id)klass]; + } + return singleton; +} + +// This method ensures that "anObject" is retained until the next runloop iteration when +// performNoOp: is executed. +// +// This is useful in situations where, potentially due to a callback chain reaction, an object +// is synchronously deallocated as it's trying to do more work, especially invoking self, after +// the callback. +- (void)keepObjectAliveForCurrentRunLoopIteration:(id)anObject +{ + [self performSelector:@selector(performNoOp:) withObject:anObject afterDelay:0]; +} + +- (void)performNoOp:(id)anObject +{ + ; // noop +} + +#pragma mark - Initializing Carrier Info + +- (void)initializeCarrierInfo +{ + self.carrierInfo = [NSMutableDictionary dictionary]; + + // check if we have a saved copy + NSDictionary *saved = [[NSUserDefaults standardUserDefaults] dictionaryForKey:MOPUB_CARRIER_INFO_DEFAULTS_KEY]; + if (saved != nil) { + [self.carrierInfo addEntriesFromDictionary:saved]; + } + + // now asynchronously load a fresh copy + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init]; + [self performSelectorOnMainThread:@selector(updateCarrierInfoForCTCarrier:) withObject:networkInfo.subscriberCellularProvider waitUntilDone:NO]; + }); +} + +- (void)updateCarrierInfoForCTCarrier:(CTCarrier *)ctCarrier +{ + // use setValue instead of setObject here because ctCarrier could be nil, and any of its properties could be nil + [self.carrierInfo setValue:ctCarrier.carrierName forKey:@"carrierName"]; + [self.carrierInfo setValue:ctCarrier.isoCountryCode forKey:@"isoCountryCode"]; + [self.carrierInfo setValue:ctCarrier.mobileCountryCode forKey:@"mobileCountryCode"]; + [self.carrierInfo setValue:ctCarrier.mobileNetworkCode forKey:@"mobileNetworkCode"]; + + [[NSUserDefaults standardUserDefaults] setObject:self.carrierInfo forKey:MOPUB_CARRIER_INFO_DEFAULTS_KEY]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +#pragma mark - Fetching Ads +- (NSMutableURLRequest *)buildConfiguredURLRequestWithURL:(NSURL *)URL +{ + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + [request setHTTPShouldHandleCookies:YES]; + [request setValue:self.userAgent forHTTPHeaderField:@"User-Agent"]; + return request; +} + +- (NSString *)userAgent +{ + if (!_userAgent) { + self.userAgent = [[[UIWebView alloc] init] stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; + } + + return _userAgent; +} + +- (MPAdServerCommunicator *)buildMPAdServerCommunicatorWithDelegate:(id)delegate +{ + return [(MPAdServerCommunicator *)[MPAdServerCommunicator alloc] initWithDelegate:delegate]; +} + + +#pragma mark - URL Handling + +- (MPURLResolver *)buildMPURLResolverWithURL:(NSURL *)URL completion:(MPURLResolverCompletionBlock)completion; +{ + return [MPURLResolver resolverWithURL:URL completion:completion]; +} + +- (MPAdDestinationDisplayAgent *)buildMPAdDestinationDisplayAgentWithDelegate:(id)delegate +{ + return [MPAdDestinationDisplayAgent agentWithDelegate:delegate]; +} + +#pragma mark - Utilities + +- (UIDevice *)sharedCurrentDevice +{ + return [UIDevice currentDevice]; +} + +- (MPGeolocationProvider *)sharedMPGeolocationProvider +{ + return [self singletonForClass:[MPGeolocationProvider class] provider:^id{ + return [MPGeolocationProvider sharedProvider]; + }]; +} + +- (CLLocationManager *)buildCLLocationManager +{ + return [[CLLocationManager alloc] init]; +} + +- (id)buildMPAdAlertManagerWithDelegate:(id)delegate +{ + id adAlertManager = nil; + + Class adAlertManagerClass = NSClassFromString(@"MPAdAlertManager"); + if (adAlertManagerClass != nil) { + adAlertManager = [[adAlertManagerClass alloc] init]; + [adAlertManager performSelector:@selector(setDelegate:) withObject:delegate]; + } + + return adAlertManager; +} + +- (MPAdAlertGestureRecognizer *)buildMPAdAlertGestureRecognizerWithTarget:(id)target action:(SEL)action +{ + MPAdAlertGestureRecognizer *gestureRecognizer = nil; + + Class gestureRecognizerClass = NSClassFromString(@"MPAdAlertGestureRecognizer"); + if (gestureRecognizerClass != nil) { + gestureRecognizer = [[gestureRecognizerClass alloc] initWithTarget:target action:action]; + } + + return gestureRecognizer; +} + +- (NSOperationQueue *)sharedOperationQueue +{ + static NSOperationQueue *sharedOperationQueue = nil; + static dispatch_once_t pred; + + dispatch_once(&pred, ^{ + sharedOperationQueue = [[NSOperationQueue alloc] init]; + }); + + return sharedOperationQueue; +} + +- (MPAnalyticsTracker *)sharedMPAnalyticsTracker +{ + return [self singletonForClass:[MPAnalyticsTracker class] provider:^id{ + return [MPAnalyticsTracker tracker]; + }]; +} + +- (MPReachability *)sharedMPReachability +{ + return [self singletonForClass:[MPReachability class] provider:^id{ + return [MPReachability reachabilityForLocalWiFi]; + }]; +} + +- (MPLogEventRecorder *)sharedLogEventRecorder +{ + return [self singletonForClass:[MPLogEventRecorder class] provider:^id{ + MPLogEventRecorder *recorder = [[MPLogEventRecorder alloc] init]; + return recorder; + }]; +} + +- (MPNetworkManager *)sharedNetworkManager +{ + return [self singletonForClass:[MPNetworkManager class] provider:^id{ + return [MPNetworkManager sharedNetworkManager]; + }]; +} + +- (MPATSSetting)appTransportSecuritySettings +{ + // Keep track of ATS settings statically, as they'll never change in the lifecycle of the application. + // This way, the setting value only gets assembled once. + static BOOL gCheckedAppTransportSettings = NO; + static MPATSSetting gSetting = MPATSSettingEnabled; + + // If we've already checked ATS settings, just use what we have + if (gCheckedAppTransportSettings) { + return gSetting; + } + + // Otherwise, figure out ATS settings + + // App Transport Security was introduced in iOS 9; if the system version is less than 9, then arbirtrary loads are fine. + if (SYSTEM_VERSION_LESS_THAN(@"9.0")) { + gSetting = MPATSSettingAllowsArbitraryLoads; + gCheckedAppTransportSettings = YES; + return gSetting; + } + + // Start with the assumption that ATS is enabled + gSetting = MPATSSettingEnabled; + + // Grab the ATS dictionary from the Info.plist + NSDictionary *atsSettingsDictionary = [NSBundle mainBundle].infoDictionary[kMoPubAppTransportSecurityDictionaryKey]; + + // Check if ATS is entirely disabled, and if so, add that to the setting value + if ([atsSettingsDictionary[kMoPubAppTransportSecurityAllowsArbitraryLoadsKey] boolValue]) { + gSetting |= MPATSSettingAllowsArbitraryLoads; + } + + // New App Transport Security keys were introduced in iOS 10. Only send settings for these keys if we're running iOS 10 or greater. + // They may exist in the dictionary if we're running iOS 9, but they won't do anything, so the server shouldn't know about them. + if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) { + // In iOS 10, NSAllowsArbitraryLoads gets ignored if ANY keys of NSAllowsArbitraryLoadsForMedia, + // NSAllowsArbitraryLoadsInWebContent, or NSAllowsLocalNetworking are PRESENT (i.e., they can be set to `false`) + // See: https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW34 + // If needed, flip NSAllowsArbitraryLoads back to 0 if any of these keys are present. + if (atsSettingsDictionary[kMoPubAppTransportSecurityAllowsArbitraryLoadsForMediaKey] != nil + || atsSettingsDictionary[kMoPubAppTransportSecurityAllowsArbitraryLoadsInWebContentKey] != nil + || atsSettingsDictionary[kMoPubAppTransportSecurityAllowsLocalNetworkingKey] != nil) { + gSetting &= (~MPATSSettingAllowsArbitraryLoads); + } + + if ([atsSettingsDictionary[kMoPubAppTransportSecurityAllowsArbitraryLoadsForMediaKey] boolValue]) { + gSetting |= MPATSSettingAllowsArbitraryLoadsForMedia; + } + if ([atsSettingsDictionary[kMoPubAppTransportSecurityAllowsArbitraryLoadsInWebContentKey] boolValue]) { + gSetting |= MPATSSettingAllowsArbitraryLoadsInWebContent; + } + if ([atsSettingsDictionary[kMoPubAppTransportSecurityRequiresCertificateTransparencyKey] boolValue]) { + gSetting |= MPATSSettingRequiresCertificateTransparency; + } + if ([atsSettingsDictionary[kMoPubAppTransportSecurityAllowsLocalNetworkingKey] boolValue]) { + gSetting |= MPATSSettingAllowsLocalNetworking; + } + } + + gCheckedAppTransportSettings = YES; + return gSetting; +} + +- (NSDictionary *)sharedCarrierInfo +{ + return self.carrierInfo; +} + +- (MPTimer *)buildMPTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)selector repeats:(BOOL)repeats +{ + return [MPTimer timerWithTimeInterval:seconds target:target selector:selector repeats:repeats]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.h new file mode 100644 index 000000000..3b0b7c4d9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.h @@ -0,0 +1,124 @@ +// +// MPInstanceProvider.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPGlobal.h" +#import "MPCoreInstanceProvider.h" + +// MPWebView +@class MPWebView; +@protocol MPWebViewDelegate; + +// Banners +@class MPBannerAdManager; +@protocol MPBannerAdManagerDelegate; +@class MPBaseBannerAdapter; +@protocol MPBannerAdapterDelegate; +@class MPBannerCustomEvent; +@protocol MPBannerCustomEventDelegate; + +// Interstitials +@class MPInterstitialAdManager; +@protocol MPInterstitialAdManagerDelegate; +@class MPBaseInterstitialAdapter; +@protocol MPInterstitialAdapterDelegate; +@class MPInterstitialCustomEvent; +@protocol MPInterstitialCustomEventDelegate; +@class MPHTMLInterstitialViewController; +@class MPMRAIDInterstitialViewController; +@protocol MPInterstitialViewControllerDelegate; + +// Rewarded Video +@class MPRewardedVideoAdManager; +@class MPRewardedVideoAdapter; +@class MPRewardedVideoCustomEvent; +@protocol MPRewardedVideoAdapterDelegate; +@protocol MPRewardedVideoCustomEventDelegate; +@protocol MPRewardedVideoAdManagerDelegate; + +// HTML Ads +@class MPAdWebViewAgent; +@protocol MPAdWebViewAgentDelegate; + +// MRAID +@class MRController; +@protocol MRControllerDelegate; +@class MPClosableView; +@class MRBridge; +@protocol MRBridgeDelegate; +@protocol MPClosableViewDelegate; +@class MRBundleManager; +@class MRVideoPlayerManager; +@protocol MRVideoPlayerManagerDelegate; +@class MPMoviePlayerViewController; +@class MRNativeCommandHandler; +@protocol MRNativeCommandHandlerDelegate; + +//Native +@protocol MPNativeCustomEventDelegate; +@class MPNativeCustomEvent; +@class MPNativeAdSource; +@protocol MPNativeAdSourceDelegate; +@class MPNativePositionSource; +@class MPStreamAdPlacementData; +@class MPStreamAdPlacer; +@class MPAdPositioning; +@protocol MPNativeAdRenderer; + +@interface MPInstanceProvider : NSObject + ++(instancetype)sharedProvider; +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider; +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider context:(id)context; + +#pragma mark - Banners +- (MPBannerAdManager *)buildMPBannerAdManagerWithDelegate:(id)delegate; +- (MPBaseBannerAdapter *)buildBannerAdapterForConfiguration:(MPAdConfiguration *)configuration + delegate:(id)delegate; +- (MPBannerCustomEvent *)buildBannerCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate; + +#pragma mark - Interstitials +- (MPInterstitialAdManager *)buildMPInterstitialAdManagerWithDelegate:(id)delegate; +- (MPBaseInterstitialAdapter *)buildInterstitialAdapterForConfiguration:(MPAdConfiguration *)configuration + delegate:(id)delegate; +- (MPInterstitialCustomEvent *)buildInterstitialCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate; +- (MPHTMLInterstitialViewController *)buildMPHTMLInterstitialViewControllerWithDelegate:(id)delegate + orientationType:(MPInterstitialOrientationType)type; +- (MPMRAIDInterstitialViewController *)buildMPMRAIDInterstitialViewControllerWithDelegate:(id)delegate + configuration:(MPAdConfiguration *)configuration; + +#pragma mark - Rewarded Video +- (MPRewardedVideoAdManager *)buildRewardedVideoAdManagerWithAdUnitID:(NSString *)adUnitID delegate:(id)delegate; +- (MPRewardedVideoAdapter *)buildRewardedVideoAdapterWithDelegate:(id)delegate; +- (MPRewardedVideoCustomEvent *)buildRewardedVideoCustomEventFromCustomClass:(Class)customClass delegate:(id)delegate; + + +#pragma mark - HTML Ads +- (MPAdWebViewAgent *)buildMPAdWebViewAgentWithAdWebViewFrame:(CGRect)frame + delegate:(id)delegate; + +#pragma mark - MRAID +- (MPClosableView *)buildMRAIDMPClosableViewWithFrame:(CGRect)frame webView:(MPWebView *)webView delegate:(id)delegate; +- (MRBundleManager *)buildMRBundleManager; +- (MRController *)buildBannerMRControllerWithFrame:(CGRect)frame delegate:(id)delegate; +- (MRController *)buildInterstitialMRControllerWithFrame:(CGRect)frame delegate:(id)delegate; +- (MRBridge *)buildMRBridgeWithWebView:(MPWebView *)webView delegate:(id)delegate; +- (MRVideoPlayerManager *)buildMRVideoPlayerManagerWithDelegate:(id)delegate; +- (MPMoviePlayerViewController *)buildMPMoviePlayerViewControllerWithURL:(NSURL *)URL; +- (MRNativeCommandHandler *)buildMRNativeCommandHandlerWithDelegate:(id)delegate; + +#pragma mark - Native + +- (MPNativeCustomEvent *)buildNativeCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate; +- (MPNativeAdSource *)buildNativeAdSourceWithDelegate:(id)delegate; +- (MPNativePositionSource *)buildNativePositioningSource; +- (MPStreamAdPlacementData *)buildStreamAdPlacementDataWithPositioning:(MPAdPositioning *)positioning; +- (MPStreamAdPlacer *)buildStreamAdPlacerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.m new file mode 100644 index 000000000..763e25f0d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPInstanceProvider.m @@ -0,0 +1,319 @@ +// +// MPInstanceProvider.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPInstanceProvider.h" +#import "MPWebView.h" +#import "MPAdWebViewAgent.h" +#import "MPInterstitialAdManager.h" +#import "MPInterstitialCustomEventAdapter.h" +#import "MPHTMLInterstitialViewController.h" +#import "MPMRAIDInterstitialViewController.h" +#import "MPInterstitialCustomEvent.h" +#import "MPBaseBannerAdapter.h" +#import "MPBannerCustomEventAdapter.h" +#import "MPBannerCustomEvent.h" +#import "MPBannerAdManager.h" +#import "MPLogging.h" +#import "MRBundleManager.h" +#import "MRVideoPlayerManager.h" +#import +#import "MRNativeCommandHandler.h" +#import "MRBridge.h" +#import "MRController.h" +#import "MPClosableView.h" +#import "MPRewardedVideoAdManager.h" +#import "MPRewardedVideoAdapter.h" +#import "MPRewardedVideoCustomEvent.h" + +#if MP_HAS_NATIVE_PACKAGE +#import "MPNativeCustomEvent.h" +#import "MPNativeAdSource.h" +#import "MPNativePositionSource.h" +#import "MPStreamAdPlacementData.h" +#import "MPStreamAdPlacer.h" +#endif + +@interface MPInstanceProvider () + +// A nested dictionary. The top-level dictionary maps Class objects to second-level dictionaries. +// The second level dictionaries map identifiers to singleton objects. +// +// An example: +// { +// SomeClass: +// { +// @"default": +// @"other_context": +// } +// } +// +@property (nonatomic, strong) NSMutableDictionary *singletons; + +@end + + +@implementation MPInstanceProvider + +static MPInstanceProvider *sharedAdProvider = nil; + ++ (instancetype)sharedProvider +{ + static dispatch_once_t once; + dispatch_once(&once, ^{ + sharedAdProvider = [[self alloc] init]; + }); + + return sharedAdProvider; +} + +- (id)init +{ + self = [super init]; + if (self) { + self.singletons = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider +{ + return [self singletonForClass:klass provider:provider context:@"default"]; +} + +- (id)singletonForClass:(Class)klass provider:(MPSingletonProviderBlock)provider context:(id)context +{ + id singleton = [[self.singletons objectForKey:klass] objectForKey:context]; + if (!singleton) { + singleton = provider(); + NSMutableDictionary *singletonsForClass = [self.singletons objectForKey:klass]; + if (!singletonsForClass) { + NSMutableDictionary *singletonsForContext = [NSMutableDictionary dictionaryWithObjectsAndKeys:singleton, context, nil]; + [self.singletons setObject:singletonsForContext forKey:(id)klass]; + } else { + [singletonsForClass setObject:singleton forKey:context]; + } + } + return singleton; +} + +#pragma mark - Banners + +- (MPBannerAdManager *)buildMPBannerAdManagerWithDelegate:(id)delegate +{ + return [(MPBannerAdManager *)[MPBannerAdManager alloc] initWithDelegate:delegate]; +} + +- (MPBaseBannerAdapter *)buildBannerAdapterForConfiguration:(MPAdConfiguration *)configuration + delegate:(id)delegate +{ + if (configuration.customEventClass) { + return [(MPBannerCustomEventAdapter *)[MPBannerCustomEventAdapter alloc] initWithDelegate:delegate]; + } + + return nil; +} + +- (MPBannerCustomEvent *)buildBannerCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate +{ + MPBannerCustomEvent *customEvent = [[customClass alloc] init]; + if (![customEvent isKindOfClass:[MPBannerCustomEvent class]]) { + MPLogError(@"**** Custom Event Class: %@ does not extend MPBannerCustomEvent ****", NSStringFromClass(customClass)); + return nil; + } + customEvent.delegate = delegate; + return customEvent; +} + +#pragma mark - Interstitials + +- (MPInterstitialAdManager *)buildMPInterstitialAdManagerWithDelegate:(id)delegate +{ + return [(MPInterstitialAdManager *)[MPInterstitialAdManager alloc] initWithDelegate:delegate]; +} + + +- (MPBaseInterstitialAdapter *)buildInterstitialAdapterForConfiguration:(MPAdConfiguration *)configuration + delegate:(id)delegate +{ + if (configuration.customEventClass) { + return [(MPInterstitialCustomEventAdapter *)[MPInterstitialCustomEventAdapter alloc] initWithDelegate:delegate]; + } + + return nil; +} + +- (MPInterstitialCustomEvent *)buildInterstitialCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate +{ + MPInterstitialCustomEvent *customEvent = [[customClass alloc] init]; + if (![customEvent isKindOfClass:[MPInterstitialCustomEvent class]]) { + MPLogError(@"**** Custom Event Class: %@ does not extend MPInterstitialCustomEvent ****", NSStringFromClass(customClass)); + return nil; + } + if ([customEvent respondsToSelector:@selector(customEventDidUnload)]) { + MPLogWarn(@"**** Custom Event Class: %@ implements the deprecated -customEventDidUnload method. This is no longer called. Use -dealloc for cleanup instead ****", NSStringFromClass(customClass)); + } + customEvent.delegate = delegate; + return customEvent; +} + +- (MPHTMLInterstitialViewController *)buildMPHTMLInterstitialViewControllerWithDelegate:(id)delegate + orientationType:(MPInterstitialOrientationType)type +{ + MPHTMLInterstitialViewController *controller = [[MPHTMLInterstitialViewController alloc] init]; + controller.delegate = delegate; + controller.orientationType = type; + return controller; +} + +- (MPMRAIDInterstitialViewController *)buildMPMRAIDInterstitialViewControllerWithDelegate:(id)delegate + configuration:(MPAdConfiguration *)configuration +{ + MPMRAIDInterstitialViewController *controller = [[MPMRAIDInterstitialViewController alloc] initWithAdConfiguration:configuration]; + controller.delegate = delegate; + return controller; +} + +#pragma mark - Rewarded Video + +- (MPRewardedVideoAdManager *)buildRewardedVideoAdManagerWithAdUnitID:(NSString *)adUnitID delegate:(id)delegate +{ + return [[MPRewardedVideoAdManager alloc] initWithAdUnitID:adUnitID delegate:delegate]; +} + +- (MPRewardedVideoAdapter *)buildRewardedVideoAdapterWithDelegate:(id)delegate +{ + return [[MPRewardedVideoAdapter alloc] initWithDelegate:delegate]; +} + +- (MPRewardedVideoCustomEvent *)buildRewardedVideoCustomEventFromCustomClass:(Class)customClass delegate:(id)delegate +{ + MPRewardedVideoCustomEvent *customEvent = [[customClass alloc] init]; + + if (![customEvent isKindOfClass:[MPRewardedVideoCustomEvent class]]) { + MPLogError(@"**** Custom Event Class: %@ does not extend MPRewardedVideoCustomEvent ****", NSStringFromClass(customClass)); + return nil; + } + + customEvent.delegate = delegate; + return customEvent; +} + +#pragma mark - HTML Ads + +- (MPAdWebViewAgent *)buildMPAdWebViewAgentWithAdWebViewFrame:(CGRect)frame delegate:(id)delegate +{ + return [[MPAdWebViewAgent alloc] initWithAdWebViewFrame:frame delegate:delegate]; +} + +#pragma mark - MRAID + +- (MPClosableView *)buildMRAIDMPClosableViewWithFrame:(CGRect)frame webView:(MPWebView *)webView delegate:(id)delegate +{ + MPClosableView *adView = [[MPClosableView alloc] initWithFrame:frame closeButtonType:MPClosableViewCloseButtonTypeTappableWithImage]; + adView.delegate = delegate; + adView.clipsToBounds = YES; + webView.frame = adView.bounds; + [adView addSubview:webView]; + return adView; +} + +- (MRBundleManager *)buildMRBundleManager +{ + return [MRBundleManager sharedManager]; +} + +- (MRController *)buildBannerMRControllerWithFrame:(CGRect)frame delegate:(id)delegate +{ + return [self buildMRControllerWithFrame:frame placementType:MRAdViewPlacementTypeInline delegate:delegate]; +} + +- (MRController *)buildInterstitialMRControllerWithFrame:(CGRect)frame delegate:(id)delegate +{ + return [self buildMRControllerWithFrame:frame placementType:MRAdViewPlacementTypeInterstitial delegate:delegate]; +} + +- (MRController *)buildMRControllerWithFrame:(CGRect)frame placementType:(MRAdViewPlacementType)placementType delegate:(id)delegate +{ + MRController *controller = [[MRController alloc] initWithAdViewFrame:frame adPlacementType:placementType]; + controller.delegate = delegate; + return controller; +} + +- (MRBridge *)buildMRBridgeWithWebView:(MPWebView *)webView delegate:(id)delegate +{ + MRBridge *bridge = [[MRBridge alloc] initWithWebView:webView]; + bridge.delegate = delegate; + bridge.shouldHandleRequests = YES; + return bridge; +} + +- (MRVideoPlayerManager *)buildMRVideoPlayerManagerWithDelegate:(id)delegate +{ + return [[MRVideoPlayerManager alloc] initWithDelegate:delegate]; +} + +- (MPMoviePlayerViewController *)buildMPMoviePlayerViewControllerWithURL:(NSURL *)URL +{ + // ImageContext used to avoid CGErrors + // http://stackoverflow.com/questions/13203336/iphone-mpmovieplayerviewcontroller-cgcontext-errors/14669166#14669166 + UIGraphicsBeginImageContext(CGSizeMake(1,1)); + MPMoviePlayerViewController *playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:URL]; + UIGraphicsEndImageContext(); + + return playerViewController; +} + +- (MRNativeCommandHandler *)buildMRNativeCommandHandlerWithDelegate:(id)delegate +{ + return [[MRNativeCommandHandler alloc] initWithDelegate:delegate]; +} + +#pragma mark - Native + +#if MP_HAS_NATIVE_PACKAGE + +- (MPNativeCustomEvent *)buildNativeCustomEventFromCustomClass:(Class)customClass + delegate:(id)delegate +{ + MPNativeCustomEvent *customEvent = [[customClass alloc] init]; + if (![customEvent isKindOfClass:[MPNativeCustomEvent class]]) { + MPLogError(@"**** Custom Event Class: %@ does not extend MPNativeCustomEvent ****", NSStringFromClass(customClass)); + return nil; + } + customEvent.delegate = delegate; + return customEvent; +} + +- (MPNativeAdSource *)buildNativeAdSourceWithDelegate:(id)delegate +{ + MPNativeAdSource *source = [MPNativeAdSource source]; + source.delegate = delegate; + return source; +} + +- (MPNativePositionSource *)buildNativePositioningSource +{ + return [[MPNativePositionSource alloc] init]; +} + +- (MPStreamAdPlacementData *)buildStreamAdPlacementDataWithPositioning:(MPAdPositioning *)positioning +{ + MPStreamAdPlacementData *placementData = [[MPStreamAdPlacementData alloc] initWithPositioning:positioning]; + return placementData; +} + +- (MPStreamAdPlacer *)buildStreamAdPlacerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + return [MPStreamAdPlacer placerWithViewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; +} + +#endif + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.h new file mode 100644 index 000000000..da5056548 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.h @@ -0,0 +1,37 @@ +// +// MPVASTTracking.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MPVideoConfig; + +typedef NS_ENUM(NSUInteger, MPVideoEventType) { + MPVideoEventTypeTimeUpdate = 0, + MPVideoEventTypeMuted, + MPVideoEventTypeUnmuted, + MPVideoEventTypePause, + MPVideoEventTypeResume, + MPVideoEventTypeFullScreen, + MPVideoEventTypeExitFullScreen, + MPVideoEventTypeExpand, + MPVideoEventTypeCollapse, + MPVideoEventTypeCompleted, + MPVideoEventTypeImpression, + MPVideoEventTypeClick, + MPVideoEventTypeError +}; + +@interface MPVASTTracking : NSObject + +@property (nonatomic, readonly) MPVideoConfig *videoConfig; +@property (nonatomic) NSTimeInterval videoDuration; + +- (instancetype)initWithMPVideoConfig:(MPVideoConfig *)videoConfig videoView:(UIView *)videoView; +- (void)handleVideoEvent:(MPVideoEventType)videoEventType videoTimeOffset:(NSTimeInterval)timeOffset; +- (void)handleNewVideoView:(UIView *)videoView; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.m new file mode 100644 index 000000000..e3fa04304 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MPVASTTracking.m @@ -0,0 +1,253 @@ +// +// MPVASTTracking.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoImpressionAgent.h" +#import "MPAnalyticsTracker.h" +#import "MPCoreInstanceProvider.h" +#import "MPLogging.h" +#import "MPVASTMacroProcessor.h" +#import "MPVASTTracking.h" +#import "MPVideoConfig.h" + +// Do not fire the start tracker until this time has been reached in the video +static const NSInteger kStartTrackerTime = 0; + +@interface VASTTrackingURL : NSObject + +@property (nonatomic, copy) NSURL *url; +@property (nonatomic) MPVASTDurationOffset *progressOffset; + +@end + +@implementation VASTTrackingURL + +@end + +@interface VASTEventTracker : NSObject + +@property (nonatomic, assign) BOOL trackersFired; +@property (nonatomic) NSArray *trackingEvents; // NSArray + +@end + +@implementation VASTEventTracker + ++ (VASTEventTracker *)eventTrackerWithMPVastTrackingEvents:(NSArray *)events +{ + VASTEventTracker *result = [[VASTEventTracker alloc] init]; + NSMutableArray *trackingEvents = [NSMutableArray array]; + for (MPVASTTrackingEvent *event in events) { + VASTTrackingURL *tracker = [[VASTTrackingURL alloc] init]; + tracker.url = event.URL; + tracker.progressOffset = event.progressOffset; + [trackingEvents addObject:tracker]; + } + + result.trackingEvents = trackingEvents; + + return result; +} + ++ (VASTEventTracker *)eventTrackerWithURLs:(NSArray *)urls +{ + VASTEventTracker *result = [[VASTEventTracker alloc] init]; + NSMutableArray *trackingEvents = [NSMutableArray array]; + for (NSURL *url in urls) { + VASTTrackingURL *tracker = [[VASTTrackingURL alloc] init]; + tracker.url = url; + tracker.progressOffset = nil; + [trackingEvents addObject:tracker]; + } + + result.trackingEvents = trackingEvents; + + return result; +} + +@end + +@interface MPVASTTracking() + +@property (nonatomic) VASTEventTracker *errorTracker; +@property (nonatomic) VASTEventTracker *impressionTracker; +@property (nonatomic) VASTEventTracker *clickTracker; +@property (nonatomic) VASTEventTracker *customViewabilityTracker; + +@property (nonatomic) VASTEventTracker *startTracker; +@property (nonatomic) VASTEventTracker *firstQuartileTracker; +@property (nonatomic) VASTEventTracker *midPointTracker; +@property (nonatomic) VASTEventTracker *thirdQuartileTracker; +@property (nonatomic) VASTEventTracker *completionTracker; + +@property (nonatomic) NSMutableArray *variableProgressTrackers; //NSMutableArray + +@property (nonatomic) VASTEventTracker *muteTracker; +@property (nonatomic) VASTEventTracker *unmuteTracker; +@property (nonatomic) VASTEventTracker *pauseTracker; +@property (nonatomic) VASTEventTracker *rewindTracker; +@property (nonatomic) VASTEventTracker *resumeTracker; +@property (nonatomic) VASTEventTracker *fullscreenTracker; +@property (nonatomic) VASTEventTracker *exitFullscreenTracker; +@property (nonatomic) VASTEventTracker *expandTracker; +@property (nonatomic) VASTEventTracker *collapseTracker; + +@property (nonatomic) MOPUBNativeVideoImpressionAgent *customViewabilityTrackingAgent; + +@end + +@implementation MPVASTTracking + +- (instancetype)initWithMPVideoConfig:(MPVideoConfig *)videoConfig videoView:(UIView *)videoView; +{ + self = [super init]; + if (self) { + _videoConfig = videoConfig; + _videoDuration = -1; + + _errorTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.errorURLs]; + _impressionTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.impressionURLs]; + _clickTracker = [VASTEventTracker eventTrackerWithURLs:_videoConfig.clickTrackingURLs]; + + _startTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.startTrackers]; + _firstQuartileTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.firstQuartileTrackers]; + _midPointTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.midpointTrackers]; + _thirdQuartileTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.thirdQuartileTrackers]; + _completionTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.completionTrackers]; + + _variableProgressTrackers = [NSMutableArray array]; + for (MPVASTTrackingEvent *event in _videoConfig.otherProgressTrackers) { + [_variableProgressTrackers addObject:[VASTEventTracker eventTrackerWithMPVastTrackingEvents:[NSArray arrayWithObject:event]]]; + } + + _muteTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.muteTrackers]; + _unmuteTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.unmuteTrackers]; + _pauseTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.pauseTrackers]; + _rewindTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.rewindTrackers]; + _resumeTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.resumeTrackers]; + _fullscreenTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.fullscreenTrackers]; + _exitFullscreenTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.exitFullscreenTrackers]; + _expandTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.expandTrackers]; + _collapseTracker = [VASTEventTracker eventTrackerWithMPVastTrackingEvents:_videoConfig.collapseTrackers]; + + if (_videoConfig.viewabilityTrackingURL) { + _customViewabilityTracker = [VASTEventTracker eventTrackerWithURLs:[NSArray arrayWithObject:_videoConfig.viewabilityTrackingURL]]; + _customViewabilityTrackingAgent = [[MOPUBNativeVideoImpressionAgent alloc] initWithVideoView:videoView requiredVisibilityPercentage:videoConfig.minimumFractionOfVideoVisible requiredPlaybackDuration:videoConfig.minimumViewabilityTimeInterval]; + } + } + return self; +} + +- (void)handleVideoEvent:(MPVideoEventType)videoEventType videoTimeOffset:(NSTimeInterval)timeOffset +{ + if (self.videoConfig && (self.videoDuration > 0 || videoEventType == MPVideoEventTypeError)) { + if (videoEventType == MPVideoEventTypeTimeUpdate) { + [self handleProgressTrackers:timeOffset]; + } else { + VASTEventTracker *eventTrackerToFire; + switch (videoEventType) { + case MPVideoEventTypeMuted: + eventTrackerToFire = self.muteTracker; + break; + case MPVideoEventTypeUnmuted: + eventTrackerToFire = self.unmuteTracker; + break; + case MPVideoEventTypePause: + eventTrackerToFire = self.pauseTracker; + break; + case MPVideoEventTypeResume: + eventTrackerToFire = self.resumeTracker; + break; + case MPVideoEventTypeFullScreen: + eventTrackerToFire = self.fullscreenTracker; + break; + case MPVideoEventTypeExitFullScreen: + eventTrackerToFire = self.exitFullscreenTracker; + break; + case MPVideoEventTypeExpand: + eventTrackerToFire = self.expandTracker; + break; + case MPVideoEventTypeCollapse: + eventTrackerToFire = self.collapseTracker; + break; + case MPVideoEventTypeError: + eventTrackerToFire = self.errorTracker; + break; + case MPVideoEventTypeImpression: + if (!self.impressionTracker.trackersFired) { + eventTrackerToFire = self.impressionTracker; + } + break; + case MPVideoEventTypeClick: + if (!self.clickTracker.trackersFired) { + eventTrackerToFire = self.clickTracker; + } + break; + case MPVideoEventTypeCompleted: + if (!self.completionTracker.trackersFired) { + eventTrackerToFire = self.completionTracker; + } + break; + default: + eventTrackerToFire = nil; + } + // Only fire event trackers after the video has started playing + if (eventTrackerToFire && (self.startTracker.trackersFired || videoEventType == MPVideoEventTypeError)) { + [self cleanAndSendTrackingEvents:eventTrackerToFire timeOffset:timeOffset]; + } + } + } +} + +- (void)handleProgressTrackers:(NSTimeInterval)timeOffset +{ + if (timeOffset >= kStartTrackerTime && !self.startTracker.trackersFired) { + [self cleanAndSendTrackingEvents:self.startTracker timeOffset:timeOffset]; + } + + if ((0.75 * self.videoDuration) <= timeOffset && !self.thirdQuartileTracker.trackersFired) { + [self cleanAndSendTrackingEvents:self.thirdQuartileTracker timeOffset:timeOffset]; + } + + if ((0.50 * self.videoDuration) <= timeOffset && !self.midPointTracker.trackersFired) { + [self cleanAndSendTrackingEvents:self.midPointTracker timeOffset:timeOffset]; + } + + if ((0.25 * self.videoDuration) <= timeOffset && !self.firstQuartileTracker.trackersFired) { + [self cleanAndSendTrackingEvents:self.firstQuartileTracker timeOffset:timeOffset]; + } + + for (VASTEventTracker *progressTracker in self.variableProgressTrackers) { + VASTTrackingURL *progressTrackingURL = progressTracker.trackingEvents[0]; // there's only one + if (!progressTracker.trackersFired && [progressTrackingURL.progressOffset timeIntervalForVideoWithDuration:self.videoDuration] <= timeOffset) { + [self cleanAndSendTrackingEvents:progressTracker timeOffset:timeOffset]; + } + } + + if (self.customViewabilityTracker && !self.customViewabilityTracker.trackersFired && + [self.customViewabilityTrackingAgent shouldTrackImpressionWithCurrentPlaybackTime:timeOffset]) { + [self cleanAndSendTrackingEvents:self.customViewabilityTracker timeOffset:timeOffset]; + } +} + +- (void)cleanAndSendTrackingEvents:(VASTEventTracker *)vastEventTracker timeOffset:(NSTimeInterval)timeOffset +{ + if (vastEventTracker && [vastEventTracker.trackingEvents count]) { + NSMutableArray *cleanedTrackingURLs = [NSMutableArray array]; + for (VASTTrackingURL *vastTrackingURL in vastEventTracker.trackingEvents) { + [cleanedTrackingURLs addObject:[MPVASTMacroProcessor macroExpandedURLForURL:vastTrackingURL.url errorCode:nil videoTimeOffset:timeOffset videoAssetURL:self.videoConfig.mediaURL]]; + } + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] sendTrackingRequestForURLs:cleanedTrackingURLs]; + } + vastEventTracker.trackersFired = YES; +} + +- (void)handleNewVideoView:(UIView *)videoView +{ + self.customViewabilityTrackingAgent = [[MOPUBNativeVideoImpressionAgent alloc] initWithVideoView:videoView requiredVisibilityPercentage:self.videoConfig.minimumFractionOfVideoVisible requiredPlaybackDuration:self.videoConfig.minimumViewabilityTimeInterval]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPForceableOrientationProtocol.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPForceableOrientationProtocol.h new file mode 100644 index 000000000..7f56818a0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPForceableOrientationProtocol.h @@ -0,0 +1,18 @@ +// +// MPForceableOrientationProtocol.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPForceableOrientationProtocol + +/** + * An orientation mask that defines the orientations the view controller supports. + * This cannot force a change in orientation though. + */ +- (void)setSupportedOrientationMask:(UIInterfaceOrientationMask)supportedOrientationMask; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.h new file mode 100644 index 000000000..94a031ba0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.h @@ -0,0 +1,18 @@ +// +// MPMRAIDBannerCustomEvent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPBannerCustomEvent.h" +#import "MPPrivateBannerCustomEventDelegate.h" + +@interface MPMRAIDBannerCustomEvent : MPBannerCustomEvent + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-property-synthesis" +@property (nonatomic, weak) id delegate; +#pragma clang diagnostic pop + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.m new file mode 100644 index 000000000..da41a97bc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDBannerCustomEvent.m @@ -0,0 +1,88 @@ +// +// MPMRAIDBannerCustomEvent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPMRAIDBannerCustomEvent.h" +#import "MPLogging.h" +#import "MPAdConfiguration.h" +#import "MPInstanceProvider.h" +#import "MRController.h" + +@interface MPMRAIDBannerCustomEvent () + +@property (nonatomic, strong) MRController *mraidController; + +@end + +@implementation MPMRAIDBannerCustomEvent + +- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info +{ + MPLogInfo(@"Loading MoPub MRAID banner"); + MPAdConfiguration *configuration = [self.delegate configuration]; + + CGRect adViewFrame = CGRectZero; + if ([configuration hasPreferredSize]) { + adViewFrame = CGRectMake(0, 0, configuration.preferredSize.width, + configuration.preferredSize.height); + } + + self.mraidController = [[MPInstanceProvider sharedProvider] buildBannerMRControllerWithFrame:adViewFrame delegate:self]; + [self.mraidController loadAdWithConfiguration:configuration]; +} + +#pragma mark - MRControllerDelegate + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (MPAdConfiguration *)adConfiguration +{ + return [self.delegate configuration]; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)adDidLoad:(UIView *)adView +{ + MPLogInfo(@"MoPub MRAID banner did load"); + [self.delegate bannerCustomEvent:self didLoadAd:adView]; +} + +- (void)adDidFailToLoad:(UIView *)adView +{ + MPLogInfo(@"MoPub MRAID banner did fail"); + [self.delegate bannerCustomEvent:self didFailToLoadAdWithError:nil]; +} + +- (void)closeButtonPressed +{ + //don't care +} + +- (void)appShouldSuspendForAd:(UIView *)adView +{ + MPLogInfo(@"MoPub MRAID banner will begin action"); + [self.delegate bannerCustomEventWillBeginAction:self]; +} + +- (void)appShouldResumeFromAd:(UIView *)adView +{ + MPLogInfo(@"MoPub MRAID banner did end action"); + [self.delegate bannerCustomEventDidFinishAction:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.h new file mode 100644 index 000000000..2c27929b9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.h @@ -0,0 +1,19 @@ +// +// MPMRAIDInterstitialCustomEvent.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPInterstitialCustomEvent.h" +#import "MPMRAIDInterstitialViewController.h" +#import "MPPrivateInterstitialCustomEventDelegate.h" + +@interface MPMRAIDInterstitialCustomEvent : MPInterstitialCustomEvent + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-property-synthesis" +@property (nonatomic, weak) id delegate; +#pragma clang diagnostic pop + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.m new file mode 100644 index 000000000..d41531560 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialCustomEvent.m @@ -0,0 +1,103 @@ +// +// MPMRAIDInterstitialCustomEvent.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPMRAIDInterstitialCustomEvent.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" + +@interface MPMRAIDInterstitialCustomEvent () + +@property (nonatomic, strong) MPMRAIDInterstitialViewController *interstitial; + +@end + +@implementation MPMRAIDInterstitialCustomEvent + +@synthesize interstitial = _interstitial; + +- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info +{ + MPLogInfo(@"Loading MoPub MRAID interstitial"); + self.interstitial = [[MPInstanceProvider sharedProvider] buildMPMRAIDInterstitialViewControllerWithDelegate:self + configuration:[self.delegate configuration]]; + + // The MRAID ad view will handle the close button so we don't need the MPInterstitialViewController's close button. + [self.interstitial setCloseButtonStyle:MPInterstitialCloseButtonStyleAlwaysHidden]; + [self.interstitial startLoading]; +} + +- (void)showInterstitialFromRootViewController:(UIViewController *)controller +{ + [self.interstitial presentInterstitialFromViewController:controller]; +} + +#pragma mark - MPMRAIDInterstitialViewControllerDelegate + +- (CLLocation *)location +{ + return [self.delegate location]; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial did load"); + [self.delegate interstitialCustomEvent:self didLoadAd:self.interstitial]; +} + +- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial did fail"); + [self.delegate interstitialCustomEvent:self didFailToLoadAdWithError:nil]; +} + +- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial will appear"); + [self.delegate interstitialCustomEventWillAppear:self]; +} + +- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial did appear"); + [self.delegate interstitialCustomEventDidAppear:self]; +} + +- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial will disappear"); + [self.delegate interstitialCustomEventWillDisappear:self]; +} + +- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial did disappear"); + [self.delegate interstitialCustomEventDidDisappear:self]; + + // Deallocate the interstitial as we don't need it anymore. If we don't deallocate the interstitial after dismissal, + // then the html in the webview will continue to run which could lead to bugs such as continuing to play the sound of an inline + // video since the app may hold onto the interstitial ad controller. Moreover, we keep an array of controllers around as well. + self.interstitial = nil; +} + +- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial did receive tap event"); + [self.delegate interstitialCustomEventDidReceiveTapEvent:self]; +} + +- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub MRAID interstitial will leave application"); + [self.delegate interstitialCustomEventWillLeaveApplication:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.h new file mode 100644 index 000000000..3cf03e377 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.h @@ -0,0 +1,24 @@ +// +// MPMRAIDInterstitialViewController.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPInterstitialViewController.h" +#import "MPForceableOrientationProtocol.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPMRAIDInterstitialViewControllerDelegate; +@class MPAdConfiguration; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPMRAIDInterstitialViewController : MPInterstitialViewController + +- (id)initWithAdConfiguration:(MPAdConfiguration *)configuration; +- (void)startLoading; + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.m new file mode 100644 index 000000000..be5dee1d1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MPMRAIDInterstitialViewController.m @@ -0,0 +1,190 @@ +// +// MPMRAIDInterstitialViewController.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPMRAIDInterstitialViewController.h" +#import "MPInstanceProvider.h" +#import "MPAdConfiguration.h" +#import "MRController.h" + +@interface MPMRAIDInterstitialViewController () + +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, strong) MRController *mraidController; +@property (nonatomic, strong) UIView *interstitialView; +@property (nonatomic, assign) UIInterfaceOrientationMask supportedOrientationMask; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPMRAIDInterstitialViewController + + +- (id)initWithAdConfiguration:(MPAdConfiguration *)configuration +{ + self = [super init]; + if (self) { + CGFloat width = MAX(configuration.preferredSize.width, 1); + CGFloat height = MAX(configuration.preferredSize.height, 1); + CGRect frame = CGRectMake(0, 0, width, height); + self.mraidController = [[MPInstanceProvider sharedProvider] buildInterstitialMRControllerWithFrame:frame delegate:self]; + + self.configuration = configuration; + self.orientationType = [self.configuration orientationType]; + } + return self; +} + +#pragma mark - Public + +- (void)startLoading +{ + [self.mraidController loadAdWithConfiguration:self.configuration]; +} + +- (void)willPresentInterstitial +{ + [self.mraidController disableRequestHandling]; + if ([self.delegate respondsToSelector:@selector(interstitialWillAppear:)]) { + [self.delegate interstitialWillAppear:self]; + } +} + +- (void)didPresentInterstitial +{ + // This ensures that we handle didPresentInterstitial at the end of the run loop, and prevents a bug + // where code is run before UIKit thinks the presentViewController animation is complete, even though + // this is is called from the completion block for said animation. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{ + [self.mraidController handleMRAIDInterstitialDidPresentWithViewController:self]; + if ([self.delegate respondsToSelector:@selector(interstitialDidAppear:)]) { + [self.delegate interstitialDidAppear:self]; + } + }); +} + +- (void)willDismissInterstitial +{ + [self.mraidController disableRequestHandling]; + if ([self.delegate respondsToSelector:@selector(interstitialWillDisappear:)]) { + [self.delegate interstitialWillDisappear:self]; + } +} + +- (void)didDismissInterstitial +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidDisappear:)]) { + [self.delegate interstitialDidDisappear:self]; + } +} + +#pragma mark - MRControllerDelegate + +- (CLLocation *)location +{ + if ([self.delegate respondsToSelector:@selector(location)]) { + return [self.delegate location]; + } + return nil; +} + +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (MPAdConfiguration *)adConfiguration +{ + return self.configuration; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return self; +} + +- (void)adDidLoad:(UIView *)adView +{ + [self.interstitialView removeFromSuperview]; + + self.interstitialView = adView; + self.interstitialView.frame = self.view.bounds; + self.interstitialView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:self.interstitialView]; + + if ([self.delegate respondsToSelector:@selector(interstitialDidLoadAd:)]) { + [self.delegate interstitialDidLoadAd:self]; + } +} + +- (void)adDidFailToLoad:(UIView *)adView +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidFailToLoadAd:)]) { + [self.delegate interstitialDidFailToLoadAd:self]; + } +} + +- (void)adWillClose:(UIView *)adView +{ + [self dismissInterstitialAnimated:YES]; +} + +- (void)adDidClose:(UIView *)adView +{ + // TODO: +} + +- (void)appShouldSuspendForAd:(UIView *)adView +{ + [self.delegate interstitialDidReceiveTapEvent:self]; +} + +- (void)appShouldResumeFromAd:(UIView *)adView +{ + +} + +- (void)setSupportedOrientationMask:(UIInterfaceOrientationMask)supportedOrientationMask +{ + _supportedOrientationMask = supportedOrientationMask; + + // This should be called whenever the return value of -shouldAutorotateToInterfaceOrientation changes. Since the return + // value is based on _supportedOrientationMask, we do that here. Prevents possible rotation bugs. + [UIViewController attemptRotationToDeviceOrientation]; +} + +- (void)rewardedVideoEnded +{ + if ([self.delegate respondsToSelector:@selector(interstitialRewardedVideoEnded)]) { + [self.delegate interstitialRewardedVideoEnded]; + } +} + +#pragma mark - Orientation Handling + +// supportedInterfaceOrientations and shouldAutorotate are for ios 6, 7, and 8. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_9_0 +- (UIInterfaceOrientationMask)supportedInterfaceOrientations +#else +- (NSUInteger)supportedInterfaceOrientations +#endif +{ + return ([[UIApplication sharedApplication] mp_supportsOrientationMask:self.supportedOrientationMask]) ? self.supportedOrientationMask : UIInterfaceOrientationMaskAll; +} + +- (BOOL)shouldAutorotate +{ + return YES; +} + +// shouldAutorotateToInterfaceOrientation is for ios 5. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return [[UIApplication sharedApplication] mp_doesOrientation:interfaceOrientation matchOrientationMask:self.supportedOrientationMask]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.h new file mode 100644 index 000000000..ac0531bc9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.h @@ -0,0 +1,78 @@ +// +// MRBridge.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import "MRConstants.h" +#import "MPWebView.h" + +@class MRProperty; +@protocol MRBridgeDelegate; + +/** + * The `MRBridge` class is an intermediate object between native code and JavaScript for + * MRAID ads. The MRAID web view communicates events to `MRBridge` which translates them + * down to native code. Likewise, native code will communicate with `MRBridge` to execute + * commands inside the JavaScript. `MRBridge` also inserts mraid.js into the web view when + * loading an ad's HTML. + */ +@interface MRBridge : NSObject + +@property (nonatomic, assign) BOOL shouldHandleRequests; +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithWebView:(MPWebView *)webView; + +- (void)loadHTMLString:(NSString *)HTML baseURL:(NSURL *)baseURL; + +- (void)fireReadyEvent; +- (void)fireChangeEventForProperty:(MRProperty *)property; +- (void)fireChangeEventsForProperties:(NSArray *)properties; +- (void)fireErrorEventForAction:(NSString *)action withMessage:(NSString *)message; + +/* + * fireSizeChangeEvent: will always execute the javascript to notify mraid bridge that the size of the ad may have + * changed. mraid.js will only fire the change event if the size has actually changed. + */ +- (void)fireSizeChangeEvent:(CGSize)size; + +- (void)fireSetScreenSize:(CGSize)size; +- (void)fireSetPlacementType:(NSString *)placementType; +- (void)fireSetCurrentPositionWithPositionRect:(CGRect)positionRect; +- (void)fireSetDefaultPositionWithPositionRect:(CGRect)positionRect; +- (void)fireSetMaxSize:(CGSize)maxSize; + +@end + +/** + * The delegate of an `MRBridge` object that implements `MRBridgeDelegate` must provide information + * about the state of an MRAID ad through `isLoadingAd` and `hasUserInteractedWithWebView` so `MRBridge` + * can correctly process web view events. The delegate will be notified of specific events that need + * to be handled natively for an MRAID ad. The delegate is also notified of most web view events so it + * can perform necessary actions such as changing the ad's state. + */ +@protocol MRBridgeDelegate + +- (BOOL)isLoadingAd; +- (MRAdViewPlacementType)placementType; +- (BOOL)hasUserInteractedWithWebViewForBridge:(MRBridge *)bridge; +- (UIViewController *)viewControllerForPresentingModalView; + +- (void)nativeCommandWillPresentModalView; +- (void)nativeCommandDidDismissModalView; + +- (void)bridge:(MRBridge *)bridge didFinishLoadingWebView:(MPWebView *)webView; +- (void)bridge:(MRBridge *)bridge didFailLoadingWebView:(MPWebView *)webView error:(NSError *)error; + +- (void)handleNativeCommandCloseWithBridge:(MRBridge *)bridge; +- (void)bridge:(MRBridge *)bridge performActionForMoPubSpecificURL:(NSURL *)url; +- (void)bridge:(MRBridge *)bridge handleDisplayForDestinationURL:(NSURL *)URL; +- (void)bridge:(MRBridge *)bridge handleNativeCommandUseCustomClose:(BOOL)useCustomClose; +- (void)bridge:(MRBridge *)bridge handleNativeCommandSetOrientationPropertiesWithForceOrientationMask:(UIInterfaceOrientationMask)forceOrientationMask; +- (void)bridge:(MRBridge *)bridge handleNativeCommandExpandWithURL:(NSURL *)url useCustomClose:(BOOL)useCustomClose; +- (void)bridge:(MRBridge *)bridge handleNativeCommandResizeWithParameters:(NSDictionary *)parameters; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.m new file mode 100644 index 000000000..af3153dc5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBridge.m @@ -0,0 +1,306 @@ +// +// MRBridge.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MRBridge.h" +#import "MPConstants.h" +#import "MPLogging.h" +#import "NSURL+MPAdditions.h" +#import "MPGlobal.h" +#import "MRBundleManager.h" +#import "MPInstanceProvider.h" +#import "UIWebView+MPAdditions.h" +#import "MRError.h" +#import "MRProperty.h" +#import "MRNativeCommandHandler.h" + +static NSString * const kMraidURLScheme = @"mraid"; + +@interface MRBridge () + +@property (nonatomic, strong) MPWebView *webView; +@property (nonatomic, strong) MRNativeCommandHandler *nativeCommandHandler; + +@end + +@implementation MRBridge + +- (instancetype)initWithWebView:(MPWebView *)webView +{ + if (self = [super init]) { + _webView = webView; + _webView.delegate = self; + _nativeCommandHandler = [[MPInstanceProvider sharedProvider] buildMRNativeCommandHandlerWithDelegate:self]; + } + + return self; +} + +- (void)dealloc +{ + _webView.delegate = nil; +} + +- (void)loadHTMLString:(NSString *)HTML baseURL:(NSURL *)baseURL +{ + // Bail out if we can't locate mraid.js. + if (![self MRAIDScriptPath]) { + NSError *error = [NSError errorWithDomain:MoPubMRAIDAdsSDKDomain code:MRErrorMRAIDJSNotFound userInfo:nil]; + [self.delegate bridge:self didFailLoadingWebView:self.webView error:error]; + return; + } + + if (HTML) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // Execute the javascript in the web view directly. + NSString *mraidString = [NSString stringWithContentsOfFile:[self MRAIDScriptPath] encoding:NSUTF8StringEncoding error:nil]; + + // Once done loading from the file, execute the javascript and load the html into the web view. + dispatch_async(dispatch_get_main_queue(), ^{ + [self.webView evaluateJavaScript:mraidString completionHandler:^(id result, NSError *error){ + [self.webView disableJavaScriptDialogs]; + [self.webView loadHTMLString:HTML baseURL:baseURL]; + }]; + }); + }); + } +} + +- (void)fireReadyEvent +{ + [self executeJavascript:@"window.mraidbridge.fireReadyEvent();"]; +} + +- (void)fireChangeEventForProperty:(MRProperty *)property +{ + NSString *JSON = [NSString stringWithFormat:@"{%@}", property]; + [self executeJavascript:@"window.mraidbridge.fireChangeEvent(%@);", JSON]; + MPLogTrace(@"JSON: %@", JSON); +} + +- (void)fireChangeEventsForProperties:(NSArray *)properties +{ + NSString *JSON = [NSString stringWithFormat:@"{%@}", [properties componentsJoinedByString:@", "]]; + [self executeJavascript:@"window.mraidbridge.fireChangeEvent(%@);", JSON]; + MPLogTrace(@"JSON: %@", JSON); +} + +- (void)fireErrorEventForAction:(NSString *)action withMessage:(NSString *)message +{ + [self executeJavascript:@"window.mraidbridge.fireErrorEvent('%@', '%@');", message, action]; +} + +- (void)fireSizeChangeEvent:(CGSize)size +{ + [self executeJavascript:@"window.mraidbridge.notifySizeChangeEvent(%.1f, %.1f);", size.width, size.height]; +} + +- (void)fireSetScreenSize:(CGSize)size +{ + [self executeJavascript:@"window.mraidbridge.setScreenSize(%.1f, %.1f);", size.width, size.height]; +} + +- (void)fireSetPlacementType:(NSString *)placementType +{ + [self executeJavascript:@"window.mraidbridge.setPlacementType('%@');", placementType]; +} + +- (void)fireSetCurrentPositionWithPositionRect:(CGRect)positionRect +{ + [self executeJavascript:@"window.mraidbridge.setCurrentPosition(%.1f, %.1f, %.1f, %.1f);", positionRect.origin.x, positionRect.origin.y, + positionRect.size.width, positionRect.size.height]; +} + +- (void)fireSetDefaultPositionWithPositionRect:(CGRect)positionRect +{ + [self executeJavascript:@"window.mraidbridge.setDefaultPosition(%.1f, %.1f, %.1f, %.1f);", positionRect.origin.x, positionRect.origin.y, + positionRect.size.width, positionRect.size.height]; +} + +- (void)fireSetMaxSize:(CGSize)maxSize +{ + [self executeJavascript:@"window.mraidbridge.setMaxSize(%.1f, %.1f);", maxSize.width, maxSize.height]; +} + +#pragma mark - + +- (BOOL)webView:(MPWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType +{ + NSURL *url = [request URL]; + NSMutableString *urlString = [NSMutableString stringWithString:[url absoluteString]]; + NSString *scheme = url.scheme; + + if ([scheme isEqualToString:kMraidURLScheme]) { + // Some native commands such as useCustomClose should be allowed to run even if we're not handling requests. + // The command handler will make sure we don't execute native commands that aren't allowed to execute while we're not handling requests. + MPLogDebug(@"Trying to process command: %@", urlString); + NSString *command = url.host; + NSDictionary *properties = MPDictionaryFromQueryString(url.query); + [self.nativeCommandHandler handleNativeCommand:command withProperties:properties]; + return NO; + } else if ([url mp_isMoPubScheme]) { + [self.delegate bridge:self performActionForMoPubSpecificURL:url]; + return NO; + } else if ([scheme isEqualToString:@"ios-log"]) { + [urlString replaceOccurrencesOfString:@"%20" + withString:@" " + options:NSLiteralSearch + range:NSMakeRange(0, [urlString length])]; + MPLogDebug(@"Web console: %@", urlString); + return NO; + } + + if (!self.shouldHandleRequests) { + return NO; + } + + if ([url mp_hasTelephoneScheme] || [url mp_hasTelephonePromptScheme]) { + [self.delegate bridge:self handleDisplayForDestinationURL:url]; + return NO; + } + + BOOL isLoading = [self.delegate isLoadingAd]; + BOOL userInteractedWithWebView = [self.delegate hasUserInteractedWithWebViewForBridge:self]; + BOOL safeToAutoloadLink = navigationType == UIWebViewNavigationTypeLinkClicked || userInteractedWithWebView || [url mp_isSafeForLoadingWithoutUserAction]; + + if (!isLoading && (navigationType == UIWebViewNavigationTypeOther || navigationType == UIWebViewNavigationTypeLinkClicked)) { + BOOL iframe = ![request.URL isEqual:request.mainDocumentURL]; + + // If we load a URL from an iFrame that did not originate from a click or + // is a deep link, handle normally and return safeToAutoloadLink. + if (iframe && !((navigationType == UIWebViewNavigationTypeLinkClicked) && ([scheme isEqualToString:@"https"] || [scheme isEqualToString:@"http"]))) { + return safeToAutoloadLink; + } + + // Otherwise, open the URL in a new web view. + [self.delegate bridge:self handleDisplayForDestinationURL:url]; + return NO; + } + + return safeToAutoloadLink; +} + +- (void)webViewDidStartLoad:(MPWebView *)webView +{ + [webView disableJavaScriptDialogs]; +} + +- (void)webViewDidFinishLoad:(MPWebView *)webView +{ + [self.delegate bridge:self didFinishLoadingWebView:webView]; +} + +- (void)webView:(MPWebView *)webView didFailLoadWithError:(NSError *)error +{ + if (error.code == NSURLErrorCancelled) { + return; + } + + [self.delegate bridge:self didFailLoadingWebView:webView error:error]; +} + +#pragma mark - Private + +- (NSString *)MRAIDScriptPath +{ + MRBundleManager *bundleManager = [[MPInstanceProvider sharedProvider] buildMRBundleManager]; + return [bundleManager mraidPath]; +} + +- (void)executeJavascript:(NSString *)javascript, ... +{ + va_list args; + va_start(args, javascript); + [self executeJavascript:javascript withVarArgs:args]; + va_end(args); +} + +- (void)fireNativeCommandCompleteEvent:(NSString *)command +{ + [self executeJavascript:@"window.mraidbridge.nativeCallComplete('%@');", command]; +} + +- (void)executeJavascript:(NSString *)javascript withVarArgs:(va_list)args +{ + NSString *js = [[NSString alloc] initWithFormat:javascript arguments:args]; + [self.webView stringByEvaluatingJavaScriptFromString:js]; +} + +#pragma mark - MRNativeCommandHandlerDelegate + +- (void)handleMRAIDUseCustomClose:(BOOL)useCustomClose +{ + [self.delegate bridge:self handleNativeCommandUseCustomClose:useCustomClose]; +} + +- (void)handleMRAIDSetOrientationPropertiesWithForceOrientationMask:(UIInterfaceOrientationMask)forceOrientationMask +{ + [self.delegate bridge:self handleNativeCommandSetOrientationPropertiesWithForceOrientationMask:forceOrientationMask]; +} + +- (void)handleMRAIDOpenCallForURL:(NSURL *)URL +{ + [self.delegate bridge:self handleDisplayForDestinationURL:URL]; +} + +- (void)handleMRAIDExpandWithParameters:(NSDictionary *)params +{ + id urlValue = [params objectForKey:@"url"]; + [self.delegate bridge:self handleNativeCommandExpandWithURL:(urlValue == [NSNull null]) ? nil : urlValue + useCustomClose:[[params objectForKey:@"useCustomClose"] boolValue]]; +} + +- (void)handleMRAIDResizeWithParameters:(NSDictionary *)params +{ + [self.delegate bridge:self handleNativeCommandResizeWithParameters:params]; +} + +- (void)handleMRAIDClose +{ + [self.delegate handleNativeCommandCloseWithBridge:self]; +} + +- (void)nativeCommandWillPresentModalView +{ + [self.delegate nativeCommandWillPresentModalView]; +} + +- (void)nativeCommandDidDismissModalView +{ + [self.delegate nativeCommandDidDismissModalView]; +} + +- (void)nativeCommandCompleted:(NSString *)command +{ + [self fireNativeCommandCompleteEvent:command]; +} + +- (void)nativeCommandFailed:(NSString *)command withMessage:(NSString *)message +{ + [self fireErrorEventForAction:command withMessage:message]; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (MRAdViewPlacementType)adViewPlacementType +{ + return [self.delegate placementType]; +} + +- (BOOL)userInteractedWithWebView +{ + return [self.delegate hasUserInteractedWithWebViewForBridge:self]; +} + +- (BOOL)handlingWebviewRequests +{ + return self.shouldHandleRequests; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.h new file mode 100644 index 000000000..e701d8be5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.h @@ -0,0 +1,15 @@ +// +// MRBundleManager.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@interface MRBundleManager : NSObject + ++ (MRBundleManager *)sharedManager; +- (NSString *)mraidPath; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.m new file mode 100644 index 000000000..aa3cc249f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRBundleManager.m @@ -0,0 +1,32 @@ +// +// MRBundleManager.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MRBundleManager.h" +#import "NSBundle+MPAdditions.h" + +@implementation MRBundleManager + +static MRBundleManager *sharedManager = nil; + ++ (MRBundleManager *)sharedManager +{ + if (!sharedManager) { + sharedManager = [[MRBundleManager alloc] init]; + } + return sharedManager; +} + +- (NSString *)mraidPath +{ + NSBundle *parentBundle = [NSBundle resourceBundleForClass:self.class]; + + NSString *mraidBundlePath = [parentBundle pathForResource:@"MRAID" ofType:@"bundle"]; + NSBundle *mraidBundle = [NSBundle bundleWithPath:mraidBundlePath]; + return [mraidBundle pathForResource:@"mraid" ofType:@"js"]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.h new file mode 100644 index 000000000..f6c7ff467 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.h @@ -0,0 +1,98 @@ +// +// MRCommand.h +// MoPub +// +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import +#import + +@class MRCommand; + +@protocol MRCommandDelegate + +- (void)mrCommand:(MRCommand *)command createCalendarEventWithParams:(NSDictionary *)params __deprecated; +- (void)mrCommand:(MRCommand *)command playVideoWithURL:(NSURL *)url; +- (void)mrCommand:(MRCommand *)command storePictureWithURL:(NSURL *)url __deprecated; +- (void)mrCommand:(MRCommand *)command shouldUseCustomClose:(BOOL)useCustomClose; +- (void)mrCommand:(MRCommand *)command setOrientationPropertiesWithForceOrientation:(UIInterfaceOrientationMask)forceOrientation; +- (void)mrCommand:(MRCommand *)command openURL:(NSURL *)url; +- (void)mrCommand:(MRCommand *)command expandWithParams:(NSDictionary *)params; +- (void)mrCommand:(MRCommand *)command resizeWithParams:(NSDictionary *)params; +- (void)mrCommandClose:(MRCommand *)command; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRCommand : NSObject + +@property (nonatomic, weak) id delegate; + ++ (id)commandForString:(NSString *)string; + +// returns YES by default for user safety +- (BOOL)requiresUserInteractionForPlacementType:(NSUInteger)placementType; +// This allows commands to run even if the delegate is not handling webview requests. Returns NO by default to avoid race conditions. This is +// primarily used to stop commands that can cause bad side effects while the mraid ad is presenting, dismissing, resizing, expanding and pretty much +// just animating at all. If you decide to return YES for this method, you must make sure that the command can operate safely at any point in time +// during an MRAID ad's lifetime from starting presentation to complete dismissal. +- (BOOL)executableWhileBlockingRequests; +- (BOOL)executeWithParams:(NSDictionary *)params; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRCloseCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRExpandCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRResizeCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRUseCustomCloseCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRSetOrientationPropertiesCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MROpenCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRCreateCalendarEventCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRPlayVideoCommand : MRCommand + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRStorePictureCommand : MRCommand + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.m new file mode 100644 index 000000000..3dd0f4964 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRCommand.m @@ -0,0 +1,405 @@ +// +// MRCommand.m +// MoPub +// +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import "MRCommand.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MRConstants.h" + +@implementation MRCommand + +@synthesize delegate = _delegate; + ++ (NSMutableDictionary *)sharedCommandClassMap +{ + static NSMutableDictionary *sharedMap = nil; + + static dispatch_once_t once; + dispatch_once(&once, ^{ + sharedMap = [[NSMutableDictionary alloc] init]; + }); + + return sharedMap; +} + ++ (void)registerCommand:(Class)commandClass +{ + NSMutableDictionary *map = [self sharedCommandClassMap]; + @synchronized(self) { + [map setValue:commandClass forKey:[commandClass commandType]]; + } +} + ++ (NSString *)commandType +{ + return @"BASE_CMD_TYPE"; +} + ++ (Class)commandClassForString:(NSString *)string +{ + NSMutableDictionary *map = [self sharedCommandClassMap]; + @synchronized(self) { + return [map objectForKey:string]; + } +} + ++ (id)commandForString:(NSString *)string +{ + Class commandClass = [self commandClassForString:string]; + return [[commandClass alloc] init]; +} + +// return YES by default for user safety +- (BOOL)requiresUserInteractionForPlacementType:(NSUInteger)placementType +{ + return YES; +} + +// Default to NO to avoid race conditions. +- (BOOL)executableWhileBlockingRequests +{ + return NO; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + return YES; +} + +- (CGFloat)floatFromParameters:(NSDictionary *)parameters forKey:(NSString *)key +{ + return [self floatFromParameters:parameters forKey:key withDefault:0.0]; +} + +- (CGFloat)floatFromParameters:(NSDictionary *)parameters forKey:(NSString *)key withDefault:(CGFloat)defaultValue +{ + NSString *stringValue = [parameters valueForKey:key]; + return stringValue ? [stringValue floatValue] : defaultValue; +} + +- (BOOL)boolFromParameters:(NSDictionary *)parameters forKey:(NSString *)key +{ + NSString *stringValue = [parameters valueForKey:key]; + return [stringValue isEqualToString:@"true"] || [stringValue isEqualToString:@"1"]; +} + +- (int)intFromParameters:(NSDictionary *)parameters forKey:(NSString *)key +{ + NSString *stringValue = [parameters valueForKey:key]; + return stringValue ? [stringValue intValue] : -1; +} + +- (NSString *)stringFromParameters:(NSDictionary *)parameters forKey:(NSString *)key +{ + NSString *value = [parameters objectForKey:key]; + if (!value || [value isEqual:[NSNull null]]) return nil; + + value = [value stringByTrimmingCharactersInSet: + [NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (!value || [value isEqual:[NSNull null]] || value.length == 0) return nil; + + return value; +} + +- (NSURL *)urlFromParameters:(NSDictionary *)parameters forKey:(NSString *)key +{ + NSString *value = [self stringFromParameters:parameters forKey:key]; + return [NSURL URLWithString:value]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRCloseCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"close"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommandClose:self]; + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRExpandCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"expand"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + NSURL *url = [self urlFromParameters:params forKey:@"url"]; + + NSDictionary *expandParams = [NSDictionary dictionaryWithObjectsAndKeys: + (url == nil) ? [NSNull null] : url , @"url", + [NSNumber numberWithBool:[self boolFromParameters:params forKey:@"shouldUseCustomClose"]], @"useCustomClose", + nil]; + + [self.delegate mrCommand:self expandWithParams:expandParams]; + + return YES; +} +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRResizeCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"resize"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self resizeWithParams:params]; + + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRUseCustomCloseCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + +// We allow useCustomClose to run while we're blocking requests because it only controls how we present a UIButton. +// It can't present/dismiss any view or view controllers. It also doesn't affect any mraid ad/screen metrics. +- (BOOL)executableWhileBlockingRequests +{ + return YES; +} + +- (BOOL)requiresUserInteractionForPlacementType:(NSUInteger)placementType +{ + return NO; +} + ++ (NSString *)commandType +{ + return @"usecustomclose"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self shouldUseCustomClose:[self boolFromParameters:params forKey:@"shouldUseCustomClose"]]; + + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRSetOrientationPropertiesCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"setOrientationProperties"; +} + +- (BOOL)requiresUserInteractionForPlacementType:(NSUInteger)placementType +{ + return NO; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + // We can take the forceOrientation and allowOrientationChange values and boil them down to an orientation mask + // that will represent the intention of the ad. + UIInterfaceOrientationMask forceOrientationMaskValue; + + NSString *forceOrientationString = params[@"forceOrientation"]; + + // Give a default value of "none" for forceOrientationString if it didn't come in through the params. + if (!forceOrientationString) { + forceOrientationString = kOrientationPropertyForceOrientationNoneKey; + } + + // Do not allow orientation changing if we're given a force orientation other than none. Based on the spec, + // we believe that forceOrientation takes precedence over allowOrientationChange and should not allow + // orientation changes when a forceOrientation other than 'none' is given. + if ([forceOrientationString isEqualToString:kOrientationPropertyForceOrientationPortraitKey]) { + forceOrientationMaskValue = UIInterfaceOrientationMaskPortrait; + } else if ([forceOrientationString isEqualToString:kOrientationPropertyForceOrientationLandscapeKey]) { + forceOrientationMaskValue = UIInterfaceOrientationMaskLandscape; + } else { + // Default allowing orientation change to YES. We will change this only if we received a value for this in our params. + BOOL allowOrientationChangeValue = YES; + + // If we end up allowing orientation change, then we're going to allow any orientation. + forceOrientationMaskValue = UIInterfaceOrientationMaskAll; + + NSObject *allowOrientationChangeObj = params[@"allowOrientationChange"]; + + if (allowOrientationChangeObj) { + allowOrientationChangeValue = [self boolFromParameters:params forKey:@"allowOrientationChange"]; + } + + // If we don't allow orientation change, we're locking the user into the current orientation. + if (!allowOrientationChangeValue) { + UIInterfaceOrientation currentOrientation = MPInterfaceOrientation(); + + if (UIInterfaceOrientationIsLandscape(currentOrientation)) { + forceOrientationMaskValue = UIInterfaceOrientationMaskLandscape; + } else if (currentOrientation == UIInterfaceOrientationPortrait) { + forceOrientationMaskValue = UIInterfaceOrientationMaskPortrait; + } else if (currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { + forceOrientationMaskValue = UIInterfaceOrientationMaskPortraitUpsideDown; + } + } + } + + [self.delegate mrCommand:self setOrientationPropertiesWithForceOrientation:forceOrientationMaskValue]; + + return YES; +} +/* + * We allow setOrientationProperties to run while we're blocking requests because this command can occur during the presentation + * animation of an interstitial, and has a strong effect on how an ad is presented so we want to make sure it's executed. + * + * Even though we return YES here, updating orientation while blocking requests is not safe. MRController receives the appropriate + * delegate call, and caches the intended call in a block, which it executes when request-blocking is disabled. + */ +- (BOOL)executableWhileBlockingRequests +{ + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MROpenCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"open"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self openURL:[self urlFromParameters:params forKey:@"url"]]; + + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRCreateCalendarEventCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"createCalendarEvent"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self createCalendarEventWithParams:params]; + + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRPlayVideoCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"playVideo"; +} + +- (BOOL)requiresUserInteractionForPlacementType:(NSUInteger)placementType +{ + // allow interstitials to auto-play video + return placementType != MRAdViewPlacementTypeInterstitial; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self playVideoWithURL:[self urlFromParameters:params forKey:@"uri"]]; + + return YES; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRStorePictureCommand + ++ (void)load +{ + [MRCommand registerCommand:self]; +} + ++ (NSString *)commandType +{ + return @"storePicture"; +} + +- (BOOL)executeWithParams:(NSDictionary *)params +{ + [self.delegate mrCommand:self storePictureWithURL:[self urlFromParameters:params forKey:@"uri"]]; + + return YES; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.h new file mode 100644 index 000000000..f994cd346 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.h @@ -0,0 +1,24 @@ +// +// MRConstants.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +enum { + MRAdViewStateHidden, + MRAdViewStateDefault, + MRAdViewStateExpanded, + MRAdViewStateResized +}; +typedef NSUInteger MRAdViewState; + +enum { + MRAdViewPlacementTypeInline, + MRAdViewPlacementTypeInterstitial +}; +typedef NSUInteger MRAdViewPlacementType; + +extern NSString *const kOrientationPropertyForceOrientationPortraitKey; +extern NSString *const kOrientationPropertyForceOrientationLandscapeKey; +extern NSString *const kOrientationPropertyForceOrientationNoneKey; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.m new file mode 100644 index 000000000..75fb85a95 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRConstants.m @@ -0,0 +1,12 @@ +// +// MRConstants.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +NSString *const kOrientationPropertyForceOrientationPortraitKey = @"portrait"; +NSString *const kOrientationPropertyForceOrientationLandscapeKey = @"landscape"; +NSString *const kOrientationPropertyForceOrientationNoneKey = @"none"; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.h new file mode 100644 index 000000000..65c7e2322 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.h @@ -0,0 +1,76 @@ +// +// MRController.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MRConstants.h" +#import "MPMRAIDInterstitialViewController.h" + +@protocol MRControllerDelegate; +@class MPAdConfiguration; +@class CLLocation; + +/** + * The `MRController` class is used to load and interact with MRAID ads. + * It contains two MRAID ad views and uses a separate `MRBridge` to + * communicate to each view. `MRController` handles view-related MRAID + * native calls such as expand(), resize(), close(), and open(). + */ +@interface MRController : NSObject + +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithAdViewFrame:(CGRect)adViewFrame adPlacementType:(MRAdViewPlacementType)placementType; + +- (void)loadAdWithConfiguration:(MPAdConfiguration *)configuration; +- (void)handleMRAIDInterstitialDidPresentWithViewController:(MPMRAIDInterstitialViewController *)viewController; +- (void)enableRequestHandling; +- (void)disableRequestHandling; + +@end + +/** + * The `MRControllerDelegate` will relay specific events such as ad loading to + * the object that implements the delegate. It also requires information + * such as adUnitId, adConfiguation, and location in order to use its + * ad alert manager. + **/ +@protocol MRControllerDelegate + +@required + +- (NSString *)adUnitId; +- (MPAdConfiguration *)adConfiguration; +- (CLLocation *)location; + +// Retrieves the view controller from which modal views should be presented. +- (UIViewController *)viewControllerForPresentingModalView; + +// Called when the ad is about to display modal content (thus taking over the screen). +- (void)appShouldSuspendForAd:(UIView *)adView; + +// Called when the ad has dismissed any modal content (removing any on-screen takeovers). +- (void)appShouldResumeFromAd:(UIView *)adView; + +@optional + +// Called when the ad loads successfully. +- (void)adDidLoad:(UIView *)adView; + +// Called when the ad fails to load. +- (void)adDidFailToLoad:(UIView *)adView; + +// Called just before the ad closes. +- (void)adWillClose:(UIView *)adView; + +// Called just after the ad has closed. +- (void)adDidClose:(UIView *)adView; + +// Called after the rewarded video finishes playing +- (void)rewardedVideoEnded; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.m new file mode 100644 index 000000000..24b43d98a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRController.m @@ -0,0 +1,1176 @@ +// +// MRController.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MRController.h" +#import "MRBridge.h" +#import "MRCommand.h" +#import "MRProperty.h" +#import "MPAdAlertManager.h" +#import "MPAdConfiguration.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MRExpandModalViewController.h" +#import "MPCoreInstanceProvider.h" +#import "MPClosableView.h" +#import "MPGlobal.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPTimer.h" +#import "NSHTTPURLResponse+MPAdditions.h" +#import "NSURL+MPAdditions.h" +#import "UIWebView+MPAdditions.h" +#import "MPForceableOrientationProtocol.h" +#import "MPAPIEndPoints.h" + +static const NSTimeInterval kAdPropertyUpdateTimerInterval = 1.0; +static const NSTimeInterval kMRAIDResizeAnimationTimeInterval = 0.3; + +static NSString *const kMRAIDCommandExpand = @"expand"; +static NSString *const kMRAIDCommandResize = @"resize"; + +@interface MRController () + +@property (nonatomic) MPAdConfiguration *adConfiguration; +@property (nonatomic, strong) MRBridge *mraidBridge; +@property (nonatomic, strong) MRBridge *mraidBridgeTwoPart; +@property (nonatomic, strong) MPClosableView *mraidAdView; +@property (nonatomic, strong) MPClosableView *mraidAdViewTwoPart; +@property (nonatomic, strong) UIView *resizeBackgroundView; +@property (nonatomic, strong) MPTimer *adPropertyUpdateTimer; +@property (nonatomic, assign) MRAdViewPlacementType placementType; +@property (nonatomic, strong) MRExpandModalViewController *expandModalViewController; +@property (nonatomic, weak) MPMRAIDInterstitialViewController *interstitialViewController; +@property (nonatomic, strong) NSMutableData *twoPartExpandData; +@property (nonatomic, assign) NSStringEncoding responseEncoding; +@property (nonatomic, assign) CGRect mraidDefaultAdFrame; +@property (nonatomic, assign) CGRect mraidDefaultAdFrameInKeyWindow; +@property (nonatomic, assign) CGSize currentAdSize; +@property (nonatomic, assign) NSUInteger modalViewCount; +@property (nonatomic, assign) MRAdViewState currentState; +@property (nonatomic, assign) BOOL shouldUseUIWebView; +// Track the original super view for when we move the ad view to the key window for a 1-part expand. +@property (nonatomic, weak) UIView *originalSuperview; +@property (nonatomic, assign) BOOL isViewable; +@property (nonatomic, assign) BOOL isAnimatingAdSize; +@property (nonatomic, assign) BOOL isAdLoading; +// Whether or not an interstitial requires precaching. Does not affect banners. +@property (nonatomic, assign) BOOL adRequiresPrecaching; +@property (nonatomic, assign) BOOL isAdVastVideoPlayer; +@property (nonatomic, assign) BOOL firedReadyEventForDefaultAd; + +// Points to mraidAdView (one-part expand) or mraidAdViewTwoPart (two-part expand) while expanded. +@property (nonatomic, strong) MPClosableView *expansionContentView; + +@property (nonatomic, strong) MPAdDestinationDisplayAgent *destinationDisplayAgent; +@property (nonatomic, strong) id adAlertManager; +@property (nonatomic, strong) id adAlertManagerTwoPart; + +// Use UIInterfaceOrientationMaskALL to specify no forcing. +@property (nonatomic, assign) UIInterfaceOrientationMask forceOrientationMask; + +@property (nonatomic, assign) UIInterfaceOrientation currentInterfaceOrientation; + +@property (nonatomic, copy) void (^forceOrientationAfterAnimationBlock)(); + +@end + +@implementation MRController + +- (instancetype)initWithAdViewFrame:(CGRect)adViewFrame adPlacementType:(MRAdViewPlacementType)placementType +{ + if (self = [super init]) { + _placementType = placementType; + _currentState = MRAdViewStateDefault; + _forceOrientationMask = UIInterfaceOrientationMaskAll; + _isAnimatingAdSize = NO; + _firedReadyEventForDefaultAd = NO; + _currentAdSize = CGSizeZero; + + _mraidDefaultAdFrame = adViewFrame; + + _adPropertyUpdateTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:kAdPropertyUpdateTimerInterval + target:self + selector:@selector(updateMRAIDProperties) + repeats:YES]; + _adPropertyUpdateTimer.runLoopMode = NSRunLoopCommonModes; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(viewEnteredBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + //Setting the frame here is irrelevant - we update it whenever an ad resizes to match the + //application frame. + _resizeBackgroundView = [[UIView alloc] initWithFrame:adViewFrame]; + _resizeBackgroundView.backgroundColor = [UIColor clearColor]; + + + _destinationDisplayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + + _adAlertManager = [[MPCoreInstanceProvider sharedProvider] buildMPAdAlertManagerWithDelegate:self]; + _adAlertManagerTwoPart = [[MPCoreInstanceProvider sharedProvider] buildMPAdAlertManagerWithDelegate:self]; + } + + return self; +} + +- (void)dealloc +{ + // Transfer delegation to the expand modal view controller in the event the modal is still being presented so it can dismiss itself. + _expansionContentView.delegate = _expandModalViewController; + + [_adPropertyUpdateTimer invalidate]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Public + +- (void)loadAdWithConfiguration:(MPAdConfiguration *)configuration +{ + self.adConfiguration = configuration; + self.isAdLoading = YES; + self.adRequiresPrecaching = configuration.precacheRequired; + self.isAdVastVideoPlayer = configuration.isVastVideoPlayer; + self.shouldUseUIWebView = self.isAdVastVideoPlayer || self.adConfiguration.forceUIWebView; + + MPWebView *webView = [self buildMRAIDWebViewWithFrame:self.mraidDefaultAdFrame + forceUIWebView:self.shouldUseUIWebView]; + + self.mraidBridge = [[MPInstanceProvider sharedProvider] buildMRBridgeWithWebView:webView delegate:self]; + self.mraidAdView = [[MPInstanceProvider sharedProvider] buildMRAIDMPClosableViewWithFrame:self.mraidDefaultAdFrame + webView:webView + delegate:self]; + if (self.placementType == MRAdViewPlacementTypeInterstitial) { + self.mraidAdView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + } + + [self initAdAlertManager:self.adAlertManager forAdView:self.mraidAdView]; + + // Initially turn off the close button for default banner MRAID ads while defaulting to turning it on for interstitials. + if (self.placementType == MRAdViewPlacementTypeInline) { + self.mraidAdView.closeButtonType = MPClosableViewCloseButtonTypeNone; + } else if (self.placementType == MRAdViewPlacementTypeInterstitial) { + self.mraidAdView.closeButtonType = MPClosableViewCloseButtonTypeTappableWithImage; + } + + // This load is guaranteed to never be called for a two-part expand so we know we need to load the HTML into the default web view. + NSString *HTML = [configuration adResponseHTMLString]; + [self.mraidBridge loadHTMLString:HTML + baseURL:[NSURL URLWithString:[MPAPIEndpoints baseURL]] + ]; +} + +- (void)handleMRAIDInterstitialDidPresentWithViewController:(MPMRAIDInterstitialViewController *)viewController +{ + self.interstitialViewController = viewController; + [self enableRequestHandling]; + [self checkViewability]; +} + +- (void)enableRequestHandling +{ + self.mraidBridge.shouldHandleRequests = YES; + self.mraidBridgeTwoPart.shouldHandleRequests = YES; + // If orientation has been forced while requests are disabled (during animation), we need to execute that command through the block forceOrientationAfterAnimationBlock() after the presentation completes. + if (self.forceOrientationAfterAnimationBlock) { + self.forceOrientationAfterAnimationBlock(); + self.forceOrientationAfterAnimationBlock = nil; + } +} + +- (void)disableRequestHandling +{ + self.mraidBridge.shouldHandleRequests = NO; + self.mraidBridgeTwoPart.shouldHandleRequests = NO; + [self.destinationDisplayAgent cancel]; +} + +#pragma mark - Loading Two Part Expand (NSURLConnectionDelegate) + +- (void)loadTwoPartCreativeFromURL:(NSURL *)url +{ + self.isAdLoading = YES; + + NSURLConnection *connection = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:self]; + if (connection) { + self.twoPartExpandData = [NSMutableData data]; + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + [self.twoPartExpandData setLength:0]; + + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + NSDictionary *headers = [httpResponse allHeaderFields]; + NSString *contentType = [headers objectForKey:kMoPubHTTPHeaderContentType]; + self.responseEncoding = [httpResponse stringEncodingFromContentType:contentType]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + [self.twoPartExpandData appendData:data]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + self.isAdLoading = NO; + // No matter what, show the close button on the expanded view. + self.expansionContentView.closeButtonType = MPClosableViewCloseButtonTypeTappableWithImage; + [self.mraidBridge fireErrorEventForAction:kMRAIDCommandExpand withMessage:@"Could not load URL."]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + NSString *str = [[NSString alloc] initWithData:self.twoPartExpandData encoding:self.responseEncoding]; + [self.mraidBridgeTwoPart loadHTMLString:str baseURL:connection.currentRequest.URL]; +} + +#pragma mark - Private + +- (void)initAdAlertManager:(id)adAlertManager forAdView:(MPClosableView *)adView +{ + adAlertManager.adConfiguration = [self.delegate adConfiguration]; + adAlertManager.adUnitId = [self.delegate adUnitId]; + adAlertManager.targetAdView = adView; + adAlertManager.location = [self.delegate location]; + [adAlertManager beginMonitoringAlerts]; +} + +- (MPClosableView *)adViewForBridge:(MRBridge *)bridge +{ + if (bridge == self.mraidBridgeTwoPart) { + return self.mraidAdViewTwoPart; + } + + return self.mraidAdView; +} + +- (MRBridge *)bridgeForAdView:(MPClosableView *)view +{ + if (view == self.mraidAdViewTwoPart) { + return self.mraidBridgeTwoPart; + } + + return self.mraidBridge; +} + +- (MPClosableView *)activeView +{ + if (self.currentState == MRAdViewStateExpanded) { + return self.expansionContentView; + } + + return self.mraidAdView; +} + +- (MRBridge *)bridgeForActiveAdView +{ + MRBridge *bridge = [self bridgeForAdView:[self activeView]]; + return bridge; +} + +- (MPWebView *)buildMRAIDWebViewWithFrame:(CGRect)frame forceUIWebView:(BOOL)forceUIWebView +{ + MPWebView *webView = [[MPWebView alloc] initWithFrame:frame forceUIWebView:forceUIWebView]; + webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + webView.backgroundColor = [UIColor clearColor]; + webView.clipsToBounds = YES; + webView.opaque = NO; + [webView mp_setScrollable:NO]; + + return webView; +} + +#pragma mark - Orientation Notifications + +- (void)orientationDidChange:(NSNotification *)notification +{ + // We listen for device notification changes because at that point our ad's frame is in + // the correct state; however, MRAID updates should only happen when the interface changes, so the update logic is only executed if the interface orientation has changed. + + //MPInterfaceOrientation is guaranteed to be the new orientation at this point. + UIInterfaceOrientation newInterfaceOrientation = MPInterfaceOrientation(); + if (newInterfaceOrientation != self.currentInterfaceOrientation) { + // Update all properties and fire a size change event. + [self updateMRAIDProperties]; + + //According to MRAID Specs, a resized ad should close when there's an orientation change + //due to unpredictability of the new layout. + if (self.currentState == MRAdViewStateResized) { + [self close]; + } + + self.currentInterfaceOrientation = newInterfaceOrientation; + } +} + +#pragma mark - Executing Javascript + +- (void)initializeLoadedAdForBridge:(MRBridge *)bridge +{ + // Set up some initial properties so mraid can operate. + MPLogDebug(@"Injecting initial JavaScript state."); + NSArray *startingMraidProperties = @[[MRHostSDKVersionProperty defaultProperty], + [MRPlacementTypeProperty propertyWithType:self.placementType], + [MRSupportsProperty defaultProperty], + [MRStateProperty propertyWithState:self.currentState] + ]; + + [bridge fireChangeEventsForProperties:startingMraidProperties]; + + [self updateMRAIDProperties]; + + [bridge fireReadyEvent]; +} + +- (void)fireChangeEventToBothBridgesForProperty:(MRProperty *)property +{ + [self.mraidBridge fireChangeEventForProperty:property]; + [self.mraidBridgeTwoPart fireChangeEventForProperty:property]; +} + +#pragma mark - Resize Helpers + +- (CGRect)adjustedFrameForFrame:(CGRect)frame allowOffscreen:(BOOL)allowOffscreen +{ + if (allowOffscreen) { + return frame; + } + + CGRect applicationFrame = MPApplicationFrame(); + CGFloat applicationWidth = CGRectGetWidth(applicationFrame); + CGFloat applicationHeight = CGRectGetHeight(applicationFrame); + CGFloat adFrameWidth = CGRectGetWidth(frame); + CGFloat adFrameHeight = CGRectGetHeight(frame); + + //Checking that the ad's frame falls offscreen, and then it is smaller than the screen's bounds (so when + //moved onscreen, it will fit). If not, we bail out, and validation is done separately. + if (!CGRectContainsRect(applicationFrame, frame) && adFrameWidth <= applicationWidth && adFrameHeight <= applicationHeight) { + + CGFloat applicationMinX = CGRectGetMinX(applicationFrame); + CGFloat applicationMaxX = CGRectGetMaxX(applicationFrame); + CGFloat adFrameMinX = CGRectGetMinX(frame); + CGFloat adFrameMaxX = CGRectGetMaxX(frame); + + if (adFrameMinX < applicationMinX) { + frame.origin.x += applicationMinX - adFrameMinX; + } else if (adFrameMaxX > applicationMaxX) { + frame.origin.x -= adFrameMaxX - applicationMaxX; + } + + CGFloat applicationMinY = CGRectGetMinY(applicationFrame); + CGFloat applicationMaxY = CGRectGetMaxY(applicationFrame); + CGFloat adFrameMinY = CGRectGetMinY(frame); + CGFloat adFrameMaxY = CGRectGetMaxY(frame); + + if (adFrameMinY < applicationMinY) { + frame.origin.y += applicationMinY - adFrameMinY; + } else if (adFrameMaxY > applicationMaxY) { + frame.origin.y -= adFrameMaxY - applicationMaxY; + } + } + + return frame; +} + +- (BOOL)isValidResizeFrame:(CGRect)frame allowOffscreen:(BOOL)allowOffscreen +{ + BOOL valid = YES; + if (!allowOffscreen && !CGRectContainsRect(MPApplicationFrame(), frame)) { + valid = NO; + } else if (CGRectGetWidth(frame) < 50.0f || CGRectGetHeight(frame) < 50.0f) { + valid = NO; + } + + return valid; +} + +- (BOOL)isValidResizeCloseButtonPlacementInFrame:(CGRect)newFrame +{ + CGRect closeButtonFrameForResize = MPClosableViewCustomCloseButtonFrame(newFrame.size, self.mraidAdView.closeButtonLocation); + //Manually calculating Button's Frame in the window (newFrame's soon-to-be superview) because newFrame is not + //part of the view hierarchy yet. + CGRect closeButtonFrameInWindow = CGRectOffset(closeButtonFrameForResize, CGRectGetMinX(newFrame), CGRectGetMinY(newFrame)); + + return CGRectContainsRect(MPApplicationFrame(), closeButtonFrameInWindow); +} + +- (MPClosableViewCloseButtonLocation)adCloseButtonLocationFromString:(NSString *)closeButtonLocationString +{ + if ([closeButtonLocationString isEqualToString:@"top-left"]) { + return MPClosableViewCloseButtonLocationTopLeft; + } else if ([closeButtonLocationString isEqualToString:@"top-center"]) { + return MPClosableViewCloseButtonLocationTopCenter; + } else if ([closeButtonLocationString isEqualToString:@"bottom-left"]) { + return MPClosableViewCloseButtonLocationBottomLeft; + } else if ([closeButtonLocationString isEqualToString:@"bottom-center"]) { + return MPClosableViewCloseButtonLocationBottomCenter; + } else if ([closeButtonLocationString isEqualToString:@"bottom-right"]) { + return MPClosableViewCloseButtonLocationBottomRight; + } else if ([closeButtonLocationString isEqualToString:@"center"]) { + return MPClosableViewCloseButtonLocationCenter; + } else { + return MPClosableViewCloseButtonLocationTopRight; + } +} + +- (void)animateViewFromDefaultStateToResizedState:(MPClosableView *)view withFrame:(CGRect)newFrame +{ + [self willBeginAnimatingAdSize]; + + [UIView animateWithDuration:kMRAIDResizeAnimationTimeInterval animations:^{ + self.mraidAdView.frame = newFrame; + } completion:^(BOOL finished) { + [self changeStateTo:MRAdViewStateResized]; + [self didEndAnimatingAdSize]; + }]; +} + +#pragma mark - Expand Helpers + +- (void)presentExpandModalViewControllerWithView:(MPClosableView *)view animated:(BOOL)animated +{ + [self presentExpandModalViewControllerWithView:view animated:animated completion:nil]; +} + +- (void)presentExpandModalViewControllerWithView:(MPClosableView *)view animated:(BOOL)animated completion:(void (^)())completionBlock +{ + [self willBeginAnimatingAdSize]; + + self.expandModalViewController = [[MRExpandModalViewController alloc] initWithOrientationMask:self.forceOrientationMask]; + [self.expandModalViewController.view addSubview:view]; + view.frame = self.expandModalViewController.view.bounds; + view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.expandModalViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + [self.expandModalViewController hideStatusBar]; + + [[self.delegate viewControllerForPresentingModalView] presentViewController:self.expandModalViewController + animated:animated + completion:^{ + self.currentInterfaceOrientation = MPInterfaceOrientation(); + [self didEndAnimatingAdSize]; + + if (completionBlock) { + completionBlock(); + } + }]; +} + +- (void)willBeginAnimatingAdSize +{ + self.isAnimatingAdSize = YES; + [self disableRequestHandling]; +} + +- (void)didEndAnimatingAdSize +{ + self.isAnimatingAdSize = NO; + [self enableRequestHandling]; +} + +#pragma mark - Close Helpers + +- (void)close +{ + switch (self.currentState) { + case MRAdViewStateDefault: + [self closeFromDefaultState]; + break; + case MRAdViewStateExpanded: + [self closeFromExpandedState]; + break; + case MRAdViewStateResized: + [self closeFromResizedState]; + break; + case MRAdViewStateHidden: + break; + default: + break; + } +} + +- (void)closeFromDefaultState +{ + [self adWillClose]; + + self.mraidAdView.hidden = YES; + [self changeStateTo:MRAdViewStateHidden]; + + [self adDidClose]; +} + +- (void)closeFromExpandedState +{ + self.mraidAdView.closeButtonType = MPClosableViewCloseButtonTypeNone; + + // Immediately re-parent the ad so it will show up as the expand modal goes away rather than after. + [self.originalSuperview addSubview:self.mraidAdView]; + self.mraidAdView.frame = self.mraidDefaultAdFrame; + if (self.placementType != MRAdViewPlacementTypeInterstitial) { + self.mraidAdView.autoresizingMask = UIViewAutoresizingNone; + } + + // Track isAnimatingAdSize because we have a timer that will update the mraid ad properties. We don't want to examine our views when + // they're in a transitional state. + [self willBeginAnimatingAdSize]; + + // Tell the modal view controller to restore the state of the status bar back to what the application had it set to. + [self.expandModalViewController restoreStatusBarVisibility]; + __weak __typeof__(self) weakSelf = self; + [self.expandModalViewController dismissViewControllerAnimated:YES completion:^{ + __typeof__(self) strongSelf = weakSelf; + + + [strongSelf didEndAnimatingAdSize]; + [strongSelf adDidDismissModalView]; + + // Get rid of the bridge and view if we are closing from two-part expand. + if (strongSelf.mraidAdViewTwoPart) { + [strongSelf.adAlertManagerTwoPart endMonitoringAlerts]; + strongSelf.mraidAdViewTwoPart = nil; + strongSelf.mraidBridgeTwoPart = nil; + } + + strongSelf.expansionContentView = nil; + strongSelf.expandModalViewController = nil; + + // Waiting this long to change the state results in some awkward animation. The full screen ad will briefly appear in the banner's + // frame after the modal dismisses. However, this is a much safer time to change the state and results in less side effects. + [strongSelf changeStateTo:MRAdViewStateDefault]; + }]; +} + +- (void)closeFromResizedState +{ + self.mraidAdView.closeButtonType = MPClosableViewCloseButtonTypeNone; + + [self willBeginAnimatingAdSize]; + + [UIView animateWithDuration:kMRAIDResizeAnimationTimeInterval animations:^{ + self.mraidAdView.frame = self.mraidDefaultAdFrameInKeyWindow; + } completion:^(BOOL finished) { + [self.resizeBackgroundView removeFromSuperview]; + [self.originalSuperview addSubview:self.mraidAdView]; + self.mraidAdView.frame = self.mraidDefaultAdFrame; + [self changeStateTo:MRAdViewStateDefault]; + [self didEndAnimatingAdSize]; + [self adDidDismissModalView]; + }]; +} + +#pragma mark - + +- (BOOL)isLoadingAd +{ + return self.isAdLoading; +} + +- (BOOL)hasUserInteractedWithWebViewForBridge:(MRBridge *)bridge +{ + // inline videos seem to delay tap gesture recognition so that we get the click through + // request in the webview delegate BEFORE we get the gesture recognizer triggered callback. For now + // excuse all MRAID interstitials from the user interaction requirement. We do the same for expanded ads. + // We can go ahead and return true for either bridge (default, expanded) if the current state is expanded since + // the fact we're in expanded means that the first webview has been tapped. Then we just don't require the check + // for the expanded bridge. + if (self.placementType == MRAdViewPlacementTypeInterstitial || self.currentState == MRAdViewStateExpanded) { + return YES; + } + + MPClosableView *adView = [self adViewForBridge:bridge]; + return adView.wasTapped; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + UIViewController *delegateVC = [self.delegate viewControllerForPresentingModalView]; + + // Use the expand modal view controller as the presenting modal if it's being presented. + if (self.expandModalViewController.presentingViewController != nil) { + return self.expandModalViewController; + } + + return delegateVC; +} + +- (void)nativeCommandWillPresentModalView +{ + [self adWillPresentModalView]; +} + +- (void)nativeCommandDidDismissModalView +{ + [self adDidDismissModalView]; +} + +- (void)bridge:(MRBridge *)bridge didFinishLoadingWebView:(MPWebView *)webView +{ + // Loading an iframe can cause this method to execute and could potentially cause us to initialize the javascript for a two-part expand + // and fire the ready event more than once. The isAdLoading flags helps us prevent that from happening. + if (self.isAdLoading) { + + self.isAdLoading = NO; + + if (!self.adRequiresPrecaching) { + // Only tell the delegate that the ad loaded when the view is the default ad view and not a two-part ad view. + if (bridge == self.mraidBridge) { + // We do not intialize the javascript/fire ready event, or start our timer for a banner load yet. We wait until + // the ad is in the view hierarchy. We are notified by the view when it is potentially added to the hierarchy in + // -closableView:didMoveToWindow:. + [self adDidLoad]; + } else if (bridge == self.mraidBridgeTwoPart) { + // If the default ad was already viewable, we need to simply tell the two part it is viewable. Otherwise, if the default + // ad wasn't viewable, we need to update the state across both webviews and the controller. + if (self.isViewable) { + [self.mraidBridgeTwoPart fireChangeEventForProperty:[MRViewableProperty propertyWithViewable:YES]]; + } else { + [self updateViewabilityWithBool:YES]; + } + + // We initialize javascript and fire the ready event for the two part ad view once it loads + // since it'll already be in the view hierarchy. + [self initializeLoadedAdForBridge:bridge]; + } + } + } +} + +- (void)bridge:(MRBridge *)bridge didFailLoadingWebView:(MPWebView *)webView error:(NSError *)error +{ + self.isAdLoading = NO; + + if (bridge == self.mraidBridge) { + // We need to report that the ad failed to load when the default ad fails to load. + [self adDidFailToLoad]; + } else if (bridge == self.mraidBridgeTwoPart) { + // Always show the close button when the two-part expand fails. + self.expansionContentView.closeButtonType = MPClosableViewCloseButtonTypeTappableWithImage; + + // For two-part expands, we don't want to tell the delegate anything went wrong since the ad did successfully load. + // We will fire an error to the javascript though. + [self.mraidBridge fireErrorEventForAction:kMRAIDCommandExpand withMessage:@"Could not load URL."]; + } +} + +- (void)bridge:(MRBridge *)bridge performActionForMoPubSpecificURL:(NSURL *)url +{ + MPLogDebug(@"MRController - loading MoPub URL: %@", url); + MPMoPubHostCommand command = [url mp_mopubHostCommand]; + if (command == MPMoPubHostCommandPrecacheComplete && self.adRequiresPrecaching) { + [self adDidLoad]; + } else if (command == MPMoPubHostCommandFailLoad) { + [self adDidFailToLoad]; + } else if (command == MPMoPubHostCommandRewardedVideoEnded) { + [self.delegate rewardedVideoEnded]; + } else { + MPLogWarn(@"MRController - unsupported MoPub URL: %@", [url absoluteString]); + } +} + +- (void)handleNativeCommandCloseWithBridge:(MRBridge *)bridge +{ + [self close]; +} + +- (void)bridge:(MRBridge *)bridge handleDisplayForDestinationURL:(NSURL *)URL +{ + if ([self hasUserInteractedWithWebViewForBridge:bridge]) { + [self.destinationDisplayAgent displayDestinationForURL:URL]; + } +} + +- (void)bridge:(MRBridge *)bridge handleNativeCommandUseCustomClose:(BOOL)useCustomClose +{ + // Calling useCustomClose() for banners won't take effect until expand() is called so we don't need to take + // any action here as useCustomClose will be given to us when expand is called. Interstitials can have their + // close buttons changed at any time though. + if (self.placementType != MRAdViewPlacementTypeInterstitial) { + return; + } + + [self configureCloseButtonForView:self.mraidAdView forUseCustomClose:useCustomClose]; +} + +- (void)configureCloseButtonForView:(MPClosableView *)view forUseCustomClose:(BOOL)useCustomClose +{ + if (useCustomClose) { + // When using custom close, we must leave a tappable region on the screen and just hide the image + // unless the ad is a vast video ad. For vast video, we expect that the creative will have a tappable + // close region. + if (self.isAdVastVideoPlayer) { + view.closeButtonType = MPClosableViewCloseButtonTypeNone; + } else { + view.closeButtonType = MPClosableViewCloseButtonTypeTappableWithoutImage; + } + } else { + // When not using custom close, show our own image with a tappable region. + view.closeButtonType = MPClosableViewCloseButtonTypeTappableWithImage; + } +} + +- (void)bridge:(MRBridge *)bridge handleNativeCommandSetOrientationPropertiesWithForceOrientationMask:(UIInterfaceOrientationMask)forceOrientationMask +{ + // If the ad is trying to force an orientation that the app doesn't support, we shouldn't try to force the orientation. + if (![[UIApplication sharedApplication] mp_supportsOrientationMask:forceOrientationMask]) { + return; + } + + BOOL inExpandedState = self.currentState == MRAdViewStateExpanded; + + // If we aren't expanded or showing an interstitial ad, we don't have to force orientation on our ad. + if (!inExpandedState && self.placementType != MRAdViewPlacementTypeInterstitial) { + return; + } + + // If request handling is paused, we want to queue up this method to be called again when they are re-enabled. + if (!bridge.shouldHandleRequests) { + __weak __typeof__(self) weakSelf = self; + self.forceOrientationAfterAnimationBlock = ^void() { + __typeof__(self) strongSelf = weakSelf; + [strongSelf bridge:bridge handleNativeCommandSetOrientationPropertiesWithForceOrientationMask:forceOrientationMask]; + }; + return; + } + + // By this point, we've committed to forcing the orientation so we don't need a forceOrientationAfterAnimationBlock. + self.forceOrientationAfterAnimationBlock = nil; + self.forceOrientationMask = forceOrientationMask; + + BOOL inSameOrientation = [[UIApplication sharedApplication] mp_doesOrientation:MPInterfaceOrientation() matchOrientationMask:forceOrientationMask]; + UIViewController *fullScreenAdViewController = inExpandedState ? self.expandModalViewController : self.interstitialViewController; + + // If we're currently in the force orientation, we don't need to do any rotation. However, we still need to make sure + // that the view controller knows to use the forced orientation when the user rotates the device. + if (inSameOrientation) { + fullScreenAdViewController.supportedOrientationMask = forceOrientationMask; + } else { + // It doesn't seem possible to force orientation in iOS 7+. So we dismiss the current view controller and re-present it with the forced orientation. + // If it's an expanded ad, we need to restore the status bar visibility before we dismiss the current VC since we don't show the status bar in expanded state. + if (inExpandedState) { + [self.expandModalViewController restoreStatusBarVisibility]; + } + + // Block our timer from updating properties while we force orientation on the view controller. + [self willBeginAnimatingAdSize]; + + UIViewController *presentingViewController = fullScreenAdViewController.presentingViewController; + __weak __typeof__(self) weakSelf = self; + [fullScreenAdViewController dismissViewControllerAnimated:NO completion:^{ + __typeof__(self) strongSelf = weakSelf; + + if (inExpandedState) { + [strongSelf didEndAnimatingAdSize]; + + // If expanded, we don't need to change the state of the ad once the modal is present here as the ad is technically + // always in the expanded state throughout the process of dismissing and presenting. + [strongSelf presentExpandModalViewControllerWithView:strongSelf.expansionContentView animated:NO completion:^{ + [strongSelf updateMRAIDProperties]; + }]; + } else { + fullScreenAdViewController.supportedOrientationMask = forceOrientationMask; + [presentingViewController presentViewController:fullScreenAdViewController animated:NO completion:^{ + [strongSelf didEndAnimatingAdSize]; + strongSelf.currentInterfaceOrientation = MPInterfaceOrientation(); + [strongSelf updateMRAIDProperties]; + }]; + } + }]; + } +} + +- (void)bridge:(MRBridge *)bridge handleNativeCommandExpandWithURL:(NSURL *)url useCustomClose:(BOOL)useCustomClose +{ + if (self.placementType != MRAdViewPlacementTypeInline) { + [bridge fireErrorEventForAction:kMRAIDCommandExpand withMessage:@"Cannot expand from interstitial ads."]; + return; + } + + // Save the state of the default ad view if it's in default state. If it's resized, the controller has already + // been informed of a modal being presented on resize, and the expand basically takes its place. Additionally, + // self.mraidDefaultAdFrame has already been set from resize, and the mraidAdView's frame is not the correct default. + if (self.currentState != MRAdViewStateResized) { + self.mraidDefaultAdFrame = self.mraidAdView.frame; + [self adWillPresentModalView]; + } else { + [self.resizeBackgroundView removeFromSuperview]; + } + + // We change the state after the modal is fully presented which results in an undesirable animation where the banner will briefly appear in the modal which then + // will instantly change to the full screen ad. However, it is far safer to update the state like this and has less side effects. + if (url) { + // It doesn't matter what frame we use for the two-part expand. We'll overwrite it with a new frame when presenting the modal. + CGRect twoPartFrame = self.mraidAdView.frame; + + MPWebView *twoPartWebView = [self buildMRAIDWebViewWithFrame:twoPartFrame forceUIWebView:self.shouldUseUIWebView]; + self.mraidBridgeTwoPart = [[MPInstanceProvider sharedProvider] buildMRBridgeWithWebView:twoPartWebView delegate:self]; + self.mraidAdViewTwoPart = [[MPInstanceProvider sharedProvider] buildMRAIDMPClosableViewWithFrame:twoPartFrame webView:twoPartWebView delegate:self]; + self.isAdLoading = YES; + + self.expansionContentView = self.mraidAdViewTwoPart; + + // To avoid race conditions, we start loading the two part creative after the ad has fully expanded. + [self presentExpandModalViewControllerWithView:self.expansionContentView animated:YES completion:^{ + [self initAdAlertManager:self.adAlertManagerTwoPart forAdView:self.mraidAdViewTwoPart]; + [self loadTwoPartCreativeFromURL:url]; + [self changeStateTo:MRAdViewStateExpanded]; + }]; + } else { + self.expansionContentView = self.mraidAdView; + //If the ad is resized, the original superview has already been set. + if (self.currentState != MRAdViewStateResized) { + self.originalSuperview = self.mraidAdView.superview; + } + [self presentExpandModalViewControllerWithView:self.expansionContentView animated:YES completion:^{ + [self changeStateTo:MRAdViewStateExpanded]; + }]; + } + + [self configureCloseButtonForView:self.expansionContentView forUseCustomClose:useCustomClose]; +} + +- (void)bridge:(MRBridge *)bridge handleNativeCommandResizeWithParameters:(NSDictionary *)parameters +{ + NSArray *parameterKeys = [parameters allKeys]; + if (self.currentState == MRAdViewStateExpanded) { + [bridge fireErrorEventForAction:kMRAIDCommandResize withMessage:@"Cannot resize from and expanded state."]; + return; + } else if (self.placementType != MRAdViewPlacementTypeInline) { + [bridge fireErrorEventForAction:kMRAIDCommandResize withMessage:@"Cannot resize from interstitial ads."]; + return; + } else if (![parameterKeys containsObject:@"width"] || ![parameterKeys containsObject:@"height"] || ![parameterKeys containsObject:@"offsetX"] || ![parameterKeys containsObject:@"offsetY"]) { + [bridge fireErrorEventForAction:kMRAIDCommandResize withMessage:@"Cannot resize when missing required parameter(s)."]; + return; + } + + CGFloat width = [[parameters objectForKey:@"width"] floatValue]; + CGFloat height = [[parameters objectForKey:@"height"] floatValue]; + CGFloat offsetX = [[parameters objectForKey:@"offsetX"] floatValue]; + CGFloat offsetY = [[parameters objectForKey:@"offsetY"] floatValue]; + BOOL allowOffscreen = [parameters objectForKey:@"allowOffscreen"] ? [[parameters objectForKey:@"allowOffscreen"] boolValue] : YES; + NSString *customClosePositionString = [[parameters objectForKey:@"customClosePosition"] length] ? [parameters objectForKey:@"customClosePosition"] : @"top-right"; + + //save default frame of the ad view + if (self.currentState == MRAdViewStateDefault) { + self.mraidDefaultAdFrameInKeyWindow = [self.mraidAdView.superview convertRect:self.mraidAdView.frame toView:MPKeyWindow().rootViewController.view]; + } + + CGRect newFrame = CGRectMake(CGRectGetMinX(self.mraidDefaultAdFrameInKeyWindow) + offsetX, CGRectGetMinY(self.mraidDefaultAdFrameInKeyWindow) + offsetY, width, height); + newFrame = [self adjustedFrameForFrame:newFrame allowOffscreen:allowOffscreen]; + + self.mraidAdView.closeButtonType = MPClosableViewCloseButtonTypeTappableWithoutImage; + self.mraidAdView.closeButtonLocation = [self adCloseButtonLocationFromString:customClosePositionString]; + + if (![self isValidResizeFrame:newFrame allowOffscreen:allowOffscreen]) { + [self.mraidBridge fireErrorEventForAction:kMRAIDCommandResize withMessage:@"Could not display desired frame in compliance with MRAID 2.0 specifications."]; + } else if (![self isValidResizeCloseButtonPlacementInFrame:newFrame]) { + [self.mraidBridge fireErrorEventForAction:kMRAIDCommandResize withMessage:@"Custom close event region is offscreen."]; + } else { + // If current state is default, save our current frame as the default frame, set originalSuperview, setup resizeBackgroundView, + // move mraidAdView to rootViewController's view, and call adWillPresentModalView + if (self.currentState == MRAdViewStateDefault) { + self.mraidDefaultAdFrame = self.mraidAdView.frame; + self.originalSuperview = self.mraidAdView.superview; + + self.mraidAdView.frame = self.mraidDefaultAdFrameInKeyWindow; + self.resizeBackgroundView.frame = MPApplicationFrame(); + + [MPKeyWindow().rootViewController.view addSubview:self.resizeBackgroundView]; + [MPKeyWindow().rootViewController.view addSubview:self.mraidAdView]; + + [self adWillPresentModalView]; + } + + [self animateViewFromDefaultStateToResizedState:self.mraidAdView withFrame:newFrame]; + } +} + +#pragma mark - + +- (void)closeButtonPressed:(MPClosableView *)view +{ + [self close]; +} + +- (void)closableView:(MPClosableView *)closableView didMoveToWindow:(UIWindow *)window +{ + // Fire the ready event and initialize properties if the view has a window. + MRBridge *bridge = [self bridgeForAdView:closableView]; + + if (!self.firedReadyEventForDefaultAd && bridge == self.mraidBridge) { + // The window may be nil if it was removed from a window or added to a view that isn't attached to a window so make sure it actually has a window. + if (window != nil) { + // Just in case this code is executed twice, ensures that self is only added as + // an observer once. + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; + + //Keep track of the orientation before we start observing changes. + self.currentInterfaceOrientation = MPInterfaceOrientation(); + + // Placing orientation notification observing here ensures that the controller only + // observes changes after it's been added to the view hierarchy. Subscribing to + // orientation changes so we can notify the javascript about the new screen size. + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(orientationDidChange:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; + + [self.adPropertyUpdateTimer scheduleNow]; + [self initializeLoadedAdForBridge:bridge]; + self.firedReadyEventForDefaultAd = YES; + } + } +} + +#pragma mark - + +- (void)displayAgentWillPresentModal +{ + [self adWillPresentModalView]; +} + +- (void)displayAgentDidDismissModal +{ + [self adDidDismissModalView]; +} + +- (void)displayAgentWillLeaveApplication +{ + // Do nothing. +} + +// - (MPAdConfiguration *)adConfiguration delegate method is automatically implemented via the adConfiguration property declaration. + +#pragma mark - Property Updating + +- (void)updateMRAIDProperties +{ + // Don't need to update mraid properties while animating as they'll be set correctly when the animations start/finish and it + // requires a bit of extra state logic to handle. We also don't want to check if the ad is visible during animation because + // the view is transitioning to a parent view that may or may not be on screen at any given time. + if (!self.isAnimatingAdSize) { + [self checkViewability]; + [self updateCurrentPosition]; + [self updateDefaultPosition]; + [self updateScreenSize]; + [self updateMaxSize]; + [self updateEventSizeChange]; + } +} + +- (CGRect)activeAdFrameInScreenSpace +{ + CGRect visibleFrame = CGRectZero; + + if (self.placementType == MRAdViewPlacementTypeInline) { + if (self.currentState == MRAdViewStateExpanded) { + // We're in a modal so we can just return the expanded view's frame. + visibleFrame = self.expansionContentView.frame; + } else { + UIWindow *keyWindow = MPKeyWindow(); + visibleFrame = [self.mraidAdView.superview convertRect:self.mraidAdView.frame toView:keyWindow.rootViewController.view]; + } + } else if (self.placementType == MRAdViewPlacementTypeInterstitial) { + visibleFrame = self.mraidAdView.frame; + } + + return visibleFrame; +} + +- (CGRect)defaultAdFrameInScreenSpace +{ + CGRect defaultFrame = CGRectZero; + + if (self.placementType == MRAdViewPlacementTypeInline) { + UIWindow *keyWindow = MPKeyWindow(); + if (self.expansionContentView == self.mraidAdViewTwoPart) { + defaultFrame = [self.mraidAdView.superview convertRect:self.mraidAdView.frame toView:keyWindow.rootViewController.view]; + } else { + defaultFrame = [self.originalSuperview convertRect:self.mraidDefaultAdFrame toView:keyWindow.rootViewController.view]; + } + } else if (self.placementType == MRAdViewPlacementTypeInterstitial) { + defaultFrame = self.mraidAdView.frame; + } + + return defaultFrame; +} + +- (void)updateCurrentPosition +{ + CGRect frame = [self activeAdFrameInScreenSpace]; + + // Only fire to the active ad view. + MRBridge *activeBridge = [self bridgeForActiveAdView]; + [activeBridge fireSetCurrentPositionWithPositionRect:frame]; + + MPLogTrace(@"Current Position: %@", NSStringFromCGRect(frame)); +} + +- (void)updateDefaultPosition +{ + CGRect defaultFrame = [self defaultAdFrameInScreenSpace]; + + // Not necessary to fire to both ad views, but it's better that the two-part expand knows the default position than not. + [self.mraidBridge fireSetDefaultPositionWithPositionRect:defaultFrame]; + [self.mraidBridgeTwoPart fireSetDefaultPositionWithPositionRect:defaultFrame]; + + MPLogTrace(@"Default Position: %@", NSStringFromCGRect(defaultFrame)); +} + +- (void)updateScreenSize +{ + // Fire an event for screen size changing. This includes the area of the status bar in its calculation. + CGSize screenSize = MPScreenBounds().size; + + // Fire to both ad views as it pertains to both views. + [self.mraidBridge fireSetScreenSize:screenSize]; + [self.mraidBridgeTwoPart fireSetScreenSize:screenSize]; + + MPLogTrace(@"Screen Size: %@", NSStringFromCGSize(screenSize)); +} + +- (void)updateMaxSize +{ + // Similar to updateScreenSize except this doesn't include the area of the status bar in its calculation. + CGSize maxSize = MPApplicationFrame().size; + + // Fire to both ad views as it pertains to both views. + [self.mraidBridge fireSetMaxSize:maxSize]; + [self.mraidBridgeTwoPart fireSetMaxSize:maxSize]; + + MPLogTrace(@"Max Size: %@", NSStringFromCGSize(maxSize)); +} + +#pragma mark - MRAID events + +- (void)updateEventSizeChange +{ + CGSize adSize = [self activeAdFrameInScreenSpace].size; + + // Firing the size change event will broadcast the event to the ad. The ad may subscribe to this event and + // perform some action when it receives the event. As a result, we don't want to have the ad do any work + // when the size hasn't changed. So we make sure we don't fire the size change event unless the size has + // actually changed. We don't place similar guards around updating properties that don't broadcast events + // since the ad won't be notified when we update the properties. Thus, the ad can't do any unnecessary work + // when we update other properties. + if (!CGSizeEqualToSize(adSize, self.currentAdSize)) { + MRBridge *activeBridge = [self bridgeForActiveAdView]; + self.currentAdSize = adSize; + + MPLogDebug(@"Ad Size (Size Event): %@", NSStringFromCGSize(self.currentAdSize)); + [activeBridge fireSizeChangeEvent:adSize]; + } +} + +- (void)changeStateTo:(MRAdViewState)state +{ + self.currentState = state; + + // Update the mraid properties so they're ready before the state change happens. + [self updateMRAIDProperties]; + [self fireChangeEventToBothBridgesForProperty:[MRStateProperty propertyWithState:self.currentState]]; +} + +#pragma mark - Viewability Helpers + +- (void)checkViewability +{ + BOOL viewable = MPViewIsVisible([self activeView]) && + ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive); + [self updateViewabilityWithBool:viewable]; +} + +- (void)viewEnteredBackground +{ + [self updateViewabilityWithBool:NO]; +} + +- (void)updateViewabilityWithBool:(BOOL)currentViewability +{ + if (self.isViewable != currentViewability) + { + MPLogDebug(@"Viewable changed to: %@", currentViewability ? @"YES" : @"NO"); + self.isViewable = currentViewability; + + // Both views in two-part expand need to report if they're viewable or not depending on the active one. + [self fireChangeEventToBothBridgesForProperty:[MRViewableProperty propertyWithViewable:self.isViewable]]; + } +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingMailVC +{ + return [self viewControllerForPresentingModalView]; +} + +- (void)adAlertManagerDidTriggerAlert:(MPAdAlertManager *)manager +{ + [manager processAdAlertOnce]; +} + +#pragma mark - Delegation Wrappers + +- (void)adDidLoad +{ + if ([self.delegate respondsToSelector:@selector(adDidLoad:)]) { + [self.delegate adDidLoad:self.mraidAdView]; + } +} + +- (void)adDidFailToLoad +{ + if ([self.delegate respondsToSelector:@selector(adDidFailToLoad:)]) { + [self.delegate adDidFailToLoad:self.mraidAdView]; + } +} + +- (void)adWillClose +{ + if ([self.delegate respondsToSelector:@selector(adWillClose:)]) { + [self.delegate adWillClose:self.mraidAdView]; + } +} + +- (void)adDidClose +{ + if ([self.delegate respondsToSelector:@selector(adDidClose:)]) { + [self.delegate adDidClose:self.mraidAdView]; + } +} + +- (void)adWillPresentModalView +{ + self.modalViewCount++; + if (self.modalViewCount == 1) { + [self appShouldSuspend]; + } +} + +- (void)adDidDismissModalView +{ + self.modalViewCount--; + if (self.modalViewCount == 0) { + [self appShouldResume]; + } +} + +- (void)appShouldSuspend +{ + if ([self.delegate respondsToSelector:@selector(appShouldSuspendForAd:)]) { + [self.delegate appShouldSuspendForAd:self.mraidAdView]; + } +} + +- (void)appShouldResume +{ + if ([self.delegate respondsToSelector:@selector(appShouldResumeFromAd:)]) { + [self.delegate appShouldResumeFromAd:self.mraidAdView]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.h new file mode 100644 index 000000000..eeb105395 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.h @@ -0,0 +1,15 @@ +// +// MRError.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +extern NSString * const MoPubMRAIDAdsSDKDomain; + +enum { + MRErrorMRAIDJSNotFound +}; +typedef NSInteger MRErrorCode; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.m new file mode 100644 index 000000000..6df5d883b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRError.m @@ -0,0 +1,10 @@ +// +// MRError.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MRError.h" + +NSString * const MoPubMRAIDAdsSDKDomain = @"com.mopub.iossdk.mraid"; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.h new file mode 100644 index 000000000..63cc829a3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.h @@ -0,0 +1,41 @@ +// +// MRExpandModalViewController.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import "MPClosableView.h" +#import "MPForceableOrientationProtocol.h" +@protocol MRExpandModalViewControllerDelegate; + +/** + * `MRExpandModalViewController` is specifically for presenting expanded MRAID ads. Its orientation can be + * forced via the orientationMask property. + */ +@interface MRExpandModalViewController : UIViewController + +/** + * Initializes the view controller with an orientation mask that defines what orientation + * the view controller supports. When using an orientation mask on initialization, the view controlller + * will force the orientation of the device to match the orientation mask if the app supports it. + */ +- (instancetype)initWithOrientationMask:(UIInterfaceOrientationMask)orientationMask; + +/** + * Hides the status bar when called. Every call to hideStatusBar should be matched with a call to + * restoreStatusBarVisibility. That is, each time hideStatusBar is called, restoreStatusBarVisibility + * must be called before calling hideStatusBar again. If the methods aren't called in the correct order, + * consecutive calls to this method become no ops. + */ +- (void)hideStatusBar; + +/** + * This will set the visibility of the status bar based on whether or not the status bar was hidden when hideStatusBar was called. + * A call to this method should be matched with a call to hideStatusBar. That is, each call to restoreStatusBarVisibility should + * be preceded by a call to hideStatusBar. Calling this method consecutively will not affect the status bar beyond the first call. + */ +- (void)restoreStatusBarVisibility; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.m new file mode 100644 index 000000000..1ec84cafc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRExpandModalViewController.m @@ -0,0 +1,110 @@ +// +// MRExpandModalViewController.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MRExpandModalViewController.h" +#import "MPGlobal.h" + +@interface MRExpandModalViewController () + +@property (nonatomic, assign) BOOL statusBarHidden; +@property (nonatomic, assign) BOOL applicationHidesStatusBar; +@property (nonatomic, assign) UIInterfaceOrientationMask supportedOrientationMask; + +@end + +@implementation MRExpandModalViewController + +- (instancetype)initWithOrientationMask:(UIInterfaceOrientationMask)orientationMask +{ + if (self = [super init]) { + _supportedOrientationMask = orientationMask; + } + + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = [UIColor blackColor]; +} + +- (void)hideStatusBar +{ + if (!self.statusBarHidden) { + self.statusBarHidden = YES; + self.applicationHidesStatusBar = [UIApplication sharedApplication].statusBarHidden; + + // pre-ios 7 hiding status bar + [[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:YES]; + + // In the event we come back to this view controller from another modal, we need to update the status bar's + // visibility again in ios 7/8. + if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { + [self setNeedsStatusBarAppearanceUpdate]; + } + } +} + +- (void)restoreStatusBarVisibility +{ + self.statusBarHidden = self.applicationHidesStatusBar; + + // pre-ios 7 restoring the status bar + [[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:self.applicationHidesStatusBar]; + + // ios 7/8 restoring status bar + if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { + [self setNeedsStatusBarAppearanceUpdate]; + } +} + +- (BOOL)prefersStatusBarHidden +{ + // ios 7 hiding status bar + return self.statusBarHidden; +} + +- (void)setSupportedOrientationMask:(UIInterfaceOrientationMask)supportedOrientationMask +{ + _supportedOrientationMask = supportedOrientationMask; + + [UIViewController attemptRotationToDeviceOrientation]; +} + +// supportedInterfaceOrientations and shouldAutorotate are for ios 6, 7, and 8. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_9_0 +- (UIInterfaceOrientationMask)supportedInterfaceOrientations +#else +- (NSUInteger)supportedInterfaceOrientations +#endif +{ + return ([[UIApplication sharedApplication] mp_supportsOrientationMask:self.supportedOrientationMask]) ? self.supportedOrientationMask : UIInterfaceOrientationMaskAll; +} + +- (BOOL)shouldAutorotate +{ + return YES; +} + +// shouldAutorotateToInterfaceOrientation is for ios 5. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return [[UIApplication sharedApplication] mp_doesOrientation:interfaceOrientation matchOrientationMask:self.supportedOrientationMask]; +} + +#pragma mark - + +// We transfer closable view delegation to the expand view controller in the event MRController is deallocated and the expand modal is presented. +- (void)closeButtonPressed:(MPClosableView *)closableView +{ + // All we need to do is dismiss ourself. + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.h new file mode 100644 index 000000000..656bf57a0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.h @@ -0,0 +1,49 @@ +// +// MRNativeCommandHandler.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MRConstants.h" + +@class MRCommand; +@protocol MRNativeCommandHandlerDelegate; + +/** + * The `MRNativeCommandHandler` class is an object that encapsulates functionality that processes, + * and where possible, executes MRAID commands. + */ +@interface MRNativeCommandHandler : NSObject + +- (instancetype)initWithDelegate:(id)delegate; +- (void)handleNativeCommand:(NSString *)command withProperties:(NSDictionary *)properties; + +@end + +/** + * The delegate of an `MRNativeCommandHandler` object that implements `MRNativeCommandHandlerDelegate` + * must provide information and a view controller that allow the `MRNativeCommandHandler` to execute + * MRAID commands. The `MRNativeCommandHandlerDelegate` is also notified of certain events and + * expected to respond appropriately to them. + */ +@protocol MRNativeCommandHandlerDelegate + +- (void)handleMRAIDUseCustomClose:(BOOL)useCustomClose; +- (void)handleMRAIDSetOrientationPropertiesWithForceOrientationMask:(UIInterfaceOrientationMask)forceOrientationMask; +- (void)handleMRAIDExpandWithParameters:(NSDictionary *)params; +- (void)handleMRAIDResizeWithParameters:(NSDictionary *)params; +- (void)handleMRAIDClose; +- (void)handleMRAIDOpenCallForURL:(NSURL *)URL; +- (void)nativeCommandWillPresentModalView; +- (void)nativeCommandDidDismissModalView; +- (void)nativeCommandCompleted:(NSString *)command; +- (void)nativeCommandFailed:(NSString *)command withMessage:(NSString *)message; +- (UIViewController *)viewControllerForPresentingModalView; +- (MRAdViewPlacementType)adViewPlacementType; +- (BOOL)userInteractedWithWebView; +- (BOOL)handlingWebviewRequests; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.m new file mode 100644 index 000000000..40dbb9695 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRNativeCommandHandler.m @@ -0,0 +1,136 @@ +// +// MRNativeCommandHandler.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MRNativeCommandHandler.h" +#import "MRCommand.h" +#import "MPGlobal.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MRVideoPlayerManager.h" + +@interface MRNativeCommandHandler () + +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) MRVideoPlayerManager *videoPlayerManager; + +@end + +@implementation MRNativeCommandHandler + +- (instancetype)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + _delegate = delegate; + + _videoPlayerManager = [[MPInstanceProvider sharedProvider] buildMRVideoPlayerManagerWithDelegate:self]; + } + + return self; +} + +- (void)handleNativeCommand:(NSString *)command withProperties:(NSDictionary *)properties +{ + BOOL success = YES; + + MRCommand *cmd = [MRCommand commandForString:command]; + if (cmd == nil) { + success = NO; + } else if ([self shouldExecuteMRCommand:cmd]) { + cmd.delegate = self; + success = [cmd executeWithParams:properties]; + } + + [self.delegate nativeCommandCompleted:command]; + + if (!success) { + MPLogDebug(@"Unknown command: %@", command); + [self.delegate nativeCommandFailed:command withMessage:@"Specified command is not implemented."]; + } +} + +- (BOOL)shouldExecuteMRCommand:(MRCommand *)cmd +{ + // The command may not be whitelisted to run while the delegate is not handling webview requests. + if (![self.delegate handlingWebviewRequests] && ![cmd executableWhileBlockingRequests]) { + return NO; + } + + // some MRAID commands may not require user interaction + return ![cmd requiresUserInteractionForPlacementType:[self.delegate adViewPlacementType]] || [self.delegate userInteractedWithWebView]; +} + +#pragma mark - MRCommandDelegate + +- (void)mrCommand:(MRCommand *)command createCalendarEventWithParams:(NSDictionary *)params +{ + // DEPRECATED +} + +- (void)mrCommand:(MRCommand *)command playVideoWithURL:(NSURL *)url +{ + [self.videoPlayerManager playVideo:url]; +} + +- (void)mrCommand:(MRCommand *)command storePictureWithURL:(NSURL *)url +{ + // DEPRECATED +} + +- (void)mrCommand:(MRCommand *)command shouldUseCustomClose:(BOOL)useCustomClose +{ + [self.delegate handleMRAIDUseCustomClose:useCustomClose]; +} + +- (void)mrCommand:(MRCommand *)command setOrientationPropertiesWithForceOrientation:(UIInterfaceOrientationMask)forceOrientation +{ + [self.delegate handleMRAIDSetOrientationPropertiesWithForceOrientationMask:forceOrientation]; +} + +- (void)mrCommand:(MRCommand *)command openURL:(NSURL *)url +{ + [self.delegate handleMRAIDOpenCallForURL:url]; +} + +- (void)mrCommand:(MRCommand *)command expandWithParams:(NSDictionary *)params +{ + [self.delegate handleMRAIDExpandWithParameters:params]; +} + +- (void)mrCommand:(MRCommand *)command resizeWithParams:(NSDictionary *)params +{ + [self.delegate handleMRAIDResizeWithParameters:params]; +} + +- (void)mrCommandClose:(MRCommand *)command +{ + [self.delegate handleMRAIDClose]; +} + +#pragma mark - + +- (void)videoPlayerManager:(MRVideoPlayerManager *)manager didFailToPlayVideoWithErrorMessage:(NSString *)message +{ + [self.delegate nativeCommandFailed:@"playVideo" withMessage:message]; +} + +- (void)videoPlayerManagerWillPresentVideo:(MRVideoPlayerManager *)manager +{ + [self.delegate nativeCommandWillPresentModalView]; +} + +- (void)videoPlayerManagerDidDismissVideo:(MRVideoPlayerManager *)manager +{ + [self.delegate nativeCommandDidDismissModalView]; +} + +- (UIViewController *)viewControllerForPresentingVideoPlayer +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.h new file mode 100644 index 000000000..6264849f9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.h @@ -0,0 +1,91 @@ +// +// MRProperty.h +// MoPub +// +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import +#import +#import "MRConstants.h" + +@interface MRProperty : NSObject + +- (NSString *)description; +- (NSString *)jsonString; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRHostSDKVersionProperty : MRProperty + +@property (nonatomic, copy) NSString *version; + ++ (MRHostSDKVersionProperty *)defaultProperty; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRPlacementTypeProperty : MRProperty { + MRAdViewPlacementType _placementType; +} + +@property (nonatomic, assign) MRAdViewPlacementType placementType; + ++ (MRPlacementTypeProperty *)propertyWithType:(MRAdViewPlacementType)type; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRStateProperty : MRProperty { + MRAdViewState _state; +} + +@property (nonatomic, assign) MRAdViewState state; + ++ (MRStateProperty *)propertyWithState:(MRAdViewState)state; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRScreenSizeProperty : MRProperty { + CGSize _screenSize; +} + +@property (nonatomic, assign) CGSize screenSize; + ++ (MRScreenSizeProperty *)propertyWithSize:(CGSize)size; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRSupportsProperty : MRProperty + +@property (nonatomic, assign) BOOL supportsSms; +@property (nonatomic, assign) BOOL supportsTel; +@property (nonatomic, assign) BOOL supportsCalendar; +@property (nonatomic, assign) BOOL supportsStorePicture; +@property (nonatomic, assign) BOOL supportsInlineVideo; + ++ (NSDictionary *)supportedFeatures; ++ (MRSupportsProperty *)defaultProperty; ++ (MRSupportsProperty *)propertyWithSupportedFeaturesDictionary:(NSDictionary *)dictionary; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MRViewableProperty : MRProperty { + BOOL _isViewable; +} + +@property (nonatomic, assign) BOOL isViewable; + ++ (MRViewableProperty *)propertyWithViewable:(BOOL)viewable; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.m new file mode 100644 index 000000000..e47b151a2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRProperty.m @@ -0,0 +1,193 @@ +// +// MRProperty.m +// MoPub +// +// Created by Andrew He on 12/13/11. +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import "MRProperty.h" +#import "MPConstants.h" +#import "MPCoreInstanceProvider.h" + +@implementation MRProperty + +- (NSString *)description { + return @""; +} + +- (NSString *)jsonString { + return @"{}"; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRHostSDKVersionProperty : MRProperty + +@synthesize version = _version; + ++ (instancetype)defaultProperty +{ + MRHostSDKVersionProperty *property = [[self alloc] init]; + property.version = MP_SDK_VERSION; + return property; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"hostSDKVersion: '%@'", self.version]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRPlacementTypeProperty : MRProperty + +@synthesize placementType = _placementType; + ++ (MRPlacementTypeProperty *)propertyWithType:(MRAdViewPlacementType)type { + MRPlacementTypeProperty *property = [[self alloc] init]; + property.placementType = type; + return property; +} + +- (NSString *)description { + NSString *placementTypeString = @"unknown"; + switch (_placementType) { + case MRAdViewPlacementTypeInline: placementTypeString = @"inline"; break; + case MRAdViewPlacementTypeInterstitial: placementTypeString = @"interstitial"; break; + default: break; + } + + return [NSString stringWithFormat:@"placementType: '%@'", placementTypeString]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRStateProperty + +@synthesize state = _state; + ++ (MRStateProperty *)propertyWithState:(MRAdViewState)state { + MRStateProperty *property = [[self alloc] init]; + property.state = state; + return property; +} + +- (NSString *)description { + NSString *stateString; + switch (_state) { + case MRAdViewStateHidden: + stateString = @"hidden"; + break; + case MRAdViewStateDefault: + stateString = @"default"; + break; + case MRAdViewStateExpanded: + stateString = @"expanded"; + break; + case MRAdViewStateResized: + stateString = @"resized"; + break; + default: + stateString = @"loading"; + break; + } + return [NSString stringWithFormat:@"state: '%@'", stateString]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRScreenSizeProperty : MRProperty + +@synthesize screenSize = _screenSize; + ++ (MRScreenSizeProperty *)propertyWithSize:(CGSize)size { + MRScreenSizeProperty *property = [[self alloc] init]; + property.screenSize = size; + return property; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"screenSize: {width: %f, height: %f}", + _screenSize.width, + _screenSize.height]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRSupportsProperty : MRProperty + ++ (NSDictionary *)supportedFeatures +{ + BOOL supportsSms, supportsTel; + supportsSms = supportsTel = [MPCoreInstanceProvider sharedProvider].sharedCarrierInfo[@"carrierName"] != nil; + + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:supportsSms], @"sms", + [NSNumber numberWithBool:supportsTel], @"tel", + [NSNumber numberWithBool:NO], @"calendar", + [NSNumber numberWithBool:NO], @"storePicture", + [NSNumber numberWithBool:YES], @"inlineVideo", + nil]; +} + ++ (MRSupportsProperty *)defaultProperty +{ + return [self propertyWithSupportedFeaturesDictionary:[self supportedFeatures]]; +} + ++ (MRSupportsProperty *)propertyWithSupportedFeaturesDictionary:(NSDictionary *)dictionary +{ + MRSupportsProperty *property = [[self alloc] init]; + property.supportsSms = [[dictionary objectForKey:@"sms"] boolValue]; + property.supportsTel = [[dictionary objectForKey:@"tel"] boolValue]; + property.supportsCalendar = NO; + property.supportsStorePicture = NO; + property.supportsInlineVideo = [[dictionary objectForKey:@"inlineVideo"] boolValue]; + return property; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"supports: {sms: %@, tel: %@, calendar: %@, storePicture: %@, inlineVideo: %@}", + [self javascriptBooleanStringFromBoolValue:self.supportsSms], + [self javascriptBooleanStringFromBoolValue:self.supportsTel], + [self javascriptBooleanStringFromBoolValue:self.supportsCalendar], + [self javascriptBooleanStringFromBoolValue:self.supportsStorePicture], + [self javascriptBooleanStringFromBoolValue:self.supportsInlineVideo]]; +} + +- (NSString *)javascriptBooleanStringFromBoolValue:(BOOL)value +{ + return value ? @"true" : @"false"; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MRViewableProperty : MRProperty + +@synthesize isViewable = _isViewable; + ++ (MRViewableProperty *)propertyWithViewable:(BOOL)viewable { + MRViewableProperty *property = [[self alloc] init]; + property.isViewable = viewable; + return property; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"viewable: %@", _isViewable ? @"true" : @"false"]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.h new file mode 100644 index 000000000..373f327df --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.h @@ -0,0 +1,26 @@ +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@protocol MRVideoPlayerManagerDelegate; + +@interface MRVideoPlayerManager : NSObject + +@property (nonatomic, weak) id delegate; + +- (id)initWithDelegate:(id)delegate; +- (void)playVideo:(NSURL *)url; + +@end + +@protocol MRVideoPlayerManagerDelegate + +- (UIViewController *)viewControllerForPresentingVideoPlayer; +- (void)videoPlayerManagerWillPresentVideo:(MRVideoPlayerManager *)manager; +- (void)videoPlayerManagerDidDismissVideo:(MRVideoPlayerManager *)manager; +- (void)videoPlayerManager:(MRVideoPlayerManager *)manager + didFailToPlayVideoWithErrorMessage:(NSString *)message; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.m new file mode 100644 index 000000000..7f144ccd9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/MRAID/MRVideoPlayerManager.m @@ -0,0 +1,57 @@ +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MRVideoPlayerManager.h" +#import +#import "MPInstanceProvider.h" + +@implementation MRVideoPlayerManager + +@synthesize delegate = _delegate; + +- (id)initWithDelegate:(id)delegate +{ + self = [super init]; + if (self) { + _delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:MPMoviePlayerPlaybackDidFinishNotification + object:nil]; +} + +- (void)playVideo:(NSURL *)url +{ + if (!url) { + [self.delegate videoPlayerManager:self didFailToPlayVideoWithErrorMessage:@"URI was not valid."]; + return; + } + + MPMoviePlayerViewController *controller = [[MPInstanceProvider sharedProvider] buildMPMoviePlayerViewControllerWithURL:url]; + + [self.delegate videoPlayerManagerWillPresentVideo:self]; + [[self.delegate viewControllerForPresentingVideoPlayer] presentViewController:controller animated:MP_ANIMATED completion:nil]; + + // Avoid subscribing to the notification multiple times in the event the user plays the video more than once. + [[NSNotificationCenter defaultCenter] removeObserver:self + name:MPMoviePlayerPlaybackDidFinishNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(moviePlayerPlaybackDidFinish:) + name:MPMoviePlayerPlaybackDidFinishNotification + object:nil]; +} + +- (void)moviePlayerPlaybackDidFinish:(NSNotification *)notification +{ + [self.delegate videoPlayerManagerDidDismissVideo:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.h new file mode 100644 index 000000000..780314a3e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.h @@ -0,0 +1,19 @@ +// +// NSBundle+MPAdditions.h +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import + +@interface NSBundle (MPAdditions) + +/** + * Retrieves the bundle that contains the MoPubSDK resources. + * @param aClass MoPub class. Typically will be self.class. + * @returns The bundle containing the MoPubSDK resources. + */ ++ (NSBundle *)resourceBundleForClass:(Class)aClass; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.m new file mode 100644 index 000000000..fcb3ff55a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSBundle+MPAdditions.m @@ -0,0 +1,17 @@ +// +// NSBundle+MPAdditions.m +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "NSBundle+MPAdditions.h" + +@implementation NSBundle (MPAdditions) + ++ (NSBundle *)resourceBundleForClass:(Class)aClass { + NSString * resourceBundlePath = [[NSBundle mainBundle] pathForResource:@"MoPub" ofType:@"bundle"]; + return (resourceBundlePath != nil ? [NSBundle bundleWithPath:resourceBundlePath] : [NSBundle bundleForClass:aClass]); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.h new file mode 100644 index 000000000..76f041c49 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.h @@ -0,0 +1,16 @@ +// +// NSHTTPURLResponse+MPAdditions.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +extern NSString * const kMoPubHTTPHeaderContentType; + +@interface NSHTTPURLResponse (MPAdditions) + +- (NSStringEncoding)stringEncodingFromContentType:(NSString *)contentType; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.m new file mode 100644 index 000000000..f9b40770b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSHTTPURLResponse+MPAdditions.m @@ -0,0 +1,44 @@ +// +// NSHTTPURLResponse+MPAdditions.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "NSHTTPURLResponse+MPAdditions.h" +#import "MPLogging.h" + +NSString * const kMoPubHTTPHeaderContentType = @"Content-Type"; + +@implementation NSHTTPURLResponse (MPAdditions) + +- (NSStringEncoding)stringEncodingFromContentType:(NSString *)contentType +{ + NSStringEncoding encoding = NSUTF8StringEncoding; + + if (![contentType length]) { + MPLogWarn(@"Attempting to set string encoding from nil %@", kMoPubHTTPHeaderContentType); + return encoding; + } + + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=charset=)[^;]*" options:kNilOptions error:nil]; + + NSTextCheckingResult *charsetResult = [regex firstMatchInString:contentType options:kNilOptions range:NSMakeRange(0, [contentType length])]; + if (charsetResult && charsetResult.range.location != NSNotFound) { + NSString *charset = [contentType substringWithRange:[charsetResult range]]; + + // ensure that charset is not deallocated early + CFStringRef cfCharset = (CFStringRef)CFBridgingRetain(charset); + CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding(cfCharset); + CFBridgingRelease(cfCharset); + + if (cfEncoding == kCFStringEncodingInvalidId) { + return encoding; + } + encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); + } + + return encoding; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.h new file mode 100644 index 000000000..106388a10 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.h @@ -0,0 +1,14 @@ +// +// NSJSONSerialization+MPAdditions.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@interface NSJSONSerialization (MPAdditions) + ++ (id)mp_JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt clearNullObjects:(BOOL)clearNulls error:(NSError **)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.m new file mode 100644 index 000000000..1dd193429 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSJSONSerialization+MPAdditions.m @@ -0,0 +1,93 @@ +// +// NSJSONSerialization+MPAdditions.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "NSJSONSerialization+MPAdditions.h" + +@interface NSMutableDictionary (RemoveNullObjects) + +- (void)mp_removeNullsRecursively; + +@end + +@interface NSMutableArray (RemoveNullObjects) + +- (void)mp_removeNullsRecursively; + +@end + +@implementation NSJSONSerialization (MPAdditions) + ++ (id)mp_JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt clearNullObjects:(BOOL)clearNulls error:(NSError **)error +{ + if (clearNulls) { + opt |= NSJSONReadingMutableContainers; + } + + id JSONObject = [NSJSONSerialization JSONObjectWithData:data options:opt error:error]; + + if (error || !clearNulls) { + return JSONObject; + } + + [JSONObject mp_removeNullsRecursively]; + + return JSONObject; +} + +@end + +@implementation NSMutableDictionary (RemovingNulls) + +-(void)mp_removeNullsRecursively +{ + // First, filter out directly stored nulls + NSMutableArray *nullKeys = [NSMutableArray array]; + NSMutableArray *arrayKeys = [NSMutableArray array]; + NSMutableArray *dictionaryKeys = [NSMutableArray array]; + + [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + if ([obj isEqual:[NSNull null]]) { + [nullKeys addObject:key]; + } else if ([obj isKindOfClass:[NSDictionary class]]) { + [dictionaryKeys addObject:key]; + } else if ([obj isKindOfClass:[NSArray class]]) { + [arrayKeys addObject:key]; + } + }]; + + // Remove all the nulls + [self removeObjectsForKeys:nullKeys]; + + // Cascade down the dictionaries + for (id dictionaryKey in dictionaryKeys) { + NSMutableDictionary *dictionary = [self objectForKey:dictionaryKey]; + [dictionary mp_removeNullsRecursively]; + } + + // Recursively remove nulls from arrays + for (id arrayKey in arrayKeys) { + NSMutableArray *array = [self objectForKey:arrayKey]; + [array mp_removeNullsRecursively]; + } +} + +@end + +@implementation NSMutableArray (RemovingNulls) + +-(void)mp_removeNullsRecursively +{ + [self removeObjectIdenticalTo:[NSNull null]]; + + for (id object in self) { + if ([object respondsToSelector:@selector(mp_removeNullsRecursively)]) { + [(NSMutableDictionary *)object mp_removeNullsRecursively]; + } + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.h new file mode 100644 index 000000000..f66bb525e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.h @@ -0,0 +1,37 @@ +// +// NSURL+MPAdditions.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +typedef enum { + MPMoPubHostCommandUnrecognized, + MPMoPubHostCommandClose, + MPMoPubHostCommandFinishLoad, + MPMoPubHostCommandFailLoad, + MPMoPubHostCommandPrecacheComplete, + MPMoPubHostCommandRewardedVideoEnded +} MPMoPubHostCommand; + +typedef enum { + MPMoPubShareHostCommandTweet, + MPMoPubShareHostCommandUnrecognized +} MPMoPubShareHostCommand; + +@interface NSURL (MPAdditions) + +- (NSString *)mp_queryParameterForKey:(NSString *)key; +- (NSArray *)mp_queryParametersForKey:(NSString *)key; +- (NSDictionary *)mp_queryAsDictionary; +- (BOOL)mp_hasTelephoneScheme; +- (BOOL)mp_hasTelephonePromptScheme; +- (BOOL)mp_isSafeForLoadingWithoutUserAction; +- (BOOL)mp_isMoPubScheme; +- (MPMoPubHostCommand)mp_mopubHostCommand; +- (BOOL)mp_isMoPubShareScheme; +- (MPMoPubShareHostCommand)mp_MoPubShareHostCommand; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.m new file mode 100644 index 000000000..86a8abca4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/NSURL+MPAdditions.m @@ -0,0 +1,131 @@ +// +// NSURL+MPAdditions.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "NSURL+MPAdditions.h" + +static NSString * const kTelephoneScheme = @"tel"; +static NSString * const kTelephonePromptScheme = @"telprompt"; + +// Share Constants +static NSString * const kMoPubShareScheme = @"mopubshare"; +static NSString * const kMoPubShareTweetHost = @"tweet"; + +// Commands Constants +static NSString * const kMoPubURLScheme = @"mopub"; +static NSString * const kMoPubCloseHost = @"close"; +static NSString * const kMoPubFinishLoadHost = @"finishLoad"; +static NSString * const kMoPubFailLoadHost = @"failLoad"; +static NSString * const kMoPubPrecacheCompleteHost = @"precacheComplete"; +static NSString * const kMoPubRewardedVideoEndedHost = @"rewardedVideoEnded"; + +@implementation NSURL (MPAdditions) + +- (NSString *)mp_queryParameterForKey:(NSString *)key +{ + NSArray *queryElements = [self.query componentsSeparatedByString:@"&"]; + for (NSString *element in queryElements) { + NSArray *keyAndValue = [element componentsSeparatedByString:@"="]; + if (keyAndValue.count >= 2 && + [[keyAndValue objectAtIndex:0] isEqualToString:key] && + [[keyAndValue objectAtIndex:1] length] > 0) { + return [[keyAndValue objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + } + } + return nil; +} + +- (NSArray *)mp_queryParametersForKey:(NSString *)key +{ + NSMutableArray *matchingParameters = [NSMutableArray array]; + NSArray *queryElements = [self.query componentsSeparatedByString:@"&"]; + for (NSString *element in queryElements) { + NSArray *keyAndValue = [element componentsSeparatedByString:@"="]; + if (keyAndValue.count >= 2 && + [[keyAndValue objectAtIndex:0] isEqualToString:key] && + [[keyAndValue objectAtIndex:1] length] > 0) { + [matchingParameters addObject:[[keyAndValue objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + } + } + return [NSArray arrayWithArray:matchingParameters]; +} + +- (NSDictionary *)mp_queryAsDictionary +{ + NSMutableDictionary *queryDict = [NSMutableDictionary dictionary]; + NSArray *queryElements = [self.query componentsSeparatedByString:@"&"]; + for (NSString *element in queryElements) { + NSArray *keyVal = [element componentsSeparatedByString:@"="]; + if (keyVal.count >= 2) { + NSString *key = [keyVal objectAtIndex:0]; + NSString *value = [keyVal objectAtIndex:1]; + [queryDict setObject:[value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + forKey:key]; + } + } + return queryDict; +} + +- (BOOL)mp_hasTelephoneScheme +{ + return [[[self scheme] lowercaseString] isEqualToString:kTelephoneScheme]; +} + +- (BOOL)mp_hasTelephonePromptScheme +{ + return [[[self scheme] lowercaseString] isEqualToString:kTelephonePromptScheme]; +} + +- (BOOL)mp_isSafeForLoadingWithoutUserAction +{ + return [[self scheme].lowercaseString isEqualToString:@"http"] || + [[self scheme].lowercaseString isEqualToString:@"https"] || + [[self scheme].lowercaseString isEqualToString:@"about"]; +} + +- (BOOL)mp_isMoPubScheme +{ + return [[self scheme] isEqualToString:kMoPubURLScheme]; +} + +- (MPMoPubShareHostCommand)mp_MoPubShareHostCommand +{ + NSString *host = [self host]; + if (![self mp_isMoPubShareScheme]) { + return MPMoPubShareHostCommandUnrecognized; + } else if ([host isEqualToString:kMoPubShareTweetHost]) { + return MPMoPubShareHostCommandTweet; + } else { + return MPMoPubShareHostCommandUnrecognized; + } +} + +- (MPMoPubHostCommand)mp_mopubHostCommand +{ + NSString *host = [self host]; + if (![self mp_isMoPubScheme]) { + return MPMoPubHostCommandUnrecognized; + } else if ([host isEqualToString:kMoPubCloseHost]) { + return MPMoPubHostCommandClose; + } else if ([host isEqualToString:kMoPubFinishLoadHost]) { + return MPMoPubHostCommandFinishLoad; + } else if ([host isEqualToString:kMoPubFailLoadHost]) { + return MPMoPubHostCommandFailLoad; + } else if ([host isEqualToString:kMoPubPrecacheCompleteHost]) { + return MPMoPubHostCommandPrecacheComplete; + } else if ([host isEqualToString:kMoPubRewardedVideoEndedHost]) { + return MPMoPubHostCommandRewardedVideoEnded; + } else { + return MPMoPubHostCommandUnrecognized; + } +} + +- (BOOL)mp_isMoPubShareScheme +{ + return [[self scheme] isEqualToString:kMoPubShareScheme]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.h new file mode 100644 index 000000000..6dcf8411e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.h @@ -0,0 +1,12 @@ +// +// UIButton+MPAdditions.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface UIButton (MPAdditions) + +@property (nonatomic) UIEdgeInsets mp_TouchAreaInsets; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.m new file mode 100644 index 000000000..9a49ecb3d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIButton+MPAdditions.m @@ -0,0 +1,33 @@ +// +// UIButton+MPAdditions.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "UIButton+MPAdditions.h" +#import + +@implementation UIButton (MPAdditions) + +- (UIEdgeInsets)mp_TouchAreaInsets +{ + return [objc_getAssociatedObject(self, @selector(mp_TouchAreaInsets)) UIEdgeInsetsValue]; +} + +- (void)setMp_TouchAreaInsets:(UIEdgeInsets)touchAreaInsets +{ + NSValue *value = [NSValue valueWithUIEdgeInsets:touchAreaInsets]; + objc_setAssociatedObject(self, @selector(mp_TouchAreaInsets), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event +{ + UIEdgeInsets touchAreaInsets = self.mp_TouchAreaInsets; + CGRect bounds = self.bounds; + bounds = CGRectMake(bounds.origin.x - touchAreaInsets.left, + bounds.origin.y - touchAreaInsets.top, + bounds.size.width + touchAreaInsets.left + touchAreaInsets.right, + bounds.size.height + touchAreaInsets.top + touchAreaInsets.bottom); + return CGRectContainsPoint(bounds, point); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.h new file mode 100644 index 000000000..02ff51c88 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.h @@ -0,0 +1,12 @@ +// +// UIColor+MPAdditions.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface UIColor (MPAdditions) + ++ (UIColor *)mp_colorFromHexString:(NSString *)hexString alpha:(CGFloat)alpha; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.m new file mode 100644 index 000000000..bc5e5d7fa --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIColor+MPAdditions.m @@ -0,0 +1,19 @@ +// +// UIColor+MPAdditions.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "UIColor+MPAdditions.h" + +@implementation UIColor (MPAdditions) + ++ (UIColor *)mp_colorFromHexString:(NSString *)hexString alpha:(CGFloat)alpha +{ + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; // bypass '#' character + [scanner scanHexInt:&rgbValue]; + return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:alpha]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.h new file mode 100644 index 000000000..6b4ea348b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.h @@ -0,0 +1,25 @@ +// +// UIView+MPAdditions.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface UIView (MPAdditions) + +@property (nonatomic) CGFloat mp_x; +@property (nonatomic) CGFloat mp_y; +@property (nonatomic) CGFloat mp_height; +@property (nonatomic) CGFloat mp_width; + +- (void)setMp_x:(CGFloat)mp_x; +- (void)setMp_y:(CGFloat)mp_y; +- (void)setMp_width:(CGFloat)mp_width; +- (void)setMp_height:(CGFloat)mp_height; + +- (UIView *)mp_snapshotView; + +// convert any UIView to UIImage view. We can apply blur effect on UIImage. +- (UIImage *)mp_snapshot:(BOOL)usePresentationLayer; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.m new file mode 100644 index 000000000..3420d8b25 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIView+MPAdditions.m @@ -0,0 +1,97 @@ +// +// UIView+MPAdditions.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "UIView+MPAdditions.h" + +@implementation UIView (Helper) + +- (CGFloat)mp_x +{ + return self.frame.origin.x; +} + +- (CGFloat)mp_y +{ + return self.frame.origin.y; +} + +- (CGFloat)mp_width +{ + return self.frame.size.width; +} + +- (CGFloat)mp_height +{ + return self.frame.size.height; +} + +- (void)setMp_x:(CGFloat)mp_x +{ + [self setX:mp_x andY:self.frame.origin.y]; +} + +- (void)setMp_y:(CGFloat)mp_y +{ + [self setX:self.frame.origin.x andY:mp_y]; +} + +- (void)setX:(CGFloat)x andY:(CGFloat)y +{ + CGRect f = self.frame; + self.frame = CGRectMake(x, y, f.size.width, f.size.height); +} + + +- (void)setMp_width:(CGFloat)mp_width +{ + CGRect frame = self.frame; + frame.size.width = mp_width; + self.frame = frame; +} + +- (void)setMp_height:(CGFloat)mp_height +{ + CGRect frame = self.frame; + frame.size.height = mp_height; + self.frame = frame; +} + +- (UIView *)mp_snapshotView +{ + CGRect rect = self.bounds; + UIGraphicsBeginImageContextWithOptions(rect.size, NO, self.window.screen.scale); + UIView *snapshotView; + if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) { + snapshotView = [self snapshotViewAfterScreenUpdates:NO]; + } else { + CGContextRef ctx = UIGraphicsGetCurrentContext(); + [self.layer renderInContext:ctx]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + snapshotView = [[UIImageView alloc] initWithImage:image]; + } + UIGraphicsEndImageContext(); + return snapshotView; +} + +- (UIImage *)mp_snapshot:(BOOL)usePresentationLayer +{ + CGRect rect = self.bounds; + UIGraphicsBeginImageContextWithOptions(rect.size, NO, self.window.screen.scale); + if (!usePresentationLayer && [self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { + [self drawViewHierarchyInRect:rect afterScreenUpdates:NO]; + } else { + CGContextRef ctx = UIGraphicsGetCurrentContext(); + if (usePresentationLayer) { + [self.layer.presentationLayer renderInContext:ctx]; + } else { + [self.layer renderInContext:ctx]; + } + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.h new file mode 100644 index 000000000..3ffde6134 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.h @@ -0,0 +1,19 @@ +// +// UIWebView+MPAdditions.h +// MoPub +// +// Created by Andrew He on 11/6/11. +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import +#import + +extern NSString *const kJavaScriptDisableDialogSnippet; + +@interface UIWebView (MPAdditions) + +- (void)mp_setScrollable:(BOOL)scrollable; +- (void)disableJavaScriptDialogs; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.m new file mode 100644 index 000000000..0a1157327 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/Categories/UIWebView+MPAdditions.m @@ -0,0 +1,51 @@ +// +// UIWebView+MPAdditions.m +// MoPub +// +// Created by Andrew He on 11/6/11. +// Copyright (c) 2011 MoPub, Inc. All rights reserved. +// + +#import "UIWebView+MPAdditions.h" + +NSString *const kJavaScriptDisableDialogSnippet = @"window.alert = function() { }; window.prompt = function() { }; window.confirm = function() { };"; + +@implementation UIWebView (MPAdditions) + +/* + * Find all subviews that are UIScrollViews or subclasses and set their scrolling and bounce. + */ +- (void)mp_setScrollable:(BOOL)scrollable { + #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000 // iOS 5.0+ + if ([self respondsToSelector:@selector(scrollView)]) + { + UIScrollView *scrollView = self.scrollView; + scrollView.scrollEnabled = scrollable; + scrollView.bounces = scrollable; + } + else + #endif + { + UIScrollView *scrollView = nil; + for (UIView *v in self.subviews) + { + if ([v isKindOfClass:[UIScrollView class]]) + { + scrollView = (UIScrollView *)v; + break; + } + } + scrollView.scrollEnabled = scrollable; + scrollView.bounces = scrollable; + } +} + +/* + * Redefine alert, prompt, and confirm to do nothing + */ +- (void)disableJavaScriptDialogs +{ + [self stringByEvaluatingJavaScriptFromString:kJavaScriptDisableDialogSnippet]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.h new file mode 100644 index 000000000..422c405ac --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.h @@ -0,0 +1,20 @@ +// +// MPAnalyticsTracker.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@class MPAdConfiguration; + +@interface MPAnalyticsTracker : NSObject + ++ (MPAnalyticsTracker *)tracker; + +- (void)trackImpressionForConfiguration:(MPAdConfiguration *)configuration; +- (void)trackClickForConfiguration:(MPAdConfiguration *)configuration; +- (void)sendTrackingRequestForURLs:(NSArray *)URLs; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.m new file mode 100644 index 000000000..adf0b6953 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPAnalyticsTracker.m @@ -0,0 +1,55 @@ +// +// MPAnalyticsTracker.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPAnalyticsTracker.h" +#import "MPAdConfiguration.h" +#import "MPCoreInstanceProvider.h" +#import "MPLogging.h" + +@interface MPAnalyticsTracker () + +- (NSURLRequest *)requestForURL:(NSURL *)URL; + +@end + +@implementation MPAnalyticsTracker + ++ (MPAnalyticsTracker *)tracker +{ + return [[MPAnalyticsTracker alloc] init]; +} + +- (void)trackImpressionForConfiguration:(MPAdConfiguration *)configuration +{ + MPLogDebug(@"Tracking impression: %@", configuration.impressionTrackingURL); + [NSURLConnection connectionWithRequest:[self requestForURL:configuration.impressionTrackingURL] + delegate:nil]; +} + +- (void)trackClickForConfiguration:(MPAdConfiguration *)configuration +{ + MPLogDebug(@"Tracking click: %@", configuration.clickTrackingURL); + [NSURLConnection connectionWithRequest:[self requestForURL:configuration.clickTrackingURL] + delegate:nil]; +} + +- (void)sendTrackingRequestForURLs:(NSArray *)URLs +{ + for (NSURL *URL in URLs) { + NSURLRequest *trackingRequest = [self requestForURL:URL]; + [NSURLConnection connectionWithRequest:trackingRequest delegate:nil]; + } +} + +- (NSURLRequest *)requestForURL:(NSURL *)URL +{ + NSMutableURLRequest *request = [[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:URL]; + request.cachePolicy = NSURLRequestReloadIgnoringCacheData; + return request; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.h new file mode 100644 index 000000000..1c72ddb81 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.h @@ -0,0 +1,27 @@ +// +// MPError.h +// MoPub +// +// Copyright (c) 2012 MoPub. All rights reserved. +// + +#import + +extern NSString * const kMOPUBErrorDomain; + +typedef enum { + MOPUBErrorUnknown = -1, + MOPUBErrorNoInventory = 0, + MOPUBErrorAdUnitWarmingUp = 1, + MOPUBErrorNetworkTimedOut = 4, + MOPUBErrorServerError = 8, + MOPUBErrorAdapterNotFound = 16, + MOPUBErrorAdapterInvalid = 17, + MOPUBErrorAdapterHasNoInventory = 18 +} MOPUBErrorCode; + +@interface MOPUBError : NSError + ++ (MOPUBError *)errorWithCode:(MOPUBErrorCode)code; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.m new file mode 100644 index 000000000..a41c28469 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPError.m @@ -0,0 +1,19 @@ +// +// MPError.m +// MoPub +// +// Copyright (c) 2012 MoPub. All rights reserved. +// + +#import "MPError.h" + +NSString * const kMOPUBErrorDomain = @"com.mopub.iossdk"; + +@implementation MOPUBError + ++ (MOPUBError *)errorWithCode:(MOPUBErrorCode)code +{ + return [self errorWithDomain:kMOPUBErrorDomain code:code userInfo:nil]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.h new file mode 100644 index 000000000..5fae5347f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.h @@ -0,0 +1,31 @@ +// +// MPGeolocationProvider.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import + +@interface MPGeolocationProvider : NSObject + +/** + * Returns the shared instance of the `MPGeolocationProvider` class. + * + * @return The shared instance of the `MPGeolocationProvider` class. + */ ++ (instancetype)sharedProvider; + +/** + * The most recent location determined by the location provider. + */ +@property (nonatomic, readonly) CLLocation *lastKnownLocation; + +/** + * Determines whether the location provider should attempt to listen for location updates. The + * default value is YES. + */ +@property (nonatomic, assign) BOOL locationUpdatesEnabled; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.m new file mode 100644 index 000000000..753735f82 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGeolocationProvider.m @@ -0,0 +1,297 @@ +// +// MPGeolocationProvider.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPGeolocationProvider.h" + +#import "MPCoreInstanceProvider.h" +#import "MPIdentityProvider.h" +#import "MPLogging.h" +#import "MPTimer.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// The minimum distance (meters) a device must move horizontally before CLLocationManager generates +// an update event. Used to limit the amount of events generated. +const CLLocationDistance kMPCityBlockDistanceFilter = 100.0; + +// The duration (seconds) for which we want to listen for location updates (i.e. how long we wait to +// call -stopUpdatingLocation after calling -startUpdatingLocation). +const NSTimeInterval kMPLocationUpdateDuration = 15.0; + +// The duration (seconds) between calls to -startUpdatingLocation. +const NSTimeInterval kMPLocationUpdateInterval = 10.0 * 60.0; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPGeolocationProvider () + +@property (nonatomic, readwrite) CLLocation *lastKnownLocation; +@property (nonatomic) CLLocationManager *locationManager; +@property (nonatomic) BOOL authorizedForLocationServices; +@property (nonatomic) NSDate *timeOfLastLocationUpdate; +@property (nonatomic) MPTimer *nextLocationUpdateTimer; +@property (nonatomic) MPTimer *locationUpdateDurationTimer; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPGeolocationProvider + ++ (instancetype)sharedProvider +{ + static MPGeolocationProvider *sharedProvider = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedProvider = [[[self class] alloc] init]; + }); + return sharedProvider; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _locationUpdatesEnabled = YES; + + _locationManager = [[MPCoreInstanceProvider sharedProvider] buildCLLocationManager]; + _locationManager.delegate = self; + _locationManager.distanceFilter = kMPCityBlockDistanceFilter; + + // CLLocationManager's `location` property may already contain location data upon + // initialization (for example, if the application uses significant location updates). + CLLocation *existingLocation = _locationManager.location; + if ([self locationHasValidCoordinates:existingLocation]) { + _lastKnownLocation = existingLocation; + MPLogDebug(@"Found previous location information."); + } + + // Avoid processing location updates when the application enters the background. + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + [self stopAllCurrentOrScheduledLocationUpdates]; + }]; + + // Re-activate location updates when the application comes back to the foreground. + [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + if (_locationUpdatesEnabled) { + [self resumeLocationUpdatesAfterBackgrounding]; + } + }]; + + [self startRecurringLocationUpdates]; + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]]; +} + +#pragma mark - Public + +- (CLLocation *)lastKnownLocation +{ + if (!self.locationUpdatesEnabled) { + return nil; + } + + return _lastKnownLocation; +} + +- (void)setLocationUpdatesEnabled:(BOOL)enabled +{ + _locationUpdatesEnabled = enabled; + + if (!_locationUpdatesEnabled) { + [self stopAllCurrentOrScheduledLocationUpdates]; + self.lastKnownLocation = nil; + } else if (![self.locationUpdateDurationTimer isValid] && ![self.nextLocationUpdateTimer isValid]) { + [self startRecurringLocationUpdates]; + } +} + +#pragma mark - Internal + +- (void)setAuthorizedForLocationServices:(BOOL)authorizedForLocationServices +{ + _authorizedForLocationServices = authorizedForLocationServices; + + if (_authorizedForLocationServices && [CLLocationManager locationServicesEnabled]) { + [self startRecurringLocationUpdates]; + } else { + [self stopAllCurrentOrScheduledLocationUpdates]; + self.lastKnownLocation = nil; + } +} + +- (BOOL)isAuthorizedStatus:(CLAuthorizationStatus)status +{ +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + return (status == kCLAuthorizationStatusAuthorizedAlways) || (status == kCLAuthorizationStatusAuthorizedWhenInUse); +#else + return status == kCLAuthorizationStatusAuthorized; +#endif +} + +/** + * Tells the location provider to start periodically retrieving new location data. + * + * The location provider will activate its underlying location manager for a specified amount of + * time, during which the provider may receive delegate callbacks about location updates. After this + * duration, the provider will schedule a future update. These updates can be stopped via + * -stopAllCurrentOrScheduledLocationUpdates. + */ +- (void)startRecurringLocationUpdates +{ + self.timeOfLastLocationUpdate = [NSDate date]; + + if (![CLLocationManager locationServicesEnabled] || ![self isAuthorizedStatus:[CLLocationManager authorizationStatus]]) { + MPLogDebug(@"Will not start location updates: the application is not authorized " + @"for location services."); + return; + } + + if (!_locationUpdatesEnabled) { + MPLogDebug(@"Will not start location updates because they have been disabled."); + return; + } + + [self.locationManager startUpdatingLocation]; + + [self.locationUpdateDurationTimer invalidate]; + self.locationUpdateDurationTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:kMPLocationUpdateDuration target:self selector:@selector(currentLocationUpdateDidFinish) repeats:NO]; + [self.locationUpdateDurationTimer scheduleNow]; +} + +- (void)currentLocationUpdateDidFinish +{ + MPLogDebug(@"Stopping the current location update session and scheduling the next session."); + [self.locationUpdateDurationTimer invalidate]; + [self.locationManager stopUpdatingLocation]; + + [self scheduleNextLocationUpdateAfterDelay:kMPLocationUpdateInterval]; +} + +- (void)scheduleNextLocationUpdateAfterDelay:(NSTimeInterval)delay +{ + MPLogDebug(@"Next user location update due in %.1f seconds.", delay); + [self.nextLocationUpdateTimer invalidate]; + self.nextLocationUpdateTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:delay target:self selector:@selector(startRecurringLocationUpdates) repeats:NO]; + [self.nextLocationUpdateTimer scheduleNow]; +} + +- (void)stopAllCurrentOrScheduledLocationUpdates +{ + MPLogDebug(@"Stopping any scheduled location updates."); + [self.locationUpdateDurationTimer invalidate]; + [self.locationManager stopUpdatingLocation]; + + [self.nextLocationUpdateTimer invalidate]; +} + +- (void)resumeLocationUpdatesAfterBackgrounding +{ + NSTimeInterval timeSinceLastUpdate = [[NSDate date] timeIntervalSinceDate:self.timeOfLastLocationUpdate]; + + if (timeSinceLastUpdate >= kMPLocationUpdateInterval) { + MPLogDebug(@"Last known user location is stale. Updating location."); + [self startRecurringLocationUpdates]; + } else if (timeSinceLastUpdate >= 0) { + NSTimeInterval timeToNextUpdate = kMPLocationUpdateInterval - timeSinceLastUpdate; + [self scheduleNextLocationUpdateAfterDelay:timeToNextUpdate]; + } else { + [self scheduleNextLocationUpdateAfterDelay:kMPLocationUpdateInterval]; + } +} + +#pragma mark - CLLocation Helpers + +- (BOOL)isLocation:(CLLocation *)location betterThanLocation:(CLLocation *)otherLocation +{ + if (!otherLocation) { + return YES; + } + + // Nil locations and locations with invalid horizontal accuracy are worse than any location. + if (![self locationHasValidCoordinates:location]) { + return NO; + } + + if ([self isLocation:location olderThanLocation:otherLocation]) { + return NO; + } + + return YES; +} + +- (BOOL)locationHasValidCoordinates:(CLLocation *)location +{ + return location && location.horizontalAccuracy > 0; +} + +- (BOOL)isLocation:(CLLocation *)location olderThanLocation:(CLLocation *)otherLocation +{ + return [location.timestamp timeIntervalSinceDate:otherLocation.timestamp] < 0; +} + +#pragma mark - (iOS 6.0+) + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status +{ + MPLogDebug(@"Location authorization status changed to: %ld", (long)status); + + switch (status) { + case kCLAuthorizationStatusNotDetermined: + case kCLAuthorizationStatusDenied: + case kCLAuthorizationStatusRestricted: + self.authorizedForLocationServices = NO; + break; + case kCLAuthorizationStatusAuthorized: // same as kCLAuthorizationStatusAuthorizedAlways +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + case kCLAuthorizationStatusAuthorizedWhenInUse: +#endif + self.authorizedForLocationServices = YES; + break; + default: + self.authorizedForLocationServices = NO; + break; + } +} + +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations +{ + for (CLLocation *location in locations) { + if ([self isLocation:location betterThanLocation:self.lastKnownLocation]) { + self.lastKnownLocation = location; + MPLogDebug(@"Updated last known user location: %@", location); + } + } +} + +- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error +{ + if (error.code == kCLErrorDenied) { + MPLogDebug(@"Location manager failed: the user has denied access to location services."); + [self stopAllCurrentOrScheduledLocationUpdates]; + } else if (error.code == kCLErrorLocationUnknown) { + MPLogDebug(@"Location manager could not obtain a location right now."); + } +} + +#pragma mark - (iOS < 6.0) + +- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation +{ + if ([self isLocation:newLocation betterThanLocation:self.lastKnownLocation]) { + self.lastKnownLocation = newLocation; + MPLogDebug(@"Updated last known user location."); + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.h new file mode 100644 index 000000000..168d389ce --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.h @@ -0,0 +1,131 @@ +// +// MPGlobal.h +// MoPub +// +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import +#import + +#ifndef MP_ANIMATED +#define MP_ANIMATED YES +#endif + +UIInterfaceOrientation MPInterfaceOrientation(void); +UIWindow *MPKeyWindow(void); +CGFloat MPStatusBarHeight(void); +CGRect MPApplicationFrame(void); +CGRect MPScreenBounds(void); +CGSize MPScreenResolution(void); +CGFloat MPDeviceScaleFactor(void); +NSDictionary *MPDictionaryFromQueryString(NSString *query); +NSString *MPSHA1Digest(NSString *string); +BOOL MPViewIsVisible(UIView *view); +BOOL MPViewIntersectsParentWindowWithPercent(UIView *view, CGFloat percentVisible); +NSString *MPResourcePathForResource(NSString *resourceName); +NSArray *MPConvertStringArrayToURLArray(NSArray *strArray); +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * Availability constants. + */ + +#define MP_IOS_2_0 20000 +#define MP_IOS_2_1 20100 +#define MP_IOS_2_2 20200 +#define MP_IOS_3_0 30000 +#define MP_IOS_3_1 30100 +#define MP_IOS_3_2 30200 +#define MP_IOS_4_0 40000 +#define MP_IOS_4_1 40100 +#define MP_IOS_4_2 40200 +#define MP_IOS_4_3 40300 +#define MP_IOS_5_0 50000 +#define MP_IOS_5_1 50100 +#define MP_IOS_6_0 60000 +#define MP_IOS_7_0 70000 +#define MP_IOS_8_0 80000 +#define MP_IOS_9_0 90000 + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +enum { + MPInterstitialCloseButtonStyleAlwaysVisible, + MPInterstitialCloseButtonStyleAlwaysHidden, + MPInterstitialCloseButtonStyleAdControlled +}; +typedef NSUInteger MPInterstitialCloseButtonStyle; + +enum { + MPInterstitialOrientationTypePortrait, + MPInterstitialOrientationTypeLandscape, + MPInterstitialOrientationTypeAll +}; +typedef NSUInteger MPInterstitialOrientationType; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface NSString (MPAdditions) + +/* + * Returns string with reserved/unsafe characters encoded. + */ +- (NSString *)mp_URLEncodedString; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UIDevice (MPAdditions) + +- (NSString *)mp_hardwareDeviceName; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface UIApplication (MPAdditions) + +// Correct way to hide/show the status bar on pre-ios 7. +- (void)mp_preIOS7setApplicationStatusBarHidden:(BOOL)hidden; +- (BOOL)mp_supportsOrientationMask:(UIInterfaceOrientationMask)orientationMask; +- (BOOL)mp_doesOrientation:(UIInterfaceOrientation)orientation matchOrientationMask:(UIInterfaceOrientationMask)orientationMask; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Optional Class Forward Def Protocols +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@class MPAdConfiguration, CLLocation; + +@protocol MPAdAlertManagerProtocol + +@property (nonatomic, strong) MPAdConfiguration *adConfiguration; +@property (nonatomic, copy) NSString *adUnitId; +@property (nonatomic, copy) CLLocation *location; +@property (nonatomic, weak) UIView *targetAdView; +@property (nonatomic, weak) id delegate; + +- (void)beginMonitoringAlerts; +- (void)endMonitoringAlerts; +- (void)processAdAlertOnce; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Small alert wrapper class to handle telephone protocol prompting +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@class MPTelephoneConfirmationController; + +typedef void (^MPTelephoneConfirmationControllerClickHandler)(NSURL *targetTelephoneURL, BOOL confirmed); + +@interface MPTelephoneConfirmationController : NSObject + +- (id)initWithURL:(NSURL *)url clickHandler:(MPTelephoneConfirmationControllerClickHandler)clickHandler; +- (void)show; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.m new file mode 100644 index 000000000..1c8632746 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPGlobal.m @@ -0,0 +1,401 @@ +// +// MPGlobal.m +// MoPub +// +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPGlobal.h" +#import "MPConstants.h" +#import "MPLogging.h" +#import "NSURL+MPAdditions.h" +#import "MoPub.h" +#import + +#import +#import + +BOOL MPViewHasHiddenAncestor(UIView *view); +UIWindow *MPViewGetParentWindow(UIView *view); +BOOL MPViewIntersectsParentWindow(UIView *view); +NSString *MPSHA1Digest(NSString *string); + +UIInterfaceOrientation MPInterfaceOrientation() +{ + return [UIApplication sharedApplication].statusBarOrientation; +} + +UIWindow *MPKeyWindow() +{ + return [UIApplication sharedApplication].keyWindow; +} + +CGFloat MPStatusBarHeight() { + if ([UIApplication sharedApplication].statusBarHidden) return 0.0f; + + CGFloat width = CGRectGetWidth([UIApplication sharedApplication].statusBarFrame); + CGFloat height = CGRectGetHeight([UIApplication sharedApplication].statusBarFrame); + + return (width < height) ? width : height; +} + +CGRect MPApplicationFrame() +{ + CGRect frame = MPScreenBounds(); + + frame.origin.y += MPStatusBarHeight(); + frame.size.height -= MPStatusBarHeight(); + + return frame; +} + +CGRect MPScreenBounds() +{ + // Prior to iOS 8, window and screen coordinates were fixed and always specified relative to the + // device’s screen in a portrait orientation. Starting with iOS8, the `fixedCoordinateSpace` + // property was introduced which specifies bounds that always reflect the screen dimensions of + // the device in a portrait-up orientation. + CGRect bounds = [UIScreen mainScreen].bounds; + if ([[UIScreen mainScreen] respondsToSelector:@selector(fixedCoordinateSpace)]) { + bounds = [UIScreen mainScreen].fixedCoordinateSpace.bounds; + } + + // Rotate the portrait-up bounds if the orientation of the device is in landscape. + if (UIInterfaceOrientationIsLandscape(MPInterfaceOrientation())) { + CGFloat width = bounds.size.width; + bounds.size.width = bounds.size.height; + bounds.size.height = width; + } + + return bounds; +} + +CGSize MPScreenResolution() +{ + CGRect bounds = MPScreenBounds(); + CGFloat scale = MPDeviceScaleFactor(); + + return CGSizeMake(bounds.size.width*scale, bounds.size.height*scale); +} + +CGFloat MPDeviceScaleFactor() +{ + if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && + [[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { + return [[UIScreen mainScreen] scale]; + } else { + return 1.0; + } +} + +NSDictionary *MPDictionaryFromQueryString(NSString *query) { + NSMutableDictionary *queryDict = [NSMutableDictionary dictionary]; + NSArray *queryElements = [query componentsSeparatedByString:@"&"]; + for (NSString *element in queryElements) { + NSArray *keyVal = [element componentsSeparatedByString:@"="]; + NSString *key = [keyVal objectAtIndex:0]; + NSString *value = [keyVal lastObject]; + [queryDict setObject:[value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + forKey:key]; + } + return queryDict; +} + +NSString *MPSHA1Digest(NSString *string) +{ + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding]; + CC_SHA1([data bytes], (CC_LONG)[data length], digest); + + NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; + for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { + [output appendFormat:@"%02x", digest[i]]; + } + + return output; +} + +BOOL MPViewIsVisible(UIView *view) +{ + // In order for a view to be visible, it: + // 1) must not be hidden, + // 2) must not have an ancestor that is hidden, + // 3) must be within the frame of its parent window. + // + // Note: this function does not check whether any part of the view is obscured by another view. + + return (!view.hidden && + !MPViewHasHiddenAncestor(view) && + MPViewIntersectsParentWindow(view)); +} + +BOOL MPViewHasHiddenAncestor(UIView *view) +{ + UIView *ancestor = view.superview; + while (ancestor) { + if (ancestor.hidden) return YES; + ancestor = ancestor.superview; + } + return NO; +} + +UIWindow *MPViewGetParentWindow(UIView *view) +{ + UIView *ancestor = view.superview; + while (ancestor) { + if ([ancestor isKindOfClass:[UIWindow class]]) { + return (UIWindow *)ancestor; + } + ancestor = ancestor.superview; + } + return nil; +} + +BOOL MPViewIntersectsParentWindow(UIView *view) +{ + UIWindow *parentWindow = MPViewGetParentWindow(view); + + if (parentWindow == nil) { + return NO; + } + + // We need to call convertRect:toView: on this view's superview rather than on this view itself. + CGRect viewFrameInWindowCoordinates = [view.superview convertRect:view.frame toView:parentWindow]; + + return CGRectIntersectsRect(viewFrameInWindowCoordinates, parentWindow.frame); +} + +BOOL MPViewIntersectsParentWindowWithPercent(UIView *view, CGFloat percentVisible) +{ + UIWindow *parentWindow = MPViewGetParentWindow(view); + + if (parentWindow == nil) { + return NO; + } + + // We need to call convertRect:toView: on this view's superview rather than on this view itself. + CGRect viewFrameInWindowCoordinates = [view.superview convertRect:view.frame toView:parentWindow]; + CGRect intersection = CGRectIntersection(viewFrameInWindowCoordinates, parentWindow.frame); + + CGFloat intersectionArea = CGRectGetWidth(intersection) * CGRectGetHeight(intersection); + CGFloat originalArea = CGRectGetWidth(view.bounds) * CGRectGetHeight(view.bounds); + + return intersectionArea >= (originalArea * percentVisible); +} + +NSString *MPResourcePathForResource(NSString *resourceName) +{ + if ([[NSBundle mainBundle] pathForResource:@"MoPub" ofType:@"bundle"] != nil) { + return [@"MoPub.bundle" stringByAppendingPathComponent:resourceName]; + } + else if ([[UIDevice currentDevice].systemVersion compare:@"8.0" options:NSNumericSearch] != NSOrderedAscending) { + // When using open source or cocoapods (on ios 8 and above), we can rely on the MoPub class + // living in the same bundle/framework as the assets. + // We can use pathForResource on ios 8 and above to succesfully load resources. + NSBundle *resourceBundle = [NSBundle bundleForClass:[MoPub class]]; + NSString *resourcePath = [resourceBundle pathForResource:resourceName ofType:nil]; + return resourcePath; + } + else { + // We can just return the resource name because: + // 1. This is being used as an open source release so the resource will be + // in the main bundle. + // 2. This is cocoapods but CAN'T be using frameworks since that is only allowed + // on ios 8 and above. + return resourceName; + } +} + +NSArray *MPConvertStringArrayToURLArray(NSArray *strArray) +{ + NSMutableArray *urls = [NSMutableArray array]; + + for (NSObject *str in strArray) { + if ([str isKindOfClass:[NSString class]]) { + NSURL *url = [NSURL URLWithString:(NSString *)str]; + if (url) { + [urls addObject:url]; + } + } + } + + return urls; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation NSString (MPAdditions) + +- (NSString *)mp_URLEncodedString +{ + NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, + (CFStringRef)self, + NULL, + (CFStringRef)@"!*'();:@&=+$,/?%#[]<>", + kCFStringEncodingUTF8)); + return result; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation UIDevice (MPAdditions) + +- (NSString *)mp_hardwareDeviceName +{ + size_t size; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char *machine = malloc(size); + sysctlbyname("hw.machine", machine, &size, NULL, 0); + NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; + free(machine); + return platform; +} + +@end + +@implementation UIApplication (MPAdditions) + +- (void)mp_preIOS7setApplicationStatusBarHidden:(BOOL)hidden +{ + // Hiding the status bar should use a fade effect. + // Displaying the status bar should use no animation. + UIStatusBarAnimation animation = hidden ? + UIStatusBarAnimationFade : UIStatusBarAnimationNone; + [[UIApplication sharedApplication] setStatusBarHidden:hidden withAnimation:animation]; +} + +- (BOOL)mp_supportsOrientationMask:(UIInterfaceOrientationMask)orientationMask +{ + NSArray *supportedOrientations = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"UISupportedInterfaceOrientations"]; + + if (orientationMask & UIInterfaceOrientationMaskLandscapeLeft) { + if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeLeft"]) { + return YES; + } + } + + if (orientationMask & UIInterfaceOrientationMaskLandscapeRight) { + if ([supportedOrientations containsObject:@"UIInterfaceOrientationLandscapeRight"]) { + return YES; + } + } + + if (orientationMask & UIInterfaceOrientationMaskPortrait) { + if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"]) { + return YES; + } + } + + if (orientationMask & UIInterfaceOrientationMaskPortraitUpsideDown) { + if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortraitUpsideDown"]) { + return YES; + } + } + + return NO; +} + +- (BOOL)mp_doesOrientation:(UIInterfaceOrientation)orientation matchOrientationMask:(UIInterfaceOrientationMask)orientationMask +{ + BOOL supportsLandscapeLeft = (orientationMask & UIInterfaceOrientationMaskLandscapeLeft) > 0; + BOOL supportsLandscapeRight = (orientationMask & UIInterfaceOrientationMaskLandscapeRight) > 0; + BOOL supportsPortrait = (orientationMask & UIInterfaceOrientationMaskPortrait) > 0; + BOOL supportsPortraitUpsideDown = (orientationMask & UIInterfaceOrientationMaskPortraitUpsideDown) > 0; + + if (supportsLandscapeLeft && orientation == UIInterfaceOrientationLandscapeLeft) { + return YES; + } + + if (supportsLandscapeRight && orientation == UIInterfaceOrientationLandscapeRight) { + return YES; + } + + if (supportsPortrait && orientation == UIInterfaceOrientationPortrait) { + return YES; + } + + if (supportsPortraitUpsideDown && orientation == UIInterfaceOrientationPortraitUpsideDown) { + return YES; + } + + return NO; +} + +@end +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPTelephoneConfirmationController () + +@property (nonatomic, strong) UIAlertView *alertView; +@property (nonatomic, strong) NSURL *telephoneURL; +@property (nonatomic, copy) MPTelephoneConfirmationControllerClickHandler clickHandler; + +@end + +@implementation MPTelephoneConfirmationController + +- (id)initWithURL:(NSURL *)url clickHandler:(MPTelephoneConfirmationControllerClickHandler)clickHandler +{ + if (![url mp_hasTelephoneScheme] && ![url mp_hasTelephonePromptScheme]) { + // Shouldn't be here as the url must have a tel or telPrompt scheme. + MPLogError(@"Processing URL as a telephone URL when %@ doesn't follow the tel:// or telprompt:// schemes", url.absoluteString); + return nil; + } + + if (self = [super init]) { + // If using tel://xxxxxxx, the host will be the number. If using tel:xxxxxxx, we will try the resourceIdentifier. + NSString *phoneNumber = [url host]; + + if (!phoneNumber) { + phoneNumber = [url resourceSpecifier]; + if ([phoneNumber length] == 0) { + MPLogError(@"Invalid telelphone URL: %@.", url.absoluteString); + return nil; + } + } + + _alertView = [[UIAlertView alloc] initWithTitle: @"Are you sure you want to call?" + message:phoneNumber + delegate:self + cancelButtonTitle:@"Cancel" + otherButtonTitles:@"Call", nil]; + self.clickHandler = clickHandler; + + // We want to manually handle telPrompt scheme alerts. So we'll convert telPrompt schemes to tel schemes. + if ([url mp_hasTelephonePromptScheme]) { + self.telephoneURL = [NSURL URLWithString:[NSString stringWithFormat:@"tel://%@", phoneNumber]]; + } else { + self.telephoneURL = url; + } + } + + return self; +} + +- (void)dealloc +{ + self.alertView.delegate = nil; + [self.alertView dismissWithClickedButtonIndex:0 animated:YES]; +} + +- (void)show +{ + [self.alertView show]; +} + +#pragma mark - UIAlertViewDelegate + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + BOOL confirmed = (buttonIndex == 1); + + if (self.clickHandler) { + self.clickHandler(self.telephoneURL, confirmed); + } + +} + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.h new file mode 100644 index 000000000..835ee0cfb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.h @@ -0,0 +1,28 @@ +// +// MPIdentityProvider.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@interface MPIdentityProvider : NSObject + ++ (NSString *)identifier; ++ (NSString *)obfuscatedIdentifier; ++ (BOOL)advertisingTrackingEnabled; + +/** + * A Boolean value indicating whether the MoPub SDK should create a MoPub ID that can be used + * for frequency capping when Limit ad tracking is on & the IDFA we get is + * 00000000-0000-0000-0000-000000000000. + * + * When set to NO, the SDK will not create a MoPub ID in the above case. When set to YES, the + * SDK will generate a MoPub ID. The default value is YES. + * + */ ++ (void)setFrequencyCappingIdUsageEnabled:(BOOL)frequencyCappingIdUsageEnabled; ++ (BOOL)frequencyCappingIdUsageEnabled; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.m new file mode 100644 index 000000000..15877d2b3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPIdentityProvider.m @@ -0,0 +1,125 @@ +// +// MPIdentityProvider.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPIdentityProvider.h" +#import "MPGlobal.h" +#import + +#define MOPUB_IDENTIFIER_DEFAULTS_KEY @"com.mopub.identifier" +#define MOPUB_IDENTIFIER_LAST_SET_TIME_KEY @"com.mopub.identifiertime" +#define MOPUB_DAY_IN_SECONDS 24 * 60 * 60 +#define MOPUB_ALL_ZERO_UUID @"00000000-0000-0000-0000-000000000000" + +static BOOL gFrequencyCappingIdUsageEnabled = YES; + +@interface MPIdentityProvider () + ++ (NSString *)identifierFromASIdentifierManager:(BOOL)obfuscate; ++ (NSString *)mopubIdentifier:(BOOL)obfuscate; + +@end + +@implementation MPIdentityProvider + ++ (NSString *)identifier +{ + return [self _identifier:NO]; +} + ++ (NSString *)obfuscatedIdentifier +{ + return [self _identifier:YES]; +} + ++ (NSString *)_identifier:(BOOL)obfuscate +{ + if (![self isAdvertisingIdAllZero]) { + return [self identifierFromASIdentifierManager:obfuscate]; + } else { + return [self mopubIdentifier:obfuscate]; + } +} + ++ (BOOL)advertisingTrackingEnabled +{ + return [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]; +} + ++ (NSString *)identifierFromASIdentifierManager:(BOOL)obfuscate +{ + if (obfuscate) { + return @"ifa:XXXX"; + } + + NSString *identifier = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; + + return [NSString stringWithFormat:@"ifa:%@", [identifier uppercaseString]]; +} + ++ (NSString *)mopubIdentifier:(BOOL)obfuscate +{ + if (![self frequencyCappingIdUsageEnabled]) { + return [NSString stringWithFormat:@"ifa:%@", MOPUB_ALL_ZERO_UUID]; + } + + if (obfuscate) { + return @"mopub:XXXX"; + } + + // reset identifier every 24 hours + NSDate *lastSetDate = [[NSUserDefaults standardUserDefaults] objectForKey:MOPUB_IDENTIFIER_LAST_SET_TIME_KEY]; + if (!lastSetDate) { + [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:MOPUB_IDENTIFIER_LAST_SET_TIME_KEY]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } else { + NSTimeInterval diff = [[NSDate date] timeIntervalSinceDate:lastSetDate]; + if (diff > MOPUB_DAY_IN_SECONDS) { + [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:MOPUB_IDENTIFIER_LAST_SET_TIME_KEY]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:MOPUB_IDENTIFIER_DEFAULTS_KEY]; + } + } + + NSString *identifier = [[NSUserDefaults standardUserDefaults] objectForKey:MOPUB_IDENTIFIER_DEFAULTS_KEY]; + if (!identifier) { + CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault); + NSString *uuidStr = (NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuidObject)); + CFRelease(uuidObject); + + identifier = [NSString stringWithFormat:@"mopub:%@", [uuidStr uppercaseString]]; + [[NSUserDefaults standardUserDefaults] setObject:identifier forKey:MOPUB_IDENTIFIER_DEFAULTS_KEY]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } + + return identifier; +} + ++ (void)setFrequencyCappingIdUsageEnabled:(BOOL)frequencyCappingIdUsageEnabled +{ + gFrequencyCappingIdUsageEnabled = frequencyCappingIdUsageEnabled; +} + ++ (BOOL)frequencyCappingIdUsageEnabled +{ + return gFrequencyCappingIdUsageEnabled; +} + + + +// Beginning in iOS 10, when a user enables "Limit Ad Tracking", the OS will send advertising identifier with value of +// 00000000-0000-0000-0000-000000000000 + ++ (BOOL)isAdvertisingIdAllZero { + NSString *identifier = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; + if (!identifier) { + // when identifier is nil, ifa:(null) is sent. + return false; + } else { + return [identifier isEqualToString:MOPUB_ALL_ZERO_UUID]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.h new file mode 100644 index 000000000..3fd069cf8 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.h @@ -0,0 +1,25 @@ +// +// MPInternalUtils.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +#define SUPPRESS_PERFORM_SELECTOR_LEAK_WARNING(code) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ + code; \ + _Pragma("clang diagnostic pop") \ + +@interface MPInternalUtils : NSObject + +@end + +@interface NSMutableDictionary (MPInternalUtils) + +- (void)mp_safeSetObject:(id)obj forKey:(id)key; +- (void)mp_safeSetObject:(id)obj forKey:(id)key withDefault:(id)defaultObj; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.m new file mode 100644 index 000000000..5b7cc07cc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPInternalUtils.m @@ -0,0 +1,32 @@ +// +// MPInternalUtils.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPInternalUtils.h" + +@implementation MPInternalUtils + +@end + +@implementation NSMutableDictionary (MPInternalUtils) + +- (void)mp_safeSetObject:(id)obj forKey:(id)key +{ + if (obj != nil) { + [self setObject:obj forKey:key]; + } +} + +- (void)mp_safeSetObject:(id)obj forKey:(id)key withDefault:(id)defaultObj +{ + if (obj != nil) { + [self setObject:obj forKey:key]; + } else { + [self setObject:defaultObj forKey:key]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.h new file mode 100644 index 000000000..96f9a6739 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.h @@ -0,0 +1,27 @@ +// +// MPLogProvider.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import "MPLogging.h" + +@protocol MPLogger; + +@interface MPLogProvider : NSObject + ++ (MPLogProvider *)sharedLogProvider; +- (void)addLogger:(id)logger; +- (void)removeLogger:(id)logger; +- (void)logMessage:(NSString *)message atLogLevel:(MPLogLevel)logLevel; + +@end + +@protocol MPLogger + +- (MPLogLevel)logLevel; +- (void)logMessage:(NSString *)message; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.m new file mode 100644 index 000000000..b9aa1d0a9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogProvider.m @@ -0,0 +1,83 @@ +// +// MPLogProvider.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPLogProvider.h" + +@interface MPLogProvider () + +@property (nonatomic, strong) NSMutableArray *loggers; + +@end + +@interface MPSystemLogger : NSObject +@end + +@implementation MPLogProvider + +#pragma mark - Singleton instance + ++ (MPLogProvider *)sharedLogProvider +{ + static dispatch_once_t once; + static MPLogProvider *sharedLogProvider; + dispatch_once(&once, ^{ + sharedLogProvider = [[self alloc] init]; + }); + + return sharedLogProvider; +} + +#pragma mark - Object Lifecycle + +- (id)init +{ + self = [super init]; + if (self) { + _loggers = [NSMutableArray array]; + [self addLogger:[[MPSystemLogger alloc] init]]; + } + return self; +} + +#pragma mark - Loggers + +- (void)addLogger:(id)logger +{ + [self.loggers addObject:logger]; +} + +- (void)removeLogger:(id)logger +{ + [self.loggers removeObject:logger]; +} + +#pragma mark - Logging + +- (void)logMessage:(NSString *)message atLogLevel:(MPLogLevel)logLevel +{ + [self.loggers enumerateObjectsUsingBlock:^(id logger, NSUInteger idx, BOOL *stop) { + if ([logger logLevel] <= logLevel) { + [logger logMessage:message]; + } + }]; +} + +@end + +@implementation MPSystemLogger + +- (void)logMessage:(NSString *)message +{ + NSLog(@"%@", message); +} + +- (MPLogLevel)logLevel +{ + return MPLogGetLevel(); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.h new file mode 100644 index 000000000..02b3069c4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.h @@ -0,0 +1,54 @@ +// +// MPLogging.h +// MoPub +// +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import +#import "MPConstants.h" + +extern NSString * const kMPClearErrorLogFormatWithAdUnitID; +extern NSString * const kMPWarmingUpErrorLogFormatWithAdUnitID; + +// Lower = finer-grained logs. +typedef enum +{ + MPLogLevelAll = 0, + MPLogLevelTrace = 10, + MPLogLevelDebug = 20, + MPLogLevelInfo = 30, + MPLogLevelWarn = 40, + MPLogLevelError = 50, + MPLogLevelFatal = 60, + MPLogLevelOff = 70 +} MPLogLevel; + +MPLogLevel MPLogGetLevel(void); +void MPLogSetLevel(MPLogLevel level); +void _MPLogTrace(NSString *format, ...); +void _MPLogDebug(NSString *format, ...); +void _MPLogInfo(NSString *format, ...); +void _MPLogWarn(NSString *format, ...); +void _MPLogError(NSString *format, ...); +void _MPLogFatal(NSString *format, ...); + +#if MP_DEBUG_MODE && !SPECS + +#define MPLogTrace(...) _MPLogTrace(__VA_ARGS__) +#define MPLogDebug(...) _MPLogDebug(__VA_ARGS__) +#define MPLogInfo(...) _MPLogInfo(__VA_ARGS__) +#define MPLogWarn(...) _MPLogWarn(__VA_ARGS__) +#define MPLogError(...) _MPLogError(__VA_ARGS__) +#define MPLogFatal(...) _MPLogFatal(__VA_ARGS__) + +#else + +#define MPLogTrace(...) {} +#define MPLogDebug(...) {} +#define MPLogInfo(...) {} +#define MPLogWarn(...) {} +#define MPLogError(...) {} +#define MPLogFatal(...) {} + +#endif diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.m new file mode 100644 index 000000000..5dee8463c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPLogging.m @@ -0,0 +1,101 @@ +// +// MPLogging.m +// MoPub +// +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPLogging.h" +#import "MPIdentityProvider.h" +#import "MPLogProvider.h" + +NSString * const kMPClearErrorLogFormatWithAdUnitID = @"No ads found for ad unit: %@"; +NSString * const kMPWarmingUpErrorLogFormatWithAdUnitID = @"Ad unit %@ is currently warming up. Please try again in a few minutes."; +NSString * const kMPSystemLogPrefix = @"MOPUB: %@"; + +static MPLogLevel systemLogLevel = MPLogLevelInfo; + +MPLogLevel MPLogGetLevel() +{ + return systemLogLevel; +} + +void MPLogSetLevel(MPLogLevel level) +{ + systemLogLevel = level; +} + +void _MPLog(MPLogLevel level, NSString *format, va_list args) +{ + static NSString *sIdentifier; + static NSString *sObfuscatedIdentifier; + + if (!sIdentifier) { + sIdentifier = [[MPIdentityProvider identifier] copy]; + } + + if (!sObfuscatedIdentifier) { + sObfuscatedIdentifier = [[MPIdentityProvider obfuscatedIdentifier] copy]; + } + + NSString *logString = [[NSString alloc] initWithFormat:format arguments:args]; + + // Replace identifier with a obfuscated version when logging. + logString = [logString stringByReplacingOccurrencesOfString:sIdentifier withString:sObfuscatedIdentifier]; + + [[MPLogProvider sharedLogProvider] logMessage:logString atLogLevel:level]; +} + +void _MPLogTrace(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelTrace, format, args); + va_end(args); +} + +void _MPLogDebug(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelDebug, format, args); + va_end(args); +} + +void _MPLogWarn(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelWarn, format, args); + va_end(args); +} + +void _MPLogInfo(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelInfo, format, args); + va_end(args); +} + +void _MPLogError(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelError, format, args); + va_end(args); +} + +void _MPLogFatal(NSString *format, ...) +{ + format = [NSString stringWithFormat:kMPSystemLogPrefix, format]; + va_list args; + va_start(args, format); + _MPLog(MPLogLevelFatal, format, args); + va_end(args); +} diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.h new file mode 100644 index 000000000..af9344891 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.h @@ -0,0 +1,100 @@ +/* + File: Reachability.h + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. + Version: 3.5 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + + */ + +#import +#import +#import + + +typedef enum : NSInteger { + MPNotReachable = 0, + MPReachableViaWiFi, + MPReachableViaWWAN +} MPNetworkStatus; + + +extern NSString *kMPReachabilityChangedNotification; + + +@interface MPReachability : NSObject + +/*! + * Use to check the reachability of a given host name. + */ ++ (instancetype)reachabilityWithHostName:(NSString *)hostName; + +/*! + * Use to check the reachability of a given IP address. + */ ++ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress; + +/*! + * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. + */ ++ (instancetype)reachabilityForInternetConnection; + +/*! + * Checks whether a local WiFi connection is available. + */ ++ (instancetype)reachabilityForLocalWiFi; + +/*! + * Start listening for reachability notifications on the current run loop. + */ +- (BOOL)startNotifier; +- (void)stopNotifier; + +- (MPNetworkStatus)currentReachabilityStatus; + +/*! + * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. + */ +- (BOOL)connectionRequired; +- (BOOL)hasWifi; +- (BOOL)hasCellular; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.m new file mode 100644 index 000000000..e17fa4b20 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPReachability.m @@ -0,0 +1,331 @@ +/* + File: Reachability.m + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. + Version: 3.5 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + + */ + +#import +#import +#import +#import + +#import + +#import "MPReachability.h" +#import "MPLogging.h" + + +NSString *kMPReachabilityChangedNotification = @"kMPReachabilityChangedNotification"; + + +#pragma mark - Supporting functions + +#define kShouldPrintReachabilityFlags 0 + +static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment) +{ +#if kShouldPrintReachabilityFlags + + NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', + comment + ); +#endif +} + + +static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) +{ +#pragma unused (target, flags) + if (info == NULL) { + MPLogWarn(@"info was NULL in ReachabilityCallback"); + } + if (![(__bridge NSObject*) info isKindOfClass: [MPReachability class]]) { + MPLogWarn(@"info was wrong class in ReachabilityCallback"); + } + + MPReachability* reachabilityObject = (__bridge MPReachability *)info; + // Post a notification to notify the client that the network reachability changed. + [[NSNotificationCenter defaultCenter] postNotificationName: kMPReachabilityChangedNotification object: reachabilityObject]; +} + + +#pragma mark - Reachability implementation + +@implementation MPReachability +{ + BOOL _alwaysReturnLocalWiFiStatus; //default is NO + SCNetworkReachabilityRef _reachabilityRef; +} + ++ (instancetype)reachabilityWithHostName:(NSString *)hostName +{ + MPReachability* returnValue = NULL; + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); + if (reachability != NULL) + { + returnValue= [[self alloc] init]; + if (returnValue != NULL) + { + returnValue->_reachabilityRef = reachability; + returnValue->_alwaysReturnLocalWiFiStatus = NO; + } else { + CFRelease(reachability); + } + } + return returnValue; +} + + ++ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress +{ + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress); + + MPReachability* returnValue = NULL; + + if (reachability != NULL) + { + returnValue = [[self alloc] init]; + if (returnValue != NULL) + { + returnValue->_reachabilityRef = reachability; + returnValue->_alwaysReturnLocalWiFiStatus = NO; + } else { + CFRelease(reachability); + } + } + return returnValue; +} + + + ++ (instancetype)reachabilityForInternetConnection +{ + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress:&zeroAddress]; +} + + ++ (instancetype)reachabilityForLocalWiFi +{ + struct sockaddr_in localWifiAddress; + bzero(&localWifiAddress, sizeof(localWifiAddress)); + localWifiAddress.sin_len = sizeof(localWifiAddress); + localWifiAddress.sin_family = AF_INET; + + // IN_LINKLOCALNETNUM is defined in as 169.254.0.0. + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); + + MPReachability* returnValue = [self reachabilityWithAddress: &localWifiAddress]; + if (returnValue != NULL) + { + returnValue->_alwaysReturnLocalWiFiStatus = YES; + } + + return returnValue; +} + + +#pragma mark - Start and stop notifier + +- (BOOL)startNotifier +{ + BOOL returnValue = NO; + SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL}; + + if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)) + { + if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) + { + returnValue = YES; + } + } + + return returnValue; +} + + +- (void)stopNotifier +{ + if (_reachabilityRef != NULL) + { + SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + } +} + + +- (void)dealloc +{ + [self stopNotifier]; + if (_reachabilityRef != NULL) + { + CFRelease(_reachabilityRef); + } +} + + +#pragma mark - Network Flag Handling + +- (MPNetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags +{ + PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); + MPNetworkStatus returnValue = MPNotReachable; + + if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)) + { + returnValue = MPReachableViaWiFi; + } + + return returnValue; +} + + +- (MPNetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags +{ + PrintReachabilityFlags(flags, "networkStatusForFlags"); + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) + { + // The target host is not reachable. + return MPNotReachable; + } + + MPNetworkStatus returnValue = MPNotReachable; + + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) + { + /* + If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi... + */ + returnValue = MPReachableViaWiFi; + } + + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) + { + /* + ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs... + */ + + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) + { + /* + ... and no [user] intervention is needed... + */ + returnValue = MPReachableViaWiFi; + } + } + + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) + { + /* + ... but WWAN connections are OK if the calling application is using the CFNetwork APIs. + */ + returnValue = MPReachableViaWWAN; + } + + return returnValue; +} + + +- (BOOL)connectionRequired +{ + NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef"); + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) + { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + + +- (MPNetworkStatus)currentReachabilityStatus +{ + NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef"); + MPNetworkStatus returnValue = MPNotReachable; + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) + { + if (_alwaysReturnLocalWiFiStatus) + { + returnValue = [self localWiFiStatusForFlags:flags]; + } + else + { + returnValue = [self networkStatusForFlags:flags]; + } + } + + return returnValue; +} + + +- (BOOL)hasWifi +{ + return [self currentReachabilityStatus] == MPReachableViaWiFi; +} + +- (BOOL)hasCellular +{ + return [self currentReachabilityStatus] == MPReachableViaWWAN; +} + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.h new file mode 100644 index 000000000..630cb06b1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.h @@ -0,0 +1,12 @@ +// +// MPSessionTracker.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@interface MPSessionTracker : NSObject + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.m new file mode 100644 index 000000000..d9ed3e707 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPSessionTracker.m @@ -0,0 +1,51 @@ +// +// MPSessionTracker.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPSessionTracker.h" +#import "MPConstants.h" +#import "MPIdentityProvider.h" +#import "MPGlobal.h" +#import "MPCoreInstanceProvider.h" +#import "MPAPIEndpoints.h" + +@implementation MPSessionTracker + ++ (void)load +{ + if (SESSION_TRACKING_ENABLED) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(trackEvent) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(trackEvent) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; + } +} + ++ (void)trackEvent +{ + [NSURLConnection connectionWithRequest:[[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:[self URL]] + delegate:nil]; +} + ++ (NSURL *)URL +{ + NSString *path = [NSString stringWithFormat:@"%@?v=%@&udid=%@&id=%@&av=%@&st=1", + [MPAPIEndpoints baseURLStringWithPath:MOPUB_API_PATH_SESSION testing:NO], + MP_SERVER_VERSION, + [MPIdentityProvider identifier], + [[[NSBundle mainBundle] bundleIdentifier] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + ]; + + return [NSURL URLWithString:path]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.h new file mode 100644 index 000000000..716120d38 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.h @@ -0,0 +1,30 @@ +// +// MPFeatureDetector.h +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import "MPGlobal.h" +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 +#import +#endif + +@class SKStoreProductViewController; + +@interface MPStoreKitProvider : NSObject + ++ (BOOL)deviceHasStoreKit; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 ++ (SKStoreProductViewController *)buildController; +#endif + +@end + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 +@protocol MPSKStoreProductViewControllerDelegate +#else +@protocol MPSKStoreProductViewControllerDelegate +#endif +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.m new file mode 100644 index 000000000..e196fc760 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPStoreKitProvider.m @@ -0,0 +1,50 @@ +// +// MPFeatureDetector.m +// MoPub +// +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPStoreKitProvider.h" +#import "MPGlobal.h" + +#import + +/* + * On iOS 7 and above, SKStoreProductViewController can cause a crash if the application does not list Portrait as a supported + * interface orientation. Specifically, SKStoreProductViewController's shouldAutorotate returns YES, even though + * the SKStoreProductViewController's supported interface orientations does not intersect with the application's list. + * + * To fix, we disallow autorotation so the SKStoreProductViewController will use its supported orientation on iOS 7 devices. + */ +@interface MPiOS7SafeStoreProductViewController : SKStoreProductViewController + +@end + +@implementation MPiOS7SafeStoreProductViewController + +- (BOOL)shouldAutorotate +{ + return NO; +} + +@end + +@implementation MPStoreKitProvider + ++ (BOOL)deviceHasStoreKit +{ + return !!NSClassFromString(@"SKStoreProductViewController"); +} + ++ (SKStoreProductViewController *)buildController +{ + // use our safe subclass on iOS 7 and above + if ([[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) { + return [[MPiOS7SafeStoreProductViewController alloc] init]; + } else { + return [[SKStoreProductViewController alloc] init]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.h new file mode 100644 index 000000000..409541432 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.h @@ -0,0 +1,31 @@ +// +// MPTimer.h +// MoPub +// +// Created by Andrew He on 3/8/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import + +/* + * MPTimer wraps an NSTimer and adds pause/resume functionality. + */ +@interface MPTimer : NSObject + +@property (nonatomic, copy) NSString *runLoopMode; + ++ (MPTimer *)timerWithTimeInterval:(NSTimeInterval)seconds + target:(id)target + selector:(SEL)aSelector + repeats:(BOOL)repeats; + +- (BOOL)isValid; +- (void)invalidate; +- (BOOL)isScheduled; +- (BOOL)scheduleNow; +- (BOOL)pause; +- (BOOL)resume; +- (NSTimeInterval)initialTimeInterval; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.m new file mode 100644 index 000000000..544501ec3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPTimer.m @@ -0,0 +1,177 @@ +// +// MPTimer.m +// MoPub +// +// Created by Andrew He on 3/8/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPTimer.h" +#import "MPLogging.h" +#import "MPInternalUtils.h" + +@interface MPTimer () +@property (nonatomic, assign) NSTimeInterval timeInterval; +@property (nonatomic, strong) NSTimer *timer; +@property (nonatomic, copy) NSDate *pauseDate; +@property (nonatomic, assign) BOOL isPaused; +@end + +@interface MPTimer () + +@property (nonatomic, weak) id target; +@property (nonatomic, assign) SEL selector; + +@end + +@implementation MPTimer + +@synthesize timeInterval = _timeInterval; +@synthesize timer = _timer; +@synthesize pauseDate = _pauseDate; +@synthesize target = _target; +@synthesize selector = _selector; +@synthesize isPaused = _isPaused; + ++ (MPTimer *)timerWithTimeInterval:(NSTimeInterval)seconds + target:(id)target + selector:(SEL)aSelector + repeats:(BOOL)repeats +{ + MPTimer *timer = [[MPTimer alloc] init]; + timer.target = target; + timer.selector = aSelector; + timer.timer = [NSTimer timerWithTimeInterval:seconds + target:timer + selector:@selector(timerDidFire) + userInfo:nil + repeats:repeats]; + timer.timeInterval = seconds; + timer.runLoopMode = NSDefaultRunLoopMode; + return timer; +} + +- (void)dealloc +{ + [self.timer invalidate]; +} + +- (void)timerDidFire +{ + SUPPRESS_PERFORM_SELECTOR_LEAK_WARNING( + [self.target performSelector:self.selector withObject:nil] + ); +} + +- (BOOL)isValid +{ + return [self.timer isValid]; +} + +- (void)invalidate +{ + self.target = nil; + self.selector = nil; + [self.timer invalidate]; + self.timer = nil; +} + +- (BOOL)isScheduled +{ + if (!self.timer) { + return NO; + } + CFRunLoopRef runLoopRef = [[NSRunLoop currentRunLoop] getCFRunLoop]; + CFArrayRef arrayRef = CFRunLoopCopyAllModes(runLoopRef); + CFIndex count = CFArrayGetCount(arrayRef); + + for (CFIndex i = 0; i < count; ++i) { + CFStringRef runLoopMode = CFArrayGetValueAtIndex(arrayRef, i); + if (CFRunLoopContainsTimer(runLoopRef, (__bridge CFRunLoopTimerRef)self.timer, runLoopMode)) { + CFRelease(arrayRef); + return YES; + } + } + + CFRelease(arrayRef); + return NO; +} + +- (BOOL)scheduleNow +{ + if (![self.timer isValid]) { + MPLogDebug(@"Could not schedule invalidated MPTimer (%p).", self); + return NO; + } + + [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:self.runLoopMode]; + return YES; +} + +- (BOOL)pause +{ + NSTimeInterval secondsLeft; + if (self.isPaused) { + MPLogDebug(@"No-op: tried to pause an MPTimer (%p) that was already paused.", self); + return NO; + } + + if (![self.timer isValid]) { + MPLogDebug(@"Cannot pause invalidated MPTimer (%p).", self); + return NO; + } + + if (![self isScheduled]) { + MPLogDebug(@"No-op: tried to pause an MPTimer (%p) that was never scheduled.", self); + return NO; + } + + NSDate *fireDate = [self.timer fireDate]; + self.pauseDate = [NSDate date]; + secondsLeft = [fireDate timeIntervalSinceDate:self.pauseDate]; + if (secondsLeft <= 0) { + MPLogWarn(@"An MPTimer was somehow paused after it was supposed to fire."); + } else { + MPLogDebug(@"Paused MPTimer (%p) %.1f seconds left before firing.", self, secondsLeft); + } + + // Pause the timer by setting its fire date far into the future. + [self.timer setFireDate:[NSDate distantFuture]]; + self.isPaused = YES; + + return YES; +} + +- (BOOL)resume +{ + if (![self.timer isValid]) { + MPLogDebug(@"Cannot resume invalidated MPTimer (%p).", self); + return NO; + } + + if (!self.isPaused) { + MPLogDebug(@"No-op: tried to resume an MPTimer (%p) that was never paused.", self); + return NO; + } + + MPLogDebug(@"Resumed MPTimer (%p), should fire in %.1f seconds.", self.timeInterval); + + // Resume the timer. + NSDate *newFireDate = [NSDate dateWithTimeInterval:self.timeInterval sinceDate:[NSDate date]]; + [self.timer setFireDate:newFireDate]; + + if (![self isScheduled]) { + [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:self.runLoopMode]; + } + + self.isPaused = NO; + return YES; +} + +- (NSTimeInterval)initialTimeInterval +{ + return self.timeInterval; +} + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.h new file mode 100644 index 000000000..0f77145c1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.h @@ -0,0 +1,12 @@ +// +// MPUserInteractionGestureRecognizer.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@interface MPUserInteractionGestureRecognizer : UIGestureRecognizer + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.m new file mode 100644 index 000000000..23dc47c7d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/Utility/MPUserInteractionGestureRecognizer.m @@ -0,0 +1,45 @@ +// +// MPUserInteractionGestureRecognizer.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPUserInteractionGestureRecognizer.h" + +#import + +@implementation MPUserInteractionGestureRecognizer + +// Currently, we treat any touch as evidence of user interaction +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesBegan:touches withEvent:event]; + + if (self.state == UIGestureRecognizerStatePossible) { + self.state = UIGestureRecognizerStateRecognized; + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesMoved:touches withEvent:event]; + + self.state = UIGestureRecognizerStateFailed; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesEnded:touches withEvent:event]; + + self.state = UIGestureRecognizerStateFailed; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesCancelled:touches withEvent:event]; + + self.state = UIGestureRecognizerStateFailed; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.h new file mode 100644 index 000000000..5ad3e7d9a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.h @@ -0,0 +1,21 @@ +// +// MPVASTAd.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@class MPVASTInline; +@class MPVASTWrapper; + +@interface MPVASTAd : MPVASTModel + +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, copy, readonly) NSString *sequence; +@property (nonatomic, readonly) MPVASTInline *inlineAd; +@property (nonatomic, readonly) MPVASTWrapper *wrapper; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.m new file mode 100644 index 000000000..ceb1f334b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTAd.m @@ -0,0 +1,38 @@ +// +// MPVASTAd.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTAd.h" +#import "MPVASTInline.h" +#import "MPVASTWrapper.h" +#import "MPLogging.h" + +@implementation MPVASTAd + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + // The VAST spec (2.2.2.2) prohibits an element from having both an and a + // element. If both are present, we'll only allow the element. + if (_inlineAd && _wrapper) { + MPLogWarn(@"VAST element is not allowed to contain both an and a " + @". The will be ignored."); + _wrapper = nil; + } + } + return self; +} + ++ (NSDictionary *)modelMap +{ + return @{@"identifier": @"id", + @"sequence": @"sequence", + @"inlineAd": @[@"InLine", MPParseClass([MPVASTInline class])], + @"wrapper": @[@"Wrapper", MPParseClass([MPVASTWrapper class])]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.h new file mode 100644 index 000000000..07416a90d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.h @@ -0,0 +1,26 @@ +// +// MPVASTCompanionAd.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import +#import "MPVASTModel.h" + +@interface MPVASTCompanionAd : MPVASTModel + +@property (nonatomic, readonly) CGFloat assetHeight; +@property (nonatomic, readonly) CGFloat assetWidth; +@property (nonatomic, copy, readonly) NSURL *clickThroughURL; +@property (nonatomic, readonly) NSArray *clickTrackingURLs; +@property (nonatomic, readonly) CGFloat height; +@property (nonatomic, readonly) NSArray *HTMLResources; +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, readonly) NSArray *iframeResources; +@property (nonatomic, readonly) NSArray *staticResources; +@property (nonatomic, readonly) NSDictionary *trackingEvents; +@property (nonatomic, readonly) CGFloat width; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.m new file mode 100644 index 000000000..f97f26d18 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCompanionAd.m @@ -0,0 +1,52 @@ +// +// MPVASTCompanionAd.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTCompanionAd.h" +#import "MPVASTResource.h" +#import "MPVASTStringUtilities.h" +#import "MPVASTTrackingEvent.h" + +@implementation MPVASTCompanionAd + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + NSArray *trackingEvents = [self generateModelsFromDictionaryValue:dictionary[@"TrackingEvents"][@"Tracking"] + modelProvider:^id(NSDictionary *dictionary) { + return [[MPVASTTrackingEvent alloc] initWithDictionary:dictionary]; + }]; + NSMutableDictionary *eventsDictionary = [NSMutableDictionary dictionary]; + for (MPVASTTrackingEvent *event in trackingEvents) { + NSMutableArray *events = [eventsDictionary objectForKey:event.eventType]; + if (!events) { + [eventsDictionary setObject:[NSMutableArray array] forKey:event.eventType]; + events = [eventsDictionary objectForKey:event.eventType]; + } + [events addObject:event]; + } + _trackingEvents = eventsDictionary; + } + return self; +} + ++ (NSDictionary *)modelMap +{ + return @{@"assetHeight": @[@"assetHeight", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"assetWidth": @[@"assetWidth", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"height": @[@"height", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"width": @[@"width", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"clickThroughURL": @[@"CompanionClickThrough.text", MPParseURLFromString()], + @"clickTrackingURLs": @[@"CompanionClickTracking.text", MPParseArrayOf(MPParseURLFromString())], + @"viewTrackingURLs": @[@"IconViewTracking.text", MPParseArrayOf(MPParseURLFromString())], + @"identifier": @"id", + @"HTMLResources": @[@"HTMLResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))], + @"iframeResources": @[@"IFrameResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))], + @"staticResources": @[@"StaticResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.h new file mode 100644 index 000000000..125f86c7b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.h @@ -0,0 +1,21 @@ +// +// MPVASTCreative.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@class MPVASTLinearAd; + +@interface MPVASTCreative : MPVASTModel + +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, copy, readonly) NSString *sequence; +@property (nonatomic, copy, readonly) NSString *adID; +@property (nonatomic, readonly) MPVASTLinearAd *linearAd; +@property (nonatomic, readonly) NSArray *companionAds; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.m new file mode 100644 index 000000000..ea34ab89d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTCreative.m @@ -0,0 +1,23 @@ +// +// MPVASTCreative.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTCreative.h" +#import "MPVASTLinearAd.h" +#import "MPVASTCompanionAd.h" + +@implementation MPVASTCreative + ++ (NSDictionary *)modelMap +{ + return @{@"identifier": @"id", + @"sequence": @"sequence", + @"adID": @"adID", + @"linearAd": @[@"Linear", MPParseClass([MPVASTLinearAd class])], + @"companionAds": @[@"CompanionAds.Companion", MPParseArrayOf(MPParseClass([MPVASTCompanionAd class]))]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.h new file mode 100644 index 000000000..4594c4e42 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.h @@ -0,0 +1,23 @@ +// +// MPVASTDurationOffset.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +typedef NS_ENUM(NSUInteger, MPVASTDurationOffsetType) { + MPVASTDurationOffsetTypeAbsolute, + MPVASTDurationOffsetTypePercentage, +}; + +@interface MPVASTDurationOffset : MPVASTModel + +@property (nonatomic, readonly) MPVASTDurationOffsetType type; +@property (nonatomic, copy, readonly) NSString *offset; + +- (NSTimeInterval)timeIntervalForVideoWithDuration:(NSTimeInterval)duration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.m new file mode 100644 index 000000000..1b86d359b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTDurationOffset.m @@ -0,0 +1,49 @@ +// +// MPVASTDurationOffset.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTDurationOffset.h" +#import "MPVASTStringUtilities.h" + +@implementation MPVASTDurationOffset + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + _offset = dictionary[@"offset"] ?: dictionary[@"skipoffset"]; + if (!_offset) { + return nil; + } + + BOOL isPercentage = [MPVASTStringUtilities stringRepresentsNonNegativePercentage:_offset]; + BOOL isDuration = [MPVASTStringUtilities stringRepresentsNonNegativeDuration:_offset]; + if (!isPercentage && !isDuration) { + return nil; + } + + _type = isDuration ? MPVASTDurationOffsetTypeAbsolute : MPVASTDurationOffsetTypePercentage; + } + return self; +} + +- (NSTimeInterval)timeIntervalForVideoWithDuration:(NSTimeInterval)duration +{ + if (duration < 0) { + return 0; + } + + if (self.type == MPVASTDurationOffsetTypeAbsolute) { + return [MPVASTStringUtilities timeIntervalFromString:self.offset]; + } else if (self.type == MPVASTDurationOffsetTypePercentage) { + NSInteger percentage = [MPVASTStringUtilities percentageFromString:self.offset]; + return duration * percentage / 100.0f; + } else { + return 0; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.h new file mode 100644 index 000000000..38460d72e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.h @@ -0,0 +1,35 @@ +// +// MPVASTIndustryIcon.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import +#import "MPVASTModel.h" + +@class MPVASTDurationOffset; +@class MPVASTResource; + +@interface MPVASTIndustryIcon : MPVASTModel + +@property (nonatomic, copy, readonly) NSString *program; +@property (nonatomic, readonly) CGFloat height; +@property (nonatomic, readonly) CGFloat width; +@property (nonatomic, copy, readonly) NSString *xPosition; +@property (nonatomic, copy, readonly) NSString *yPosition; + +@property (nonatomic, copy, readonly) NSString *apiFramework; +@property (nonatomic, readonly) NSTimeInterval duration; +@property (nonatomic, readonly) MPVASTDurationOffset *offset; + +@property (nonatomic, copy, readonly) NSURL *clickThroughURL; +@property (nonatomic, readonly) NSArray *clickTrackingURLs; +@property (nonatomic, readonly) NSArray *viewTrackingURLs; + +@property (nonatomic, readonly) MPVASTResource *HTMLResource; +@property (nonatomic, readonly) MPVASTResource *iframeResource; +@property (nonatomic, readonly) MPVASTResource *staticResource; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.m new file mode 100644 index 000000000..27b838829 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTIndustryIcon.m @@ -0,0 +1,34 @@ +// +// MPVASTIndustryIcon.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTIndustryIcon.h" +#import "MPVASTDurationOffset.h" +#import "MPVASTResource.h" +#import "MPVASTStringUtilities.h" + +@implementation MPVASTIndustryIcon + ++ (NSDictionary *)modelMap +{ + return @{@"program": @"program", + @"height": @[@"height", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"width": @[@"width", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"xPosition": @"xPosition", + @"yPosition": @"yPosition", + @"clickThroughURL": @[@"IconClicks.IconClickThrough.text", MPParseURLFromString()], + @"clickTrackingURLs": @[@"IconClicks.IconClickTracking.text", MPParseArrayOf(MPParseURLFromString())], + @"viewTrackingURLs": @[@"IconViewTracking.text", MPParseArrayOf(MPParseURLFromString())], + @"apiFramework": @"apiFramework", + @"duration": @[@"duration", MPParseTimeIntervalFromDurationString()], + @"offset": @[@"@self", MPParseClass([MPVASTDurationOffset class])], + @"HTMLResource": @[@"HTMLResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))], + @"iframeResource": @[@"IFrameResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))], + @"staticResource": @[@"StaticResource", MPParseArrayOf(MPParseClass([MPVASTResource class]))]}; + +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.h new file mode 100644 index 000000000..b64333849 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.h @@ -0,0 +1,18 @@ +// +// MPVASTInline.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@interface MPVASTInline : MPVASTModel + +@property (nonatomic, readonly) NSArray *creatives; +@property (nonatomic, readonly) NSArray *errorURLs; +@property (nonatomic, readonly) NSDictionary *extensions; +@property (nonatomic, readonly) NSArray *impressionURLs; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.m new file mode 100644 index 000000000..3b73b505a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTInline.m @@ -0,0 +1,32 @@ +// +// MPVASTInline.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTInline.h" +#import "MPVASTCreative.h" + +@implementation MPVASTInline + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + _extensions = [self generateModelFromDictionaryValue:dictionary[@"Extensions"] + modelProvider:^id(NSDictionary *dictionary) { + return dictionary; + }]; + } + return self; +} + ++ (NSDictionary *)modelMap +{ + return @{@"creatives": @[@"Creatives.Creative", MPParseArrayOf(MPParseClass([MPVASTCreative class]))], + @"errorURLs": @[@"Error.text", MPParseArrayOf(MPParseURLFromString())], + @"impressionURLs": @[@"Impression.text", MPParseArrayOf(MPParseURLFromString())]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.h new file mode 100644 index 000000000..905c0e4db --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.h @@ -0,0 +1,30 @@ +// +// MPVASTLinearAd.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@class MPVASTDurationOffset; +@class MPVASTMediaFile; + +@interface MPVASTLinearAd : MPVASTModel + +@property (nonatomic, copy, readonly) NSURL *clickThroughURL; +@property (nonatomic, readonly) NSArray *clickTrackingURLs; +@property (nonatomic, readonly) NSArray *customClickURLs; +@property (nonatomic, readonly) NSTimeInterval duration; +@property (nonatomic, readonly) NSArray *industryIcons; +@property (nonatomic, readonly) NSArray *mediaFiles; +@property (nonatomic, readonly) MPVASTDurationOffset *skipOffset; +@property (nonatomic, readonly) NSDictionary *trackingEvents; + +@end + +@interface MPVASTLinearAd (Media) +@property (nonatomic, readonly) MPVASTMediaFile *highestBitrateMediaFile; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.m new file mode 100644 index 000000000..c5b3d9800 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTLinearAd.m @@ -0,0 +1,87 @@ +// +// MPVASTLinearAd.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTLinearAd.h" +#import "MPVASTDurationOffset.h" +#import "MPVASTIndustryIcon.h" +#import "MPVASTMediaFile.h" +#import "MPVASTStringUtilities.h" +#import "MPVASTTrackingEvent.h" + +@interface MPVASTLinearAd () + +@property (nonatomic, readwrite) NSArray *clickTrackingURLs; +@property (nonatomic, readwrite) NSArray *customClickURLs; +@property (nonatomic, readwrite) NSArray *industryIcons; +@property (nonatomic, readwrite) NSDictionary *trackingEvents; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVASTLinearAd + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + NSArray *trackingEvents = [self generateModelsFromDictionaryValue:dictionary[@"TrackingEvents"][@"Tracking"] + modelProvider:^id(NSDictionary *dictionary) { + return [[MPVASTTrackingEvent alloc] initWithDictionary:dictionary]; + }]; + NSMutableDictionary *eventsDictionary = [NSMutableDictionary dictionary]; + for (MPVASTTrackingEvent *event in trackingEvents) { + NSMutableArray *events = [eventsDictionary objectForKey:event.eventType]; + if (!events) { + [eventsDictionary setObject:[NSMutableArray array] forKey:event.eventType]; + events = [eventsDictionary objectForKey:event.eventType]; + } + [events addObject:event]; + } + _trackingEvents = eventsDictionary; + } + return self; +} + ++ (NSDictionary *)modelMap +{ + return @{@"clickThroughURL": @[@"VideoClicks.ClickThrough.text", MPParseURLFromString()], + @"clickTrackingURLs": @[@"VideoClicks.ClickTracking.text", MPParseArrayOf(MPParseURLFromString())], + @"customClickURLs": @[@"VideoClicks.CustomClick.text", MPParseArrayOf(MPParseURLFromString())], + @"duration": @[@"Duration.text", MPParseTimeIntervalFromDurationString()], + @"industryIcons": @[@"Icons.Icon", MPParseArrayOf(MPParseClass([MPVASTIndustryIcon class]))], + @"mediaFiles": @[@"MediaFiles.MediaFile", MPParseArrayOf(MPParseClass([MPVASTMediaFile class]))], + @"skipOffset": @[@"@self", MPParseClass([MPVASTDurationOffset class])]}; +} + +@end + +@implementation MPVASTLinearAd (Media) + +// Static set of supported MIME types for native video. +- (NSSet *)validVideoMimeTypes { + static dispatch_once_t onceToken; + static NSSet * validVideoMimeTypes = nil; + dispatch_once(&onceToken, ^{ + validVideoMimeTypes = [NSSet setWithObjects:@"video/quicktime", @"video/mp4", @"video/3gpp", @"video/3gpp2", @"video/x-m4v", nil]; + }); + + return validVideoMimeTypes; +} + +// Filters out unsupported media files and selects the highest bitrate video +- (MPVASTMediaFile *)highestBitrateMediaFile { + NSPredicate * predicate = [NSPredicate predicateWithFormat:@"mimeType IN %@", self.validVideoMimeTypes]; + NSArray * filteredMediaFiles = [self.mediaFiles filteredArrayUsingPredicate:predicate]; + NSArray * sortedMediaFiles = [filteredMediaFiles sortedArrayUsingComparator:^NSComparisonResult(MPVASTMediaFile * a, MPVASTMediaFile * b) { + return a.bitrate < b.bitrate; + }]; + + return (sortedMediaFiles.count > 0 ? sortedMediaFiles[0] : nil); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.h new file mode 100644 index 000000000..b105fa554 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.h @@ -0,0 +1,15 @@ +// +// MPVASTMacroProcessor.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPVASTMacroProcessor : NSObject + ++ (NSURL *)macroExpandedURLForURL:(NSURL *)URL errorCode:(NSString *)errorCode; ++ (NSURL *)macroExpandedURLForURL:(NSURL *)URL errorCode:(NSString *)errorCode videoTimeOffset:(NSTimeInterval)timeOffset videoAssetURL:(NSURL *)videoAssetURL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.m new file mode 100644 index 000000000..40e758975 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMacroProcessor.m @@ -0,0 +1,48 @@ +// +// MPVASTMacroProcessor.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTMacroProcessor.h" +#import "MPGlobal.h" +#import "MPVASTStringUtilities.h" + +@implementation MPVASTMacroProcessor + ++ (NSURL *)macroExpandedURLForURL:(NSURL *)URL errorCode:(NSString *)errorCode +{ + return [self macroExpandedURLForURL:URL errorCode:errorCode videoTimeOffset:-1 videoAssetURL:nil]; +} + ++ (NSURL *)macroExpandedURLForURL:(NSURL *)URL errorCode:(NSString *)errorCode videoTimeOffset:(NSTimeInterval)timeOffset videoAssetURL:(NSURL *)assetURL +{ + NSMutableString *URLString = [[URL absoluteString] mutableCopy]; + + NSString *trimmedErrorCode = [errorCode stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if ([trimmedErrorCode length]) { + [URLString replaceOccurrencesOfString:@"[ERRORCODE]" withString:errorCode options:0 range:NSMakeRange(0, [URLString length])]; + [URLString replaceOccurrencesOfString:@"%5BERRORCODE%5D" withString:errorCode options:0 range:NSMakeRange(0, [URLString length])]; + } + + if (timeOffset >= 0) { + NSString *timeOffsetString = [MPVASTStringUtilities stringFromTimeInterval:timeOffset]; + [URLString replaceOccurrencesOfString:@"[CONTENTPLAYHEAD]" withString:timeOffsetString options:0 range:NSMakeRange(0, [URLString length])]; + [URLString replaceOccurrencesOfString:@"%5BCONTENTPLAYHEAD%5D" withString:timeOffsetString options:0 range:NSMakeRange(0, [URLString length])]; + } + + if (assetURL) { + NSString *encodedAssetURLString = [[assetURL absoluteString] mp_URLEncodedString]; + [URLString replaceOccurrencesOfString:@"[ASSETURI]" withString:encodedAssetURLString options:0 range:NSMakeRange(0, [URLString length])]; + [URLString replaceOccurrencesOfString:@"%5BASSETURI%5D" withString:encodedAssetURLString options:0 range:NSMakeRange(0, [URLString length])]; + } + + NSString *cachebuster = [NSString stringWithFormat:@"%u", arc4random() % 90000000 + 10000000]; + [URLString replaceOccurrencesOfString:@"[CACHEBUSTING]" withString:cachebuster options:0 range:NSMakeRange(0, [URLString length])]; + [URLString replaceOccurrencesOfString:@"%5BCACHEBUSTING%5D" withString:cachebuster options:0 range:NSMakeRange(0, [URLString length])]; + + return [NSURL URLWithString:URLString]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.h new file mode 100644 index 000000000..4a42b87d5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.h @@ -0,0 +1,22 @@ +// +// MPVASTManager.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTResponse.h" + +typedef enum { + MPVASTErrorXMLParseFailure, + MPVASTErrorExceededMaximumWrapperDepth, + MPVASTErrorNoAdsFound +} MPVASTError; + +@interface MPVASTManager : NSObject + ++ (void)fetchVASTWithURL:(NSURL *)URL completion:(void (^)(MPVASTResponse *, NSError *))completion; ++ (void)fetchVASTWithData:(NSData *)data completion:(void (^)(MPVASTResponse *, NSError *))completion; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.m new file mode 100644 index 000000000..765f4dadb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTManager.m @@ -0,0 +1,136 @@ +// +// MPVASTManager.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTManager.h" +#import "MPVASTAd.h" +#import "MPVASTWrapper.h" +#import "MPXMLParser.h" + +@interface MPVASTWrapper (MPVASTManager) + +@property (nonatomic, readwrite) MPVASTResponse *wrappedVASTResponse; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static const NSInteger kMaximumWrapperDepth = 10; +static NSString * const kMPVASTManagerErrorDomain = @"com.mopub.MPVASTManager"; + +@implementation MPVASTManager + ++ (void)fetchVASTWithURL:(NSURL *)URL completion:(void (^)(MPVASTResponse *, NSError *))completion +{ + [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:URL] + queue:[NSOperationQueue mainQueue] + completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { + [self fetchVASTWithData:data completion:completion]; + }]; +} + ++ (void)fetchVASTWithData:(NSData *)data completion:(void (^)(MPVASTResponse *, NSError *))completion +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self parseVASTResponseFromData:data depth:0 completion:^(MPVASTResponse *response, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + completion(nil, error); + } else { + completion(response, nil); + } + }); + }]; + }); +} + ++ (void)parseVASTResponseFromData:(NSData *)data depth:(NSInteger)depth completion:(void (^)(MPVASTResponse *response, NSError *error))completion +{ + if (depth >= kMaximumWrapperDepth) { + completion(nil, [NSError errorWithDomain:kMPVASTManagerErrorDomain code:MPVASTErrorExceededMaximumWrapperDepth userInfo:nil]); + return; + } + + NSError *XMLParserError = nil; + MPXMLParser *parser = [[MPXMLParser alloc] init]; + NSDictionary *dictionary = [parser dictionaryWithData:data error:&XMLParserError]; + if (XMLParserError) { + completion(nil, [NSError errorWithDomain:kMPVASTManagerErrorDomain code:MPVASTErrorXMLParseFailure userInfo:nil]); + return; + } + + MPVASTResponse *VASTResponse = [[MPVASTResponse alloc] initWithDictionary:dictionary]; + NSArray *wrappers = [self wrappersForVASTResponse:VASTResponse]; + if ([wrappers count] == 0) { + if ([self VASTResponseContainsAtLeastOneAd:VASTResponse]) { + completion(VASTResponse, nil); + return; + } else { + completion(nil, [NSError errorWithDomain:kMPVASTManagerErrorDomain code:MPVASTErrorNoAdsFound userInfo:nil]); + return; + } + } + + __block NSInteger wrappersFetched = 0; + for (MPVASTWrapper *wrapper in wrappers) { + [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:wrapper.VASTAdTagURI] + queue:[NSOperationQueue mainQueue] + completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + if (connectionError) { + wrapper.wrappedVASTResponse = nil; + } else if (data) { + [self parseVASTResponseFromData:data depth:depth + 1 completion:^(MPVASTResponse *response, NSError *error) { + if (error) { + completion(nil, error); + return; + } + + wrapper.wrappedVASTResponse = response; + wrappersFetched++; + + // Once we've fetched all wrappers within the VAST + // response, we can call the top-level completion + // handler. + if (wrappersFetched == [wrappers count]) { + if ([self VASTResponseContainsAtLeastOneAd:VASTResponse]) { + completion(VASTResponse, nil); + return; + } else { + completion(nil, [NSError errorWithDomain:kMPVASTManagerErrorDomain code:MPVASTErrorNoAdsFound userInfo:nil]); + return; + } + } + }]; + } + }); + }]; + } +} + ++ (NSArray *)wrappersForVASTResponse:(MPVASTResponse *)response +{ + NSMutableArray *wrappers = [NSMutableArray array]; + for (MPVASTAd *ad in response.ads) { + if (ad.wrapper) { + [wrappers addObject:ad.wrapper]; + } + } + return wrappers; +} + ++ (BOOL)VASTResponseContainsAtLeastOneAd:(MPVASTResponse *)response +{ + for (MPVASTAd *ad in response.ads) { + if (ad.inlineAd || ad.wrapper.wrappedVASTResponse) { + return YES; + } + } + return NO; +} + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.h new file mode 100644 index 000000000..70bf6b9bd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.h @@ -0,0 +1,22 @@ +// +// MPVASTMediaFile.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import +#import "MPVASTModel.h" + +@interface MPVASTMediaFile : MPVASTModel + +@property (nonatomic, copy, readonly) NSString *identifier; +@property (nonatomic, copy, readonly) NSString *delivery; +@property (nonatomic, copy, readonly) NSString *mimeType; +@property (nonatomic, readonly) double bitrate; +@property (nonatomic, readonly) CGFloat width; +@property (nonatomic, readonly) CGFloat height; +@property (nonatomic, copy, readonly) NSURL *URL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.m new file mode 100644 index 000000000..7e0377e6f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTMediaFile.m @@ -0,0 +1,24 @@ +// +// MPVASTMediaFile.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTMediaFile.h" +#import "MPVASTStringUtilities.h" + +@implementation MPVASTMediaFile + ++ (NSDictionary *)modelMap +{ + return @{@"bitrate": @[@"bitrate", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"height": @[@"height", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"width": @[@"width", MPParseNumberFromString(NSNumberFormatterDecimalStyle)], + @"identifier": @"id", + @"delivery": @"delivery", + @"mimeType": @"type", + @"URL": @[@"text", MPParseURLFromString()]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.h new file mode 100644 index 000000000..bbee686b2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.h @@ -0,0 +1,68 @@ +// +// MPVASTModel.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPObjectMapper + +- (id)mappedObjectFromSourceObject:(id)object; +- (Class)requiredSourceObjectClass; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +id MPParseArrayOf(id internalMapper); +id MPParseURLFromString(); +id MPParseNumberFromString(NSNumberFormatterStyle numberStyle); +id MPParseTimeIntervalFromDurationString(); +id MPParseClass(Class destinationClass); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNSStringToNSURLMapper : NSObject +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPDurationStringToTimeIntervalMapper : NSObject +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPStringToNumberMapper : NSObject + +- (id)initWithNumberStyle:(NSNumberFormatterStyle)numberStyle; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPClassMapper : NSObject + +- (id)initWithDestinationClass:(Class)destinationClass; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNSArrayMapper : NSObject + +- (id)initWithInternalMapper:(id)mapper; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPVASTModel : NSObject + ++ (NSDictionary *)modelMap; +- (instancetype)initWithDictionary:(NSDictionary *)dictionary; +- (id)generateModelFromDictionaryValue:(id)value modelProvider:(id(^)(id))provider; +- (NSArray *)generateModelsFromDictionaryValue:(id)value modelProvider:(id(^)(id))provider; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.m new file mode 100644 index 000000000..700ade063 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTModel.m @@ -0,0 +1,335 @@ +// +// MPVASTModel.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTModel.h" +#import "MPVASTStringUtilities.h" +#import "MPLogging.h" +#import + +id MPParseArrayOf(id internalMapper) +{ + return [[MPNSArrayMapper alloc] initWithInternalMapper:internalMapper]; +} + +id MPParseURLFromString() +{ + return [[MPNSStringToNSURLMapper alloc] init]; +} + +id MPParseNumberFromString(NSNumberFormatterStyle numberStyle) +{ + return [[MPStringToNumberMapper alloc] initWithNumberStyle:numberStyle]; +} + +id MPParseTimeIntervalFromDurationString() +{ + return [[MPDurationStringToTimeIntervalMapper alloc] init]; +} + +id MPParseClass(Class destinationClass) +{ + return [[MPClassMapper alloc] initWithDestinationClass:destinationClass]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPNSStringToNSURLMapper + +- (id)mappedObjectFromSourceObject:(id)object +{ + NSString *URLString = [object stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + return [NSURL URLWithString:URLString]; +} + +- (Class)requiredSourceObjectClass +{ + return [NSString class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPDurationStringToTimeIntervalMapper + +- (id)mappedObjectFromSourceObject:(id)object +{ + return @([MPVASTStringUtilities timeIntervalFromString:object]); +} + +- (Class)requiredSourceObjectClass +{ + return [NSString class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPStringToNumberMapper () + +@property (nonatomic) NSNumberFormatter *numberFormatter; + +@end + +@implementation MPStringToNumberMapper + +- (id)init +{ + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (id)initWithNumberStyle:(NSNumberFormatterStyle)numberStyle +{ + self = [super init]; + if (self) { + _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = numberStyle; + } + return self; +} + +- (id)mappedObjectFromSourceObject:(id)object +{ + return [self.numberFormatter numberFromString:object]; +} + +- (Class)requiredSourceObjectClass +{ + return [NSString class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPClassMapper () + +@property (nonatomic) Class destinationClass; + +@end + +@implementation MPClassMapper + +- (id)init +{ + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (id)initWithDestinationClass:(Class)destinationClass +{ + self = [super init]; + if (self) { + _destinationClass = destinationClass; + } + return self; +} + +- (id)mappedObjectFromSourceObject:(id)object +{ + if (![self.destinationClass isSubclassOfClass:[MPVASTModel class]] || + ![self.destinationClass instancesRespondToSelector:@selector(initWithDictionary:)]) { + return nil; + } + + return [[self.destinationClass alloc] initWithDictionary:object]; +} + +- (Class)requiredSourceObjectClass +{ + return [NSDictionary class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNSArrayMapper () + +@property (nonatomic) id mapper; + +@end + +@implementation MPNSArrayMapper + +- (id)init +{ + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (id)initWithInternalMapper:(id)mapper +{ + self = [super init]; + if (self) { + _mapper = mapper; + } + return self; +} + +- (id)mappedObjectFromSourceObject:(id)object +{ + NSMutableArray *result = [NSMutableArray array]; + + if ([object isKindOfClass:[NSArray class]]) { + for (id obj in object) { + id model = [self.mapper mappedObjectFromSourceObject:obj]; + if (model) { + [result addObject:model]; + } + } + } else if ([object isKindOfClass:[self.mapper requiredSourceObjectClass]]) { + id model = [self.mapper mappedObjectFromSourceObject:object]; + if (model) { + [result addObject:model]; + } + } + + return result; +} + +- (Class)requiredSourceObjectClass +{ + return [NSArray class]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVASTModel + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super init]; + if (self) { + if (!dictionary) { + return nil; + } + + NSDictionary *modelMap = [[self class] modelMap]; + for (NSString *key in modelMap) { + if ([self hasPropertyNamed:key]) { + id modelMapValue = modelMap[key]; + + if ([modelMapValue isKindOfClass:[NSString class]]) { + // The simple case: grab the value corresponding to the given key path and + // assign it to the property. + id value = [dictionary valueForKeyPath:modelMapValue]; + if (value) { + [self setValue:value forKey:key]; + } + } else if ([modelMapValue isKindOfClass:[NSArray class]] && [modelMapValue count] == 2) { + NSString *dictionaryKeyPath = modelMapValue[0]; + id mapper = modelMapValue[1]; + + if ([mapper conformsToProtocol:@protocol(MPObjectMapper)]) { + id sourceObject = [dictionary valueForKeyPath:dictionaryKeyPath]; + if (sourceObject) { + id model = [mapper mappedObjectFromSourceObject:sourceObject]; + if (model) { + [self setValue:model forKey:key]; + } + } + } + } else { + MPLogError(@"Could not populate %@ of class %@ because its mapper is invalid.", + key, NSStringFromClass([self class])); + } + } + } + } + return self; +} + ++ (NSDictionary *)modelMap +{ + // Implemented by subclasses. + return nil; +} + +- (id)generateModelFromDictionaryValue:(id)value modelProvider:(id(^)(id))provider { + if (value && [value isKindOfClass:[NSArray class]] && [value count] > 0) { + return provider(value[0]); + } else if (value && [value isKindOfClass:[NSDictionary class]]) { + return provider(value); + } else { + return nil; + } +} + +- (NSArray *)generateModelsFromDictionaryValue:(id)value modelProvider:(id(^)(id))provider { + NSMutableArray *models = [NSMutableArray array]; + + if (value && [value isKindOfClass:[NSArray class]]) { + for (NSDictionary *dictionary in value) { + id model = provider(dictionary); + if (model) { + [models addObject:model]; + } + } + } else if (value && [value isKindOfClass:[NSDictionary class]]) { + id model = provider(value); + if (model) { + [models addObject:model]; + } + } + + return [models copy]; +} + +#pragma mark - Internal + +- (BOOL)hasPropertyNamed:(NSString *)name +{ + // This method uses the objc runtime API to check whether the current model class has a given + // property. After we grab the set of properties for a given class, we cache it for efficiency. + + static NSMutableDictionary *propertyNamesForClass; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + propertyNamesForClass = [NSMutableDictionary dictionary]; + }); + + NSString *className = NSStringFromClass([self class]); + NSMutableSet *propertyNames = propertyNamesForClass[className]; + + if (!propertyNames) { + unsigned int propertyCount; + objc_property_t *properties = class_copyPropertyList([self class], &propertyCount); + propertyNames = [NSMutableSet setWithCapacity:propertyCount]; + for (unsigned int i = 0; i < propertyCount; i++) { + objc_property_t property = properties[i]; + [propertyNames addObject:[NSString stringWithUTF8String:property_getName(property)]]; + } + propertyNamesForClass[className] = propertyNames; + free(properties); + } + + return [propertyNames containsObject:name]; +} + +- (NSString *)description +{ + NSMutableString *descriptionString = [NSMutableString stringWithFormat:@"%@:", NSStringFromClass([self class])]; + + unsigned int propertyCount; + objc_property_t *properties = class_copyPropertyList([self class], &propertyCount); + + for (unsigned int i = 0; i < propertyCount; i++) { + objc_property_t property = properties[i]; + NSString *propertyName = [[NSString alloc] initWithUTF8String:property_getName(property)]; + [descriptionString appendFormat:@"\n\t%s = %s", propertyName.UTF8String, [[self valueForKey:propertyName] description].UTF8String]; + } + + free(properties); + return descriptionString; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.h new file mode 100644 index 000000000..82b642b28 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.h @@ -0,0 +1,16 @@ +// +// MPVASTResource.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@interface MPVASTResource : MPVASTModel + +@property (nonatomic, readonly) NSString *content; +@property (nonatomic, readonly) NSString *staticCreativeType; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.m new file mode 100644 index 000000000..7c0ce3779 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResource.m @@ -0,0 +1,18 @@ +// +// MPVASTResource.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTResource.h" + +@implementation MPVASTResource + ++ (NSDictionary *)modelMap +{ + return @{@"content": @"text", + @"staticCreativeType": @"creativeType"}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.h new file mode 100644 index 000000000..3d6f70279 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.h @@ -0,0 +1,29 @@ +// +// MPVASTResponse.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +#import "MPVASTAd.h" +#import "MPVASTCompanionAd.h" +#import "MPVASTCreative.h" +#import "MPVASTDurationOffset.h" +#import "MPVASTIndustryIcon.h" +#import "MPVASTInline.h" +#import "MPVASTLinearAd.h" +#import "MPVASTMediaFile.h" +#import "MPVASTResource.h" +#import "MPVASTTrackingEvent.h" +#import "MPVASTWrapper.h" + +@interface MPVASTResponse : MPVASTModel + +@property (nonatomic, readonly) NSArray *ads; +@property (nonatomic, readonly) NSArray *errorURLs; +@property (nonatomic, copy, readonly) NSString *version; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.m new file mode 100644 index 000000000..fa93b49b1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTResponse.m @@ -0,0 +1,28 @@ +// +// MPVASTResponse.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTResponse.h" + +@interface MPVASTResponse () + +@property (nonatomic) NSArray *ads; +@property (nonatomic) NSArray *errorURLs; +@property (nonatomic, copy) NSString *version; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVASTResponse + ++ (NSDictionary *)modelMap +{ + return @{@"ads": @[@"VAST.Ad", MPParseArrayOf(MPParseClass([MPVASTAd class]))], + @"version": @"VAST.version"}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.h new file mode 100644 index 000000000..13a89dca7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.h @@ -0,0 +1,19 @@ +// +// MPVASTStringUtilities.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPVASTStringUtilities : NSObject + ++ (double)doubleFromString:(NSString *)string; ++ (BOOL)stringRepresentsNonNegativePercentage:(NSString *)string; ++ (BOOL)stringRepresentsNonNegativeDuration:(NSString *)string; ++ (NSInteger)percentageFromString:(NSString *)string; ++ (NSTimeInterval)timeIntervalFromString:(NSString *)string; ++ (NSString *)stringFromTimeInterval:(NSTimeInterval)timeInterval; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.m new file mode 100644 index 000000000..14d6e167e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTStringUtilities.m @@ -0,0 +1,146 @@ +// +// MPVASTStringUtilities.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTStringUtilities.h" + +// Expected format is a decimal number from 0-100 followed by the % sign. +static NSString * const kPercentageRegexString = @"^(\\d?\\d(\\.\\d*)?|100(?:\\.0*)?)%$"; +static dispatch_once_t percentageRegexOnceToken; +static NSRegularExpression *percentageRegex; + +// Expected format is either HH:mm:ss.mmm or simply a floating-point number. +static NSString * const kDurationRegexString = @"^(\\d{2}):([0-5]\\d):([0-5]\\d(?:\\.\\d{1,3})?)|(^[0-9]*\\.?[0-9]+$)"; +static dispatch_once_t durationRegexOnceToken; +static NSRegularExpression *durationRegex; + +@implementation MPVASTStringUtilities + ++ (double)doubleFromString:(NSString *)string +{ + static NSNumberFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + }); + + return [[formatter numberFromString:string] doubleValue]; +} + ++ (BOOL)stringRepresentsNonNegativePercentage:(NSString *)string +{ + dispatch_once(&percentageRegexOnceToken, ^{ + percentageRegex = [NSRegularExpression regularExpressionWithPattern:kPercentageRegexString options:0 error:nil]; + }); + + NSArray *matches = [percentageRegex matchesInString:string options:0 range:NSMakeRange(0, [string length])]; + + if (![matches count]) { + return NO; + } + + NSTextCheckingResult *match = matches[0]; + return (match.range.location != NSNotFound); +} + ++ (BOOL)stringRepresentsNonNegativeDuration:(NSString *)string +{ + dispatch_once(&durationRegexOnceToken, ^{ + durationRegex = [NSRegularExpression regularExpressionWithPattern:kDurationRegexString options:0 error:nil]; + }); + + NSArray *matches = [durationRegex matchesInString:string options:0 range:NSMakeRange(0, [string length])]; + + if (![matches count]) { + return NO; + } + + NSTextCheckingResult *match = matches[0]; + return (match.range.location != NSNotFound); +} + ++ (NSInteger)percentageFromString:(NSString *)string +{ + dispatch_once(&percentageRegexOnceToken, ^{ + percentageRegex = [NSRegularExpression regularExpressionWithPattern:kPercentageRegexString options:0 error:nil]; + }); + + if (![string length]) { + return 0; + } + + NSArray *matches = [percentageRegex matchesInString:string options:0 range:NSMakeRange(0, [string length])]; + if ([matches count]) { + NSTextCheckingResult *match = matches[0]; + if (match.range.location == NSNotFound) { + return 0; + } + + return [[string substringWithRange:[match rangeAtIndex:1]] integerValue]; + } else { + return 0; + } +} + ++ (NSTimeInterval)timeIntervalFromString:(NSString *)string +{ + dispatch_once(&durationRegexOnceToken, ^{ + durationRegex = [NSRegularExpression regularExpressionWithPattern:kDurationRegexString options:0 error:nil]; + }); + + if (![string length]) { + return 0; + } + + NSArray *matches = [durationRegex matchesInString:string options:0 range:NSMakeRange(0, [string length])]; + + if (![matches count]) { + return 0; + } + + NSTextCheckingResult *match = matches[0]; + if (match.range.location == NSNotFound) { + return 0; + } + + // This is the case where the string is simply a floating-point number. + if ([match rangeAtIndex:4].location != NSNotFound) { + return [[string substringWithRange:[match rangeAtIndex:4]] doubleValue]; + } + + // Fail if hours, minutes, or seconds are missing. + if ([match rangeAtIndex:1].location == NSNotFound || + [match rangeAtIndex:2].location == NSNotFound || + [match rangeAtIndex:3].location == NSNotFound) { + return 0; + } + + NSInteger hours = 0; + NSInteger minutes = 0; + double seconds = 0; + + hours = [[string substringWithRange:[match rangeAtIndex:1]] integerValue]; + minutes = [[string substringWithRange:[match rangeAtIndex:2]] integerValue]; + seconds = [[string substringWithRange:[match rangeAtIndex:3]] doubleValue]; + + return hours * 60 * 60 + minutes * 60 + seconds; +} + ++ (NSString *)stringFromTimeInterval:(NSTimeInterval)timeInterval +{ + if (timeInterval < 0) { + return @"00:00:00.000"; + } + + NSInteger flooredTimeInterval = (NSInteger)timeInterval; + NSInteger hours = flooredTimeInterval / 3600; + NSInteger minutes = (flooredTimeInterval / 60) % 60; + NSTimeInterval seconds = fmod(timeInterval, 60); + return [NSString stringWithFormat:@"%02ld:%02ld:%06.3f", (long)hours, (long)minutes, seconds]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.h new file mode 100644 index 000000000..a9c41044b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.h @@ -0,0 +1,39 @@ +// +// MPVASTTrackingEvent.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@class MPVASTDurationOffset; + +extern NSString * const MPVASTTrackingEventTypeCreativeView; +extern NSString * const MPVASTTrackingEventTypeStart; +extern NSString * const MPVASTTrackingEventTypeFirstQuartile; +extern NSString * const MPVASTTrackingEventTypeMidpoint; +extern NSString * const MPVASTTrackingEventTypeThirdQuartile; +extern NSString * const MPVASTTrackingEventTypeComplete; +extern NSString * const MPVASTTrackingEventTypeMute; +extern NSString * const MPVASTTrackingEventTypeUnmute; +extern NSString * const MPVASTTrackingEventTypePause; +extern NSString * const MPVASTTrackingEventTypeRewind; +extern NSString * const MPVASTTrackingEventTypeResume; +extern NSString * const MPVASTTrackingEventTypeFullscreen; +extern NSString * const MPVASTTrackingEventTypeExitFullscreen; +extern NSString * const MPVASTTrackingEventTypeExpand; +extern NSString * const MPVASTTrackingEventTypeCollapse; +extern NSString * const MPVASTTrackingEventTypeAcceptInvitationLinear; +extern NSString * const MPVASTTrackingEventTypeCloseLinear; +extern NSString * const MPVASTTrackingEventTypeSkip; +extern NSString * const MPVASTTrackingEventTypeProgress; + +@interface MPVASTTrackingEvent : MPVASTModel + +@property (nonatomic, copy, readonly) NSString *eventType; +@property (nonatomic, copy, readonly) NSURL *URL; +@property (nonatomic, readonly) MPVASTDurationOffset *progressOffset; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.m new file mode 100644 index 000000000..a89a12229 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTTrackingEvent.m @@ -0,0 +1,50 @@ +// +// MPVASTTrackingEvent.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTTrackingEvent.h" +#import "MPVASTDurationOffset.h" + +NSString * const MPVASTTrackingEventTypeCreativeView = @"creativeView"; +NSString * const MPVASTTrackingEventTypeStart = @"start"; +NSString * const MPVASTTrackingEventTypeFirstQuartile = @"firstQuartile"; +NSString * const MPVASTTrackingEventTypeMidpoint = @"midpoint"; +NSString * const MPVASTTrackingEventTypeThirdQuartile = @"thirdQuartile"; +NSString * const MPVASTTrackingEventTypeComplete = @"complete"; +NSString * const MPVASTTrackingEventTypeMute = @"mute"; +NSString * const MPVASTTrackingEventTypeUnmute = @"unmute"; +NSString * const MPVASTTrackingEventTypePause = @"pause"; +NSString * const MPVASTTrackingEventTypeRewind = @"rewind"; +NSString * const MPVASTTrackingEventTypeResume = @"resume"; +NSString * const MPVASTTrackingEventTypeFullscreen = @"fullscreen"; +NSString * const MPVASTTrackingEventTypeExitFullscreen = @"exitFullscreen"; +NSString * const MPVASTTrackingEventTypeExpand = @"expand"; +NSString * const MPVASTTrackingEventTypeCollapse = @"collapse"; +NSString * const MPVASTTrackingEventTypeAcceptInvitationLinear = @"acceptInvitationLinear"; +NSString * const MPVASTTrackingEventTypeCloseLinear = @"closeLinear"; +NSString * const MPVASTTrackingEventTypeSkip = @"skip"; +NSString * const MPVASTTrackingEventTypeProgress = @"progress"; + +@implementation MPVASTTrackingEvent + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + _eventType = dictionary[@"event"]; + _URL = [self generateModelFromDictionaryValue:dictionary + modelProvider:^id(NSDictionary *dictionary) { + return [NSURL URLWithString:[dictionary[@"text"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; + }]; + _progressOffset = [self generateModelFromDictionaryValue:dictionary + modelProvider:^id(NSDictionary *dictionary) { + return [[MPVASTDurationOffset alloc] initWithDictionary:dictionary]; + }]; + } + return self; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.h b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.h new file mode 100644 index 000000000..27f474417 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.h @@ -0,0 +1,22 @@ +// +// MPVASTWrapper.h +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPVASTModel.h" + +@class MPVASTResponse; + +@interface MPVASTWrapper : MPVASTModel + +@property (nonatomic, readonly) NSArray *creatives; +@property (nonatomic, readonly) NSArray *errorURLs; +@property (nonatomic, readonly) NSArray *extensions; +@property (nonatomic, readonly) NSArray *impressionURLs; +@property (nonatomic, copy, readonly) NSURL *VASTAdTagURI; +@property (nonatomic, readonly) MPVASTResponse *wrappedVASTResponse; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.m b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.m new file mode 100644 index 000000000..ebd4fba00 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Internal/VAST/MPVASTWrapper.m @@ -0,0 +1,42 @@ +// +// MPVASTWrapper.m +// MoPub +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPVASTWrapper.h" +#import "MPVASTCreative.h" + +@interface MPVASTWrapper () + +@property (nonatomic, readwrite) MPVASTResponse *wrappedVASTResponse; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPVASTWrapper + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super initWithDictionary:dictionary]; + if (self) { + _extensions = [self generateModelsFromDictionaryValue:dictionary[@"Extensions"][@"Extension"] + modelProvider:^id(NSDictionary *dictionary) { + return dictionary; + }]; + } + return self; +} + ++ (NSDictionary *)modelMap +{ + return @{@"creatives": @[@"Creatives.Creative", MPParseArrayOf(MPParseClass([MPVASTCreative class]))], + @"errorURLs": @[@"Error.text", MPParseArrayOf(MPParseURLFromString())], + @"impressionURLs": @[@"Impression.text", MPParseArrayOf(MPParseURLFromString())], + // @"extensions": @[@"Extensions.Extension"], + @"VASTAdTagURI": @[@"VASTAdTagURI.text", MPParseURLFromString()]}; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.h b/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.h new file mode 100644 index 000000000..3672d70a4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.h @@ -0,0 +1,55 @@ +// +// MPAdConversionTracker.h +// MoPub +// +// Created by Andrew He on 2/4/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import + +/** + * The `MPAdConversionTracker` class provides a mechanism for reporting application download + * (conversion) events to MoPub. This type of tracking is important for measuring the effectiveness + * of cross-promotional and direct-sold advertising. + * + * To track application downloads, get a reference to the shared instance of this class using the + * `sharedConversionTracker` method. Then, in your application delegate's + * `application:didFinishLaunchingWithOptions:` method, call the + * `reportApplicationOpenForApplicationID:` method on the shared instance. With this call in place, + * the conversion tracker will report an event to MoPub whenever the application is launched on a + * given device for the first time. Any subsequent launches will not be recorded as conversion + * events. + */ + +@interface MPAdConversionTracker : NSObject + +/** @name Recording Conversions */ + +/** + * Returns the shared instance of the `MPAdConversionTracker` class. + * + * @return A singleton `MPAdConversionTracker` object. + */ ++ (MPAdConversionTracker *)sharedConversionTracker; + +/** + * Notifies MoPub that a conversion event should be recorded for the application corresponding to + * the specified `appID`. + * + * A conversion event will only be reported once per application download, even if this method + * is called multiple times. + * + * @param appID An iTunes application ID. + * + * The easiest way to find the correct ID for your application is to generate an iTunes URL using + * the [iTunes Link Maker](https://itunes.apple.com/linkmaker), and then extract the number + * immediately following the "id" string. + * + * For example, the iTunes URL for the "Find My Friends" application is + * https://itunes.apple.com/us/app/find-my-friends/id466122094, so its application ID is + * 466122094. + */ +- (void)reportApplicationOpenForApplicationID:(NSString *)appID; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.m b/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.m new file mode 100644 index 000000000..2f4b85b50 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPAdConversionTracker.m @@ -0,0 +1,96 @@ +// +// MPAdConversionTracker.m +// MoPub +// +// Created by Andrew He on 2/4/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPAdConversionTracker.h" +#import "MPConstants.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MPIdentityProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPAPIEndpoints.h" + +#define MOPUB_CONVERSION_DEFAULTS_KEY @"com.mopub.conversion" + +@interface MPAdConversionTracker () + +@property (nonatomic, strong) NSMutableData *responseData; +@property (nonatomic, assign) NSInteger statusCode; + +- (NSURL *)URLForAppID:(NSString *)appID; + +@end + +@implementation MPAdConversionTracker + +@synthesize responseData = _responseData; +@synthesize statusCode = _statusCode; + ++ (MPAdConversionTracker *)sharedConversionTracker +{ + static MPAdConversionTracker *sharedConversionTracker; + + @synchronized(self) + { + if (!sharedConversionTracker) + sharedConversionTracker = [[MPAdConversionTracker alloc] init]; + return sharedConversionTracker; + } +} + + +- (void)reportApplicationOpenForApplicationID:(NSString *)appID +{ + if (![[NSUserDefaults standardUserDefaults] boolForKey:MOPUB_CONVERSION_DEFAULTS_KEY]) { + MPLogInfo(@"Tracking conversion"); + NSMutableURLRequest *request = [[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:[self URLForAppID:appID]]; + self.responseData = [NSMutableData data]; + [NSURLConnection connectionWithRequest:request delegate:self]; + } +} + +#pragma mark - + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + self.statusCode = [(NSHTTPURLResponse *)response statusCode]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + [self.responseData appendData:data]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + //NOOP +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + if (self.statusCode == 200 && [self.responseData length] > 0) { + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:MOPUB_CONVERSION_DEFAULTS_KEY]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } +} + +#pragma mark - +#pragma mark Internal + +- (NSURL *)URLForAppID:(NSString *)appID +{ + NSString *path = [NSString stringWithFormat:@"%@?v=%@&udid=%@&id=%@&av=%@", + [MPAPIEndpoints baseURLStringWithPath:MOPUB_API_PATH_CONVERSION testing:NO], + MP_SERVER_VERSION, + [MPIdentityProvider identifier], + appID, + [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + ]; + + return [NSURL URLWithString:path]; +} +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPAdView.h b/examples/PrebidMobileDemo/MoPubSDK/MPAdView.h new file mode 100644 index 000000000..686a9f93a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPAdView.h @@ -0,0 +1,296 @@ +// +// MPAdView.h +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import +#import +#import "MPConstants.h" + +typedef enum +{ + MPNativeAdOrientationAny, + MPNativeAdOrientationPortrait, + MPNativeAdOrientationLandscape +} MPNativeAdOrientation; + +@protocol MPAdViewDelegate; + +/** + * The MPAdView class provides a view that can display banner advertisements. + */ + +@interface MPAdView : UIView + +/** @name Initializing a Banner Ad */ + +/** + * Initializes an MPAdView with the given ad unit ID and banner size. + * + * @param adUnitId A string representing a MoPub ad unit ID. + * @param size The desired ad size. A list of standard ad sizes is available in MPConstants.h. + * @return A newly initialized ad view corresponding to the given ad unit ID and size. + */ +- (id)initWithAdUnitId:(NSString *)adUnitId size:(CGSize)size; + +/** @name Setting and Getting the Delegate */ + +/** + * The delegate (`MPAdViewDelegate`) of the ad view. + * + * @warning **Important**: Before releasing an instance of `MPAdView`, you must set its delegate + * property to `nil`. + */ +@property (nonatomic, weak) id delegate; + +/** @name Setting Request Parameters */ + +/** + * The MoPub ad unit ID for this ad view. + * + * Ad unit IDs are created on the MoPub website. An ad unit is a defined placement in your + * application set aside for advertising. If no ad unit ID is set, the ad view will use a default + * ID that only receives test ads. + */ +@property (nonatomic, copy) NSString *adUnitId; + +/** + * A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * + * Keywords are typically used to target ad campaigns at specific user segments. They should be + * formatted as comma-separated key-value pairs (e.g. "marital:single,age:24"). + * + * On the MoPub website, keyword targeting options can be found under the "Advanced Targeting" + * section when managing campaigns. + */ +@property (nonatomic, copy) NSString *keywords; + +/** + * A `CLLocation` object representing a user's location that should be passed to the MoPub ad server + * to receive more relevant advertising. + */ +@property (nonatomic, copy) CLLocation *location; + +/** @name Enabling Test Mode */ + +/** + * A Boolean value that determines whether the ad view should request ads in test mode. + * + * The default value is NO. + * @warning **Important**: If you set this value to YES, make sure to reset it to NO before + * submitting your application to the App Store. + */ +@property (nonatomic, assign, getter = isTesting) BOOL testing; + +/** @name Loading a Banner Ad */ + +/** + * Requests a new ad from the MoPub ad server. + * + * If the ad view is already loading an ad, this call will be ignored. You may use `forceRefreshAd` + * if you would like cancel any existing ad requests and force a new ad to load. + */ +- (void)loadAd; + +/** + * Cancels any existing ad requests and requests a new ad from the MoPub ad server. + */ +- (void)forceRefreshAd; + +/** @name Handling Orientation Changes */ + +/** + * Informs the ad view that the device orientation has changed. + * + * Banners from some third-party ad networks have orientation-specific behavior. You should call + * this method when your application's orientation changes if you want mediated ads to acknowledge + * their new orientation. + * + * If your application layout needs to change based on the size of the mediated ad, you may want to + * check the value of `adContentViewSize` after calling this method, in case the orientation change + * causes the mediated ad to resize. + * + * @param newOrientation The new interface orientation (after orientation changes have occurred). + */ +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation; + +/** + * Forces third-party native ad networks to only use ads sized for the specified orientation. + * + * Banners from some third-party ad networks have orientation-specific behaviors and/or sizes. + * You may use this method to lock ads to a certain orientation. For instance, + * if you call this with MPInterfaceOrientationPortrait, native networks will never + * return ads sized for the landscape orientation. + * + * @param orientation An MPNativeAdOrientation enum value. + * + *
typedef enum {
+ *          MPNativeAdOrientationAny,
+ *          MPNativeAdOrientationPortrait,
+ *          MPNativeAdOrientationLandscape
+ *      } MPNativeAdOrientation;
+ * 
+ * + * @see unlockNativeAdsOrientation + * @see allowedNativeAdsOrientation + */ + +- (void)lockNativeAdsToOrientation:(MPNativeAdOrientation)orientation; + +/** + * Allows third-party native ad networks to use ads sized for any orientation. + * + * You do not need to call this method unless you have previously called + * `lockNativeAdsToOrientation:`. + * + * @see lockNativeAdsToOrientation: + * @see allowedNativeAdsOrientation + */ +- (void)unlockNativeAdsOrientation; + +/** + * Returns the banner orientations that third-party ad networks are allowed to use. + * + * @return An enum value representing an allowed set of orientations. + * + * @see lockNativeAdsToOrientation: + * @see unlockNativeAdsOrientation + */ +- (MPNativeAdOrientation)allowedNativeAdsOrientation; + +/** @name Obtaining the Size of the Current Ad */ + +/** + * Returns the size of the current ad being displayed in the ad view. + * + * Ad sizes may vary between different ad networks. This method returns the actual size of the + * underlying mediated ad. This size may be different from the original, initialized size of the + * ad view. You may use this size to determine to adjust the size or positioning of the ad view + * to avoid clipping or border issues. + * + * @returns The size of the underlying mediated ad. + */ +- (CGSize)adContentViewSize; + +/** @name Managing the Automatic Refreshing of Ads */ + +/** + * Stops the ad view from periodically loading new advertisements. + * + * By default, an ad view is allowed to automatically load new advertisements if a refresh interval + * has been configured on the MoPub website. This method prevents new ads from automatically loading, + * even if a refresh interval has been specified. + * + * As a best practice, you should call this method whenever the ad view will be hidden from the user + * for any period of time, in order to avoid unnecessary ad requests. You can then call + * `startAutomaticallyRefreshingContents` to re-enable the refresh behavior when the ad view becomes + * visible. + * + * @see startAutomaticallyRefreshingContents + */ +- (void)stopAutomaticallyRefreshingContents; + +/** + * Causes the ad view to periodically load new advertisements in accordance with user-defined + * refresh settings on the MoPub website. + * + * Calling this method is only necessary if you have previously stopped the ad view's refresh + * behavior using `stopAutomaticallyRefreshingContents`. By default, an ad view is allowed to + * automatically load new advertisements if a refresh interval has been configured on the MoPub + * website. This method has no effect if a refresh interval has not been set. + * + * @see stopAutomaticallyRefreshingContents + */ +- (void)startAutomaticallyRefreshingContents; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark - + +/** + * The delegate of an `MPAdView` object must adopt the `MPAdViewDelegate` protocol. It must + * implement `viewControllerForPresentingModalView` to provide a root view controller from which + * the ad view should present modal content. + * + * Optional methods of this protocol allow the delegate to be notified of banner success or + * failure, as well as other lifecycle events. + */ + +@protocol MPAdViewDelegate + +@required + +/** @name Managing Modal Content Presentation */ + +/** + * Asks the delegate for a view controller to use for presenting modal content, such as the in-app + * browser that can appear when an ad is tapped. + * + * @return A view controller that should be used for presenting modal content. + */ +- (UIViewController *)viewControllerForPresentingModalView; + +@optional + +/** @name Detecting When a Banner Ad is Loaded */ + +/** + * Sent when an ad view successfully loads an ad. + * + * Your implementation of this method should insert the ad view into the view hierarchy, if you + * have not already done so. + * + * @param view The ad view sending the message. + */ +- (void)adViewDidLoadAd:(MPAdView *)view; + +/** + * Sent when an ad view fails to load an ad. + * + * To avoid displaying blank ads, you should hide the ad view in response to this message. + * + * @param view The ad view sending the message. + */ +- (void)adViewDidFailToLoadAd:(MPAdView *)view; + +/** @name Detecting When a User Interacts With the Ad View */ + +/** + * Sent when an ad view is about to present modal content. + * + * This method is called when the user taps on the ad view. Your implementation of this method + * should pause any application activity that requires user interaction. + * + * @param view The ad view sending the message. + * @see `didDismissModalViewForAd:` + */ +- (void)willPresentModalViewForAd:(MPAdView *)view; + +/** + * Sent when an ad view has dismissed its modal content, returning control to your application. + * + * Your implementation of this method should resume any application activity that was paused + * in response to `willPresentModalViewForAd:`. + * + * @param view The ad view sending the message. + * @see `willPresentModalViewForAd:` + */ +- (void)didDismissModalViewForAd:(MPAdView *)view; + +/** + * Sent when a user is about to leave your application as a result of tapping + * on an ad. + * + * Your application will be moved to the background shortly after this method is called. + * + * @param view The ad view sending the message. + */ +- (void)willLeaveApplicationFromAd:(MPAdView *)view; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPAdView.m b/examples/PrebidMobileDemo/MoPubSDK/MPAdView.m new file mode 100644 index 000000000..c46ebdee1 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPAdView.m @@ -0,0 +1,190 @@ +// +// MPAdView.m +// MoPub +// +// Created by Nafis Jamal on 1/19/11. +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import "MPAdView.h" +#import "MPClosableView.h" +#import "MPBannerAdManager.h" +#import "MPInstanceProvider.h" +#import "MPBannerAdManagerDelegate.h" +#import "MPLogging.h" + +@interface MPAdView () + +@property (nonatomic, strong) MPBannerAdManager *adManager; +@property (nonatomic, weak) UIView *adContentView; +@property (nonatomic, assign) CGSize originalSize; +@property (nonatomic, assign) MPNativeAdOrientation allowedNativeAdOrientation; + +@end + +@implementation MPAdView +@synthesize location = _location; +@synthesize adManager = _adManager; +@synthesize adUnitId = _adUnitId; +@synthesize keywords = _keywords; +@synthesize delegate = _delegate; +@synthesize originalSize = _originalSize; +@synthesize testing = _testing; +@synthesize adContentView = _adContentView; +@synthesize allowedNativeAdOrientation = _allowedNativeAdOrientation; + +#pragma mark - +#pragma mark Lifecycle + +- (id)initWithAdUnitId:(NSString *)adUnitId size:(CGSize)size +{ + CGRect f = (CGRect){{0, 0}, size}; + if (self = [super initWithFrame:f]) + { + self.backgroundColor = [UIColor clearColor]; + self.clipsToBounds = YES; + self.originalSize = size; + self.allowedNativeAdOrientation = MPNativeAdOrientationAny; + self.adUnitId = (adUnitId) ? adUnitId : DEFAULT_PUB_ID; + self.adManager = [[MPInstanceProvider sharedProvider] buildMPBannerAdManagerWithDelegate:self]; + } + return self; +} + +- (void)dealloc +{ + self.adManager.delegate = nil; +} + +#pragma mark - + +- (void)setAdContentView:(UIView *)view +{ + [self.adContentView removeFromSuperview]; + _adContentView = view; + [self addSubview:view]; +} + +- (CGSize)adContentViewSize +{ + // MPClosableView represents an MRAID ad. + if (!self.adContentView || [self.adContentView isKindOfClass:[MPClosableView class]]) { + return self.originalSize; + } else { + return self.adContentView.bounds.size; + } +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation +{ + [self.adManager rotateToOrientation:newOrientation]; +} + +- (void)loadAd +{ + [self.adManager loadAd]; +} + +- (void)refreshAd +{ + [self loadAd]; +} + +- (void)forceRefreshAd +{ + [self.adManager forceRefreshAd]; +} + +- (void)stopAutomaticallyRefreshingContents +{ + [self.adManager stopAutomaticallyRefreshingContents]; +} + +- (void)startAutomaticallyRefreshingContents +{ + [self.adManager startAutomaticallyRefreshingContents]; +} + +- (void)lockNativeAdsToOrientation:(MPNativeAdOrientation)orientation +{ + self.allowedNativeAdOrientation = orientation; +} + +- (void)unlockNativeAdsOrientation +{ + self.allowedNativeAdOrientation = MPNativeAdOrientationAny; +} + +- (MPNativeAdOrientation)allowedNativeAdsOrientation +{ + return self.allowedNativeAdOrientation; +} + +#pragma mark - + +- (MPAdView *)banner +{ + return self; +} + +- (id)bannerDelegate +{ + return self.delegate; +} + +- (CGSize)containerSize +{ + return self.originalSize; +} + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)invalidateContentView +{ + [self setAdContentView:nil]; +} + +- (void)managerDidFailToLoadAd +{ + if ([self.delegate respondsToSelector:@selector(adViewDidFailToLoadAd:)]) { + // make sure we are not released synchronously as objects owned by us + // may do additional work after this callback + [[MPCoreInstanceProvider sharedProvider] keepObjectAliveForCurrentRunLoopIteration:self]; + + [self.delegate adViewDidFailToLoadAd:self]; + } +} + +- (void)managerDidLoadAd:(UIView *)ad +{ + [self setAdContentView:ad]; + if ([self.delegate respondsToSelector:@selector(adViewDidLoadAd:)]) { + [self.delegate adViewDidLoadAd:self]; + } +} + +- (void)userActionWillBegin +{ + if ([self.delegate respondsToSelector:@selector(willPresentModalViewForAd:)]) { + [self.delegate willPresentModalViewForAd:self]; + } +} + +- (void)userActionDidFinish +{ + if ([self.delegate respondsToSelector:@selector(didDismissModalViewForAd:)]) { + [self.delegate didDismissModalViewForAd:self]; + } +} + +- (void)userWillLeaveApplication +{ + if ([self.delegate respondsToSelector:@selector(willLeaveApplicationFromAd:)]) { + [self.delegate willLeaveApplicationFromAd:self]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.h new file mode 100644 index 000000000..bc6d3483d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.h @@ -0,0 +1,93 @@ +// +// MPBannerCustomEvent.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import "MPBannerCustomEventDelegate.h" + +/** + * The MoPub iOS SDK mediates third party Ad Networks using custom events. The custom events are + * responsible for instantiating and manipulating objects in the third party SDK and translating + * and communicating events from those objects back to the MoPub SDK by notifying a delegate. + * + * `MPBannerCustomEvent` is a base class for custom events that support banners. By implementing + * subclasses of `MPBannerCustomEvent` you can enable the MoPub SDK to natively support a wide + * variety of third-party ad networks. + * + * At runtime, the MoPub SDK will find and instantiate an `MPBannerCustomEvent` subclass as needed and + * invoke its `-requestAdWithSize:customEventInfo:` method. + */ + +@interface MPBannerCustomEvent : NSObject + +/** @name Requesting a Banner Ad */ + +/** + * Called when the MoPub SDK requires a new banner ad. + * + * When the MoPub SDK receives a response indicating it should load a custom event, it will send + * this message to your custom event class. Your implementation of this method can either load a + * banner ad from a third-party ad network, or execute any application code. It must also notify the + * `MPBannerCustomEventDelegate` of certain lifecycle events. + * + * @param size The current size of the parent `MPAdView`. You should use this information to create + * and request a banner of the appropriate size. + * + * @param info A dictionary containing additional custom data associated with a given custom event + * request. This data is configurable on the MoPub website, and may be used to pass dynamic information, such as publisher IDs. + */ +- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info; + +/** @name Callbacks */ + +/** + * Called when a banner rotation should occur. + * + * If you call `-rotateToOrientation` on an `MPAdView`, it will forward the message to its custom event. + * You can implement this method for third-party ad networks that have special behavior when + * orientation changes happen. + * + * @param newOrientation The `UIInterfaceOrientation` passed to the `MPAdView`'s `rotateToOrientation` method. + * + */ +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation; + +/** + * Calld when the banner is presented on screen. + * + * If you decide to [opt out of automatic impression tracking](enableAutomaticImpressionAndClickTracking), you should place your + * manual calls to [-trackImpression]([MPBannerCustomEventDelegate trackImpression]) in this method to ensure correct metrics. + */ +- (void)didDisplayAd; + +/** @name Impression and Click Tracking */ + +/** + * Override to opt out of automatic impression and click tracking. + * + * By default, the MPBannerCustomEventDelegate will automatically record impressions and clicks in + * response to the appropriate callbacks. You may override this behavior by implementing this method + * to return `NO`. + * + * @warning **Important**: If you do this, you are responsible for calling the `[-trackImpression]([MPBannerCustomEventDelegate trackImpression])` and + * `[-trackClick]([MPBannerCustomEventDelegate trackClick])` methods on the custom event delegate. Additionally, you should make sure that these + * methods are only called **once** per ad. + * + */ +- (BOOL)enableAutomaticImpressionAndClickTracking; + +/** @name Communicating with the MoPub SDK */ + +/** + * The `MPBannerCustomEventDelegate` to send messages to as events occur. + * + * The `delegate` object defines several methods that you should call in order to inform both MoPub + * and your `MPAdView`'s delegate of the progress of your custom event. + * + */ +@property (nonatomic, weak) id delegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.m new file mode 100644 index 000000000..c1a898570 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEvent.m @@ -0,0 +1,39 @@ +// +// MPBannerCustomEvent.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPBannerCustomEvent.h" + +@implementation MPBannerCustomEvent + +@synthesize delegate; + +- (void)requestAdWithSize:(CGSize)size customEventInfo:(NSDictionary *)info +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to load a banner here. +} + +- (void)didDisplayAd +{ + // The default implementation of this method does nothing. Subclasses may override this method + // to be notified when the ad is actually displayed on screen. +} + +- (BOOL)enableAutomaticImpressionAndClickTracking +{ + // Subclasses may override this method to return NO to perform impression and click tracking + // manually. + return YES; +} + +- (void)rotateToOrientation:(UIInterfaceOrientation)newOrientation +{ + // The default implementation of this method does nothing. Subclasses may override this method + // to be notified when the parent MPAdView receives -rotateToOrientation: calls. +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEventDelegate.h new file mode 100644 index 000000000..f7b7be5f3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPBannerCustomEventDelegate.h @@ -0,0 +1,135 @@ +// +// MPBannerCustomEventDelegate.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import + +@class MPBannerCustomEvent; + +/** + * Instances of your custom subclass of `MPBannerCustomEvent` will have an `MPBannerCustomEventDelegate` delegate. + * You use this delegate to communicate events ad events back to the MoPub SDK. + * + * When mediating a third party ad network it is important to call as many of these methods + * as accurately as possible. Not all ad networks support all these events, and some support + * different events. It is your responsibility to find an appropriate mapping betwen the ad + * network's events and the callbacks defined on `MPBannerCustomEventDelegate`. + */ + +@protocol MPBannerCustomEventDelegate + +/** + * The view controller instance to use when presenting modals. + * + * @return `viewControllerForPresentingModalView` returns the same view controller that you + * specify when implementing the `MPAdViewDelegate` protocol. + */ +- (UIViewController *)viewControllerForPresentingModalView; + +/** + * The user's current location. + * + * @return This method provides the location that was passed into the parent `MPAdView`. The MoPub + * SDK does **not** automatically request the user's location. It is your responsibility to pass the location + * into `MPAdView`. + * + * You may use this to inform third-party ad networks of the user's location. + */ +- (CLLocation *)location; + +/** @name Banner Ad Event Callbacks - Fetching Ads */ + +/** + * Call this method immediately after an ad loads succesfully. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param ad The `UIView` representing the banner ad. This view will be inserted into the `MPAdView` + * and presented to the user by the MoPub SDK. + * + * @warning **Important**: Your custom event subclass **must** call this method when it successfully loads an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)bannerCustomEvent:(MPBannerCustomEvent *)event didLoadAd:(UIView *)ad; + +/** + * Call this method immediately after an ad fails to load. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param error (*optional*) You may pass an error describing the failure. + * + * @warning **Important**: Your custom event subclass **must** call this method when it fails to load an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)bannerCustomEvent:(MPBannerCustomEvent *)event didFailToLoadAdWithError:(NSError *)error; + +/** @name Banner Ad Event Callbacks - User Interaction */ + +/** + * Call this method when the user taps on the banner ad. + * + * This method is optional. When automatic click and impression tracking is enabled (the default) + * this method will track a click (the click is guaranteed to only be tracked once per ad). + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: If you call `-bannerCustomEventWillBeginAction:`, you _**must**_ also call + * `-bannerCustomEventDidFinishAction:` at a later point. + */ +- (void)bannerCustomEventWillBeginAction:(MPBannerCustomEvent *)event; + +/** + * Call this method when the user finishes interacting with the banner ad. + * + * For example, the user may have dismissed any modal content. This method is optional. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: If you call `-bannerCustomEventWillBeginAction:`, you _**must**_ also call + * `-bannerCustomEventDidFinishAction:` at a later point. + */ +- (void)bannerCustomEventDidFinishAction:(MPBannerCustomEvent *)event; + +/** + * Call this method when the banner ad will cause the user to leave the application. + * + * For example, the user may have tapped on a link to visit the App Store or Safari. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + */ +- (void)bannerCustomEventWillLeaveApplication:(MPBannerCustomEvent *)event; + +/** @name Impression and Click Tracking */ + +/** + * Call this method to track an impression. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPBannerCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks impressions. + * + * **Important**: In order to obtain accurate metrics, it is your responsibility to call `trackImpression` only **once** per ad. + */ +- (void)trackImpression; + +/** + * Call this method to track a click. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPBannerCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks clicks. + * + * **Important**: In order to obtain accurate metrics, it is your responsibility to call `trackClick` only **once** per ad. + */ +- (void)trackClick; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPConstants.h b/examples/PrebidMobileDemo/MoPubSDK/MPConstants.h new file mode 100644 index 000000000..ba0a46f63 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPConstants.h @@ -0,0 +1,33 @@ +// +// MPConstants.h +// MoPub +// +// Copyright 2011 MoPub, Inc. All rights reserved. +// + +#import + +#define MP_DEBUG_MODE 1 + +#define MP_HAS_NATIVE_PACKAGE 1 + +#define DEFAULT_PUB_ID @"agltb3B1Yi1pbmNyDAsSBFNpdGUYkaoMDA" +#define MP_SERVER_VERSION @"8" +#define MP_BUNDLE_IDENTIFIER @"com.mopub.mopub" +#define MP_SDK_VERSION @"4.12.0" + +// Sizing constants. +extern CGSize const MOPUB_BANNER_SIZE; +extern CGSize const MOPUB_MEDIUM_RECT_SIZE; +extern CGSize const MOPUB_LEADERBOARD_SIZE; +extern CGSize const MOPUB_WIDE_SKYSCRAPER_SIZE; + +// Miscellaneous constants. +#define MINIMUM_REFRESH_INTERVAL 10.0 +#define DEFAULT_BANNER_REFRESH_INTERVAL 60 +#define BANNER_TIMEOUT_INTERVAL 10 +#define INTERSTITIAL_TIMEOUT_INTERVAL 30 +#define REWARDED_VIDEO_TIMEOUT_INTERVAL 30 + +// Feature Flags +#define SESSION_TRACKING_ENABLED 1 diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPConstants.m b/examples/PrebidMobileDemo/MoPubSDK/MPConstants.m new file mode 100644 index 000000000..b6d281a81 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPConstants.m @@ -0,0 +1,13 @@ +// +// MPConstants.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPConstants.h" + +CGSize const MOPUB_BANNER_SIZE = { .width = 320.0f, .height = 50.0f }; +CGSize const MOPUB_MEDIUM_RECT_SIZE = { .width = 300.0f, .height = 250.0f }; +CGSize const MOPUB_LEADERBOARD_SIZE = { .width = 728.0f, .height = 90.0f }; +CGSize const MOPUB_WIDE_SKYSCRAPER_SIZE = { .width = 160.0f, .height = 600.0f }; diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.h b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.h new file mode 100644 index 000000000..bc0f37f03 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.h @@ -0,0 +1,249 @@ +// +// MPInterstitialAdController.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import + +@protocol MPInterstitialAdControllerDelegate; + +/** + * The `MPInterstitialAdController` class provides a full-screen advertisement that can be + * displayed during natural transition points in your application. + */ + +@interface MPInterstitialAdController : UIViewController + +/** @name Obtaining an Interstitial Ad */ + +/** + * Returns an interstitial ad object matching the given ad unit ID. + * + * The first time this method is called for a given ad unit ID, a new interstitial ad object is + * created, stored in a shared pool, and returned. Subsequent calls for the same ad unit ID will + * return that object, unless you have disposed of the object using + * `removeSharedInterstitialAdController:`. + * + * There can only be one interstitial object for an ad unit ID at a given time. + * + * @param adUnitId A string representing a MoPub ad unit ID. + */ ++ (MPInterstitialAdController *)interstitialAdControllerForAdUnitId:(NSString *)adUnitId; + +/** @name Setting and Getting the Delegate */ + +/** + * The delegate (`MPInterstitialAdControllerDelegate`) of the interstitial ad object. + */ +@property (nonatomic, weak) id delegate; + +/** @name Setting Request Parameters */ + +/** + * The MoPub ad unit ID for this interstitial ad. + * + * Ad unit IDs are created on the MoPub website. An ad unit is a defined placement in your + * application set aside for advertising. If no ad unit ID is set, the ad object will use a default + * ID that only receives test ads. + */ +@property (nonatomic, copy) NSString *adUnitId; + +/** + * A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * + * Keywords are typically used to target ad campaigns at specific user segments. They should be + * formatted as comma-separated key-value pairs (e.g. "marital:single,age:24"). + * + * On the MoPub website, keyword targeting options can be found under the "Advanced Targeting" + * section when managing campaigns. + */ +@property (nonatomic, copy) NSString *keywords; + +/** + * A `CLLocation` object representing a user's location that should be passed to the MoPub ad server + * to receive more relevant advertising. + */ +@property (nonatomic, copy) CLLocation *location; + +/** @name Enabling Test Mode */ + +/** + * A Boolean value that determines whether the interstitial ad object should request ads in test + * mode. + * + * The default value is NO. + * @warning **Important**: If you set this value to YES, make sure to reset it to NO before + * submitting your application to the App Store. + */ +@property (nonatomic, assign, getter=isTesting) BOOL testing; + +/** @name Loading an Interstitial Ad */ + +/** + * Begins loading ad content for the interstitial. + * + * You can implement the `interstitialDidLoadAd:` and `interstitialDidFailToLoadAd:` methods of + * `MPInterstitialAdControllerDelegate` if you would like to be notified as loading succeeds or + * fails. + */ +- (void)loadAd; + +/** @name Detecting Whether the Interstitial Ad Has Loaded */ + +/** + * A Boolean value that represents whether the interstitial ad has loaded an advertisement and is + * ready to be presented. + * + * After obtaining an interstitial ad object, you can use `loadAd` to tell the object to begin + * loading ad content. Once the content has been loaded, the value of this property will be YES. + * + * The value of this property can be NO if the ad content has not finished loading, has already + * been presented, or has expired. The expiration condition only applies for ads from certain + * third-party ad networks. See `MPInterstitialAdControllerDelegate` for more details. + */ +@property (nonatomic, assign, readonly) BOOL ready; + +/** @name Presenting an Interstitial Ad */ + +/** + * Presents the interstitial ad modally from the specified view controller. + * + * This method will do nothing if the interstitial ad has not been loaded (i.e. the value of its + * `ready` property is NO). + * + * `MPInterstitialAdControllerDelegate` provides optional methods that you may implement to stay + * informed about when an interstitial takes over or relinquishes the screen. + * + * @param controller The view controller that should be used to present the interstitial ad. + */ +- (void)showFromViewController:(UIViewController *)controller; + +/** @name Disposing of an Interstitial Ad */ + +/** + * Removes the given interstitial object from the shared pool of interstitials available to your + * application. + * + * This method removes the mapping from the interstitial's ad unit ID to the interstitial ad + * object. In other words, you will receive a different ad object if you subsequently call + * `interstitialAdControllerForAdUnitId:` for the same ad unit ID. + * + * @warning **Important**: This method is intended to be used for deallocating the interstitial + * ad object when it is no longer needed. You should `nil` out any references you have to the + * object after calling this method. + * + * @param controller The interstitial ad object that should be disposed. + */ ++ (void)removeSharedInterstitialAdController:(MPInterstitialAdController *)controller; + +/* + * Returns the shared pool of interstitial objects for your application. + */ ++ (NSMutableArray *)sharedInterstitialAdControllers; + +@end + +#pragma mark - + +/** + * The delegate of an `MPInterstitialAdController` object must adopt the + * `MPInterstitialAdControllerDelegate` protocol. + * + * The optional methods of this protocol allow the delegate to be notified of interstitial state + * changes, such as when an ad has loaded, when an ad has been presented or dismissed from the + * screen, and when an ad has expired. + */ + +@protocol MPInterstitialAdControllerDelegate + +@optional + +/** @name Detecting When an Interstitial Ad is Loaded */ + +/** + * Sent when an interstitial ad object successfully loads an ad. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidLoadAd:(MPInterstitialAdController *)interstitial; + +/** + * Sent when an interstitial ad object fails to load an ad. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidFailToLoadAd:(MPInterstitialAdController *)interstitial; + +/** @name Detecting When an Interstitial Ad is Presented */ + +/** + * Sent immediately before an interstitial ad object is presented on the screen. + * + * Your implementation of this method should pause any application activity that requires user + * interaction. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialWillAppear:(MPInterstitialAdController *)interstitial; + +/** + * Sent after an interstitial ad object has been presented on the screen. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidAppear:(MPInterstitialAdController *)interstitial; + +/** @name Detecting When an Interstitial Ad is Dismissed */ + +/** + * Sent immediately before an interstitial ad object will be dismissed from the screen. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialWillDisappear:(MPInterstitialAdController *)interstitial; + +/** + * Sent after an interstitial ad object has been dismissed from the screen, returning control + * to your application. + * + * Your implementation of this method should resume any application activity that was paused + * prior to the interstitial being presented on-screen. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidDisappear:(MPInterstitialAdController *)interstitial; + +/** @name Detecting When an Interstitial Ad Expires */ + +/** + * Sent when a loaded interstitial ad is no longer eligible to be displayed. + * + * Interstitial ads from certain networks may expire their content at any time, + * even if the content is currently on-screen. This method notifies you when the currently- + * loaded interstitial has expired and is no longer eligible for display. + * + * If the ad was on-screen when it expired, you can expect that the ad will already have been + * dismissed by the time this message is sent. + * + * Your implementation may include a call to `loadAd` to fetch a new ad, if desired. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidExpire:(MPInterstitialAdController *)interstitial; + +/** + * Sent when the user taps the interstitial ad and the ad is about to perform its target action. + * + * This action may include displaying a modal or leaving your application. Certain ad networks + * may not expose a "tapped" callback so you should not rely on this callback to perform + * critical tasks. + * + * @param interstitial The interstitial ad object sending the message. + */ +- (void)interstitialDidReceiveTapEvent:(MPInterstitialAdController *)interstitial; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.m b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.m new file mode 100644 index 000000000..785a56b61 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialAdController.m @@ -0,0 +1,195 @@ +// +// MPInterstitialAdController.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPInterstitialAdController.h" + +#import "MPLogging.h" +#import "MPInstanceProvider.h" +#import "MPInterstitialAdManager.h" +#import "MPInterstitialAdManagerDelegate.h" + +@interface MPInterstitialAdController () + +@property (nonatomic, strong) MPInterstitialAdManager *manager; + ++ (NSMutableArray *)sharedInterstitials; +- (id)initWithAdUnitId:(NSString *)adUnitId; + +@end + +@implementation MPInterstitialAdController + +@synthesize manager = _manager; +@synthesize delegate = _delegate; +@synthesize adUnitId = _adUnitId; +@synthesize keywords = _keywords; +@synthesize location = _location; +@synthesize testing = _testing; + +- (id)initWithAdUnitId:(NSString *)adUnitId +{ + if (self = [super init]) { + self.manager = [[MPInstanceProvider sharedProvider] buildMPInterstitialAdManagerWithDelegate:self]; + self.adUnitId = adUnitId; + } + return self; +} + +- (void)dealloc +{ + [self.manager setDelegate:nil]; +} + +#pragma mark - Public + ++ (MPInterstitialAdController *)interstitialAdControllerForAdUnitId:(NSString *)adUnitId +{ + NSMutableArray *interstitials = [[self class] sharedInterstitials]; + + @synchronized(self) { + // Find the correct ad controller based on the ad unit ID. + MPInterstitialAdController *interstitial = nil; + for (MPInterstitialAdController *currentInterstitial in interstitials) { + if ([currentInterstitial.adUnitId isEqualToString:adUnitId]) { + interstitial = currentInterstitial; + break; + } + } + + // Create a new ad controller for this ad unit ID if one doesn't already exist. + if (!interstitial) { + interstitial = [[[self class] alloc] initWithAdUnitId:adUnitId]; + [interstitials addObject:interstitial]; + } + + return interstitial; + } +} + +- (BOOL)ready +{ + return self.manager.ready; +} + +- (void)loadAd +{ + [self.manager loadInterstitialWithAdUnitID:self.adUnitId + keywords:self.keywords + location:self.location + testing:self.testing]; +} + +- (void)showFromViewController:(UIViewController *)controller +{ + if (!controller) { + MPLogWarn(@"The interstitial could not be shown: " + @"a nil view controller was passed to -showFromViewController:."); + return; + } + + if (![controller.view.window isKeyWindow]) { + MPLogWarn(@"Attempted to present an interstitial ad in non-key window. The ad may not render properly"); + } + + [self.manager presentInterstitialFromViewController:controller]; +} + +#pragma mark - Internal + ++ (NSMutableArray *)sharedInterstitials +{ + static NSMutableArray *sharedInterstitials; + + @synchronized(self) { + if (!sharedInterstitials) { + sharedInterstitials = [NSMutableArray array]; + } + } + + return sharedInterstitials; +} + +#pragma mark - MPInterstitialAdManagerDelegate + +- (MPInterstitialAdController *)interstitialAdController +{ + return self; +} + +- (id)interstitialDelegate +{ + return self.delegate; +} + +- (void)managerDidLoadInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidLoadAd:)]) { + [self.delegate interstitialDidLoadAd:self]; + } +} + +- (void)manager:(MPInterstitialAdManager *)manager + didFailToLoadInterstitialWithError:(NSError *)error +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidFailToLoadAd:)]) { + [self.delegate interstitialDidFailToLoadAd:self]; + } +} + +- (void)managerWillPresentInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialWillAppear:)]) { + [self.delegate interstitialWillAppear:self]; + } +} + +- (void)managerDidPresentInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidAppear:)]) { + [self.delegate interstitialDidAppear:self]; + } +} + +- (void)managerWillDismissInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialWillDisappear:)]) { + [self.delegate interstitialWillDisappear:self]; + } +} + +- (void)managerDidDismissInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidDisappear:)]) { + [self.delegate interstitialDidDisappear:self]; + } +} + +- (void)managerDidExpireInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidExpire:)]) { + [self.delegate interstitialDidExpire:self]; + } +} + +- (void)managerDidReceiveTapEventFromInterstitial:(MPInterstitialAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(interstitialDidReceiveTapEvent:)]) { + [self.delegate interstitialDidReceiveTapEvent:self]; + } +} + ++ (NSMutableArray *)sharedInterstitialAdControllers +{ + return [[self class] sharedInterstitials]; +} + ++ (void)removeSharedInterstitialAdController:(MPInterstitialAdController *)controller +{ + [[[self class] sharedInterstitials] removeObject:controller]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.h new file mode 100644 index 000000000..dc76b68f8 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.h @@ -0,0 +1,85 @@ +// +// MPInterstitialCustomEvent.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import "MPInterstitialCustomEventDelegate.h" + +/** + * The MoPub iOS SDK mediates third party Ad Networks using custom events. The custom events are + * responsible for instantiating and manipulating objects in the third party SDK and translating + * and communicating events from those objects back to the MoPub SDK by notifying a delegate. + * + * `MPInterstitialCustomEvent` is a base class for custom events that support full-screen interstitial ads. + * By implementing subclasses of `MPInterstitialCustomEvent` you can enable the MoPub SDK to + * natively support a wide variety of third-party ad networks. + * + * At runtime, the MoPub SDK will find and instantiate an `MPInterstitialCustomEvent` subclass as needed and + * invoke its `-requestInterstitialWithCustomEventInfo:` method. + */ + + +@interface MPInterstitialCustomEvent : NSObject + +/** @name Requesting and Displaying an Interstitial Ad */ + +/** + * Called when the MoPub SDK requires a new interstitial ad. + * + * When the MoPub SDK receives a response indicating it should load a custom event, it will send + * this message to your custom event class. Your implementation of this method should load an + * interstitial ad from a third-party ad network. It must also notify the + * `MPInterstitialCustomEventDelegate` of certain lifecycle events. + * + * @param info A dictionary containing additional custom data associated with a given custom event + * request. This data is configurable on the MoPub website, and may be used to pass dynamic information, such as publisher IDs. + */ + +- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info; + +/** + * Called when the interstitial should be displayed. + * + * This message is sent sometime after an interstitial has been successfully loaded, as a result + * of your code calling `-[MPInterstitialAdController showFromViewController:]`. Your implementation + * of this method should present the interstitial ad from the specified view controller. + * + * If you decide to [opt out of automatic impression tracking](enableAutomaticImpressionAndClickTracking), you should place your + * manual calls to [-trackImpression]([MPInterstitialCustomEventDelegate trackImpression]) in this method to ensure correct metrics. + * + * @param rootViewController The controller to use to present the interstitial modally. + * + */ +- (void)showInterstitialFromRootViewController:(UIViewController *)rootViewController; + +/** @name Impression and Click Tracking */ + +/** + * Override to opt out of automatic impression and click tracking. + * + * By default, the MPInterstitialCustomEventDelegate will automatically record impressions and clicks in + * response to the appropriate callbacks. You may override this behavior by implementing this method + * to return `NO`. + * + * @warning **Important**: If you do this, you are responsible for calling the `[-trackImpression]([MPInterstitialCustomEventDelegate trackImpression])` and + * `[-trackClick]([MPInterstitialCustomEventDelegate trackClick])` methods on the custom event delegate. Additionally, you should make sure that these + * methods are only called **once** per ad. + */ +- (BOOL)enableAutomaticImpressionAndClickTracking; + +/** @name Communicating with the MoPub SDK */ + +/** + * The `MPInterstitialCustomEventDelegate` to send messages to as events occur. + * + * The `delegate` object defines several methods that you should call in order to inform both MoPub + * and your `MPInterstitialAdController`'s delegate of the progress of your custom event. + * + */ + +@property (nonatomic, weak) id delegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.m new file mode 100644 index 000000000..7a36ec105 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEvent.m @@ -0,0 +1,33 @@ +// +// MPInterstitialCustomEvent.m +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import "MPInterstitialCustomEvent.h" + +@implementation MPInterstitialCustomEvent + +@synthesize delegate; + +- (void)requestInterstitialWithCustomEventInfo:(NSDictionary *)info +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to load an interstitial here. +} + +- (BOOL)enableAutomaticImpressionAndClickTracking +{ + // Subclasses may override this method to return NO to perform impression and click tracking + // manually. + return YES; +} + +- (void)showInterstitialFromRootViewController:(UIViewController *)rootViewController +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to display an interstitial here. +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEventDelegate.h new file mode 100644 index 000000000..d634f2227 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MPInterstitialCustomEventDelegate.h @@ -0,0 +1,183 @@ +// +// MPInterstitialCustomEventDelegate.h +// MoPub +// +// Copyright (c) 2012 MoPub, Inc. All rights reserved. +// + +#import +#import + +@class MPInterstitialCustomEvent; + +/** + * Instances of your custom subclass of `MPInterstitialCustomEvent` will have an `MPInterstitialCustomEventDelegate` delegate. + * You use this delegate to communicate events ad events back to the MoPub SDK. + * + * When mediating a third party ad network it is important to call as many of these methods + * as accurately as possible. Not all ad networks support all these events, and some support + * different events. It is your responsibility to find an appropriate mapping betwen the ad + * network's events and the callbacks defined on `MPInterstitialCustomEventDelegate`. + */ + +@protocol MPInterstitialCustomEventDelegate + +/** + * The user's current location. + * + * @return This method provides the location that was passed into the parent `MPInterstitialAdController`. The MoPub + * SDK does **not** automatically request the user's location. It is your responsibility to pass the location + * into `MPInterstitialAdController`. + * + * You may use this to inform third-party ad networks of the user's location. + */ +- (CLLocation *)location; + +/** @name Interstitial Ad Event Callbacks - Fetching Ads */ + +/** + * Call this method immediately after an ad loads succesfully. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param ad (*optional*) An object that represents the ad that was retrieved. The MoPub SDK does not + * do anything with this optional parameter. + * + * @warning **Important**: Your custom event subclass **must** call this method when it successfully loads an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)interstitialCustomEvent:(MPInterstitialCustomEvent *)customEvent + didLoadAd:(id)ad; + +/** + * Call this method immediately after an ad fails to load. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param error (*optional*) You may pass an error describing the failure. + * + * @warning **Important**: Your custom event subclass **must** call this method when it fails to load an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)interstitialCustomEvent:(MPInterstitialCustomEvent *)customEvent + didFailToLoadAdWithError:(NSError *)error; + +/** + * Call this method if a previously loaded interstitial should no longer be eligible for presentation. + * + * Some third-party networks will mark interstitials as expired (indicating they should not be + * presented) *after* they have loaded. You may use this method to inform the MoPub SDK that a + * previously loaded interstitial has expired and that a new interstitial should be obtained. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + */ +- (void)interstitialCustomEventDidExpire:(MPInterstitialCustomEvent *)customEvent; + +/** @name Interstitial Ad Event Callbacks - Presenting and Dismissing Ads */ + +/** + * Call this method when an ad is about to appear. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is about to present the interstitial. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + */ +- (void)interstitialCustomEventWillAppear:(MPInterstitialCustomEvent *)customEvent; + +/** + * Call this method when an ad has finished appearing. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is finished presenting the interstitial. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + * **Note**: if it is not possible to know when the interstitial *finished* appearing, you should call + * this immediately after calling `-interstitialCustomEventWillAppear:`. + */ +- (void)interstitialCustomEventDidAppear:(MPInterstitialCustomEvent *)customEvent; + +/** + * Call this method when an ad is about to disappear. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is about to dismiss the interstitial. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + */ +- (void)interstitialCustomEventWillDisappear:(MPInterstitialCustomEvent *)customEvent; + +/** + * Call this method when an ad has finished disappearing. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is finished with dismissing the interstitial. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + * **Note**: if it is not possible to know when the interstitial *finished* dismissing, you should call + * this immediately after calling `-interstitialCustomEventDidDisappear:`. + */ +- (void)interstitialCustomEventDidDisappear:(MPInterstitialCustomEvent *)customEvent; + +/** @name Interstitial Ad Event Callbacks - User Interaction */ + +/** + * Call this method when the user taps on the interstitial ad. + * + * This method is optional. When automatic click and impression tracking is enabled (the default) + * this method will track a click (the click is guaranteed to only be tracked once per ad). + * + * **Note**: some third-party networks provide a "will leave application" callback instead of/in + * addition to a "user did click" callback. You should call this method in response to either of + * those callbacks (since leaving the application is generally an indicator of a user tap). + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + */ +- (void)interstitialCustomEventDidReceiveTapEvent:(MPInterstitialCustomEvent *)customEvent; + +/** + * Call this method when the interstitial ad will cause the user to leave the application. + * + * For example, the user may have tapped on a link to visit the App Store or Safari. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + */ +- (void)interstitialCustomEventWillLeaveApplication:(MPInterstitialCustomEvent *)customEvent; + +/** @name Impression and Click Tracking */ + +/** + * Call this method to track an impression. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPInterstitialCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks impressions. + * + * **Important**: In order to obtain accurate metrics, it is your responsibility to call `trackImpression` only **once** per ad. + */ +- (void)trackImpression; + +/** + * Call this method to track a click. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPInterstitialCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks clicks. + * + * **Important**: In order to obtain accurate metrics, it is your responsibility to call `trackClick` only **once** per ad. + */ +- (void)trackClick; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MoPub-Bridging-Header.h b/examples/PrebidMobileDemo/MoPubSDK/MoPub-Bridging-Header.h new file mode 100644 index 000000000..474eec536 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MoPub-Bridging-Header.h @@ -0,0 +1,51 @@ +// +// MoPub-Bridging-Header.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MoPub.h" + +#import "MPAdConversionTracker.h" +#import "MPAdView.h" +#import "MPBannerCustomEvent.h" +#import "MPBannerCustomEventDelegate.h" +#import "MPConstants.h" +#import "MPInterstitialAdController.h" +#import "MPInterstitialCustomEvent.h" +#import "MPInterstitialCustomEventDelegate.h" + +#if MP_HAS_NATIVE_PACKAGE + +#import "MPNativeAd.h" +#import "MPNativeAdAdapter.h" +#import "MPNativeAdConstants.h" +#import "MPNativeCustomEvent.h" +#import "MPNativeCustomEventDelegate.h" +#import "MPNativeAdDelegate.h" +#import "MPNativeAdError.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdRequest.h" +#import "MPNativeAdRequestTargeting.h" +#import "MPStaticNativeAdRendererSettings.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPNativeAdRendererSettings.h" +#import "MPNativeAdRenderer.h" +#import "MPStaticNativeAdRenderer.h" +#import "MOPUBNativeVideoAdRendererSettings.h" +#import "MOPUBNativeVideoAdRenderer.h" +#import "MPNativeAdRenderingImageLoader.h" +#import "MPClientAdPositioning.h" +#import "MPServerAdPositioning.h" +#import "MPCollectionViewAdPlacer.h" +#import "MPTableViewAdPlacer.h" + +#endif + + +#import "MPMediationSettingsProtocol.h" +#import "MPRewardedVideo.h" +#import "MPRewardedVideoReward.h" +#import "MPRewardedVideoCustomEvent.h" +#import "MPRewardedVideoError.h" diff --git a/examples/PrebidMobileDemo/MoPubSDK/MoPub.h b/examples/PrebidMobileDemo/MoPubSDK/MoPub.h new file mode 100644 index 000000000..b815d8956 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MoPub.h @@ -0,0 +1,122 @@ +// +// MoPub.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPConstants.h" + +#import "MPAdConversionTracker.h" +#import "MPAdView.h" +#import "MPBannerCustomEvent.h" +#import "MPBannerCustomEventDelegate.h" +#import "MPInterstitialAdController.h" +#import "MPInterstitialCustomEvent.h" +#import "MPInterstitialCustomEventDelegate.h" +#import "MPMediationSettingsProtocol.h" +#import "MPRewardedVideo.h" +#import "MPRewardedVideoReward.h" +#import "MPRewardedVideoCustomEvent.h" +#import "MPRewardedVideoError.h" + +#if MP_HAS_NATIVE_PACKAGE +#import "MPNativeAd.h" +#import "MPNativeAdAdapter.h" +#import "MPNativeAdConstants.h" +#import "MPNativeCustomEvent.h" +#import "MPNativeCustomEventDelegate.h" +#import "MPNativeAdError.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdRequest.h" +#import "MPNativeAdRequestTargeting.h" +#import "MPCollectionViewAdPlacer.h" +#import "MPTableViewAdPlacer.h" +#import "MPClientAdPositioning.h" +#import "MPServerAdPositioning.h" +#import "MPNativeAdDelegate.h" +#import "MPStaticNativeAdRendererSettings.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPNativeAdRendererSettings.h" +#import "MPNativeAdRenderer.h" +#import "MPStaticNativeAdRenderer.h" +#import "MOPUBNativeVideoAdRendererSettings.h" +#import "MOPUBNativeVideoAdRenderer.h" +#import "MPNativeAdRenderingImageLoader.h" +#endif + +// Import these frameworks for module support. +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#define MoPubKit [MoPub sharedInstance] + +@interface MoPub : NSObject + +/** + * Returns the MoPub singleton object. + * + * @return The MoPub singleton object. + */ ++ (MoPub *)sharedInstance; + +/** + * A Boolean value indicating whether the MoPub SDK should use Core Location APIs to automatically + * derive targeting information for location-based ads. + * + * When set to NO, the SDK will not attempt to determine device location. When set to YES, the + * SDK will periodically try to listen for location updates in order to request location-based ads. + * This only occurs if location services are enabled and the user has already authorized the use + * of location services for the application. The default value is YES. + * + * @param enabled A Boolean value indicating whether the SDK should listen for location updates. + */ +@property (nonatomic, assign) BOOL locationUpdatesEnabled; + + +/** + * A Boolean value indicating whether the MoPub SDK should create a MoPub ID that can be used + * for frequency capping when Limit ad tracking is on & the IDFA we get is + * 00000000-0000-0000-0000-000000000000. + * + * When set to NO, the SDK will not create a MoPub ID in the above case. When set to YES, the + * SDK will generate a MoPub ID. The default value is YES. + * + */ +@property (nonatomic) BOOL frequencyCappingIdUsageEnabled; + +/** @name Rewarded Video */ +/** + * Initializes the rewarded video system. + * + * This method should only be called once. It should also be called prior to requesting any rewarded video ads. + * Once the global mediation settings and delegate are set, they cannot be changed. + * + * @param globalMediationSettings Global configurations for all rewarded video ad networks your app supports. + * + * @param delegate The delegate that will receive all events related to rewarded video. + */ +- (void)initializeRewardedVideoWithGlobalMediationSettings:(NSArray *)globalMediationSettings delegate:(id)delegate; + +/** + * Retrieves the global mediation settings for a given class type. +* + * @param aClass The type of mediation settings object you want to receive from the collection. + */ +- (id)globalMediationSettingsForClass:(Class)aClass; + +- (void)start; +- (NSString *)version; +- (NSString *)bundleIdentifier; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/MoPub.m b/examples/PrebidMobileDemo/MoPubSDK/MoPub.m new file mode 100644 index 000000000..9662cf797 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/MoPub.m @@ -0,0 +1,89 @@ +// +// MoPub.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MoPub.h" +#import "MPConstants.h" +#import "MPCoreInstanceProvider.h" +#import "MPGeolocationProvider.h" +#import "MPRewardedVideo.h" +#import "MPIdentityProvider.h" + +@interface MoPub () + +@property (nonatomic, strong) NSArray *globalMediationSettings; + +@end + +@implementation MoPub + ++ (MoPub *)sharedInstance +{ + static MoPub *sharedInstance = nil; + static dispatch_once_t initOnceToken; + dispatch_once(&initOnceToken, ^{ + sharedInstance = [[MoPub alloc] init]; + }); + return sharedInstance; +} + +- (void)setLocationUpdatesEnabled:(BOOL)locationUpdatesEnabled +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPGeolocationProvider] setLocationUpdatesEnabled:locationUpdatesEnabled]; +} + +- (BOOL)locationUpdatesEnabled +{ + return [[MPCoreInstanceProvider sharedProvider] sharedMPGeolocationProvider].locationUpdatesEnabled; +} + +- (void)setFrequencyCappingIdUsageEnabled:(BOOL)frequencyCappingIdUsageEnabled +{ + [MPIdentityProvider setFrequencyCappingIdUsageEnabled:frequencyCappingIdUsageEnabled]; +} + +- (BOOL)frequencyCappingIdUsageEnabled +{ + return [MPIdentityProvider frequencyCappingIdUsageEnabled]; +} + +- (void)start +{ + +} + +// Keep -version and -bundleIdentifier methods around for Fabric backwards compatibility. +- (NSString *)version +{ + return MP_SDK_VERSION; +} + +- (NSString *)bundleIdentifier +{ + return MP_BUNDLE_IDENTIFIER; +} + +- (void)initializeRewardedVideoWithGlobalMediationSettings:(NSArray *)globalMediationSettings delegate:(id)delegate +{ + // initializeWithDelegate: is a known private initialization method on MPRewardedVideo. So we forward the initialization call to that class. + [MPRewardedVideo performSelector:@selector(initializeWithDelegate:) withObject:delegate]; + self.globalMediationSettings = globalMediationSettings; +} + +- (id)globalMediationSettingsForClass:(Class)aClass +{ + NSArray *mediationSettingsCollection = self.globalMediationSettings; + + for (id settings in mediationSettingsCollection) { + if ([settings isKindOfClass:aClass]) { + return settings; + } + } + + return nil; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/Categories/MPNativeAdRequest+MPNativeAdSource.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/Categories/MPNativeAdRequest+MPNativeAdSource.h new file mode 100644 index 000000000..8c18dca23 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/Categories/MPNativeAdRequest+MPNativeAdSource.h @@ -0,0 +1,14 @@ +// +// MPNativeAdRequest+MPNativeAdSource.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdRequest.h" + +@interface MPNativeAdRequest (MPNativeAdSource) + +- (void)startForAdSequence:(NSInteger)adSequence withCompletionHandler:(MPNativeAdRequestHandler)handler; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.h new file mode 100644 index 000000000..13030c181 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.h @@ -0,0 +1,124 @@ +// +// MPAdPlacerInvocation.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class MPStreamAdPlacer; + +/** + * A convenience class that handles a lot of the common logic when implementing a wrapper for the delegate / data source of a UI collection object + * (e.g. UITableView or UICollectionView). + * + * When implementing wrapper object methods, you will often have to take the following into consideration: + * + * - Handling cells that contain ads differently from regular content cells. For example, you may want to disable moving an ad cell while allowing + * regular content cells to move. + * + * - Calling through to the original object when handling regular content cells. The original delegate / data source only knows about regular content + * cells. Thus, you need to translate the given index path, that indexes ads and content, to an original index path that only indexes content. + * You can use the original translated index path to have the original delegate / data source process logic on the correct cell. + * + * - Providing the default behavior when the original object doesn't respond to the specific method and an ad doesn't occupy the given index path. + * + * This class takes care of all the work in two steps. Set up and invoke an NSInvocation object by calling invokeForTarget:. If you wish to return + * a value based on the invocation, you may pass the returned invocation to one of the result methods (e.g. boolResultForInvocation:defaultValue:) and + * provide a defaultValue that will be returned if an ad occupies the cell or the original delegate / data source doesn't respond to the selector. + * If an ad is not at the given index path and the original delegate / data source responds to the selector, invokeForTarget: will translate the index + * path for you and pass it to the original delegate / data source. The result method will then return the result from the invocation. + */ + +@interface MPAdPlacerInvocation : NSObject + +/** + * Creates an NSInvocation object with the given parameters and invokes the object. + * This will return nil if there is an ad at the index path or the target doesn't respond to the selector. + * + * @param target The object's original data source or delegate. + * @param with2ArgSelector The method we want to execute on the target if an ad doesn't exist. + * @param firstArg The first argument to the selector. + * @param secondArg The second argument to the selector. + * @param streamAdPlacer The MPStreamAdPlacer backing your UI collection that can translate index paths to their originals. + * + * @return The invocation with all the parameters passed into the method. + */ ++ (NSInvocation *)invokeForTarget:(id)target + with2ArgSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer; + +/** + * Creates an NSInvocation object with the given parameters and invokes the object. + * This will return nil if there is an ad at the index path or the target doesn't respond to the selector. + * + * @param target The object's original data source or delegate. + * @param with3ArgSelector The method we want to execute on the target if an ad doesn't exist. + * @param firstArg The first argument to the selector. + * @param secondArg The second argument to the selector. + * @param thirdArg The third argument to the selector. + * @param streamAdPlacer The MPStreamAdPlacer backing your UI collection that can translate index paths to their originals. + * + * @return The invocation with all the parameters passed into the method. + */ ++ (NSInvocation *)invokeForTarget:(id)target + with3ArgSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(id)arg2 + thirdArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer; + +/** + * Creates an NSInvocation object with the given parameters and invokes the object. + * This will return nil if there is an ad at the index path or the target doesn't respond to the selector. + * + * @param target The object's original data source or delegate. + * @param with3ArgSelector The method we want to execute on the target if an ad doesn't exist. + * @param firstArg The first argument to the selector. + * @param secondArg The second argument to the selector. + * @param thirdArg The third argument to the selector. + * @param streamAdPlacer The MPStreamAdPlacer backing your UI collection that can translate index paths to their originals. + * + * @return The invocation with all the parameters passed into the method. + */ ++ (NSInvocation *)invokeForTarget:(id)target + with3ArgIntSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(NSInteger)arg2 + thirdArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer; + +/** + * Returns the result for an invocation. Will return defaultReturnValue if invocation is nil. + * + * @param invocation The invocation that was returned from invokeForTarget:. + * @param defaultReturnValue What to return when the invocation is nil. + * + * @return defaultReturnValue or the invocation's return value. + */ ++ (BOOL)boolResultForInvocation:(NSInvocation *)invocation defaultValue:(BOOL)defaultReturnValue; + +/** + * Returns the result for an invocation. Will return defaultReturnValue if invocation is nil. + * + * @param invocation The invocation that was returned from invokeForTarget:. + * @param defaultReturnValue What to return when the invocation is nil. + * + * @return defaultReturnValue or the invocation's return value. + */ ++ (NSInteger)integerResultForInvocation:(NSInvocation *)invocation defaultValue:(NSInteger)defaultReturnValue; + +/** + * Returns the result for an invocation. Will return defaultReturnValue if invocation is nil. + * + * @param invocation The invocation that was returned from invokeForTarget:. + * @param defaultReturnValue What to return when the invocation is nil. + * + * @return defaultReturnValue or the invocation's return value. + */ ++ (id)resultForInvocation:(NSInvocation *)invocation defaultValue:(id)defaultReturnValue; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.m new file mode 100644 index 000000000..8fe0af42e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPAdPlacerInvocation.m @@ -0,0 +1,129 @@ +// +// MPAdPlacerInvocation.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPAdPlacerInvocation.h" +#import "MPStreamAdPlacer.h" + +@implementation MPAdPlacerInvocation + ++ (NSInvocation *)invocationForTarget:(id)target + selector:(SEL)selector + indexPath:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer +{ + if (![target respondsToSelector:selector]) { + return nil; + } + + // No invocations for ad rows. + if ([streamAdPlacer isAdAtIndexPath:indexPath]) { + return nil; + } + + // Create the invocation. + NSMethodSignature *signature = [target methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:target]; + [invocation setSelector:selector]; + return invocation; +} + ++ (NSInvocation *)invokeForTarget:(id)target + with2ArgSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer +{ + NSInvocation *invocation = [MPAdPlacerInvocation invocationForTarget:target + selector:selector + indexPath:indexPath + streamAdPlacer:streamAdPlacer]; + if (invocation) { + NSIndexPath *origPath = [streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [invocation setArgument:&(arg1) atIndex:2]; + [invocation setArgument:&(origPath) atIndex:3]; + [invocation invoke]; + } + return invocation; +} + ++ (NSInvocation *)invokeForTarget:(id)target + with3ArgSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(id)arg2 + thirdArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer +{ + NSInvocation *invocation = [MPAdPlacerInvocation invocationForTarget:target + selector:selector + indexPath:indexPath + streamAdPlacer:streamAdPlacer]; + if (invocation) { + NSIndexPath *origPath = [streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [invocation setArgument:&(arg1) atIndex:2]; + [invocation setArgument:&(arg2) atIndex:3]; + [invocation setArgument:&(origPath) atIndex:4]; + [invocation invoke]; + } + return invocation; +} + ++ (NSInvocation *)invokeForTarget:(id)target + with3ArgIntSelector:(SEL)selector + firstArg:(id)arg1 + secondArg:(NSInteger)arg2 + thirdArg:(NSIndexPath *)indexPath + streamAdPlacer:(MPStreamAdPlacer *)streamAdPlacer +{ + NSInvocation *invocation = [MPAdPlacerInvocation invocationForTarget:target + selector:selector + indexPath:indexPath + streamAdPlacer:streamAdPlacer]; + if (invocation) { + NSIndexPath *origPath = [streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [invocation setArgument:&(arg1) atIndex:2]; + [invocation setArgument:&(arg2) atIndex:3]; + [invocation setArgument:&(origPath) atIndex:4]; + [invocation invoke]; + } + return invocation; +} + ++ (BOOL)boolResultForInvocation:(NSInvocation *)invocation defaultValue:(BOOL)defaultReturnValue +{ + if (!invocation) { + return defaultReturnValue; + } + + BOOL returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + ++ (id)resultForInvocation:(NSInvocation *)invocation defaultValue:(id)defaultReturnValue +{ + if (!invocation) { + return defaultReturnValue; + } + + __unsafe_unretained id returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + ++ (NSInteger)integerResultForInvocation:(NSInvocation *)invocation defaultValue:(NSInteger)defaultReturnValue +{ + if (!invocation) { + return defaultReturnValue; + } + + NSInteger returnValue; + [invocation getReturnValue:&returnValue]; + return returnValue; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.h new file mode 100644 index 000000000..def7c3298 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.h @@ -0,0 +1,12 @@ +// +// MPCollectionViewAdPlacerCell.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPCollectionViewAdPlacerCell : UICollectionViewCell + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.m new file mode 100644 index 000000000..60e9cfb8f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPCollectionViewAdPlacerCell.m @@ -0,0 +1,12 @@ +// +// MPCollectionViewAdPlacerCell.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPCollectionViewAdPlacerCell.h" + +@implementation MPCollectionViewAdPlacerCell + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.h new file mode 100755 index 000000000..7eab0ab1e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.h @@ -0,0 +1,21 @@ +// +// MPDiskLRUCache.h +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@interface MPDiskLRUCache : NSObject + ++ (MPDiskLRUCache *)sharedDiskCache; + +/* + * Do NOT call any of the following methods on the main thread, potentially lengthy wait for disk IO + */ +- (BOOL)cachedDataExistsForKey:(NSString *)key; +- (NSData *)retrieveDataForKey:(NSString *)key; +- (void)storeData:(NSData *)data forKey:(NSString *)key; +- (void)removeAllCachedFiles; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.m new file mode 100755 index 000000000..8736ae131 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPDiskLRUCache.m @@ -0,0 +1,266 @@ +// +// MPDiskLRUCache.m +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPDiskLRUCache.h" +#import "MPGlobal.h" +#import "MPLogging.h" + +#import + +// cached files that have not been access since kCacheFileMaxAge ago will be evicted +#define kCacheFileMaxAge (7 * 24 * 60 * 60) // 1 week + +// once the cache hits this size AND we've added at least kCacheBytesStoredBeforeSizeCheck bytes, +// cached files will be evicted (LRU) until the total size drops below this limit +#define kCacheSoftMaxSize (100 * 1024 * 1024) // 100 MB + +#define kCacheBytesStoredBeforeSizeCheck (kCacheSoftMaxSize / 10) // 10% of kCacheSoftMaxSize + +@interface MPDiskLRUCacheFile : NSObject + +@property (nonatomic, copy) NSString *filePath; +@property (nonatomic, assign) NSTimeInterval lastModTimestamp; +@property (nonatomic, assign) uint64_t fileSize; + +@end + +@implementation MPDiskLRUCacheFile + + +@end + +@interface MPDiskLRUCache () + +#if !OS_OBJECT_USE_OBJC +@property (nonatomic, assign) dispatch_queue_t diskIOQueue; +#else +@property (nonatomic, strong) dispatch_queue_t diskIOQueue; +#endif +@property (nonatomic, copy) NSString *diskCachePath; +@property (atomic, assign) uint64_t numBytesStoredForSizeCheck; + +@end + +@implementation MPDiskLRUCache + ++ (MPDiskLRUCache *)sharedDiskCache +{ + static dispatch_once_t once; + static MPDiskLRUCache *sharedDiskCache; + dispatch_once(&once, ^{ + sharedDiskCache = [self new]; + }); + return sharedDiskCache; +} + +- (id)init +{ + self = [super init]; + if (self != nil) { + _diskIOQueue = dispatch_queue_create("com.mopub.diskCacheIOQueue", DISPATCH_QUEUE_SERIAL); + + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + if (paths.count > 0) { + _diskCachePath = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"com.mopub.diskCache"] copy]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:_diskCachePath]) { + [fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:nil]; + } + } + + // check cache size on startup + [self ensureCacheSizeLimit]; + } + + return self; +} + +- (void)dealloc +{ +#if !OS_OBJECT_USE_OBJC + dispatch_release(_diskIOQueue); +#endif +} + +#pragma mark Public + +- (void)removeAllCachedFiles +{ + dispatch_sync(self.diskIOQueue, ^{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + + NSArray *allFiles = [self cacheFilesSortedByModDate]; + for (MPDiskLRUCacheFile *file in allFiles) { + [fileManager removeItemAtPath:file.filePath error:nil]; + } + }); +} + +- (BOOL)cachedDataExistsForKey:(NSString *)key +{ + __block BOOL result = NO; + + dispatch_sync(self.diskIOQueue, ^{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + result = [fileManager fileExistsAtPath:[self cacheFilePathForKey:key]]; + }); + + return result; +} + +- (NSData *)retrieveDataForKey:(NSString *)key +{ + __block NSData *data = nil; + + dispatch_sync(self.diskIOQueue, ^{ + NSString *cachedFilePath = [self cacheFilePathForKey:key]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL isDirectory = NO; + if ([fileManager fileExistsAtPath:cachedFilePath isDirectory:&isDirectory]) { + data = [NSData dataWithContentsOfFile:cachedFilePath]; + + // "touch" file to mark access since NSFileManager doesn't return a last accessed date + [fileManager setAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] ofItemAtPath:cachedFilePath error:nil]; + } + }); + + return data; +} + +- (void)storeData:(NSData *)data forKey:(NSString *)key +{ + dispatch_sync(self.diskIOQueue, ^{ + NSString *cacheFilePath = [self cacheFilePathForKey:key]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (![fileManager fileExistsAtPath:cacheFilePath]) { + [fileManager createFileAtPath:cacheFilePath contents:data attributes:nil]; + } else { + // overwrite existing file + [data writeToFile:cacheFilePath atomically:YES]; + } + }); + + self.numBytesStoredForSizeCheck += data.length; + + if (self.numBytesStoredForSizeCheck >= kCacheBytesStoredBeforeSizeCheck) { + [self ensureCacheSizeLimit]; + self.numBytesStoredForSizeCheck = 0; + } +} + +#pragma mark Private + +- (void)ensureCacheSizeLimit +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + MPLogDebug(@"Checking cache size..."); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + NSMutableArray *cacheFilesSortedByModDate = [self cacheFilesSortedByModDate]; + + dispatch_async(self.diskIOQueue, ^{ + @autoreleasepool { + // verify age + NSArray *expiredFiles = [self expiredCachedFilesInArray:cacheFilesSortedByModDate]; + for (MPDiskLRUCacheFile *file in expiredFiles) { + MPLogDebug(@"Trying to remove %@ from cache due to expiration", file.filePath); + + [fileManager removeItemAtPath:file.filePath error:nil]; + [cacheFilesSortedByModDate removeObject:file]; + } + + // verify size + while ([self sizeOfCacheFilesInArray:cacheFilesSortedByModDate] >= kCacheSoftMaxSize && cacheFilesSortedByModDate.count > 0) { + NSString *oldestFilePath = ((MPDiskLRUCacheFile *)[cacheFilesSortedByModDate objectAtIndex:0]).filePath; + + MPLogDebug(@"Trying to remove %@ from cache due to size", oldestFilePath); + + [fileManager removeItemAtPath:oldestFilePath error:nil]; + [cacheFilesSortedByModDate removeObjectAtIndex:0]; + } + } + }); + }); +} + +- (NSArray *)expiredCachedFilesInArray:(NSArray *)cachedFiles +{ + NSMutableArray *result = [NSMutableArray array]; + + NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate]; + + for (MPDiskLRUCacheFile *file in cachedFiles) { + if (now - file.lastModTimestamp >= kCacheFileMaxAge) { + [result addObject:file]; + } + } + + return result; +} + +- (NSMutableArray *)cacheFilesSortedByModDate +{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + + NSArray *cachedFiles = [fileManager contentsOfDirectoryAtPath:self.diskCachePath error:nil]; + NSArray *sortedFiles = [cachedFiles sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { + NSString *fileName1 = [self.diskCachePath stringByAppendingPathComponent:(NSString *)obj1]; + NSString *fileName2 = [self.diskCachePath stringByAppendingPathComponent:(NSString *)obj2]; + + NSDictionary *fileAttrs1 = [fileManager attributesOfItemAtPath:fileName1 error:nil]; + NSDictionary *fileAttrs2 = [fileManager attributesOfItemAtPath:fileName2 error:nil]; + + NSDate *lastModDate1 = [fileAttrs1 fileModificationDate]; + NSDate *lastModDate2 = [fileAttrs2 fileModificationDate]; + + return [lastModDate1 compare:lastModDate2]; + }]; + + NSMutableArray *result = [NSMutableArray array]; + + for (NSString *fileName in sortedFiles) { + if ([fileName hasPrefix:@"."]) { + continue; + } + + MPDiskLRUCacheFile *cacheFile = [[MPDiskLRUCacheFile alloc] init]; + cacheFile.filePath = [self.diskCachePath stringByAppendingPathComponent:fileName]; + + NSDictionary *fileAttrs = [fileManager attributesOfItemAtPath:cacheFile.filePath error:nil]; + cacheFile.fileSize = [fileAttrs fileSize]; + cacheFile.lastModTimestamp = [[fileAttrs fileModificationDate] timeIntervalSinceReferenceDate]; + + [result addObject:cacheFile]; + } + + return result; +} + +- (uint64_t)sizeOfCacheFilesInArray:(NSArray *)files +{ + uint64_t currentSize = 0; + + for (MPDiskLRUCacheFile *file in files) { + currentSize += file.fileSize; + } + + MPLogDebug(@"Current cache size %qu bytes", currentSize); + + return currentSize; +} + +- (NSString *)cacheFilePathForKey:(NSString *)key +{ + NSString *hashedKey = MPSHA1Digest(key); + NSString *cachedFilePath = [self.diskCachePath stringByAppendingPathComponent:hashedKey]; + return cachedFilePath; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.h new file mode 100755 index 000000000..d9c579338 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.h @@ -0,0 +1,19 @@ +// +// MPImageDownloadQueue.h +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +typedef void (^MPImageDownloadQueueCompletionBlock)(NSArray *errors); + +@interface MPImageDownloadQueue : NSObject + +// pass useCachedImage:NO to force download of images. default is YES, cached images will not be re-downloaded +- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock; +- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock useCachedImage:(BOOL)useCachedImage; + +- (void)cancelAllDownloads; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.m new file mode 100755 index 000000000..783a283d4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPImageDownloadQueue.m @@ -0,0 +1,105 @@ +// +// MPImageDownloadQueue.m +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPImageDownloadQueue.h" +#import "MPNativeAdError.h" +#import "MPLogging.h" +#import "MPNativeCache.h" + +@interface MPImageDownloadQueue () + +@property (atomic, strong) NSOperationQueue *imageDownloadQueue; +@property (atomic, assign) BOOL isCanceled; + +@end + +@implementation MPImageDownloadQueue + +- (id)init +{ + self = [super init]; + + if (self != nil) { + _imageDownloadQueue = [[NSOperationQueue alloc] init]; + [_imageDownloadQueue setMaxConcurrentOperationCount:1]; // serial queue + } + + return self; +} + +- (void)dealloc +{ + [_imageDownloadQueue cancelAllOperations]; +} + +- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock +{ + [self addDownloadImageURLs:imageURLs completionBlock:completionBlock useCachedImage:YES]; +} + +- (void)addDownloadImageURLs:(NSArray *)imageURLs completionBlock:(MPImageDownloadQueueCompletionBlock)completionBlock useCachedImage:(BOOL)useCachedImage +{ + __block NSMutableArray *errors = nil; + + for (NSURL *imageURL in imageURLs) { + [self.imageDownloadQueue addOperationWithBlock:^{ + @autoreleasepool { + if (![[MPNativeCache sharedCache] cachedDataExistsForKey:imageURL.absoluteString] || !useCachedImage) { + MPLogDebug(@"Downloading %@", imageURL); + + NSURLResponse *response = nil; + NSError *error = nil; + NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:imageURL] + returningResponse:&response + error:&error]; + + BOOL validImageDownloaded = data != nil; + if (validImageDownloaded) { + UIImage *downloadedImage = [UIImage imageWithData:data]; + if (downloadedImage != nil) { + [[MPNativeCache sharedCache] storeData:data forKey:imageURL.absoluteString]; + } else { + if (downloadedImage == nil) { + MPLogDebug(@"Error: invalid image data downloaded"); + } + + validImageDownloaded = NO; + } + } + + if (!validImageDownloaded) { + if (error == nil) { + error = MPNativeAdNSErrorForImageDownloadFailure(); + } + + if (errors == nil) { + errors = [NSMutableArray array]; + } + + [errors addObject:error]; + } + } + } + }]; + } + + // after all images have been downloaded, invoke callback on main thread + [self.imageDownloadQueue addOperationWithBlock:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (!self.isCanceled) { + completionBlock(errors); + } + }); + }]; +} + +- (void)cancelAllDownloads +{ + self.isCanceled = YES; + [self.imageDownloadQueue cancelAllOperations]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.h new file mode 100644 index 000000000..c48f7f581 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.h @@ -0,0 +1,20 @@ +// +// MPMoPubNativeAdAdapter.h +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdAdapter.h" + +@class MPAdConfiguration; + +@interface MPMoPubNativeAdAdapter : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, readonly) NSArray *impressionTrackerURLs; +@property (nonatomic, readonly) NSArray *clickTrackerURLs; +@property (nonatomic) MPAdConfiguration *adConfiguration; + +- (instancetype)initWithAdProperties:(NSMutableDictionary *)properties; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.m new file mode 100644 index 000000000..a8d6c6aa5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeAdAdapter.m @@ -0,0 +1,156 @@ +// +// MPMoPubNativeAdAdapter.m +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPMoPubNativeAdAdapter.h" +#import "MPNativeAdError.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPCoreInstanceProvider.h" +#import "MPStaticNativeAdImpressionTimer.h" +#import "MPNativeAdConstants.h" +#import "MPGlobal.h" + +static const NSTimeInterval kMoPubRequiredSecondsForImpression = 1.0; +static const CGFloat kMoPubRequiredViewVisibilityPercentage = 0.5; + +@interface MPMoPubNativeAdAdapter () + +@property (nonatomic) MPStaticNativeAdImpressionTimer *impressionTimer; +@property (nonatomic, readonly) MPAdDestinationDisplayAgent *destinationDisplayAgent; + +@end + +@implementation MPMoPubNativeAdAdapter + +@synthesize properties = _properties; +@synthesize defaultActionURL = _defaultActionURL; + +- (instancetype)initWithAdProperties:(NSMutableDictionary *)properties +{ + if (self = [super init]) { + + // Let's make sure the data types of all the provided native ad properties are strings before creating the adapter + + NSArray *keysToCheck = @[kAdIconImageKey, kAdMainImageKey, kAdTextKey, kAdTitleKey, kAdCTATextKey]; + + for (NSString *key in keysToCheck) { + id value = properties[key]; + if (value != nil && ![value isKindOfClass:[NSString class]]) { + return nil; + } + } + + BOOL valid = YES; + NSArray *impressionTrackers = [properties objectForKey:kImpressionTrackerURLsKey]; + if (![impressionTrackers isKindOfClass:[NSArray class]] || [impressionTrackers count] < 1) { + valid = NO; + } else { + _impressionTrackerURLs = MPConvertStringArrayToURLArray(impressionTrackers); + } + + NSObject *clickTracker = [properties objectForKey:kClickTrackerURLKey]; + + // The click tracker could either be a single URL or an array of URLS. + if ([clickTracker isKindOfClass:[NSArray class]]) { + _clickTrackerURLs = MPConvertStringArrayToURLArray((NSArray *)clickTracker); + } else if ([clickTracker isKindOfClass:[NSString class]]) { + NSURL *url = [NSURL URLWithString:(NSString *)clickTracker]; + if (url) { + _clickTrackerURLs = @[ url ]; + } else { + valid = NO; + } + } else { + valid = NO; + } + + _defaultActionURL = [NSURL URLWithString:[properties objectForKey:kDefaultActionURLKey]]; + + [properties removeObjectsForKeys:[NSArray arrayWithObjects:kImpressionTrackerURLsKey, kClickTrackerURLKey, kDefaultActionURLKey, nil]]; + _properties = properties; + + if (!valid) { + return nil; + } + + // Add the DAA icon settings to our properties dictionary. + NSString * daaIconImagePath = MPResourcePathForResource(kDAAIconImageName); + if (daaIconImagePath != nil) { + [properties setObject:daaIconImagePath forKey:kAdDAAIconImageKey]; + } + + _destinationDisplayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + _impressionTimer = [[MPStaticNativeAdImpressionTimer alloc] initWithRequiredSecondsForImpression:kMoPubRequiredSecondsForImpression requiredViewVisibilityPercentage:kMoPubRequiredViewVisibilityPercentage]; + _impressionTimer.delegate = self; + } + + return self; +} + +- (void)dealloc +{ + [_destinationDisplayAgent cancel]; + [_destinationDisplayAgent setDelegate:nil]; +} + +#pragma mark - + +- (void)willAttachToView:(UIView *)view +{ + [self.impressionTimer startTrackingView:view]; +} + +- (void)displayContentForURL:(NSURL *)URL rootViewController:(UIViewController *)controller +{ + if (!controller) { + return; + } + + if (!URL || ![URL isKindOfClass:[NSURL class]] || ![URL.absoluteString length]) { + return; + } + + [self.destinationDisplayAgent displayDestinationForURL:URL]; +} + +#pragma mark - DAA Icon + +- (void)displayContentForDAAIconTap +{ + [self.destinationDisplayAgent displayDestinationForURL:[NSURL URLWithString:kDAAIconTapDestinationURL]]; +} + +#pragma mark - + +- (void)trackImpression +{ + [self.delegate nativeAdWillLogImpression:self]; +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)displayAgentWillPresentModal +{ + [self.delegate nativeAdWillPresentModalForAdapter:self]; +} + +- (void)displayAgentWillLeaveApplication +{ + [self.delegate nativeAdWillLeaveApplicationFromAdapter:self]; +} + +- (void)displayAgentDidDismissModal +{ + [self.delegate nativeAdDidDismissModalForAdapter:self]; +} + +// - (MPAdConfiguration *)adConfiguration delegate method is automatically implemented via the adConfiguration property declaration. + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.h new file mode 100644 index 000000000..a62bf50e3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.h @@ -0,0 +1,12 @@ +// +// MPMoPubNativeCustomEvent.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeCustomEvent.h" + +@interface MPMoPubNativeCustomEvent : MPNativeCustomEvent + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.m new file mode 100644 index 000000000..d444c2c3f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPMoPubNativeCustomEvent.m @@ -0,0 +1,50 @@ +// +// MPMoPubNativeCustomEvent.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPMoPubNativeCustomEvent.h" +#import "MPMoPubNativeAdAdapter.h" +#import "MPNativeAd+Internal.h" +#import "MPNativeAdError.h" +#import "MPLogging.h" +#import "MPNativeAdUtils.h" + +@implementation MPMoPubNativeCustomEvent + +- (void)requestAdWithCustomEventInfo:(NSDictionary *)info +{ + MPMoPubNativeAdAdapter *adAdapter = [[MPMoPubNativeAdAdapter alloc] initWithAdProperties:[info mutableCopy]]; + + if (adAdapter.properties) { + MPNativeAd *interfaceAd = [[MPNativeAd alloc] initWithAdAdapter:adAdapter]; + [interfaceAd.impressionTrackerURLs addObjectsFromArray:adAdapter.impressionTrackerURLs]; + [interfaceAd.clickTrackerURLs addObjectsFromArray:adAdapter.clickTrackerURLs]; + + // Get the image urls so we can download them prior to returning the ad. + NSMutableArray *imageURLs = [NSMutableArray array]; + for (NSString *key in [info allKeys]) { + if ([[key lowercaseString] hasSuffix:@"image"] && [[info objectForKey:key] isKindOfClass:[NSString class]]) { + if (![MPNativeAdUtils addURLString:[info objectForKey:key] toURLArray:imageURLs]) { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidImageURL()]; + } + } + } + + [super precacheImagesWithURLs:imageURLs completionBlock:^(NSArray *errors) { + if (errors) { + MPLogDebug(@"%@", errors); + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForImageDownloadFailure()]; + } else { + [self.delegate nativeCustomEvent:self didLoadAd:interfaceAd]; + } + }]; + } else { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(nil)]; + } + +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.h new file mode 100644 index 000000000..571ed5f58 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.h @@ -0,0 +1,40 @@ +// +// MPNativeAd+Internal.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAd.h" + +@class MPNativeView; + +@interface MPNativeAd (Internal) + +@property (nonatomic, readonly) NSDate *creationDate; +@property (nonatomic) MPNativeView *associatedView; +@property (nonatomic, readwrite, strong) id renderer; +@property (nonatomic, readonly) NSMutableSet *clickTrackerURLs; +@property (nonatomic, readonly) NSMutableSet *impressionTrackerURLs; +@property (nonatomic, readonly, strong) id adAdapter; + +/** + * This method is called by the ad placers when the sizes of the ad placer stream + * view's have changed. The ad placer will get the size from the renderer and just + * pass it through to the mpnativead to update the view size since the ad is the only one + * who has access to the ad view. +*/ +- (void)updateAdViewSize:(CGSize)size; + +/** + * Retrieves the custom ad view with its frame set to the would-be containing native view. Unlike + * `retrieveAdViewWithError:`, this method does not have side effects of changing the view hierarchy + * and is only intended for size calculation purposes. + * + * @param error A pointer to an error object. If an error occurs, this pointer will be set to an + * actual error object containing the error information. + * + * @return If successful, the method will return the rendered ad. The method will + * return nil if it cannot render the ad data to a view. + */ +- (UIView *)retrieveAdViewForSizeCalculationWithError:(NSError **)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.m new file mode 100644 index 000000000..813f1453f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAd+Internal.m @@ -0,0 +1,38 @@ +// +// MPNativeAd+Internal.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAd+Internal.h" +#import "MPNativeAdRenderer.h" +#import "MPNativeView.h" + +@implementation MPNativeAd (Internal) + +@dynamic impressionTrackerURLs; +@dynamic clickTrackerURLs; +@dynamic creationDate; +@dynamic renderer; +@dynamic associatedView; +@dynamic adAdapter; + +- (void)updateAdViewSize:(CGSize)size +{ + self.associatedView.frame = CGRectMake(0, 0, size.width, size.height); +} + +- (UIView *)retrieveAdViewForSizeCalculationWithError:(NSError **)error +{ + // retrieve the ad and apply the frame of the associatedView (superview of the adView) so the + // adView can calculate its own size. It's important that we don't add adView to the associatedView + // because this can mess up expectations in `retrieveAdViewWithError:` especially around hydrating + // image views asynchronously + UIView *adView = [self.renderer retrieveViewWithAdapter:self.adAdapter error:error]; + adView.frame = self.associatedView.bounds; + return adView; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererConstants.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererConstants.h new file mode 100644 index 000000000..bc1e9af48 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererConstants.h @@ -0,0 +1,14 @@ +// +// MPNativeAdRendererConstants.h +// MoPubSDK +// +// Copyright (c) 2016 MoPub. All rights reserved. +// + +/** + * Return this value from `MPNativeViewSizeHandler` when you want to display ad content that could + * have variable height and needs to be calculated only after ad properties are available. The + * implementation of ad view conforming to the `MPNativeAdRendering` protocol should implement + * `sizeThatFits:` and handle layout changes appropriately. + */ +FOUNDATION_EXPORT const CGFloat MPNativeViewDynamicDimension; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.h new file mode 100644 index 000000000..36ea61a1b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.h @@ -0,0 +1,22 @@ +// +// MPNativeAdRendererImageHandler.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@protocol MPNativeAdRendererImageHandlerDelegate + +- (BOOL)nativeAdViewInViewHierarchy; + +@end + +@interface MPNativeAdRendererImageHandler : NSObject + + +@property (nonatomic, weak) id delegate; + +- (void)loadImageForURL:(NSURL *)imageURL intoImageView:(UIImageView *)imageView; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.m new file mode 100644 index 000000000..4214e570f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdRendererImageHandler.m @@ -0,0 +1,96 @@ +// +// MPNativeAdRendererImageHandler.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeAdRendererImageHandler.h" +#import "MPLogging.h" +#import "MPNativeCache.h" +#import "MPImageDownloadQueue.h" + +@interface MPNativeAdRendererImageHandler() + +@property (nonatomic) MPImageDownloadQueue *imageDownloadQueue; + +@end + +@implementation MPNativeAdRendererImageHandler + +- (instancetype)init +{ + if (self = [super init]) { + _imageDownloadQueue = [[MPImageDownloadQueue alloc] init]; + } + return self; +} + +- (void)loadImageForURL:(NSURL *)imageURL intoImageView:(UIImageView *)imageView +{ + imageView.image = nil; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + __block BOOL isAdViewInHierarchy = NO; + + // Try to prevent unnecessary work if the ad view is not currently in the view hierarchy. + // Note that this doesn't prevent 100% of the cases as the ad view can still be recycled after this passes. + // We have an additional 100% accurate check in safeMainQueueSetImage to ensure that we don't overwrite. + + dispatch_sync(dispatch_get_main_queue(), ^{ + isAdViewInHierarchy = [self.delegate nativeAdViewInViewHierarchy]; + }); + + if (!isAdViewInHierarchy) { + MPLogDebug(@"Cell was recycled. Don't bother rendering the image."); + return; + } + + NSData *cachedImageData = [[MPNativeCache sharedCache] retrieveDataForKey:imageURL.absoluteString]; + UIImage *image = [UIImage imageWithData:cachedImageData]; + + if (image) { + // By default, the image data isn't decompressed until set on a UIImageView, on the main thread. This + // can result in poor scrolling performance. To fix this, we force decompression in the background before + // assignment to a UIImageView. + UIGraphicsBeginImageContext(CGSizeMake(1, 1)); + [image drawAtPoint:CGPointZero]; + UIGraphicsEndImageContext(); + + [self safeMainQueueSetImage:image intoImageView:imageView]; + } else if (imageURL) { + MPLogDebug(@"Cache miss on %@. Re-downloading...", imageURL); + + __weak typeof(self) weakSelf = self; + [self.imageDownloadQueue addDownloadImageURLs:@[imageURL] + completionBlock:^(NSArray *errors) { + __strong typeof(self) strongSelf = weakSelf; + if (strongSelf) { + if (errors.count == 0) { + UIImage *image = [UIImage imageWithData:[[MPNativeCache sharedCache] retrieveDataForKey:imageURL.absoluteString]]; + + [strongSelf safeMainQueueSetImage:image intoImageView:imageView]; + } else { + MPLogDebug(@"Failed to download %@ on cache miss. Giving up for now.", imageURL); + } + } else { + MPLogInfo(@"MPNativeAd deallocated before loadImageForURL:intoImageView: download completion block was called"); + } + }]; + } + }); +} + +- (void)safeMainQueueSetImage:(UIImage *)image intoImageView:(UIImageView *)imageView +{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (![self.delegate nativeAdViewInViewHierarchy]) { + MPLogDebug(@"Cell was recycled. Don't bother setting the image."); + return; + } + + if (image) { + imageView.image = image; + } + }); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.h new file mode 100644 index 000000000..af870c27b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.h @@ -0,0 +1,31 @@ +// +// MPNativeAdSourceQueue.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +@class MPNativeAdRequestTargeting; +@class MPNativeAd; + +@protocol MPNativeAdSourceQueueDelegate; + +@interface MPNativeAdSourceQueue : NSObject + +@property (nonatomic, weak) id delegate; + + +- (instancetype)initWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations andTargeting:(MPNativeAdRequestTargeting *)targeting; +- (MPNativeAd *)dequeueAdWithMaxAge:(NSTimeInterval)age; +- (NSUInteger)count; +- (void)loadAds; +- (void)cancelRequests; + +@end + +@protocol MPNativeAdSourceQueueDelegate + +- (void)adSourceQueueAdIsAvailable:(MPNativeAdSourceQueue *)source; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.m new file mode 100644 index 000000000..a8796f415 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdSourceQueue.m @@ -0,0 +1,152 @@ +// +// MPNativeAdSourceQueue.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdSourceQueue.h" +#import "MPNativeAd+Internal.h" +#import "MPNativeAdRequestTargeting.h" +#import "MPNativeAdRequest+MPNativeAdSource.h" +#import "MPLogging.h" +#import "MPNativeAdError.h" + +static NSUInteger const kCacheSizeLimit = 1; +static NSTimeInterval const kAdFetchRetryTimes[] = {1, 3, 5, 25, 60, 300}; +// Calculate the number of elements inside the array by taking the size divided by the size of one element. +static NSUInteger const kMaxRetries = sizeof(kAdFetchRetryTimes)/sizeof(kAdFetchRetryTimes[0]); + +@interface MPNativeAdSourceQueue () + +@property (nonatomic) NSMutableArray *adQueue; +@property (nonatomic, assign) NSUInteger adFetchRetryCounter; +@property (nonatomic, assign) NSUInteger currentSequence; +@property (nonatomic, copy) NSString *adUnitIdentifier; +@property (nonatomic) MPNativeAdRequestTargeting *targeting; +@property (nonatomic) NSArray *rendererConfigurations; +@property (nonatomic, assign) BOOL isAdLoading; + +@end + +@implementation MPNativeAdSourceQueue + +#pragma mark - Object Lifecycle + +- (instancetype)initWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations andTargeting:(MPNativeAdRequestTargeting *)targeting +{ + self = [super init]; + if (self) { + _adUnitIdentifier = [identifier copy]; + _rendererConfigurations = rendererConfigurations; + _targeting = targeting; + _adQueue = [[NSMutableArray alloc] init]; + } + return self; +} + + +#pragma mark - Public Methods + +- (MPNativeAd *)dequeueAd +{ + MPNativeAd *nextAd = [self.adQueue firstObject]; + [self.adQueue removeObject:nextAd]; + [self loadAds]; + return nextAd; +} + +- (MPNativeAd *)dequeueAdWithMaxAge:(NSTimeInterval)age +{ + MPNativeAd *nextAd = [self dequeueAd]; + + while (nextAd && ![self isAdAgeValid:nextAd withMaxAge:age]) { + nextAd = [self dequeueAd]; + } + + return nextAd; +} + +- (void)addNativeAd:(MPNativeAd *)nativeAd +{ + [self.adQueue addObject:nativeAd]; +} + +- (NSUInteger)count +{ + return [self.adQueue count]; +} + +- (void)cancelRequests +{ + [self resetBackoff]; +} + +#pragma mark - Internal Logic + +- (BOOL)isAdAgeValid:(MPNativeAd *)ad withMaxAge:(NSTimeInterval)maxAge +{ + NSTimeInterval adAge = [ad.creationDate timeIntervalSinceNow]; + + return fabs(adAge) < maxAge; +} + +#pragma mark - Ad Requests + +- (void)resetBackoff +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + self.adFetchRetryCounter = 0; +} + +- (void)loadAds +{ + if (self.adFetchRetryCounter == 0) { + [self replenishCache]; + } +} + +- (void)replenishCache +{ + if ([self count] >= kCacheSizeLimit || self.isAdLoading) { + return; + } + + self.isAdLoading = YES; + + MPNativeAdRequest *adRequest = [MPNativeAdRequest requestWithAdUnitIdentifier:self.adUnitIdentifier rendererConfigurations:self.rendererConfigurations]; + adRequest.targeting = self.targeting; + + [adRequest startForAdSequence:self.currentSequence withCompletionHandler:^(MPNativeAdRequest *request, MPNativeAd *response, NSError *error) { + if (response && !error) { + self.adFetchRetryCounter = 0; + + [self addNativeAd:response]; + self.currentSequence++; + if ([self count] == 1) { + [self.delegate adSourceQueueAdIsAvailable:self]; + } + } else { + MPLogDebug(@"%@", error); + //increment in this failure case to prevent retrying a request that wasn't bid on. + //currently under discussion on whether we do this or not. + if (error.code == MPNativeAdErrorNoInventory) { + self.currentSequence++; + } + + if (self.adFetchRetryCounter < kMaxRetries) { + NSTimeInterval retryTime = kAdFetchRetryTimes[self.adFetchRetryCounter]; + self.adFetchRetryCounter++; + [self performSelector:@selector(replenishCache) withObject:nil afterDelay:retryTime]; + MPLogDebug(@"Will re-attempt to replenish the ad cache in %.1f seconds.", retryTime); + } else { + // Don't try to fetch anymore ads after we have tried kMaxRetries times. + MPLogDebug(@"Replenishing the cache has timed out."); + } + } + self.isAdLoading = NO; + [self loadAds]; + }]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.h new file mode 100644 index 000000000..4f9d49ac9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.h @@ -0,0 +1,16 @@ +// +// MPNativeAdUtils.h +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +extern NSTimeInterval const kUpdateVisibleCellsInterval; + +@interface MPNativeAdUtils : NSObject + ++ (BOOL)addURLString:(NSString *)urlString toURLArray:(NSMutableArray *)urlArray; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.m new file mode 100644 index 000000000..506231c07 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeAdUtils.m @@ -0,0 +1,28 @@ +// +// MPNativeAdUtils.m +// MoPubSDK +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdUtils.h" + +NSTimeInterval const kUpdateVisibleCellsInterval = 0.25; + +@implementation MPNativeAdUtils + ++ (BOOL)addURLString:(NSString *)urlString toURLArray:(NSMutableArray *)urlArray +{ + if (urlString.length == 0) { + return NO; + } + + NSURL *url = [NSURL URLWithString:urlString]; + if (url) { + [urlArray addObject:url]; + return YES; + } else { + return NO; + } +} +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.h new file mode 100644 index 000000000..10762e72e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.h @@ -0,0 +1,23 @@ +// +// MPNativeCache.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@interface MPNativeCache : NSObject + ++ (instancetype)sharedCache; + +/* + * Do NOT call any of the following methods on the main thread, potentially lengthy wait for disk IO + */ +- (BOOL)cachedDataExistsForKey:(NSString *)key; +- (NSData *)retrieveDataForKey:(NSString *)key; +- (void)storeData:(NSData *)data forKey:(NSString *)key; +- (void)removeAllDataFromCache; +- (void)setInMemoryCacheEnabled:(BOOL)enabled; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.m new file mode 100644 index 000000000..7babede42 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeCache.m @@ -0,0 +1,185 @@ +// +// MPNativeCache.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeCache.h" +#import "MPDiskLRUCache.h" +#import "MPLogging.h" + +typedef enum { + MPNativeCacheMethodDisk = 0, + MPNativeCacheMethodDiskAndMemory = 1 << 0 +} MPNativeCacheMethod; + +@interface MPNativeCache () + +@property (nonatomic, strong) NSCache *memoryCache; +@property (nonatomic, strong) MPDiskLRUCache *diskCache; +@property (nonatomic, assign) MPNativeCacheMethod cacheMethod; + +- (BOOL)cachedDataExistsForKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod; +- (NSData *)retrieveDataForKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod; +- (void)storeData:(id)data forKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod; +- (void)removeAllDataFromMemory; +- (void)removeAllDataFromDisk; + +@end + +@implementation MPNativeCache + ++ (instancetype)sharedCache; +{ + static dispatch_once_t once; + static MPNativeCache *sharedCache; + dispatch_once(&once, ^{ + sharedCache = [[self alloc] init]; + }); + return sharedCache; +} + +- (id)init +{ + self = [super init]; + if (self != nil) { + _memoryCache = [[NSCache alloc] init]; + _memoryCache.delegate = self; + + _diskCache = [[MPDiskLRUCache alloc] init]; + + _cacheMethod = MPNativeCacheMethodDiskAndMemory; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:[UIApplication sharedApplication]]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; +} + +#pragma mark - Public Cache Interactions + +- (void)setInMemoryCacheEnabled:(BOOL)enabled +{ + if (enabled) { + self.cacheMethod = MPNativeCacheMethodDiskAndMemory; + } else { + self.cacheMethod = MPNativeCacheMethodDisk; + [self.memoryCache removeAllObjects]; + } +} + +- (BOOL)cachedDataExistsForKey:(NSString *)key +{ + return [self cachedDataExistsForKey:key withCacheMethod:self.cacheMethod]; +} + +- (NSData *)retrieveDataForKey:(NSString *)key +{ + return [self retrieveDataForKey:key withCacheMethod:self.cacheMethod]; +} + +- (void)storeData:(NSData *)data forKey:(NSString *)key +{ + [self storeData:data forKey:key withCacheMethod:self.cacheMethod]; +} + +- (void)removeAllDataFromCache +{ + [self removeAllDataFromMemory]; + [self removeAllDataFromDisk]; +} + +#pragma mark - Private Cache Implementation + +- (BOOL)cachedDataExistsForKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod +{ + BOOL dataExists = NO; + if (cacheMethod & MPNativeCacheMethodDiskAndMemory) { + dataExists = [self.memoryCache objectForKey:key] != nil; + } + + if (!dataExists) { + dataExists = [self.diskCache cachedDataExistsForKey:key]; + } + + return dataExists; +} + +- (id)retrieveDataForKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod +{ + id data = nil; + + if (cacheMethod & MPNativeCacheMethodDiskAndMemory) { + data = [self.memoryCache objectForKey:key]; + } + + if (data) { + MPLogDebug(@"RETRIEVE FROM MEMORY: %@", key); + } + + + if (data == nil) { + data = [self.diskCache retrieveDataForKey:key]; + + if (data && cacheMethod & MPNativeCacheMethodDiskAndMemory) { + MPLogDebug(@"RETRIEVE FROM DISK: %@", key); + + [self.memoryCache setObject:data forKey:key]; + MPLogDebug(@"STORED IN MEMORY: %@", key); + } + } + + if (data == nil) { + MPLogDebug(@"RETRIEVE FAILED: %@", key); + } + + return data; +} + +- (void)storeData:(id)data forKey:(NSString *)key withCacheMethod:(MPNativeCacheMethod)cacheMethod +{ + if (data == nil) { + return; + } + + if (cacheMethod & MPNativeCacheMethodDiskAndMemory) { + [self.memoryCache setObject:data forKey:key]; + MPLogDebug(@"STORED IN MEMORY: %@", key); + } + + [self.diskCache storeData:data forKey:key]; + MPLogDebug(@"STORED ON DISK: %@", key); +} + +- (void)removeAllDataFromMemory +{ + [self.memoryCache removeAllObjects]; +} + +- (void)removeAllDataFromDisk +{ + [self.diskCache removeAllCachedFiles]; +} + +#pragma mark - Notifications + +- (void)didReceiveMemoryWarning:(NSNotification *)notification +{ + [self.memoryCache removeAllObjects]; +} + +#pragma mark - NSCacheDelegate + +- (void)cache:(NSCache *)cache willEvictObject:(id)obj +{ + MPLogDebug(@"Evicting Object"); +} + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.h new file mode 100644 index 000000000..fdbf00e2b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.h @@ -0,0 +1,51 @@ +// +// MPNativePositionResponseDeserializer.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import + +@class MPClientAdPositioning; + +typedef enum : NSUInteger { + MPNativePositionResponseDataIsEmpty, + MPNativePositionResponseIsNotValidJSON, + MPNativePositionResponseJSONHasInvalidPositionData, +} MPNativePositionResponseDeserializationErrorCode; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The `MPNativePositionResponseDeserializer` class is used to convert HTTP response data + * containing positioning information into ad positioning objects that may be used by various + * native ad placers. + */ +@interface MPNativePositionResponseDeserializer : NSObject + +/** + * Creates and returns an object that can deserialize HTTP response data into ad positioning + * objects. + * + * @return The newly created deserializer. + */ ++ (instancetype)deserializer; + +/** + * Returns an ad positioning object given a data object. + * + * If an error occurs during the data conversion, this method will return an empty positioning + * object containing no desired ad positions. + * + * @param data A data object containing positioning information. + * @param error A pointer to an error object. If an error occurs, this pointer will be set to an + * actual error object containing the error information. + * + * @return An `MPClientAdPositioning` object. This is guaranteed to be non-nil; if an error occurs + * during deserialization, the return value will still be a positioning object with no ad positions. + */ +- (MPClientAdPositioning *)clientPositioningForData:(NSData *)data error:(NSError **)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.m new file mode 100644 index 000000000..3e931c993 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionResponseDeserializer.m @@ -0,0 +1,250 @@ +// +// MPNativePositionResponseDeserializer.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativePositionResponseDeserializer.h" +#import "MPClientAdPositioning.h" +#import "NSJSONSerialization+MPAdditions.h" + +static NSString * const MPNativePositionResponseDeserializationErrorDomain = @"com.mopub.iossdk.position.deserialization"; +static NSString * const MPNativePositionResponseFixedPositionsKey = @"fixed"; +static NSString * const MPNativePositionResponseSectionKey = @"section"; +static NSString * const MPNativePositionResponsePositionKey = @"position"; +static NSString * const MPNativePositionResponseRepeatingKey = @"repeating"; +static NSString * const MPNativePositionResponseIntervalKey = @"interval"; +static NSInteger const MPMinRepeatingInterval = 2; +static NSInteger const MPMaxRepeatingInterval = 1 << 16; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPNativePositionResponseDeserializer + ++ (instancetype)deserializer +{ + return [[[self class] alloc] init]; +} + +- (MPClientAdPositioning *)clientPositioningForData:(NSData *)data error:(NSError **)error +{ + MPClientAdPositioning *positioning = [MPClientAdPositioning positioning]; + + if (!data || [data length] == 0) { + [self safeAssignError:error code:MPNativePositionResponseDataIsEmpty description:@"Positioning cannot be created from nil or empty data."]; + return [MPClientAdPositioning positioning]; + } + + NSError *deserializationError = nil; + NSDictionary *positionDictionary = [NSJSONSerialization mp_JSONObjectWithData:data options:0 clearNullObjects:YES error:&deserializationError]; + + if (deserializationError) { + [self safeAssignError:error code:MPNativePositionResponseIsNotValidJSON description:@"Failed to deserialize JSON." underlyingError:deserializationError]; + return [MPClientAdPositioning positioning]; + } + + NSError *fixedPositionsError = nil; + NSArray *fixedPositions = [self parseFixedPositionsObject:[positionDictionary objectForKey:MPNativePositionResponseFixedPositionsKey] error:&fixedPositionsError]; + + if (fixedPositionsError) { + if (error) { + *error = fixedPositionsError; + } + return [MPClientAdPositioning positioning]; + } + + NSError *repeatingIntervalError = nil; + NSInteger repeatingInterval = [self parseRepeatingIntervalObject:[positionDictionary objectForKey:MPNativePositionResponseRepeatingKey] error:&repeatingIntervalError]; + + if (repeatingIntervalError) { + if (error) { + *error = repeatingIntervalError; + } + return [MPClientAdPositioning positioning]; + } + + if ([fixedPositions count] == 0 && repeatingInterval <= 0) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:@"Positioning object must have either fixed positions or a repeating interval."]; + return [MPClientAdPositioning positioning]; + } + + [fixedPositions enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { + [positioning addFixedIndexPath:indexPath]; + }]; + [positioning enableRepeatingPositionsWithInterval:repeatingInterval]; + return positioning; +} + +#pragma mark - Parsing and validation + +- (NSArray *)parseFixedPositionsObject:(id)positionsObject error:(NSError **)error +{ + NSMutableArray *parsedPositions = [NSMutableArray array]; + + if (positionsObject && ![positionsObject isKindOfClass:[NSArray class]]) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"Expected object for key \"%@\" to be an array. Actual: %@", MPNativePositionResponseFixedPositionsKey, positionsObject]]; + return nil; + } + + __block NSError *fixedPositionError = nil; + [positionsObject enumerateObjectsUsingBlock:^(id positionObj, NSUInteger idx, BOOL *stop) { + if (![self validatePositionObject:positionObj error:&fixedPositionError]) { + *stop = YES; + return; + } + + NSInteger section = [self integerFromDictionary:positionObj forKey:MPNativePositionResponseSectionKey defaultValue:0]; + NSInteger position = [self integerFromDictionary:positionObj forKey:MPNativePositionResponsePositionKey defaultValue:0]; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:position inSection:section]; + [parsedPositions addObject:indexPath]; + }]; + + if (fixedPositionError) { + if (error) { + *error = fixedPositionError; + } + return nil; + } + + return parsedPositions; +} + +- (NSInteger)parseRepeatingIntervalObject:(id)repeatingIntervalObject error:(NSError **)error +{ + if (!repeatingIntervalObject) { + return 0; + } + + NSError *repeatingIntervalError = nil; + if (![self validateRepeatingIntervalObject:repeatingIntervalObject error:&repeatingIntervalError]) { + if (error) { + *error = repeatingIntervalError; + } + return 0; + } + + return [self integerFromDictionary:repeatingIntervalObject forKey:MPNativePositionResponseIntervalKey defaultValue:0]; +} + +- (BOOL)validatePositionObject:(id)positionObject error:(NSError **)error +{ + if (![positionObject isKindOfClass:[NSDictionary class]]) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"Position object is not a dictionary: %@.", positionObject]]; + return NO; + } + + // Section number is not required. If it's present, we have to check that it's non-negative; + // if it isn't there, we assign a section number of 0. + NSInteger section = [positionObject objectForKey:MPNativePositionResponseSectionKey] ? [self integerFromDictionary:positionObject forKey:MPNativePositionResponseSectionKey defaultValue:-1] : 0; + if (section < 0) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"Position object has an invalid \"%@\" value or is not a positive number: %ld.", MPNativePositionResponseSectionKey, (long)section]]; + return NO; + } + + // Unlike section, position is required. It also must be a non-negative number. + NSInteger position = [self integerFromDictionary:positionObject forKey:MPNativePositionResponsePositionKey defaultValue:-1]; + if (position < 0) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"Position object has an invalid \"%@\" value or is not a positive number: %ld.", MPNativePositionResponsePositionKey, (long)position]]; + return NO; + } + + return YES; +} + +- (BOOL)validateRepeatingIntervalObject:(id)repeatingIntervalObject error:(NSError **)error +{ + if (![repeatingIntervalObject isKindOfClass:[NSDictionary class]]) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"Repeating interval object is not a dictionary: %@.", repeatingIntervalObject]]; + return NO; + } + + // The object must contain a value between MPMinRepeatingInterval and MPMaxRepeatingInterval. + NSInteger interval = [self integerFromDictionary:repeatingIntervalObject forKey:MPNativePositionResponseIntervalKey defaultValue:0]; + if (interval < MPMinRepeatingInterval || interval > MPMaxRepeatingInterval) { + [self safeAssignError:error code:MPNativePositionResponseJSONHasInvalidPositionData description:[NSString stringWithFormat:@"\"%@\" value in repeating interval object needs to be between %ld and %ld: %ld.", MPNativePositionResponseIntervalKey, (long)MPMinRepeatingInterval, (long)MPMaxRepeatingInterval, (long)interval]]; + return NO; + } + + return YES; +} + +#pragma mark - Dictionary helpers + +/** + * Returns an `NSInteger` value associated with a certain key in a dictionary, or a specified + * default value if the key is not associated with a valid integer representation. + * + * Valid integer representations include `NSNumber` objects and `NSString` objects that + * consist only of integer or sign characters. + * + * @param dictionary A dictionary containing keys and values. + * @param key The key for which to return an integer value. + * @param defaultValue A value that should be returned if `key` is not associated with an object + * that contains an integer representation. + * + * @return The integer value associated with `key`, or `defaultValue` if the object is not an + * `NSNumber` or an `NSString` representing an integer. + */ +- (NSInteger)integerFromDictionary:(NSDictionary *)dictionary forKey:(NSString *)key defaultValue:(NSInteger)defaultValue +{ + static NSCharacterSet *nonIntegerCharacterSet; + + id object = [dictionary objectForKey:key]; + + if ([object isKindOfClass:[NSNumber class]]) { + return [object integerValue]; + } else if ([object isKindOfClass:[NSString class]]) { + if (!nonIntegerCharacterSet) { + nonIntegerCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789-"] invertedSet]; + } + + // If the string consists of all digits, we'll call -integerValue. Otherwise, return the + // default value. + if ([object rangeOfCharacterFromSet:nonIntegerCharacterSet].location == NSNotFound) { + return [object integerValue]; + } else { + return defaultValue; + } + } else { + return defaultValue; + } +} + +#pragma mark - Error helpers + +- (void)safeAssignError:(NSError **)error code:(MPNativePositionResponseDeserializationErrorCode)code userInfo:(NSDictionary *)userInfo +{ + if (error) { + *error = [self deserializationErrorWithCode:code userInfo:userInfo]; + } +} + +- (void)safeAssignError:(NSError **)error code:(MPNativePositionResponseDeserializationErrorCode)code description:(NSString *)description +{ + [self safeAssignError:error code:code description:description underlyingError:nil]; +} + +- (void)safeAssignError:(NSError **)error code:(MPNativePositionResponseDeserializationErrorCode)code description:(NSString *)description underlyingError:(NSError *)underlyingError +{ + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + + if (description) { + [userInfo setObject:description forKey:NSLocalizedDescriptionKey]; + } + + if (underlyingError) { + [userInfo setObject:underlyingError forKey:NSUnderlyingErrorKey]; + } + + [self safeAssignError:error code:code userInfo:userInfo]; +} + +- (NSError *)deserializationErrorWithCode:(MPNativePositionResponseDeserializationErrorCode)code userInfo:(NSDictionary *)userInfo +{ + return [NSError errorWithDomain:MPNativePositionResponseDeserializationErrorDomain + code:code + userInfo:userInfo]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.h new file mode 100644 index 000000000..f03593bcb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.h @@ -0,0 +1,26 @@ +// +// MPNativePositionSource.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class MPAdPositioning; + +typedef enum : NSUInteger { + MPNativePositionSourceInvalidAdUnitIdentifier, + MPNativePositionSourceEmptyResponse, + MPNativePositionSourceDeserializationFailed, + MPNativePositionSourceConnectionFailed, +} MPNativePositionSourceErrorCode; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNativePositionSource : NSObject + +- (void)loadPositionsWithAdUnitIdentifier:(NSString *)identifier completionHandler:(void (^)(MPAdPositioning *positioning, NSError *error))completionHandler; +- (void)cancel; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.m new file mode 100644 index 000000000..dfb662e5a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativePositionSource.m @@ -0,0 +1,169 @@ +// +// MPNativePositionSource.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativePositionSource.h" +#import "MPConstants.h" +#import "MPIdentityProvider.h" +#import "MPAdPositioning.h" +#import "MPClientAdPositioning.h" +#import "MPLogging.h" +#import "MPNativePositionResponseDeserializer.h" +#import "MPAPIEndpoints.h" + +static NSString * const kPositioningSourceErrorDomain = @"com.mopub.iossdk.positioningsource"; +static const NSTimeInterval kMaximumRetryInterval = 60.0; +static const NSTimeInterval kMinimumRetryInterval = 1.0; +static const CGFloat kRetryIntervalBackoffMultiplier = 2.0; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNativePositionSource () + +@property (nonatomic, assign) BOOL loading; +@property (nonatomic, copy) NSString *adUnitIdentifier; +@property (nonatomic, strong) NSURLConnection *connection; +@property (nonatomic, strong) NSMutableData *data; +@property (nonatomic, copy) void (^completionHandler)(MPAdPositioning *positioning, NSError *error); +@property (nonatomic, assign) NSTimeInterval maximumRetryInterval; +@property (nonatomic, assign) NSTimeInterval minimumRetryInterval; +@property (nonatomic, assign) NSTimeInterval retryInterval; +@property (nonatomic, assign) NSUInteger retryCount; + +- (NSURL *)serverURLWithAdUnitIdentifier:(NSString *)identifier; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPNativePositionSource + +- (id)init +{ + if (self) { + self.maximumRetryInterval = kMaximumRetryInterval; + self.minimumRetryInterval = kMinimumRetryInterval; + self.retryInterval = self.minimumRetryInterval; + } + return self; +} + +- (void)dealloc +{ + [_connection cancel]; +} + +#pragma mark - Public + +- (void)loadPositionsWithAdUnitIdentifier:(NSString *)identifier completionHandler:(void (^)(MPAdPositioning *positioning, NSError *error))completionHandler +{ + NSAssert(completionHandler != nil, @"A completion handler is required to load positions."); + + if (![identifier length]) { + NSError *invalidIDError = [NSError errorWithDomain:kPositioningSourceErrorDomain code:MPNativePositionSourceInvalidAdUnitIdentifier userInfo:nil]; + completionHandler(nil, invalidIDError); + return; + } + + self.adUnitIdentifier = identifier; + self.completionHandler = completionHandler; + self.retryCount = 0; + self.retryInterval = self.minimumRetryInterval; + + MPLogInfo(@"Requesting ad positions for native ad unit (%@).", identifier); + + NSURLRequest *request = [NSURLRequest requestWithURL:[self serverURLWithAdUnitIdentifier:identifier]]; + [self.connection cancel]; + [self.data setLength:0]; + self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; +} + +- (void)cancel +{ + // Cancel any connection currently in flight. + [self.connection cancel]; + + // Cancel any queued retry requests. + [NSObject cancelPreviousPerformRequestsWithTarget:self]; +} + +#pragma mark - Internal + +- (NSURL *)serverURLWithAdUnitIdentifier:(NSString *)identifier +{ + NSString *URLString = [NSString stringWithFormat:@"%@?id=%@&v=%@&nsv=%@&udid=%@", + [MPAPIEndpoints baseURLStringWithPath:MOPUB_API_PATH_NATIVE_POSITIONING testing:NO], + identifier, + MP_SERVER_VERSION, + MP_SDK_VERSION, + [MPIdentityProvider identifier]]; + return [NSURL URLWithString:URLString]; +} + +- (void)retryLoadingPositions +{ + self.retryCount++; + + MPLogInfo(@"Retrying positions (retry attempt #%lu).", (unsigned long)self.retryCount); + + NSURLRequest *request = [NSURLRequest requestWithURL:[self serverURLWithAdUnitIdentifier:self.adUnitIdentifier]]; + [self.connection cancel]; + [self.data setLength:0]; + self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; +} + +#pragma mark - + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + if (self.retryInterval >= self.maximumRetryInterval) { + self.completionHandler(nil, error); + self.completionHandler = nil; + } else { + [self performSelector:@selector(retryLoadingPositions) withObject:nil afterDelay:self.retryInterval]; + self.retryInterval = MIN(self.retryInterval * kRetryIntervalBackoffMultiplier, self.maximumRetryInterval); + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + if (!self.data) { + self.data = [NSMutableData data]; + } + + [self.data appendData:data]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + NSError *deserializationError = nil; + MPClientAdPositioning *positioning = [[MPNativePositionResponseDeserializer deserializer] clientPositioningForData:self.data error:&deserializationError]; + + if (deserializationError) { + MPLogDebug(@"Position deserialization failed with error: %@", deserializationError); + + NSError *underlyingError = [[deserializationError userInfo] objectForKey:NSUnderlyingErrorKey]; + if ([underlyingError code] == MPNativePositionResponseDataIsEmpty) { + // Empty response data means the developer hasn't assigned any ad positions for the ad + // unit. No point in retrying the request. + self.completionHandler(nil, [NSError errorWithDomain:kPositioningSourceErrorDomain code:MPNativePositionSourceEmptyResponse userInfo:nil]); + self.completionHandler = nil; + } else if (self.retryInterval >= self.maximumRetryInterval) { + self.completionHandler(nil, deserializationError); + self.completionHandler = nil; + } else { + [self performSelector:@selector(retryLoadingPositions) withObject:nil afterDelay:self.retryInterval]; + self.retryInterval = MIN(self.retryInterval * kRetryIntervalBackoffMultiplier, self.maximumRetryInterval); + } + + return; + } + + self.completionHandler(positioning, nil); + self.completionHandler = nil; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.h new file mode 100644 index 000000000..46b2c2882 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.h @@ -0,0 +1,24 @@ +// +// MPNativeView.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPNativeViewDelegate; + +@interface MPNativeView : UIView + +@property (nonatomic, weak) id delegate; + +@end + +@protocol MPNativeViewDelegate + +@required + +- (void)nativeViewWillMoveToSuperview:(UIView *)superview; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.m new file mode 100644 index 000000000..1ea7aa33b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPNativeView.m @@ -0,0 +1,17 @@ +// +// MPNativeView.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeView.h" + +@implementation MPNativeView + +- (void)willMoveToSuperview:(UIView *)superview +{ + [self.delegate nativeViewWillMoveToSuperview:superview]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.h new file mode 100644 index 000000000..f89d93806 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.h @@ -0,0 +1,48 @@ +// +// MPStaticNativeAdImpressionTimer.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPStaticNativeAdImpressionTimerDelegate; + +@interface MPStaticNativeAdImpressionTimer : NSObject + +@property (nonatomic, weak) id delegate; + +/* + * Initializes and returns an object that will tell its delegate when the a certain percentage of the view + * has been visible for a given amount of time. + * + * visibilityPercentage is a float between 0.0 and 1.0. For example, 0.7 represents 70%. + */ + +- (instancetype)initWithRequiredSecondsForImpression:(NSTimeInterval)requiredSecondsForImpression requiredViewVisibilityPercentage:(CGFloat)visibilityPercentage; + +/* + * Begins monitoring the view to meet the impression tracking criteria set up in -initWithRequiredSecondsForImpression:requiredViewVisibilityPercentage:. + * + * The current visibility duration is not reset when calling this method. If the first view + * was visible for 1 second, the internal state will maintain that the view its tracking has + * been visible for 1 second even if this method is called again with a different view. + */ + +- (void)startTrackingView:(UIView *)view; + +@end + +@protocol MPStaticNativeAdImpressionTimerDelegate + +@required + +/* + * Called when the required visibility time has been satisfied. This delegate method + * will only be called once for the lifetime of this object. + */ + +- (void)trackImpression; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.m new file mode 100644 index 000000000..32d5fa5eb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPStaticNativeAdImpressionTimer.m @@ -0,0 +1,80 @@ +// +// MPStaticNativeAdImpressionTimer.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPStaticNativeAdImpressionTimer.h" + +#import "MPTimer.h" +#import "MPGlobal.h" +#import "MPNativeAdConstants.h" + +static const CGFloat kImpressionTimerInterval = 0.25; +static const NSTimeInterval kFirstVisibilityTimestampNone = -1; + +@interface MPStaticNativeAdImpressionTimer () + +@property (nonatomic) UIView *adView; +@property (nonatomic) MPTimer *viewVisibilityTimer; +@property (nonatomic, assign) NSTimeInterval firstVisibilityTimestamp; +@property (nonatomic, assign) CGFloat requiredViewVisibilityPercentage; +@property (nonatomic, readonly) NSTimeInterval requiredSecondsForImpression; + +@end + +@implementation MPStaticNativeAdImpressionTimer + +- (instancetype)initWithRequiredSecondsForImpression:(NSTimeInterval)requiredSecondsForImpression requiredViewVisibilityPercentage:(CGFloat)visibilityPercentage +{ + if (self = [super init]) { + _viewVisibilityTimer = [MPTimer timerWithTimeInterval:kImpressionTimerInterval target:self selector:@selector(tick:) repeats:YES]; + _viewVisibilityTimer.runLoopMode = NSRunLoopCommonModes; + _requiredSecondsForImpression = requiredSecondsForImpression; + _requiredViewVisibilityPercentage = visibilityPercentage; + _firstVisibilityTimestamp = kFirstVisibilityTimestampNone; + } + + return self; +} + +- (void)dealloc +{ + [_viewVisibilityTimer invalidate]; + _delegate = nil; + _viewVisibilityTimer = nil; +} + +- (void)startTrackingView:(UIView *)view +{ + self.adView = view; + + if (!self.viewVisibilityTimer.isScheduled) { + [self.viewVisibilityTimer scheduleNow]; + } +} + +- (void)tick:(NSTimer *)timer +{ + BOOL visible = MPViewIsVisible(self.adView) && MPViewIntersectsParentWindowWithPercent(self.adView, self.requiredViewVisibilityPercentage) && ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive); + + if (visible) { + NSTimeInterval now = [[NSDate date] timeIntervalSinceReferenceDate]; + + if (self.firstVisibilityTimestamp == kFirstVisibilityTimestampNone) { + self.firstVisibilityTimestamp = now; + } else if (now - self.firstVisibilityTimestamp >= self.requiredSecondsForImpression) { + // Invalidate the timer and tell the delegate it should track an impression. + self.firstVisibilityTimestamp = kFirstVisibilityTimestampNone; + [self.viewVisibilityTimer invalidate]; + self.viewVisibilityTimer = nil; + + [self.delegate trackImpression]; + } + } else { + self.firstVisibilityTimestamp = kFirstVisibilityTimestampNone; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.h new file mode 100644 index 000000000..bebf859e4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.h @@ -0,0 +1,12 @@ +// +// MPTableViewAdPlacerCell.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MPTableViewAdPlacerCell : UITableViewCell + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.m new file mode 100644 index 000000000..4f6489e0d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewAdPlacerCell.m @@ -0,0 +1,12 @@ +// +// MPTableViewAdPlacerCell.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPTableViewAdPlacerCell.h" + +@implementation MPTableViewAdPlacerCell + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.h new file mode 100644 index 000000000..b7baa8576 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.h @@ -0,0 +1,23 @@ +// +// MPTableViewCellImpressionTracker.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import + +@protocol MPTableViewCellImpressionTrackerDelegate; + +@interface MPTableViewCellImpressionTracker : NSObject + +- (id)initWithTableView:(UITableView *)tableView delegate:(id)delegate; +- (void)startTracking; +- (void)stopTracking; + +@end + +@protocol MPTableViewCellImpressionTrackerDelegate + +- (void)tracker:(MPTableViewCellImpressionTracker *)tracker didDetectVisibleRowsAtIndexPaths:(NSArray *)indexPaths; + +@end \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.m new file mode 100644 index 000000000..37bc44b9d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/Internal/MPTableViewCellImpressionTracker.m @@ -0,0 +1,82 @@ +// +// MPTableViewCellImpressionTracker.m +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPTableViewCellImpressionTracker.h" + +@interface MPTableViewCellImpressionTracker () + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) NSTimer *timer; + +@end + +#define MPTableViewCellImpressionTrackerTimeInterval 0.25 + +@implementation MPTableViewCellImpressionTracker + +- (id)initWithTableView:(UITableView *)tableView delegate:(id)delegate +{ + self = [super init]; + if (self) { + _tableView = tableView; + _delegate = delegate; + } + return self; +} + +- (void)dealloc +{ + [_timer invalidate]; +} + +- (void)startTracking +{ + [self.timer invalidate]; + self.timer = [NSTimer timerWithTimeInterval:MPTableViewCellImpressionTrackerTimeInterval target:self selector:@selector(tick:) userInfo:nil repeats:YES]; + + [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; +} + +- (void)stopTracking +{ + [self.timer invalidate]; + self.timer = nil; +} + +#pragma mark - Internal + +- (void)tick:(NSTimer *)timer +{ + NSMutableArray *indexPathsForVisibleRows = [[self.tableView indexPathsForVisibleRows] mutableCopy]; + NSUInteger rowCount = [indexPathsForVisibleRows count]; + + // For our purposes, "visible" means that more than half of the cell is on-screen. + // Filter -indexPathsForVisibleRows to fit this definition. + if (rowCount > 1) { + NSIndexPath *firstVisibleRow = [indexPathsForVisibleRows objectAtIndex:0]; + if (![self isMajorityOfCellAtIndexPathVisible:firstVisibleRow]) { + [indexPathsForVisibleRows removeObjectAtIndex:0]; + } + + NSIndexPath *lastVisibleRow = [indexPathsForVisibleRows lastObject]; + if (![self isMajorityOfCellAtIndexPathVisible:lastVisibleRow]) { + [indexPathsForVisibleRows removeLastObject]; + } + } + + if ([indexPathsForVisibleRows count]) { + [self.delegate tracker:self didDetectVisibleRowsAtIndexPaths:[NSArray arrayWithArray:indexPathsForVisibleRows]]; + } +} + +- (BOOL)isMajorityOfCellAtIndexPathVisible:(NSIndexPath *)indexPath +{ + CGRect cellRect = [self.tableView rectForRowAtIndexPath:indexPath]; + CGPoint cellRectMidY = CGPointMake(0, CGRectGetMidY(cellRect)); + return CGRectContainsPoint(self.tableView.bounds, cellRectMidY); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.h new file mode 100644 index 000000000..805f97ee4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.h @@ -0,0 +1,15 @@ +// +// MPAdPositioning.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@interface MPAdPositioning : NSObject + +@property (nonatomic, assign) NSUInteger repeatingInterval; +@property (nonatomic, strong, readonly) NSMutableOrderedSet *fixedPositions; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.m new file mode 100644 index 000000000..7d7502764 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPAdPositioning.m @@ -0,0 +1,39 @@ +// +// MPAdPositioning.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPAdPositioning.h" + +@interface MPAdPositioning () + +@property (nonatomic, strong) NSMutableOrderedSet *fixedPositions; + +@end + +@implementation MPAdPositioning + +- (id)init +{ + self = [super init]; + if (self) { + _fixedPositions = [[NSMutableOrderedSet alloc] init]; + } + + return self; +} + + +#pragma mark - + +- (id)copyWithZone:(NSZone *)zone +{ + MPAdPositioning *newPositioning = [[[self class] allocWithZone:zone] init]; + newPositioning.fixedPositions = [self.fixedPositions copyWithZone:zone]; + newPositioning.repeatingInterval = self.repeatingInterval; + return newPositioning; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.h new file mode 100644 index 000000000..7bfa7a3c0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.h @@ -0,0 +1,64 @@ +// +// MPClientAdPositioning.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import "MPAdPositioning.h" + +/** + * The `MPClientAdPositioning` class is a model that allows you to control the positions where + * native advertisements should appear within a stream. A positioning object works in conjunction + * with an ad placer, giving the ad placer the information it needs to configure the positions and + * frequency of ads. You can specify that ads should appear at fixed index paths and/or at equally + * spaced intervals throughout your content. + * + * Unlike with `MPServerAdPositioning`, which tells an ad placer to obtain its positioning + * information from the MoPub ad server, client ad positioning does not allow you to control your ad + * positions via the MoPub website. + */ + +@interface MPClientAdPositioning : MPAdPositioning + +/** @name Creating a Client Positioning Object */ + +/** + * Creates and returns an empty positioning object. In order for ads to display in a stream, the + * positioning object must either have at least one fixed position or have repeating positions + * enabled. + * + * @return The newly created positioning object. + */ ++ (instancetype)positioning; + +/** + * Tells the positioning object that an ad should be placed at the specified position. + * + * Positions are passed in as absolute index paths within a stream. For example, if you place an + * ad in a table view at a fixed index path with row 1, an ad will appear in row 1, which may shift + * other content items to higher row indexes. + * + * Note: this method uses `NSIndexPath` objects to accommodate streams with multiple sections. If + * your stream does not contain multiple sections, you should pass in index paths with a section + * value of 0. + * + * @param indexPath An index path representing a position for an ad. + */ +- (void)addFixedIndexPath:(NSIndexPath *)indexPath; + +/** + * Tells the positioning object that ads should be displayed evenly throughout a stream using the + * specified interval. + * + * Repeating ads will only appear within a single section. If the receiver has fixed positions, + * the sequence of repeating ads will start to appear following the last registered fixed position. + * If the receiver does not have any fixed positions, ads will appear regularly starting at + * `interval`, within the first section. + * + * @param interval The frequency at which to display ads. This must be a value greater than 1. + */ +- (void)enableRepeatingPositionsWithInterval:(NSUInteger)interval; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.m new file mode 100644 index 000000000..00310356d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPClientAdPositioning.m @@ -0,0 +1,33 @@ +// +// MPClientAdPositioning.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPClientAdPositioning.h" +#import "MPLogging.h" + +@implementation MPClientAdPositioning + ++ (instancetype)positioning +{ + return [[self alloc] init]; +} + +- (void)addFixedIndexPath:(NSIndexPath *)indexPath +{ + [self.fixedPositions addObject:indexPath]; +} + +- (void)enableRepeatingPositionsWithInterval:(NSUInteger)interval +{ + if (interval > 1) { + self.repeatingInterval = interval; + } else { + MPLogWarn(@"Repeating positions will not be enabled: the provided interval must be greater " + @"than 1."); + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.h new file mode 100644 index 000000000..2e0ad58d9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.h @@ -0,0 +1,387 @@ +// +// MPCollectionViewAdPlacer.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MPClientAdPositioning.h" +#import "MPServerAdPositioning.h" + +@class MPNativeAdRequestTargeting; +@protocol MPCollectionViewAdPlacerDelegate; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The `MPCollectionViewAdPlacer` class allows you to request native ads from the MoPub ad server + * and place them into a `UICollectionView` object. + * + * When an instance of this class is initialized with a collection view, it wraps the collection + * view's data source and delegate in order to insert ads and adjust the positions of your regular + * content cells. + */ + +@interface MPCollectionViewAdPlacer : NSObject + +@property (nonatomic, weak) id delegate; + +/** @name Initializing a Collection View Ad Placer */ + +/** + * Creates and returns an ad placer that will insert ads into a collection view at positions that can + * be configured dynamically on the MoPub website. + * + * When you make an ad request, the ad placer will ask the MoPub ad server for the positions where + * ads should be inserted into the collection view. You can configure these positioning values by + * editing your ad unit's settings on the MoPub website. + * + * Using this method is equivalent to calling + * +placerWithCollectionView:viewController:adPositioning:defaultAdRenderingClass: and passing in an + * `MPServerAdPositioning` object as the `positioning` parameter. + * + * @param collectionView The collection view in which to insert ads. + * @param controller The view controller which should be used to present modal content. + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. + * + * @return An `MPCollectionViewAdPlacer` object. + */ ++ (instancetype)placerWithCollectionView:(UICollectionView *)collectionView viewController:(UIViewController *)controller rendererConfigurations:(NSArray *)rendererConfigurations; + +/** + * Creates and returns an ad placer that will insert ads into a collection view. + * + * When using this method, there are two options for controlling the positions where ads appear + * within the collection view. + * + * First, you may pass an `MPServerAdPositioning` object as the `positioning` parameter, which tells + * the ad placer to obtain positioning information dynamically from the ad server, which you can + * configure on the MoPub website. In many cases, this is the preferred approach, since it allows + * you to modify the positions without rebuilding your application. Note that calling the + * convenience method +placerWithCollectionView:viewController:defaultAdRenderingClass: accomplishes + * this as well. + * + * Alternatively, if you wish to hard-code your positions, you may pass an `MPClientAdPositioning` + * object instead. + * + * @param collectionView The collection view in which to insert ads. + * @param controller The view controller which should be used to present modal content. + * @param positioning The positioning object that specifies where ads should be shown in the stream. + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. + * + * @return An `MPCollectionViewAdPlacer` object. + */ ++ (instancetype)placerWithCollectionView:(UICollectionView *)collectionView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations; + +/** @name Requesting Ads */ + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID. + * + * @param adUnitID A string representing a MoPub ad unit ID. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID; + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID and targeting parameters. + * + * @param adUnitID A string representing a MoPub ad unit ID. + * @param targeting An object containing targeting information, such as geolocation data. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The MoPub SDK adds interfaces to the `UICollectionView` class to help your application with + * responsibilities related to `MPCollectionViewAdPlacer`. These APIs include methods to help notify + * the ad placer of all modifications to the original collection view, as well as to simplify your + * application code such that it does not need to perform index path manipulations to account for + * the presence of ads. + * + * Since the ad placer replaces the original data source and delegate objects of your collection + * view, the SDK also provides new methods for you to set these properties such that the ad placer + * remains aware of the changes. + */ + +@interface UICollectionView (MPCollectionViewAdPlacer) + +- (void)mp_setAdPlacer:(MPCollectionViewAdPlacer *)placer; + +/** @name Obtaining the Collection View Ad Placer */ + +/** + * Returns the ad placer currently being used for this collection view. + * + * @return An ad placer object or `nil` if no ad placer is being used. + */ +- (MPCollectionViewAdPlacer *)mp_adPlacer; + +/** @name Setting and Getting the Delegate and Data Source */ + +/** + * Sets the collection view's data source. + * + * If your application needs to change a collection view's data source after it has instantiated an + * ad placer using that collection view, use this method rather than + * -[UICollectionView setDataSource:]. + * + * @param dataSource The new collection view data source. + */ +- (void)mp_setDataSource:(id)dataSource; + +/** + * Returns the original data source of the collection view. + * + * When you instantiate an ad placer using a collection view, the ad placer replaces the collection + * view's original data source object. If your application needs to access the original data source, + * use this method instead of -[UICollectionView dataSource]. + * + * @return The original collection view data source. + */ +- (id)mp_dataSource; + +/** + * Sets the collection view's delegate. + * + * If your application needs to change a collection view's delegate after it has instantiated an ad + * placer using that collection view, use this method rather than -[UICollectionView setDelegate:]. + * + * @param delegate The new collection view delegate. + */ +- (void)mp_setDelegate:(id)delegate; + +/** + * Returns the original delegate of the collection view. + * + * When you instantiate an ad placer using a collection view, the ad placer replaces the collection + * view's original delegate object. If your application needs to access the original delegate, use + * this method instead of -[UICollectionView delegate]. + * + * @return The original collection view delegate. + */ +- (id)mp_delegate; + +/** @name Notifying the Collection View Ad Placer of Content Changes */ + +/** + * Reloads all of the data for the collection view. + */ +- (void)mp_reloadData; + +/** + * Inserts new items at the specified index paths, and informs the attached ad placer of the + * insertions. + * + * @param indexPaths An array of `NSIndexPath` objects, each of which contains a section index and + * item index at which to insert a new cell. This parameter must not be `nil`. + */ +- (void)mp_insertItemsAtIndexPaths:(NSArray *)indexPaths; + +/** + * Deletes the items at the specified index paths, and informs the attached ad placer of the + * deletions. + * + * @param indexPaths An array of `NSIndexPath` objects, each of which contains a section index and + * item index for the item you want to delete from the collection view. This parameter must not be + * `nil`. + */ +- (void)mp_deleteItemsAtIndexPaths:(NSArray *)indexPaths; + +/** + * Reloads just the items at the specified index paths. + * + * @param indexPaths An array of `NSIndexPath` objects identifying the items you want to update. + */ +- (void)mp_reloadItemsAtIndexPaths:(NSArray *)indexPaths; + +/** + * Moves an item from one location to another in the collection view, taking into account ads + * inserted by the ad placer. + * + * @param indexPath The index path of the item you want to move. This parameter must not be + * `nil`. + * @param newIndexPath The index path of the item’s new location. This parameter must not be `nil`. + */ +- (void)mp_moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath; + +/** + * Inserts new sections at the specified indexes, and informs the attached ad placer of the + * insertions. + * + * @param sections An index set containing the indexes of the sections you want to insert. This + * parameter must not be `nil`. + */ +- (void)mp_insertSections:(NSIndexSet *)sections; + +/** + * Deletes the sections at the specified indexes, and informs the attached ad placer of the + * deletions. + * + * @param sections The indexes of the sections you want to delete. This parameter must not be `nil`. + */ +- (void)mp_deleteSections:(NSIndexSet *)sections; + +/** + * Reloads the data in the specified sections of the collection view, and informs the attached ad + * placer that sections may have changed. + * + * @param sections The indexes of the sections to reload. + */ +- (void)mp_reloadSections:(NSIndexSet *)sections; + +/** + * Moves a section from one location to another in the collection view, and informs the attached ad + * placer. + * + * @param section The index path of the section you want to move. This parameter must not be + * `nil`. + * @param newSection The index path of the section’s new location. This parameter must not be `nil`. + */ +- (void)mp_moveSection:(NSInteger)section toSection:(NSInteger)newSection; + +/** @name Methods Involving Index Paths */ + +/** + * Returns the visible cell object at the specified index path. + * + * @param indexPath The index path that specifies the section and item number of the cell. + * + * @return The cell object at the corresponding index path or `nil` if the cell is not visible or + * *indexPath* is out of range. + */ +- (UICollectionViewCell *)mp_cellForItemAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Returns a reusable cell object located by its identifier. + * + * @param identifier The reuse identifier for the specified cell. This parameter must not be `nil`. + * @param indexPath The index path specifying the location of the cell. The data source receives + * this information when it is asked for the cell and should just pass it along. This method uses + * the index path to perform additional configuration based on the cell’s position in the collection + * view. + * + * @return A valid `UICollectionReusableView` object. + */ +- (id)mp_dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath; + +/** + * Deselects the item at the specified index. + * + * @param indexPath The index path of the item to select. Specifying `nil` results in no change to + * the current selection. + * @param animated Specify YES to animate the change in the selection or NO to make the change + * without animating it. + */ +- (void)mp_deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; + +/** + * Returns the original index path for the given cell or `nil` if the cell is an ad cell. + * + * @param cell The cell object whose index path you want. + * + * @return The index path of the cell or `nil` if the specified cell contains an ad or is not in the + * collection view. + */ +- (NSIndexPath *)mp_indexPathForCell:(UICollectionViewCell *)cell; + +/** + * Returns the index path of the item at the specified point in the collection view. + * + * @param point A point in the collection view’s coordinate system. + * + * @return The index path of the item at the specified point or `nil` if either an ad or no item was + * found at the specified point. + */ +- (NSIndexPath *)mp_indexPathForItemAtPoint:(CGPoint)point; + +/** + * Returns the original index paths (as if no ads were inserted) for the selected items. + * + * @return An array of the original index paths for the selected items. + */ +- (NSArray *)mp_indexPathsForSelectedItems; + +/** + * Returns an array of original index paths each identifying a visible non-ad item in the collection + * view, calculated before any ads were inserted. + * + * @return An array of the original index paths representing visible non-ad items in the collection + * view. Returns `nil` if no items are visible. + */ +- (NSArray *)mp_indexPathsForVisibleItems; + +/** + * Returns the layout information for the item at the specified index path. + * + * @param indexPath The index path of the item. + * + * @return The layout attributes for the item or `nil` if no item exists at the specified path. + */ +- (UICollectionViewLayoutAttributes *)mp_layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Scrolls the collection view contents until the specified item is visible. + * + * @param indexPath The index path of the item to scroll into view. + * @param scrollPosition An option that specifies where the item should be positioned when scrolling + * finishes. + * @param animated Specify YES to animate the scrolling behavior or NO to adjust the scroll + * view’s visible content immediately. + */ +- (void)mp_scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated; + +/** + * Selects the item at the specified index path and optionally scrolls it into view. + * + * @param indexPath The index path of the item to select. Specifying `nil` for this parameter + * clears the current selection. + * @param animated Specify YES to animate the change in the selection or NO to make the change + * without animating it. + * @param scrollPosition An option that specifies where the item should be positioned when scrolling + * finishes. + */ +- (void)mp_selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition; + +/** + * Returns an array of the non-ad cells that are visible in the collection view. + * + * @return An array of `UICollectionViewCell` objects, each representing a visible, non-ad cell in + * the receiving collection view. + */ +- (NSArray *)mp_visibleCells; + +@end + +@protocol MPCollectionViewAdPlacerDelegate + +@optional + +/* + * This method is called when a native ad, placed by the collection view ad placer, will present a modal view controller. + * + * @param placer The collection view ad placer that contains the ad displaying the modal. + */ +-(void)nativeAdWillPresentModalForCollectionViewAdPlacer:(MPCollectionViewAdPlacer *)placer; + +/* + * This method is called when a native ad, placed by the collection view ad placer, did dismiss its modal view controller. + * + * @param placer The collection view ad placer that contains the ad that dismissed the modal. + */ +-(void)nativeAdDidDismissModalForCollectionViewAdPlacer:(MPCollectionViewAdPlacer *)placer; + +/* + * This method is called when a native ad, placed by the collection view ad placer, will cause the app to background due to user interaction with the ad. + * + * @param placer The collection view ad placer that contains the ad causing the app to background. + */ +-(void)nativeAdWillLeaveApplicationFromCollectionViewAdPlacer:(MPCollectionViewAdPlacer *)placer; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.m new file mode 100644 index 000000000..fc33d2454 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPCollectionViewAdPlacer.m @@ -0,0 +1,652 @@ +// +// MPCollectionViewAdPlacer.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPCollectionViewAdPlacer.h" +#import "MPStreamAdPlacer.h" +#import "MPInstanceProvider.h" +#import "MPAdPlacerInvocation.h" +#import "MPTimer.h" +#import "MPNativeAdUtils.h" +#import "MPCollectionViewAdPlacerCell.h" +#import "MPNativeAdRendererConfiguration.h" +#import + +static NSString * const kCollectionViewAdPlacerReuseIdentifier = @"MPCollectionViewAdPlacerReuseIdentifier"; + +@protocol MPNativeAdRenderer; + +@interface MPCollectionViewAdPlacer () + +@property (nonatomic, strong) MPStreamAdPlacer *streamAdPlacer; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, weak) id originalDataSource; +@property (nonatomic, weak) id originalDelegate; +@property (nonatomic, strong) MPTimer *insertionTimer; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPCollectionViewAdPlacer + ++ (instancetype)placerWithCollectionView:(UICollectionView *)collectionView viewController:(UIViewController *)controller rendererConfigurations:(NSArray *)rendererConfigurations +{ + return [[self class] placerWithCollectionView:collectionView viewController:controller adPositioning:[MPServerAdPositioning positioning] rendererConfigurations:rendererConfigurations]; +} + ++ (instancetype)placerWithCollectionView:(UICollectionView *)collectionView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + MPCollectionViewAdPlacer *collectionViewAdPlacer = [[MPCollectionViewAdPlacer alloc] initWithCollectionView:collectionView viewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; + return collectionViewAdPlacer; +} + +- (instancetype)initWithCollectionView:(UICollectionView *)collectionView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + for (id rendererConfiguration in rendererConfigurations) { + NSAssert([rendererConfiguration isKindOfClass:[MPNativeAdRendererConfiguration class]], @"A collection view ad placer must be instantiated with rendererConfigurations that are of type MPNativeAdRendererConfiguration."); + } + + if (self = [super init]) { + _collectionView = collectionView; + _streamAdPlacer = [[MPInstanceProvider sharedProvider] buildStreamAdPlacerWithViewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; + _streamAdPlacer.delegate = self; + + _insertionTimer = [MPTimer timerWithTimeInterval:kUpdateVisibleCellsInterval target:self selector:@selector(updateVisibleCells) repeats:YES]; + _insertionTimer.runLoopMode = NSRunLoopCommonModes; + [_insertionTimer scheduleNow]; + + _originalDataSource = collectionView.dataSource; + _originalDelegate = collectionView.delegate; + collectionView.dataSource = self; + collectionView.delegate = self; + + [_collectionView registerClass:[MPCollectionViewAdPlacerCell class] forCellWithReuseIdentifier:kCollectionViewAdPlacerReuseIdentifier]; + + [collectionView mp_setAdPlacer:self]; + } + + return self; +} + +- (void)dealloc +{ + [_insertionTimer invalidate]; +} + +#pragma mark - Public + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID +{ + [self.streamAdPlacer loadAdsForAdUnitID:adUnitID]; +} + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting +{ + [self.streamAdPlacer loadAdsForAdUnitID:adUnitID targeting:targeting]; +} + +#pragma mark - Ad Insertion + +- (void)updateVisibleCells +{ + NSArray *visiblePaths = self.collectionView.mp_indexPathsForVisibleItems; + + if ([visiblePaths count]) { + [self.streamAdPlacer setVisibleIndexPaths:visiblePaths]; + } +} + +#pragma mark - + +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didLoadAdAtIndexPath:(NSIndexPath *)indexPath +{ + BOOL animationsWereEnabled = [UIView areAnimationsEnabled]; + //We only want to enable animations if the index path is before or within our visible cells + BOOL animationsEnabled = ([(NSIndexPath *)[self.collectionView.indexPathsForVisibleItems lastObject] compare:indexPath] != NSOrderedAscending) && animationsWereEnabled; + + [UIView setAnimationsEnabled:animationsEnabled]; + + [self.collectionView insertItemsAtIndexPaths:@[indexPath]]; + + [UIView setAnimationsEnabled:animationsWereEnabled]; +} + +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didRemoveAdsAtIndexPaths:(NSArray *)indexPaths +{ + BOOL animationsWereEnabled = [UIView areAnimationsEnabled]; + [UIView setAnimationsEnabled:NO]; + + [self.collectionView performBatchUpdates:^{ + [self.collectionView deleteItemsAtIndexPaths:indexPaths]; + } completion:^(BOOL finished) { + [UIView setAnimationsEnabled:animationsWereEnabled]; + }]; +} + +- (void)nativeAdWillPresentModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillPresentModalForCollectionViewAdPlacer:)]) { + [self.delegate nativeAdWillPresentModalForCollectionViewAdPlacer:self]; + } +} + +- (void)nativeAdDidDismissModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdDidDismissModalForCollectionViewAdPlacer:)]) { + [self.delegate nativeAdDidDismissModalForCollectionViewAdPlacer:self]; + } +} + +- (void)nativeAdWillLeaveApplicationFromStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillLeaveApplicationFromCollectionViewAdPlacer:)]) { + [self.delegate nativeAdWillLeaveApplicationFromCollectionViewAdPlacer:self]; + } +} + +#pragma mark - + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView +{ + if ([self.originalDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) { + return [self.originalDataSource numberOfSectionsInCollectionView:collectionView]; + } + else { + return 1; + } +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section +{ + NSUInteger numberOfItems = [self.originalDataSource collectionView:collectionView numberOfItemsInSection:section]; + [self.streamAdPlacer setItemCount:numberOfItems forSection:section]; + return [self.streamAdPlacer adjustedNumberOfItems:numberOfItems inSection:section]; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + MPCollectionViewAdPlacerCell *cell = (MPCollectionViewAdPlacerCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kCollectionViewAdPlacerReuseIdentifier forIndexPath:indexPath]; + cell.clipsToBounds = YES; + + [self.streamAdPlacer renderAdAtIndexPath:indexPath inView:cell.contentView]; + return cell; + } + + NSIndexPath *originalIndexPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [self.originalDataSource collectionView:collectionView cellForItemAtIndexPath:originalIndexPath]; +} + +#pragma mark - + +- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return NO; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(collectionView:canPerformAction:forItemAtIndexPath:withSender:)]) { + NSIndexPath *originalPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [delegate collectionView:collectionView canPerformAction:action forItemAtIndexPath:originalPath withSender:sender]; + } + + return NO; +} + +- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:didDeselectItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with3ArgSelector:@selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) firstArg:collectionView secondArg:cell thirdArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:didHighlightItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + // The view inside the cell already has a gesture recognizer to handle the tap event. + [self.collectionView deselectItemAtIndexPath:indexPath animated:NO]; + return; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(collectionView:didSelectItemAtIndexPath:)]) { + NSIndexPath *originalPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [delegate collectionView:collectionView didSelectItemAtIndexPath:originalPath]; + } +} + +- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:didUnhighlightItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(collectionView:performAction:forItemAtIndexPath:withSender:)]) { + NSIndexPath *originalPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [delegate collectionView:collectionView performAction:action forItemAtIndexPath:originalPath withSender:sender]; + } +} + +- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:shouldDeselectItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:YES]; +} + +- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:shouldHighlightItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:YES]; +} + +- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:shouldSelectItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:collectionView.allowsSelection]; +} + +- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(collectionView:shouldShowMenuForItemAtIndexPath:) firstArg:collectionView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:NO]; +} + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.originalDelegate respondsToSelector:@selector(collectionView:willDisplayCell:forItemAtIndexPath:)]) { + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with3ArgSelector:@selector(collectionView:willDisplayCell:forItemAtIndexPath:) firstArg:collectionView secondArg:cell thirdArg:indexPath streamAdPlacer:self.streamAdPlacer]; + } +} + +#pragma mark - UICollectionViewDelegateFlowLayout + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return [self.streamAdPlacer sizeForAdAtIndexPath:indexPath withMaximumWidth:CGRectGetWidth(self.collectionView.bounds)]; + } + + if ([self.originalDelegate respondsToSelector:@selector(collectionView:layout:sizeForItemAtIndexPath:)]) { + NSIndexPath *originalPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + id flowLayout = (id)[self originalDelegate]; + return [flowLayout collectionView:collectionView layout:collectionViewLayout sizeForItemAtIndexPath:originalPath]; + } + return ((UICollectionViewFlowLayout *)collectionViewLayout).itemSize; +} + +#pragma mark - Method Forwarding + +- (BOOL)isKindOfClass:(Class)aClass { + return [super isKindOfClass:aClass] || + [self.originalDataSource isKindOfClass:aClass] || + [self.originalDelegate isKindOfClass:aClass]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol +{ + return [super conformsToProtocol:aProtocol] || + [self.originalDelegate conformsToProtocol:aProtocol] || + [self.originalDataSource conformsToProtocol:aProtocol]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + return [super respondsToSelector:aSelector] || + [self.originalDataSource respondsToSelector:aSelector] || + [self.originalDelegate respondsToSelector:aSelector]; +} + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + if ([self.originalDataSource respondsToSelector:aSelector]) { + return self.originalDataSource; + } else if ([self.originalDelegate respondsToSelector:aSelector]) { + return self.originalDelegate; + } else { + return [super forwardingTargetForSelector:aSelector]; + } +} + +@end + +@implementation UICollectionView (MPCollectionViewAdPlacer) + +static char kAdPlacerKey; + +- (void)mp_setAdPlacer:(MPCollectionViewAdPlacer *)placer +{ + objc_setAssociatedObject(self, &kAdPlacerKey, placer, OBJC_ASSOCIATION_ASSIGN); +} + +- (MPCollectionViewAdPlacer *)mp_adPlacer +{ + return objc_getAssociatedObject(self, &kAdPlacerKey); +} + +- (void)mp_setDelegate:(id)delegate +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + adPlacer.originalDelegate = delegate; + } else { + self.delegate = delegate; + } +} + +- (id)mp_delegate +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + return adPlacer.originalDelegate; + } else { + return self.delegate; + } +} + +- (void)mp_setDataSource:(id)dataSource +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + adPlacer.originalDataSource = dataSource; + } else { + self.dataSource = dataSource; + } +} + +- (id)mp_dataSource +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + return adPlacer.originalDataSource; + } else { + return self.dataSource; + } +} + +- (id)mp_dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + // Only pass nil through if developer passed it through + if (!indexPath || adjustedIndexPath) { + return [self dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:adjustedIndexPath]; + } else { + return nil; + } +} + +- (NSArray *)mp_indexPathsForSelectedItems +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = [self indexPathsForSelectedItems]; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer originalIndexPathsForAdjustedIndexPaths:adjustedIndexPaths]; + } + + return adjustedIndexPaths; +} + +- (void)mp_selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + // Only pass nil through if developer passed it through + if (!indexPath || adjustedIndexPath) { + [self selectItemAtIndexPath:adjustedIndexPath animated:animated scrollPosition:scrollPosition]; + } +} + +- (void)mp_deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + [self deselectItemAtIndexPath:adjustedIndexPath animated:animated]; +} + +- (void)mp_reloadData +{ + [self reloadData]; +} + +- (UICollectionViewLayoutAttributes *)mp_layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + return [self layoutAttributesForItemAtIndexPath:adjustedIndexPath]; +} + +- (NSIndexPath *)mp_indexPathForItemAtPoint:(CGPoint)point +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = [self indexPathForItemAtPoint:point]; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer originalIndexPathForAdjustedIndexPath:adjustedIndexPath]; + } + + return adjustedIndexPath; +} + +- (NSIndexPath *)mp_indexPathForCell:(UICollectionViewCell *)cell +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = [self indexPathForCell:cell]; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer originalIndexPathForAdjustedIndexPath:adjustedIndexPath]; + } + + return adjustedIndexPath; +} + +- (UICollectionViewCell *)mp_cellForItemAtIndexPath:(NSIndexPath *)indexPath +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:adjustedIndexPath]; + } + + return [self cellForItemAtIndexPath:adjustedIndexPath]; +} + +- (NSArray *)mp_visibleCells +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + NSArray *indexPaths = [self mp_indexPathsForVisibleItems]; + NSMutableArray *visibleCells = [NSMutableArray array]; + for (NSIndexPath *indexPath in indexPaths) { + [visibleCells addObject:[self mp_cellForItemAtIndexPath:indexPath]]; + } + return visibleCells; + } else { + return [self visibleCells]; + } +} + +- (NSArray *)mp_indexPathsForVisibleItems +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = [self indexPathsForVisibleItems]; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer originalIndexPathsForAdjustedIndexPaths:adjustedIndexPaths]; + } + + return adjustedIndexPaths; +} + +- (void)mp_scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:adjustedIndexPath]; + } + + // Only pass nil through if developer passed it through + if (!indexPath || adjustedIndexPath) { + [self scrollToItemAtIndexPath:adjustedIndexPath atScrollPosition:scrollPosition animated:animated]; + } +} + +- (void)mp_insertSections:(NSIndexSet *)sections +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer insertSections:sections]; + } + + [self insertSections:sections]; +} + +- (void)mp_deleteSections:(NSIndexSet *)sections +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer deleteSections:sections]; + } + + [self deleteSections:sections]; +} + +- (void)mp_reloadSections:(NSIndexSet *)sections +{ + [self reloadSections:sections]; +} + +- (void)mp_moveSection:(NSInteger)section toSection:(NSInteger)newSection +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer moveSection:section toSection:newSection]; + } + + [self moveSection:section toSection:newSection]; +} + +- (void)mp_insertItemsAtIndexPaths:(NSArray *)indexPaths +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = indexPaths; + + if (adPlacer) { + [adPlacer.streamAdPlacer insertItemsAtIndexPaths:indexPaths]; + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + } + + // We perform the actual UI insertion AFTER updating the stream ad placer's + // data, because the insertion can trigger queries to the data source, which + // needs to reflect the post-insertion state. + [self insertItemsAtIndexPaths:adjustedIndexPaths]; +} + +- (void)mp_deleteItemsAtIndexPaths:(NSArray *)indexPaths +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + [self performBatchUpdates:^{ + NSArray *adjustedIndexPaths = indexPaths; + + if (adPlacer) { + // We need to obtain the adjusted index paths to delete BEFORE we + // update the stream ad placer's data. + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + + [adPlacer.streamAdPlacer deleteItemsAtIndexPaths:indexPaths]; + } + + // We perform the actual UI deletion AFTER updating the stream ad placer's + // data, because the deletion can trigger queries to the data source, which + // needs to reflect the post-deletion state. + [self deleteItemsAtIndexPaths:adjustedIndexPaths]; + } completion:nil]; +} + +- (void)mp_reloadItemsAtIndexPaths:(NSArray *)indexPaths +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = indexPaths; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + } + + [self reloadItemsAtIndexPaths:adjustedIndexPaths]; +} + +- (void)mp_moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath +{ + MPCollectionViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedFrom = indexPath; + NSIndexPath *adjustedTo = newIndexPath; + + if (adPlacer) { + // We need to obtain the adjusted index paths to move BEFORE we + // update the stream ad placer's data. + adjustedFrom = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + adjustedTo = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:newIndexPath]; + + [adPlacer.streamAdPlacer moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; + } + + // We perform the actual UI operation AFTER updating the stream ad placer's + // data, because the operation can trigger queries to the data source, which + // needs to reflect the post-operation state. + [self moveItemAtIndexPath:adjustedFrom toIndexPath:adjustedTo]; +} +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.h new file mode 100644 index 000000000..9cec36206 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.h @@ -0,0 +1,51 @@ +// +// MPNativeAd.h +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import +#import + +@protocol MPNativeAdAdapter; +@protocol MPNativeAdDelegate; +@protocol MPNativeAdRenderer; +@class MPAdConfiguration; + +/** + * The `MPNativeAd` class is used to render and manage events for a native advertisement. The + * class provides methods for accessing native ad properties returned by the server, as well as + * convenience methods for URL navigation and metrics-gathering. + */ + +@interface MPNativeAd : NSObject + +/** @name Ad Resources */ + +/** + * The delegate of the `MPNativeAd` object. + */ +@property (nonatomic, weak) id delegate; + +/** + * A dictionary representing the native ad properties. + */ +@property (nonatomic, readonly) NSDictionary *properties; + +- (instancetype)initWithAdAdapter:(id)adAdapter; + +/** @name Retrieving Ad View */ + +/** + * Retrieves a rendered view containing the ad. + * + * @param error A pointer to an error object. If an error occurs, this pointer will be set to an + * actual error object containing the error information. + * + * @return If successful, the method will return a view containing the rendered ad. The method will + * return nil if it cannot render the ad data to a view. + */ +- (UIView *)retrieveAdViewWithError:(NSError **)error; + +- (void)trackMetricForURL:(NSURL *)URL; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.m new file mode 100644 index 000000000..ecffa2fcc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAd.m @@ -0,0 +1,235 @@ +// +// MPNativeAd.m +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPNativeAd+Internal.h" +#import "MPAdConfiguration.h" +#import "MPCoreInstanceProvider.h" +#import "MPNativeAdError.h" +#import "MPLogging.h" +#import "MPNativeCache.h" +#import "MPNativeAdRendering.h" +#import "MPImageDownloadQueue.h" +#import "NSJSONSerialization+MPAdditions.h" +#import "MPNativeCustomEvent.h" +#import "MPNativeAdAdapter.h" +#import "MPNativeAdConstants.h" +#import "MPTimer.h" +#import "MPNativeAdRenderer.h" +#import "MPNativeAdDelegate.h" +#import "MPNativeView.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNativeAd () + +@property (nonatomic, readwrite, strong) id renderer; + +@property (nonatomic, strong) NSDate *creationDate; + +@property (nonatomic, strong) NSMutableSet *clickTrackerURLs; +@property (nonatomic, strong) NSMutableSet *impressionTrackerURLs; + +@property (nonatomic, readonly, strong) id adAdapter; +@property (nonatomic, assign) BOOL hasTrackedImpression; +@property (nonatomic, assign) BOOL hasTrackedClick; + +@property (nonatomic, copy) NSString *adIdentifier; +@property (nonatomic) MPNativeView *associatedView; + +@property (nonatomic) BOOL hasAttachedToView; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPNativeAd + +- (instancetype)initWithAdAdapter:(id)adAdapter +{ + static int sequenceNumber = 0; + + self = [super init]; + if (self) { + _adAdapter = adAdapter; + if ([_adAdapter respondsToSelector:@selector(setDelegate:)]) { + [_adAdapter setDelegate:self]; + } + _adIdentifier = [[NSString stringWithFormat:@"%d", sequenceNumber++] copy]; + _impressionTrackerURLs = [[NSMutableSet alloc] init]; + _clickTrackerURLs = [[NSMutableSet alloc] init]; + _creationDate = [NSDate date]; + _associatedView = [[MPNativeView alloc] init]; + _associatedView.clipsToBounds = YES; + _associatedView.delegate = self; + + // Add a tap recognizer on top of the view if the ad network isn't handling clicks on its own. + if (!([_adAdapter respondsToSelector:@selector(enableThirdPartyClickTracking)] && [_adAdapter enableThirdPartyClickTracking])) { + UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(adViewTapped)]; + [_associatedView addGestureRecognizer:recognizer]; + } + } + return self; +} + +#pragma mark - Public + +- (UIView *)retrieveAdViewWithError:(NSError **)error +{ + // We always return the same MPNativeView (self.associatedView) so we need to remove its subviews + // before attaching the new ad view to it. + [[self.associatedView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + UIView *adView = [self.renderer retrieveViewWithAdapter:self.adAdapter error:error]; + + if (adView) { + if (!self.hasAttachedToView) { + [self willAttachToView:self.associatedView]; + self.hasAttachedToView = YES; + } + + adView.frame = self.associatedView.bounds; + [self.associatedView addSubview:adView]; + + return self.associatedView; + } else { + return nil; + } +} + +- (NSDictionary *)properties +{ + return self.adAdapter.properties; +} + +- (void)trackImpression +{ + if (self.hasTrackedImpression) { + MPLogDebug(@"Impression already tracked."); + return; + } + + MPLogDebug(@"Tracking an impression for %@.", self.adIdentifier); + self.hasTrackedImpression = YES; + [self trackMetricsForURLs:self.impressionTrackerURLs]; +} + +- (void)trackClick +{ + if (self.hasTrackedClick) { + MPLogDebug(@"Click already tracked."); + return; + } + + MPLogDebug(@"Tracking a click for %@.", self.adIdentifier); + self.hasTrackedClick = YES; + [self trackMetricsForURLs:self.clickTrackerURLs]; + + if ([self.adAdapter respondsToSelector:@selector(trackClick)] && ![self isThirdPartyHandlingClicks]) { + [self.adAdapter trackClick]; + } + +} + +- (void)trackMetricsForURLs:(NSSet *)URLs +{ + for (NSURL *URL in URLs) { + [self trackMetricForURL:URL]; + } +} + +- (void)trackMetricForURL:(NSURL *)URL +{ + NSMutableURLRequest *request = [[MPCoreInstanceProvider sharedProvider] buildConfiguredURLRequestWithURL:URL]; + request.cachePolicy = NSURLRequestReloadIgnoringCacheData; + [NSURLConnection connectionWithRequest:request delegate:nil]; +} + +#pragma mark - Internal + +- (void)willAttachToView:(UIView *)view +{ + if ([self.adAdapter respondsToSelector:@selector(willAttachToView:)]) { + [self.adAdapter willAttachToView:view]; + } +} + +- (BOOL)isThirdPartyHandlingClicks +{ + return [self.adAdapter respondsToSelector:@selector(enableThirdPartyClickTracking)] && [self.adAdapter enableThirdPartyClickTracking]; +} + +- (void)displayAdContent +{ + [self trackClick]; + + if ([self.adAdapter respondsToSelector:@selector(displayContentForURL:rootViewController:)]) { + [self.adAdapter displayContentForURL:self.adAdapter.defaultActionURL rootViewController:[self.delegate viewControllerForPresentingModalView]]; + } else { + // If this method is called, that means that the backing adapter should implement -displayContentForURL:rootViewController:completion:. + // If it doesn't, we'll log a warning. + MPLogWarn(@"Cannot display native ad content. -displayContentForURL:rootViewController:completion: not implemented by native ad adapter: %@", [self.adAdapter class]); + } +} + +#pragma mark - UITapGestureRecognizer + +- (void)adViewTapped +{ + [self displayAdContent]; + + if ([self.renderer respondsToSelector:@selector(nativeAdTapped)]) { + [self.renderer nativeAdTapped]; + } +} + +#pragma mark - MPNativeViewDelegate + +- (void)nativeViewWillMoveToSuperview:(UIView *)superview +{ + if ([self.renderer respondsToSelector:@selector(adViewWillMoveToSuperview:)]) + { + [self.renderer adViewWillMoveToSuperview:superview]; + } +} + +#pragma mark - MPNativeAdAdapterDelegate + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)nativeAdWillLogImpression:(id)adAdapter +{ + [self trackImpression]; +} + +- (void)nativeAdDidClick:(id)adAdapter +{ + [self trackClick]; +} + +- (void)nativeAdWillPresentModalForAdapter:(id)adapter +{ + if ([self.delegate respondsToSelector:@selector(willPresentModalForNativeAd:)]) { + [self.delegate willPresentModalForNativeAd:self]; + } +} + +- (void)nativeAdDidDismissModalForAdapter:(id)adapter +{ + if ([self.delegate respondsToSelector:@selector(didDismissModalForNativeAd:)]) { + [self.delegate didDismissModalForNativeAd:self]; + } +} + +- (void)nativeAdWillLeaveApplicationFromAdapter:(id)adapter +{ + if ([self.delegate respondsToSelector:@selector(willLeaveApplicationFromNativeAd:)]) { + [self.delegate willLeaveApplicationFromNativeAd:self]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdAdapter.h new file mode 100644 index 000000000..baed12ff6 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdAdapter.h @@ -0,0 +1,184 @@ +// +// MPNativeAdAdapter.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@protocol MPNativeAdAdapter; + +/** + * Classes that conform to the `MPNativeAdAdapter` protocol can have an + * `MPNativeAdAdapterDelegate` delegate object. You use this delegate to communicate + * native ad events (such as impressions and clicks occurring) back to the MoPub SDK. + */ +@protocol MPNativeAdAdapterDelegate + +@required + +/** + * Asks the delegate for a view controller to use for presenting modal content, such as the in-app + * browser that can appear when an ad is tapped. + * + * @return A view controller that should be used for presenting modal content. + */ +- (UIViewController *)viewControllerForPresentingModalView; + +/** + * You should call this method when your adapter's modal is about to be presented. + * + * @param adapter The adapter that will present the modal. + */ +- (void)nativeAdWillPresentModalForAdapter:(id)adapter; + +/** + * You should call this method when your adapter's modal has been dismissed. + * + * @param adapter The adapter that dismissed the modal. + */ +- (void)nativeAdDidDismissModalForAdapter:(id)adapter; + +/** + * You should call this method when your the user will leave the application due to interaction with the ad. + * + * @param adapter The adapter that represents the ad that caused the user to leave the application. + */ +- (void)nativeAdWillLeaveApplicationFromAdapter:(id)adapter; + +@optional + +/** + * This method is called before the backing native ad logs an impression. + * + * @param adAdapter You should pass `self` to allow the MoPub SDK to associate this event with the + * correct instance of your ad adapter. + */ +- (void)nativeAdWillLogImpression:(id)adAdapter; + +/** + * This method is called when the user interacts with the ad. + * + * @param adAdapter You should pass `self` to allow the MoPub SDK to associate this event with the + * correct instance of your ad adapter. + */ +- (void)nativeAdDidClick:(id)adAdapter; + +@end + +/** + * The `MPNativeAdAdapter` protocol allows the MoPub SDK to interact with native ad objects obtained + * from third-party ad networks. An object that adopts this protocol acts as a wrapper for a native + * ad object, translating its proprietary interface into a common one that the MoPub SDK can + * understand. + * + * An object that adopts this protocol must implement the `properties` property to specify a + * dictionary of assets, such as title and text, that should be rendered as part of a native ad. + * When possible, you should place values in the returned dictionary such that they correspond to + * the pre-defined keys in the MPNativeAdConstants header file. + * + * An adopting object must additionally implement -displayContentForURL:rootViewController:completion: + * to supply the behavior that should occur when the user interacts with the ad. + * + * Optional methods of the protocol allow the adopting object to define when and how impressions + * and interactions should be tracked. + */ +@protocol MPNativeAdAdapter + +@required + +/** @name Ad Resources */ + +/** + * Provides a dictionary of all publicly accessible assets (such as title and text) for the + * native ad. + * + * When possible, you should place values in the returned dictionary such that they correspond to + * the pre-defined keys in the MPNativeAdConstants header file. + */ +@property (nonatomic, readonly) NSDictionary *properties; + +/** + * The default click-through URL for the ad. + * + * This may safely be set to nil if your network doesn't expose this value (for example, it may only + * provide a method to handle a click, lacking another for retrieving the URL itself). + */ +@property (nonatomic, readonly) NSURL *defaultActionURL; + +/** @name Handling Ad Interactions */ + +@optional + +/** + * Tells the object to open the specified URL using an appropriate mechanism. + * + * @param URL The URL to be opened. + * @param controller The view controller that should be used to present the modal view controller. + * + * Your implementation of this method should either forward the request to the underlying + * third-party ad object (if it has built-in support for handling ad interactions), or open an + * in-application modal web browser or a modal App Store controller. + */ +- (void)displayContentForURL:(NSURL *)URL rootViewController:(UIViewController *)controller; + +/** + * Determines whether MPNativeAd should track clicks + * + * If not implemented, this will be assumed to return NO, and MPNativeAd will track clicks. + * If this returns YES, then MPNativeAd will defer to the MPNativeAdAdapterDelegate callbacks to + * track clicks. + */ +- (BOOL)enableThirdPartyClickTracking; + +/** + * Tracks a click for this ad. + * + * To avoid reporting discrepancies, you should only implement this method if the third-party ad + * network requires clicks to be reported manually. + */ +- (void)trackClick; + +/** + * The `MPNativeAdAdapterDelegate` to send messages to as events occur. + * + * The `delegate` object defines several methods that you should call in order to inform MoPub + * of interactions with the ad. This delegate needs to be implemented if third party impression and/or + * click tracking is enabled. + */ +@property (nonatomic, weak) id delegate; + +/** @name Responding to an Ad Being Attached to a View */ + +/** + * This method will be called when your ad's content is about to be loaded into a view. + * + * @param view A view that will contain the ad content. + * + * You should implement this method if the underlying third-party ad object needs to be informed + * of this event. + */ +- (void)willAttachToView:(UIView *)view; + +/** + * This method will be called if your implementation provides a DAA icon through the properties dictionary + * and the user has tapped the icon. + */ +- (void)displayContentForDAAIconTap; + +/** + * Return your ad's privacy information icon view. + * + * You should implement this method if your ad supplies its own view for its privacy information icon. + */ +- (UIView *)privacyInformationIconView; + +/** + * Return your ad's main media view. + * + * You should implement this method if your ad supplies its own view for the main media view which is typically + * an image or video. If you implement this method, the SDK will not make any other attempts at retrieving + * the main media asset. + */ +- (UIView *)mainMediaView; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.h new file mode 100644 index 000000000..6452cb1d3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.h @@ -0,0 +1,31 @@ +// +// MPNativeAdConstants.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import + +extern const CGFloat kUniversalStarRatingScale; +extern const CGFloat kStarRatingMaxValue; +extern const CGFloat kStarRatingMinValue; +extern const NSTimeInterval kDefaultRequiredSecondsForImpression; + +/** @name MPNativeAd asset keys */ + +extern NSString *const kAdTitleKey; +extern NSString *const kAdTextKey; +extern NSString *const kAdIconImageKey; +extern NSString *const kAdMainImageKey; +extern NSString *const kAdCTATextKey; +extern NSString *const kAdStarRatingKey; +extern NSString *const kVideoConfigKey; +extern NSString *const kVASTVideoKey; +extern NSString *const kNativeVideoAdConfigKey; +extern NSString *const kAdDAAIconImageKey; +extern NSString *const kDAAIconImageName; +extern NSString *const kDAAIconTapDestinationURL; +extern NSString *const kImpressionTrackerURLsKey; +extern NSString *const kDefaultActionURLKey; +extern NSString *const kClickTrackerURLKey; +extern NSString *const kLogEventRequestPropertiesKey; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.m new file mode 100644 index 000000000..640b70a82 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdConstants.m @@ -0,0 +1,28 @@ +// +// MPNativeAdConstants.m +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdConstants.h" + +const CGFloat kUniversalStarRatingScale = 5.0f; +const CGFloat kStarRatingMaxValue = 5.0f; +const CGFloat kStarRatingMinValue = 0.0f; +const NSTimeInterval kDefaultRequiredSecondsForImpression = 1.0; + +NSString *const kAdTitleKey = @"title"; +NSString *const kAdTextKey = @"text"; +NSString *const kAdIconImageKey = @"iconimage"; +NSString *const kAdMainImageKey = @"mainimage"; +NSString *const kAdCTATextKey = @"ctatext"; +NSString *const kAdStarRatingKey = @"starrating"; +NSString *const kVideoConfigKey = @"videoconfig"; +NSString *const kVASTVideoKey = @"video"; +NSString *const kNativeVideoAdConfigKey = @"nativevideoadconfig"; +NSString *const kAdDAAIconImageKey = @"daaicon"; +NSString *const kDAAIconImageName = @"MPDAAIcon.png"; +NSString *const kDAAIconTapDestinationURL = @"https://www.mopub.com/optout"; +NSString *const kImpressionTrackerURLsKey = @"imptracker"; +NSString *const kDefaultActionURLKey = @"clk"; +NSString *const kClickTrackerURLKey = @"clktracker"; +NSString *const kLogEventRequestPropertiesKey = @"logeventrequestproperties"; diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.h new file mode 100644 index 000000000..1f4f2b118 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.h @@ -0,0 +1,17 @@ +// +// MPNativeAdData.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class MPNativeAd; + +@interface MPNativeAdData : NSObject + +@property (nonatomic, copy) NSString *adUnitID; +@property (nonatomic, strong) MPNativeAd *ad; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.m new file mode 100644 index 000000000..08cf9c8a0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdData.m @@ -0,0 +1,12 @@ +// +// MPNativeAdData.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdData.h" + +@implementation MPNativeAdData + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdDelegate.h new file mode 100644 index 000000000..0702cc79f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdDelegate.h @@ -0,0 +1,51 @@ +// +// MPNativeAdDelegate.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +/** + * The delegate of an `MPNativeAd` object must adopt the `MPNativeAdDelegate` protocol. It must + * implement `viewControllerForPresentingModalView` to provide a root view controller from which + * the ad view should present modal content. + */ +@class MPNativeAd; +@protocol MPNativeAdDelegate + +@optional + +/** + * Sent when the native ad will present its modal content. + * + * @param nativeAd The native ad sending the message. + */ +- (void)willPresentModalForNativeAd:(MPNativeAd *)nativeAd; + +/** + * Sent when a native ad has dismissed its modal content, returning control to your application. + * + * @param nativeAd The native ad sending the message. + */ +- (void)didDismissModalForNativeAd:(MPNativeAd *)nativeAd; + +/** + * Sent when a user is about to leave your application as a result of tapping this native ad. + * + * @param nativeAd The native ad sending the message. + */ +- (void)willLeaveApplicationFromNativeAd:(MPNativeAd *)nativeAd; + +@required + +/** @name Managing Modal Content Presentation */ + +/** + * Asks the delegate for a view controller to use for presenting modal content, such as the in-app + * browser that can appear when an ad is tapped. + * + * @return A view controller that should be used for presenting modal content. + */ +- (UIViewController *)viewControllerForPresentingModalView; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.h new file mode 100644 index 000000000..7a346861d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.h @@ -0,0 +1,35 @@ +// +// MPNativeAdError.h +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +typedef enum MPNativeAdErrorCode { + MPNativeAdErrorUnknown = -1, + + MPNativeAdErrorHTTPError = -1000, + MPNativeAdErrorInvalidServerResponse = -1001, + MPNativeAdErrorNoInventory = -1002, + MPNativeAdErrorImageDownloadFailed = -1003, + MPNativeAdErrorAdUnitWarmingUp = -1004, + MPNativeAdErrorVASTParsingFailed = -1005, + MPNativeAdErrorVideoConfigInvalid = -1006, + + MPNativeAdErrorContentDisplayError = -1100, + MPNativeAdErrorRenderError = -1200 +} MPNativeAdErrorCode; + +extern NSString * const MoPubNativeAdsSDKDomain; + +NSError *MPNativeAdNSErrorForInvalidAdServerResponse(NSString *reason); +NSError *MPNativeAdNSErrorForAdUnitWarmingUp(); +NSError *MPNativeAdNSErrorForNoInventory(); +NSError *MPNativeAdNSErrorForNetworkConnectionError(); +NSError *MPNativeAdNSErrorForInvalidImageURL(); +NSError *MPNativeAdNSErrorForImageDownloadFailure(); +NSError *MPNativeAdNSErrorForContentDisplayErrorMissingRootController(); +NSError *MPNativeAdNSErrorForContentDisplayErrorInvalidURL(); +NSError *MPNativeAdNSErrorForVASTParsingFailure(); +NSError *MPNativeAdNSErrorForVideoConfigInvalid(); +NSError *MPNativeAdNSErrorForRenderValueTypeError(); diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.m new file mode 100644 index 000000000..8f9c40c94 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdError.m @@ -0,0 +1,56 @@ +// +// MPNativeAdError.m +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPNativeAdError.h" + +NSString * const MoPubNativeAdsSDKDomain = @"com.mopub.nativeads"; + +NSError *MPNativeAdNSErrorForInvalidAdServerResponse(NSString *reason) { + if (reason.length == 0) { + reason = @"Invalid ad server response"; + } + + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorInvalidServerResponse userInfo:@{NSLocalizedDescriptionKey : [reason copy]}]; +} + +NSError *MPNativeAdNSErrorForAdUnitWarmingUp() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorAdUnitWarmingUp userInfo:@{NSLocalizedDescriptionKey : @"Ad unit is warming up"}]; +} + +NSError *MPNativeAdNSErrorForNoInventory() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorNoInventory userInfo:@{NSLocalizedDescriptionKey : @"Ad server returned no inventory"}]; +} + +NSError *MPNativeAdNSErrorForNetworkConnectionError() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorHTTPError userInfo:@{NSLocalizedDescriptionKey : @"Connection error"}]; +} + +NSError *MPNativeAdNSErrorForInvalidImageURL() { + return MPNativeAdNSErrorForInvalidAdServerResponse(@"Invalid image URL"); +} + +NSError *MPNativeAdNSErrorForImageDownloadFailure() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorImageDownloadFailed userInfo:@{NSLocalizedDescriptionKey : @"Failed to download images"}]; +} + +NSError *MPNativeAdNSErrorForVASTParsingFailure() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorVASTParsingFailed userInfo:@{NSLocalizedDescriptionKey : @"Failed to parse VAST tag"}]; +} + +NSError *MPNativeAdNSErrorForVideoConfigInvalid() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorVideoConfigInvalid userInfo:@{NSLocalizedDescriptionKey : @"Native Video Config Values in Adserver response are invalid"}]; +} + +NSError *MPNativeAdNSErrorForContentDisplayErrorMissingRootController() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorContentDisplayError userInfo:@{NSLocalizedDescriptionKey : @"Cannot display content without a root view controller"}]; +} + +NSError *MPNativeAdNSErrorForContentDisplayErrorInvalidURL() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorContentDisplayError userInfo:@{NSLocalizedDescriptionKey : @"Cannot display content without a valid URL"}]; +} + +NSError *MPNativeAdNSErrorForRenderValueTypeError() { + return [NSError errorWithDomain:MoPubNativeAdsSDKDomain code:MPNativeAdErrorRenderError userInfo:@{NSLocalizedDescriptionKey : @"Native ad property was an incorrect data type"}]; +} diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderer.h new file mode 100644 index 000000000..3e7356ecf --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderer.h @@ -0,0 +1,106 @@ +// +// MPNativeAdRenderer.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@protocol MPNativeAdAdapter; +@protocol MPNativeAdRendererSettings; +@class MPNativeAdRendererConfiguration; + +/** + * Provide an implementation of this handler for your renderer settings. + * + * @param maximumWidth Max width of the ad expected to be rendered as. + * + * @return Size of the view as rendered given the maximum width desired. + */ +typedef CGSize (^MPNativeViewSizeHandler)(CGFloat maximumWidth); + +/** + * The MoPub SDK has a concept of native ad renderer that allows you to render the ad however you want. It also gives you the + * ability to expose configurable properties through renderer settings objects to the application that influence how you render + * your native custom event's view. + * + * Your renderer should implement this protocol. Your renderer is responsible for rendering the network's ad data into a view + * when `-retrieveViewWithAdapter:error:` is called. Your renderer will be asked to render the native ad if your renderer configuration + * indicates that your renderer supports your specific native ad network. + * + * Finally, your renderer will live as long as the ad adapter so you may store data in your renderer if necessary. + */ +@protocol MPNativeAdRenderer + +@required + +/** + * You must construct and return an MPNativeAdRendererConfiguration object specific for your renderer. You must + * set all the properties on the configuration object. + * + * @param rendererSettings Application defined settings that you should store in the configuration object that you + * construct. + * + * @return A configuration object that allows the MoPub SDK to instantiate your renderer with the application + * settings and for the supported ad types. + */ ++ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id)rendererSettings; + +/** + * This is the init method that will be called when the MoPub SDK initializes your renderer. + * + * @param rendererSettings The renderer settings object that corresponds to your renderer. + */ +- (instancetype)initWithRendererSettings:(id)rendererSettings; + +/** + * You must return a native ad view when `-retrieveViewWithAdapter:error:` is called. Ideally, you should create a native view + * each time this is called as holding onto the view may end up consuming a lot of memory when many ads are being shown. + * However, it is OK to hold a strong reference to the view if you must. + * + * @param adapter Your custom event's adapter class that contains the network specific data necessary to render the ad to + * a view. + * @param error If you can't construct a view for whatever reason, you must fill in this error object. + * + * @return If successful, the method will return a native view presenting the ad. If it + * is unsuccessful at retrieving a view, it will return nil and create + * an error object for the error parameter. + */ +- (UIView *)retrieveViewWithAdapter:(id)adapter error:(NSError **)error; + +@optional + +/** + * The viewSizeHandler is used to allow the app to configure its native ad view size + * given a maximum width when using ad placer solutions. This is not called when the + * app is manually integrating native ads. + * + * You should obtain the renderer's viewSizeHandler from the settings object in + * `-initWithRendererSettings:`. + */ +@property (nonatomic, readonly) MPNativeViewSizeHandler viewSizeHandler; + +/** + * The MoPubSDK will notify your renderer when your native ad's view has moved in + * the hierarchy. superview will be nil if the native ad's view has been removed + * from the view hierarchy. + * + * The view your renderer creates is attached to another view before being added + * to the view hierarchy. As a result, the superview argument will not be the renderer's ad view's superview. + * + * @param superview The app's view that contains the native ad view. There is an + * intermediate view between the renderer's ad view and the app's view. + */ +- (void)adViewWillMoveToSuperview:(UIView *)superview; + +/** + * + * The MoPubSDK will call this method when the user has tapped the ad and will + * invoke the clickthrough action. + * + */ +- (void)nativeAdTapped; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.h new file mode 100644 index 000000000..26e243399 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.h @@ -0,0 +1,38 @@ +// +// MPNativeAdRendererConfiguration.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@protocol MPNativeAdRendererSettings; + +/* + * All native ads loaded with the MoPub SDK take a renderer configuration object. This object links + * the necessary native ad objects together. + * + * The configuration stores the renderer settings that will eventually be used when initializing the + * render class. Furthermore, the configuration indicates what custom events the renderer class supports + * through the supportedCustomEvents property. + */ +@interface MPNativeAdRendererConfiguration : NSObject + +/* + * The settings that inform the ad renderer about how it should render the ad. + */ +@property (nonatomic, strong) id rendererSettings; + +/* + * The renderer class used to render supported custom events. + */ +@property (nonatomic, assign) Class rendererClass; + +/* + * An array of custom event class names (as strings) that the renderClass can + * render. + */ +@property (nonatomic, strong) NSArray *supportedCustomEvents; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.m new file mode 100644 index 000000000..b59a580e6 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererConfiguration.m @@ -0,0 +1,12 @@ +// +// MPNativeAdRendererConfiguration.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeAdRendererConfiguration.h" + +@implementation MPNativeAdRendererConfiguration + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererSettings.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererSettings.h new file mode 100644 index 000000000..372b88a31 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendererSettings.h @@ -0,0 +1,33 @@ +// +// MPNativeAdRendererSettings.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdRenderer.h" + +/* + * Renderer settings are objects that allow you to expose configurable properties to the application. + * You renderer will be initialized with these settings. + * + * You should create a renderer settings object that adheres to this protocol and exposes configurable + * configurable properties for your renderer class. + */ +@protocol MPNativeAdRendererSettings + +@optional + +/** + * The viewSizeHandler is used to allow the app to configure its native ad view size + * given a maximum width when using ad placer solutions. This is not called when the + * app is manually integrating native ads. + * + * Your renderer settings object should expose a settable viewSizeHandler property so the + * application can choose how it wants to size its ad views. Your renderer will be able + * to use the view size handler from your settings object. + */ +@property (nonatomic, readwrite, copy) MPNativeViewSizeHandler viewSizeHandler; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendering.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendering.h new file mode 100644 index 000000000..532cc1b5b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRendering.h @@ -0,0 +1,103 @@ +// +// MPNativeAdRendering.h +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +#import "MPNativeAd.h" + +@class MPNativeAdRenderingImageLoader; + +/** + * The MPNativeAdRendering protocol provides methods for displaying ad content in + * custom view classes. + * + * It can be used for both static native ads and native video ads. If you are serving + * native video ads, you need to implement nativeVideoView. + */ + +@protocol MPNativeAdRendering + +@optional + +/** + * Return the UILabel that your view is using for the main text. + * + * @return a UILabel that is used for the main text. + */ +- (UILabel *)nativeMainTextLabel; + +/** + * Return the UILabel that your view is using for the title text. + * + * @return a UILabel that is used for the title text. + */ +- (UILabel *)nativeTitleTextLabel; + +/** + * Return the UIImageView that your view is using for the icon image. + * + * @return a UIImageView that is used for the icon image. + */ +- (UIImageView *)nativeIconImageView; + +/** + * Return the UIImageView that your view is using for the main image. + * + * @return a UIImageView that is used for the main image. + */ +- (UIImageView *)nativeMainImageView; + +/** + * Return the UIView that your view is using for the video. + * You only need to implement this when you are serving video ads. + * + * @return a UIView that is used to hold the video. + */ + +- (UIView *)nativeVideoView; + +/** + * Returns the UILabel that your view is using for the call to action (cta) text. + * + * @return a UILabel that is used for the cta text. + */ +- (UILabel *)nativeCallToActionTextLabel; + +/** + * Returns the UIImageView that your view is using for the privacy information icon. + * + * @return a UIImageView that is used for the privacy information icon. + */ +- (UIImageView *)nativePrivacyInformationIconImageView; + +/** + * This method is called if the ad contains a star rating. + * + * Implement this method if you expect and wish to display a star rating. + * + * @param starRating An NSNumber that is a float in the range of 0.0f and 5.0f. + */ +- (void)layoutStarRating:(NSNumber *)starRating; + +/** + * This method allows you to insert your custom native ad elements into your view. + * + * This method will be called when your ad view is added to the view hierarchy. + * + * @param customProperties Dictionary that contains custom native ad elements. + * @param imageLoader Use this object to load your custom images by calling `loadImageForURL:intoImageView:`. + */ +- (void)layoutCustomAssetsWithProperties:(NSDictionary *)customProperties imageLoader:(MPNativeAdRenderingImageLoader *)imageLoader; + +/** + * Specifies a nib object containing a view that should be used to render ads. + * + * If you want to use a nib object to render ads, you must implement this method. + * + * @return an initialized UINib object. This is not allowed to be `nil`. + */ ++ (UINib *)nibForAd; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.h new file mode 100644 index 000000000..dd30a0269 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.h @@ -0,0 +1,16 @@ +// +// MPNativeAdRenderingImageLoader.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MPNativeAdRendererImageHandler; + +@interface MPNativeAdRenderingImageLoader : NSObject + +- (instancetype)initWithImageHandler:(MPNativeAdRendererImageHandler *)imageHandler; + +- (void)loadImageForURL:(NSURL *)url intoImageView:(UIImageView *)imageView; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.m new file mode 100644 index 000000000..919096a70 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRenderingImageLoader.m @@ -0,0 +1,31 @@ +// +// MPNativeAdRenderingImageLoader.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeAdRenderingImageLoader.h" +#import "MPNativeAdRendererImageHandler.h" + +@interface MPNativeAdRenderingImageLoader () + +@property (nonatomic) MPNativeAdRendererImageHandler *imageHandler; + +@end + +@implementation MPNativeAdRenderingImageLoader + +- (instancetype)initWithImageHandler:(MPNativeAdRendererImageHandler *)imageHandler +{ + if (self = [super init]) { + _imageHandler = imageHandler; + } + + return self; +} + +- (void)loadImageForURL:(NSURL *)url intoImageView:(UIImageView *)imageView +{ + [self.imageHandler loadImageForURL:url intoImageView:imageView]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.h new file mode 100644 index 000000000..f9f3d325f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.h @@ -0,0 +1,60 @@ +// +// MPNativeAdRequest.h +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import + +@class MPNativeAd; +@class MPNativeAdRequest; +@class MPNativeAdRequestTargeting; + +typedef void(^MPNativeAdRequestHandler)(MPNativeAdRequest *request, + MPNativeAd *response, + NSError *error); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The `MPNativeAdRequest` class is used to manage individual requests to the MoPub ad server for + * native ads. + * + * @warning **Note:** This class is meant for one-off requests for which you intend to manually + * process the native ad response. If you are using `MPTableViewAdPlacer` or + * `MPCollectionViewAdPlacer` to display ads, there should be no need for you to use this class. + */ + +@interface MPNativeAdRequest : NSObject + +/** @name Targeting Information */ + +/** + * An object representing targeting parameters that can be passed to the MoPub ad server to + * serve more relevant advertising. + */ +@property (nonatomic, strong) MPNativeAdRequestTargeting *targeting; + +/** @name Initializing and Starting an Ad Request */ + +/** + * Initializes a request object. + * + * @param identifier The ad unit identifier for this request. An ad unit is a defined placement in + * your application set aside for advertising. Ad unit IDs are created on the MoPub website. + * + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. + * + * @return An `MPNativeAdRequest` object. + */ ++ (MPNativeAdRequest *)requestWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations; + +/** + * Executes a request to the MoPub ad server. + * + * @param handler A block to execute when the request finishes. The block includes as parameters the + * request itself and either a valid MPNativeAd or an NSError object indicating failure. + */ +- (void)startWithCompletionHandler:(MPNativeAdRequestHandler)handler; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.m new file mode 100644 index 000000000..3f64fb7cf --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequest.m @@ -0,0 +1,284 @@ +// +// MPNativeAdRequest.m +// Copyright (c) 2013 MoPub. All rights reserved. +// + +#import "MPNativeAdRequest.h" + +#import "MPAdServerURLBuilder.h" +#import "MPCoreInstanceProvider.h" +#import "MPNativeAdError.h" +#import "MPNativeAd+Internal.h" +#import "MPNativeAdRequestTargeting.h" +#import "MPLogEvent.h" +#import "MPLogging.h" +#import "MPImageDownloadQueue.h" +#import "MPConstants.h" +#import "MPNativeAdConstants.h" +#import "MPNativeCustomEventDelegate.h" +#import "MPNativeCustomEvent.h" +#import "MOPUBNativeVideoAdConfigValues.h" +#import "MOPUBNativeVideoCustomEvent.h" +#import "MPInstanceProvider.h" +#import "NSJSONSerialization+MPAdditions.h" +#import "MPAdServerCommunicator.h" +#import "MPNativeAdRenderer.h" +#import "MPMoPubNativeCustomEvent.h" +#import "MPNativeAdRendererConfiguration.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPNativeAdRequest () + +@property (nonatomic, copy) NSString *adUnitIdentifier; +@property (nonatomic) NSArray *rendererConfigurations; +@property (nonatomic, strong) NSURL *URL; +@property (nonatomic, strong) MPAdServerCommunicator *communicator; +@property (nonatomic, copy) MPNativeAdRequestHandler completionHandler; +@property (nonatomic, strong) MPNativeCustomEvent *nativeCustomEvent; +@property (nonatomic, strong) MPAdConfiguration *adConfiguration; +@property (nonatomic) id customEventRenderer; +@property (nonatomic, assign) BOOL loading; + +@end + +@implementation MPNativeAdRequest + +- (id)initWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations +{ + self = [super init]; + if (self) { + _adUnitIdentifier = [identifier copy]; + _communicator = [[MPCoreInstanceProvider sharedProvider] buildMPAdServerCommunicatorWithDelegate:self]; + _rendererConfigurations = rendererConfigurations; + } + return self; +} + +- (void)dealloc +{ + [_communicator cancel]; + [_communicator setDelegate:nil]; + [_nativeCustomEvent setDelegate:nil]; +} + +#pragma mark - Public + ++ (MPNativeAdRequest *)requestWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations +{ + return [[self alloc] initWithAdUnitIdentifier:identifier rendererConfigurations:rendererConfigurations]; +} + +- (void)startWithCompletionHandler:(MPNativeAdRequestHandler)handler +{ + if (handler) { + self.URL = [MPAdServerURLBuilder URLWithAdUnitID:self.adUnitIdentifier + keywords:self.targeting.keywords + location:self.targeting.location + versionParameterName:@"nsv" + version:MP_SDK_VERSION + testing:NO + desiredAssets:[self.targeting.desiredAssets allObjects]]; + + [self assignCompletionHandler:handler]; + + [self loadAdWithURL:self.URL]; + } else { + MPLogWarn(@"Native Ad Request did not start - requires completion handler block."); + } +} + +- (void)startForAdSequence:(NSInteger)adSequence withCompletionHandler:(MPNativeAdRequestHandler)handler +{ + if (handler) { + self.URL = [MPAdServerURLBuilder URLWithAdUnitID:self.adUnitIdentifier + keywords:self.targeting.keywords + location:self.targeting.location + versionParameterName:@"nsv" + version:MP_SDK_VERSION + testing:NO + desiredAssets:[self.targeting.desiredAssets allObjects] + adSequence:adSequence]; + + [self assignCompletionHandler:handler]; + + [self loadAdWithURL:self.URL]; + } else { + MPLogWarn(@"Native Ad Request did not start - requires completion handler block."); + } +} + +#pragma mark - Private + +- (void)assignCompletionHandler:(MPNativeAdRequestHandler)handler +{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + // we explicitly create a block retain cycle here to prevent self from being deallocated if the developer + // removes his strong reference to the request. This retain cycle is broken in + // - (void)completeAdRequestWithAdObject:(MPNativeAd *)adObject error:(NSError *)error + // when self.completionHandler is set to nil. + self.completionHandler = ^(MPNativeAdRequest *request, MPNativeAd *response, NSError *error) { + handler(self, response, error); + }; +#pragma clang diagnostic pop +} + +- (void)loadAdWithURL:(NSURL *)URL +{ + if (self.loading) { + MPLogWarn(@"Native ad request is already loading an ad. Wait for previous load to finish."); + return; + } + + MPLogInfo(@"Starting ad request with URL: %@", self.URL); + + self.loading = YES; + [self.communicator loadURL:URL]; +} + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration +{ + if (configuration.customEventClass) { + MPLogInfo(@"Looking for custom event class named %@.", configuration.customEventClass); + } + + // For MoPub native ads, set the classData to be the adResponseData + if ((configuration.customEventClass == [MPMoPubNativeCustomEvent class]) || (configuration.customEventClass == [MOPUBNativeVideoCustomEvent class])) { + NSError *error; + NSMutableDictionary *classData = [NSJSONSerialization mp_JSONObjectWithData:configuration.adResponseData + options:0 + clearNullObjects:YES + error:&error]; + if (configuration.customEventClass == [MOPUBNativeVideoCustomEvent class]) { + [classData setObject:[[MOPUBNativeVideoAdConfigValues alloc] + initWithPlayVisiblePercent:configuration.nativeVideoPlayVisiblePercent + pauseVisiblePercent:configuration.nativeVideoPauseVisiblePercent + impressionMinVisiblePercent:configuration.nativeVideoImpressionMinVisiblePercent + impressionVisible:configuration.nativeVideoImpressionVisible + maxBufferingTime:configuration.nativeVideoMaxBufferingTime + trackers:configuration.nativeVideoTrackers] forKey:kNativeVideoAdConfigKey]; + MPAdConfigurationLogEventProperties *logEventProperties = + [[MPAdConfigurationLogEventProperties alloc] initWithConfiguration:configuration]; + [classData setObject:logEventProperties forKey:kLogEventRequestPropertiesKey]; + } + + configuration.customEventClassData = classData; + } + + // See if we have a renderer that we can use for the custom event now so we can fail early. + NSString *customEventClassName = NSStringFromClass(configuration.customEventClass); + MPNativeAdRendererConfiguration *customEventRendererConfig = nil; + + for (MPNativeAdRendererConfiguration *rendererConfig in self.rendererConfigurations) { + NSArray *supportedCustomEvents = rendererConfig.supportedCustomEvents; + + if ([supportedCustomEvents containsObject:customEventClassName]) { + customEventRendererConfig = rendererConfig; + break; + } + } + + if (customEventRendererConfig) { + // Create a renderer from the config. + self.customEventRenderer = [[customEventRendererConfig.rendererClass alloc] initWithRendererSettings:customEventRendererConfig.rendererSettings]; + self.nativeCustomEvent = [[MPInstanceProvider sharedProvider] buildNativeCustomEventFromCustomClass:configuration.customEventClass delegate:self]; + } else { + MPLogError(@"Could not find renderer configuration for custom event class: %@", NSStringFromClass(configuration.customEventClass)); + } + + if (self.nativeCustomEvent) { + [self.nativeCustomEvent requestAdWithCustomEventInfo:configuration.customEventClassData]; + } else if ([[self.adConfiguration.failoverURL absoluteString] length]) { + self.loading = NO; + [self loadAdWithURL:self.adConfiguration.failoverURL]; + } else { + [self completeAdRequestWithAdObject:nil error:MPNativeAdNSErrorForInvalidAdServerResponse(nil)]; + } +} + +- (void)completeAdRequestWithAdObject:(MPNativeAd *)adObject error:(NSError *)error +{ + self.loading = NO; + + adObject.renderer = self.customEventRenderer; + + if ([(id)adObject.adAdapter respondsToSelector:@selector(setAdConfiguration:)]) { + [(id)adObject.adAdapter performSelector:@selector(setAdConfiguration:) withObject:self.adConfiguration]; + } + + if (!error) { + MPLogInfo(@"Successfully loaded native ad."); + } else { + MPLogError(@"Native ad failed to load with error: %@", error); + } + + if (self.completionHandler) { + self.completionHandler(self, adObject, error); + self.completionHandler = nil; + } +} + +#pragma mark - + +- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration +{ + self.adConfiguration = configuration; + + if (configuration.adUnitWarmingUp) { + MPLogInfo(kMPWarmingUpErrorLogFormatWithAdUnitID, self.adUnitIdentifier); + [self completeAdRequestWithAdObject:nil error:MPNativeAdNSErrorForAdUnitWarmingUp()]; + return; + } + + if ([configuration.networkType isEqualToString:kAdTypeClear]) { + MPLogInfo(kMPClearErrorLogFormatWithAdUnitID, self.adUnitIdentifier); + [self completeAdRequestWithAdObject:nil error:MPNativeAdNSErrorForNoInventory()]; + return; + } + + MPLogInfo(@"Received data from MoPub to construct native ad.\n"); + [self getAdWithConfiguration:configuration]; +} + +- (void)communicatorDidFailWithError:(NSError *)error +{ + MPLogDebug(@"Error: Couldn't retrieve an ad from MoPub. Message: %@", error); + + [self completeAdRequestWithAdObject:nil error:MPNativeAdNSErrorForNetworkConnectionError()]; +} + +#pragma mark - + +- (void)nativeCustomEvent:(MPNativeCustomEvent *)event didLoadAd:(MPNativeAd *)adObject +{ + // Add the click tracker url from the header to our set. + if (self.adConfiguration.clickTrackingURL) { + [adObject.clickTrackerURLs addObject:self.adConfiguration.clickTrackingURL]; + } + + // Add the impression tracker url from the header to our set. + if (self.adConfiguration.impressionTrackingURL) { + [adObject.impressionTrackerURLs addObject:self.adConfiguration.impressionTrackingURL]; + } + + // Error if we don't have click trackers or impression trackers. + if (adObject.clickTrackerURLs.count < 1 || adObject.impressionTrackerURLs.count < 1) { + [self completeAdRequestWithAdObject:nil error:MPNativeAdNSErrorForInvalidAdServerResponse(@"Invalid ad trackers")]; + } else { + [self completeAdRequestWithAdObject:adObject error:nil]; + } +} + +- (void)nativeCustomEvent:(MPNativeCustomEvent *)event didFailToLoadAdWithError:(NSError *)error +{ + if ([[self.adConfiguration.failoverURL absoluteString] length]) { + self.loading = NO; + [self loadAdWithURL:self.adConfiguration.failoverURL]; + } else { + [self completeAdRequestWithAdObject:nil error:error]; + } +} + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.h new file mode 100644 index 000000000..5fb814a45 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.h @@ -0,0 +1,54 @@ +// +// MPNativeAdRequestTargeting.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class CLLocation; + +/** + * The `MPNativeAdRequestTargeting` class is used to attach targeting information to + * `MPNativeAdRequest` objects. + */ + +@interface MPNativeAdRequestTargeting : NSObject + +/** @name Creating a Targeting Object */ + +/** + * Creates and returns an empty MPNativeAdRequestTargeting object. + * + * @return A newly initialized MPNativeAdRequestTargeting object. + */ ++ (MPNativeAdRequestTargeting *)targeting; + +/** @name Targeting Parameters */ + +/** + * A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * + * Keywords are typically used to target ad campaigns at specific user segments. They should be + * formatted as comma-separated key-value pairs (e.g. "marital:single,age:24"). + * + * On the MoPub website, keyword targeting options can be found under the "Advanced Targeting" + * section when managing campaigns. + */ +@property (nonatomic, copy) NSString *keywords; + +/** + * A `CLLocation` object representing a user's location that should be passed to the MoPub ad server + * to receive more relevant advertising. + */ +@property (nonatomic, copy) CLLocation *location; + +/** + * A set of defined strings that correspond to assets for the intended native ad + * object. This set should contain only those assets that will be displayed in the ad. + * + * The MoPub ad server will attempt to only return the assets in desiredAssets. + */ +@property (nonatomic, strong) NSSet *desiredAssets; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.m new file mode 100644 index 000000000..fea34ceec --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdRequestTargeting.m @@ -0,0 +1,35 @@ +// +// MPNativeAdRequestTargeting.m +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdRequestTargeting.h" +#import "MPNativeAdConstants.h" + +#import + +@implementation MPNativeAdRequestTargeting + ++ (MPNativeAdRequestTargeting *)targeting +{ + return [[MPNativeAdRequestTargeting alloc] init]; +} + +- (void)setDesiredAssets:(NSSet *)desiredAssets +{ + if (_desiredAssets != desiredAssets) { + + NSMutableSet *allowedAdAssets = [NSMutableSet setWithObjects:kAdTitleKey, + kAdTextKey, + kAdIconImageKey, + kAdMainImageKey, + kAdCTATextKey, + kAdStarRatingKey, + nil]; + [allowedAdAssets intersectSet:desiredAssets]; + _desiredAssets = allowedAdAssets; + } +} + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.h new file mode 100644 index 000000000..b338a1b2c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.h @@ -0,0 +1,22 @@ +// +// MPNativeAdSource.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdSourceDelegate.h" +@class MPNativeAdRequestTargeting; + +@interface MPNativeAdSource : NSObject + +@property (nonatomic, weak) id delegate; + ++ (instancetype)source; +- (void)loadAdsWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations andTargeting:(MPNativeAdRequestTargeting *)targeting; +- (void)deleteCacheForAdUnitIdentifier:(NSString *)identifier; +- (id)dequeueAdForAdUnitIdentifier:(NSString *)identifier; + + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.m new file mode 100644 index 000000000..1c0a61b5d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSource.m @@ -0,0 +1,83 @@ +// +// MPNativeAdSource.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeAdSource.h" +#import "MPNativeAd.h" +#import "MPNativeAdRequestTargeting.h" +#import "MPNativeAdSourceQueue.h" + +static NSTimeInterval const kCacheTimeoutInterval = 900; //15 minutes + +@interface MPNativeAdSource () + +@property (nonatomic, strong) NSMutableDictionary *adQueueDictionary; + +@end + +@implementation MPNativeAdSource + +#pragma mark - Object Lifecycle + ++ (instancetype)source +{ + return [[MPNativeAdSource alloc] init]; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _adQueueDictionary = [[NSMutableDictionary alloc] init]; + } + + return self; +} + +- (void)dealloc +{ + for (NSString *queueKey in [_adQueueDictionary allKeys]) { + [self deleteCacheForAdUnitIdentifier:queueKey]; + } +} + +#pragma mark - Ad Source Interface + +- (void)loadAdsWithAdUnitIdentifier:(NSString *)identifier rendererConfigurations:(NSArray *)rendererConfigurations andTargeting:(MPNativeAdRequestTargeting *)targeting +{ + [self deleteCacheForAdUnitIdentifier:identifier]; + + MPNativeAdSourceQueue *adQueue = [[MPNativeAdSourceQueue alloc] initWithAdUnitIdentifier:identifier rendererConfigurations:rendererConfigurations andTargeting:targeting]; + adQueue.delegate = self; + [self.adQueueDictionary setObject:adQueue forKey:identifier]; + + [adQueue loadAds]; +} + +- (id)dequeueAdForAdUnitIdentifier:(NSString *)identifier +{ + MPNativeAdSourceQueue *adQueue = [self.adQueueDictionary objectForKey:identifier]; + MPNativeAd *nextAd = [adQueue dequeueAdWithMaxAge:kCacheTimeoutInterval]; + return nextAd; +} + +- (void)deleteCacheForAdUnitIdentifier:(NSString *)identifier +{ + MPNativeAdSourceQueue *sourceQueue = [self.adQueueDictionary objectForKey:identifier]; + sourceQueue.delegate = nil; + [sourceQueue cancelRequests]; + + [self.adQueueDictionary removeObjectForKey:identifier]; +} + +#pragma mark - MPNativeAdSourceQueueDelegate + +- (void)adSourceQueueAdIsAvailable:(MPNativeAdSourceQueue *)source +{ + [self.delegate adSourceDidFinishRequest:self]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSourceDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSourceDelegate.h new file mode 100644 index 000000000..eac059934 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeAdSourceDelegate.h @@ -0,0 +1,16 @@ +// +// MPNativeAdSourceDelegate.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class MPNativeAdSource; + +@protocol MPNativeAdSourceDelegate + +- (void)adSourceDidFinishRequest:(MPNativeAdSource *)source; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.h new file mode 100644 index 000000000..447295df9 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.h @@ -0,0 +1,69 @@ +// +// MPNativeCustomEvent.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeCustomEventDelegate.h" + +/** + * The MoPub iOS SDK mediates third-party native ad networks using custom events. Custom events are + * responsible for instantiating and manipulating native ad objects in the third-party SDK and + * translating and communicating events from those objects back to the MoPub SDK by notifying a + * delegate. + * + * `MPNativeCustomEvent` is a base class for custom events that support native ads. By implementing + * subclasses of `MPNativeCustomEvent` you can enable the MoPub SDK to support a variety of + * third-party ad networks. + * + * Your implementation should create an `MPNativeAd` object using an appropriate `MPNativeAdAdapter` + * for your network. Your custom event should also call the appropriate + * `MPNativeCustomEventDelegate` methods. + * + * At runtime, the MoPub SDK will find and instantiate an `MPNativeCustomEvent` subclass as needed + * and invoke its `-requestAdWithCustomEventInfo:` method. + */ +@interface MPNativeCustomEvent : NSObject + +/** @name Requesting a Native Ad */ + +/** + * Called when the MoPub SDK requires a new native ad. + * + * When the MoPub SDK receives a response indicating it should load a custom event, it will send + * this message to your custom event class. Your implementation should load a native ad from a + * third-party ad network. + * + * @param info A dictionary containing additional custom data associated with a given custom event + * request. This data is configurable on the MoPub website, and may be used to pass dynamic + * information, such as publisher IDs. + */ +- (void)requestAdWithCustomEventInfo:(NSDictionary *)info; + +/** @name Caching Image Resources */ + +/** + * Downloads and pre-caches images. + * + * If your ad network does not provide built-in support for image caching, you may invoke this + * method in your custom event implementation to pre-cache image assets. If you do call this method, + * you should wait until the completion block is called before invoking the appropriate + * success or failure callbacks on the `MPNativeCustomEventDelegate`. + * + * @param imageURLs An array of `NSURL` objects representing image resource locations. + * @param completionBlock A block that will be called after all download operations are complete. + * If any image downloads do not complete successfully, the `errors` parameter will contain + * error information about the failures. + */ +- (void)precacheImagesWithURLs:(NSArray *)imageURLs completionBlock:(void (^)(NSArray *errors))completionBlock; + +/** @name Communicating with the MoPub SDK */ + +/** + * The `MPNativeCustomEventDelegate` receives messages concerning the status of loading a native ad. + * + * The `delegate` object defines several methods that you should call in order to inform MoPub + * of the progress of your custom event. + */ +@property (nonatomic, weak) id delegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.m new file mode 100644 index 000000000..aa7e11605 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEvent.m @@ -0,0 +1,49 @@ +// +// MPNativeCustomEvent.m +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPNativeCustomEvent.h" +#import "MPNativeAdError.h" +#import "MPImageDownloadQueue.h" +#import "MPLogging.h" + +@interface MPNativeCustomEvent () + +@property (nonatomic, strong) MPImageDownloadQueue *imageDownloadQueue; + +@end + +@implementation MPNativeCustomEvent + +- (id)init +{ + self = [super init]; + if (self) { + _imageDownloadQueue = [[MPImageDownloadQueue alloc] init]; + } + + return self; +} + +- (void)precacheImagesWithURLs:(NSArray *)imageURLs completionBlock:(void (^)(NSArray *errors))completionBlock +{ + if (imageURLs.count > 0) { + [_imageDownloadQueue addDownloadImageURLs:imageURLs completionBlock:^(NSArray *errors) { + if (completionBlock) { + completionBlock(errors); + } + }]; + } else { + if (completionBlock) { + completionBlock(nil); + } + } +} + +- (void)requestAdWithCustomEventInfo:(NSDictionary *)info +{ + /*override with custom network behavior*/ +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEventDelegate.h new file mode 100644 index 000000000..ff0b0f39a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPNativeCustomEventDelegate.h @@ -0,0 +1,36 @@ +// +// MPNativeCustomEventDelegate.h +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import + +@class MPNativeAd; +@class MPNativeCustomEvent; + +/** + * Instances of your custom subclass of `MPNativeCustomEvent` will have an + * `MPNativeCustomEventDelegate` delegate object. You use this delegate to communicate progress + * (such as whether an ad has loaded successfully) back to the MoPub SDK. + */ +@protocol MPNativeCustomEventDelegate + +/** + * This method is called when the ad and all required ad assets are loaded. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the + * correct instance of your custom event. + * @param adObject An `MPNativeAd` object, representing the ad that was retrieved. + */ +- (void)nativeCustomEvent:(MPNativeCustomEvent *)event didLoadAd:(MPNativeAd *)adObject; + +/** + * This method is called when the ad or any required ad assets fail to load. + * + * @param event You should pass `self` to allow the MoPub SDK to associate this event with the + * correct instance of your custom event. + * @param error (*optional*) You may pass an error describing the failure. + */ +- (void)nativeCustomEvent:(MPNativeCustomEvent *)event didFailToLoadAdWithError:(NSError *)error; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.h new file mode 100644 index 000000000..c2952f2df --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.h @@ -0,0 +1,38 @@ +// +// MPServerAdPositioning.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPAdPositioning.h" + +/** + * The `MPServerAdPositioning` class is a model that allows you to control the positions where + * native advertisements should appear within a stream. A server positioning object works in + * conjunction with an ad placer, telling the ad placer that it should retrieve positioning + * information from the MoPub ad server. + * + * Unlike `MPClientAdPositioning`, which represents hard-coded positioning information, a server + * positioning object offers you the benefit of modifying your ad positions via the MoPub website, + * without rebuilding your application. + */ + +@interface MPServerAdPositioning : MPAdPositioning + +/** @name Creating a Server Positioning Object */ + +/** + * Creates and returns a server positioning object. + * + * When an ad placer is set to use server positioning, it will ask the MoPub ad server for the + * positions where ads should be inserted into a given stream. These positioning values are + * configurable on the MoPub website. + * + * @return The newly created positioning object. + * + * @see MPClientAdPositioning + */ ++ (instancetype)positioning; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.m new file mode 100644 index 000000000..d75d85912 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPServerAdPositioning.m @@ -0,0 +1,17 @@ +// +// MPServerAdPositioning.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPServerAdPositioning.h" + +@implementation MPServerAdPositioning + ++ (instancetype)positioning +{ + return [[[self class] alloc] init]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.h new file mode 100644 index 000000000..666b42de0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.h @@ -0,0 +1,20 @@ +// +// MPStaticNativeAdRenderer.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdRenderer.h" + +@class MPNativeAdRendererConfiguration; +@class MPStaticNativeAdRendererSettings; + +@interface MPStaticNativeAdRenderer : NSObject + +@property (nonatomic, readonly) MPNativeViewSizeHandler viewSizeHandler; + ++ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id)rendererSettings; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.m new file mode 100644 index 000000000..93bd856a3 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRenderer.m @@ -0,0 +1,200 @@ +// +// MPStaticNativeAdRenderer.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPAdDestinationDisplayAgent.h" +#import "MPLogging.h" +#import "MPNativeAdAdapter.h" +#import "MPNativeAdConstants.h" +#import "MPNativeAdError.h" +#import "MPNativeAdRenderer.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPNativeAdRendererConstants.h" +#import "MPNativeAdRendererImageHandler.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdRenderingImageLoader.h" +#import "MPNativeCache.h" +#import "MPNativeView.h" +#import "MPStaticNativeAdRenderer.h" +#import "MPStaticNativeAdRendererSettings.h" + +/** + * -1.0 is somewhat significant because this also happens to be what `UITableViewAutomaticDimension` + * is so it makes for easier migration to use `UITableViewAutomaticDimension` on iOS 8+ later but is not + * currently passed back in `-tableView:shouldIndentWhileEditingRowAtIndexPath:` directly so it can + * be any abitrary value. + */ +const CGFloat MPNativeViewDynamicDimension = -1.0; + +@interface MPStaticNativeAdRenderer () + +@property (nonatomic) UIView *adView; +@property (nonatomic) id adapter; +@property (nonatomic) BOOL adViewInViewHierarchy; +@property (nonatomic) Class renderingViewClass; +@property (nonatomic) MPNativeAdRendererImageHandler *rendererImageHandler; + +@end + +@implementation MPStaticNativeAdRenderer + ++ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id)rendererSettings +{ + MPNativeAdRendererConfiguration *config = [[MPNativeAdRendererConfiguration alloc] init]; + config.rendererClass = [self class]; + config.rendererSettings = rendererSettings; + config.supportedCustomEvents = @[@"MPMoPubNativeCustomEvent", @"FacebookNativeCustomEvent", @"FlurryNativeCustomEvent", @"InMobiNativeCustomEvent", @"MillennialNativeCustomEvent"]; + + return config; +} + +- (instancetype)initWithRendererSettings:(id)rendererSettings +{ + if (self = [super init]) { + MPStaticNativeAdRendererSettings *settings = (MPStaticNativeAdRendererSettings *)rendererSettings; + _renderingViewClass = settings.renderingViewClass; + _viewSizeHandler = [settings.viewSizeHandler copy]; + _rendererImageHandler = [MPNativeAdRendererImageHandler new]; + _rendererImageHandler.delegate = self; + } + + return self; +} + +- (UIView *)retrieveViewWithAdapter:(id)adapter error:(NSError **)error +{ + if (!adapter) { + if (error) { + *error = MPNativeAdNSErrorForRenderValueTypeError(); + } + + return nil; + } + + self.adapter = adapter; + + if ([self.renderingViewClass respondsToSelector:@selector(nibForAd)]) { + self.adView = (UIView *)[[[self.renderingViewClass nibForAd] instantiateWithOwner:nil options:nil] firstObject]; + } else { + self.adView = [[self.renderingViewClass alloc] init]; + } + + self.adView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + // We only load text here. We delay loading of images until the view is added to the view hierarchy + // so we don't unnecessarily load images from the cache if the user is scrolling fast. So we will + // just store the image URLs for now. + if ([self.adView respondsToSelector:@selector(nativeMainTextLabel)]) { + self.adView.nativeMainTextLabel.text = [adapter.properties objectForKey:kAdTextKey]; + } + + if ([self.adView respondsToSelector:@selector(nativeTitleTextLabel)]) { + self.adView.nativeTitleTextLabel.text = [adapter.properties objectForKey:kAdTitleKey]; + } + + if ([self.adView respondsToSelector:@selector(nativeCallToActionTextLabel)] && self.adView.nativeCallToActionTextLabel) { + self.adView.nativeCallToActionTextLabel.text = [adapter.properties objectForKey:kAdCTATextKey]; + } + + if ([self.adView respondsToSelector:@selector(nativePrivacyInformationIconImageView)]) { + // MoPub ads pass the privacy information icon key through the properties dictionary. + NSString *daaIconImageLoc = [adapter.properties objectForKey:kAdDAAIconImageKey]; + if (daaIconImageLoc) { + UIImageView *imageView = self.adView.nativePrivacyInformationIconImageView; + imageView.hidden = NO; + + UIImage *daaIconImage = [UIImage imageNamed:daaIconImageLoc]; + imageView.image = daaIconImage; + + // Attach a gesture recognizer to handle loading the daa icon URL. + UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(DAAIconTapped)]; + imageView.userInteractionEnabled = YES; + [imageView addGestureRecognizer:tapRecognizer]; + } else if ([adapter respondsToSelector:@selector(privacyInformationIconView)]) { + // The ad network may provide its own view for its privacy information icon. We assume the ad handles the tap on the icon as well. + UIView *privacyIconAdView = [adapter privacyInformationIconView]; + privacyIconAdView.frame = self.adView.nativePrivacyInformationIconImageView.bounds; + privacyIconAdView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.adView.nativePrivacyInformationIconImageView.userInteractionEnabled = YES; + [self.adView.nativePrivacyInformationIconImageView addSubview:privacyIconAdView]; + self.adView.nativePrivacyInformationIconImageView.hidden = NO; + } else { + self.adView.nativePrivacyInformationIconImageView.userInteractionEnabled = NO; + self.adView.nativePrivacyInformationIconImageView.hidden = YES; + } + } + + if ([self shouldLoadMediaView]) { + UIView *mediaView = [self.adapter mainMediaView]; + UIView *mainImageView = [self.adView nativeMainImageView]; + + mediaView.frame = mainImageView.bounds; + mediaView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + mainImageView.userInteractionEnabled = YES; + + [mainImageView addSubview:mediaView]; + } + + // See if the ad contains a star rating and notify the view if it does. + if ([self.adView respondsToSelector:@selector(layoutStarRating:)]) { + NSNumber *starRatingNum = [adapter.properties objectForKey:kAdStarRatingKey]; + + if ([starRatingNum isKindOfClass:[NSNumber class]] && starRatingNum.floatValue >= kStarRatingMinValue && starRatingNum.floatValue <= kStarRatingMaxValue) { + [self.adView layoutStarRating:starRatingNum]; + } + } + + return self.adView; +} + +- (BOOL)shouldLoadMediaView +{ + return [self.adapter respondsToSelector:@selector(mainMediaView)] + && [self.adapter mainMediaView] + && [self.adView respondsToSelector:@selector(nativeMainImageView)]; +} + +- (void)DAAIconTapped +{ + if ([self.adapter respondsToSelector:@selector(displayContentForDAAIconTap)]) { + [self.adapter displayContentForDAAIconTap]; + } +} + +- (void)adViewWillMoveToSuperview:(UIView *)superview +{ + self.adViewInViewHierarchy = (superview != nil); + + if (superview) { + // We'll start asychronously loading the native ad images now. + if ([self.adapter.properties objectForKey:kAdIconImageKey] && [self.adView respondsToSelector:@selector(nativeIconImageView)]) { + [self.rendererImageHandler loadImageForURL:[NSURL URLWithString:[self.adapter.properties objectForKey:kAdIconImageKey]] intoImageView:self.adView.nativeIconImageView]; + } + + // Only handle the loading of the main image if the adapter doesn't already have a view for it. + if (!([self.adapter respondsToSelector:@selector(mainMediaView)] && [self.adapter mainMediaView])) { + if ([self.adapter.properties objectForKey:kAdMainImageKey] && [self.adView respondsToSelector:@selector(nativeMainImageView)]) { + [self.rendererImageHandler loadImageForURL:[NSURL URLWithString:[self.adapter.properties objectForKey:kAdMainImageKey]] intoImageView:self.adView.nativeMainImageView]; + } + } + + // Layout custom assets here as the custom assets may contain images that need to be loaded. + if ([self.adView respondsToSelector:@selector(layoutCustomAssetsWithProperties:imageLoader:)]) { + // Create a simplified image loader for the ad view to use. + MPNativeAdRenderingImageLoader *imageLoader = [[MPNativeAdRenderingImageLoader alloc] initWithImageHandler:self.rendererImageHandler]; + [self.adView layoutCustomAssetsWithProperties:self.adapter.properties imageLoader:imageLoader]; + } + } +} + +#pragma mark - MPNativeAdRendererImageHandlerDelegate + +- (BOOL)nativeAdViewInViewHierarchy +{ + return self.adViewInViewHierarchy; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.h new file mode 100644 index 000000000..3ddc074dd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.h @@ -0,0 +1,30 @@ +// +// MPStaticNativeAdRendererSettings.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdRendererSettings.h" +#import "MPNativeAdRenderer.h" + +@interface MPStaticNativeAdRendererSettings : NSObject + +/** + * A rendering class that must be a UIView that implements the MPNativeAdRendering protocol. + * The ad will be rendered to a view of this class type. + */ +@property (nonatomic, assign) Class renderingViewClass; + +/** + * A block that returns the size of the view given a maximum width. This needs to be set when + * used in conjunction with ad placer classes so the ad placers can correctly size the cells + * that contain the ads. + * + * viewSizeHandler is not used for manual native ad integration. You must set the + * frame of your manually integrated native ad view. + */ +@property (nonatomic, readwrite, copy) MPNativeViewSizeHandler viewSizeHandler; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.m new file mode 100644 index 000000000..264ca8ac5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStaticNativeAdRendererSettings.m @@ -0,0 +1,12 @@ +// +// MPStaticNativeAdRendererSettings.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPStaticNativeAdRendererSettings.h" + +@implementation MPStaticNativeAdRendererSettings + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.h new file mode 100644 index 000000000..35769b68e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.h @@ -0,0 +1,35 @@ +// +// MPStreamAdPlacementData.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import + +@class MPAdPositioning; +@class MPNativeAdData; + +@interface MPStreamAdPlacementData : NSObject + +- (instancetype)initWithPositioning:(MPAdPositioning *)positioning; +- (void)insertAdData:(MPNativeAdData *)data atIndexPath:(NSIndexPath *)adjustedIndexPath; +- (NSArray *)adjustedAdIndexPathsInAdjustedRange:(NSRange)range inSection:(NSInteger)section; +- (void)clearAdsInAdjustedRange:(NSRange)range inSection:(NSInteger)section; +- (NSIndexPath *)nextAdInsertionIndexPathForAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath; +- (NSIndexPath *)previousAdInsertionIndexPathForAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath; +- (BOOL)isAdAtAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath; +- (NSArray *)adjustedIndexPathsWithAdsInSection:(NSUInteger)section; +- (MPNativeAdData *)adDataAtAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath; +- (NSUInteger)adjustedNumberOfItems:(NSUInteger)numberOfItems inSection:(NSUInteger)section; +- (NSIndexPath *)adjustedIndexPathForOriginalIndexPath:(NSIndexPath *)indexPath; +- (NSIndexPath *)originalIndexPathForAdjustedIndexPath:(NSIndexPath *)indexPath; +- (void)insertSections:(NSIndexSet *)sections; +- (void)deleteSections:(NSIndexSet *)sections; +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection; +- (void)insertItemsAtIndexPaths:(NSArray *)originalIndexPaths; +- (void)deleteItemsAtIndexPaths:(NSArray *)originalIndexPaths; +- (void)moveItemAtIndexPath:(NSIndexPath *)originalIndexPath toIndexPath:(NSIndexPath *)newIndexPath; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.m new file mode 100644 index 000000000..b16b42cb0 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacementData.m @@ -0,0 +1,514 @@ +// +// MPStreamAdPlacementData.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPStreamAdPlacementData.h" +#import "MPAdPositioning.h" +#import "MPLogging.h" + +static const NSUInteger kMaximumNumberOfAdsPerStream = 255; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface MPStreamAdPlacementData () + +@property (nonatomic, strong) NSMutableDictionary *desiredOriginalPositions; +@property (nonatomic, strong) NSMutableDictionary *desiredInsertionPositions; +@property (nonatomic, strong) NSMutableDictionary *originalAdIndexPaths; +@property (nonatomic, strong) NSMutableDictionary *adjustedAdIndexPaths; +@property (nonatomic, strong) NSMutableDictionary *adDataObjects; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPStreamAdPlacementData + +- (id)initWithPositioning:(MPAdPositioning *)positioning +{ + self = [super init]; + if (self) { + [self initializeDesiredPositionsFromPositioning:positioning]; + self.originalAdIndexPaths = [NSMutableDictionary dictionary]; + self.adjustedAdIndexPaths = [NSMutableDictionary dictionary]; + self.adDataObjects = [NSMutableDictionary dictionary]; + } + return self; +} + + +- (NSMutableArray *)positioningArrayForSection:(NSUInteger)section inDictionary:(NSMutableDictionary *)dictionary +{ + NSMutableArray *array = [dictionary objectForKey:[NSNumber numberWithUnsignedInteger:section]]; + if (array) { + return array; + } else { + array = [NSMutableArray array]; + [dictionary setObject:array forKey:[NSNumber numberWithUnsignedInteger:section]]; + return array; + } +} + +- (void)initializeDesiredPositionsFromPositioning:(MPAdPositioning *)positioning +{ + NSArray *fixedPositions = [[positioning.fixedPositions array] sortedArrayUsingSelector:@selector(compare:)]; + + self.desiredOriginalPositions = [NSMutableDictionary dictionary]; + self.desiredInsertionPositions = [NSMutableDictionary dictionary]; + + [fixedPositions enumerateObjectsUsingBlock:^(NSIndexPath *position, NSUInteger idx, BOOL *stop) { + [self insertDesiredPositionsForIndexPath:position]; + }]; + + //Current behavior only inserts repeating ads following the last fixed position in the table, and they will only be inserted + //within the same section as that position. If no fixed positions exist, repeating ads will be placed only in the first section. + if (positioning.repeatingInterval > 1) { + NSInteger lastInsertionSection = [[fixedPositions lastObject] section]; + + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:lastInsertionSection inDictionary:self.desiredOriginalPositions]; + + NSUInteger numberOfFixedAds = [desiredOriginalPositions count]; + NSUInteger numberOfRepeatingAds = kMaximumNumberOfAdsPerStream - numberOfFixedAds; + + NSInteger startingIndex = [fixedPositions lastObject] ? [(NSIndexPath *)[fixedPositions lastObject] row] : -1; + for (NSUInteger repeatingAdIndex = 1; repeatingAdIndex <= numberOfRepeatingAds; repeatingAdIndex++) { + NSInteger adIndexItem = startingIndex + positioning.repeatingInterval * repeatingAdIndex; + [self insertDesiredPositionsForIndexPath:[NSIndexPath indexPathForRow:adIndexItem inSection:lastInsertionSection]]; + } + } +} + +//assumes items are inserted sequentially, beginning to end +- (void)insertDesiredPositionsForIndexPath:(NSIndexPath *)indexPath +{ + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:indexPath.section inDictionary:self.desiredOriginalPositions]; + NSIndexPath *insertionIndexPath = [NSIndexPath indexPathForRow:indexPath.row - [desiredOriginalPositions count] inSection:indexPath.section]; + [desiredOriginalPositions addObject:[insertionIndexPath copy]]; + + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:indexPath.section inDictionary:self.desiredInsertionPositions]; + [desiredInsertionPositions addObject:[insertionIndexPath copy]]; +} + +- (NSUInteger)adjustedNumberOfItems:(NSUInteger)numberOfItems inSection:(NSUInteger)section +{ + if (numberOfItems <= 0) return 0; + + NSIndexPath *pathOfLastItem = [NSIndexPath indexPathForRow:numberOfItems - 1 inSection:section]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.originalAdIndexPaths]; + NSUInteger numberOfAdsBeforeLastItem = [self indexOfIndexPath:pathOfLastItem inSortedArray:originalAdIndexPaths options:NSBinarySearchingInsertionIndex | NSBinarySearchingLastEqual]; + + return numberOfItems + numberOfAdsBeforeLastItem; +} + +- (NSIndexPath *)adjustedIndexPathForOriginalIndexPath:(NSIndexPath *)indexPath +{ + if (!indexPath || indexPath.row == NSNotFound) { + return indexPath; + } + + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:indexPath.section inDictionary:self.originalAdIndexPaths]; + NSUInteger numberOfAdsBeforeIndexPath = [self indexOfIndexPath:indexPath inSortedArray:originalAdIndexPaths options:NSBinarySearchingInsertionIndex | NSBinarySearchingLastEqual]; + + return [NSIndexPath indexPathForRow:indexPath.row + numberOfAdsBeforeIndexPath inSection:indexPath.section]; +} + +- (NSIndexPath *)originalIndexPathForAdjustedIndexPath:(NSIndexPath *)indexPath +{ + if (!indexPath || indexPath.row == NSNotFound) { + return indexPath; + } else if ([self isAdAtAdjustedIndexPath:indexPath]) { + return nil; + } else { + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:indexPath.section inDictionary:self.adjustedAdIndexPaths]; + NSUInteger numberOfAdsBeforeIndexPath = [self indexOfIndexPath:indexPath inSortedArray:adjustedAdIndexPaths options:NSBinarySearchingInsertionIndex]; + return [NSIndexPath indexPathForRow:indexPath.row - numberOfAdsBeforeIndexPath inSection:indexPath.section]; + } +} + +- (NSIndexPath *)nextAdInsertionIndexPathForAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath +{ + if (adjustedIndexPath.section > [self largestSectionIndexContainingAds]) { + return nil; + } + + NSMutableArray *desiredInsertionPositions = [self.desiredInsertionPositions objectForKey:[NSNumber numberWithUnsignedInteger:adjustedIndexPath.section]]; + + NSUInteger index = [self indexOfIndexPath:adjustedIndexPath inSortedArray:desiredInsertionPositions options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + + if (desiredInsertionPositions && (index < [desiredInsertionPositions count])) { + return [desiredInsertionPositions objectAtIndex:index]; + } else { + // Go to the next section. + return [self nextAdInsertionIndexPathForAdjustedIndexPath:[NSIndexPath indexPathForRow:0 inSection:adjustedIndexPath.section+1]]; + } +} + +- (NSIndexPath *)previousAdInsertionIndexPathForAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath +{ + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.desiredInsertionPositions]; + NSUInteger index = [self indexOfIndexPath:adjustedIndexPath inSortedArray:desiredInsertionPositions options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + + if (index > 0) { + return desiredInsertionPositions[index - 1]; + } else { + return nil; + } +} + +- (void)insertAdData:(MPNativeAdData *)data atIndexPath:(NSIndexPath *)adjustedIndexPath +{ + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.desiredInsertionPositions]; + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.adjustedAdIndexPaths]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.originalAdIndexPaths]; + NSMutableArray *adDataObjects = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.adDataObjects]; + + NSUInteger indexInDesiredArrays = [self indexOfIndexPath:adjustedIndexPath inSortedArray:desiredInsertionPositions options:NSBinarySearchingFirstEqual]; + + if (indexInDesiredArrays == NSNotFound) { + MPLogWarn(@"Attempted to insert an ad at position %@, which is not in the desired array.", adjustedIndexPath); + return; + } + + NSIndexPath *originalPosition = desiredOriginalPositions[indexInDesiredArrays]; + NSIndexPath *insertionPosition = desiredInsertionPositions[indexInDesiredArrays]; + + NSUInteger insertionIndex = [self indexOfIndexPath:insertionPosition inSortedArray:adjustedAdIndexPaths options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + + [originalAdIndexPaths insertObject:originalPosition atIndex:insertionIndex]; + [adjustedAdIndexPaths insertObject:insertionPosition atIndex:insertionIndex]; + [adDataObjects insertObject:data atIndex:insertionIndex]; + + [desiredOriginalPositions removeObjectAtIndex:indexInDesiredArrays]; + [desiredInsertionPositions removeObjectAtIndex:indexInDesiredArrays]; + + for (NSUInteger i = insertionIndex + 1; i < [adjustedAdIndexPaths count]; i++) { + NSIndexPath *newIndexPath = adjustedAdIndexPaths[i]; + adjustedAdIndexPaths[i] = [NSIndexPath indexPathForRow:newIndexPath.row + 1 inSection:newIndexPath.section]; + } + + for (NSUInteger j = indexInDesiredArrays; j < [desiredInsertionPositions count]; j++) { + NSIndexPath *newInsertionPosition = desiredInsertionPositions[j]; + desiredInsertionPositions[j] = [NSIndexPath indexPathForRow:newInsertionPosition.row + 1 inSection:newInsertionPosition.section]; + } +} + +- (NSArray *)adjustedAdIndexPathsInAdjustedRange:(NSRange)range inSection:(NSInteger)section +{ + NSMutableArray *adjustedIndexPaths = [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; + + NSIndexSet *indexesOfObjectsInRange = [adjustedIndexPaths indexesOfObjectsPassingTest:^BOOL(NSIndexPath *adjustedIndexPath, NSUInteger idx, BOOL *stop) { + return NSLocationInRange(adjustedIndexPath.row, range); + }]; + + return [adjustedIndexPaths objectsAtIndexes:indexesOfObjectsInRange]; +} + +- (void)clearAdsInAdjustedRange:(NSRange)range inSection:(NSInteger)section +{ + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.originalAdIndexPaths]; + NSMutableArray *adDataObjects = [self positioningArrayForSection:section inDictionary:self.adDataObjects]; + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:section inDictionary:self.desiredInsertionPositions]; + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:section inDictionary:self.desiredOriginalPositions]; + + NSIndexSet *indexesOfObjectsToRemove = [adjustedAdIndexPaths indexesOfObjectsPassingTest:^BOOL(NSIndexPath *adjustedIndexPath, NSUInteger idx, BOOL *stop) { + return NSLocationInRange(adjustedIndexPath.row, range); + }]; + + if ([indexesOfObjectsToRemove count]) { + [indexesOfObjectsToRemove enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger idx, BOOL *stop) { + NSIndexPath *adjustedIndexPathToRemove = adjustedAdIndexPaths[idx]; + NSIndexPath *originalIndexPathToRemove = originalAdIndexPaths[idx]; + NSUInteger insertionIndex = [self indexOfIndexPath:originalIndexPathToRemove inSortedArray:desiredOriginalPositions options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + for (NSInteger i = insertionIndex; i < [desiredInsertionPositions count]; i++) { + NSIndexPath *nextIndexPath = desiredInsertionPositions[i]; + desiredInsertionPositions[i] = [NSIndexPath indexPathForRow:nextIndexPath.row - 1 inSection:nextIndexPath.section]; + } + [desiredOriginalPositions insertObject:originalIndexPathToRemove atIndex:insertionIndex]; + [desiredInsertionPositions insertObject:adjustedIndexPathToRemove atIndex:insertionIndex]; + + }]; + + [adjustedAdIndexPaths removeObjectsAtIndexes:indexesOfObjectsToRemove]; + [originalAdIndexPaths removeObjectsAtIndexes:indexesOfObjectsToRemove]; + [adDataObjects removeObjectsAtIndexes:indexesOfObjectsToRemove]; + } +} + +- (BOOL)isAdAtAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath +{ + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.adjustedAdIndexPaths]; + NSUInteger indexOfIndexPath = [self indexOfIndexPath:adjustedIndexPath inSortedArray:adjustedAdIndexPaths options:NSBinarySearchingFirstEqual]; + + return indexOfIndexPath != NSNotFound; +} + +- (NSArray *)adjustedIndexPathsWithAdsInSection:(NSUInteger)section +{ + return [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; +} + +- (MPNativeAdData *)adDataAtAdjustedIndexPath:(NSIndexPath *)adjustedIndexPath +{ + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.adjustedAdIndexPaths]; + NSMutableArray *adDataObjects = [self positioningArrayForSection:adjustedIndexPath.section inDictionary:self.adDataObjects]; + + NSUInteger indexOfIndexPath = [self indexOfIndexPath:adjustedIndexPath inSortedArray:adjustedAdIndexPaths options:NSBinarySearchingFirstEqual]; + + if (indexOfIndexPath != NSNotFound) { + return adDataObjects[indexOfIndexPath]; + } else { + return nil; + } +} + +- (void)insertSections:(NSIndexSet *)sections +{ + [sections enumerateIndexesUsingBlock:^(NSUInteger insertionSection, BOOL *stop) { + // Explicitly casting indices to NSInteger because we're counting backwards. + NSInteger maxSection = [self largestSectionIndexContainingAds]; + NSInteger signedInsertionSection = insertionSection; + + // We need to shift all the data above the new section up by 1. + for (NSInteger i = maxSection; i >= signedInsertionSection; --i) { + if (self.desiredInsertionPositions[@(i)]) { + [self moveAllPositioningArraysInDictionariesAtSection:i toSection:i+1]; + } + } + }]; +} + +- (void)deleteSections:(NSIndexSet *)sections +{ + [sections enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger deletionSection, BOOL *stop) { + NSUInteger maxSection = [self largestSectionIndexContainingAds]; + + [self clearPositioningArraysInDictionariesAtSection:deletionSection]; + + // We need to shift all the data above the deletionSection down by 1. + for (NSUInteger i = deletionSection; i < maxSection; ++i) { + if (self.desiredInsertionPositions[@(i+1)]) { + [self moveAllPositioningArraysInDictionariesAtSection:i+1 toSection:i]; + } + } + }]; +} + +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection +{ + // Store the data at the section we're moving and retain it so it doesn't get deleted. + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:section inDictionary:self.desiredInsertionPositions]; + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.originalAdIndexPaths]; + NSMutableArray *adDataObjects = [self positioningArrayForSection:section inDictionary:self.adDataObjects]; + + // Delete it from our dictionaries. + [self deleteSections:[NSIndexSet indexSetWithIndex:section]]; + + // Now insert an empty section at the new spot. + [self insertSections:[NSIndexSet indexSetWithIndex:newSection]]; + + // Fill in its data. + self.desiredInsertionPositions[@(newSection)] = desiredInsertionPositions; + self.desiredOriginalPositions[@(newSection)] = desiredOriginalPositions; + self.adjustedAdIndexPaths[@(newSection)] = adjustedAdIndexPaths; + self.originalAdIndexPaths[@(newSection)] = originalAdIndexPaths; + self.adDataObjects[@(newSection)] = adDataObjects; + + [self updateAllSectionsForPositioningArraysAtSection:newSection]; +} + +- (void)insertItemsAtIndexPaths:(NSArray *)originalIndexPaths +{ + originalIndexPaths = [originalIndexPaths sortedArrayUsingSelector:@selector(compare:)]; + + [originalIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *originalIndexPath, NSUInteger idx, BOOL *stop) { + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:originalIndexPath.section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:originalIndexPath.section inDictionary:self.originalAdIndexPaths]; + + NSUInteger insertionIndex = [self indexOfIndexPath:originalIndexPath inSortedArray:desiredOriginalPositions options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + for (NSUInteger i = insertionIndex; i < [desiredOriginalPositions count]; i++) { + [self incrementDesiredIndexPathsAtIndex:i inSection:originalIndexPath.section]; + } + + NSUInteger originalInsertionIndex = [self indexOfIndexPath:originalIndexPath inSortedArray:originalAdIndexPaths options:NSBinarySearchingInsertionIndex | NSBinarySearchingFirstEqual]; + for (NSUInteger i = originalInsertionIndex; i < [originalAdIndexPaths count]; i++) { + [self incrementPlacedIndexPathsAtIndex:i inSection:originalIndexPath.section]; + } + }]; +} + +- (void)deleteItemsAtIndexPaths:(NSArray *)originalIndexPaths +{ + originalIndexPaths = [originalIndexPaths sortedArrayUsingSelector:@selector(compare:)]; + + __block NSUInteger currentNumberOfAdsInSection = 0; + __block NSInteger lastSection = [[originalIndexPaths firstObject] section]; + + [originalIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *originalIndexPath, NSUInteger idx, BOOL *stop) { + // Batch deletions are actually performed one at a time. This requires us to shift up the + // deletion index paths each time a deletion is performed. + // + // For example, batch-deleting the 2nd and 3rd items is not equivalent to incrementally + // deleting the 2nd item and then the 3rd item; the equivalent would be to delete the 2nd + // item each time. + if (originalIndexPath.section != lastSection) { + lastSection = originalIndexPath.section; + currentNumberOfAdsInSection = 0; + } + + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:originalIndexPath.section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:originalIndexPath.section inDictionary:self.originalAdIndexPaths]; + + NSIndexPath *indexPathOfItemToDelete = [NSIndexPath indexPathForRow:originalIndexPath.row - currentNumberOfAdsInSection inSection:originalIndexPath.section]; + + NSUInteger searchIndexInDesired = [self indexOfIndexPath:indexPathOfItemToDelete inSortedArray:desiredOriginalPositions options:NSBinarySearchingInsertionIndex | NSBinarySearchingLastEqual]; + for (NSUInteger i = searchIndexInDesired; i < [desiredOriginalPositions count]; i++) { + [self decrementDesiredIndexPathsAtIndex:i inSection:originalIndexPath.section]; + } + + NSUInteger searchIndexInPlaced = [self indexOfIndexPath:indexPathOfItemToDelete inSortedArray:originalAdIndexPaths options:NSBinarySearchingInsertionIndex | NSBinarySearchingLastEqual]; + for (NSUInteger i = searchIndexInPlaced; i < [originalAdIndexPaths count]; i++) { + [self decrementPlacedIndexPathsAtIndex:i inSection:originalIndexPath.section]; + } + + currentNumberOfAdsInSection++; + }]; +} + +- (void)moveItemAtIndexPath:(NSIndexPath *)originalIndexPath toIndexPath:(NSIndexPath *)newIndexPath +{ + [self deleteItemsAtIndexPaths:@[originalIndexPath]]; + [self insertItemsAtIndexPaths:@[newIndexPath]]; +} + +#pragma mark - NSIndexPath array helpers + +- (NSUInteger)indexOfIndexPath:(NSIndexPath *)indexPath inSortedArray:(NSArray *)array options:(NSBinarySearchingOptions)options +{ + if (!indexPath || indexPath.row == NSNotFound) { + return NSNotFound; + } + return [array indexOfObject:indexPath inSortedRange:NSMakeRange(0, [array count]) options:options usingComparator:^NSComparisonResult(NSIndexPath *path1, NSIndexPath *path2) { + return [path1 compare:path2]; + }]; +} + +- (void)incrementDesiredIndexPathsAtIndex:(NSUInteger)index inSection:(NSUInteger)section +{ + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:section inDictionary:self.desiredInsertionPositions]; + + NSIndexPath *currentDesiredOriginalPosition = desiredOriginalPositions[index]; + NSIndexPath *newDesiredOriginalPosition = [NSIndexPath indexPathForRow:currentDesiredOriginalPosition.row + 1 inSection:currentDesiredOriginalPosition.section]; + desiredOriginalPositions[index] = newDesiredOriginalPosition; + + NSIndexPath *currentDesiredInsertionPosition = desiredInsertionPositions[index]; + NSIndexPath *newDesiredInsertionPosition = [NSIndexPath indexPathForRow:currentDesiredInsertionPosition.row + 1 inSection:currentDesiredInsertionPosition.section]; + desiredInsertionPositions[index] = newDesiredInsertionPosition; +} + +- (void)incrementPlacedIndexPathsAtIndex:(NSUInteger)index inSection:(NSUInteger)section +{ + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.originalAdIndexPaths]; + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; + + NSIndexPath *currentOriginalIndexPath = originalAdIndexPaths[index]; + NSIndexPath *newOriginalIndexPath = [NSIndexPath indexPathForRow:currentOriginalIndexPath.row + 1 inSection:currentOriginalIndexPath.section]; + originalAdIndexPaths[index] = newOriginalIndexPath; + + NSIndexPath *currentAdjustedIndexPath = adjustedAdIndexPaths[index]; + NSIndexPath *newAdjustedIndexPath = [NSIndexPath indexPathForRow:currentAdjustedIndexPath.row + 1 inSection:currentAdjustedIndexPath.section]; + adjustedAdIndexPaths[index] = newAdjustedIndexPath; +} + +- (void)decrementDesiredIndexPathsAtIndex:(NSUInteger)index inSection:(NSUInteger)section +{ + NSMutableArray *desiredOriginalPositions = [self positioningArrayForSection:section inDictionary:self.desiredOriginalPositions]; + NSMutableArray *desiredInsertionPositions = [self positioningArrayForSection:section inDictionary:self.desiredInsertionPositions]; + + NSIndexPath *currentDesiredOriginalPosition = desiredOriginalPositions[index]; + NSIndexPath *newDesiredOriginalPosition = [NSIndexPath indexPathForRow:currentDesiredOriginalPosition.row - 1 inSection:currentDesiredOriginalPosition.section]; + desiredOriginalPositions[index] = newDesiredOriginalPosition; + + NSIndexPath *currentDesiredInsertionPosition = desiredInsertionPositions[index]; + NSIndexPath *newDesiredInsertionPosition = [NSIndexPath indexPathForRow:currentDesiredInsertionPosition.row - 1 inSection:currentDesiredInsertionPosition.section]; + desiredInsertionPositions[index] = newDesiredInsertionPosition; +} + +- (void)decrementPlacedIndexPathsAtIndex:(NSUInteger)index inSection:(NSUInteger)section +{ + NSMutableArray *originalAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.originalAdIndexPaths]; + NSMutableArray *adjustedAdIndexPaths = [self positioningArrayForSection:section inDictionary:self.adjustedAdIndexPaths]; + + NSIndexPath *currentOriginalIndexPath = originalAdIndexPaths[index]; + NSIndexPath *newOriginalIndexPath = [NSIndexPath indexPathForRow:currentOriginalIndexPath.row - 1 inSection:currentOriginalIndexPath.section]; + originalAdIndexPaths[index] = newOriginalIndexPath; + + NSIndexPath *currentAdjustedIndexPath = adjustedAdIndexPaths[index]; + NSIndexPath *newAdjustedIndexPath = [NSIndexPath indexPathForRow:currentAdjustedIndexPath.row - 1 inSection:currentAdjustedIndexPath.section]; + adjustedAdIndexPaths[index] = newAdjustedIndexPath; +} + +#pragma mark - Section modification helpers + +- (NSUInteger)largestSectionIndexContainingAds +{ + return [[[self.desiredInsertionPositions allKeys] valueForKeyPath:@"@max.unsignedIntValue"] unsignedIntegerValue]; +} + +// Does not update the index path sections. Call updateSectionForPositioningArray to update the sections in the index paths. +- (void)copyPositioningArrayInDictionary:(NSMutableDictionary *)dict atSection:(NSUInteger)atSection toSection:(NSUInteger)toSection +{ + if (dict[@(atSection)]) { + dict[@(toSection)] = dict[@(atSection)]; + } +} + +- (void)clearPositioningArraysInDictionariesAtSection:(NSUInteger)section +{ + [self.desiredInsertionPositions removeObjectForKey:@(section)]; + [self.desiredOriginalPositions removeObjectForKey:@(section)]; + [self.adjustedAdIndexPaths removeObjectForKey:@(section)]; + [self.originalAdIndexPaths removeObjectForKey:@(section)]; + [self.adDataObjects removeObjectForKey:@(section)]; +} + +// Moves the positioning arrays to the correct spots in the dictionaries and also updates the sections for all the index paths. +- (void)moveAllPositioningArraysInDictionariesAtSection:(NSUInteger)atSection toSection:(NSUInteger)toSection +{ + [self copyPositioningArrayInDictionary:self.desiredInsertionPositions atSection:atSection toSection:toSection]; + [self copyPositioningArrayInDictionary:self.desiredOriginalPositions atSection:atSection toSection:toSection]; + [self copyPositioningArrayInDictionary:self.adjustedAdIndexPaths atSection:atSection toSection:toSection]; + [self copyPositioningArrayInDictionary:self.originalAdIndexPaths atSection:atSection toSection:toSection]; + [self copyPositioningArrayInDictionary:self.adDataObjects atSection:atSection toSection:toSection]; + + [self updateAllSectionsForPositioningArraysAtSection:toSection]; + + [self clearPositioningArraysInDictionariesAtSection:atSection]; +} + +- (void)updateAllSectionsForPositioningArraysAtSection:(NSUInteger)section +{ + [self updateSectionForPositioningArray:self.desiredInsertionPositions[@(section)] toSection:section]; + [self updateSectionForPositioningArray:self.desiredOriginalPositions[@(section)] toSection:section]; + [self updateSectionForPositioningArray:self.adjustedAdIndexPaths[@(section)] toSection:section]; + [self updateSectionForPositioningArray:self.originalAdIndexPaths[@(section)] toSection:section]; +} + +- (void)updateSectionForPositioningArray:(NSMutableArray *)positioningArray toSection:(NSUInteger)section +{ + for (NSUInteger i = 0; i < positioningArray.count; ++i) { + NSIndexPath *indexPath = positioningArray[i]; + + NSUInteger indices[] = { section, [indexPath indexAtPosition:1] }; + positioningArray[i] = [NSIndexPath indexPathWithIndexes:indices length:2]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.h new file mode 100644 index 000000000..e5f0ce823 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.h @@ -0,0 +1,272 @@ +// +// MPStreamAdPlacer.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MPClientAdPositioning.h" + +@protocol MPStreamAdPlacerDelegate; +@protocol MPNativeAdRendering; +@class MPNativeAdRequestTargeting; +@class MPNativeAd; + +/** + * The `MPStreamAdPlacer` class allows you to retrieve native ads from the MoPub ad server and + * place them into any custom UI component that represents a stream of content. It does not actually + * present or insert any ads on its own; you must provide a delegate conforming to the + * `MPStreamAdPlacerDelegate` protocol to handle ad insertions. + * + * @warning **Note:** If you are inserting ads into a `UITableView` or `UICollectionView`, you + * should first consider whether the `UITableViewAdPlacer` or `UICollectionViewAdPlacer` classes are + * sufficient for your use case before choosing to use this class. + * + * @discussion Your app's first responsibility when creating a stream ad placer is to communicate + * the state of your stream. Specifically, you must provide it with the count of the + * original content items in your stream using -setItemCount:forSection:, so that it can determine + * where and how many ads should appear. Additionally, you must also make sure to notify the ad + * placer of any insertions, deletions, or rearrangement of content items or sections. + * + * Use the -loadAdsForAdUnitID: method to tell the stream ad placer to begin retrieving ads. In + * order to optimize performance, this call may not immediately result in the ad placer asking its + * delegate to insert any ads. Instead, the ad placer decides whether to insert ads by determining + * what content items are currently visible. This means that your delegate may be intermittently + * informed about new insertions, and is meant to minimize situations in which ads are requested for + * positions in the stream that have a low likelihood of visibility. + * + * ### Responding to Insertions and Rendering Ads + * + * Your delegate should respond to insertion callbacks by updating your stream's data source so + * that it knows to render an ad (rather than an original content item) at the given index path. + * Note that the implementation may vary depending on the design of your data source. + * + * Use -renderAdAtIndexPath:inView: to populate a view with the contents of an ad. + */ + +@interface MPStreamAdPlacer : NSObject + +/** + * An array of `NSIndexPath` objects representing the positions of items that are currently visible + * on the screen. + * + * The stream ad placer uses the contents of this array to determine where ads should be inserted. + * It calculates an on-screen range and uses a small look-ahead to place ads where the user is + * likely to view them. + */ +@property (nonatomic, strong) NSArray *visibleIndexPaths; + +@property (nonatomic, readonly) NSArray *rendererConfigurations; +@property (nonatomic, weak) UIViewController *viewController; +@property (nonatomic, weak) id delegate; +@property (nonatomic, readonly, copy) MPAdPositioning *adPositioning; + +/** + * Creates and returns a new ad placer that can display ads in a stream. + * + * @param controller The view controller which should be used to present modal content. + * @param positioning The positioning object that specifies where ads should be shown in the stream. + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. You should pass in configurations that can render any ad type that + * may be displayed for the given ad unit. + * + */ ++ (instancetype)placerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations; + +/** + * Lets the ad placer know of how many items are in a section. This allows the ad placer + * to place ads more effectively around its visible range. + * + * @param count How many items are in the section. + * @param section The section that the ad placer is recording the count for. + */ +- (void)setItemCount:(NSUInteger)count forSection:(NSInteger)section; + +/** + * Uses the corresponding rendering class to render content in the view. + * + * @param indexPath The index path of the cell you want to render. + * @param view The view you want to render your contents into. + */ +- (void)renderAdAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view; + +/** + * Get the size of the ad at the index path. + * + * @param indexPath Retrieve the size at indexPath. + * @param maxWidth The maximum acceptable width for the view. + * + * @return The size of the ad at indexPath. + */ +- (CGSize)sizeForAdAtIndexPath:(NSIndexPath *)indexPath withMaximumWidth:(CGFloat)maxWidth; + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID. + * + * @param adUnitID A string representing a MoPub ad unit ID. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID; + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID and targeting parameters. + * + * @param adUnitID A string representing a MoPub ad unit ID. + * @param targeting An object containing targeting information, such as geolocation data. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting; + +/** + * Returns whether an ad is ready to be displayed at the indexPath. + * + * @param indexPath The index path to examine for ad readiness. + */ +- (BOOL)isAdAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Returns the number of items in the given section of the stream, including any ads that have been + * inserted. + * + * @param numberOfItems The number of content items. + * @param section The section the method will retrieve the adjusted number of items for. + */ +- (NSUInteger)adjustedNumberOfItems:(NSUInteger)numberOfItems inSection:(NSUInteger)section; + +/** + * Returns the index path representing the location of an item after accounting for ads that have + * been inserted into the stream. + * + * @param indexPath An index path object identifying the original location of a content item, before + * any ads have been inserted into the stream. + */ +- (NSIndexPath *)adjustedIndexPathForOriginalIndexPath:(NSIndexPath *)indexPath; + +/** + * Asks for the original position of a content item, given its position in the stream after ads + * have been inserted. + * + * If the specified index path does not identify a content item, but rather an ad, this method + * will return nil. + * + * @param indexPath An index path object identifying an item in the stream, after ads have been + * inserted. + */ +- (NSIndexPath *)originalIndexPathForAdjustedIndexPath:(NSIndexPath *)indexPath; + +/** + * Returns the index paths representing the locations of items after accounting for ads that have + * been inserted into the stream. + * + * @param indexPaths An array of index path objects each identifying the original location of a + * content item, before any ads have been inserted into the stream. + */ +- (NSArray *)adjustedIndexPathsForOriginalIndexPaths:(NSArray *)indexPaths; + +/** + * Retrieves the original positions of content items, given their positions in the stream after ads + * have been inserted. + * + * If a specified index path does not identify a content item, but rather an ad, it will not be + * included in the result. + * + * @param indexPaths An array of index path objects each identifying an item in the stream, after + * ads have been inserted. + */ +- (NSArray *)originalIndexPathsForAdjustedIndexPaths:(NSArray *)indexPaths; + +/** @name Notifying the Ad Placer of Content Updates */ + +/** + * Tells the ad placer that content items have been inserted at the specified index paths. + * + * This method allows the ad placer to adjust its ad positions correctly. + * + * @param originalIndexPaths An array of NSIndexPath objects that identify positions where content + * has been inserted. + */ +- (void)insertItemsAtIndexPaths:(NSArray *)originalIndexPaths; + +/** + * Tells the ad placer that content items have been deleted at the specified index paths. + * + * This method allows the ad placer to adjust its ad positions correctly, and remove from the + * stream if necessary + * + * @param originalIndexPaths An array of NSIndexPath objects that identify positions where content + * has been deleted. +*/ +- (void)deleteItemsAtIndexPaths:(NSArray *)originalIndexPaths; + +/** + * Tells the ad placer that a content item has moved from one index path to another. + * + * This method allows the ad placer to adjust its ad positions correctly. + * + * @param fromIndexPath The index path identifying the original location of the item. + * @param toIndexPath The destination index path for the item. + */ +- (void)moveItemAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath; + +/** + * Tells the ad placer that sections have been inserted at the specified indices. + * + * This method allows the ad placer to adjust its ad positions correctly. + * + * @param sections An NSIndexSet that identifies the positions where sections + * have been inserted. + */ +- (void)insertSections:(NSIndexSet *)sections; + +/** + * Tells the ad placer that sections have been deleted at the specified indices. + * + * This method allows the ad placer to adjust its ad positions correctly. + * + * @param sections An NSIndexSet that identifies the positions where sections + * have been deleted. + */ +- (void)deleteSections:(NSIndexSet *)sections; + +/** + * Tells the ad placer that a section has moved from one index to another. + * + * This method allows the ad placer to adjust its ad positions correctly. + * + * @param section The index identifying the original location of the section. + * @param newSection The destination index for the section. + */ +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol MPStreamAdPlacerDelegate + +@optional +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didLoadAdAtIndexPath:(NSIndexPath *)indexPath; +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didRemoveAdsAtIndexPaths:(NSArray *)indexPaths; + +/* + * This method is called when a native ad, placed by the stream ad placer, will present a modal view controller. + * + * @param placer The stream ad placer that contains the ad displaying the modal. + */ +- (void)nativeAdWillPresentModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer; + +/* + * This method is called when a native ad, placed by the stream ad placer, did dismiss its modal view controller. + * + * @param placer The stream ad placer that contains the ad that dismissed the modal. + */ +- (void)nativeAdDidDismissModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer; + +/* + * This method is called when a native ad, placed by the stream ad placer, will cause the app to background due to user interaction with the ad. + * + * @param placer The stream ad placer that contains the ad causing the app to background. + */ +- (void)nativeAdWillLeaveApplicationFromStreamAdPlacer:(MPStreamAdPlacer *)adPlacer; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.m new file mode 100644 index 000000000..d68786fbb --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPStreamAdPlacer.m @@ -0,0 +1,581 @@ +// +// MPStreamAdPlacer.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPAdPositioning.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPNativeAd+Internal.h" +#import "MPNativeAdData.h" +#import "MPNativeAdDelegate.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPNativeAdRendererConstants.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdSource.h" +#import "MPNativePositionSource.h" +#import "MPNativeView.h" +#import "MPServerAdPositioning.h" +#import "MPStaticNativeAdRenderer.h" +#import "MPStreamAdPlacementData.h" +#import "MPStreamAdPlacer.h" + +static NSInteger const kAdInsertionLookAheadAmount = 3; +static const NSUInteger kIndexPathItemIndex = 1; + +@protocol MPNativeAdRenderer; + +@interface MPStreamAdPlacer () + +@property (nonatomic, strong) NSArray *rendererConfigurations; +@property (nonatomic, strong) MPNativeAdSource *adSource; +@property (nonatomic, strong) MPNativePositionSource *positioningSource; +@property (nonatomic, copy) MPAdPositioning *adPositioning; +@property (nonatomic, strong) MPStreamAdPlacementData *adPlacementData; +@property (nonatomic, copy) NSString *adUnitID; +@property (nonatomic, strong) NSMutableDictionary *sectionCounts; +@property (nonatomic, strong) NSIndexPath *topConsideredIndexPath; +@property (nonatomic, strong) NSIndexPath *bottomConsideredIndexPath; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPStreamAdPlacer + ++ (instancetype)placerWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + MPStreamAdPlacer *placer = [[self alloc] initWithViewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; + return placer; +} + +- (instancetype)initWithViewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + NSAssert(controller != nil, @"A stream ad placer cannot be instantiated with a nil view controller."); + NSAssert(positioning != nil, @"A stream ad placer cannot be instantiated with a nil positioning object."); + + for (id rendererConfiguration in rendererConfigurations) { + NSAssert([rendererConfiguration isKindOfClass:[MPNativeAdRendererConfiguration class]], @"A stream ad placer must be instantiated with rendererConfigurations that are of type MPNativeAdRendererConfiguration."); + } + + self = [super init]; + if (self) { + _viewController = controller; + _adPositioning = [positioning copy]; + _adSource = [[MPInstanceProvider sharedProvider] buildNativeAdSourceWithDelegate:self]; + _adPlacementData = [[MPInstanceProvider sharedProvider] buildStreamAdPlacementDataWithPositioning:_adPositioning]; + _rendererConfigurations = rendererConfigurations; + _sectionCounts = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)dealloc +{ + [_positioningSource cancel]; +} + +- (void)setVisibleIndexPaths:(NSArray *)visibleIndexPaths +{ + if (visibleIndexPaths.count == 0) { + _visibleIndexPaths = nil; + self.topConsideredIndexPath = nil; + self.bottomConsideredIndexPath = nil; + return; + } + + _visibleIndexPaths = [visibleIndexPaths sortedArrayUsingSelector:@selector(compare:)]; + self.topConsideredIndexPath = self.visibleIndexPaths.firstObject; + self.bottomConsideredIndexPath = [self furthestValidIndexPathAfterIndexPath:self.visibleIndexPaths.lastObject withinDistance:visibleIndexPaths.count + kAdInsertionLookAheadAmount]; + + [self fillAdsInConsideredRange]; +} + +- (void)setItemCount:(NSUInteger)count forSection:(NSInteger)section +{ + self.sectionCounts[@(section)] = @(count); +} + +- (void)renderAdAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view +{ + MPNativeAdData *adData = [self.adPlacementData adDataAtAdjustedIndexPath:indexPath]; + + if (!adData) { + MPLogError(@"-renderAdAtIndexPath: An ad does not exist at indexPath"); + return; + } + + // Remove any old native ad views from the view prior to adding the new ad view as a sub view. + for (UIView *subview in view.subviews) { + if ([subview isKindOfClass:[MPNativeView class]]) { + [subview removeFromSuperview]; + } + } + + [view addSubview:[adData.ad retrieveAdViewWithError:nil]]; + + CGSize adSize = [self sizeForAd:adData.ad withMaximumWidth:view.bounds.size.width andIndexPath:indexPath]; + [adData.ad updateAdViewSize:adSize]; +} + +- (CGSize)sizeForAdAtIndexPath:(NSIndexPath *)indexPath withMaximumWidth:(CGFloat)maxWidth +{ + MPNativeAdData *adData = [self.adPlacementData adDataAtAdjustedIndexPath:indexPath]; + + // Tell the ad that it should resize the native ad view. + CGSize adSize = [self sizeForAd:adData.ad withMaximumWidth:maxWidth andIndexPath:indexPath]; + [adData.ad updateAdViewSize:adSize]; + + return adSize; +} + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID +{ + [self loadAdsForAdUnitID:adUnitID targeting:nil]; +} + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting +{ + self.adUnitID = adUnitID; + + // Gather all the index paths with ads so we can notify the delegate that ads were removed. + NSMutableArray *adIndexPaths = [NSMutableArray array]; + for (NSNumber *section in self.sectionCounts) { + NSInteger intSection = [section unsignedIntegerValue]; + [adIndexPaths addObjectsFromArray:[self.adPlacementData adjustedIndexPathsWithAdsInSection:intSection]]; + } + + if (!adUnitID) { + // We need some placement data. Pass nil to it so it doesn't do any unnecessary work. + self.adPlacementData = [[MPInstanceProvider sharedProvider] buildStreamAdPlacementDataWithPositioning:nil]; + } else if ([self.adPositioning isKindOfClass:[MPClientAdPositioning class]]) { + // Reset to a placement data that has "desired" ads but not "placed" ones. + self.adPlacementData = [[MPInstanceProvider sharedProvider] buildStreamAdPlacementDataWithPositioning:self.adPositioning]; + } else if ([self.adPositioning isKindOfClass:[MPServerAdPositioning class]]) { + // Reset to a placement data that has no "desired" ads at all. + self.adPlacementData = [[MPInstanceProvider sharedProvider] buildStreamAdPlacementDataWithPositioning:nil]; + + // Get positioning information from the server. + self.positioningSource = [[MPInstanceProvider sharedProvider] buildNativePositioningSource]; + __typeof__(self) __weak weakSelf = self; + [self.positioningSource loadPositionsWithAdUnitIdentifier:self.adUnitID completionHandler:^(MPAdPositioning *positioning, NSError *error) { + __typeof__(self) strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + if (error) { + if ([error code] == MPNativePositionSourceEmptyResponse) { + MPLogError(@"ERROR: Ad placer cannot show any ads because ad positions have " + @"not been configured for your ad unit %@. You must assign positions " + @"by editing the ad unit's settings on the MoPub website.", + strongSelf.adUnitID); + } else { + MPLogError(@"ERROR: Ad placer failed to get positions from the ad server for " + @"ad unit ID %@. Error: %@", strongSelf.adUnitID, error); + } + } else { + strongSelf.adPlacementData = [[MPInstanceProvider sharedProvider] buildStreamAdPlacementDataWithPositioning:positioning]; + } + }]; + } + + if (adIndexPaths.count > 0) { + [self.delegate adPlacer:self didRemoveAdsAtIndexPaths:adIndexPaths]; + } + + if (!adUnitID) { + MPLogError(@"Ad placer cannot load ads with a nil ad unit ID."); + return; + } + + [self.adSource loadAdsWithAdUnitIdentifier:adUnitID rendererConfigurations:self.rendererConfigurations andTargeting:targeting]; +} + +- (BOOL)isAdAtIndexPath:(NSIndexPath *)indexPath +{ + return [self.adPlacementData isAdAtAdjustedIndexPath:indexPath]; +} + +- (NSUInteger)adjustedNumberOfItems:(NSUInteger)numberOfItems inSection:(NSUInteger)section +{ + return [self.adPlacementData adjustedNumberOfItems:numberOfItems inSection:section]; +} + +- (NSIndexPath *)adjustedIndexPathForOriginalIndexPath:(NSIndexPath *)indexPath +{ + return [self.adPlacementData adjustedIndexPathForOriginalIndexPath:indexPath]; +} + +- (NSIndexPath *)originalIndexPathForAdjustedIndexPath:(NSIndexPath *)indexPath +{ + return [self.adPlacementData originalIndexPathForAdjustedIndexPath:indexPath]; +} + +- (NSArray *)adjustedIndexPathsForOriginalIndexPaths:(NSArray *)indexPaths +{ + NSMutableArray *adjustedIndexPaths = [NSMutableArray array]; + for (NSIndexPath *indexPath in indexPaths) { + [adjustedIndexPaths addObject:[self adjustedIndexPathForOriginalIndexPath:indexPath]]; + } + return [adjustedIndexPaths copy]; +} + +- (NSArray *)originalIndexPathsForAdjustedIndexPaths:(NSArray *)indexPaths +{ + NSMutableArray *originalIndexPaths = [NSMutableArray array]; + for (NSIndexPath *indexPath in indexPaths) { + NSIndexPath *originalIndexPath = [self originalIndexPathForAdjustedIndexPath:indexPath]; + if (originalIndexPath) { + [originalIndexPaths addObject:originalIndexPath]; + } + } + return [originalIndexPaths copy]; +} + +- (void)insertItemsAtIndexPaths:(NSArray *)originalIndexPaths +{ + [self.adPlacementData insertItemsAtIndexPaths:originalIndexPaths]; + [originalIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *originalIndexPath, NSUInteger idx, BOOL *stop) { + NSInteger section = originalIndexPath.section; + [self setItemCount:[[self.sectionCounts objectForKey:@(section)] integerValue] + 1 forSection:section]; + }]; +} + +- (void)deleteItemsAtIndexPaths:(NSArray *)originalIndexPaths +{ + originalIndexPaths = [originalIndexPaths sortedArrayUsingSelector:@selector(compare:)]; + NSMutableSet *activeSections = [NSMutableSet setWithCapacity:[originalIndexPaths count]]; + [originalIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { + [activeSections addObject:[NSNumber numberWithInteger:indexPath.section]]; + }]; + + NSMutableArray *removedIndexPaths = [NSMutableArray array]; + [activeSections enumerateObjectsUsingBlock:^(NSNumber *section, BOOL *stop) { + NSArray *originalIndexPathsInSection = [originalIndexPaths filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"section = %@", section]]; + NSRange deleteRange = [self rangeToDeleteInSection:section forOriginalContentIndexPaths:originalIndexPathsInSection]; + + NSArray *indexPathsToDelete = [self.adPlacementData adjustedAdIndexPathsInAdjustedRange:deleteRange inSection:[section integerValue]]; + [removedIndexPaths addObjectsFromArray:indexPathsToDelete]; + [self.adPlacementData clearAdsInAdjustedRange:deleteRange inSection:[section integerValue]]; + }]; + + [self.adPlacementData deleteItemsAtIndexPaths:originalIndexPaths]; + + [originalIndexPaths enumerateObjectsUsingBlock:^(NSIndexPath *originalIndexPath, NSUInteger idx, BOOL *stop) { + NSInteger section = originalIndexPath.section; + [self setItemCount:[[self.sectionCounts objectForKey:@(section)] integerValue] - 1 forSection:section]; + }]; + + if ([removedIndexPaths count]) { + [self.delegate adPlacer:self didRemoveAdsAtIndexPaths:removedIndexPaths]; + } +} + +- (void)moveItemAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath +{ + [self.adPlacementData moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath]; +} + +- (void)insertSections:(NSIndexSet *)sections +{ + [self.adPlacementData insertSections:sections]; + [self insertItemCountSections:sections]; +} + +- (void)deleteSections:(NSIndexSet *)sections +{ + [self.adPlacementData deleteSections:sections]; + [self deleteItemCountSections:sections]; +} + +- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection +{ + [self.adPlacementData moveSection:section toSection:newSection]; + + NSUInteger originalSectionCount = [self.sectionCounts[@(section)] unsignedIntegerValue]; + + [self deleteItemCountSections:[NSIndexSet indexSetWithIndex:section]]; + [self insertItemCountSections:[NSIndexSet indexSetWithIndex:newSection]]; + + [self setItemCount:originalSectionCount forSection:newSection]; +} + +#pragma mark - Private + +- (void)insertItemCountSections:(NSIndexSet *)sections +{ + [sections enumerateIndexesUsingBlock:^(NSUInteger insertionSection, BOOL *stop) { + // Explicitly casting indices to NSInteger because we're counting backwards. + NSInteger maxSection = [[[self.sectionCounts allKeys] valueForKeyPath:@"@max.unsignedIntValue"] unsignedIntegerValue]; + NSInteger signedInsertionSection = insertionSection; + + // We need to shift all the data above the new section up by 1. This assumes each section has a count (as each section should). + for (NSInteger i = maxSection; i >= signedInsertionSection; --i) { + NSUInteger currentCount = [self.sectionCounts[@(i)] unsignedIntegerValue]; + [self setItemCount:currentCount forSection:i+1]; + } + + // Setting the count to 0 isn't exactly correct, but it will be updated correctly when numberOfItems/Rows is called onthe data source. + [self setItemCount:0 forSection:insertionSection]; + }]; +} + +- (void)deleteItemCountSections:(NSIndexSet *)sections +{ + [sections enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger deletionSection, BOOL *stop) { + NSUInteger maxSection = [[[self.sectionCounts allKeys] valueForKeyPath:@"@max.unsignedIntValue"] unsignedIntegerValue]; + + // We need to shift all the data above the deletionSection down by 1. This assumes each section has a count (as each section should). + for (NSUInteger i = deletionSection; i <= maxSection; ++i) { + NSUInteger nextCount = [self.sectionCounts[@(i+1)] unsignedIntegerValue]; + [self setItemCount:nextCount forSection:i]; + } + + [self.sectionCounts removeObjectForKey:@(maxSection)]; + }]; +} + +/* + * Returns the range to consider removing cells from the datasource for a given section. + * + * We want to prevent a state where ads are present after the last remaining content item. + * In order to do this, we need to find the range between the last remaining content item + * (after deletion occurs) and last item being deleted. If the end of this range includes + * the (current) last remaining item, we should delete all ads within the range, since they + * would otherwise be "trailing" ads. + * + * The range returned from this method will not include any ads that appear before the + * last remaining content item, because all we care about is preventing trailing ads. + */ +- (NSRange)rangeToDeleteInSection:(NSNumber *)section forOriginalContentIndexPaths:(NSArray *)originalContentIndexPaths +{ + NSRange rangeToDelete = NSMakeRange(0, 0); + NSInteger sectionCount = [self.sectionCounts[section] integerValue]; + //In order to remove trailing ads, we need to find the first index path of the last contiguous block of content items + //That we're deleting. Using the item of this index path, we can create a range in which to remove ads from the datasource. + __block NSIndexPath *firstIndexPathOfLastContiguousContentItemBlock = [originalContentIndexPaths lastObject]; + + //determines if the last content item is being deleted. If not, no ads will be deleted. + if (sectionCount == firstIndexPathOfLastContiguousContentItemBlock.row + 1) { + + //Traverses (in reverse) the content index paths being deleted until it reaches the beginning of the section (all items being deleted), or a gap in that block. + [[[originalContentIndexPaths reverseObjectEnumerator] allObjects] enumerateObjectsUsingBlock:^(NSIndexPath *contentPath, NSUInteger idx, BOOL *stop) { + if (idx > 0 && contentPath.row == firstIndexPathOfLastContiguousContentItemBlock.row - 1) { + firstIndexPathOfLastContiguousContentItemBlock = contentPath; + } + }]; + + NSInteger sectionTotal = [self.adPlacementData adjustedNumberOfItems:sectionCount inSection:[section integerValue]]; + + if (firstIndexPathOfLastContiguousContentItemBlock.row == 0) { + rangeToDelete = NSMakeRange(0, sectionTotal); + } else { + //Last content item *not* being deleted - will be the new end of the section. + NSIndexPath *lastRemainingContentIndexPath = [NSIndexPath indexPathForRow:firstIndexPathOfLastContiguousContentItemBlock.row - 1 inSection:firstIndexPathOfLastContiguousContentItemBlock.section]; + NSIndexPath *adjustedLastContent = [self.adPlacementData adjustedIndexPathForOriginalIndexPath:lastRemainingContentIndexPath]; + rangeToDelete = NSMakeRange(adjustedLastContent.row, sectionTotal - adjustedLastContent.row); + } + } + return rangeToDelete; +} + +- (NSIndexPath *)furthestValidIndexPathAfterIndexPath:(NSIndexPath *)startingPath withinDistance:(NSUInteger)numberOfItems +{ + NSUInteger section = [startingPath indexAtPosition:0]; + NSInteger itemIndex = [startingPath indexAtPosition:1]; + + NSNumber *sectionCountNumber = self.sectionCounts[@(section)]; + NSUInteger sectionItemCount = [sectionCountNumber unsignedIntegerValue]; + NSUInteger itemsPassed = 0; + while (itemsPassed < numberOfItems) { + if (sectionItemCount > (itemIndex + 1)) { + ++itemIndex; + ++itemsPassed; + } else { + // Ignore 0 sized sections. + NSUInteger trySection = section; + do { + ++trySection; + sectionCountNumber = self.sectionCounts[@(trySection)]; + sectionItemCount = [sectionCountNumber unsignedIntegerValue]; + } while (sectionCountNumber && sectionItemCount == 0); + + // We can exit and use the last known valid index path if we can't get a section count number. + if (!sectionCountNumber) { + break; + } else { + // Otherwise we move onto the next non-zero section. + section = trySection; + ++itemsPassed; + itemIndex = 0; + } + } + } + + NSUInteger indices[] = {section, itemIndex}; + return [NSIndexPath indexPathWithIndexes:indices length:2]; +} + +- (NSIndexPath *)earliestValidIndexPathBeforeIndexPath:(NSIndexPath *)startingPath withinDistance:(NSUInteger)numberOfItems +{ + NSUInteger section = [startingPath indexAtPosition:0]; + NSInteger itemIndex = [startingPath indexAtPosition:1]; + + NSUInteger itemsPassed = 0; + while (itemsPassed < numberOfItems) { + if ((itemIndex - 1) >= 0) { + --itemIndex; + ++itemsPassed; + } else { + // Ignore 0 sized sections. + NSNumber *sectionCountNumber; + NSUInteger trySection = section; + NSUInteger trySectionCount; + + do { + --trySection; + sectionCountNumber = self.sectionCounts[@(trySection)]; + trySectionCount = [sectionCountNumber unsignedIntegerValue]; + } while (sectionCountNumber && trySectionCount == 0); + + // Exit and use the last known valid index path. + if (!sectionCountNumber) { + break; + } else { + // Otherwise we move backwards. + section = trySection; + itemIndex = trySectionCount - 1; + ++itemsPassed; + } + } + } + + NSUInteger indices[] = {section, itemIndex}; + return [NSIndexPath indexPathWithIndexes:indices length:2]; +} + +// Determines whether or not insertionPath is close enough to the visible cells to place an ad at insertionPath. +- (BOOL)shouldPlaceAdAtIndexPath:(NSIndexPath *)insertionPath +{ + if (!self.topConsideredIndexPath || !self.bottomConsideredIndexPath || !insertionPath) { + return NO; + } + + // We need to make sure the insertionPath is actually at a valid index in a section by confirming the index is less than the count in the section. + NSUInteger originalSectionCount = [self.sectionCounts[@(insertionPath.section)] unsignedIntegerValue]; + NSUInteger adjustedSectionCount = [self adjustedNumberOfItems:originalSectionCount inSection:insertionPath.section]; + + if ([insertionPath indexAtPosition:kIndexPathItemIndex] >= adjustedSectionCount) { + return NO; + } + + NSIndexPath *topAdjustedIndexPath = [self adjustedIndexPathForOriginalIndexPath:self.topConsideredIndexPath]; + NSIndexPath *bottomAdjustedIndexPath = [self adjustedIndexPathForOriginalIndexPath:self.bottomConsideredIndexPath]; + + return ([topAdjustedIndexPath compare:insertionPath] != NSOrderedDescending) && ([bottomAdjustedIndexPath compare:insertionPath] != NSOrderedAscending); +} + +- (MPNativeAdData *)retrieveAdDataForInsertionPath:(NSIndexPath *)insertionPath +{ + MPNativeAd *adObject = [self.adSource dequeueAdForAdUnitIdentifier:self.adUnitID]; + + if (!adObject) { + return nil; + } + + MPNativeAdData *adData = [[MPNativeAdData alloc] init]; + adData.adUnitID = self.adUnitID; + adData.ad = adObject; + + return adData; +} + +- (void)fillAdsInConsideredRange +{ + if (!self.topConsideredIndexPath || !self.bottomConsideredIndexPath) { + return; + } + + NSIndexPath *topAdjustedIndexPath = [self adjustedIndexPathForOriginalIndexPath:self.topConsideredIndexPath]; + NSIndexPath *insertionPath = [self.adPlacementData nextAdInsertionIndexPathForAdjustedIndexPath:topAdjustedIndexPath]; + + while ([self shouldPlaceAdAtIndexPath:insertionPath]) { + MPNativeAdData *adData = [self retrieveAdDataForInsertionPath:insertionPath]; + adData.ad.delegate = self; + + if (!adData) { + break; + } + + [self.adPlacementData insertAdData:adData atIndexPath:insertionPath]; + [self.delegate adPlacer:self didLoadAdAtIndexPath:insertionPath]; + + insertionPath = [self.adPlacementData nextAdInsertionIndexPathForAdjustedIndexPath:insertionPath]; + } +} + +#pragma mark - + +- (void)adSourceDidFinishRequest:(MPNativeAdSource *)source +{ + [self fillAdsInConsideredRange]; +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return self.viewController; +} + +- (void)willPresentModalForNativeAd:(MPNativeAd *)nativeAd +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillPresentModalForStreamAdPlacer:)]) { + [self.delegate nativeAdWillPresentModalForStreamAdPlacer:self]; + } +} + +- (void)didDismissModalForNativeAd:(MPNativeAd *)nativeAd +{ + if ([self.delegate respondsToSelector:@selector(nativeAdDidDismissModalForStreamAdPlacer:)]) { + [self.delegate nativeAdDidDismissModalForStreamAdPlacer:self]; + } +} + +- (void)willLeaveApplicationFromNativeAd:(MPNativeAd *)nativeAd +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillLeaveApplicationFromStreamAdPlacer:)]) { + [self.delegate nativeAdWillLeaveApplicationFromStreamAdPlacer:self]; + } +} + +#pragma mark - Internal + +- (CGSize)sizeForAd:(MPNativeAd *)ad withMaximumWidth:(CGFloat)maxWidth andIndexPath:(NSIndexPath *)indexPath +{ + id renderer = ad.renderer; + + CGSize adSize; + + if ([renderer respondsToSelector:@selector(viewSizeHandler)] && renderer.viewSizeHandler) { + adSize = [renderer viewSizeHandler](maxWidth); + if (adSize.height == MPNativeViewDynamicDimension) { + UIView *adView = [ad retrieveAdViewForSizeCalculationWithError:nil]; + if (adView) { + CGSize hydratedAdViewSize = [adView sizeThatFits:CGSizeMake(adSize.width, CGFLOAT_MAX)]; + return hydratedAdViewSize; + } + } + return adSize; + } + + adSize = CGSizeMake(maxWidth, 44.0f); + MPLogWarn(@"WARNING: + (CGSize)viewSizeHandler is NOT implemented for native ad renderer %@ at index path %@. You MUST implement this method to ensure that ad placer native ad cells are correctly sized. Returning a default size of %@ for now.", NSStringFromClass([(id)renderer class]), indexPath, NSStringFromCGSize(adSize)); + + return adSize; +} +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.h b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.h new file mode 100644 index 000000000..8207aa515 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.h @@ -0,0 +1,431 @@ +// +// MPTableViewAdPlacer.h +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import +#import +#import "MPClientAdPositioning.h" +#import "MPServerAdPositioning.h" + +@class MPNativeAdRequestTargeting; +@protocol MPTableViewAdPlacerDelegate; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The `MPTableViewAdPlacer` class allows you to request native ads from the MoPub ad server and + * place them into a `UITableView` object. + * + * When an instance of this class is initialized with a table view, it wraps the table view's + * data source and delegate in order to insert ads and adjust the positions of your regular + * content cells. + */ + +@interface MPTableViewAdPlacer : NSObject + +@property (nonatomic, weak) id delegate; + +/** @name Initializing a Table View Ad Placer */ + +/** + * Creates and returns an ad placer that will insert ads into a table view at positions that can + * be configured dynamically on the MoPub website. + * + * When you make an ad request, the ad placer will ask the MoPub ad server for the positions where + * ads should be inserted into the table view. You can configure these positioning values by + * editing your ad unit's settings on the MoPub website. + * + * Using this method is equivalent to calling + * +placerWithTableView:viewController:adPositioning:rendererConfigurations: and passing in an + * `MPServerAdPositioning` object as the `positioning` parameter. + * + * @param tableView The table view in which to insert ads. + * @param controller The view controller which should be used to present modal content. + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. You should pass in configurations that can render any ad type that + * may be displayed for the given ad unit. + * + * @return An `MPTableViewAdPlacer` object. + */ ++ (instancetype)placerWithTableView:(UITableView *)tableView viewController:(UIViewController *)controller rendererConfigurations:(NSArray *)rendererConfigurations; + +/** + * Creates and returns an ad placer that will insert ads into a table view at specified positions. + * + * When using this method, there are two options for controlling the positions where ads appear + * within the table view. + * + * First, you may pass an `MPServerAdPositioning` object as the `positioning` parameter, which tells + * the ad placer to obtain positioning information dynamically from the ad server, which you can + * configure on the MoPub website. In many cases, this is the preferred approach, since it allows + * you to modify the positions without rebuilding your application. Note that calling the + * convenience method +placerWithTableView:viewController:defaultAdRenderingClass: accomplishes + * this as well. + * + * Alternatively, if you wish to hard-code your positions, you may pass an `MPClientAdPositioning` + * object instead. + * + * @param tableView The table view in which to insert ads. + * @param controller The view controller which should be used to present modal content. + * @param positioning The positioning object that specifies where ads should be shown in the stream. + * @param rendererConfigurations An array of MPNativeAdRendererConfiguration objects that control how + * the native ad is rendered. You should pass in configurations that can render any ad type that + * may be displayed for the given ad unit. + * + * @return An `MPTableViewAdPlacer` object. + */ ++ (instancetype)placerWithTableView:(UITableView *)tableView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations; + +/** @name Requesting Ads */ + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID. + * + * @param adUnitID A string representing a MoPub ad unit ID. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID; + +/** + * Requests ads from the MoPub ad server using the specified ad unit ID and targeting parameters. + * + * @param adUnitID A string representing a MoPub ad unit ID. + * @param targeting An object containing targeting information, such as geolocation data. + */ +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The MoPub SDK adds interfaces to the `UITableView` class to help your application with + * responsibilities related to `MPTableViewAdPlacer`. These APIs include methods to help notify the + * ad placer of all modifications to the original table view, as well as to simplify your + * application code such that it does not need to perform index path manipulations to account for + * the presence of ads. + * + * Since the ad placer replaces the original data source and delegate objects of your table view, + * the SDK also provides new methods for you to set these properties such that the ad placer remains + * aware of the changes. + */ + +@interface UITableView (MPTableViewAdPlacer) + +- (void)mp_setAdPlacer:(MPTableViewAdPlacer *)placer; + +/** @name Obtaining the Table View Ad Placer */ + +/** + * Returns the ad placer currently being used for this table view. + * + * @return An ad placer object or `nil` if no ad placer is being used. + */ +- (MPTableViewAdPlacer *)mp_adPlacer; + +/** @name Setting and Getting the Delegate and Data Source */ + +/** + * Sets the table view's data source. + * + * If your application needs to change a table view's data source after it has instantiated an ad + * placer using that table view, use this method rather than -[UITableView setDataSource:]. + * + * @param dataSource The new table view data source. + */ +- (void)mp_setDataSource:(id)dataSource; + +/** + * Returns the original data source of the table view. + * + * When you instantiate an ad placer using a table view, the ad placer replaces the table view's + * original data source object. If your application needs to access the original data source, use + * this method instead of -[UITableView dataSource]. + * + * @return The original table view data source. + */ +- (id)mp_dataSource; + +/** + * Sets the table view's delegate. + * + * If your application needs to change a table view's delegate after it has instantiated an ad + * placer using that table view, use this method rather than -[UITableView setDelegate:]. + * + * @param delegate The new table view delegate. + */ +- (void)mp_setDelegate:(id)delegate; + +/** + * Returns the original delegate of the table view. + * + * When you instantiate an ad placer using a table view, the ad placer replaces the table view's + * original delegate object. If your application needs to access the original delegate, use this + * method instead of -[UITableView delegate]. + * + * @return The original table view delegate. + */ +- (id)mp_delegate; + +/** @name Notifying the Table View Ad Placer of Content Changes */ + +/** + * Begin a series of method calls that insert, delete, or select rows and sections of the table + * view. + */ +- (void)mp_beginUpdates; + +/** + * Conclude a series of method calls that insert, delete, select, or reload rows and sections of + * the table view. + */ +- (void)mp_endUpdates; + +/** + * Reloads the rows and sections of the table view. + */ +- (void)mp_reloadData; + +/** + * Inserts rows in the receiver at the locations identified by an array of index paths, and informs + * the attached ad placer of the insertions. + * + * @param indexPaths An array of `NSIndexPath` objects that represent rows to insert into the + * table. + * @param animation A constant that either specifies the kind of animation to perform when + * inserting the cells or requests no animation. + */ +- (void)mp_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Deletes rows in the receiver at the locations identified by an array of index paths, and informs + * the attached ad placer of the deletions. + * + * @param indexPaths An array of `NSIndexPath` objects identifying the rows to delete. + * @param animation A constant that either specifies the kind of animation to perform when + * deleting the cells or requests no animation. + */ +- (void)mp_deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Reloads the specified rows using the given animation effect, and informs the attached ad placer + * that the row positions may have changed. + * + * @param indexPaths An array of `NSIndexPath` objects identifying the rows to reload. + * @param animation A constant that indicates how the reloading is to be animated. + */ +- (void)mp_reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Moves the row at a specified location to a destination location, taking into account ads + * inserted by the ad placer. + * + * @param indexPath An index path identifying the row to move. + * @param newIndexPath An index path identifying the row that is the destination of the row at + * *indexPath*. + */ +- (void)mp_moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath; + +/** + * Inserts one or more sections in the receiver, and informs the attached ad placer of the + * insertions. + * + * @param sections An index set that specifies the sections to insert in the receiving table view. + * If a section already exists at the specified index location, it is moved down one index + * location. + * @param animation A constant that indicates how the insertion is to be animated. + */ +- (void)mp_insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Deletes one or more sections in the receiver, and informs the attached ad placer of the + * deletions. + * + * @param sections An index set that specifies the sections to delete from the receiving table + * view. If a section exists after the specified index location, it is moved up one index location. + * @param animation A constant that either specifies the kind of animation to perform when deleting + * the section or requests no animation. + */ +- (void)mp_deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Reloads the specified sections, and informs the attached ad placer that sections may have + * changed. + * + * @param sections An index set identifying the sections to reload. + * @param animation A constant that indicates how the reloading is to be animated. + */ +- (void)mp_reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation; + +/** + * Moves a section to a new location in the table view, and informs the attached ad placer. + * + * @param section The index of the section to move. + * @param newSection The index in the table view that is the destination of the move for the + * section. The existing section at that location slides up or down to an adjoining index position + * to make room for it. + */ +- (void)mp_moveSection:(NSInteger)section toSection:(NSInteger)newSection; + +/** @name Methods Involving Index Paths */ + +/** + * Returns the table view cell at the specified index path. + * + * @param indexPath The index path locating the row in the table view. + * + * @return An object representing a cell of the table or `nil` if the cell is not visible or + * *indexPath* is out of range. + */ +- (UITableViewCell *)mp_cellForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Returns a reusable table-view cell object for the specified reuse identifier. + * + * @param identifier A string identifying the cell object to be reused. This parameter must not be + * `nil`. + * @param indexPath The index path specifying the location of the cell. The data source receives + * this information when asked for the cell and should just pass it along. + * + * @return A `UITableViewCell` object with the associated reuse identifier. + */ +- (id)mp_dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath; + +/** + * Deselects a given row identified by index path, with an option to animate the deselection. + * + * @param indexPath An index path identifying a row in the receiver. + * @param animated YES if you want to animate the deselection and NO if the change should be + * immediate. + */ +- (void)mp_deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated; + +/** + * Returns an index path representing the original row and section of a given table view cell, + * calculated before any ads were inserted. + * + * @param cell A cell object of the table view. + * + * @return An index path representing the row and section of the cell or `nil` if the index path + * is invalid or is a reference to a cell containing an ad. + */ +- (NSIndexPath *)mp_indexPathForCell:(UITableViewCell *)cell; + +/** + * Returns an index path representing the original row and section at the given point. + * + * @param point A point in the local coordinate system of the receiver (the table view's bounds). + * + * @return An index path representing the row and section associated with *point* or `nil` if the + * point is out of bounds of any row or is associated with a cell containing an ad. + */ +- (NSIndexPath *)mp_indexPathForRowAtPoint:(CGPoint)point; + +/** + * Returns the original index path for the selected row, as if no ads have been inserted. + * + * @return The original index path for the selected row. + */ +- (NSIndexPath *)mp_indexPathForSelectedRow; + +/** + * Returns an array of index paths each representing a non-ad row enclosed by a given rectangle, + * calculated before any ads were inserted. + * + * @param rect A rectangle defining an area of the table view in local coordinates. + * + * @return An array of `NSIndexPath` objects each representing a row and section index identifying + * a row within *rect*. Index paths representing ads are not returned. + */ +- (NSArray *)mp_indexPathsForRowsInRect:(CGRect)rect; + +/** + * Returns an array of the original index paths for the selected rows, as if no ads have been + * inserted. + * + * @return An array of the original index paths for the selected rows. + */ +- (NSArray *)mp_indexPathsForSelectedRows; + +/** + * Returns an array of index paths each identifying a visible non-ad row in the table view, + * calculated before any ads were inserted. + * + * @return An array of `NSIndexPath` objects each representing a visible non-ad row in the table + * view. Returns `nil` if no rows are visible. + */ +- (NSArray *)mp_indexPathsForVisibleRows; + +/** + * Returns the drawing area for a row identified by index path. + * + * @param indexPath An index path object that identifies a row of your original content. + * + * @return A rectangle defining the area in which the table view draws the row or `CGRectZero` if + * *indexPath* is invalid. + */ +- (CGRect)mp_rectForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + * Scrolls the table view so that the selected row nearest to a specified position in the table + * view is at that position. + * + * @param indexPath An index path that identifies a row in the table view by its row index and + * its section index. + * @param scrollPosition A constant that identifies a relative position in the receiving table view + * (top, middle, bottom) for row when scrolling concludes. + * @param animated YES if you want to animate the change in position, NO if it should be + * immediate. + */ +- (void)mp_scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated; + +/** + * Selects a row in the receiver identified by index path, optionally scrolling the row to a + * location in the receiver. + * + * @param indexPath An index path identifying a row in the receiver. + * @param animated YES if you want to animate the selection and any change in position, NO if + * the change should be immediate. + * @param scrollPosition A constant that identifies a relative position in the receiving table view + * (top, middle, bottom) for the row when scrolling concludes. + */ +- (void)mp_selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition; + +/** + * Returns an array of the non-ad cells that are visible in the table view. + * + * @return An array containing `UITableViewCell` objects, each representing a visible, non-ad cell + * in the receiving table view. + */ +- (NSArray *)mp_visibleCells; + +@end + +@protocol MPTableViewAdPlacerDelegate + +@optional + +/* + * This method is called when a native ad, placed by the table view ad placer, will present a modal view controller. + * + * @param placer The table view ad placer that contains the ad displaying the modal. + */ +-(void)nativeAdWillPresentModalForTableViewAdPlacer:(MPTableViewAdPlacer *)placer; + +/* + * This method is called when a native ad, placed by the table view ad placer, did dismiss its modal view controller. + * + * @param placer The table view ad placer that contains the ad that dismissed the modal. + */ +-(void)nativeAdDidDismissModalForTableViewAdPlacer:(MPTableViewAdPlacer *)placer; + +/* + * This method is called when a native ad, placed by the table view ad placer, will cause the app to background due to user interaction with the ad. + * + * @param placer The table view ad placer that contains the ad causing the app to background. + */ +-(void)nativeAdWillLeaveApplicationFromTableViewAdPlacer:(MPTableViewAdPlacer *)placer; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.m b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.m new file mode 100644 index 000000000..e75183921 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Native Ads/MPTableViewAdPlacer.m @@ -0,0 +1,823 @@ +// +// MPTableViewAdPlacer.m +// MoPub +// +// Copyright (c) 2014 MoPub. All rights reserved. +// + +#import "MPTableViewAdPlacer.h" +#import "MPStreamAdPlacer.h" +#import "MPInstanceProvider.h" +#import "MPAdPlacerInvocation.h" +#import "MPTimer.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdUtils.h" +#import "MPGlobal.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPTableViewAdPlacerCell.h" +#import + +static NSString * const kTableViewAdPlacerReuseIdentifier = @"MPTableViewAdPlacerReuseIdentifier"; + +@interface MPTableViewAdPlacer () + +@property (nonatomic, strong) MPStreamAdPlacer *streamAdPlacer; +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, weak) id originalDataSource; +@property (nonatomic, weak) id originalDelegate; +@property (nonatomic, strong) MPTimer *insertionTimer; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation MPTableViewAdPlacer + ++ (instancetype)placerWithTableView:(UITableView *)tableView viewController:(UIViewController *)controller rendererConfigurations:(NSArray *)rendererConfigurations +{ + return [[self class] placerWithTableView:tableView viewController:controller adPositioning:[MPServerAdPositioning positioning] rendererConfigurations:rendererConfigurations]; +} + ++ (instancetype)placerWithTableView:(UITableView *)tableView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + MPTableViewAdPlacer *tableViewAdPlacer = [[MPTableViewAdPlacer alloc] initWithTableView:tableView viewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; + return tableViewAdPlacer; +} + +- (instancetype)initWithTableView:(UITableView *)tableView viewController:(UIViewController *)controller adPositioning:(MPAdPositioning *)positioning rendererConfigurations:(NSArray *)rendererConfigurations +{ + for (id rendererConfiguration in rendererConfigurations) { + NSAssert([rendererConfiguration isKindOfClass:[MPNativeAdRendererConfiguration class]], @"A table view ad placer must be instantiated with rendererConfigurations that are of type MPNativeAdRendererConfiguration."); + } + + if (self = [super init]) { + _tableView = tableView; + _streamAdPlacer = [[MPInstanceProvider sharedProvider] buildStreamAdPlacerWithViewController:controller adPositioning:positioning rendererConfigurations:rendererConfigurations]; + _streamAdPlacer.delegate = self; + + _originalDataSource = tableView.dataSource; + _originalDelegate = tableView.delegate; + tableView.dataSource = self; + tableView.delegate = self; + + [self.tableView registerClass:[MPTableViewAdPlacerCell class] forCellReuseIdentifier:kTableViewAdPlacerReuseIdentifier]; + + [tableView mp_setAdPlacer:self]; + } + return self; +} + +- (void)dealloc +{ + [_insertionTimer invalidate]; +} + +#pragma mark - Public + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID +{ + [self loadAdsForAdUnitID:adUnitID targeting:nil]; +} + +- (void)loadAdsForAdUnitID:(NSString *)adUnitID targeting:(MPNativeAdRequestTargeting *)targeting +{ + if (!self.insertionTimer) { + self.insertionTimer = [MPTimer timerWithTimeInterval:kUpdateVisibleCellsInterval target:self selector:@selector(updateVisibleCells) repeats:YES]; + self.insertionTimer.runLoopMode = NSRunLoopCommonModes; + [self.insertionTimer scheduleNow]; + } + [self.streamAdPlacer loadAdsForAdUnitID:adUnitID targeting:targeting]; +} + +#pragma mark - Ad Insertion + +- (void)updateVisibleCells +{ + NSArray *visiblePaths = self.tableView.mp_indexPathsForVisibleRows; + + if ([visiblePaths count]) { + [self.streamAdPlacer setVisibleIndexPaths:visiblePaths]; + } +} + +#pragma mark - + +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didLoadAdAtIndexPath:(NSIndexPath *)indexPath +{ + BOOL originalAnimationsEnabled = [UIView areAnimationsEnabled]; + //We only want to enable animations if the index path is before or within our visible cells + BOOL animationsEnabled = ([(NSIndexPath *)[self.tableView.indexPathsForVisibleRows lastObject] compare:indexPath] != NSOrderedAscending) && originalAnimationsEnabled; + + [UIView setAnimationsEnabled:animationsEnabled]; + [self.tableView mp_beginUpdates]; + [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationMiddle]; + [self.tableView mp_endUpdates]; + [UIView setAnimationsEnabled:originalAnimationsEnabled]; +} + +- (void)adPlacer:(MPStreamAdPlacer *)adPlacer didRemoveAdsAtIndexPaths:(NSArray *)indexPaths +{ + BOOL originalAnimationsEnabled = [UIView areAnimationsEnabled]; + [UIView setAnimationsEnabled:NO]; + [self.tableView mp_beginUpdates]; + [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone]; + [self.tableView mp_endUpdates]; + [UIView setAnimationsEnabled:originalAnimationsEnabled]; +} + +- (void)nativeAdWillPresentModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillPresentModalForTableViewAdPlacer:)]) { + [self.delegate nativeAdWillPresentModalForTableViewAdPlacer:self]; + } +} + +- (void)nativeAdDidDismissModalForStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdDidDismissModalForTableViewAdPlacer:)]) { + [self.delegate nativeAdDidDismissModalForTableViewAdPlacer:self]; + } +} + +- (void)nativeAdWillLeaveApplicationFromStreamAdPlacer:(MPStreamAdPlacer *)adPlacer +{ + if ([self.delegate respondsToSelector:@selector(nativeAdWillLeaveApplicationFromTableViewAdPlacer:)]) { + [self.delegate nativeAdWillLeaveApplicationFromTableViewAdPlacer:self]; + } +} + +#pragma mark - + +// Default is 1 if not implemented +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + if ([self.originalDataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) { + return [self.originalDataSource numberOfSectionsInTableView:tableView]; + } + else { + return 1; + } +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + NSUInteger numberOfItems = [self.originalDataSource tableView:tableView numberOfRowsInSection:section]; + [self.streamAdPlacer setItemCount:numberOfItems forSection:section]; + return [self.streamAdPlacer adjustedNumberOfItems:numberOfItems inSection:section]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + MPTableViewAdPlacerCell *cell = (MPTableViewAdPlacerCell *)[tableView dequeueReusableCellWithIdentifier:kTableViewAdPlacerReuseIdentifier forIndexPath:indexPath]; + cell.clipsToBounds = YES; + + [self.streamAdPlacer renderAdAtIndexPath:indexPath inView:cell.contentView]; + return cell; + } + NSIndexPath *originalIndexPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [self.originalDataSource tableView:tableView cellForRowAtIndexPath:originalIndexPath]; +} + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return NO; + } + + id datasource = self.originalDataSource; + if ([datasource respondsToSelector:@selector(tableView:canEditRowAtIndexPath:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [datasource tableView:tableView canEditRowAtIndexPath:origPath]; + } + + // When the data source doesn't implement tableView:canEditRowAtIndexPath:, Apple assumes the cells are editable. So we return YES. + return YES; +} + +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDataSource with2ArgSelector:@selector(tableView:canMoveRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:NO]; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDataSource with3ArgIntSelector:@selector(tableView:commitEditingStyle:forRowAtIndexPath:) firstArg:tableView secondArg:editingStyle thirdArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:sourceIndexPath]) { + // Can't move an ad explicitly. + return; + } + + id dataSource = self.originalDataSource; + if ([dataSource respondsToSelector:@selector(tableView:moveRowAtIndexPath:toIndexPath:)]) { + NSIndexPath *origSource = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:sourceIndexPath]; + NSIndexPath *origDestination = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:destinationIndexPath]; + [dataSource tableView:tableView moveRowAtIndexPath:origSource toIndexPath:origDestination]; + } +} + +#pragma mark - + +// We don't override the following: +// +// -tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath - No need to override because +// targeting is typically based on the adjusted paths. +// +// -tableView:accessoryTypeForRowWithIndexPath - Deprecated, and causes a runtime exception. + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return [self.streamAdPlacer sizeForAdAtIndexPath:indexPath withMaximumWidth:CGRectGetWidth(self.tableView.bounds)].height; + } + + if ([self.originalDelegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)]) { + NSIndexPath *originalIndexPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [self.originalDelegate tableView:tableView heightForRowAtIndexPath:originalIndexPath]; + } + + return tableView.rowHeight; +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with3ArgSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:) firstArg:tableView secondArg:cell thirdArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with3ArgSelector:@selector(tableView:didEndDisplayingCell:forRowAtIndexPath:) firstArg:tableView secondArg:cell thirdArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:accessoryButtonTappedForRowWithIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:shouldHighlightRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:YES]; +} + +- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:didHighlightRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:didUnhighlightRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return indexPath; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:willSelectRowAtIndexPath:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + NSIndexPath *origResult = [delegate tableView:tableView willSelectRowAtIndexPath:origPath]; + return [self.streamAdPlacer adjustedIndexPathForOriginalIndexPath:origResult]; + } + + return indexPath; +} + +- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return indexPath; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + NSIndexPath *origResult = [delegate tableView:tableView willDeselectRowAtIndexPath:origPath]; + return [self.streamAdPlacer adjustedIndexPathForOriginalIndexPath:origResult]; + } + + return indexPath; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + // The view inside the cell already has a gesture recognizer to handle the tap event. + [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; + return; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) { + NSIndexPath *originalPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [delegate tableView:tableView didSelectRowAtIndexPath:originalPath]; + } +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:didDeselectRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + return UITableViewCellEditingStyleNone; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [delegate tableView:tableView editingStyleForRowAtIndexPath:origPath]; + } + + // Apple returns UITableViewCellEditingStyleDelete by default when the cell is editable. So we'll do the same. + // We'll also return UITableViewCellEditingStyleNone if the cell isn't editable. + BOOL editable = [self tableView:tableView canEditRowAtIndexPath:indexPath]; + + if (editable) { + return UITableViewCellEditingStyleDelete; + } else { + return UITableViewCellEditingStyleNone; + } +} + +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation resultForInvocation:invocation defaultValue:@"Delete"]; +} + +- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:shouldIndentWhileEditingRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:YES]; +} + +- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:willBeginEditingRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:didEndEditingRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; +} + +- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:indentationLevelForRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation integerResultForInvocation:invocation + defaultValue:UITableViewCellEditingStyleNone]; +} + +- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSInvocation *invocation = [MPAdPlacerInvocation invokeForTarget:self.originalDelegate with2ArgSelector:@selector(tableView:shouldShowMenuForRowAtIndexPath:) firstArg:tableView secondArg:indexPath streamAdPlacer:self.streamAdPlacer]; + + return [MPAdPlacerInvocation boolResultForInvocation:invocation defaultValue:NO]; +} + +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + // Can't copy or paste to an ad. + return NO; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:canPerformAction:forRowAtIndexPath:withSender:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + return [delegate tableView:tableView canPerformAction:action forRowAtIndexPath:origPath withSender:sender]; + } + + return NO; +} + +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { + + if ([self.streamAdPlacer isAdAtIndexPath:indexPath]) { + // Can't copy or paste to an ad. + return; + } + + id delegate = self.originalDelegate; + if ([delegate respondsToSelector:@selector(tableView:performAction:forRowAtIndexPath:withSender:)]) { + NSIndexPath *origPath = [self.streamAdPlacer originalIndexPathForAdjustedIndexPath:indexPath]; + [delegate tableView:tableView performAction:action forRowAtIndexPath:origPath withSender:sender]; + } +} + +#pragma mark - Method Forwarding + +- (BOOL)isKindOfClass:(Class)aClass { + return [super isKindOfClass:aClass] || + [self.originalDataSource isKindOfClass:aClass] || + [self.originalDelegate isKindOfClass:aClass]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol +{ + return [super conformsToProtocol:aProtocol] || + [self.originalDelegate conformsToProtocol:aProtocol] || + [self.originalDataSource conformsToProtocol:aProtocol]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + return [super respondsToSelector:aSelector] || + [self.originalDataSource respondsToSelector:aSelector] || + [self.originalDelegate respondsToSelector:aSelector]; +} + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + if ([self.originalDataSource respondsToSelector:aSelector]) { + return self.originalDataSource; + } else if ([self.originalDelegate respondsToSelector:aSelector]) { + return self.originalDelegate; + } else { + return [super forwardingTargetForSelector:aSelector]; + } +} + +@end + +#pragma mark - + +@implementation UITableView (MPTableViewAdPlacer) + +static char kAdPlacerKey; + +- (void)mp_setAdPlacer:(MPTableViewAdPlacer *)placer +{ + objc_setAssociatedObject(self, &kAdPlacerKey, placer, OBJC_ASSOCIATION_ASSIGN); +} + +- (MPTableViewAdPlacer *)mp_adPlacer +{ + return objc_getAssociatedObject(self, &kAdPlacerKey); +} + +- (void)mp_setDelegate:(id)delegate +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + adPlacer.originalDelegate = delegate; + } else { + self.delegate = delegate; + } +} + +- (id)mp_delegate +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + return adPlacer.originalDelegate; + } else { + return self.delegate; + } +} + +- (void)mp_setDataSource:(id)dataSource +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + adPlacer.originalDataSource = dataSource; + } else { + self.dataSource = dataSource; + } +} + +- (id)mp_dataSource +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + return adPlacer.originalDataSource; + } else { + return self.dataSource; + } +} + +- (void)mp_reloadData +{ + [self reloadData]; +} + +- (CGRect)mp_rectForRowAtIndexPath:(NSIndexPath *)indexPath +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:adjustedIndexPath]; + } + + if (!indexPath || adjustedIndexPath) { + return [self rectForRowAtIndexPath:adjustedIndexPath]; + } else { + return CGRectZero; + } +} + +- (NSIndexPath *)mp_indexPathForRowAtPoint:(CGPoint)point +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = [self indexPathForRowAtPoint:point]; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer originalIndexPathForAdjustedIndexPath:adjustedIndexPath]; + } + + return adjustedIndexPath; +} + +- (NSIndexPath *)mp_indexPathForCell:(UITableViewCell *)cell +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = [self indexPathForCell:cell]; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer originalIndexPathForAdjustedIndexPath:adjustedIndexPath]; + } + + return adjustedIndexPath; +} + +- (NSArray *)mp_indexPathsForRowsInRect:(CGRect)rect +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *indexPaths = [self indexPathsForRowsInRect:rect]; + + if (adPlacer) { + indexPaths = [adPlacer.streamAdPlacer originalIndexPathsForAdjustedIndexPaths:indexPaths]; + } + + return indexPaths; +} + +- (UITableViewCell *)mp_cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:adjustedIndexPath]; + } + + return [self cellForRowAtIndexPath:adjustedIndexPath]; +} + +- (NSArray *)mp_visibleCells +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + NSArray *indexPaths = [self mp_indexPathsForVisibleRows]; + NSMutableArray *visibleCells = [NSMutableArray array]; + for (NSIndexPath *indexPath in indexPaths) { + [visibleCells addObject:[self mp_cellForRowAtIndexPath:indexPath]]; + } + return visibleCells; + } else { + return [self visibleCells]; + } +} + +- (NSArray *)mp_indexPathsForVisibleRows +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = [self indexPathsForVisibleRows]; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer originalIndexPathsForAdjustedIndexPaths:adjustedIndexPaths]; + } + + return adjustedIndexPaths; +} + +- (void)mp_scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer && indexPath.row != NSNotFound) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:adjustedIndexPath]; + } + + [self scrollToRowAtIndexPath:adjustedIndexPath atScrollPosition:scrollPosition animated:animated]; +} + +- (void)mp_beginUpdates +{ + [self beginUpdates]; +} + +- (void)mp_endUpdates +{ + [self endUpdates]; +} + +- (void)mp_insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer insertSections:sections]; + } + + [self insertSections:sections withRowAnimation:animation]; +} + +- (void)mp_deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer deleteSections:sections]; + } + + [self deleteSections:sections withRowAnimation:animation]; +} + +- (void)mp_reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation +{ + [self reloadSections:sections withRowAnimation:animation]; +} + +- (void)mp_moveSection:(NSInteger)section toSection:(NSInteger)newSection +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + + if (adPlacer) { + [adPlacer.streamAdPlacer moveSection:section toSection:newSection]; + } + + [self moveSection:section toSection:newSection]; +} + +- (void)mp_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = indexPaths; + + if (adPlacer) { + [adPlacer.streamAdPlacer insertItemsAtIndexPaths:indexPaths]; + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + } + + // We perform the actual UI insertion AFTER updating the stream ad placer's + // data, because the insertion can trigger queries to the data source, which + // needs to reflect the post-insertion state. + [self insertRowsAtIndexPaths:adjustedIndexPaths withRowAnimation:animation]; +} + +- (void)mp_deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = indexPaths; + + // We need to wrap the delete process in begin/end updates in case any ad + // cells are also deleted. MPStreamAdPlacer's deleteItemsAtIndexPaths: can + // call the delegate's didRemoveAdsAtIndexPaths, which will remove those + // ads from the tableview. + [self mp_beginUpdates]; + if (adPlacer) { + // We need to obtain the adjusted index paths to delete BEFORE we + // update the stream ad placer's data. + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + [adPlacer.streamAdPlacer deleteItemsAtIndexPaths:indexPaths]; + } + + // We perform the actual UI deletion AFTER updating the stream ad placer's + // data, because the deletion can trigger queries to the data source, which + // needs to reflect the post-deletion state. + [self deleteRowsAtIndexPaths:adjustedIndexPaths withRowAnimation:animation]; + [self mp_endUpdates]; +} + +- (void)mp_reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = indexPaths; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer adjustedIndexPathsForOriginalIndexPaths:indexPaths]; + } + + [self reloadRowsAtIndexPaths:adjustedIndexPaths withRowAnimation:animation]; +} + +- (void)mp_moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedFrom = indexPath; + NSIndexPath *adjustedTo = newIndexPath; + + if (adPlacer) { + // We need to obtain the adjusted index paths to move BEFORE we + // update the stream ad placer's data. + adjustedFrom = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + adjustedTo = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:newIndexPath]; + + [adPlacer.streamAdPlacer moveItemAtIndexPath:indexPath toIndexPath:newIndexPath]; + } + + // We perform the actual UI operation AFTER updating the stream ad placer's + // data, because the operation can trigger queries to the data source, which + // needs to reflect the post-operation state. + [self moveRowAtIndexPath:adjustedFrom toIndexPath:adjustedTo]; +} + +- (NSIndexPath *)mp_indexPathForSelectedRow +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = [self indexPathForSelectedRow]; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer originalIndexPathForAdjustedIndexPath:adjustedIndexPath]; + } + + return adjustedIndexPath; +} + +- (NSArray *)mp_indexPathsForSelectedRows +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSArray *adjustedIndexPaths = [self indexPathsForSelectedRows]; + + if (adPlacer) { + adjustedIndexPaths = [adPlacer.streamAdPlacer originalIndexPathsForAdjustedIndexPaths:adjustedIndexPaths]; + } + + return adjustedIndexPaths; +} + +- (void)mp_selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + if (!indexPath || adjustedIndexPath) { + [self selectRowAtIndexPath:adjustedIndexPath animated:animated scrollPosition:scrollPosition]; + } +} + +- (void)mp_deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + if (!indexPath || adjustedIndexPath) { + [self deselectRowAtIndexPath:adjustedIndexPath animated:animated]; + } +} + +- (id)mp_dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath +{ + MPTableViewAdPlacer *adPlacer = [self mp_adPlacer]; + NSIndexPath *adjustedIndexPath = indexPath; + + if (adPlacer) { + adjustedIndexPath = [adPlacer.streamAdPlacer adjustedIndexPathForOriginalIndexPath:indexPath]; + } + + if (!indexPath || adjustedIndexPath) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= MP_IOS_6_0 + if ([self respondsToSelector:@selector(dequeueReusableCellWithIdentifier:forIndexPath:)]) { + return [self dequeueReusableCellWithIdentifier:identifier forIndexPath:adjustedIndexPath]; + } else { + return [self dequeueReusableCellWithIdentifier:identifier]; + } +#endif + } else { + return nil; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.h new file mode 100644 index 000000000..df00b29e4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.h @@ -0,0 +1,37 @@ +// +// MOPUBAVPlayer.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MOPUBAVPlayer; + +@protocol MOPUBAVPlayerDelegate + +- (void)avPlayer:(MOPUBAVPlayer *)player didError:(NSError *)error withMessage:(NSString *)message; + +- (void)avPlayer:(MOPUBAVPlayer *)player playbackTimeDidProgress:(NSTimeInterval)currentPlaybackTime; + +- (void)avPlayerDidFinishPlayback:(MOPUBAVPlayer *)player; + +- (void)avPlayerDidRecoverFromStall:(MOPUBAVPlayer *)player; + +- (void)avPlayerDidStall:(MOPUBAVPlayer *)player; + +@end + + +@interface MOPUBAVPlayer : AVPlayer + +// Indicates the duration of the player item. +@property (nonatomic, readonly) NSTimeInterval currentItemDuration; + +// Returns the current time of the current player item. +@property (nonatomic, readonly) NSTimeInterval currentPlaybackTime; + +- (id)initWithDelegate:(id)delegate playerItem:(AVPlayerItem *)playerItem; + +- (void)dispose; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.m new file mode 100644 index 000000000..47bc00e84 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayer.m @@ -0,0 +1,256 @@ +// +// MOPUBAVPlayer.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPReachability.h" +#import "MOPUBAVPlayer.h" +#import "MPLogging.h" +#import "MPTimer.h" +#import "MPCoreInstanceProvider.h" + +static CGFloat const kAvPlayerTimerInterval = 0.1f; + +static NSString * const MPAVPlayerItemLoadErrorTemplate = @"Loading player item at %@ failed."; + +@interface MOPUBAVPlayer() + +@property (nonatomic, weak, readonly) id delegate; + +@property (nonatomic, copy) NSURL *mediaURL; +@property (nonatomic) MPTimer *playbackTimer; +@property (nonatomic) CMTime lastContinuousPlaybackCMTime; +@property (nonatomic) MPReachability *reachability; +@property (nonatomic) BOOL playbackDidStall; + +@end + +@implementation MOPUBAVPlayer + +- (id)initWithDelegate:(id)delegate playerItem:(AVPlayerItem *)playerItem +{ + if (playerItem && delegate) { + self = [super initWithPlayerItem:playerItem]; + if (self) { + _delegate = delegate; + + // AVPlayer KVO doesn't handle disconnect/reconnect case. + // Reachability is used to detect network drop and reconnect. + _reachability = [MPReachability reachabilityForInternetConnection]; + [_reachability startNotifier]; + [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(checkNetworkStatus:) name:kMPReachabilityChangedNotification object:nil]; + } + return self; + } else { + return nil; + } +} + +- (void)dealloc +{ + [self dispose]; +} + +#pragma mark - controls of AVPlayer + +- (void)play +{ + [super play]; + [self startTimeObserver]; + MPLogDebug(@"start playback"); +} + +- (void)pause +{ + [super pause]; + [self stopTimeObserver]; + MPLogDebug(@"playback paused"); +} + +- (void)setMuted:(BOOL)muted +{ + if ([[self superclass] instancesRespondToSelector:@selector(setMuted:)]) { + [super setMuted:muted]; + } else { + if (muted) { + [self setAudioVolume:0]; + } else { + [self setAudioVolume:1]; + } + } +} + +// iOS 6 doesn't have muted for avPlayerItem. Use volume to control mute/unmute +- (void)setAudioVolume:(float)volume +{ + NSArray *audioTracks = [self.currentItem.asset tracksWithMediaType:AVMediaTypeAudio]; + NSMutableArray *allAudioParams = [NSMutableArray array]; + for (AVAssetTrack *track in audioTracks) { + AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters]; + [audioInputParams setVolume:volume atTime:kCMTimeZero]; + [audioInputParams setTrackID:[track trackID]]; + [allAudioParams addObject:audioInputParams]; + } + AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; + [audioMix setInputParameters:allAudioParams]; + [self.currentItem setAudioMix:audioMix]; +} + +#pragma mark - Timer + +- (void)startTimeObserver +{ + // Use custom timer to check for playback time changes and stall detection, since there are bugs + // in the AVPlayer time observing API that can cause crashes. Also, the AVPlayerItem stall notification + // does not always report accurately. + if (_playbackTimer == nil) { + _playbackTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:kAvPlayerTimerInterval target:self selector:@selector(timerTick) repeats:YES]; + // Add timer to main run loop with common modes to allow the timer to tick while user is scrolling. + _playbackTimer.runLoopMode = NSRunLoopCommonModes; + [_playbackTimer scheduleNow]; + _lastContinuousPlaybackCMTime = kCMTimeZero; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:self.currentItem]; + } else { + [_playbackTimer resume]; + } +} + +- (void)timerTick +{ + if (!self.currentItem || self.currentItem.error != nil) { + [self stopTimeObserver]; + NSError *error = nil; + NSString *errorMessage = nil; + if (self.currentItem) { + error = self.currentItem.error; + errorMessage = self.currentItem.error.description ?: self.currentItem.errorLog.description; + } else { + errorMessage = [NSString stringWithFormat:MPAVPlayerItemLoadErrorTemplate, self.mediaURL]; + } + + if ([self.delegate respondsToSelector:@selector(avPlayer:didError:withMessage:)]) { + [self.delegate avPlayer:self didError:error withMessage:errorMessage]; + } + MPLogInfo(@"avplayer experienced error: %@", errorMessage); + } else { + CMTime currentCMTime = self.currentTime; + int32_t result = CMTimeCompare(currentCMTime, self.lastContinuousPlaybackCMTime); + // finished or stalled + if (result == 0) { + NSTimeInterval duration = self.currentItemDuration; + NSTimeInterval currentPlaybackTime = self.currentPlaybackTime; + if (!isnan(duration) && !isnan(currentPlaybackTime) && duration > 0 && currentPlaybackTime > 0) { + [self avPlayerDidStall]; + } + } else { + self.lastContinuousPlaybackCMTime = currentCMTime; + if (result > 0) { + NSTimeInterval currentPlaybackTime = self.currentPlaybackTime; + if (!isnan(currentPlaybackTime) && isfinite(currentPlaybackTime)) { + // There are bugs in AVPlayer that causes the currentTime to be negative + if (currentPlaybackTime < 0) { + currentPlaybackTime = 0; + } + [self avPlayer:self playbackTimeDidProgress:currentPlaybackTime]; + } + } + } + + } +} + +- (void)stopTimeObserver +{ + [_playbackTimer pause]; + MPLogDebug(@"AVPlayer timer stopped"); +} + +#pragma mark - disconnect/reconnect handling +- (void)checkNetworkStatus:(NSNotification *)notice +{ + MPNetworkStatus remoteHostStatus = [self.reachability currentReachabilityStatus]; + + if (remoteHostStatus == MPNotReachable) { + if (!self.rate) { + [self pause]; + if ([self.delegate respondsToSelector:@selector(avPlayerDidStall:)]) { + [self.delegate avPlayerDidStall:self]; + } + } + } else { + if (!self.rate) { + [self play]; + } + } +} + +#pragma mark - avPlayer state changes + +- (void)avPlayer:(MOPUBAVPlayer *)player playbackTimeDidProgress:(NSTimeInterval)currentPlaybackTime +{ + if (self.playbackDidStall) { + self.playbackDidStall = NO; + if ([self.delegate respondsToSelector:@selector(avPlayerDidRecoverFromStall:)]) { + [self.delegate avPlayerDidRecoverFromStall:self]; + } + } + + if ([self.delegate respondsToSelector:@selector(avPlayer:playbackTimeDidProgress:)]) { + [self.delegate avPlayer:self playbackTimeDidProgress:currentPlaybackTime]; + } +} + +- (void)avPlayerDidStall +{ + // Only call delegate methods once per stall cycle. + if (!self.playbackDidStall && [self.delegate respondsToSelector:@selector(avPlayerDidStall:)]) { + [self.delegate avPlayerDidStall:self]; + } + self.playbackDidStall = YES; +} + +- (void)playbackDidFinish +{ + // Make sure we stop time observing once we know we've done playing. + [self stopTimeObserver]; + if ([self.delegate respondsToSelector:@selector(avPlayerDidFinishPlayback:)]) { + [self.delegate avPlayerDidFinishPlayback:self]; + } + MPLogDebug(@"playback finished"); +} + +- (void)dispose +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [self stopTimeObserver]; + [self.reachability stopNotifier]; + if (_playbackTimer) { + [_playbackTimer invalidate]; + _playbackTimer = nil; + } + + // Cancel preroll after time observer is removed, + // otherwise an NSInternalInconsistencyException may be thrown and crash on + // [AVCMNotificationDispatcher _copyAndRemoveListenerAndCallbackForWeakReferenceToListener:callback:name:object:], + // depends on timing. + [self cancelPendingPrerolls]; +} + + +#pragma mark - getter + +- (NSTimeInterval)currentItemDuration +{ + NSTimeInterval duration = CMTimeGetSeconds(self.currentItem.duration); + return (isfinite(duration)) ? duration : NAN; +} + +- (NSTimeInterval)currentPlaybackTime +{ + NSTimeInterval currentTime = CMTimeGetSeconds(self.currentTime); + return (isfinite(currentTime)) ? currentTime : NAN; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.h new file mode 100644 index 000000000..d87babb3b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.h @@ -0,0 +1,15 @@ +// +// MPAVPlayerView.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class AVPlayer; + +@interface MOPUBAVPlayerView : UIView + +@property (nonatomic) AVPlayer *player; +@property (nonatomic) NSString *videoGravity; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.m new file mode 100644 index 000000000..2aa499378 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBAVPlayerView.m @@ -0,0 +1,40 @@ +// +// MPAVPlayerView.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBAVPlayerView.h" + +@implementation MOPUBAVPlayerView + ++ (Class)layerClass +{ + return [AVPlayerLayer class]; +} + +- (AVPlayer *)player +{ + AVPlayerLayer *playerLayer = (AVPlayerLayer *)self.layer; + return playerLayer.player; +} + +- (void)setPlayer:(AVPlayer *)player +{ + AVPlayerLayer *playerLayer = (AVPlayerLayer *)self.layer; + playerLayer.player = player; +} + +- (NSString *)videoGravity +{ + AVPlayerLayer *playerLayer = (AVPlayerLayer *)self.layer; + return playerLayer.videoGravity; +} + +- (void)setVideoGravity:(NSString *)videoGravity +{ + AVPlayerLayer *playerLayer = (AVPlayerLayer *)self.layer; + playerLayer.videoGravity = videoGravity; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.h new file mode 100644 index 000000000..5a6a5bda2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.h @@ -0,0 +1,15 @@ +// +// MOPUBActivityIndicatorView.h +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MOPUBActivityIndicatorView : UIView + +- (void)startAnimating; +- (void)stopAnimating; +- (BOOL)isAnimating; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.m new file mode 100644 index 000000000..c6540e6fc --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBActivityIndicatorView.m @@ -0,0 +1,57 @@ +// +// MOPUBActivityIndicatorView.m +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBActivityIndicatorView.h" +#import "MPGlobal.h" +#import "UIColor+MPAdditions.h" + +static NSString * const kSpinnerBgColor = @"#000000"; +static CGFloat const kSpinnerAlpha = 0.5f; +static CGFloat const kSpinnerCornerRadius = 4.0f; + +@interface MOPUBActivityIndicatorView() + +@property (nonatomic) UIActivityIndicatorView *activityIndicator; +@property (nonatomic) UIView *bgView; + +@end + +@implementation MOPUBActivityIndicatorView + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + _bgView = [[UIView alloc] initWithFrame:frame]; + _bgView.backgroundColor = [UIColor mp_colorFromHexString:kSpinnerBgColor alpha:kSpinnerAlpha]; + _bgView.layer.cornerRadius = kSpinnerCornerRadius; + [self addSubview:_bgView]; + + _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + _activityIndicator.center = self.center; + _activityIndicator.frame = CGRectIntegral(_activityIndicator.frame); + [self addSubview:_activityIndicator]; + } + return self; +} + +- (void)startAnimating +{ + self.bgView.hidden = NO; + [self.activityIndicator startAnimating]; +} + +- (void)stopAnimating +{ + self.bgView.hidden = YES; + [self.activityIndicator stopAnimating]; +} + +- (BOOL)isAnimating +{ + return self.activityIndicator.isAnimating; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.h new file mode 100644 index 000000000..aa9ddfc2c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.h @@ -0,0 +1,30 @@ +// +// MOPUBFullscreenPlayerViewController.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MOPUBPlayerViewController; +@class MOPUBPlayerView; +@class MOPUBFullscreenPlayerViewController; + +@protocol MOPUBFullscreenPlayerViewControllerDelegate + +- (void)playerDidProgressToTime:(NSTimeInterval)playbackTime; +- (void)ctaTapped:(MOPUBFullscreenPlayerViewController *)viewController; +- (void)fullscreenPlayerWillLeaveApplication:(MOPUBFullscreenPlayerViewController *)viewController; + +@end + +typedef void (^MOPUBFullScreenPlayerViewControllerDismissBlock)(UIView *originalParentView); + +@interface MOPUBFullscreenPlayerViewController : UIViewController + +@property (nonatomic) MOPUBPlayerView *playerView; + +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithVideoPlayer:(MOPUBPlayerViewController *)playerController dismissBlock:(MOPUBFullScreenPlayerViewControllerDismissBlock)dismiss; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.m new file mode 100644 index 000000000..500c111f2 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBFullscreenPlayerViewController.m @@ -0,0 +1,363 @@ +// +// MOPUBFullscreenPlayerViewController.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBFullscreenPlayerViewController.h" +#import "MOPUBPlayerView.h" +#import "MOPUBPlayerViewController.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPCoreInstanceProvider.h" +#import "MPGlobal.h" +#import "MPNativeAdConstants.h" +#import "MOPUBActivityIndicatorView.h" +#import "UIView+MPAdditions.h" +#import "UIButton+MPAdditions.h" +#import "UIColor+MPAdditions.h" + +static CGFloat const kDaaIconFullscreenLeftMargin = 16.0f; +static CGFloat const kDaaIconFullscreenTopMargin = 16.0f; +static CGFloat const kDaaIconSize = 16.0f; +static CGFloat const kCloseButtonRightMargin = 16.0f; +static CGFloat const kDefaultButtonTouchAreaInsets = 10.0f; + +static NSString * const kCloseButtonImage = @"MPCloseBtn.png"; +static NSString * const kCtaButtonTitleText = @"Learn More"; +static CGFloat const kCtaButtonTopMarginPortrait = 15.0f; +static CGFloat const kCtaButtonTrailingMarginLandscape = 15.0f; +static CGFloat const kCtaButtonBottomMarginLandscape = 15.0f; +static CGFloat const kCtaButtonBottomCornerRadius = 4.0f; +static CGFloat const kCtaButtonBottomBorderWidth = 0.5f; +static CGFloat const kCtaButtonBottomFontSize = 18.0f; +static CGFloat const kCtaButtonContentInsetsHorizontal = 35.0f; +static CGFloat const kCtaButtonContentInsetsVertical = 10.0f; +static CGFloat const kCtaButtonBackgroundAlpha = 0.2f; +static NSString * const kCtaButtonBackgroundColor = @"#000000"; + +static NSString * const kTopGradientColor = @"#000000"; +static NSString * const kBottomGradientColor= @"#000000"; +static CGFloat const kTopGradientAlpha = 0.4f; +static CGFloat const kBottomGradientAlpha = 0.0f; +static CGFloat const kGradientHeight = 42; + +static CGFloat const kStallSpinnerSize = 35.0f; + +@interface MOPUBFullscreenPlayerViewController () + +// UI components +@property (nonatomic) UIButton *daaButton; +@property (nonatomic) UIButton *closeButton; +@property (nonatomic) UIButton *ctaButton; +@property (nonatomic) MOPUBActivityIndicatorView *stallSpinner; +@property (nonatomic) UIActivityIndicatorView *playerNotReadySpinner; +@property (nonatomic) UIView *gradientView; +@property (nonatomic) CAGradientLayer *gradient; + +@property (nonatomic) MOPUBPlayerViewController *playerController; +@property (nonatomic) UIView *originalParentView; +@property (nonatomic) MPAdDestinationDisplayAgent *displayAgent; +@property (nonatomic, copy) MOPUBFullScreenPlayerViewControllerDismissBlock dismissBlock; + +@end + +@implementation MOPUBFullscreenPlayerViewController + +- (instancetype)initWithVideoPlayer:(MOPUBPlayerViewController *)playerController dismissBlock:(MOPUBFullScreenPlayerViewControllerDismissBlock)dismissBlock +{ + if (self = [super init]) { + _playerController = playerController; + _originalParentView = self.playerController.playerView.superview; + _playerView = self.playerController.playerView; + _playerController.delegate = self; + _dismissBlock = [dismissBlock copy]; + _displayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self setApplicationStatusBarHidden:YES]; + [self.playerController willEnterFullscreen]; + + self.view.backgroundColor = [UIColor blackColor]; + [self.view addSubview:self.playerView]; + + [self createAndAddGradientView]; + + self.daaButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.daaButton.frame = CGRectMake(0, 0, kDaaIconSize, kDaaIconSize); + [self.daaButton setImage:[UIImage imageNamed:MPResourcePathForResource(kDAAIconImageName)] forState:UIControlStateNormal]; + [self.daaButton addTarget:self action:@selector(daaButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + self.daaButton.mp_TouchAreaInsets = UIEdgeInsetsMake(kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets); + [self.view addSubview:self.daaButton]; + + self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.closeButton setImage:[UIImage imageNamed:MPResourcePathForResource(kCloseButtonImage)] forState:UIControlStateNormal]; + [self.closeButton addTarget:self action:@selector(closeButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + self.closeButton.mp_TouchAreaInsets = UIEdgeInsetsMake(kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets, kDefaultButtonTouchAreaInsets); + [self.closeButton sizeToFit]; + [self.view addSubview:self.closeButton]; + + self.ctaButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.ctaButton setTitle:kCtaButtonTitleText forState:UIControlStateNormal]; + [self.ctaButton setBackgroundColor:[UIColor mp_colorFromHexString:kCtaButtonBackgroundColor alpha:kCtaButtonBackgroundAlpha]]; + [self.ctaButton addTarget:self action:@selector(ctaButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + self.ctaButton.layer.cornerRadius = kCtaButtonBottomCornerRadius; + self.ctaButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:kCtaButtonBottomFontSize]; + [self.ctaButton setContentEdgeInsets:UIEdgeInsetsMake(kCtaButtonContentInsetsVertical, kCtaButtonContentInsetsHorizontal, kCtaButtonContentInsetsVertical, kCtaButtonContentInsetsHorizontal)]; + [[self.ctaButton layer] setBorderWidth:kCtaButtonBottomBorderWidth]; + [[self.ctaButton layer] setBorderColor:[UIColor whiteColor].CGColor]; + [self.ctaButton sizeToFit]; + [self.view addSubview:self.ctaButton]; + + if (!self.playerController.isReadyToPlay) { + [self createPlayerNotReadySpinner]; + } + + // Once the video enters fullscreen mode, we should resume the playback if it is paused. + if (self.playerController.paused) { + [self.playerController resume]; + } +} + +- (void)createAndAddGradientView +{ + // Create the gradient + self.gradientView = [UIView new]; + self.gradientView.userInteractionEnabled = NO; + UIColor *topColor = [UIColor mp_colorFromHexString:kTopGradientColor alpha:kTopGradientAlpha]; + UIColor *bottomColor= [UIColor mp_colorFromHexString:kBottomGradientColor alpha:kBottomGradientAlpha]; + self.gradient = [CAGradientLayer layer]; + self.gradient.colors = [NSArray arrayWithObjects: (id)topColor.CGColor, (id)bottomColor.CGColor, nil]; + CGSize screenSize = MPScreenBounds().size; + self.gradient.frame = CGRectMake(0, 0, screenSize.width, kGradientHeight); + + //Add gradient to view + [self.gradientView.layer insertSublayer:self.gradient atIndex:0]; + [self.view addSubview:self.gradientView]; +} + +- (void)showStallSpinner +{ + if (!self.stallSpinner) { + self.stallSpinner = [[MOPUBActivityIndicatorView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, kStallSpinnerSize, kStallSpinnerSize)]; + [self.view addSubview:self.stallSpinner]; + } +} + +- (void)hideStallSpinner +{ + if (self.stallSpinner) { + [self.stallSpinner stopAnimating]; + [self.stallSpinner removeFromSuperview]; + } +} + +- (void)createPlayerNotReadySpinner +{ + if (!self.playerNotReadySpinner) { + self.playerNotReadySpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + [self.view addSubview:self.playerNotReadySpinner]; + [self.playerNotReadySpinner startAnimating]; + } +} + +- (void)removePlayerNotReadySpinner +{ + [self.playerNotReadySpinner stopAnimating]; + [self.playerNotReadySpinner removeFromSuperview]; + self.playerNotReadySpinner = nil; +} + +#pragma mark - Layout UI components + +- (void)viewWillLayoutSubviews +{ + [super viewWillLayoutSubviews]; + + [self layoutPlayerView]; + [self layoutDaaButton]; + [self layoutCloseButton]; + [self layoutCtaButton]; + [self layoutStallSpinner]; + [self layoutPlayerNotReadySpinner]; + [self layoutGradientView]; +} + +- (void)layoutPlayerView +{ + CGSize screenSize = MPScreenBounds().size; + self.playerView.videoGravity = AVLayerVideoGravityResizeAspectFill; + if (UIInterfaceOrientationIsLandscape(MPInterfaceOrientation())) { + self.playerView.frame = CGRectMake(0, 0, screenSize.width, screenSize.height); + } else { + self.playerView.mp_width = screenSize.width; + self.playerView.mp_height = self.playerView.mp_width/self.playerController.videoAspectRatio; + self.playerView.center = self.view.center; + self.playerView.frame = CGRectIntegral(self.playerView.frame); + } +} + +- (void)layoutDaaButton +{ + self.daaButton.mp_x = kDaaIconFullscreenLeftMargin; + self.daaButton.mp_y = kDaaIconFullscreenTopMargin; +} + +- (void)layoutCloseButton +{ + CGSize screenSize = MPScreenBounds().size; + self.closeButton.mp_x = screenSize.width - kCloseButtonRightMargin - self.closeButton.mp_width; + CGFloat daaCenterY = self.daaButton.frame.origin.y + self.daaButton.mp_height/2.0f; + self.closeButton.mp_y = daaCenterY - self.closeButton.mp_height/2.0f; + self.closeButton.frame = CGRectIntegral(self.closeButton.frame); +} + +- (void)layoutCtaButton +{ + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + if (UIInterfaceOrientationIsLandscape(orientation)) { + self.ctaButton.mp_x = CGRectGetMaxX(self.playerView.frame) - kCtaButtonTrailingMarginLandscape - CGRectGetWidth(self.ctaButton.bounds); + self.ctaButton.mp_y = CGRectGetMaxY(self.playerView.frame) - kCtaButtonBottomMarginLandscape - CGRectGetHeight(self.ctaButton.bounds); + } else { + self.ctaButton.center = self.view.center; + self.ctaButton.mp_y = CGRectGetMaxY(self.playerView.frame) + kCtaButtonTopMarginPortrait; + self.ctaButton.frame = CGRectIntegral(self.ctaButton.frame); + } +} + +- (void)layoutStallSpinner +{ + if (self.stallSpinner) { + CGSize screenSize = MPScreenBounds().size; + self.stallSpinner.center = CGPointMake(screenSize.width/2.0f, screenSize.height/2.0f); + self.stallSpinner.frame = CGRectIntegral(self.stallSpinner.frame); + } +} + +- (void)layoutPlayerNotReadySpinner +{ + if (self.playerNotReadySpinner) { + CGSize screenSize = MPScreenBounds().size; + self.playerNotReadySpinner.center = CGPointMake(screenSize.width/2.0f, screenSize.height/2.0f); + self.playerNotReadySpinner.frame = CGRectIntegral(self.playerNotReadySpinner.frame); + } +} + +- (void)layoutGradientView +{ + if (UIInterfaceOrientationIsLandscape(MPInterfaceOrientation())) { + self.gradientView.hidden = NO; + } else { + self.gradientView.hidden = YES; + } + CGSize screenSize = MPScreenBounds().size; + self.gradient.frame = CGRectMake(0, 0, screenSize.width, kGradientHeight); + self.gradientView.frame = CGRectMake(0, 0, screenSize.width, kGradientHeight); +} + +#pragma mark - button tap + +- (void)closeButtonTapped +{ + [self dismissViewControllerAnimated:NO completion:^{ + if (self.dismissBlock) { + self.dismissBlock(self.originalParentView); + } + }]; +} + +- (void)ctaButtonTapped +{ + if ([self.delegate respondsToSelector:@selector(ctaTapped:)]) { + [self.delegate ctaTapped:self]; + } + [self.displayAgent displayDestinationForURL:self.playerController.defaultActionURL]; +} + +- (void)daaButtonTapped +{ + [self.displayAgent displayDestinationForURL:[NSURL URLWithString:kDAAIconTapDestinationURL]]; +} + +#pragma mark - MOPUBPlayerViewControllerDelegate + +- (void)playerPlaybackDidStart:(MOPUBPlayerViewController *)player +{ + [self removePlayerNotReadySpinner]; +} + +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController willShowReplayView:(MOPUBPlayerView *)view +{ + [self.view bringSubviewToFront:self.daaButton]; +} + +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController didStall:(MOPUBAVPlayer *)player +{ + if (self.stallSpinner) { + if (!self.stallSpinner.superview) { + [self.view addSubview:self.stallSpinner]; + } + if (!self.stallSpinner.isAnimating) { + [self.stallSpinner startAnimating]; + } + } else { + [self showStallSpinner]; + [self.stallSpinner startAnimating]; + } +} + +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController didRecoverFromStall:(MOPUBAVPlayer *)player +{ + [self hideStallSpinner]; +} + +- (void)playerDidProgressToTime:(NSTimeInterval)playbackTime +{ + if ([self.delegate respondsToSelector:@selector(playerDidProgressToTime:)]) { + [self.delegate playerDidProgressToTime:playbackTime]; + } +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return self; +} + +- (void)displayAgentWillPresentModal +{ + [self.playerController pause]; +} + +- (void)displayAgentWillLeaveApplication +{ + [self.playerController pause]; + [self.delegate fullscreenPlayerWillLeaveApplication:self]; +} + +- (void)displayAgentDidDismissModal +{ + [self.playerController resume]; +} + +#pragma mark - Hidding status bar (pre-iOS 7) + +- (void)setApplicationStatusBarHidden:(BOOL)hidden +{ + [[UIApplication sharedApplication] mp_preIOS7setApplicationStatusBarHidden:hidden]; +} + +#pragma mark - Hidding status bar (iOS 7 and above) + +- (BOOL)prefersStatusBarHidden +{ + return YES; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.h new file mode 100644 index 000000000..a4b62d887 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.h @@ -0,0 +1,23 @@ +// +// MOPUBNativeVideoAdAdapter.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeAdAdapter.h" + +@class MPAdConfiguration; + +@interface MOPUBNativeVideoAdAdapter : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, readonly) NSArray *impressionTrackerURLs; +@property (nonatomic, readonly) NSArray *clickTrackerURLs; +@property (nonatomic) MPAdConfiguration *adConfiguration; + +- (instancetype)initWithAdProperties:(NSMutableDictionary *)properties; + +- (void)handleVideoViewImpression; +- (void)handleVideoViewClick; +- (void)handleVideoHasProgressedToTime:(NSTimeInterval)playbackTime; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.m new file mode 100644 index 000000000..65f38f0fa --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdAdapter.m @@ -0,0 +1,188 @@ +// +// MOPUBNativeVideoAdAdapter.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoAdAdapter.h" +#import "MPNativeAdError.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPCoreInstanceProvider.h" +#import "MPNativeAdConstants.h" +#import "MPLogging.h" +#import "MPStaticNativeAdImpressionTimer.h" +#import "MOPUBNativeVideoAdConfigValues.h" + +@interface MOPUBNativeVideoAdAdapter() + +@property (nonatomic) MPStaticNativeAdImpressionTimer *staticImpressionTimer; +@property (nonatomic, readonly) MPAdDestinationDisplayAgent *destinationDisplayAgent; + +@end + +@implementation MOPUBNativeVideoAdAdapter + +@synthesize properties = _properties; +@synthesize defaultActionURL = _defaultActionURL; + +- (instancetype)initWithAdProperties:(NSMutableDictionary *)properties +{ + if (self = [super init]) { + + // Let's make sure the data types of all the provided native ad properties are strings before creating the adapter. + + NSArray *keysToCheck = @[kAdIconImageKey, kAdMainImageKey, kAdTextKey, kAdTitleKey, kAdCTATextKey, kVASTVideoKey]; + + for (NSString *key in keysToCheck) { + id value = properties[key]; + if (value != nil && ![value isKindOfClass:[NSString class]]) { + return nil; + } + } + + BOOL valid = YES; + NSArray *impressionTrackers = [properties objectForKey:kImpressionTrackerURLsKey]; + if (![impressionTrackers isKindOfClass:[NSArray class]] || [impressionTrackers count] < 1) { + valid = NO; + } else { + _impressionTrackerURLs = MPConvertStringArrayToURLArray(impressionTrackers); + } + + NSObject *clickTracker = [properties objectForKey:kClickTrackerURLKey]; + + // The click tracker could either be a single URL or an array of URLS. + if ([clickTracker isKindOfClass:[NSArray class]]) { + _clickTrackerURLs = MPConvertStringArrayToURLArray((NSArray *)clickTracker); + } else if ([clickTracker isKindOfClass:[NSString class]]) { + NSURL *url = [NSURL URLWithString:(NSString *)clickTracker]; + if (url) { + _clickTrackerURLs = @[ url ]; + } else { + valid = NO; + } + } else { + valid = NO; + } + + _defaultActionURL = [NSURL URLWithString:[properties objectForKey:kDefaultActionURLKey]]; + + [properties removeObjectsForKeys:[NSArray arrayWithObjects:kImpressionTrackerURLsKey, kClickTrackerURLKey, kDefaultActionURLKey, nil]]; + _properties = properties; + + if (!valid) { + return nil; + } + + // Add the DAA icon settings to our properties dictionary. + [properties setObject:MPResourcePathForResource(kDAAIconImageName) forKey:kAdDAAIconImageKey]; + + _destinationDisplayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + + _staticImpressionTimer = nil; + } + + return self; +} + +- (void)dealloc +{ + [self removeStaticImpressionTimer]; + [_destinationDisplayAgent cancel]; + [_destinationDisplayAgent setDelegate:nil]; + _delegate = nil; +} + +#pragma mark - Private + +- (void)removeStaticImpressionTimer +{ + _staticImpressionTimer.delegate = nil; + _staticImpressionTimer = nil; +} + +#pragma mark - + +- (void)willAttachToView:(UIView *)view +{ + [self removeStaticImpressionTimer]; + + // Set up a static impression timer that will fire the mopub impression if the video fails to play prior to meeting the video impression tracking requirements. + MOPUBNativeVideoAdConfigValues *nativeVideoAdConfig = [self.properties objectForKey:kNativeVideoAdConfigKey]; + + // impressionMinVisiblePercent is an integer (a value of 50 means 50%) while the impression timer takes in a float (.50 means 50%) so we have to multiply it by .01f. + self.staticImpressionTimer = [[MPStaticNativeAdImpressionTimer alloc] initWithRequiredSecondsForImpression:nativeVideoAdConfig.impressionVisible requiredViewVisibilityPercentage:nativeVideoAdConfig.impressionMinVisiblePercent*0.01f]; + self.staticImpressionTimer.delegate = self; + + [self.staticImpressionTimer startTrackingView:view]; +} + +- (void)displayContentForURL:(NSURL *)URL rootViewController:(UIViewController *)controller +{ + if (!controller) { + return; + } + + if (!URL || ![URL isKindOfClass:[NSURL class]] || ![URL.absoluteString length]) { + return; + } + + [self.destinationDisplayAgent displayDestinationForURL:URL]; +} + +#pragma mark - DAA Icon + +- (void)displayContentForDAAIconTap +{ + [self.destinationDisplayAgent displayDestinationForURL:[NSURL URLWithString:kDAAIconTapDestinationURL]]; +} + +#pragma mark - Impression and click tracking. Renderer calls those two methods + +- (void)handleVideoViewImpression +{ + [self.delegate nativeAdWillLogImpression:self]; +} + +- (void)handleVideoViewClick +{ + [self.delegate nativeAdDidClick:self]; +} + +- (void)handleVideoHasProgressedToTime:(NSTimeInterval)playbackTime +{ + // If the video makes progress, don't allow static impression tracking. + self.staticImpressionTimer.delegate = nil; + self.staticImpressionTimer = nil; +} + +#pragma mark - + +- (void)trackImpression +{ + // We'll fire a static impression if the video hasn't started playing by the time the static impression timer has met its requirements. + [self.delegate nativeAdWillLogImpression:self]; +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)displayAgentWillPresentModal +{ + [self.delegate nativeAdWillPresentModalForAdapter:self]; +} + +- (void)displayAgentWillLeaveApplication +{ + [self.delegate nativeAdWillLeaveApplicationFromAdapter:self]; +} + +- (void)displayAgentDidDismissModal +{ + [self.delegate nativeAdDidDismissModalForAdapter:self]; +} + +// -adConfiguration delegate method is automatically implemented via the adConfiguration property declaration. +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.h new file mode 100644 index 000000000..b50d6427a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.h @@ -0,0 +1,26 @@ +// +// MOPUBNativeVideoAdConfigValues.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@interface MOPUBNativeVideoAdConfigValues : NSObject + +@property (nonatomic, readonly) NSInteger playVisiblePercent; +@property (nonatomic, readonly) NSInteger pauseVisiblePercent; +@property (nonatomic, readonly) NSInteger impressionMinVisiblePercent; +@property (nonatomic, readonly) NSTimeInterval impressionVisible; +@property (nonatomic, readonly) NSTimeInterval maxBufferingTime; +@property (nonatomic, readonly) NSDictionary *trackers; + +- (instancetype)initWithPlayVisiblePercent:(NSInteger)playVisiblePercent + pauseVisiblePercent:(NSInteger)pauseVisiblePercent + impressionMinVisiblePercent:(NSInteger)impressionMinVisiblePercent + impressionVisible:(NSTimeInterval)impressionVisible + maxBufferingTime:(NSTimeInterval)maxBufferingTime trackers:(NSDictionary *)trackers; +- (BOOL)isValid; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.m new file mode 100644 index 000000000..8b471f251 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoAdConfigValues.m @@ -0,0 +1,49 @@ +// +// MOPUBNativeVideoAdConfigValues.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoAdConfigValues.h" + +@implementation MOPUBNativeVideoAdConfigValues + +- (instancetype)initWithPlayVisiblePercent:(NSInteger)playVisiblePercent + pauseVisiblePercent:(NSInteger)pauseVisiblePercent + impressionMinVisiblePercent:(NSInteger)impressionMinVisiblePercent + impressionVisible:(NSTimeInterval)impressionVisible + maxBufferingTime:(NSTimeInterval)maxBufferingTime trackers:(NSDictionary *)trackers +{ + self = [super init]; + if (self) { + _playVisiblePercent = playVisiblePercent; + _pauseVisiblePercent = pauseVisiblePercent; + _impressionMinVisiblePercent = impressionMinVisiblePercent; + _impressionVisible = impressionVisible; + _maxBufferingTime = maxBufferingTime; + _trackers = trackers; + } + return self; +} + +- (BOOL)isValid +{ + return ([self isValidPercentage:self.playVisiblePercent] && + [self isValidPercentage:self.pauseVisiblePercent] && + [self isValidPercentage:self.impressionMinVisiblePercent] && + [self isValidTimeInterval:self.impressionVisible] && + [self isValidTimeInterval:self.maxBufferingTime]); +} + +- (BOOL)isValidPercentage:(NSInteger)percentage +{ + return (percentage >= 0 && percentage <= 100); +} + +- (BOOL)isValidTimeInterval:(NSTimeInterval)timeInterval +{ + return timeInterval > 0; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.h new file mode 100644 index 000000000..e24df7e59 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.h @@ -0,0 +1,12 @@ +// +// MOPUBNativeVideoCustomEvent.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeCustomEvent.h" + +@interface MOPUBNativeVideoCustomEvent : MPNativeCustomEvent + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.m new file mode 100644 index 000000000..3d30aa864 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoCustomEvent.m @@ -0,0 +1,76 @@ +// +// MOPUBNativeVideoCustomEvent.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPNativeAd.h" +#import "MPNativeAdError.h" +#import "MPNativeAdUtils.h" +#import "MPNativeAdConstants.h" +#import "MOPUBNativeVideoAdAdapter.h" +#import "MOPUBNativeVideoAdConfigValues.h" +#import "MOPUBNativeVideoCustomEvent.h" +#import "MPLogging.h" +#import "MPVideoConfig.h" +#import "MPVASTManager.h" +#import "MPNativeAd+Internal.h" + +@implementation MOPUBNativeVideoCustomEvent + +- (void)handleSuccessfulVastParsing:(MPVASTResponse *)mpVastResponse info:(NSDictionary *)info +{ + NSMutableDictionary *infoMutableCopy = [info mutableCopy]; + [infoMutableCopy setObject:[[MPVideoConfig alloc] initWithVASTResponse:mpVastResponse additionalTrackers:((MOPUBNativeVideoAdConfigValues *)info[kNativeVideoAdConfigKey]).trackers] forKey:kVideoConfigKey]; + MOPUBNativeVideoAdAdapter *adAdapter = [[MOPUBNativeVideoAdAdapter alloc] initWithAdProperties:infoMutableCopy]; + if (adAdapter.properties) { + MPNativeAd *interfaceAd = [[MPNativeAd alloc] initWithAdAdapter:adAdapter]; + [interfaceAd.impressionTrackerURLs addObjectsFromArray:adAdapter.impressionTrackerURLs]; + [interfaceAd.clickTrackerURLs addObjectsFromArray:adAdapter.clickTrackerURLs]; + // Get the image urls so we can download them prior to returning the ad. + NSMutableArray *imageURLs = [NSMutableArray array]; + for (NSString *key in [info allKeys]) { + if ([[key lowercaseString] hasSuffix:@"image"] && [[info objectForKey:key] isKindOfClass:[NSString class]]) { + if (![MPNativeAdUtils addURLString:[info objectForKey:key] toURLArray:imageURLs]) { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidImageURL()]; + } + } + } + + [super precacheImagesWithURLs:imageURLs completionBlock:^(NSArray *errors) { + if (errors) { + MPLogDebug(@"%@", errors); + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForImageDownloadFailure()]; + } else { + [self.delegate nativeCustomEvent:self didLoadAd:interfaceAd]; + } + }]; + } else { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForInvalidAdServerResponse(nil)]; + } +} + +- (void)requestAdWithCustomEventInfo:(NSDictionary *)info +{ + MOPUBNativeVideoAdConfigValues *nativeVideoAdConfigValues = [info objectForKey:kNativeVideoAdConfigKey]; + if (nativeVideoAdConfigValues && [nativeVideoAdConfigValues isValid]) { + NSString *vastString = [info objectForKey:kVASTVideoKey]; + if (vastString) { + [MPVASTManager fetchVASTWithData:[vastString dataUsingEncoding:NSUTF8StringEncoding] + completion: ^(MPVASTResponse *mpVastResponse, NSError *error) { + if (error) { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForVASTParsingFailure()]; + } else { + [self handleSuccessfulVastParsing:mpVastResponse info:info]; + } + }]; + } else { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForVASTParsingFailure()]; + } + } else { + [self.delegate nativeCustomEvent:self didFailToLoadAdWithError:MPNativeAdNSErrorForVideoConfigInvalid()]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.h new file mode 100644 index 000000000..c8c9d5958 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.h @@ -0,0 +1,16 @@ +// +// MOPUBNativeVideoImpressionAgent.h +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@interface MOPUBNativeVideoImpressionAgent : NSObject + +- (instancetype)initWithVideoView:(UIView *)videoView requiredVisibilityPercentage:(CGFloat)visiblePercentage requiredPlaybackDuration:(NSTimeInterval)playbackDuration; + +- (BOOL)shouldTrackImpressionWithCurrentPlaybackTime:(NSTimeInterval)currentPlaybackTime; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.m new file mode 100644 index 000000000..67a0f1f73 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBNativeVideoImpressionAgent.m @@ -0,0 +1,62 @@ +// +// MOPUBNativeVideoImpressionAgent.m +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoImpressionAgent.h" +#import "MPGlobal.h" + +static const NSTimeInterval kInvalidTimestamp = -1; + +@interface MOPUBNativeVideoImpressionAgent () + +@property (nonatomic) CGFloat requiredVisiblePercentage; +@property (nonatomic) NSTimeInterval requiredPlaybackDuration; +@property (nonatomic) NSTimeInterval visibilitySatisfiedPlaybackTime; +@property (nonatomic, weak) UIView *measuredVideoView; +@property (nonatomic) BOOL requirementsSatisfied; + +@end + +@implementation MOPUBNativeVideoImpressionAgent + +- (instancetype)initWithVideoView:(UIView *)videoView requiredVisibilityPercentage:(CGFloat)visiblePercentage requiredPlaybackDuration:(NSTimeInterval)playbackDuration +{ + self = [super init]; + + if (self) { + _measuredVideoView = videoView; + _requiredVisiblePercentage = visiblePercentage; + _requiredPlaybackDuration = playbackDuration; + _visibilitySatisfiedPlaybackTime = kInvalidTimestamp; + _requirementsSatisfied = NO; + } + + return self; +} + +- (BOOL)shouldTrackImpressionWithCurrentPlaybackTime:(NSTimeInterval)currentPlaybackTime +{ + // this class's work is done once the requirements are met + if (!self.requirementsSatisfied) { + if (MPViewIntersectsParentWindowWithPercent(self.measuredVideoView, self.requiredVisiblePercentage)) { + // if this is the first time we satisfied the visibility requirement or + // if the user replays the video and we haven't satisfied the impression yet, set satisfied playback timestamp + if (self.visibilitySatisfiedPlaybackTime == kInvalidTimestamp || self.visibilitySatisfiedPlaybackTime > currentPlaybackTime) { + self.visibilitySatisfiedPlaybackTime = currentPlaybackTime; + } + + // we consider the requirements met if the visibility requirements are met for requiredPlaybackDuration seconds of actual continuous playback + if (currentPlaybackTime - self.visibilitySatisfiedPlaybackTime >= self.requiredPlaybackDuration) { + self.requirementsSatisfied = YES; + } + } else { + self.visibilitySatisfiedPlaybackTime = kInvalidTimestamp; + } + } + + return self.requirementsSatisfied; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.h new file mode 100644 index 000000000..ffb512200 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.h @@ -0,0 +1,20 @@ +// +// MOPUBPlayerManager.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +@class MOPUBPlayerViewController; +@class MOPUBNativeVideoAdConfigValues; +@class MPVideoConfig; +@class MPAdConfigurationLogEventProperties; + +@interface MOPUBPlayerManager : NSObject + ++ (MOPUBPlayerManager *)sharedInstance; +- (void)disposePlayerViewController; + +- (MOPUBPlayerViewController *)playerViewControllerWithVideoConfig:(MPVideoConfig *)videoConfig nativeVideoAdConfig:(MOPUBNativeVideoAdConfigValues *)nativeVideoAdConfig logEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.m new file mode 100644 index 000000000..195a79007 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerManager.m @@ -0,0 +1,47 @@ +// +// MOPUBPlayerManager.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBPlayerManager.h" +#import "MOPUBPlayerViewController.h" +#import "MOPUBNativeVideoAdRenderer.h" +#import "MPVideoConfig.h" +#import "MOPUBNativeVideoAdConfigValues.h" + +@interface MOPUBPlayerManager() + +@property (nonatomic) MOPUBPlayerViewController *currentPlayerViewController; + +@end + +@implementation MOPUBPlayerManager + ++ (MOPUBPlayerManager *)sharedInstance +{ + static MOPUBPlayerManager *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[MOPUBPlayerManager alloc] init]; + }); + return sharedInstance; +} + +- (void)disposePlayerViewController +{ + [self.currentPlayerViewController dispose]; + self.currentPlayerViewController = nil; +} + +- (MOPUBPlayerViewController *)playerViewControllerWithVideoConfig:(MPVideoConfig *)videoConfig nativeVideoAdConfig:(MOPUBNativeVideoAdConfigValues *)nativeVideoAdConfig logEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties +{ + // make sure only one instance of avPlayer at a time + if (self.currentPlayerViewController) { + [self disposePlayerViewController]; + } + + self.currentPlayerViewController = [[MOPUBPlayerViewController alloc] initWithVideoConfig:videoConfig nativeVideoAdConfig:nativeVideoAdConfig logEventProperties:logEventProperties]; + return self.currentPlayerViewController; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.h new file mode 100644 index 000000000..db32cf4b5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.h @@ -0,0 +1,38 @@ +// +// MPPlayerView.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBAVPlayer.h" + +@class MOPUBPlayerView; + +typedef NS_ENUM(NSUInteger, MOPUBPlayerDisplayMode) { + MOPUBPlayerDisplayModeInline = 0, + MOPUBPlayerDisplayModeFullscreen +}; + +@protocol MOPUBPlayerViewDelegate + +- (void)playerViewDidTapReplayButton:(MOPUBPlayerView *)view; +- (void)playerViewWillShowReplayView:(MOPUBPlayerView *)view; +- (void)playerViewWillEnterFullscreen:(MOPUBPlayerView *)view; + +@end + +@interface MOPUBPlayerView : UIControl + +@property (nonatomic) MOPUBAVPlayer *avPlayer; +@property (nonatomic) MOPUBPlayerDisplayMode displayMode; +@property (nonatomic, copy) NSString *videoGravity; + +- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate; + +- (void)createPlayerView; +- (void)playbackTimeDidProgress; +- (void)playbackDidFinish; +- (void)setProgressBarVisible:(BOOL)visible; +- (void)handleVideoInitFailure; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.m new file mode 100644 index 000000000..622e69bea --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerView.m @@ -0,0 +1,227 @@ +// +// MPPlayerView.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MOPUBAVPlayerView.h" +#import "MOPUBAVPlayer.h" +#import "MOPUBAVPlayerView.h" +#import "MOPUBPlayerView.h" +#import "MOPUBPlayerViewController.h" +#import "MOPUBReplayView.h" +#import "UIView+MPAdditions.h" +#import "UIColor+MPAdditions.h" + +static NSString * const kProgressBarFillColor = @"#FFCC4D"; +static CGFloat const kVideoProgressBarHeight = 4.0f; + +// gradient +static NSString * const kTopGradientColor = @"#000000"; +static NSString * const kBottomGradientColor = @"#000000"; +static CGFloat const kTopGradientAlpha = 0.0f; +static CGFloat const kBottomGradientAlpha = 0.4f; +static CGFloat const kGradientViewHeight = 25.0f; + +@interface MOPUBPlayerView() + +// UI elements +@property (nonatomic) MOPUBAVPlayerView *avView; +@property (nonatomic) MOPUBReplayView *replayView; +@property (nonatomic) UIButton *replayVideoButton; +@property (nonatomic) UIView *progressBarBackground; +@property (nonatomic) UIView *progressBar; +@property (nonatomic) UIView *gradientView; +@property (nonatomic) CAGradientLayer *gradient; + +@property (nonatomic) UITapGestureRecognizer *tapGestureRecognizer; +@property (nonatomic, weak) id delegate; + +@end + +@implementation MOPUBPlayerView + +- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate +{ + self = [super initWithFrame:frame]; + if (self) { + _delegate = delegate; + + _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(avPlayerTapped)]; + [self addGestureRecognizer:_tapGestureRecognizer]; + } + return self; +} + +- (void)dealloc +{ + [self.tapGestureRecognizer removeTarget:self action:@selector(avPlayerTapped)]; +} + +- (void)createPlayerView +{ + self.clipsToBounds = YES; + if (!self.gradientView && self.displayMode == MOPUBPlayerDisplayModeInline) { + // Create the gradient + self.gradientView = [UIView new]; + UIColor *topColor = [UIColor mp_colorFromHexString:kTopGradientColor alpha:kTopGradientAlpha]; + UIColor *bottomColor = [UIColor mp_colorFromHexString:kBottomGradientColor alpha:kBottomGradientAlpha]; + self.gradient = [CAGradientLayer layer]; + self.gradient.colors = [NSArray arrayWithObjects: (id)topColor.CGColor, (id)bottomColor.CGColor, nil]; + self.gradient.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), kGradientViewHeight); + + //Add gradient to view + [self.gradientView.layer insertSublayer:self.gradient atIndex:0]; + [self addSubview:self.gradientView]; + } + + if (!self.progressBar) { + self.progressBar = [[UIView alloc] init]; + self.progressBarBackground = [[UIView alloc] init]; + [self addSubview:self.progressBarBackground]; + + self.progressBarBackground.backgroundColor = [UIColor colorWithRed:.5f green:.5f blue:.5f alpha:.5f]; + self.progressBar.backgroundColor = [UIColor mp_colorFromHexString:kProgressBarFillColor alpha:1.0f]; + [self addSubview:self.progressBar]; + } +} + +#pragma mark - set avPlayer + +- (void)setAvPlayer:(MOPUBAVPlayer *)player +{ + if (!player) { + MPLogError(@"Cannot set avPlayer to nil"); + return; + } + if (_avPlayer == player) { + return; + } + _avPlayer = player; + [_avView removeFromSuperview]; + _avView = [[MOPUBAVPlayerView alloc] initWithFrame:CGRectZero]; + _avView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.videoGravity = AVLayerVideoGravityResizeAspectFill; + self.avView.player = self.avPlayer; + self.avView.frame = (CGRect){CGPointZero, self.bounds.size}; + [self insertSubview:_avView atIndex:0]; +} + +- (void)setVideoGravity:(NSString *)videoGravity +{ + ((AVPlayerLayer *)_avView.layer).videoGravity = videoGravity; +} + +// make the player view not clickable when initializing video failed. +- (void)handleVideoInitFailure +{ + [self removeGestureRecognizer:self.tapGestureRecognizer]; +} + +#pragma mark - Synchronize UI Elements + +- (void)playbackTimeDidProgress +{ + [self layoutProgressBar]; +} + +- (void)playbackDidFinish +{ + if (!self.replayView) { + self.replayView = [[MOPUBReplayView alloc] initWithFrame:self.avView.bounds displayMode:self.displayMode]; + __weak typeof(self) weakSelf = self; + self.replayView.actionBlock = ^(MOPUBReplayView *view) { + __strong typeof(self) strongSelf = weakSelf; + if ([strongSelf.delegate respondsToSelector:@selector(playerViewDidTapReplayButton:)]) { + [strongSelf.delegate playerViewDidTapReplayButton:strongSelf]; + } + [strongSelf.replayView removeFromSuperview]; + strongSelf.replayView = nil; + }; + [self addSubview:self.replayView]; + + if ([self.delegate respondsToSelector:@selector(playerViewWillShowReplayView:)]) { + [self.delegate playerViewWillShowReplayView:self]; + } + } +} + +- (void)setProgressBarVisible:(BOOL)visible +{ + self.progressBarBackground.hidden = !visible; + self.progressBar.hidden = !visible; +} + +#pragma mark - Touch event + +- (void)avPlayerTapped +{ + // Only trigger tap event in infeed mode + if (self.displayMode == MOPUBPlayerDisplayModeInline) { + self.displayMode = MOPUBPlayerDisplayModeFullscreen; + if ([self.delegate respondsToSelector:@selector(playerViewWillEnterFullscreen:)]) { + [self.delegate playerViewWillEnterFullscreen:self]; + } + [self setNeedsLayout]; + [self layoutIfNeeded]; + } +} + +#pragma mark - layout views + +- (void)layoutSubviews +{ + [super layoutSubviews]; + + [self layoutProgressBar]; + [self layoutGradientview]; + [self layoutReplayView]; +} + +- (void)layoutProgressBar +{ + if (self.avPlayer && !isnan(self.avPlayer.currentItemDuration)) { + CGFloat vcWidth = CGRectGetWidth(self.bounds); + CGFloat currentProgress = self.avPlayer.currentPlaybackTime/self.avPlayer.currentItemDuration; + if (currentProgress < 0) { + currentProgress = 0; + MPLogError(@"Progress shouldn't be < 0"); + } + if (currentProgress > 1) { + currentProgress = 1; + MPLogError(@"Progress shouldn't be > 1"); + } + + self.progressBar.frame = CGRectMake(0, CGRectGetMaxY(self.avView.frame)- kVideoProgressBarHeight, vcWidth * currentProgress, kVideoProgressBarHeight); + self.progressBarBackground.frame = CGRectMake(0, CGRectGetMaxY(self.avView.frame) - kVideoProgressBarHeight, vcWidth, kVideoProgressBarHeight); + } +} + + +- (void)layoutGradientview +{ + if (self.displayMode == MOPUBPlayerDisplayModeInline) { + self.gradientView.hidden = NO; + self.gradient.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), kGradientViewHeight); + self.gradientView.frame = CGRectMake(0, CGRectGetMaxY(self.avView.frame) - kGradientViewHeight, CGRectGetWidth(self.bounds), kGradientViewHeight); + } else { + self.gradientView.hidden = YES; + } +} + +- (void)layoutReplayView +{ + if (self.replayView) { + CGSize screenSize = MPScreenBounds().size; + if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && self.displayMode == MOPUBPlayerDisplayModeFullscreen) { + self.replayView.frame = CGRectMake(0, 0, screenSize.width, screenSize.height); + } else { + self.replayView.frame = self.avView.frame; + } + [self.replayView setNeedsLayout]; + [self.replayView layoutIfNeeded]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.h new file mode 100644 index 000000000..34c7f5649 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.h @@ -0,0 +1,77 @@ +// +// MOPUBPlayerViewController.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBPlayerView.h" + +@class AVPlayerItem; +@class MOPUBAVPlayer; +@class MOPUBPlayerViewController; +@class MOPUBNativeVideoAdConfigValues; +@class MPAdConfigurationLogEventProperties; +@class MPVASTTracking; +@class MPVideoConfig; + +@protocol MOPUBPlayerViewControllerDelegate + +@optional + +- (void)willEnterFullscreen:(MOPUBPlayerViewController *)viewController; +- (void)playerPlaybackWillStart:(MOPUBPlayerViewController *)player; +- (void)playerPlaybackDidStart:(MOPUBPlayerViewController *)player; +- (void)playerDidProgressToTime:(NSTimeInterval)playbackTime; +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController didTapReplayButton:(MOPUBPlayerView *)view; +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController willShowReplayView:(MOPUBPlayerView *)view; +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController didStall:(MOPUBAVPlayer *)player; +- (void)playerViewController:(MOPUBPlayerViewController *)playerViewController didRecoverFromStall:(MOPUBAVPlayer *)player; + +- (UIViewController *)viewControllerForPresentingModalView; + +@end + +@interface MOPUBPlayerViewController : UIViewController + +@property (nonatomic, readonly) NSURL *mediaURL; + +@property (nonatomic, readonly) MOPUBPlayerView *playerView; +@property (nonatomic, readonly) AVPlayerItem *playerItem; +@property (nonatomic, readonly) MOPUBAVPlayer *avPlayer; +@property (nonatomic) MPVASTTracking *vastTracking; +@property (nonatomic, readonly) CGFloat videoAspectRatio; +@property (nonatomic, readonly) MOPUBNativeVideoAdConfigValues *nativeVideoAdConfig; + +#pragma mark - Configurations/States +@property (nonatomic) MOPUBPlayerDisplayMode displayMode; +@property (nonatomic) BOOL muted; +@property (nonatomic) BOOL startedLoading; +@property (nonatomic) BOOL playing; +@property (nonatomic) BOOL paused; +@property (nonatomic) BOOL isReadyToPlay; +@property (nonatomic) BOOL disposed; + +#pragma - Call to action click tracking url +@property (nonatomic) NSURL *defaultActionURL; + +@property (nonatomic, weak) id delegate; + +#pragma mark - Initializer +- (instancetype)initWithVideoConfig:(MPVideoConfig *)videoConfig nativeVideoAdConfig:(MOPUBNativeVideoAdConfigValues *)nativeVideoAdConfig logEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (void)loadAndPlayVideo; +- (void)seekToTime:(NSTimeInterval)time; +- (void)pause; +- (void)resume; +- (void)dispose; + +- (BOOL)shouldStartNewPlayer; +- (BOOL)shouldResumePlayer; +- (BOOL)shouldPausePlayer; + +- (void)willEnterFullscreen; +- (void)willExitFullscreen; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.m new file mode 100644 index 000000000..2daea1fb8 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBPlayerViewController.m @@ -0,0 +1,634 @@ +// +// MOPUBPlayerViewController.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBAVPlayer.h" +#import "MOPUBFullscreenPlayerViewController.h" +#import "MOPUBPlayerViewController.h" +#import "MOPUBActivityIndicatorView.h" +#import "MPAdDestinationDisplayAgent.h" +#import "MPCoreInstanceProvider.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MPLogEvent+NativeVideo.h" +#import "MPLogEventRecorder.h" +#import "MOPUBNativeVideoAdConfigValues.h" +#import "MPVastTracking.h" +#import "MPVideoConfig.h" +#import "UIView+MPAdditions.h" +#import "MOPUBNativeVideoAdConfigValues.h" +#import "MPVideoConfig.h" +#import "UIButton+MPAdditions.h" + +#define kDefaultVideoAspectRatio 16.0f/9.0f + +static NSString * const kMutedButtonImage = @"MPMutedBtn.png"; +static NSString * const kUnmutedButtonImage = @"MPUnmutedBtn.png"; + +static NSString * const kTracksKey = @"tracks"; +static NSString * const kPlayableKey = @"playable"; + +// playerItem keys +static NSString * const kStatusKey = @"status"; +static NSString * const kCurrentItemKey = @"currentItem"; +static NSString * const kLoadedTimeRangesKey = @"loadedTimeRanges"; +static void *AudioControllerBufferingObservationContext = &AudioControllerBufferingObservationContext; + +// UI specifications +static CGFloat const kMuteIconInlineModeLeftMargin = 6.0f; +static CGFloat const kMuteIconInlineModeBottomMargin = 5.0f; +static CGFloat const kMuteIconInlineModeTouchAreaInsets = 25.0f; + +static CGFloat const kLoadingIndicatorTopMargin = 8.0f; +static CGFloat const kLoadingIndicatorRightMargin = 8.0f; + +// force resume playback in 3 seconds. player might get stuck due to stalled item +static CGFloat const kDelayPlayInSeconds = 3.0f; + +// We compare the buffered time to the length of the video to determine when it has been +// fully buffered. To account for rounding errors, allow a small error when making this +// calculation. +static const double kVideoFinishedBufferingAllowedError = 0.1; + +@interface MOPUBPlayerViewController() + +@property (nonatomic) UIButton *muteButton; +@property (nonatomic) UIActivityIndicatorView *loadingIndicator; +@property (nonatomic) MPAdDestinationDisplayAgent *displayAgent; + +// KVO might be triggerd multipe times. This property is used to make sure the view will only be created once. +@property (nonatomic) BOOL alreadyInitialized; +@property (nonatomic) MPAdConfigurationLogEventProperties *logEventProperties; +@property (nonatomic) BOOL downloadFinishedEventFired; +@property (nonatomic) BOOL alreadyCreatedPlayerView; +@property (nonatomic) BOOL finishedPlaying; + +@end + +@implementation MOPUBPlayerViewController + +- (instancetype)initWithVideoConfig:(MPVideoConfig *)videoConfig nativeVideoAdConfig:(MOPUBNativeVideoAdConfigValues *)nativeVideoAdConfig logEventProperties:(MPAdConfigurationLogEventProperties *)logEventProperties +{ + if (self = [super init]) { + _mediaURL = videoConfig.mediaURL; + _playerView = [[MOPUBPlayerView alloc] initWithFrame:CGRectZero delegate:self]; + self.displayMode = MOPUBPlayerDisplayModeInline; + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(applicationDidEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + _nativeVideoAdConfig = nativeVideoAdConfig; + _logEventProperties = logEventProperties; + + // default aspect ratio is 16:9 + _videoAspectRatio = kDefaultVideoAspectRatio; + } + return self; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self.view addSubview:self.playerView]; + [self startLoadingIndicator]; +} + +- (void)viewWillLayoutSubviews +{ + [super viewWillLayoutSubviews]; + + // Bring mute button to front. This is necessary because the video view might be detached + // and re-attached during fullscreen to in-feed transition + [self.view bringSubviewToFront:self.muteButton]; + // Set playerView's frame so it will work for rotation + self.playerView.frame = self.view.bounds; + + [self layoutLoadingIndicator]; +} + +- (void)layoutLoadingIndicator +{ + if (_loadingIndicator) { + _loadingIndicator.mp_x = CGRectGetWidth(self.view.bounds) - kLoadingIndicatorRightMargin - CGRectGetWidth(_loadingIndicator.bounds); + _loadingIndicator.mp_y = kLoadingIndicatorTopMargin; + } +} + +#pragma mark - dealloc or dispose the controller + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + if (self.avPlayer) { + [self.avPlayer removeObserver:self forKeyPath:kStatusKey]; + } + + if (self.playerItem) { + [self.playerItem removeObserver:self forKeyPath:kStatusKey]; + [self.playerItem removeObserver:self forKeyPath:kLoadedTimeRangesKey]; + } + + MPLogDebug(@"playerViewController dealloc called"); +} + +- (void)dispose +{ + [self.view removeFromSuperview]; + [self.avPlayer dispose]; + self.avPlayer = nil; + self.disposed = YES; +} + +#pragma mark - load asset, set up aVplayer and avPlayer view + +- (void)handleVideoInitError +{ + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeErrorFailedToPlay]); + [self.vastTracking handleVideoEvent:MPVideoEventTypeError videoTimeOffset:self.avPlayer.currentPlaybackTime]; + [self stopLoadingIndicator]; + [self.playerView handleVideoInitFailure]; +} + +- (void)loadAndPlayVideo +{ + self.startedLoading = YES; + + AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:self.mediaURL options:nil]; + + if (asset == nil) { + MPLogError(@"failed to initialize video asset for URL %@", self.mediaURL); + [self handleVideoInitError]; + + return; + } + + MPAddLogEvent([[MPLogEvent alloc ] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeDownloadStart]); + + NSArray *requestedKeys = @[kTracksKey, kPlayableKey]; + [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (!self.disposed) { + [self prepareToPlayAsset:asset withKeys:requestedKeys]; + } + }); + }]; +} + +- (void)setVideoAspectRatioWithAsset:(AVURLAsset *)asset +{ + if (asset && [asset tracksWithMediaType:AVMediaTypeVideo].count > 0) { + AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0]; + CGSize naturalSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform); + naturalSize = CGSizeMake(fabs(naturalSize.width), fabs(naturalSize.height)); + + // make sure the natural size is at least 1pt (not 0) check + if (naturalSize.height > 0 && naturalSize.width > 0) { + _videoAspectRatio = naturalSize.width / naturalSize.height; + } + } +} + +- (void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys +{ + NSError *error = nil; + + if (!asset.playable) { + MPLogError(@"asset is not playable"); + [self handleVideoInitError]; + + return; + } + + AVKeyValueStatus status = [asset statusOfValueForKey:kTracksKey error:&error]; + if (status == AVKeyValueStatusFailed) { + MPLogError(@"AVKeyValueStatusFailed"); + [self handleVideoInitError]; + + return; + } else if (status == AVKeyValueStatusLoaded) { + [self setVideoAspectRatioWithAsset:asset]; + + self.playerItem = [AVPlayerItem playerItemWithAsset:asset]; + self.avPlayer = [[MOPUBAVPlayer alloc] initWithDelegate:self playerItem:self.playerItem]; + self.avPlayer.muted = YES; + + [self.playerView setAvPlayer:self.avPlayer]; + } +} + +#pragma mark - video ready to play +- (void)initOnVideoReady +{ + [self startPlayer]; + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeVideoReady]); +} + +- (void)createView +{ + [self.playerView createPlayerView]; + [self createMuteButton]; +} + +- (void)createMuteButton +{ + if (!self.muteButton) { + self.muteButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [self.muteButton setImage:[UIImage imageNamed:MPResourcePathForResource(kMutedButtonImage)] forState:UIControlStateNormal]; + [self.muteButton setImage:[UIImage imageNamed:MPResourcePathForResource(kUnmutedButtonImage)] forState:UIControlStateSelected]; + [self.muteButton addTarget:self action:@selector(muteButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + self.muteButton.mp_TouchAreaInsets = UIEdgeInsetsMake(kMuteIconInlineModeTouchAreaInsets, kMuteIconInlineModeTouchAreaInsets, kMuteIconInlineModeTouchAreaInsets, kMuteIconInlineModeTouchAreaInsets); + [self.muteButton sizeToFit]; + [self.view addSubview:self.muteButton]; + self.muteButton.frame = CGRectMake(kMuteIconInlineModeLeftMargin, CGRectGetMaxY(self.view.bounds) - kMuteIconInlineModeBottomMargin - CGRectGetHeight(self.muteButton.bounds), CGRectGetWidth(self.muteButton.bounds), CGRectGetHeight(self.muteButton.bounds)); + } +} + +- (void)startPlayer +{ + [self.avPlayer play]; + self.playing = YES; + self.isReadyToPlay = YES; + if ([self.delegate respondsToSelector:@selector(playerPlaybackDidStart:)]) { + [self.delegate playerPlaybackDidStart:self]; + } +} + +#pragma mark - displayAgent + +- (MPAdDestinationDisplayAgent *)displayAgent +{ + if (!_displayAgent) { + _displayAgent = [[MPCoreInstanceProvider sharedProvider] buildMPAdDestinationDisplayAgentWithDelegate:self]; + } + return _displayAgent; +} + + +#pragma mark - setter for player related objects + +- (void)setPlayerItem:(AVPlayerItem *)playerItem +{ + if (_playerItem) { + [_playerItem removeObserver:self forKeyPath:kStatusKey]; + [_playerItem removeObserver:self forKeyPath:kLoadedTimeRangesKey]; + } + _playerItem = playerItem; + if (!playerItem) { + return; + } + + [_playerItem addObserver:self forKeyPath:kStatusKey options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil]; + [_playerItem addObserver:self + forKeyPath:kLoadedTimeRangesKey + options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew + context:AudioControllerBufferingObservationContext]; +} + +- (void)setAvPlayer:(MOPUBAVPlayer *)avPlayer +{ + if (_avPlayer) { + [_avPlayer removeObserver:self forKeyPath:kStatusKey]; + } + _avPlayer = avPlayer; + if (_avPlayer) { + NSKeyValueObservingOptions options = (NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew); + [_avPlayer addObserver:self forKeyPath:kStatusKey options:options context:nil]; + } +} + +- (void)setMuted:(BOOL)muted +{ + _muted = muted; + [self.muteButton setSelected:!muted]; + self.avPlayer.muted = muted; +} + +#pragma mark - displayMode + +- (MOPUBPlayerDisplayMode)displayMode +{ + return self.playerView.displayMode; +} + +- (void)setDisplayMode:(MOPUBPlayerDisplayMode)displayMode +{ + self.playerView.displayMode = displayMode; + if (displayMode == MOPUBPlayerDisplayModeInline) { + self.muted = YES; + } else { + self.muted = NO; + } +} + +#pragma mark - acvivityIndicator +- (UIActivityIndicatorView *)loadingIndicator +{ + if (!_loadingIndicator) { + _loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + _loadingIndicator.hidesWhenStopped = YES; + _loadingIndicator.color = [UIColor whiteColor]; + [self.view addSubview:_loadingIndicator]; + } + return _loadingIndicator; +} + +- (void)startLoadingIndicator +{ + [self.loadingIndicator.superview bringSubviewToFront:_loadingIndicator]; + [self.loadingIndicator startAnimating]; +} + +- (void)stopLoadingIndicator +{ + if (_loadingIndicator && _loadingIndicator.isAnimating) { + [_loadingIndicator stopAnimating]; + } +} + +- (void)removeLoadingIndicator +{ + if (_loadingIndicator) { + [_loadingIndicator stopAnimating]; + [_loadingIndicator removeFromSuperview]; + _loadingIndicator = nil; + } +} + + +#pragma mark - Tap actions + +- (void)muteButtonTapped +{ + self.muteButton.selected = !self.muteButton.selected; + self.muted = !self.muteButton.selected; + + MPVideoEventType eventType = self.muted ? MPVideoEventTypeMuted : MPVideoEventTypeUnmuted; + [self.vastTracking handleVideoEvent:eventType videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +# pragma mark - KVO + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (object == self.avPlayer) { + if (self.avPlayer.status == AVPlayerItemStatusFailed) { + if (self.isReadyToPlay) { + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeErrorDuringPlayback]); + } else { + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeErrorFailedToPlay]); + } + MPLogError(@"avPlayer status failed"); + [self.vastTracking handleVideoEvent:MPVideoEventTypeError videoTimeOffset:self.avPlayer.currentPlaybackTime]; + } + } else if (object == self.playerItem) { + if (context == AudioControllerBufferingObservationContext) { + NSArray *timeRangeArray = [self.playerItem loadedTimeRanges]; + if (timeRangeArray && timeRangeArray.count > 0) { + CMTimeRange aTimeRange = [[timeRangeArray objectAtIndex:0] CMTimeRangeValue]; + double startTime = CMTimeGetSeconds(aTimeRange.start); + double loadedDuration = CMTimeGetSeconds(aTimeRange.duration); + double videoDuration = CMTimeGetSeconds(self.playerItem.duration); + if ((startTime + loadedDuration + kVideoFinishedBufferingAllowedError) >= videoDuration && !self.downloadFinishedEventFired) { + self.downloadFinishedEventFired = YES; + MPAddLogEvent([[MPLogEvent alloc ] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeDownloadFinished]); + } + } + } + if ([keyPath isEqualToString:kStatusKey]) { + switch (self.playerItem.status) { + case AVPlayerItemStatusReadyToPlay: + self.vastTracking.videoDuration = CMTimeGetSeconds(self.playerItem.duration); + if (!self.alreadyInitialized) { + self.alreadyInitialized = YES; + [self initOnVideoReady]; + } + break; + case AVPlayerItemStatusFailed: + { + MPLogError(@"avPlayerItem status failed"); + [self.vastTracking handleVideoEvent:MPVideoEventTypeError videoTimeOffset:self.avPlayer.currentPlaybackTime]; + break; + } + default: + break; + } + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +#pragma mark - player controls + +- (void)pause +{ + self.paused = YES; + self.playing = NO; + [self.avPlayer pause]; + [self.vastTracking handleVideoEvent:MPVideoEventTypePause videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +- (void)resume +{ + self.paused = NO; + self.playing = YES; + [self.avPlayer play]; + [self.vastTracking handleVideoEvent:MPVideoEventTypeResume videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +- (void)seekToTime:(NSTimeInterval)time +{ + [self.avPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; +} + +#pragma mark - auto play helper method +- (BOOL)shouldStartNewPlayer +{ + UIApplicationState state = [[UIApplication sharedApplication] applicationState]; + if (!self.startedLoading && !self.playing && !self.paused && state == UIApplicationStateActive) { + return YES; + } + return NO; +} + +- (BOOL)shouldResumePlayer +{ + UIApplicationState state = [[UIApplication sharedApplication] applicationState]; + if (self.startedLoading && self.paused == YES && self.displayMode == MOPUBPlayerDisplayModeInline + && state == UIApplicationStateActive) { + return YES; + } + return NO; +} + +- (BOOL)shouldPausePlayer +{ + if (self.playing && self.displayMode == MOPUBPlayerDisplayModeInline) { + return YES; + } + return NO; +} + +#pragma mark - enter fullscreen or exit fullscreen + +- (void)willEnterFullscreen +{ + self.displayMode = MOPUBPlayerDisplayModeFullscreen; + [self.vastTracking handleVideoEvent:MPVideoEventTypeFullScreen videoTimeOffset:self.avPlayer.currentPlaybackTime]; + [self.vastTracking handleVideoEvent:MPVideoEventTypeExpand videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +- (void)willExitFullscreen +{ + self.displayMode = MOPUBPlayerDisplayModeInline; + [self.vastTracking handleVideoEvent:MPVideoEventTypeExitFullScreen videoTimeOffset:self.avPlayer.currentPlaybackTime]; + [self.vastTracking handleVideoEvent:MPVideoEventTypeCollapse videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +#pragma mark - MOPUBAVPlayerDelegate + +- (void)avPlayer:(MOPUBAVPlayer *)player playbackTimeDidProgress:(NSTimeInterval)currentPlaybackTime +{ + // stop the loading indicator if it exists and is animating. + [self stopLoadingIndicator]; + + // When the KVO sends AVPlayerItemStatusReadyToPlay, there could still be a delay for the video really starts playing. + // If we create the mute button and progress bar immediately after AVPlayerItemStatusReadyToPlay signal, we might + // end up with showing them before the video is visible. To prevent that, we create mute button and progress bar here. + // There will be 0.1s delay after the video starts playing, but it's a much better user experience. + + if (!self.alreadyCreatedPlayerView) { + [self createView]; + self.alreadyCreatedPlayerView = YES; + } + + [self.playerView playbackTimeDidProgress]; + + if ([self.delegate respondsToSelector:@selector(playerDidProgressToTime:)]) { + [self.delegate playerDidProgressToTime:currentPlaybackTime]; + } +} + +- (void)avPlayer:(MOPUBAVPlayer *)player didError:(NSError *)error withMessage:(NSString *)message +{ + [self.avPlayer pause]; + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeErrorDuringPlayback]); + [self.vastTracking handleVideoEvent:MPVideoEventTypeError videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +- (void)avPlayerDidFinishPlayback:(MOPUBAVPlayer *)player +{ + self.finishedPlaying = YES; + [self removeLoadingIndicator]; + [self.avPlayer pause]; + // update view + [self.playerView playbackDidFinish]; + [self.vastTracking handleVideoEvent:MPVideoEventTypeCompleted videoTimeOffset:self.avPlayer.currentPlaybackTime]; +} + +- (void)avPlayerDidRecoverFromStall:(MOPUBAVPlayer *)player +{ + if (self.displayMode == MOPUBPlayerDisplayModeInline) { + [self removeLoadingIndicator]; + } else { + if ([self.delegate respondsToSelector:@selector(playerViewController:didRecoverFromStall:)]) { + [self.delegate playerViewController:self didRecoverFromStall:player]; + } + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resume) object:nil]; +} + +- (void)avPlayerDidStall:(MOPUBAVPlayer *)player +{ + MPAddLogEvent([[MPLogEvent alloc] initWithLogEventProperties:self.logEventProperties nativeVideoEventType:MPNativeVideoEventTypeBuffering]); + if (self.displayMode == MOPUBPlayerDisplayModeInline) { + [self startLoadingIndicator]; + } else { + if ([self.delegate respondsToSelector:@selector(playerViewController:didStall:)]) { + [self.delegate playerViewController:self didStall:self.avPlayer]; + } + } + + // Try to resume the video play after 3 seconds. The perform selector request is cancelled when + // didRecoverFromStall signal is received. This way, we won't queue up the requests. + [self performSelector:@selector(resume) withObject:nil afterDelay:kDelayPlayInSeconds]; +} + +#pragma mark - MOPUBPlayerViewDelegate +- (void)playerViewDidTapReplayButton:(MOPUBPlayerView *)view +{ + self.muteButton.hidden = NO; + self.finishedPlaying = NO; + [self.playerView setProgressBarVisible:YES]; + [self seekToTime:0]; + [self.avPlayer play]; +} + +- (void)playerViewWillShowReplayView:(MOPUBPlayerView *)view +{ + self.muteButton.hidden = YES; + [self.playerView setProgressBarVisible:NO]; + if (self.displayMode == MOPUBPlayerDisplayModeFullscreen) { + if ([self.delegate respondsToSelector:@selector(playerViewController:didTapReplayButton:)]) { + [self.delegate playerViewController:self willShowReplayView:self.playerView]; + } + } +} + +- (void)playerViewWillEnterFullscreen:(MOPUBPlayerView *)view +{ + if ([self.delegate respondsToSelector:@selector(willEnterFullscreen:)]) { + [self.delegate willEnterFullscreen:self]; + } +} + +#pragma mark - Application state monitoring + +- (void)applicationDidEnterBackground:(NSNotification *)notification +{ + if (self.avPlayer && self.avPlayer.rate > 0) { + [self pause]; + } +} + +- (void)applicationDidEnterForeground:(NSNotification *)notification +{ + // Resume video playback only if the visible area is larger than or equal to the autoplay threshold. + + BOOL playVisible = MPViewIntersectsParentWindowWithPercent(self.playerView, self.nativeVideoAdConfig.playVisiblePercent/100.0f); + if (self.avPlayer && self.isReadyToPlay && !self.finishedPlaying && playVisible) { + [self resume]; + } +} + +#pragma mark - + +- (UIViewController *)viewControllerForPresentingModalView +{ + return [self.delegate viewControllerForPresentingModalView]; +} + +- (void)displayAgentWillPresentModal +{ + [self pause]; +} + +- (void)displayAgentWillLeaveApplication +{ + [self pause]; +} + +- (void)displayAgentDidDismissModal +{ + [self resume]; +} + +@end + diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.h new file mode 100644 index 000000000..3e421007d --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.h @@ -0,0 +1,19 @@ +// +// MPBReplayView.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MOPUBPlayerView.h" + +@class MOPUBReplayView; + +typedef void (^MPBReplayActionBlock)(MOPUBReplayView *replayView); + +@interface MOPUBReplayView : UIView + +@property (nonatomic, copy) MPBReplayActionBlock actionBlock; + +- (instancetype)initWithFrame:(CGRect)frame displayMode:(MOPUBPlayerDisplayMode)displayMode; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.m new file mode 100644 index 000000000..e55c70f50 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/Internal/MOPUBReplayView.m @@ -0,0 +1,56 @@ +// +// MPBReplayView.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBReplayView.h" +#import "MPGlobal.h" +#import "UIView+MPAdditions.h" +#import "UIColor+MPAdditions.h" + +static NSString * const kPlayButtonImage = @"MPPlayBtn.png"; +static NSString * const kOverlayBgColor = @"#000000"; +static CGFloat const kOverlayAlpha = 0.5f; + +@interface MOPUBReplayView() + +@property (nonatomic) UIView *overlayView; +@property (nonatomic) UIButton *replayVideoButton; + +@end + +@implementation MOPUBReplayView + +- (instancetype)initWithFrame:(CGRect)frame displayMode:(MOPUBPlayerDisplayMode)displayMode +{ + if (self = [super initWithFrame:frame]) { + // only apply the overlay for fullscreen mode + if (displayMode == MOPUBPlayerDisplayModeFullscreen) { + _overlayView = [UIView new]; + _overlayView.backgroundColor = [UIColor mp_colorFromHexString:kOverlayBgColor alpha:kOverlayAlpha]; + [self addSubview:_overlayView]; + } + + _replayVideoButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_replayVideoButton setImage:[UIImage imageNamed:MPResourcePathForResource(kPlayButtonImage)] forState:UIControlStateNormal]; + [_replayVideoButton addTarget:self action:@selector(replayButtonTapped) forControlEvents:UIControlEventTouchUpInside]; + [_replayVideoButton sizeToFit]; + [self addSubview:_replayVideoButton]; + } + return self; +} + +- (void)layoutSubviews +{ + [super layoutSubviews]; + self.overlayView.frame = self.bounds; + self.replayVideoButton.center = self.center; + self.replayVideoButton.frame = CGRectIntegral(self.replayVideoButton.frame); +} + +- (void)replayButtonTapped +{ + self.actionBlock(self); +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.h new file mode 100644 index 000000000..ecf7d971a --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.h @@ -0,0 +1,18 @@ +// +// MOPUBNativeVideoAdRenderer.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdRenderer.h" + +@class MPNativeAdRendererConfiguration; +@class MPStaticNativeAdRendererSettings; + +@interface MOPUBNativeVideoAdRenderer : NSObject + +@property (nonatomic, readonly) MPNativeViewSizeHandler viewSizeHandler; + ++ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id)rendererSettings; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.m new file mode 100644 index 000000000..ac142ba95 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRenderer.m @@ -0,0 +1,355 @@ +// +// MOPUBNativeVideoAdRenderer.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoAdRenderer.h" +#import "MPNativeAdRendererConfiguration.h" +#import "MPNativeAdRenderer.h" +#import "MPNativeAdRendering.h" +#import "MPNativeAdAdapter.h" +#import "MPNativeAdConstants.h" +#import "MPNativeAdError.h" +#import "MPNativeAdRendererImageHandler.h" +#import "MPTimer.h" +#import "MPGlobal.h" +#import "MPLogging.h" +#import "MOPUBNativeVideoAdRendererSettings.h" +#import "MOPUBFullscreenPlayerViewController.h" +#import "MOPUBPlayerManager.h" +#import "MOPUBNativeVideoAdAdapter.h" +#import "MPVASTTracking.h" +#import "MPVideoConfig.h" +#import "MOPUBNativeVideoAdConfigValues.h" +#import "MOPUBNativeVideoImpressionAgent.h" +#import "MOPUBPlayerViewController.h" +#import "MPNativeAdRenderingImageLoader.h" + +static const CGFloat kAutoPlayTimerInterval = 0.25f; + +@interface MOPUBNativeVideoAdRenderer () + +@property (nonatomic) UIView *adView; +@property (nonatomic) MOPUBNativeVideoAdAdapter *adapter; +@property (nonatomic) BOOL adViewInViewHierarchy; +@property (nonatomic) Class renderingViewClass; +@property (nonatomic) MPNativeAdRendererImageHandler *rendererImageHandler; + +@property (nonatomic, weak) MOPUBPlayerViewController *videoController; +@property (nonatomic) MPTimer *autoPlayTimer; +@property (nonatomic) MPVideoConfig *videoConfig; +@property (nonatomic) MPVASTTracking *vastTracking; +@property (nonatomic) MOPUBNativeVideoAdConfigValues *nativeVideoAdConfig; +@property (nonatomic) MOPUBNativeVideoImpressionAgent *trackingAgent; +@property (nonatomic) BOOL trackingImpressionFired; + +@end + +@implementation MOPUBNativeVideoAdRenderer + ++ (MPNativeAdRendererConfiguration *)rendererConfigurationWithRendererSettings:(id)rendererSettings +{ + MPNativeAdRendererConfiguration *config = [[MPNativeAdRendererConfiguration alloc] init]; + config.rendererClass = [self class]; + config.rendererSettings = rendererSettings; + config.supportedCustomEvents = @[@"MOPUBNativeVideoCustomEvent"]; + + return config; +} + +- (instancetype)initWithRendererSettings:(id)rendererSettings +{ + if (self = [super init]) { + MOPUBNativeVideoAdRendererSettings *settings = (MOPUBNativeVideoAdRendererSettings *)rendererSettings; + _renderingViewClass = settings.renderingViewClass; + _viewSizeHandler = [settings.viewSizeHandler copy]; + _rendererImageHandler = [MPNativeAdRendererImageHandler new]; + _rendererImageHandler.delegate = self; + } + + return self; +} + +- (void)dealloc +{ + [_autoPlayTimer invalidate]; + _autoPlayTimer = nil; + + // free the video memory + [[MOPUBPlayerManager sharedInstance] disposePlayerViewController]; +} + +- (UIView *)retrieveViewWithAdapter:(MOPUBNativeVideoAdAdapter *)adapter error:(NSError **)error +{ + if (!adapter) { + if (error) { + *error = MPNativeAdNSErrorForRenderValueTypeError(); + } + + return nil; + } + + self.adapter = adapter; + + [self initAdView]; + [self setupVideoView]; + + self.adView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + // We only load text here. We delay loading of images until the view is added to the view hierarchy + // so we don't unnecessarily load images from the cache if the user is scrolling fast. So we will + // just store the image URLs for now. + if ([self.adView respondsToSelector:@selector(nativeMainTextLabel)]) { + self.adView.nativeMainTextLabel.text = [adapter.properties objectForKey:kAdTextKey]; + } + + if ([self.adView respondsToSelector:@selector(nativeTitleTextLabel)]) { + self.adView.nativeTitleTextLabel.text = [adapter.properties objectForKey:kAdTitleKey]; + } + + if ([self.adView respondsToSelector:@selector(nativeCallToActionTextLabel)] && self.adView.nativeCallToActionTextLabel) { + self.adView.nativeCallToActionTextLabel.text = [adapter.properties objectForKey:kAdCTATextKey]; + } + + if ([self.adView respondsToSelector:@selector(nativePrivacyInformationIconImageView)]) { + // MoPub ads pass the privacy information icon key through the properties dictionary. + NSString *daaIconImageLoc = [adapter.properties objectForKey:kAdDAAIconImageKey]; + if (daaIconImageLoc) { + UIImageView *imageView = self.adView.nativePrivacyInformationIconImageView; + imageView.hidden = NO; + + UIImage *daaIconImage = [UIImage imageNamed:daaIconImageLoc]; + imageView.image = daaIconImage; + + // Attach a gesture recognizer to handle loading the daa icon URL. + UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(DAAIconTapped)]; + imageView.userInteractionEnabled = YES; + [imageView addGestureRecognizer:tapRecognizer]; + } else if ([adapter respondsToSelector:@selector(privacyInformationIconView)]) { + // The ad network may provide its own view for its privacy information icon. We assume the ad handles the tap on the icon as well. + UIView *privacyIconAdView = [adapter privacyInformationIconView]; + privacyIconAdView.frame = self.adView.nativePrivacyInformationIconImageView.bounds; + privacyIconAdView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.adView.nativePrivacyInformationIconImageView.userInteractionEnabled = YES; + [self.adView.nativePrivacyInformationIconImageView addSubview:privacyIconAdView]; + self.adView.nativePrivacyInformationIconImageView.hidden = NO; + } else { + self.adView.nativePrivacyInformationIconImageView.userInteractionEnabled = NO; + self.adView.nativePrivacyInformationIconImageView.hidden = YES; + } + } + + if ([self shouldLoadMediaView]) { + UIView *mediaView = [self.adapter mainMediaView]; + UIView *mainImageView = [self.adView nativeMainImageView]; + + mediaView.frame = mainImageView.bounds; + mediaView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + mediaView.userInteractionEnabled = YES; + mainImageView.userInteractionEnabled = YES; + + [mainImageView addSubview:mediaView]; + } + + // See if the ad contains a star rating and notify the view if it does. + if ([self.adView respondsToSelector:@selector(layoutStarRating:)]) { + NSNumber *starRatingNum = [adapter.properties objectForKey:kAdStarRatingKey]; + + if ([starRatingNum isKindOfClass:[NSNumber class]] && starRatingNum.floatValue >= kStarRatingMinValue && starRatingNum.floatValue <= kStarRatingMaxValue) { + [self.adView layoutStarRating:starRatingNum]; + } + } + + return self.adView; +} + +- (BOOL)shouldLoadMediaView +{ + return [self.adapter respondsToSelector:@selector(mainMediaView)] + && [self.adapter mainMediaView] + && [self.adView respondsToSelector:@selector(nativeMainImageView)]; +} + +- (void)DAAIconTapped +{ + if ([self.adapter respondsToSelector:@selector(displayContentForDAAIconTap)]) { + [self.adapter displayContentForDAAIconTap]; + } +} + +- (void)adViewWillMoveToSuperview:(UIView *)superview +{ + self.adViewInViewHierarchy = (superview != nil); + + if (superview) { + // We'll start asychronously loading the native ad images now. + if ([self.adapter.properties objectForKey:kAdIconImageKey] && [self.adView respondsToSelector:@selector(nativeIconImageView)]) { + [self.rendererImageHandler loadImageForURL:[NSURL URLWithString:[self.adapter.properties objectForKey:kAdIconImageKey]] intoImageView:self.adView.nativeIconImageView]; + } + + // Only handle the loading of the main image if the adapter doesn't already have a view for it. + if (!([self.adapter respondsToSelector:@selector(mainMediaView)] && [self.adapter mainMediaView])) { + if ([self.adapter.properties objectForKey:kAdMainImageKey] && [self.adView respondsToSelector:@selector(nativeMainImageView)]) { + [self.rendererImageHandler loadImageForURL:[NSURL URLWithString:[self.adapter.properties objectForKey:kAdMainImageKey]] intoImageView:self.adView.nativeMainImageView]; + } + } + + // Layout custom assets here as the custom assets may contain images that need to be loaded. + if ([self.adView respondsToSelector:@selector(layoutCustomAssetsWithProperties:imageLoader:)]) { + // Create a simplified image loader for the ad view to use. + MPNativeAdRenderingImageLoader *imageLoader = [[MPNativeAdRenderingImageLoader alloc] initWithImageHandler:self.rendererImageHandler]; + [self.adView layoutCustomAssetsWithProperties:self.adapter.properties imageLoader:imageLoader]; + } + } +} + +- (void)tick:(MPTimer *)timer +{ + if (self.videoController) { + BOOL playVisible = MPViewIntersectsParentWindowWithPercent(self.videoController.playerView, self.nativeVideoAdConfig.playVisiblePercent/100.0f); + if (playVisible) { + // start new + if ([self.videoController shouldStartNewPlayer]) { + [self.videoController loadAndPlayVideo]; + } + + // resume play + if ([self.videoController shouldResumePlayer]) { + [self.videoController resume]; + } + } + + // pause video + BOOL pauseVisible = !MPViewIntersectsParentWindowWithPercent(self.videoController.playerView, self.nativeVideoAdConfig.pauseVisiblePercent/100.0f); + if (pauseVisible) { + if ([self.videoController shouldPausePlayer]) { + [self.videoController pause]; + } + } + } +} + +#pragma mark - MOPUBPlayerViewControllerDelegate + +- (void)willEnterFullscreen:(MOPUBPlayerViewController *)viewController +{ + [self enterFullscreen:[[self.adapter delegate] viewControllerForPresentingModalView]]; +} + +- (void)playerDidProgressToTime:(NSTimeInterval)playbackTime +{ + [self.adapter handleVideoHasProgressedToTime:playbackTime]; + + // Only the first impression is tracked. + if (!self.trackingImpressionFired && [self.trackingAgent shouldTrackImpressionWithCurrentPlaybackTime:playbackTime]) { + self.trackingImpressionFired = YES; + + // Fire MoPub impression tracking + [self.adapter handleVideoViewImpression]; + // Fire VAST Impression Tracking + [self.vastTracking handleVideoEvent:MPVideoEventTypeImpression + videoTimeOffset:playbackTime]; + } + [self.vastTracking handleVideoEvent:MPVideoEventTypeTimeUpdate videoTimeOffset:playbackTime]; +} + +- (void)ctaTapped:(MOPUBFullscreenPlayerViewController *)viewController +{ + // MoPub video CTA button clicked. Only the first click is tracked. The check is handled in MPNativeAd. + [self.adapter handleVideoViewClick]; + [self.vastTracking handleVideoEvent:MPVideoEventTypeClick + videoTimeOffset:self.videoController.avPlayer.currentPlaybackTime]; +} + +- (void)fullscreenPlayerWillLeaveApplication:(MOPUBFullscreenPlayerViewController *)viewController +{ + if ([self.adapter.delegate respondsToSelector:@selector(nativeAdWillLeaveApplicationFromAdapter:)]) { + [self.adapter.delegate nativeAdWillLeaveApplicationFromAdapter:self.adapter]; + } +} + +// being called from MPNativeAd +- (void)nativeAdTapped +{ + [self.vastTracking handleVideoEvent:MPVideoEventTypeClick + videoTimeOffset:self.videoController.avPlayer.currentPlaybackTime]; +} + +#pragma mark - MPNativeAdRendererImageHandlerDelegate + +- (BOOL)nativeAdViewInViewHierarchy +{ + return self.adViewInViewHierarchy; +} + +#pragma mark - Internal +- (void)enterFullscreen:(UIViewController *)fromViewController +{ + MOPUBFullscreenPlayerViewController *vc = [[MOPUBFullscreenPlayerViewController alloc] initWithVideoPlayer:self.videoController dismissBlock:^(UIView *originalParentView) { + self.videoController.view.frame = originalParentView.bounds; + self.videoController.delegate = self; + [self.videoController willExitFullscreen]; + if ([self.adapter.delegate respondsToSelector:@selector(nativeAdDidDismissModalForAdapter:)]) { + [self.adapter.delegate nativeAdDidDismissModalForAdapter:self.adapter]; + } + [originalParentView addSubview:self.videoController.playerView]; + }]; + vc.delegate = self; + if ([self.adapter.delegate respondsToSelector:@selector(nativeAdWillPresentModalForAdapter:)]) { + [self.adapter.delegate nativeAdWillPresentModalForAdapter:self.adapter]; + } + [fromViewController presentViewController:vc animated:NO completion:nil]; +} + +- (void)initAdView +{ + if (!self.videoController) { + if ([self.renderingViewClass respondsToSelector:@selector(nibForAd)]) { + self.adView = (UIView *)[[[self.renderingViewClass nibForAd] instantiateWithOwner:nil options:nil] firstObject]; + } else { + self.adView = [[self.renderingViewClass alloc] init]; + } + } +} + +- (void)setupVideoView +{ + // If a video controller is nil or it's already been disposed, create/recreate the videoController + if ([self.adView respondsToSelector:(@selector(nativeVideoView))]) { + BOOL createdNewVideoController = NO; + self.videoConfig = [self.adapter.properties objectForKey:kVideoConfigKey]; + self.nativeVideoAdConfig = [self.adapter.properties objectForKey:kNativeVideoAdConfigKey]; + + if (!self.videoController || self.videoController.disposed) { + createdNewVideoController = YES; + self.videoController = [[MOPUBPlayerManager sharedInstance] playerViewControllerWithVideoConfig:self.videoConfig + nativeVideoAdConfig:self.nativeVideoAdConfig + logEventProperties:[self.adapter.properties valueForKey:kLogEventRequestPropertiesKey]]; + self.videoController.defaultActionURL = self.adapter.defaultActionURL; + self.videoController.displayMode = MOPUBPlayerDisplayModeInline; + self.videoController.delegate = self; + self.videoController.view.frame = self.adView.nativeVideoView.bounds; + [self.adView.nativeVideoView addSubview:self.videoController.view]; + [self.adView bringSubviewToFront:self.adView.nativeVideoView]; + + if (!self.autoPlayTimer) { + self.autoPlayTimer = [MPTimer timerWithTimeInterval:kAutoPlayTimerInterval target:self selector:@selector(tick:) repeats:YES]; + self.autoPlayTimer.runLoopMode = NSRunLoopCommonModes; + [self.autoPlayTimer scheduleNow]; + } + + self.trackingAgent = [[MOPUBNativeVideoImpressionAgent alloc] initWithVideoView:self.videoController.playerView requiredVisibilityPercentage:self.nativeVideoAdConfig.impressionMinVisiblePercent/100.0f requiredPlaybackDuration:self.nativeVideoAdConfig.impressionVisible]; + } + // Lazy load vast tracking. It must be created after we know the video controller has been initialized. + // If we created a new video controller, we must ensure the vast tracking has the new view. + if (!self.vastTracking) { + self.vastTracking = [[MPVASTTracking alloc] initWithMPVideoConfig:self.videoConfig videoView:self.videoController.playerView]; + } else if (createdNewVideoController) { + [self.vastTracking handleNewVideoView:self.videoController.playerView]; + } + // Always set the videoControllers vast tracking object to be the current renderer's + self.videoController.vastTracking = self.vastTracking; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.h b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.h new file mode 100644 index 000000000..7f4c915da --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.h @@ -0,0 +1,28 @@ +// +// MOPUBNativeVideoAdRendererSettings.h +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import "MPNativeAdRendererSettings.h" +#import "MPNativeAdRenderer.h" + +@interface MOPUBNativeVideoAdRendererSettings : NSObject + +/** + * A rendering class that must be a UIView that implements the MPNativeAdRendering protocol. + * The ad will be rendered to a view of this class type. + */ +@property (nonatomic, assign) Class renderingViewClass; + +/** + * A block that returns the size of the view given a maximum width. This needs to be set when + * used in conjunction with ad placer classes so the ad placers can correctly size the cells + * that contain the ads. + * + * viewSizeHandler is not used for manual native ad integration. You must set the + * frame of your manually integrated native ad view. + */ +@property (nonatomic, readwrite, copy) MPNativeViewSizeHandler viewSizeHandler; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.m b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.m new file mode 100644 index 000000000..cd339fc28 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/NativeVideo/MOPUBNativeVideoAdRendererSettings.m @@ -0,0 +1,10 @@ +// +// MOPUBNativeVideoAdRendererSettings.m +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MOPUBNativeVideoAdRendererSettings.h" + +@implementation MOPUBNativeVideoAdRendererSettings + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn.png new file mode 100644 index 000000000..c96fa8086 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@2x.png new file mode 100644 index 000000000..b87f96b22 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@3x.png new file mode 100644 index 000000000..42e927b2a Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseBtn@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX.png new file mode 100644 index 000000000..ca4fa2981 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@2x.png new file mode 100644 index 000000000..85e39a31b Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@3x.png new file mode 100644 index 000000000..c6e5df439 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCloseButtonX@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCountdownTimer.html b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCountdownTimer.html new file mode 100644 index 000000000..70a496a26 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPCountdownTimer.html @@ -0,0 +1,35 @@ + + + + + + + + + + + +
+
+ +
+
+ + diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon.png new file mode 100644 index 000000000..3443a8617 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@2x.png new file mode 100644 index 000000000..e09e34bef Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@3x.png new file mode 100644 index 000000000..22a01abd0 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPDAAIcon@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn.png new file mode 100644 index 000000000..fe63b365e Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@2x.png new file mode 100644 index 000000000..d6443f02c Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@3x.png new file mode 100644 index 000000000..8ccd290a0 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPMutedBtn@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn.png new file mode 100644 index 000000000..ddaca971c Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@2x.png new file mode 100644 index 000000000..51c911e22 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@3x.png new file mode 100644 index 000000000..1affb6ec8 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPPlayBtn@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn.png new file mode 100644 index 000000000..a7d52e3b0 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@2x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@2x.png new file mode 100644 index 000000000..1860e9792 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@2x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@3x.png b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@3x.png new file mode 100644 index 000000000..6ec3ce688 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/Resources/MPUnmutedBtn@3x.png differ diff --git a/examples/PrebidMobileDemo/MoPubSDK/Resources/MRAID.bundle/mraid.js b/examples/PrebidMobileDemo/MoPubSDK/Resources/MRAID.bundle/mraid.js new file mode 100644 index 000000000..5b0d84b9b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/Resources/MRAID.bundle/mraid.js @@ -0,0 +1,916 @@ +/* +Do not modify this version of the file. It will be copied over when any of the project's targets are built. +If you wish to modify mraid.js, modify the version located at mopub-sdk-common/mraid/mraid.js. +*/ +(function() { + var isIOS = (/iphone|ipad|ipod/i).test(window.navigator.userAgent.toLowerCase()); + if (isIOS) { + console = {}; + console.log = function(log) { + var iframe = document.createElement('iframe'); + iframe.setAttribute('src', 'ios-log: ' + log); + document.documentElement.appendChild(iframe); + iframe.parentNode.removeChild(iframe); + iframe = null; + }; + console.debug = console.info = console.warn = console.error = console.log; + } +}()); + + +(function() { + var mraid = window.mraid = {}; + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + // Bridge interface to SDK + + var bridge = window.mraidbridge = { + nativeSDKFiredReady: false, + nativeCallQueue: [], + nativeCallInFlight: false, + lastSizeChangeProperties: null + }; + + bridge.fireChangeEvent = function(properties) { + for (var p in properties) { + if (properties.hasOwnProperty(p)) { + // Change handlers defined by MRAID below + var handler = changeHandlers[p]; + handler(properties[p]); + } + } + }; + + bridge.nativeCallComplete = function(command) { + if (this.nativeCallQueue.length === 0) { + this.nativeCallInFlight = false; + return; + } + + var nextCall = this.nativeCallQueue.pop(); + window.location = nextCall; + }; + + bridge.executeNativeCall = function(args) { + var command = args.shift(); + + if (!this.nativeSDKFiredReady) { + console.log('rejecting ' + command + ' because mraid is not ready'); + bridge.notifyErrorEvent('mraid is not ready', command); + return; + } + + var call = 'mraid://' + command; + + var key, value; + var isFirstArgument = true; + + for (var i = 0; i < args.length; i += 2) { + key = args[i]; + value = args[i + 1]; + + if (value === null) continue; + + if (isFirstArgument) { + call += '?'; + isFirstArgument = false; + } else { + call += '&'; + } + + call += encodeURIComponent(key) + '=' + encodeURIComponent(value); + } + + if (this.nativeCallInFlight) { + this.nativeCallQueue.push(call); + } else { + this.nativeCallInFlight = true; + window.location = call; + } + }; + + + bridge.setCurrentPosition = function(x, y, width, height) { + currentPosition = { + x: x, + y: y, + width: width, + height: height + }; + broadcastEvent(EVENTS.INFO, 'Set current position to ' + stringify(currentPosition)); + }; + + bridge.setDefaultPosition = function(x, y, width, height) { + defaultPosition = { + x: x, + y: y, + width: width, + height: height + }; + broadcastEvent(EVENTS.INFO, 'Set default position to ' + stringify(defaultPosition)); + }; + + bridge.setMaxSize = function(width, height) { + maxSize = { + width: width, + height: height + }; + + expandProperties.width = width; + expandProperties.height = height; + + broadcastEvent(EVENTS.INFO, 'Set max size to ' + stringify(maxSize)); + }; + + bridge.setPlacementType = function(_placementType) { + placementType = _placementType; + broadcastEvent(EVENTS.INFO, 'Set placement type to ' + stringify(placementType)); + }; + + bridge.setScreenSize = function(width, height) { + screenSize = { + width: width, + height: height + }; + broadcastEvent(EVENTS.INFO, 'Set screen size to ' + stringify(screenSize)); + }; + + bridge.setState = function(_state) { + state = _state; + broadcastEvent(EVENTS.INFO, 'Set state to ' + stringify(state)); + broadcastEvent(EVENTS.STATECHANGE, state); + }; + + bridge.setIsViewable = function(_isViewable) { + isViewable = _isViewable; + broadcastEvent(EVENTS.INFO, 'Set isViewable to ' + stringify(isViewable)); + broadcastEvent(EVENTS.VIEWABLECHANGE, isViewable); + }; + + bridge.setSupports = function(sms, tel, calendar, storePicture, inlineVideo) { + supportProperties = { + sms: sms, + tel: tel, + calendar: calendar, + storePicture: storePicture, + inlineVideo: inlineVideo + }; + }; + + bridge.notifyReadyEvent = function() { + this.nativeSDKFiredReady = true; + broadcastEvent(EVENTS.READY); + }; + + bridge.notifyErrorEvent = function(message, action) { + broadcastEvent(EVENTS.ERROR, message, action); + }; + + // Temporary aliases while we migrate to the new API + bridge.fireReadyEvent = bridge.notifyReadyEvent; + bridge.fireErrorEvent = bridge.notifyErrorEvent; + + bridge.notifySizeChangeEvent = function(width, height) { + if (this.lastSizeChangeProperties && + width == this.lastSizeChangeProperties.width && height == this.lastSizeChangeProperties.height) { + return; + } + + this.lastSizeChangeProperties = { + width: width, + height: height + }; + broadcastEvent(EVENTS.SIZECHANGE, width, height); + }; + + bridge.notifyStateChangeEvent = function() { + if (state === STATES.LOADING) { + broadcastEvent(EVENTS.INFO, 'Native SDK initialized.'); + } + + broadcastEvent(EVENTS.INFO, 'Set state to ' + stringify(state)); + broadcastEvent(EVENTS.STATECHANGE, state); + }; + + bridge.notifyViewableChangeEvent = function() { + broadcastEvent(EVENTS.INFO, 'Set isViewable to ' + stringify(isViewable)); + broadcastEvent(EVENTS.VIEWABLECHANGE, isViewable); + }; + + + // Constants. //////////////////////////////////////////////////////////////////////////////////// + + var VERSION = mraid.VERSION = '2.0'; + + var STATES = mraid.STATES = { + LOADING: 'loading', + DEFAULT: 'default', + EXPANDED: 'expanded', + HIDDEN: 'hidden', + RESIZED: 'resized' + }; + + var EVENTS = mraid.EVENTS = { + ERROR: 'error', + INFO: 'info', + READY: 'ready', + STATECHANGE: 'stateChange', + VIEWABLECHANGE: 'viewableChange', + SIZECHANGE: 'sizeChange' + }; + + var PLACEMENT_TYPES = mraid.PLACEMENT_TYPES = { + UNKNOWN: 'unknown', + INLINE: 'inline', + INTERSTITIAL: 'interstitial' + }; + + // External MRAID state: may be directly or indirectly modified by the ad JS. //////////////////// + + // Properties which define the behavior of an expandable ad. + var expandProperties = { + width: false, + height: false, + useCustomClose: false, + isModal: true + }; + + var resizeProperties = { + width: false, + height: false, + offsetX: false, + offsetY: false, + customClosePosition: 'top-right', + allowOffscreen: true + }; + + var orientationProperties = { + allowOrientationChange: true, + forceOrientation: "none" + }; + + var supportProperties = { + sms: false, + tel: false, + calendar: false, + storePicture: false, + inlineVideo: false + }; + + // default is undefined so that notifySizeChangeEvent can track changes + var lastSizeChangeProperties; + + var maxSize = {}; + + var currentPosition = {}; + + var defaultPosition = {}; + + var screenSize = {}; + + var hasSetCustomClose = false; + + var listeners = {}; + + // Internal MRAID state. Modified by the native SDK. ///////////////////////////////////////////// + + var state = STATES.LOADING; + + var isViewable = false; + + var placementType = PLACEMENT_TYPES.UNKNOWN; + + var hostSDKVersion = { + 'major': 0, + 'minor': 0, + 'patch': 0 + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + var EventListeners = function(event) { + this.event = event; + this.count = 0; + var listeners = {}; + + this.add = function(func) { + var id = String(func); + if (!listeners[id]) { + listeners[id] = func; + this.count++; + } + }; + + this.remove = function(func) { + var id = String(func); + if (listeners[id]) { + listeners[id] = null; + delete listeners[id]; + this.count--; + return true; + } else { + return false; + } + }; + + this.removeAll = function() { + for (var id in listeners) { + if (listeners.hasOwnProperty(id)) this.remove(listeners[id]); + } + }; + + this.broadcast = function(args) { + for (var id in listeners) { + if (listeners.hasOwnProperty(id)) listeners[id].apply(mraid, args); + } + }; + + this.toString = function() { + var out = [event, ':']; + for (var id in listeners) { + if (listeners.hasOwnProperty(id)) out.push('|', id, '|'); + } + return out.join(''); + }; + }; + + var broadcastEvent = function() { + var args = new Array(arguments.length); + var l = arguments.length; + for (var i = 0; i < l; i++) args[i] = arguments[i]; + var event = args.shift(); + if (listeners[event]) listeners[event].broadcast(args); + }; + + var contains = function(value, array) { + for (var i in array) { + if (array[i] === value) return true; + } + return false; + }; + + var clone = function(obj) { + if (obj === null) return null; + var f = function() {}; + f.prototype = obj; + return new f(); + }; + + var stringify = function(obj) { + if (typeof obj === 'object') { + var out = []; + if (obj.push) { + // Array. + for (var p in obj) out.push(obj[p]); + return '[' + out.join(',') + ']'; + } else { + // Other object. + for (var p in obj) out.push("'" + p + "': " + obj[p]); + return '{' + out.join(',') + '}'; + } + } else return String(obj); + }; + + var trim = function(str) { + return str.replace(/^\s+|\s+$/g, ''); + }; + + // Functions that will be invoked by the native SDK whenever a "change" event occurs. + var changeHandlers = { + state: function(val) { + if (state === STATES.LOADING) { + broadcastEvent(EVENTS.INFO, 'Native SDK initialized.'); + } + state = val; + broadcastEvent(EVENTS.INFO, 'Set state to ' + stringify(val)); + broadcastEvent(EVENTS.STATECHANGE, state); + }, + + viewable: function(val) { + isViewable = val; + broadcastEvent(EVENTS.INFO, 'Set isViewable to ' + stringify(val)); + broadcastEvent(EVENTS.VIEWABLECHANGE, isViewable); + }, + + placementType: function(val) { + broadcastEvent(EVENTS.INFO, 'Set placementType to ' + stringify(val)); + placementType = val; + }, + + sizeChange: function(val) { + broadcastEvent(EVENTS.INFO, 'Set screenSize to ' + stringify(val)); + for (var key in val) { + if (val.hasOwnProperty(key)) screenSize[key] = val[key]; + } + }, + + supports: function(val) { + broadcastEvent(EVENTS.INFO, 'Set supports to ' + stringify(val)); + supportProperties = val; + }, + + hostSDKVersion: function(val) { + // val is expected to be formatted like 'X.Y.Z[-+]identifier'. + var versions = val.split('.').map(function(version) { + return parseInt(version, 10); + }).filter(function(version) { + return version >= 0; + }); + + if (versions.length >= 3) { + hostSDKVersion['major'] = parseInt(versions[0], 10); + hostSDKVersion['minor'] = parseInt(versions[1], 10); + hostSDKVersion['patch'] = parseInt(versions[2], 10); + broadcastEvent(EVENTS.INFO, 'Set hostSDKVersion to ' + stringify(hostSDKVersion)); + } + } + }; + + var validate = function(obj, validators, action, merge) { + if (!merge) { + // Check to see if any required properties are missing. + if (obj === null) { + broadcastEvent(EVENTS.ERROR, 'Required object not provided.', action); + return false; + } else { + for (var i in validators) { + if (validators.hasOwnProperty(i) && obj[i] === undefined) { + broadcastEvent(EVENTS.ERROR, 'Object is missing required property: ' + i, action); + return false; + } + } + } + } + + for (var prop in obj) { + var validator = validators[prop]; + var value = obj[prop]; + if (validator && !validator(value)) { + // Failed validation. + broadcastEvent(EVENTS.ERROR, 'Value of property ' + prop + ' is invalid: ' + value, action); + return false; + } + } + return true; + }; + + var expandPropertyValidators = { + useCustomClose: function(v) { return (typeof v === 'boolean'); }, + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////// + + mraid.addEventListener = function(event, listener) { + if (!event || !listener) { + broadcastEvent(EVENTS.ERROR, 'Both event and listener are required.', 'addEventListener'); + } else if (!contains(event, EVENTS)) { + broadcastEvent(EVENTS.ERROR, 'Unknown MRAID event: ' + event, 'addEventListener'); + } else { + if (!listeners[event]) { + listeners[event] = new EventListeners(event); + } + listeners[event].add(listener); + } + }; + + mraid.close = function() { + if (state === STATES.HIDDEN) { + broadcastEvent(EVENTS.ERROR, 'Ad cannot be closed when it is already hidden.', + 'close'); + } else bridge.executeNativeCall(['close']); + }; + + mraid.expand = function(URL) { + if (!(this.getState() === STATES.DEFAULT || this.getState() === STATES.RESIZED)) { + broadcastEvent(EVENTS.ERROR, 'Ad can only be expanded from the default or resized state.', 'expand'); + } else { + var args = ['expand', + 'shouldUseCustomClose', expandProperties.useCustomClose + ]; + + if (URL) { + args = args.concat(['url', URL]); + } + + bridge.executeNativeCall(args); + } + }; + + mraid.getExpandProperties = function() { + var properties = { + width: expandProperties.width, + height: expandProperties.height, + useCustomClose: expandProperties.useCustomClose, + isModal: expandProperties.isModal + }; + return properties; + }; + + + mraid.getCurrentPosition = function() { + return { + x: currentPosition.x, + y: currentPosition.y, + width: currentPosition.width, + height: currentPosition.height + }; + }; + + mraid.getDefaultPosition = function() { + return { + x: defaultPosition.x, + y: defaultPosition.y, + width: defaultPosition.width, + height: defaultPosition.height + }; + }; + + mraid.getMaxSize = function() { + return { + width: maxSize.width, + height: maxSize.height + }; + }; + + mraid.getPlacementType = function() { + return placementType; + }; + + mraid.getScreenSize = function() { + return { + width: screenSize.width, + height: screenSize.height + }; + }; + + mraid.getState = function() { + return state; + }; + + mraid.isViewable = function() { + return isViewable; + }; + + mraid.getVersion = function() { + return mraid.VERSION; + }; + + mraid.open = function(URL) { + if (!URL) broadcastEvent(EVENTS.ERROR, 'URL is required.', 'open'); + else bridge.executeNativeCall(['open', 'url', URL]); + }; + + mraid.removeEventListener = function(event, listener) { + if (!event) { + broadcastEvent(EVENTS.ERROR, 'Event is required.', 'removeEventListener'); + return; + } + + if (listener) { + // If we have a valid event, we'll try to remove the listener from it. + var success = false; + if (listeners[event]) { + success = listeners[event].remove(listener); + } + + // If we didn't have a valid event or couldn't remove the listener from the event, broadcast an error and return early. + if (!success) { + broadcastEvent(EVENTS.ERROR, 'Listener not currently registered for event.', 'removeEventListener'); + return; + } + + } else if (!listener && listeners[event]) { + listeners[event].removeAll(); + } + + if (listeners[event] && listeners[event].count === 0) { + listeners[event] = null; + delete listeners[event]; + } + }; + + mraid.setExpandProperties = function(properties) { + if (validate(properties, expandPropertyValidators, 'setExpandProperties', true)) { + if (properties.hasOwnProperty('useCustomClose')) { + expandProperties.useCustomClose = properties.useCustomClose; + } + } + }; + + mraid.useCustomClose = function(shouldUseCustomClose) { + expandProperties.useCustomClose = shouldUseCustomClose; + hasSetCustomClose = true; + bridge.executeNativeCall(['usecustomclose', 'shouldUseCustomClose', shouldUseCustomClose]); + }; + + // MRAID 2.0 APIs //////////////////////////////////////////////////////////////////////////////// + + mraid.createCalendarEvent = function(parameters) { + CalendarEventParser.initialize(parameters); + if (CalendarEventParser.parse()) { + bridge.executeNativeCall(CalendarEventParser.arguments); + } else { + broadcastEvent(EVENTS.ERROR, CalendarEventParser.errors[0], 'createCalendarEvent'); + } + }; + + mraid.supports = function(feature) { + return supportProperties[feature]; + }; + + mraid.playVideo = function(uri) { + if (!mraid.isViewable()) { + broadcastEvent(EVENTS.ERROR, 'playVideo cannot be called until the ad is viewable', 'playVideo'); + return; + } + + if (!uri) { + broadcastEvent(EVENTS.ERROR, 'playVideo must be called with a valid URI', 'playVideo'); + } else { + bridge.executeNativeCall(['playVideo', 'uri', uri]); + } + }; + + mraid.storePicture = function(uri) { + if (!mraid.isViewable()) { + broadcastEvent(EVENTS.ERROR, 'storePicture cannot be called until the ad is viewable', 'storePicture'); + return; + } + + if (!uri) { + broadcastEvent(EVENTS.ERROR, 'storePicture must be called with a valid URI', 'storePicture'); + } else { + bridge.executeNativeCall(['storePicture', 'uri', uri]); + } + }; + + + var resizePropertyValidators = { + width: function(v) { + return !isNaN(v) && v > 0; + }, + height: function(v) { + return !isNaN(v) && v > 0; + }, + offsetX: function(v) { + return !isNaN(v); + }, + offsetY: function(v) { + return !isNaN(v); + }, + customClosePosition: function(v) { + return (typeof v === 'string' && + ['top-right', 'bottom-right', 'top-left', 'bottom-left', 'center', 'top-center', 'bottom-center'].indexOf(v) > -1); + }, + allowOffscreen: function(v) { + return (typeof v === 'boolean'); + } + }; + + mraid.setOrientationProperties = function(properties) { + + if (properties.hasOwnProperty('allowOrientationChange')) { + orientationProperties.allowOrientationChange = properties.allowOrientationChange; + } + + if (properties.hasOwnProperty('forceOrientation')) { + orientationProperties.forceOrientation = properties.forceOrientation; + } + + var args = ['setOrientationProperties', + 'allowOrientationChange', orientationProperties.allowOrientationChange, + 'forceOrientation', orientationProperties.forceOrientation + ]; + bridge.executeNativeCall(args); + }; + + mraid.getOrientationProperties = function() { + return { + allowOrientationChange: orientationProperties.allowOrientationChange, + forceOrientation: orientationProperties.forceOrientation + }; + }; + + mraid.resize = function() { + if (!(this.getState() === STATES.DEFAULT || this.getState() === STATES.RESIZED)) { + broadcastEvent(EVENTS.ERROR, 'Ad can only be resized from the default or resized state.', 'resize'); + } else if (!resizeProperties.width || !resizeProperties.height) { + broadcastEvent(EVENTS.ERROR, 'Must set resize properties before calling resize()', 'resize'); + } else { + var args = ['resize', + 'width', resizeProperties.width, + 'height', resizeProperties.height, + 'offsetX', resizeProperties.offsetX || 0, + 'offsetY', resizeProperties.offsetY || 0, + 'customClosePosition', resizeProperties.customClosePosition, + 'allowOffscreen', !!resizeProperties.allowOffscreen + ]; + + bridge.executeNativeCall(args); + } + }; + + mraid.getResizeProperties = function() { + var properties = { + width: resizeProperties.width, + height: resizeProperties.height, + offsetX: resizeProperties.offsetX, + offsetY: resizeProperties.offsetY, + customClosePosition: resizeProperties.customClosePosition, + allowOffscreen: resizeProperties.allowOffscreen + }; + return properties; + }; + + mraid.setResizeProperties = function(properties) { + if (validate(properties, resizePropertyValidators, 'setResizeProperties', true)) { + + var desiredProperties = ['width', 'height', 'offsetX', 'offsetY', 'customClosePosition', 'allowOffscreen']; + + var length = desiredProperties.length; + + for (var i = 0; i < length; i++) { + var propname = desiredProperties[i]; + if (properties.hasOwnProperty(propname)) { + resizeProperties[propname] = properties[propname]; + } + } + } + }; + + // Determining SDK version /////////////////////////////////////////////////////////////////////// + + mraid.getHostSDKVersion = function() { + return hostSDKVersion; + } + + // Calendar helpers ////////////////////////////////////////////////////////////////////////////// + + var CalendarEventParser = { + initialize: function(parameters) { + this.parameters = parameters; + this.errors = []; + this.arguments = ['createCalendarEvent']; + }, + + parse: function() { + if (!this.parameters) { + this.errors.push('The object passed to createCalendarEvent cannot be null.'); + } else { + this.parseDescription(); + this.parseLocation(); + this.parseSummary(); + this.parseStartAndEndDates(); + this.parseReminder(); + this.parseRecurrence(); + this.parseTransparency(); + } + + var errorCount = this.errors.length; + if (errorCount) { + this.arguments.length = 0; + } + + return (errorCount === 0); + }, + + parseDescription: function() { + this._processStringValue('description'); + }, + + parseLocation: function() { + this._processStringValue('location'); + }, + + parseSummary: function() { + this._processStringValue('summary'); + }, + + parseStartAndEndDates: function() { + this._processDateValue('start'); + this._processDateValue('end'); + }, + + parseReminder: function() { + var reminder = this._getParameter('reminder'); + if (!reminder) { + return; + } + + if (reminder < 0) { + this.arguments.push('relativeReminder'); + this.arguments.push(parseInt(reminder) / 1000); + } else { + this.arguments.push('absoluteReminder'); + this.arguments.push(reminder); + } + }, + + parseRecurrence: function() { + var recurrenceDict = this._getParameter('recurrence'); + if (!recurrenceDict) { + return; + } + + this.parseRecurrenceInterval(recurrenceDict); + this.parseRecurrenceFrequency(recurrenceDict); + this.parseRecurrenceEndDate(recurrenceDict); + this.parseRecurrenceArrayValue(recurrenceDict, 'daysInWeek'); + this.parseRecurrenceArrayValue(recurrenceDict, 'daysInMonth'); + this.parseRecurrenceArrayValue(recurrenceDict, 'daysInYear'); + this.parseRecurrenceArrayValue(recurrenceDict, 'monthsInYear'); + }, + + parseTransparency: function() { + var validValues = ['opaque', 'transparent']; + + if (this.parameters.hasOwnProperty('transparency')) { + var transparency = this.parameters.transparency; + if (contains(transparency, validValues)) { + this.arguments.push('transparency'); + this.arguments.push(transparency); + } else { + this.errors.push('transparency must be opaque or transparent'); + } + } + }, + + parseRecurrenceArrayValue: function(recurrenceDict, kind) { + if (recurrenceDict.hasOwnProperty(kind)) { + var array = recurrenceDict[kind]; + if (!array || !(array instanceof Array)) { + this.errors.push(kind + ' must be an array.'); + } else { + var arrayStr = array.join(','); + this.arguments.push(kind); + this.arguments.push(arrayStr); + } + } + }, + + parseRecurrenceInterval: function(recurrenceDict) { + if (recurrenceDict.hasOwnProperty('interval')) { + var interval = recurrenceDict.interval; + if (!interval) { + this.errors.push('Recurrence interval cannot be null.'); + } else { + this.arguments.push('interval'); + this.arguments.push(interval); + } + } else { + // If a recurrence rule was specified without an interval, use a default value of 1. + this.arguments.push('interval'); + this.arguments.push(1); + } + }, + + parseRecurrenceFrequency: function(recurrenceDict) { + if (recurrenceDict.hasOwnProperty('frequency')) { + var frequency = recurrenceDict.frequency; + var validFrequencies = ['daily', 'weekly', 'monthly', 'yearly']; + if (contains(frequency, validFrequencies)) { + this.arguments.push('frequency'); + this.arguments.push(frequency); + } else { + this.errors.push('Recurrence frequency must be one of: "daily", "weekly", "monthly", "yearly".'); + } + } + }, + + parseRecurrenceEndDate: function(recurrenceDict) { + var expires = recurrenceDict.expires; + + if (!expires) { + return; + } + + this.arguments.push('expires'); + this.arguments.push(expires); + }, + + _getParameter: function(key) { + if (this.parameters.hasOwnProperty(key)) { + return this.parameters[key]; + } + + return null; + }, + + _processStringValue: function(kind) { + if (this.parameters.hasOwnProperty(kind)) { + var value = this.parameters[kind]; + this.arguments.push(kind); + this.arguments.push(value); + } + }, + + _processDateValue: function(kind) { + if (this.parameters.hasOwnProperty(kind)) { + var dateString = this._getParameter(kind); + this.arguments.push(kind); + this.arguments.push(dateString); + } + } + }; +}()); \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.h new file mode 100644 index 000000000..015a6e30b --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.h @@ -0,0 +1,15 @@ +// +// MPMoPubRewardedPlayableCustomEvent.h +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPRewardedVideoCustomEvent.h" +#import "MPPrivateRewardedVideoCustomEventDelegate.h" + +@interface MPMoPubRewardedPlayableCustomEvent : MPRewardedVideoCustomEvent +@property (nonatomic, readonly) NSTimeInterval countdownDuration; + +@property (nonatomic, weak) id delegate; +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.m new file mode 100644 index 000000000..7cff88e60 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedPlayableCustomEvent.m @@ -0,0 +1,173 @@ +// +// MPMoPubRewardedPlayableCustomEvent.m +// MoPubSDK +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPMoPubRewardedPlayableCustomEvent.h" +#import "MPMRAIDInterstitialViewController.h" +#import "MPAdConfiguration.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPRewardedVideoError.h" +#import "MPCountdownTimerView.h" + +const NSTimeInterval kDefaultCountdownTimerIntervalInSeconds = 30; + +@interface MPMoPubRewardedPlayableCustomEvent() +@property (nonatomic, assign) BOOL adAvailable; +@property (nonatomic, strong) MPMRAIDInterstitialViewController *interstitial; +@property (nonatomic, strong) MPCountdownTimerView *timerView; +@property (nonatomic, assign) BOOL userRewarded; +@end + +@implementation MPMoPubRewardedPlayableCustomEvent + +- (void)dealloc { + [_timerView stopAndSignalCompletion:NO]; +} + +// Lazy initialization property for the MRAID interstitial. +- (MPMRAIDInterstitialViewController *)interstitial { + if (_interstitial == nil) { + _interstitial = [[MPMRAIDInterstitialViewController alloc] initWithAdConfiguration:self.delegate.configuration]; + } + + return _interstitial; +} + +// Retrieves a valid countdown duration to use for the timer. In the event that `rewardedPlayableDuration` +// from `MPAdConfiguration` is less than zero, the default value `kDefaultCountdownTimerIntervalInSeconds` +// will be used instead. +- (NSTimeInterval)countdownDuration { + NSTimeInterval duration = self.delegate.configuration.rewardedPlayableDuration; + if (duration <= 0) { + duration = kDefaultCountdownTimerIntervalInSeconds; + } + + return duration; +} + +// Shows the native close button and deallocates the countdown timer since it will no +// longer be used. +- (void)showCloseButton { + [self.interstitial setCloseButtonStyle:MPInterstitialCloseButtonStyleAlwaysVisible]; + [self.timerView removeFromSuperview]; + self.timerView = nil; +} + +// Only reward the user once; either by countdown timer elapsing or rewarding on click +// (if configured). +- (void)rewardUserWithConfiguration:(MPAdConfiguration *)configuration timerHasElapsed:(BOOL)hasElasped { + if (!self.userRewarded && (hasElasped || configuration.rewardedPlayableShouldRewardOnClick)) { + MPLogInfo(@"MoPub rewarded playable user rewarded."); + + [self.delegate rewardedVideoShouldRewardUserForCustomEvent:self reward:configuration.rewardedVideoReward]; + self.userRewarded = YES; + } +} + +#pragma mark - MPRewardedVideoCustomEvent + +@dynamic delegate; + +- (void)requestRewardedVideoWithCustomEventInfo:(NSDictionary *)info { + MPLogInfo(@"Loading MoPub rewarded playable"); + self.interstitial.delegate = self; + + [self.interstitial setCloseButtonStyle:MPInterstitialCloseButtonStyleAlwaysHidden]; + [self.interstitial startLoading]; +} + +- (BOOL)hasAdAvailable { + return self.adAvailable; +} + +- (void)handleAdPlayedForCustomEventNetwork { + // no-op +} + +- (void)handleCustomEventInvalidated { + // no-op +} + +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController { + if (self.hasAdAvailable) { + // Add the countdown timer to the interstitial and start the timer. + self.timerView = [[MPCountdownTimerView alloc] initWithFrame:viewController.view.bounds duration:self.countdownDuration]; + [self.interstitial.view addSubview:self.timerView]; + + typeof(self) __weak weakSelf = self; + [self.timerView startWithTimerCompletion:^(BOOL hasElapsed) { + [weakSelf rewardUserWithConfiguration:self.configuration timerHasElapsed:hasElapsed]; + [weakSelf showCloseButton]; + }]; + + [self.interstitial presentInterstitialFromViewController:viewController]; + } + else { + MPLogInfo(@"Failed to show MoPub rewarded playable"); + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorNoAdsAvailable userInfo:nil]; + [self.delegate rewardedVideoDidFailToPlayForCustomEvent:self error:error]; + [self showCloseButton]; + } +} + +#pragma mark - MPInterstitialViewControllerDelegate + +- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial { + MPLogInfo(@"MoPub rewarded playable did load"); + self.adAvailable = YES; + [self.delegate rewardedVideoDidLoadAdForCustomEvent:self]; +} + +- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial { + MPLogInfo(@"MoPub rewarded playable did appear"); + [self.delegate rewardedVideoDidAppearForCustomEvent:self]; +} + +- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial { + MPLogInfo(@"MoPub rewarded playable will appear"); + [self.delegate rewardedVideoWillAppearForCustomEvent:self]; +} + +- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial { + MPLogInfo(@"MoPub rewarded playable failed to load"); + self.adAvailable = NO; + [self.delegate rewardedVideoDidFailToLoadAdForCustomEvent:self error:nil]; +} + +- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial { + [self.delegate rewardedVideoWillDisappearForCustomEvent:self]; +} + +- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial { + self.adAvailable = NO; + [self.timerView stopAndSignalCompletion:NO]; + [self.delegate rewardedVideoDidDisappearForCustomEvent:self]; + + // Get rid of the interstitial view controller when done with it so we don't hold on longer than needed + self.interstitial = nil; +} + +- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial { + [self rewardUserWithConfiguration:self.configuration timerHasElapsed:NO]; + [self.delegate rewardedVideoDidReceiveTapEventForCustomEvent:self]; +} + +- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial { + [self.delegate rewardedVideoWillLeaveApplicationForCustomEvent:self]; +} + +#pragma mark - MPPrivateRewardedVideoCustomEventDelegate + +- (NSString *)adUnitId { + return [self.delegate adUnitId]; +} + +- (MPAdConfiguration *)configuration { + return [self.delegate configuration]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.h new file mode 100644 index 000000000..5fc7bf8d4 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.h @@ -0,0 +1,15 @@ +// +// MPMoPubRewardedVideoCustomEvent.h +// MoPubSDK + +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoCustomEvent.h" +#import "MPPrivateRewardedVideoCustomEventDelegate.h" + +@interface MPMoPubRewardedVideoCustomEvent : MPRewardedVideoCustomEvent + +@property (nonatomic, weak) id delegate; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.m new file mode 100644 index 000000000..d8e28b4b5 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPMoPubRewardedVideoCustomEvent.m @@ -0,0 +1,134 @@ +// +// MPMoPubRewardedVideoCustomEvent.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPMoPubRewardedVideoCustomEvent.h" +#import "MPMRAIDInterstitialViewController.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPRewardedVideoReward.h" +#import "MPAdConfiguration.h" +#import "MPRewardedVideoAdapter.h" +#import "MPRewardedVideoReward.h" +#import "MPRewardedVideoError.h" + +@interface MPMoPubRewardedVideoCustomEvent() + +@property (nonatomic) MPMRAIDInterstitialViewController *interstitial; +@property (nonatomic) BOOL adAvailable; + +@end + +@implementation MPMoPubRewardedVideoCustomEvent + +@dynamic delegate; + +- (void)requestRewardedVideoWithCustomEventInfo:(NSDictionary *)info +{ + MPLogInfo(@"Loading MoPub rewarded video"); + self.interstitial = [[MPInstanceProvider sharedProvider] buildMPMRAIDInterstitialViewControllerWithDelegate:self + configuration:[self.delegate configuration]]; + + [self.interstitial setCloseButtonStyle:MPInterstitialCloseButtonStyleAlwaysHidden]; + [self.interstitial startLoading]; +} + +- (BOOL)hasAdAvailable +{ + return self.adAvailable; +} + +- (void)handleAdPlayedForCustomEventNetwork +{ + // no-op +} + +- (void)handleCustomEventInvalidated +{ + // no-op +} + +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController +{ + if ([self hasAdAvailable]) { + [self.interstitial presentInterstitialFromViewController:viewController]; + } else { + MPLogInfo(@"Failed to show MoPub rewarded video"); + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorNoAdsAvailable userInfo:nil]; + [self.delegate rewardedVideoDidFailToPlayForCustomEvent:self error:error]; + } +} + +#pragma mark - MPMRAIDInterstitialViewControllerDelegate + +- (void)interstitialDidLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub rewarded video did load"); + self.adAvailable = YES; + [self.delegate rewardedVideoDidLoadAdForCustomEvent:self]; +} + +- (void)interstitialDidAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub rewarded video did appear"); + [self.delegate rewardedVideoDidAppearForCustomEvent:self]; +} + +- (void)interstitialWillAppear:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub rewarded video will appear"); + [self.delegate rewardedVideoWillAppearForCustomEvent:self]; +} + +- (void)interstitialDidFailToLoadAd:(MPInterstitialViewController *)interstitial +{ + MPLogInfo(@"MoPub rewarded video failed to load"); + self.adAvailable = NO; + [self.delegate rewardedVideoDidFailToLoadAdForCustomEvent:self error:nil]; +} + +- (void)interstitialWillDisappear:(MPInterstitialViewController *)interstitial +{ + [self.delegate rewardedVideoWillDisappearForCustomEvent:self]; +} + +- (void)interstitialDidDisappear:(MPInterstitialViewController *)interstitial +{ + self.adAvailable = NO; + [self.delegate rewardedVideoDidDisappearForCustomEvent:self]; + + // Get rid of the interstitial view controller when done with it so we don't hold on longer than needed + self.interstitial = nil; +} + +- (void)interstitialDidReceiveTapEvent:(MPInterstitialViewController *)interstitial +{ + [self.delegate rewardedVideoDidReceiveTapEventForCustomEvent:self]; +} + +- (void)interstitialWillLeaveApplication:(MPInterstitialViewController *)interstitial +{ + [self.delegate rewardedVideoWillLeaveApplicationForCustomEvent:self]; +} + +- (void)interstitialRewardedVideoEnded +{ + MPLogInfo(@"MoPub rewarded video finished playing."); + [self.delegate rewardedVideoShouldRewardUserForCustomEvent:self reward:[self configuration].rewardedVideoReward]; +} + +#pragma mark - MPPrivateRewardedVideoCustomEventDelegate +- (NSString *)adUnitId +{ + return [self.delegate adUnitId]; +} + +- (MPAdConfiguration *)configuration +{ + return [self.delegate configuration]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPPrivateRewardedVideoCustomEventDelegate.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPPrivateRewardedVideoCustomEventDelegate.h new file mode 100644 index 000000000..acb689084 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPPrivateRewardedVideoCustomEventDelegate.h @@ -0,0 +1,18 @@ +// +// MPPrivateRewardedVideoCustomEventDelegate.h +// MoPub +// +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPRewardedVideoCustomEvent.h" + +@class MPAdConfiguration; +@class CLLocation; + +@protocol MPPrivateRewardedVideoCustomEventDelegate + +- (NSString *)adUnitId; +- (MPAdConfiguration *)configuration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideo+Internal.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideo+Internal.h new file mode 100644 index 000000000..2e8035463 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideo+Internal.h @@ -0,0 +1,14 @@ +// +// MPRewardedVideo+Internal.h +// MoPubSDK +// Copyright © 2016 MoPub. All rights reserved. +// + +#import "MPRewardedVideo.h" + +@interface MPRewardedVideo (Internal) + ++ (MPRewardedVideo *)sharedInstance; +- (void)startRewardedVideoConnectionWithUrl:(NSURL *)url; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.h new file mode 100644 index 000000000..975fb84ec --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.h @@ -0,0 +1,83 @@ +// +// MPRewardedVideoAdManager.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@class MPRewardedVideoReward; +@class CLLocation; +@protocol MPRewardedVideoAdManagerDelegate; + +/** + * `MPRewardedVideoAdManager` represents a rewarded video for a single ad unit ID. This is the object that + * `MPRewardedVideo` uses to load and present the ad. + */ +@interface MPRewardedVideoAdManager : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, readonly) NSString *adUnitID; +@property (nonatomic, strong) NSArray *mediationSettings; +@property (nonatomic, copy) NSString *customerId; + +- (instancetype)initWithAdUnitID:(NSString *)adUnitID delegate:(id)delegate; + +/** + * Returns the custom event class type. + */ +- (Class)customEventClass; + +/** + * Loads a rewarded video ad with the ad manager's ad unit ID. + * + * @param keywords A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * + * @param location Latitude/Longitude that are passed to the MoPub ad server + * If this method is called when an ad is already available and we haven't already played a video for the last time we loaded an ad, + * the object will simply notify the delegate that an ad loaded. + * + * @param customerId The user's id within the app. + * + * However, if an ad has been played for the last time a load was issued and load is called again, the method will request a new ad. + */ +- (void)loadRewardedVideoAdWithKeywords:(NSString *)keywords location:(CLLocation *)location customerId:(NSString *)customerId; + +/** + * Tells the caller whether the underlying ad network currently has an ad available for presentation. + */ +- (BOOL)hasAdAvailable; + +/** + * Plays a rewarded video ad. + * + * @param viewController Presents the rewarded video ad from viewController. + */ +- (void)presentRewardedVideoAdFromViewController:(UIViewController *)viewController; + +/** + * This method is called when another ad unit has played a rewarded video from the same network this ad manager's custom event + * represents. + */ +- (void)handleAdPlayedForCustomEventNetwork; + +@end + +@protocol MPRewardedVideoAdManagerDelegate + +- (void)rewardedVideoDidLoadForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoDidFailToLoadForAdManager:(MPRewardedVideoAdManager *)manager error:(NSError *)error; +- (void)rewardedVideoDidExpireForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoDidFailToPlayForAdManager:(MPRewardedVideoAdManager *)manager error:(NSError *)error; +- (void)rewardedVideoWillAppearForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoDidAppearForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoWillDisappearForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoDidDisappearForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoDidReceiveTapEventForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoWillLeaveApplicationForAdManager:(MPRewardedVideoAdManager *)manager; +- (void)rewardedVideoShouldRewardUserForAdManager:(MPRewardedVideoAdManager *)manager reward:(MPRewardedVideoReward *)reward; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.m new file mode 100644 index 000000000..ccae1481f --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdManager.m @@ -0,0 +1,249 @@ +// +// MPRewardedVideoAdManager.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoAdManager.h" + +#import "MPAdServerCommunicator.h" +#import "MPAdServerURLBuilder.h" +#import "MPRewardedVideoAdapter.h" +#import "MPInstanceProvider.h" +#import "MPCoreInstanceProvider.h" +#import "MPRewardedVideoError.h" +#import "MPLogging.h" +#import "MoPub.h" + +@interface MPRewardedVideoAdManager () + +@property (nonatomic, strong) MPRewardedVideoAdapter *adapter; +@property (nonatomic, strong) MPAdServerCommunicator *communicator; +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, assign) BOOL loading; +@property (nonatomic, assign) BOOL playedAd; +@property (nonatomic, assign) BOOL ready; + +@end + +@implementation MPRewardedVideoAdManager + +- (instancetype)initWithAdUnitID:(NSString *)adUnitID delegate:(id)delegate +{ + if (self = [super init]) { + _adUnitID = [adUnitID copy]; + _communicator = [[MPCoreInstanceProvider sharedProvider] buildMPAdServerCommunicatorWithDelegate:self]; + _delegate = delegate; + } + + return self; +} + +- (void)dealloc +{ + [_communicator cancel]; +} + +- (Class)customEventClass +{ + return self.configuration.customEventClass; +} + +- (BOOL)hasAdAvailable +{ + // If we've already played an ad, return NO since we allow one play per load. + if (self.playedAd) { + return NO; + } + return [self.adapter hasAdAvailable]; +} + +- (void)loadRewardedVideoAdWithKeywords:(NSString *)keywords location:(CLLocation *)location customerId:(NSString *)customerId +{ + // We will just tell the delegate that we have loaded an ad if we already have one ready. However, if we have already + // played a video for this ad manager, we will go ahead and request another ad from the server so we aren't potentially + // stuck playing ads from the same network for a prolonged period of time which could be unoptimal with respect to the waterfall. + if (self.ready && !self.playedAd) { + // If we already have an ad, do not set the customerId. We'll leave the customerId as the old one since the ad we currently have + // may be tied to an older customerId. + [self.delegate rewardedVideoDidLoadForAdManager:self]; + } else { + // This has multiple behaviors. For ads that require us to set the customID: (outside of load), this will overwrite the ad's previously + // set customerId. Other ads require customerId on presentation in which we will use this new id coming in when presenting the ad. + self.customerId = customerId; + [self loadAdWithURL:[MPAdServerURLBuilder URLWithAdUnitID:self.adUnitID + keywords:keywords + location:location + testing:NO]]; + } +} + +- (void)presentRewardedVideoAdFromViewController:(UIViewController *)viewController +{ + // If we've already played an ad, don't allow playing of another since we allow one play per load. + if (self.playedAd) { + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorAdAlreadyPlayed userInfo:nil]; + [self.delegate rewardedVideoDidFailToPlayForAdManager:self error:error]; + return; + } + + [self.adapter presentRewardedVideoFromViewController:viewController]; +} + +- (void)handleAdPlayedForCustomEventNetwork +{ + // We only need to notify the backing ad network if the ad is marked ready for display. + if (self.ready) { + [self.adapter handleAdPlayedForCustomEventNetwork]; + } +} + +#pragma mark - Private + +- (void)loadAdWithURL:(NSURL *)URL +{ + self.playedAd = NO; + + if (self.loading) { + MPLogWarn(@"Rewarded video manager is already loading an ad. " + @"Wait for previous load to finish."); + return; + } + + MPLogInfo(@"Rewarded video manager is loading ad with MoPub server URL: %@", URL); + + self.loading = YES; + [self.communicator loadURL:URL]; +} + +#pragma mark - MPAdServerCommunicatorDelegate + +- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration +{ + self.configuration = configuration; + + MPLogInfo(@"Rewarded video ad is fetching ad network type: %@", self.configuration.networkType); + + if (self.configuration.adUnitWarmingUp) { + MPLogInfo(kMPWarmingUpErrorLogFormatWithAdUnitID, self.adUnitID); + self.loading = NO; + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorAdUnitWarmingUp userInfo:nil]; + [self.delegate rewardedVideoDidFailToLoadForAdManager:self error:error]; + return; + } + + if ([self.configuration.networkType isEqualToString:kAdTypeClear]) { + MPLogInfo(kMPClearErrorLogFormatWithAdUnitID, self.adUnitID); + self.loading = NO; + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorNoAdsAvailable userInfo:nil]; + [self.delegate rewardedVideoDidFailToLoadForAdManager:self error:error]; + return; + } + + MPRewardedVideoAdapter *adapter = [[MPInstanceProvider sharedProvider] buildRewardedVideoAdapterWithDelegate:self]; + + if (!adapter) { + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorUnknown userInfo:nil]; + [self rewardedVideoDidFailToLoadForAdapter:nil error:error]; + return; + } + + self.adapter = adapter; + [self.adapter getAdWithConfiguration:configuration]; +} + +- (void)communicatorDidFailWithError:(NSError *)error +{ + self.ready = NO; + self.loading = NO; + + [self.delegate rewardedVideoDidFailToLoadForAdManager:self error:error]; +} + +#pragma mark - MPRewardedVideoAdapterDelegate + +- (id)instanceMediationSettingsForClass:(Class)aClass +{ + for (id settings in self.mediationSettings) { + if ([settings isKindOfClass:aClass]) { + return settings; + } + } + + return nil; +} + +- (void)rewardedVideoDidLoadForAdapter:(MPRewardedVideoAdapter *)adapter +{ + self.ready = YES; + self.loading = NO; + [self.delegate rewardedVideoDidLoadForAdManager:self]; +} + +- (void)rewardedVideoDidFailToLoadForAdapter:(MPRewardedVideoAdapter *)adapter error:(NSError *)error +{ + self.ready = NO; + self.loading = NO; + [self loadAdWithURL:self.configuration.failoverURL]; +} + +- (void)rewardedVideoDidExpireForAdapter:(MPRewardedVideoAdapter *)adapter +{ + self.ready = NO; + [self.delegate rewardedVideoDidExpireForAdManager:self]; +} + +- (void)rewardedVideoDidFailToPlayForAdapter:(MPRewardedVideoAdapter *)adapter error:(NSError *)error +{ + [self.delegate rewardedVideoDidFailToPlayForAdManager:self error:error]; +} + +- (void)rewardedVideoWillAppearForAdapter:(MPRewardedVideoAdapter *)adapter +{ + [self.delegate rewardedVideoWillAppearForAdManager:self]; +} + +- (void)rewardedVideoDidAppearForAdapter:(MPRewardedVideoAdapter *)adapter +{ + [self.delegate rewardedVideoDidAppearForAdManager:self]; +} + +- (void)rewardedVideoWillDisappearForAdapter:(MPRewardedVideoAdapter *)adapter +{ + [self.delegate rewardedVideoWillDisappearForAdManager:self]; +} + +- (void)rewardedVideoDidDisappearForAdapter:(MPRewardedVideoAdapter *)adapter +{ + self.ready = NO; + self.playedAd = YES; + [self.delegate rewardedVideoDidDisappearForAdManager:self]; +} + +- (void)rewardedVideoDidReceiveTapEventForAdapter:(MPRewardedVideoAdapter *)adapter +{ + [self.delegate rewardedVideoDidReceiveTapEventForAdManager:self]; +} + +- (void)rewardedVideoWillLeaveApplicationForAdapter:(MPRewardedVideoAdapter *)adapter +{ + [self.delegate rewardedVideoWillLeaveApplicationForAdManager:self]; +} + +- (void)rewardedVideoShouldRewardUserForAdapter:(MPRewardedVideoAdapter *)adapter reward:(MPRewardedVideoReward *)reward +{ + [self.delegate rewardedVideoShouldRewardUserForAdManager:self reward:reward]; +} + +- (NSString *)rewardedVideoAdUnitId +{ + return self.adUnitID; +} + +- (NSString *)rewardedVideoCustomerId +{ + return self.customerId; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.h new file mode 100644 index 000000000..3a81d62be --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.h @@ -0,0 +1,78 @@ +// +// MPRewardedVideoAdapter.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import +#import "MPPrivateRewardedVideoCustomEventDelegate.h" + +@class MPAdConfiguration; +@class MPRewardedVideoReward; + +@protocol MPRewardedVideoAdapterDelegate; +@protocol MPMediationSettingsProtocol; + +/** + * `MPRewardedVideoAdapter` directly communicates with the appropriate custom event to + * load and show a rewarded video. It is also the class that handles impression + * and click tracking. Finally, the class will report a failure to load an ad if the ad + * takes too long to load. + */ +@interface MPRewardedVideoAdapter : NSObject + +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithDelegate:(id)delegate; + +/** + * Called to retrieve an ad once we get a response from the server. + * + * @param configuration Contains the details about the ad we are loading. + */ +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration; + +/** + * Tells the caller whether the underlying ad network currently has an ad available for presentation. + */ +- (BOOL)hasAdAvailable; + +/** + * Plays a rewarded video ad. + * + * @param viewController Presents the rewarded video ad from viewController. + */ +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController; + +/** + * This method is called when another ad unit has played a rewarded video from the same network this adapter's custom event + * represents. + */ +- (void)handleAdPlayedForCustomEventNetwork; + +@end + +@protocol MPRewardedVideoAdapterDelegate + +- (id)instanceMediationSettingsForClass:(Class)aClass; + +- (void)rewardedVideoDidLoadForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoDidFailToLoadForAdapter:(MPRewardedVideoAdapter *)adapter error:(NSError *)error; +- (void)rewardedVideoDidExpireForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoDidFailToPlayForAdapter:(MPRewardedVideoAdapter *)adapter error:(NSError *)error; +- (void)rewardedVideoWillAppearForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoDidAppearForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoWillDisappearForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoDidDisappearForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoDidReceiveTapEventForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoWillLeaveApplicationForAdapter:(MPRewardedVideoAdapter *)adapter; +- (void)rewardedVideoShouldRewardUserForAdapter:(MPRewardedVideoAdapter *)adapter reward:(MPRewardedVideoReward *)reward; + +@optional +- (NSString *)rewardedVideoAdUnitId; +- (NSString *)rewardedVideoCustomerId; +- (MPAdConfiguration *)configuration; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.m new file mode 100644 index 000000000..4fea9b5d8 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoAdapter.m @@ -0,0 +1,279 @@ +// +// MPRewardedVideoAdapter.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoAdapter.h" + +#import "MPAdConfiguration.h" +#import "MPAnalyticsTracker.h" +#import "MPCoreInstanceProvider.h" +#import "MPRewardedVideoError.h" +#import "MPRewardedVideoCustomEvent.h" +#import "MPInstanceProvider.h" +#import "MPLogging.h" +#import "MPTimer.h" +#import "MPRewardedVideoReward.h" +#import "MPRewardedVideo+Internal.h" + +static const NSString *kRewardedVideoApiVersion = @"1"; + +@interface MPRewardedVideoAdapter () + +@property (nonatomic, strong) MPRewardedVideoCustomEvent *rewardedVideoCustomEvent; +@property (nonatomic, strong) MPAdConfiguration *configuration; +@property (nonatomic, strong) MPTimer *timeoutTimer; +@property (nonatomic, assign) BOOL hasTrackedImpression; +@property (nonatomic, assign) BOOL hasTrackedClick; +// Once an ad successfully loads, we want to block sending more successful load events. +@property (nonatomic, assign) BOOL hasSuccessfullyLoaded; +// Since we only notify the application of one success per load, we also only notify the application of one expiration per success. +@property (nonatomic, assign) BOOL hasExpired; + +@end + +@implementation MPRewardedVideoAdapter + +- (instancetype)initWithDelegate:(id)delegate +{ + if (self = [super init]) { + _delegate = delegate; + } + + return self; +} + +- (void)dealloc +{ + // The rewarded video system now no longer holds references to the custom event. The custom event may have a system + // that holds extra references to the custom event. Let's tell the custom event that we no longer need it. + [_rewardedVideoCustomEvent handleCustomEventInvalidated]; + + [_timeoutTimer invalidate]; + + // Make sure the custom event isn't released synchronously as objects owned by the custom event + // may do additional work after a callback that results in dealloc being called + [[MPCoreInstanceProvider sharedProvider] keepObjectAliveForCurrentRunLoopIteration:_rewardedVideoCustomEvent]; +} + +- (void)getAdWithConfiguration:(MPAdConfiguration *)configuration +{ + MPLogInfo(@"Looking for custom event class named %@.", configuration.customEventClass); + + self.configuration = configuration; + + self.rewardedVideoCustomEvent = [[MPInstanceProvider sharedProvider] buildRewardedVideoCustomEventFromCustomClass:configuration.customEventClass delegate:self]; + + if (self.rewardedVideoCustomEvent) { + [self startTimeoutTimer]; + [self.rewardedVideoCustomEvent requestRewardedVideoWithCustomEventInfo:configuration.customEventClassData]; + } else { + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorInvalidCustomEvent userInfo:nil]; + [self.delegate rewardedVideoDidFailToLoadForAdapter:self error:error]; + } +} + +- (BOOL)hasAdAvailable +{ + return [self.rewardedVideoCustomEvent hasAdAvailable]; +} + +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController +{ + [self.rewardedVideoCustomEvent presentRewardedVideoFromViewController:viewController]; +} + +- (void)handleAdPlayedForCustomEventNetwork +{ + [self.rewardedVideoCustomEvent handleAdPlayedForCustomEventNetwork]; +} + +#pragma mark - Private + +- (void)startTimeoutTimer +{ + NSTimeInterval timeInterval = (self.configuration && self.configuration.adTimeoutInterval >= 0) ? + self.configuration.adTimeoutInterval : REWARDED_VIDEO_TIMEOUT_INTERVAL; + + if (timeInterval > 0) { + self.timeoutTimer = [[MPCoreInstanceProvider sharedProvider] buildMPTimerWithTimeInterval:timeInterval + target:self + selector:@selector(timeout) + repeats:NO]; + + [self.timeoutTimer scheduleNow]; + } +} + +- (void)timeout +{ + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorTimeout userInfo:nil]; + [self.delegate rewardedVideoDidFailToLoadForAdapter:self error:error]; +} + +- (void)didStopLoading +{ + [self.timeoutTimer invalidate]; +} + +- (NSURL *)rewardedVideoCompletionUrlByAppendingClientParams +{ + NSString *finalCompletionUrlString = self.configuration.rewardedVideoCompletionUrl; + if ([self.delegate respondsToSelector:@selector(rewardedVideoCustomerId)] && [self.delegate rewardedVideoCustomerId].length > 0) { + // self.configuration.rewardedVideoCompletionUrl is already url encoded. Only the customer_id added by the client needs url encoding. + NSString *urlEncodedCustomerId = [[self.delegate rewardedVideoCustomerId] mp_URLEncodedString]; + finalCompletionUrlString = [NSString stringWithFormat:@"%@&customer_id=%@", finalCompletionUrlString, urlEncodedCustomerId]; + } + finalCompletionUrlString = [NSString stringWithFormat:@"%@&nv=%@&v=%@", finalCompletionUrlString, [MP_SDK_VERSION mp_URLEncodedString], kRewardedVideoApiVersion]; + return [NSURL URLWithString:finalCompletionUrlString]; +} + +#pragma mark - Metrics + +- (void)trackImpression +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackImpressionForConfiguration:self.configuration]; +} + +- (void)trackClick +{ + [[[MPCoreInstanceProvider sharedProvider] sharedMPAnalyticsTracker] trackClickForConfiguration:self.configuration]; +} + +#pragma mark - MPRewardedVideoCustomEventDelegate + +- (id)instanceMediationSettingsForClass:(Class)aClass +{ + return [self.delegate instanceMediationSettingsForClass:aClass]; +} + +- (void)rewardedVideoDidLoadAdForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + // Don't report multiple successful loads. Backing ad networks may replenish their caches triggering multiple successful load + // callbacks. + if (self.hasSuccessfullyLoaded) { + return; + } + + self.hasSuccessfullyLoaded = YES; + [self didStopLoading]; + [self.delegate rewardedVideoDidLoadForAdapter:self]; +} + +- (void)rewardedVideoDidFailToLoadAdForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent error:(NSError *)error +{ + // Detach the custom event from the adapter. An ad *may* end up, after some time, loading successfully + // from the underlying network, but we don't want to bubble up the event to the application since we + // are reporting a timeout here. + [self.rewardedVideoCustomEvent handleCustomEventInvalidated]; + self.rewardedVideoCustomEvent = nil; + + [self didStopLoading]; + [self.delegate rewardedVideoDidFailToLoadForAdapter:self error:error]; +} + +- (void)rewardedVideoDidExpireForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + // Only allow one expire per custom event to match up with one successful load callback per custom event. + if (self.hasExpired) { + return; + } + + self.hasExpired = YES; + [self.delegate rewardedVideoDidExpireForAdapter:self]; +} + +- (void)rewardedVideoDidFailToPlayForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent error:(NSError *)error +{ + [self.delegate rewardedVideoDidFailToPlayForAdapter:self error:error]; +} + +- (void)rewardedVideoWillAppearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + [self.delegate rewardedVideoWillAppearForAdapter:self]; +} + +- (void)rewardedVideoDidAppearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + if ([self.rewardedVideoCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedImpression) { + self.hasTrackedImpression = YES; + [self trackImpression]; + } + + [self.delegate rewardedVideoDidAppearForAdapter:self]; +} + +- (void)rewardedVideoWillDisappearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + [self.delegate rewardedVideoWillDisappearForAdapter:self]; +} + +- (void)rewardedVideoDidDisappearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + [self.delegate rewardedVideoDidDisappearForAdapter:self]; +} + +- (void)rewardedVideoWillLeaveApplicationForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + [self.delegate rewardedVideoWillLeaveApplicationForAdapter:self]; +} + +- (void)rewardedVideoDidReceiveTapEventForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + if ([self.rewardedVideoCustomEvent enableAutomaticImpressionAndClickTracking] && !self.hasTrackedClick) { + self.hasTrackedClick = YES; + [self trackClick]; + } + + [self.delegate rewardedVideoDidReceiveTapEventForAdapter:self]; +} + +- (void)rewardedVideoShouldRewardUserForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent reward:(MPRewardedVideoReward *)reward +{ + if (self.configuration && self.configuration.rewardedVideoCompletionUrl) { + // server to server callback + [[MPRewardedVideo sharedInstance] startRewardedVideoConnectionWithUrl:[self rewardedVideoCompletionUrlByAppendingClientParams]]; + } else { + // server to server not enabled. It uses client side rewarding. + if (self.configuration) { + MPRewardedVideoReward *mopubConfiguredReward = self.configuration.rewardedVideoReward; + // If reward is set in adConfig, use reward that's set in adConfig. + // Currency type has to be defined in mopubConfiguredReward in order to use mopubConfiguredReward. + if (mopubConfiguredReward && mopubConfiguredReward.currencyType != kMPRewardedVideoRewardCurrencyTypeUnspecified){ + reward = mopubConfiguredReward; + } + } + + if (reward) { + [self.delegate rewardedVideoShouldRewardUserForAdapter:self reward:reward]; + } + } +} + +- (NSString *)customerIdForRewardedVideoCustomEvent:(MPRewardedVideoCustomEvent *)customEvent +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoCustomerId)]) { + return [self.delegate rewardedVideoCustomerId]; + } + + return nil; +} + +#pragma mark - MPPrivateRewardedVideoCustomEventDelegate + +- (NSString *)adUnitId +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdUnitId)]) { + return [self.delegate rewardedVideoAdUnitId]; + } + return nil; +} + +- (MPAdConfiguration *)configuration +{ + return _configuration; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.h new file mode 100644 index 000000000..d573b3c9e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.h @@ -0,0 +1,20 @@ +// +// MPRewardedVideoConnection.h +// MoPubSDK +// Copyright © 2016 MoPub. All rights reserved. +// + +@class MPRewardedVideoConnection; + +@protocol MPRewardedVideoConnectionDelegate + +- (void)rewardedVideoConnectionCompleted:(MPRewardedVideoConnection *)connection url:(NSURL *)url; + +@end + +@interface MPRewardedVideoConnection : NSObject + +- (instancetype)initWithUrl:(NSURL *)url delegate:(id)delegate; +- (void)sendRewardedVideoCompletionRequest; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.m new file mode 100644 index 000000000..28db57639 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/Internal/MPRewardedVideoConnection.m @@ -0,0 +1,95 @@ +// +// MPRewardedVideoConnection.m +// MoPubSDK + +// Copyright © 2016 MoPub. All rights reserved. +// + +#import +#import "MPRewardedVideoConnection.h" + +static const NSTimeInterval kMaximumRequestRetryInterval = 900.0; // 15 mins +static const NSTimeInterval kMinimumRequestRetryInterval = 5.0; +static const NSTimeInterval kMaximumBackoffTime = 60.0; +static const CGFloat kRetryIntervalBackoffMultiplier = 2.0; + +@interface MPRewardedVideoConnection() + +@property (nonatomic) NSURLConnection *connection; +@property (nonatomic) NSURL *url; +@property (nonatomic) NSUInteger retryCount; +@property (nonatomic) NSTimeInterval accumulatedRetryInterval; +@property (nonatomic, weak) id delegate; + +@end + +@implementation MPRewardedVideoConnection + +- (instancetype)initWithUrl:(NSURL *)url delegate:(id)delegate +{ + if (self = [super init]) { + _url = url; + _delegate = delegate; + } + return self; +} + +- (void)sendRewardedVideoCompletionRequest +{ + NSURLRequest *request = [NSURLRequest requestWithURL:self.url]; + [self.connection cancel]; + self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; +} + +- (void)retryRewardedVideoCompletionRequest +{ + NSTimeInterval retryInterval = [self backoffTime:self.retryCount]; + + self.accumulatedRetryInterval += retryInterval; + + if (self.accumulatedRetryInterval < kMaximumRequestRetryInterval) { + [self performSelector:@selector(sendRewardedVideoCompletionRequest) withObject:nil afterDelay:retryInterval]; + } else { + [self.delegate rewardedVideoConnectionCompleted:self url:self.url]; + [self.connection cancel]; + } + self.retryCount++; +} + +- (NSTimeInterval)backoffTime:(NSUInteger)retryCount +{ + NSTimeInterval interval = pow(kRetryIntervalBackoffMultiplier, retryCount) * kMinimumRequestRetryInterval; + + // If interval > kMaximumBackoffTime, we'll retry every kMaximumBackoffTime seconds to ensure retry happens + // often enough. + if (interval > kMaximumBackoffTime) { + interval = kMaximumBackoffTime; + } + return interval; +} + +#pragma mark - + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + if (error.code == NSURLErrorTimedOut || + error.code == NSURLErrorNetworkConnectionLost || + error.code == NSURLErrorNotConnectedToInternet) { + [self retryRewardedVideoCompletionRequest]; + } else { + [self.delegate rewardedVideoConnectionCompleted:self url:self.url]; + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; + // only retry on 5xx + if (statusCode >= 500 && statusCode <= 599) { + [self retryRewardedVideoCompletionRequest]; + } else { + [self.delegate rewardedVideoConnectionCompleted:self url:self.url]; + } +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPMediationSettingsProtocol.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPMediationSettingsProtocol.h new file mode 100644 index 000000000..180b77e61 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPMediationSettingsProtocol.h @@ -0,0 +1,35 @@ +// +// MPMediationSettingsProtocol.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +/** + * The MoPub SDK has a concept of mediation settings that allow you to define objects + * that allow the application to configure specific settings for your custom event's ad + * network. + * + * Your object can be a global mediation setting that contains settings you deem to be constant + * across all of your ad network's ads. Ideally this is where you will place settings necessary for + * your ad network's intialization as well. The global medation setting object should be ready for + * your custom event by the time you load the ad from your network. Inside your custom event, you can retrieve + * the global mediation settings by calling `[-globalMediationSettingsForClass:]([MoPub -globalMediationSettingsForClass:])` + * passing in the class type of your global based mediation settings object. + * + * You can also define instance based mediation settings. The application may or may not define + * a mediation settings object per ad unit ID in their application. This allows ads in different locations + * to behave differently. The instance based mediation settings object should be available to your custom event + * by the time you load the ad from your network. Inside your custom event, you can retrieve the instance based + * mediation settings by calling `[-instanceMediationSettingsForClass:]([MPRewardedVideoCustomEventDelegate -instanceMediationSettingsForClass:])` + * passing in the class type of your instance based mediation settings object. + * + * **Important**: Your custom event must not assume it will receive a global or any instance based mediation settings + * as the application may choose not to supply any. Your custom event must have a default implementation in the event + * the application doesn't wish to provide any specific settings. + */ +@protocol MPMediationSettingsProtocol + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.h new file mode 100644 index 000000000..1c07ebd33 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.h @@ -0,0 +1,179 @@ +// +// MPRewardedVideo.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@class MPRewardedVideoReward; +@class CLLocation; +@protocol MPRewardedVideoDelegate; + +/** + * `MPRewardedVideo` allows you to load and play rewarded video ads. All ad events are + * reported, with an ad unit ID, to the delegate allowing the application to respond to the events + * for the corresponding ad. + * + * **Important**: You must call `[initializeRewardedVideoWithGlobalMediationSettings:delegate:][MoPub initializeRewardedVideoWithGlobalMediationSettings:delegate:]` + * to initialize the rewarded video system. + */ +@interface MPRewardedVideo : NSObject + +/** + * Loads a rewarded video ad for the given ad unit ID. + * + * The mediation settings array should contain ad network specific objects for networks that may be loaded for the given ad unit ID. + * You should set the properties on these objects to determine how the underlying ad network should behave. You only need to supply + * objects for the networks you wish to configure. If you do not want your network to behave differently from its default behavior, do + * not pass in an mediation settings object for that network. + * + * @param adUnitID The ad unit ID that ads should be loaded from. + * @param mediationSettings An array of mediation settings objects that map to networks that may show ads for the ad unit ID. This array + * should only contain objects for networks you wish to configure. This can be nil. + */ ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID withMediationSettings:(NSArray *)mediationSettings; + +/** + * Loads a rewarded video ad for the given ad unit ID. + * + * The mediation settings array should contain ad network specific objects for networks that may be loaded for the given ad unit ID. + * You should set the properties on these objects to determine how the underlying ad network should behave. You only need to supply + * objects for the networks you wish to configure. If you do not want your network to behave differently from its default behavior, do + * not pass in an mediation settings object for that network. + * + * @param adUnitID The ad unit ID that ads should be loaded from. + * @param keywords A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * @param location Latitude/Longitude that are passed to the MoPub ad server + * @param mediationSettings An array of mediation settings objects that map to networks that may show ads for the ad unit ID. This array + * should only contain objects for networks you wish to configure. This can be nil. + */ ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID keywords:(NSString *)keywords location:(CLLocation *)location mediationSettings:(NSArray *)mediationSettings; + +/** + * Loads a rewarded video ad for the given ad unit ID. + * + * The mediation settings array should contain ad network specific objects for networks that may be loaded for the given ad unit ID. + * You should set the properties on these objects to determine how the underlying ad network should behave. You only need to supply + * objects for the networks you wish to configure. If you do not want your network to behave differently from its default behavior, do + * not pass in an mediation settings object for that network. + * + * @param adUnitID The ad unit ID that ads should be loaded from. + * @param keywords A string representing a set of keywords that should be passed to the MoPub ad server to receive + * more relevant advertising. + * @param location Latitude/Longitude that are passed to the MoPub ad server + * @param customerId This is the ID given to the user by the publisher to identify them in their app + * @param mediationSettings An array of mediation settings objects that map to networks that may show ads for the ad unit ID. This array + * should only contain objects for networks you wish to configure. This can be nil. + */ ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID keywords:(NSString *)keywords location:(CLLocation *)location customerId:(NSString *)customerId mediationSettings:(NSArray *)mediationSettings; + +/** + * Returns whether or not an ad is available for the given ad unit ID. + * + * @param adUnitID The ad unit ID associated with the ad you want to retrieve the availability for. + */ ++ (BOOL)hasAdAvailableForAdUnitID:(NSString *)adUnitID; + +/** + * Plays a rewarded video ad. + * + * @param adUnitID The ad unit ID associated with the video ad you wish to play. + * @param viewController The view controller that will present the rewarded video ad. + * + * @warning **Important**: You should not attempt to play the rewarded video unless `+hasAdAvailableForAdUnitID:` indicates that an + * ad is available for playing or you have received the `[-rewardedVideoAdDidLoadForAdUnitID:]([MPRewardedVideoDelegate rewardedVideoAdDidLoadForAdUnitID:])` + * message. + */ ++ (void)presentRewardedVideoAdForAdUnitID:(NSString *)adUnitID fromViewController:(UIViewController *)viewController; + +@end + +@protocol MPRewardedVideoDelegate + +@optional + +/** + * This method is called after an ad loads successfully. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdDidLoadForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called after an ad fails to load. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + * @param error An error indicating why the ad failed to load. + */ +- (void)rewardedVideoAdDidFailToLoadForAdUnitID:(NSString *)adUnitID error:(NSError *)error; + +/** + * This method is called when a previously loaded rewarded video is no longer eligible for presentation. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdDidExpireForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when an attempt to play a rewarded video fails. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + * @param error An error describing why the video couldn't play. + */ +- (void)rewardedVideoAdDidFailToPlayForAdUnitID:(NSString *)adUnitID error:(NSError *)error; + +/** + * This method is called when a rewarded video ad is about to appear. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdWillAppearForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when a rewarded video ad has appeared. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdDidAppearForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when a rewarded video ad will be dismissed. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdWillDisappearForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when a rewarded video ad has been dismissed. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdDidDisappearForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when the user taps on the ad. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdDidReceiveTapEventForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when a rewarded video ad will cause the user to leave the application. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + */ +- (void)rewardedVideoAdWillLeaveApplicationForAdUnitID:(NSString *)adUnitID; + +/** + * This method is called when the user should be rewarded for watching a rewarded video ad. + * + * @param adUnitID The ad unit ID of the ad associated with the event. + * @param reward The object that contains all the information regarding how much you should reward the user. + */ +- (void)rewardedVideoAdShouldRewardForAdUnitID:(NSString *)adUnitID reward:(MPRewardedVideoReward *)reward; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.m new file mode 100644 index 000000000..72262dcf7 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideo.m @@ -0,0 +1,240 @@ +// +// MPRewardedVideo.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideo.h" +#import "MPLogging.h" +#import "MPRewardedVideoAdManager.h" +#import "MPInstanceProvider.h" +#import "MPRewardedVideoError.h" +#import "MPRewardedVideoConnection.h" +#import "MPRewardedVideo+Internal.h" + +static MPRewardedVideo *gSharedInstance = nil; + +@interface MPRewardedVideo () + +@property (nonatomic, strong) NSMutableDictionary *rewardedVideoAdManagers; +@property (nonatomic, weak) id delegate; +@property (nonatomic) NSMutableArray *rewardedVideoConnections; + ++ (MPRewardedVideo *)sharedInstance; + +@end + +@implementation MPRewardedVideo + +- (instancetype)init +{ + if (self = [super init]) { + _rewardedVideoAdManagers = [[NSMutableDictionary alloc] init]; + _rewardedVideoConnections = [NSMutableArray new]; + } + + return self; +} + ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID withMediationSettings:(NSArray *)mediationSettings +{ + [MPRewardedVideo loadRewardedVideoAdWithAdUnitID:adUnitID keywords:nil location:nil mediationSettings:mediationSettings]; +} + ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID keywords:(NSString *)keywords location:(CLLocation *)location mediationSettings:(NSArray *)mediationSettings +{ + [self loadRewardedVideoAdWithAdUnitID:adUnitID keywords:keywords location:location customerId:nil mediationSettings:mediationSettings]; +} + ++ (void)loadRewardedVideoAdWithAdUnitID:(NSString *)adUnitID keywords:(NSString *)keywords location:(CLLocation *)location customerId:(NSString *)customerId mediationSettings:(NSArray *)mediationSettings +{ + MPRewardedVideo *sharedInstance = [[self class] sharedInstance]; + + if (![adUnitID length]) { + NSError *error = [NSError errorWithDomain:MoPubRewardedVideoAdsSDKDomain code:MPRewardedVideoAdErrorInvalidAdUnitID userInfo:nil]; + [sharedInstance.delegate rewardedVideoAdDidFailToLoadForAdUnitID:adUnitID error:error]; + return; + } + + MPRewardedVideoAdManager *adManager = sharedInstance.rewardedVideoAdManagers[adUnitID]; + + if (!adManager) { + adManager = [[MPInstanceProvider sharedProvider] buildRewardedVideoAdManagerWithAdUnitID:adUnitID delegate:sharedInstance]; + sharedInstance.rewardedVideoAdManagers[adUnitID] = adManager; + } + + adManager.mediationSettings = mediationSettings; + + [adManager loadRewardedVideoAdWithKeywords:keywords location:location customerId:customerId]; +} + ++ (BOOL)hasAdAvailableForAdUnitID:(NSString *)adUnitID +{ + MPRewardedVideo *sharedInstance = [[self class] sharedInstance]; + MPRewardedVideoAdManager *adManager = sharedInstance.rewardedVideoAdManagers[adUnitID]; + + return [adManager hasAdAvailable]; +} + ++ (void)presentRewardedVideoAdForAdUnitID:(NSString *)adUnitID fromViewController:(UIViewController *)viewController +{ + MPRewardedVideo *sharedInstance = [[self class] sharedInstance]; + MPRewardedVideoAdManager *adManager = sharedInstance.rewardedVideoAdManagers[adUnitID]; + + if (!adManager) { + MPLogWarn(@"The rewarded video could not be shown: " + @"no ads have been loaded for adUnitID: %@", adUnitID); + + return; + } + + if (!viewController) { + MPLogWarn(@"The rewarded video could not be shown: " + @"a nil view controller was passed to -presentRewardedVideoAdForAdUnitID:fromViewController:."); + + return; + } + + if (![viewController.view.window isKeyWindow]) { + MPLogWarn(@"Attempting to present a rewarded video ad in non-key window. The ad may not render properly."); + } + + [adManager presentRewardedVideoAdFromViewController:viewController]; +} + +#pragma mark - Private + ++ (MPRewardedVideo *)sharedInstance +{ + static dispatch_once_t once; + + dispatch_once(&once, ^{ + gSharedInstance = [[self alloc] init]; + }); + + return gSharedInstance; +} + +// This is private as we require the developer to initialize rewarded video through the MoPub object. ++ (void)initializeWithDelegate:(id)delegate +{ + MPRewardedVideo *sharedInstance = [[self class] sharedInstance]; + + // Do not allow calls to initialize twice. + if (sharedInstance.delegate) { + MPLogWarn(@"Attempting to initialize MPRewardedVideo when it has already been initialized."); + } else { + sharedInstance.delegate = delegate; + } +} + +#pragma mark - MPRewardedVideoAdManagerDelegate + +- (void)rewardedVideoDidLoadForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidLoadForAdUnitID:)]) { + [self.delegate rewardedVideoAdDidLoadForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoDidFailToLoadForAdManager:(MPRewardedVideoAdManager *)manager error:(NSError *)error +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidFailToLoadForAdUnitID:error:)]) { + [self.delegate rewardedVideoAdDidFailToLoadForAdUnitID:manager.adUnitID error:error]; + } +} + +- (void)rewardedVideoDidExpireForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidExpireForAdUnitID:)]) { + [self.delegate rewardedVideoAdDidExpireForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoDidFailToPlayForAdManager:(MPRewardedVideoAdManager *)manager error:(NSError *)error +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidFailToPlayForAdUnitID:error:)]) { + [self.delegate rewardedVideoAdDidFailToPlayForAdUnitID:manager.adUnitID error:error]; + } +} + +- (void)rewardedVideoWillAppearForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdWillAppearForAdUnitID:)]) { + [self.delegate rewardedVideoAdWillAppearForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoDidAppearForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidAppearForAdUnitID:)]) { + [self.delegate rewardedVideoAdDidAppearForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoWillDisappearForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdWillDisappearForAdUnitID:)]) { + [self.delegate rewardedVideoAdWillDisappearForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoDidDisappearForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidDisappearForAdUnitID:)]) { + [self.delegate rewardedVideoAdDidDisappearForAdUnitID:manager.adUnitID]; + } + + // Since multiple ad units may be attached to the same network, we should notify the custom events (which should then notify the application) + // that their ads may not be available anymore since another ad unit might have "played" their ad. We go through and notify all ad managers + // that are of the type of ad that is playing now. + Class customEventClass = manager.customEventClass; + + for (id key in self.rewardedVideoAdManagers) { + MPRewardedVideoAdManager *adManager = self.rewardedVideoAdManagers[key]; + + if (adManager != manager && adManager.customEventClass == customEventClass) { + [adManager handleAdPlayedForCustomEventNetwork]; + } + } +} + +- (void)rewardedVideoDidReceiveTapEventForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdDidReceiveTapEventForAdUnitID:)]) { + [self.delegate rewardedVideoAdDidReceiveTapEventForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoWillLeaveApplicationForAdManager:(MPRewardedVideoAdManager *)manager +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdWillLeaveApplicationForAdUnitID:)]) { + [self.delegate rewardedVideoAdWillLeaveApplicationForAdUnitID:manager.adUnitID]; + } +} + +- (void)rewardedVideoShouldRewardUserForAdManager:(MPRewardedVideoAdManager *)manager reward:(MPRewardedVideoReward *)reward +{ + if ([self.delegate respondsToSelector:@selector(rewardedVideoAdShouldRewardForAdUnitID:reward:)]) { + [self.delegate rewardedVideoAdShouldRewardForAdUnitID:manager.adUnitID reward:reward]; + } +} + +#pragma mark - rewarded video server to server callback + +- (void)startRewardedVideoConnectionWithUrl:(NSURL *)url +{ + MPRewardedVideoConnection *connection = [[MPRewardedVideoConnection alloc] initWithUrl:url delegate:self]; + [self.rewardedVideoConnections addObject:connection]; + [connection sendRewardedVideoCompletionRequest]; +} + +#pragma mark - MPRewardedVideoConnectionDelegate + +- (void)rewardedVideoConnectionCompleted:(MPRewardedVideoConnection *)connection url:(NSURL *)url +{ + [self.rewardedVideoConnections removeObject:connection]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.h new file mode 100644 index 000000000..a0fc2b3dd --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.h @@ -0,0 +1,301 @@ +// +// MPRewardedVideoCustomEvent.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import +#import + +@protocol MPRewardedVideoCustomEventDelegate; +@protocol MPMediationSettingsProtocol; + +@class MPRewardedVideoReward; + +/** + * The MoPub iOS SDK mediates third party Ad Networks using custom events. The custom events are + * responsible for instantiating and manipulating objects in the third party SDK and translating + * and communicating events from those objects back to the MoPub SDK by notifying a delegate. + * + * `MPRewardedVideoCustomEvent` is a base class for custom events that support full-screen rewarded video ads. + * By implementing subclasses of `MPRewardedVideoCustomEvent` you can enable the MoPub SDK to + * natively support a wide variety of third-party ad networks. + * + * At runtime, the MoPub SDK will find and instantiate an `MPRewardedVideoCustomEvent` subclass as needed and + * invoke its `-requestRewardedVideoWithCustomEventInfo:` method. + */ + +@interface MPRewardedVideoCustomEvent : NSObject + +@property (nonatomic, weak) id delegate; + +/** @name Requesting and Displaying a Rewarded Video Ad */ + +/** + * Called when the MoPub SDK requires a new rewarded video ad. + * + * When the MoPub SDK receives a response indicating it should load a custom event, it will send + * this message to your custom event class. Your implementation of this method should load an + * rewarded video ad from a third-party ad network. It must also notify the + * `MPRewardedVideoCustomEventDelegate` of certain lifecycle events. + * + * The default implementation of this method does nothing. Subclasses must override this method and implement code to load a rewarded video here. + * + * **Important**: The application may provide a mediation settings object containing properties that you should use to configure how you use + * the ad network's APIs. Call `[-mediationSettingsForClass:]([MPRewardedVideoCustomEventDelegate mediationSettingsForClass:])` + * specifying a specific class that your custom event uses to retrieve the mediation settings object if it exists. You define + * the mediation settings class and the properties it supports for your custom event. + * + * @param info A dictionary containing additional custom data associated with a given custom event + * request. This data is configurable on the MoPub website, and may be used to pass dynamic information, such as publisher IDs. + */ +- (void)requestRewardedVideoWithCustomEventInfo:(NSDictionary *)info; + +/** + * Called when the MoPubSDK wants to know if an ad is currently available for the ad network. + * + * This call is typically invoked when the application wants to check whether an ad unit has an ad ready to display. + * + * Subclasses must override this method and implement coheck whether or not a rewarded vidoe ad is available for presentation. + * + */ +- (BOOL)hasAdAvailable; + +/** + * Called when the rewarded video should be displayed. + * + * This message is sent sometime after a rewarded video has been successfully loaded, as a result + * of your code calling `-[MPRewardedVideo presentRewardedVideoAdForAdUnitID:fromViewController:]`. Your implementation + * of this method should present the rewarded video ad from the specified view controller. + * + * The default implementation of this method does nothing. Subclasses must override this method and implement code to display a rewarded video here. + * + * If you decide to [opt out of automatic impression tracking](enableAutomaticImpressionAndClickTracking), you should place your + * manual calls to [-trackImpression]([MPRewardedVideoCustomEventDelegate trackImpression]) in this method to ensure correct metrics. + * + * @param viewController The controller to use to present the rewarded video modally. + */ +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController; + +/** @name Impression and Click Tracking */ + +/** + * Override to opt out of automatic impression and click tracking. + * + * By default, the MPRewardedVideoCustomEventDelegate will automatically record impressions and clicks in + * response to the appropriate callbacks. You may override this behavior by implementing this method + * to return `NO`. + * + * @warning **Important**: If you do this, you are responsible for calling the `[-trackImpression]([MPRewardedVideoCustomEventDelegate trackImpression])` and + * `[-trackClick]([MPRewardedVideoCustomEventDelegate trackClick])` methods on the custom event delegate. Additionally, you should make sure that these + * methods are only called **once** per ad. + */ +- (BOOL)enableAutomaticImpressionAndClickTracking; + +/** + * Override this method to handle when an ad was played for this custom event's network, but under a different ad unit ID. + * + * Due to the way ad mediation works, two ad units may load the same ad network for displaying ads. When one ad unit plays + * an ad, the other ad unit may need to update its state and notify the application an ad may no longer be available as it + * may have already played. If an ad becomes unavailable for this custom event, call + * `[-rewardedVideoDidExpireForCustomEvent:]([MPRewardedVideoCustomEventDelegate rewardedVideoDidExpireForCustomEvent:])` + * to notify the application that an ad is no longer available. + * + * This method will only be called if your custom event has reported that an ad had successfully loaded. The default implementation of this method does nothing. + * Subclasses must override this method and implement code to handle when the custom event is no longer needed by the rewarded video system. + */ +- (void)handleAdPlayedForCustomEventNetwork; + +/** + * Override this method to handle when the custom event is no longer needed by the rewarded video system. + * + * This method is called once the rewarded video system no longer references your custom event. This method + * is provided as you may have a centralized object holding onto this custom event. If that is the case and your + * centralized object no longer needs the custom event, then you should remove the custom event from the centralized + * object in this method causing the custom event to deallocate. See `MPAdColonyRewardedVideoCustomEvent` for an + * example of how and why this method is used. + * + * Implementation of this method is not necessary if you do not hold any extra references to it. `-dealloc` will still + * be called. However, it is expected you will need to override this method to prevent memory leaks. It is safe to override with nothing + * if you believe you will not leak memory. + */ +- (void)handleCustomEventInvalidated; + +@end + +@protocol MPRewardedVideoCustomEventDelegate + +/** @name Rewarded Video Ad Mediation Settings */ + +/** + * Call this method to retrieve a mediation settings object (if one is provided by the application) for this instance + * of your ad. + * + * @param aClass The specific mediation settings class your custom event uses to configure itself for its ad network. + */ +- (id)instanceMediationSettingsForClass:(Class)aClass; + +/** @name Rewarded Video Ad Event Callbacks - Fetching Ads */ + +/** + * Call this method immediately after an ad loads succesfully. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it successfully loads an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)rewardedVideoDidLoadAdForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method immediately after an ad fails to load. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param error (*optional*) You may pass an error describing the failure. + * + * @warning **Important**: Your custom event subclass **must** call this method when it fails to load an ad. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)rewardedVideoDidFailToLoadAdForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent error:(NSError *)error; + +/** + * Call this method if a previously loaded rewarded video should no longer be eligible for presentation. + * + * Some third-party networks will mark rewarded videos as expired (indicating they should not be + * presented) *after* they have loaded. You may use this method to inform the MoPub SDK that a + * previously loaded rewarded video has expired and that a new rewarded video should be obtained. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + */ +- (void)rewardedVideoDidExpireForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when the application has attempted to play a rewarded video and it cannot be played. + * + * A common usage of this delegate method is when the application tries to play an ad and an ad is not available for play. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param error The error describing why the video couldn't play. + */ +- (void)rewardedVideoDidFailToPlayForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent error:(NSError *)error; + +/** + * Call this method when an ad is about to appear. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is about to present the rewarded video. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)rewardedVideoWillAppearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when an ad has finished appearing. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is finished presenting the rewarded video. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + * **Note**: If it is not possible to know when the rewarded video *finished* appearing, you should call + * this immediately after calling `-rewardedVideoWillAppearForCustomEvent:`. + */ +- (void)rewardedVideoDidAppearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when an ad is about to disappear. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is about to dismiss the rewarded video. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + */ +- (void)rewardedVideoWillDisappearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when an ad has finished disappearing. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @warning **Important**: Your custom event subclass **must** call this method when it is finished with dismissing the rewarded video. + * Failure to do so will disrupt the mediation waterfall and cause future ad requests to stall. + * + * **Note**: if it is not possible to know when the rewarded video *finished* dismissing, you should call + * this immediately after calling `-rewardedVideoWillDisappearForCustomEvent:`. + */ +- (void)rewardedVideoDidDisappearForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when the rewarded video ad will cause the user to leave the application. + * + * For example, the user may have tapped on the video which redirects the user to the App Store or Safari. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + */ +- (void)rewardedVideoWillLeaveApplicationForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when the user taps on the rewarded video ad. + * + * This method is optional. When automatic click and impression tracking are enabled (the default) + * this method will track a click (the click is guaranteed to only be tracked once per ad). + * + * **Note**: some third-party networks provide a "will leave application" callback instead of/in + * addition to a "user did click" callback. You should call this method in response to either of + * those callbacks (since leaving the application is generally an indicator of a user tap). + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + */ +- (void)rewardedVideoDidReceiveTapEventForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** + * Call this method when the user should be rewarded for watching the rewarded video. + * + * @param customEvent You should pass `self` to allow the MoPub SDK to associate this event with the correct + * instance of your custom event. + * + * @param reward The reward object that contains the currency type as well as the amount that should be rewarded to + * the user. If the concept of currency type doesn't exist for your ad network, set the reward's currency type as + * kMPRewardedVideoRewardCurrencyTypeUnspecified. + */ +- (void)rewardedVideoShouldRewardUserForCustomEvent:(MPRewardedVideoCustomEvent *)customEvent reward:(MPRewardedVideoReward *)reward; + +/** + * Call this method to get the customer ID associated with this custom event. + * + * @return The user's customer ID. + */ +- (NSString *)customerIdForRewardedVideoCustomEvent:(MPRewardedVideoCustomEvent *)customEvent; + +/** @name Impression and Click Tracking */ + +/** + * Call this method to track an impression. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPRewardedVideoCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks impressions. + */ +- (void)trackImpression; + +/** + * Call this method to track a click. + * + * @warning **Important**: You should **only** call this method if you have [opted out of automatic click and impression tracking]([MPRewardedVideoCustomEvent enableAutomaticImpressionAndClickTracking]). + * By default the MoPub SDK automatically tracks clicks. + */ +- (void)trackClick; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.m new file mode 100644 index 000000000..2ed84596e --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoCustomEvent.m @@ -0,0 +1,52 @@ +// +// MPRewardedVideoCustomEvent.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoCustomEvent.h" +#import + +@implementation MPRewardedVideoCustomEvent + +- (void)requestRewardedVideoWithCustomEventInfo:(NSDictionary *)info +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to load a rewarded video here. +} + +- (BOOL)hasAdAvailable +{ + // Subclasses must override this method and implement coheck whether or not a rewarded vidoe ad + // is available for presentation. + + return NO; +} + +- (void)presentRewardedVideoFromViewController:(UIViewController *)viewController +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to display a rewarded video here. +} + +- (BOOL)enableAutomaticImpressionAndClickTracking +{ + // Subclasses may override this method to return NO to perform impression and click tracking + // manually. + return YES; +} + +- (void)handleAdPlayedForCustomEventNetwork +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to handle when another ad unit plays an ad for the same ad network this custom event is representing. +} + +- (void)handleCustomEventInvalidated +{ + // The default implementation of this method does nothing. Subclasses must override this method + // and implement code to handle when the custom event is no longer needed by the rewarded video system. +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.h new file mode 100644 index 000000000..6d56c9286 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.h @@ -0,0 +1,22 @@ +// +// MPRewardedVideoError.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +typedef enum { + MPRewardedVideoAdErrorUnknown = -1, + + MPRewardedVideoAdErrorTimeout = -1000, + MPRewardedVideoAdErrorAdUnitWarmingUp = -1001, + MPRewardedVideoAdErrorNoAdsAvailable = -1100, + MPRewardedVideoAdErrorInvalidCustomEvent = -1200, + MPRewardedVideoAdErrorMismatchingAdTypes = -1300, + MPRewardedVideoAdErrorAdAlreadyPlayed = -1400, + MPRewardedVideoAdErrorInvalidAdUnitID = -1500 +} MPRewardedVideoErrorCode; + +extern NSString * const MoPubRewardedVideoAdsSDKDomain; diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.m new file mode 100644 index 000000000..b02d26cea --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoError.m @@ -0,0 +1,10 @@ +// +// MPRewardedVideoError.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoError.h" + +NSString * const MoPubRewardedVideoAdsSDKDomain = @"MoPubRewardedVideoAdsSDKDomain"; \ No newline at end of file diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.h b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.h new file mode 100644 index 000000000..5738b0c3c --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.h @@ -0,0 +1,59 @@ +// +// MPRewardedVideoReward.h +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import + +/** + * A constant that indicates that no currency type was specified with the reward. + */ +extern NSString *const kMPRewardedVideoRewardCurrencyTypeUnspecified; + +/** + * A constant that indicates that no currency amount was specified with the reward. + */ +extern NSInteger const kMPRewardedVideoRewardCurrencyAmountUnspecified; + + +/** + * `MPRewardedVideoReward` contains all the information needed to reward the user for watching + * a rewarded video ad. The class provides a currency amount and currency type. + */ + +@interface MPRewardedVideoReward : NSObject + +/** + * The type of currency that should be rewarded to the user. + * + * An undefined currency type should be specified as `kMPRewardedVideoRewardCurrencyTypeUnspecified`. + */ +@property (nonatomic, readonly) NSString *currencyType; + +/** + * The amount of currency to reward to the user. + * + * An undefined currency amount should be specified as `kMPRewardedVideoRewardCurrencyAmountUnspecified` + * wrapped as an NSNumber. + */ +@property (nonatomic, readonly) NSNumber *amount; + +/** + * Initializes the object with an undefined currency type (`kMPRewardedVideoRewardCurrencyTypeUnspecified`) and + * the amount passed in. + * + * @param amount The amount of currency the user is receiving. + */ +- (instancetype)initWithCurrencyAmount:(NSNumber *)amount; + +/** + * Initializes the object's properties with the currencyType and amount. + * + * @param currencyType The type of currency the user is receiving. + * @param amount The amount of currency the user is receiving. + */ +- (instancetype)initWithCurrencyType:(NSString *)currencyType amount:(NSNumber *)amount; + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.m b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.m new file mode 100644 index 000000000..de78f6471 --- /dev/null +++ b/examples/PrebidMobileDemo/MoPubSDK/RewardedVideo/MPRewardedVideoReward.m @@ -0,0 +1,30 @@ +// +// MPRewardedVideoReward.m +// MoPubSDK +// +// Copyright (c) 2015 MoPub. All rights reserved. +// + +#import "MPRewardedVideoReward.h" + +NSString *const kMPRewardedVideoRewardCurrencyTypeUnspecified = @"MPMoPubRewardedVideoRewardCurrencyTypeUnspecified"; +NSInteger const kMPRewardedVideoRewardCurrencyAmountUnspecified = 0; + +@implementation MPRewardedVideoReward + +- (instancetype)initWithCurrencyType:(NSString *)currencyType amount:(NSNumber *)amount +{ + if (self = [super init]) { + _currencyType = [currencyType copy]; + _amount = amount; + } + + return self; +} + +- (instancetype)initWithCurrencyAmount:(NSNumber *)amount +{ + return [self initWithCurrencyType:kMPRewardedVideoRewardCurrencyTypeUnspecified amount:amount]; +} + +@end diff --git a/examples/PrebidMobileDemo/MoPubSDK/libMoPubSDK.a b/examples/PrebidMobileDemo/MoPubSDK/libMoPubSDK.a new file mode 100755 index 000000000..e516618b8 Binary files /dev/null and b/examples/PrebidMobileDemo/MoPubSDK/libMoPubSDK.a differ diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.pbxproj b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.pbxproj new file mode 100644 index 000000000..c5b83edf1 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.pbxproj @@ -0,0 +1,1675 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + C23386CB1EE5DAC9002FD404 /* PrebidMobile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C23386CA1EE5DAA7002FD404 /* PrebidMobile.framework */; }; + C23386CC1EE5DAC9002FD404 /* PrebidMobile.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C23386CA1EE5DAA7002FD404 /* PrebidMobile.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C268CA911EA65FD7008656F2 /* pbm_basic.feature in Resources */ = {isa = PBXBuildFile; fileRef = C268CA871EA65FD7008656F2 /* pbm_basic.feature */; }; + C268CA921EA65FD7008656F2 /* pbm_basic.rb in Resources */ = {isa = PBXBuildFile; fileRef = C268CA891EA65FD7008656F2 /* pbm_basic.rb */; }; + C268CA931EA65FD7008656F2 /* 01_launch.rb in Resources */ = {isa = PBXBuildFile; fileRef = C268CA8B1EA65FD7008656F2 /* 01_launch.rb */; }; + C268CA941EA65FD7008656F2 /* dry_run.rb in Resources */ = {isa = PBXBuildFile; fileRef = C268CA8C1EA65FD7008656F2 /* dry_run.rb */; }; + C268CA951EA65FD7008656F2 /* env.rb in Resources */ = {isa = PBXBuildFile; fileRef = C268CA8D1EA65FD7008656F2 /* env.rb */; }; + C268CA961EA65FD7008656F2 /* cucumber.rb in Resources */ = {isa = PBXBuildFile; fileRef = C268CA8F1EA65FD7008656F2 /* cucumber.rb */; }; + C273C80A1E82DAAD003EF1AB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C273C8091E82DAAD003EF1AB /* main.m */; }; + C273C80D1E82DAAD003EF1AB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C273C80C1E82DAAD003EF1AB /* AppDelegate.m */; }; + C273C8131E82DAAE003EF1AB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C273C8111E82DAAE003EF1AB /* Main.storyboard */; }; + C273C8151E82DAAE003EF1AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C273C8141E82DAAE003EF1AB /* Assets.xcassets */; }; + C273C8181E82DAAE003EF1AB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C273C8161E82DAAE003EF1AB /* LaunchScreen.storyboard */; }; + C273C8231E82DAAE003EF1AB /* PrebidMobileDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C273C8221E82DAAE003EF1AB /* PrebidMobileDemoTests.m */; }; + C273C9D71E83138F003EF1AB /* MPAdBrowserController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C273C86B1E83138F003EF1AB /* MPAdBrowserController.xib */; }; + C273CA2C1E83138F003EF1AB /* libMoPubSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C273C91F1E83138F003EF1AB /* libMoPubSDK.a */; }; + C273CA661E83138F003EF1AB /* MPCloseBtn.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A41E83138F003EF1AB /* MPCloseBtn.png */; }; + C273CA671E83138F003EF1AB /* MPCloseBtn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A51E83138F003EF1AB /* MPCloseBtn@2x.png */; }; + C273CA681E83138F003EF1AB /* MPCloseBtn@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A61E83138F003EF1AB /* MPCloseBtn@3x.png */; }; + C273CA691E83138F003EF1AB /* MPCloseButtonX.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A71E83138F003EF1AB /* MPCloseButtonX.png */; }; + C273CA6A1E83138F003EF1AB /* MPCloseButtonX@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A81E83138F003EF1AB /* MPCloseButtonX@2x.png */; }; + C273CA6B1E83138F003EF1AB /* MPCloseButtonX@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9A91E83138F003EF1AB /* MPCloseButtonX@3x.png */; }; + C273CA6C1E83138F003EF1AB /* MPCountdownTimer.html in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AA1E83138F003EF1AB /* MPCountdownTimer.html */; }; + C273CA6D1E83138F003EF1AB /* MPDAAIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AB1E83138F003EF1AB /* MPDAAIcon.png */; }; + C273CA6E1E83138F003EF1AB /* MPDAAIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AC1E83138F003EF1AB /* MPDAAIcon@2x.png */; }; + C273CA6F1E83138F003EF1AB /* MPDAAIcon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AD1E83138F003EF1AB /* MPDAAIcon@3x.png */; }; + C273CA701E83138F003EF1AB /* MPMutedBtn.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AE1E83138F003EF1AB /* MPMutedBtn.png */; }; + C273CA711E83138F003EF1AB /* MPMutedBtn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9AF1E83138F003EF1AB /* MPMutedBtn@2x.png */; }; + C273CA721E83138F003EF1AB /* MPMutedBtn@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B01E83138F003EF1AB /* MPMutedBtn@3x.png */; }; + C273CA731E83138F003EF1AB /* MPPlayBtn.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B11E83138F003EF1AB /* MPPlayBtn.png */; }; + C273CA741E83138F003EF1AB /* MPPlayBtn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B21E83138F003EF1AB /* MPPlayBtn@2x.png */; }; + C273CA751E83138F003EF1AB /* MPPlayBtn@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B31E83138F003EF1AB /* MPPlayBtn@3x.png */; }; + C273CA761E83138F003EF1AB /* MPUnmutedBtn.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B41E83138F003EF1AB /* MPUnmutedBtn.png */; }; + C273CA771E83138F003EF1AB /* MPUnmutedBtn@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B51E83138F003EF1AB /* MPUnmutedBtn@2x.png */; }; + C273CA781E83138F003EF1AB /* MPUnmutedBtn@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B61E83138F003EF1AB /* MPUnmutedBtn@3x.png */; }; + C273CA791E83138F003EF1AB /* MRAID.bundle in Resources */ = {isa = PBXBuildFile; fileRef = C273C9B71E83138F003EF1AB /* MRAID.bundle */; }; + C273CA841E8313D7003EF1AB /* GoogleMobileAds.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA831E8313D7003EF1AB /* GoogleMobileAds.framework */; }; + C273CA861E8313F3003EF1AB /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA851E8313F3003EF1AB /* CoreBluetooth.framework */; }; + C273CA8D1E831404003EF1AB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA871E831404003EF1AB /* CoreFoundation.framework */; }; + C273CA8E1E831404003EF1AB /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA881E831404003EF1AB /* CoreGraphics.framework */; }; + C273CA8F1E831404003EF1AB /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA891E831404003EF1AB /* CoreImage.framework */; }; + C273CA901E831404003EF1AB /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA8A1E831404003EF1AB /* CoreLocation.framework */; }; + C273CA911E831404003EF1AB /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA8B1E831404003EF1AB /* CoreMedia.framework */; }; + C273CA921E831404003EF1AB /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA8C1E831404003EF1AB /* CoreTelephony.framework */; }; + C273CAA01E831442003EF1AB /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA931E831442003EF1AB /* AdSupport.framework */; }; + C273CAA11E831442003EF1AB /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA941E831442003EF1AB /* AudioToolbox.framework */; }; + C273CAA21E831442003EF1AB /* EventKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA951E831442003EF1AB /* EventKit.framework */; }; + C273CAA31E831442003EF1AB /* EventKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA961E831442003EF1AB /* EventKitUI.framework */; }; + C273CAA41E831442003EF1AB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA971E831442003EF1AB /* Foundation.framework */; }; + C273CAA51E831442003EF1AB /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA981E831442003EF1AB /* MediaPlayer.framework */; }; + C273CAA61E831442003EF1AB /* MediaToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA991E831442003EF1AB /* MediaToolbox.framework */; }; + C273CAA71E831442003EF1AB /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9A1E831442003EF1AB /* MessageUI.framework */; }; + C273CAA81E831442003EF1AB /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9B1E831442003EF1AB /* QuartzCore.framework */; }; + C273CAA91E831442003EF1AB /* SafariServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9C1E831442003EF1AB /* SafariServices.framework */; }; + C273CAAA1E831442003EF1AB /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9D1E831442003EF1AB /* StoreKit.framework */; }; + C273CAAB1E831442003EF1AB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9E1E831442003EF1AB /* SystemConfiguration.framework */; }; + C273CAAC1E831442003EF1AB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CA9F1E831442003EF1AB /* UIKit.framework */; }; + C273CAAE1E83146F003EF1AB /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CAAD1E83146F003EF1AB /* CoreMotion.framework */; }; + C273CAB01E831487003EF1AB /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CAAF1E831486003EF1AB /* GLKit.framework */; }; + C273CAB21E83149D003EF1AB /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C273CAB11E83149D003EF1AB /* MobileCoreServices.framework */; }; + C273CAB61E83175A003EF1AB /* BannerTestsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C273CAB51E83175A003EF1AB /* BannerTestsViewController.m */; }; + C273CABC1E832451003EF1AB /* InterstitialTestsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C273CABB1E832451003EF1AB /* InterstitialTestsViewController.m */; }; + C273CABF1E832479003EF1AB /* NativeTestsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C273CABE1E832479003EF1AB /* NativeTestsViewController.m */; }; + C273CAC21E832494003EF1AB /* VideoTestsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C273CAC11E832494003EF1AB /* VideoTestsViewController.m */; }; + C2E809731E95425D00DC7732 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E809721E95425D00DC7732 /* SettingsViewController.m */; }; + C2E8097D1E95899800DC7732 /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = C2E8097C1E95899800DC7732 /* Constants.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + C23386C91EE5DAA7002FD404 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C23386C51EE5DAA7002FD404 /* PrebidMobile.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C2B16E1B1EE1BE69006304C0; + remoteInfo = PrebidMobile; + }; + C23386CD1EE5DAC9002FD404 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C23386C51EE5DAA7002FD404 /* PrebidMobile.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C2B16E1A1EE1BE69006304C0; + remoteInfo = PrebidMobile; + }; + C273C81F1E82DAAE003EF1AB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C273C7FD1E82DAAD003EF1AB /* Project object */; + proxyType = 1; + remoteGlobalIDString = C273C8041E82DAAD003EF1AB; + remoteInfo = PrebidMobileDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + C23386CF1EE5DAC9002FD404 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + C23386CC1EE5DAC9002FD404 /* PrebidMobile.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + C23386C51EE5DAA7002FD404 /* PrebidMobile.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = PrebidMobile.xcodeproj; path = ../../sdk/PrebidMobile.xcodeproj; sourceTree = ""; }; + C268CA871EA65FD7008656F2 /* pbm_basic.feature */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = pbm_basic.feature; sourceTree = ""; }; + C268CA891EA65FD7008656F2 /* pbm_basic.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = pbm_basic.rb; sourceTree = ""; }; + C268CA8B1EA65FD7008656F2 /* 01_launch.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = 01_launch.rb; sourceTree = ""; }; + C268CA8C1EA65FD7008656F2 /* dry_run.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = dry_run.rb; sourceTree = ""; }; + C268CA8D1EA65FD7008656F2 /* env.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = env.rb; sourceTree = ""; }; + C268CA8F1EA65FD7008656F2 /* cucumber.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; path = cucumber.rb; sourceTree = ""; }; + C273C8051E82DAAD003EF1AB /* PrebidMobileDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PrebidMobileDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C273C8091E82DAAD003EF1AB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + C273C80B1E82DAAD003EF1AB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + C273C80C1E82DAAD003EF1AB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + C273C8121E82DAAE003EF1AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + C273C8141E82DAAE003EF1AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + C273C8171E82DAAE003EF1AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + C273C8191E82DAAE003EF1AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C273C81E1E82DAAE003EF1AB /* PrebidMobileDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrebidMobileDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + C273C8221E82DAAE003EF1AB /* PrebidMobileDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrebidMobileDemoTests.m; sourceTree = ""; }; + C273C8241E82DAAE003EF1AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C273C8571E83138F003EF1AB /* MPBannerAdManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBannerAdManager.h; sourceTree = ""; }; + C273C8581E83138F003EF1AB /* MPBannerAdManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPBannerAdManager.m; sourceTree = ""; }; + C273C8591E83138F003EF1AB /* MPBannerAdManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBannerAdManagerDelegate.h; sourceTree = ""; }; + C273C85A1E83138F003EF1AB /* MPBannerCustomEventAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBannerCustomEventAdapter.h; sourceTree = ""; }; + C273C85B1E83138F003EF1AB /* MPBannerCustomEventAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPBannerCustomEventAdapter.m; sourceTree = ""; }; + C273C85C1E83138F003EF1AB /* MPBaseBannerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBaseBannerAdapter.h; sourceTree = ""; }; + C273C85D1E83138F003EF1AB /* MPBaseBannerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPBaseBannerAdapter.m; sourceTree = ""; }; + C273C85E1E83138F003EF1AB /* MPPrivateBannerCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPrivateBannerCustomEventDelegate.h; sourceTree = ""; }; + C273C8611E83138F003EF1AB /* MPAdAlertGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdAlertGestureRecognizer.h; sourceTree = ""; }; + C273C8621E83138F003EF1AB /* MPAdAlertGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdAlertGestureRecognizer.m; sourceTree = ""; }; + C273C8631E83138F003EF1AB /* MPAdAlertManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdAlertManager.h; sourceTree = ""; }; + C273C8641E83138F003EF1AB /* MPAdAlertManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdAlertManager.m; sourceTree = ""; }; + C273C8651E83138F003EF1AB /* MPActivityViewControllerHelper+TweetShare.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPActivityViewControllerHelper+TweetShare.h"; sourceTree = ""; }; + C273C8661E83138F003EF1AB /* MPActivityViewControllerHelper+TweetShare.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPActivityViewControllerHelper+TweetShare.m"; sourceTree = ""; }; + C273C8671E83138F003EF1AB /* MPActivityViewControllerHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPActivityViewControllerHelper.h; sourceTree = ""; }; + C273C8681E83138F003EF1AB /* MPActivityViewControllerHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPActivityViewControllerHelper.m; sourceTree = ""; }; + C273C8691E83138F003EF1AB /* MPAdBrowserController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdBrowserController.h; sourceTree = ""; }; + C273C86A1E83138F003EF1AB /* MPAdBrowserController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdBrowserController.m; sourceTree = ""; }; + C273C86B1E83138F003EF1AB /* MPAdBrowserController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MPAdBrowserController.xib; sourceTree = ""; }; + C273C86C1E83138F003EF1AB /* MPAdConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdConfiguration.h; sourceTree = ""; }; + C273C86D1E83138F003EF1AB /* MPAdConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdConfiguration.m; sourceTree = ""; }; + C273C86E1E83138F003EF1AB /* MPAdDestinationDisplayAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdDestinationDisplayAgent.h; sourceTree = ""; }; + C273C86F1E83138F003EF1AB /* MPAdDestinationDisplayAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdDestinationDisplayAgent.m; sourceTree = ""; }; + C273C8701E83138F003EF1AB /* MPAdServerCommunicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdServerCommunicator.h; sourceTree = ""; }; + C273C8711E83138F003EF1AB /* MPAdServerCommunicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdServerCommunicator.m; sourceTree = ""; }; + C273C8721E83138F003EF1AB /* MPAdServerURLBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdServerURLBuilder.h; sourceTree = ""; }; + C273C8731E83138F003EF1AB /* MPAdServerURLBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdServerURLBuilder.m; sourceTree = ""; }; + C273C8741E83138F003EF1AB /* MPAPIEndpoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAPIEndpoints.h; sourceTree = ""; }; + C273C8751E83138F003EF1AB /* MPAPIEndpoints.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAPIEndpoints.m; sourceTree = ""; }; + C273C8761E83138F003EF1AB /* MPClosableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPClosableView.h; sourceTree = ""; }; + C273C8771E83138F003EF1AB /* MPClosableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPClosableView.m; sourceTree = ""; }; + C273C8781E83138F003EF1AB /* MPCountdownTimerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCountdownTimerView.h; sourceTree = ""; }; + C273C8791E83138F003EF1AB /* MPCountdownTimerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCountdownTimerView.m; sourceTree = ""; }; + C273C87A1E83138F003EF1AB /* MPEnhancedDeeplinkRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPEnhancedDeeplinkRequest.h; sourceTree = ""; }; + C273C87B1E83138F003EF1AB /* MPEnhancedDeeplinkRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPEnhancedDeeplinkRequest.m; sourceTree = ""; }; + C273C87C1E83138F003EF1AB /* MPFacebookKeywordProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFacebookKeywordProvider.h; sourceTree = ""; }; + C273C87D1E83138F003EF1AB /* MPFacebookKeywordProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFacebookKeywordProvider.m; sourceTree = ""; }; + C273C87E1E83138F003EF1AB /* MPKeywordProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPKeywordProvider.h; sourceTree = ""; }; + C273C87F1E83138F003EF1AB /* MPLastResortDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLastResortDelegate.h; sourceTree = ""; }; + C273C8801E83138F003EF1AB /* MPLastResortDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLastResortDelegate.m; sourceTree = ""; }; + C273C8811E83138F003EF1AB /* MPProgressOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPProgressOverlayView.h; sourceTree = ""; }; + C273C8821E83138F003EF1AB /* MPProgressOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPProgressOverlayView.m; sourceTree = ""; }; + C273C8831E83138F003EF1AB /* MPURLActionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPURLActionInfo.h; sourceTree = ""; }; + C273C8841E83138F003EF1AB /* MPURLActionInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPURLActionInfo.m; sourceTree = ""; }; + C273C8851E83138F003EF1AB /* MPURLResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPURLResolver.h; sourceTree = ""; }; + C273C8861E83138F003EF1AB /* MPURLResolver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPURLResolver.m; sourceTree = ""; }; + C273C8871E83138F003EF1AB /* MPVideoConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVideoConfig.h; sourceTree = ""; }; + C273C8881E83138F003EF1AB /* MPVideoConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVideoConfig.m; sourceTree = ""; }; + C273C8891E83138F003EF1AB /* MPXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPXMLParser.h; sourceTree = ""; }; + C273C88A1E83138F003EF1AB /* MPXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPXMLParser.m; sourceTree = ""; }; + C273C88C1E83138F003EF1AB /* MPLogEvent+NativeVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPLogEvent+NativeVideo.h"; sourceTree = ""; }; + C273C88D1E83138F003EF1AB /* MPLogEvent+NativeVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPLogEvent+NativeVideo.m"; sourceTree = ""; }; + C273C88E1E83138F003EF1AB /* MPLogEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogEvent.h; sourceTree = ""; }; + C273C88F1E83138F003EF1AB /* MPLogEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogEvent.m; sourceTree = ""; }; + C273C8901E83138F003EF1AB /* MPLogEventCommunicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogEventCommunicator.h; sourceTree = ""; }; + C273C8911E83138F003EF1AB /* MPLogEventCommunicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogEventCommunicator.m; sourceTree = ""; }; + C273C8921E83138F003EF1AB /* MPLogEventRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogEventRecorder.h; sourceTree = ""; }; + C273C8931E83138F003EF1AB /* MPLogEventRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogEventRecorder.m; sourceTree = ""; }; + C273C8941E83138F003EF1AB /* MPNetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNetworkManager.h; sourceTree = ""; }; + C273C8951E83138F003EF1AB /* MPNetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNetworkManager.m; sourceTree = ""; }; + C273C8961E83138F003EF1AB /* MPQRunLoopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPQRunLoopOperation.h; sourceTree = ""; }; + C273C8971E83138F003EF1AB /* MPQRunLoopOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPQRunLoopOperation.m; sourceTree = ""; }; + C273C8981E83138F003EF1AB /* MPRetryingHTTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRetryingHTTPOperation.h; sourceTree = ""; }; + C273C8991E83138F003EF1AB /* MPRetryingHTTPOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRetryingHTTPOperation.m; sourceTree = ""; }; + C273C89B1E83138F003EF1AB /* MPAdWebViewAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdWebViewAgent.h; sourceTree = ""; }; + C273C89C1E83138F003EF1AB /* MPAdWebViewAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdWebViewAgent.m; sourceTree = ""; }; + C273C89D1E83138F003EF1AB /* MPHTMLBannerCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPHTMLBannerCustomEvent.h; sourceTree = ""; }; + C273C89E1E83138F003EF1AB /* MPHTMLBannerCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPHTMLBannerCustomEvent.m; sourceTree = ""; }; + C273C89F1E83138F003EF1AB /* MPHTMLInterstitialCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPHTMLInterstitialCustomEvent.h; sourceTree = ""; }; + C273C8A01E83138F003EF1AB /* MPHTMLInterstitialCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPHTMLInterstitialCustomEvent.m; sourceTree = ""; }; + C273C8A11E83138F003EF1AB /* MPHTMLInterstitialViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPHTMLInterstitialViewController.h; sourceTree = ""; }; + C273C8A21E83138F003EF1AB /* MPHTMLInterstitialViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPHTMLInterstitialViewController.m; sourceTree = ""; }; + C273C8A31E83138F003EF1AB /* MPWebView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPWebView.h; sourceTree = ""; }; + C273C8A41E83138F003EF1AB /* MPWebView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPWebView.m; sourceTree = ""; }; + C273C8A61E83138F003EF1AB /* MPBaseInterstitialAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBaseInterstitialAdapter.h; sourceTree = ""; }; + C273C8A71E83138F003EF1AB /* MPBaseInterstitialAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPBaseInterstitialAdapter.m; sourceTree = ""; }; + C273C8A81E83138F003EF1AB /* MPInterstitialAdManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialAdManager.h; sourceTree = ""; }; + C273C8A91E83138F003EF1AB /* MPInterstitialAdManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInterstitialAdManager.m; sourceTree = ""; }; + C273C8AA1E83138F003EF1AB /* MPInterstitialAdManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialAdManagerDelegate.h; sourceTree = ""; }; + C273C8AB1E83138F003EF1AB /* MPInterstitialCustomEventAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialCustomEventAdapter.h; sourceTree = ""; }; + C273C8AC1E83138F003EF1AB /* MPInterstitialCustomEventAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInterstitialCustomEventAdapter.m; sourceTree = ""; }; + C273C8AD1E83138F003EF1AB /* MPInterstitialViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialViewController.h; sourceTree = ""; }; + C273C8AE1E83138F003EF1AB /* MPInterstitialViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInterstitialViewController.m; sourceTree = ""; }; + C273C8AF1E83138F003EF1AB /* MPPrivateInterstitialCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPrivateInterstitialCustomEventDelegate.h; sourceTree = ""; }; + C273C8B01E83138F003EF1AB /* MPCoreInstanceProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCoreInstanceProvider.h; sourceTree = ""; }; + C273C8B11E83138F003EF1AB /* MPCoreInstanceProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCoreInstanceProvider.m; sourceTree = ""; }; + C273C8B21E83138F003EF1AB /* MPInstanceProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInstanceProvider.h; sourceTree = ""; }; + C273C8B31E83138F003EF1AB /* MPInstanceProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInstanceProvider.m; sourceTree = ""; }; + C273C8B41E83138F003EF1AB /* MPVASTTracking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTTracking.h; sourceTree = ""; }; + C273C8B51E83138F003EF1AB /* MPVASTTracking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTTracking.m; sourceTree = ""; }; + C273C8B71E83138F003EF1AB /* MPForceableOrientationProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPForceableOrientationProtocol.h; sourceTree = ""; }; + C273C8B81E83138F003EF1AB /* MPMRAIDBannerCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMRAIDBannerCustomEvent.h; sourceTree = ""; }; + C273C8B91E83138F003EF1AB /* MPMRAIDBannerCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMRAIDBannerCustomEvent.m; sourceTree = ""; }; + C273C8BA1E83138F003EF1AB /* MPMRAIDInterstitialCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMRAIDInterstitialCustomEvent.h; sourceTree = ""; }; + C273C8BB1E83138F003EF1AB /* MPMRAIDInterstitialCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMRAIDInterstitialCustomEvent.m; sourceTree = ""; }; + C273C8BC1E83138F003EF1AB /* MPMRAIDInterstitialViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMRAIDInterstitialViewController.h; sourceTree = ""; }; + C273C8BD1E83138F003EF1AB /* MPMRAIDInterstitialViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMRAIDInterstitialViewController.m; sourceTree = ""; }; + C273C8BE1E83138F003EF1AB /* MRBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRBridge.h; sourceTree = ""; }; + C273C8BF1E83138F003EF1AB /* MRBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRBridge.m; sourceTree = ""; }; + C273C8C01E83138F003EF1AB /* MRBundleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRBundleManager.h; sourceTree = ""; }; + C273C8C11E83138F003EF1AB /* MRBundleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRBundleManager.m; sourceTree = ""; }; + C273C8C21E83138F003EF1AB /* MRCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRCommand.h; sourceTree = ""; }; + C273C8C31E83138F003EF1AB /* MRCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRCommand.m; sourceTree = ""; }; + C273C8C41E83138F003EF1AB /* MRConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRConstants.h; sourceTree = ""; }; + C273C8C51E83138F003EF1AB /* MRConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRConstants.m; sourceTree = ""; }; + C273C8C61E83138F003EF1AB /* MRController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRController.h; sourceTree = ""; }; + C273C8C71E83138F003EF1AB /* MRController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRController.m; sourceTree = ""; }; + C273C8C81E83138F003EF1AB /* MRError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRError.h; sourceTree = ""; }; + C273C8C91E83138F003EF1AB /* MRError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRError.m; sourceTree = ""; }; + C273C8CA1E83138F003EF1AB /* MRExpandModalViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRExpandModalViewController.h; sourceTree = ""; }; + C273C8CB1E83138F003EF1AB /* MRExpandModalViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRExpandModalViewController.m; sourceTree = ""; }; + C273C8CC1E83138F003EF1AB /* MRNativeCommandHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRNativeCommandHandler.h; sourceTree = ""; }; + C273C8CD1E83138F003EF1AB /* MRNativeCommandHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRNativeCommandHandler.m; sourceTree = ""; }; + C273C8CE1E83138F003EF1AB /* MRProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRProperty.h; sourceTree = ""; }; + C273C8CF1E83138F003EF1AB /* MRProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRProperty.m; sourceTree = ""; }; + C273C8D01E83138F003EF1AB /* MRVideoPlayerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MRVideoPlayerManager.h; sourceTree = ""; }; + C273C8D11E83138F003EF1AB /* MRVideoPlayerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MRVideoPlayerManager.m; sourceTree = ""; }; + C273C8D41E83138F003EF1AB /* NSBundle+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+MPAdditions.h"; sourceTree = ""; }; + C273C8D51E83138F003EF1AB /* NSBundle+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+MPAdditions.m"; sourceTree = ""; }; + C273C8D61E83138F003EF1AB /* NSHTTPURLResponse+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSHTTPURLResponse+MPAdditions.h"; sourceTree = ""; }; + C273C8D71E83138F003EF1AB /* NSHTTPURLResponse+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSHTTPURLResponse+MPAdditions.m"; sourceTree = ""; }; + C273C8D81E83138F003EF1AB /* NSJSONSerialization+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSJSONSerialization+MPAdditions.h"; sourceTree = ""; }; + C273C8D91E83138F003EF1AB /* NSJSONSerialization+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSJSONSerialization+MPAdditions.m"; sourceTree = ""; }; + C273C8DA1E83138F003EF1AB /* NSURL+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+MPAdditions.h"; sourceTree = ""; }; + C273C8DB1E83138F003EF1AB /* NSURL+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+MPAdditions.m"; sourceTree = ""; }; + C273C8DC1E83138F003EF1AB /* UIButton+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+MPAdditions.h"; sourceTree = ""; }; + C273C8DD1E83138F003EF1AB /* UIButton+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+MPAdditions.m"; sourceTree = ""; }; + C273C8DE1E83138F003EF1AB /* UIColor+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MPAdditions.h"; sourceTree = ""; }; + C273C8DF1E83138F003EF1AB /* UIColor+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+MPAdditions.m"; sourceTree = ""; }; + C273C8E01E83138F003EF1AB /* UIView+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+MPAdditions.h"; sourceTree = ""; }; + C273C8E11E83138F003EF1AB /* UIView+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+MPAdditions.m"; sourceTree = ""; }; + C273C8E21E83138F003EF1AB /* UIWebView+MPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIWebView+MPAdditions.h"; sourceTree = ""; }; + C273C8E31E83138F003EF1AB /* UIWebView+MPAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIWebView+MPAdditions.m"; sourceTree = ""; }; + C273C8E41E83138F003EF1AB /* MPAnalyticsTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAnalyticsTracker.h; sourceTree = ""; }; + C273C8E51E83138F003EF1AB /* MPAnalyticsTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAnalyticsTracker.m; sourceTree = ""; }; + C273C8E61E83138F003EF1AB /* MPError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPError.h; sourceTree = ""; }; + C273C8E71E83138F003EF1AB /* MPError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPError.m; sourceTree = ""; }; + C273C8E81E83138F003EF1AB /* MPGeolocationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGeolocationProvider.h; sourceTree = ""; }; + C273C8E91E83138F003EF1AB /* MPGeolocationProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGeolocationProvider.m; sourceTree = ""; }; + C273C8EA1E83138F003EF1AB /* MPGlobal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPGlobal.h; sourceTree = ""; }; + C273C8EB1E83138F003EF1AB /* MPGlobal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPGlobal.m; sourceTree = ""; }; + C273C8EC1E83138F003EF1AB /* MPIdentityProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPIdentityProvider.h; sourceTree = ""; }; + C273C8ED1E83138F003EF1AB /* MPIdentityProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPIdentityProvider.m; sourceTree = ""; }; + C273C8EE1E83138F003EF1AB /* MPInternalUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInternalUtils.h; sourceTree = ""; }; + C273C8EF1E83138F003EF1AB /* MPInternalUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInternalUtils.m; sourceTree = ""; }; + C273C8F01E83138F003EF1AB /* MPLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogging.h; sourceTree = ""; }; + C273C8F11E83138F003EF1AB /* MPLogging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogging.m; sourceTree = ""; }; + C273C8F21E83138F003EF1AB /* MPLogProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPLogProvider.h; sourceTree = ""; }; + C273C8F31E83138F003EF1AB /* MPLogProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLogProvider.m; sourceTree = ""; }; + C273C8F41E83138F003EF1AB /* MPReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPReachability.h; sourceTree = ""; }; + C273C8F51E83138F003EF1AB /* MPReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPReachability.m; sourceTree = ""; }; + C273C8F61E83138F003EF1AB /* MPSessionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSessionTracker.h; sourceTree = ""; }; + C273C8F71E83138F003EF1AB /* MPSessionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSessionTracker.m; sourceTree = ""; }; + C273C8F81E83138F003EF1AB /* MPStoreKitProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStoreKitProvider.h; sourceTree = ""; }; + C273C8F91E83138F003EF1AB /* MPStoreKitProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStoreKitProvider.m; sourceTree = ""; }; + C273C8FA1E83138F003EF1AB /* MPTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTimer.h; sourceTree = ""; }; + C273C8FB1E83138F003EF1AB /* MPTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTimer.m; sourceTree = ""; }; + C273C8FC1E83138F003EF1AB /* MPUserInteractionGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUserInteractionGestureRecognizer.h; sourceTree = ""; }; + C273C8FD1E83138F003EF1AB /* MPUserInteractionGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUserInteractionGestureRecognizer.m; sourceTree = ""; }; + C273C8FF1E83138F003EF1AB /* MPVASTAd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTAd.h; sourceTree = ""; }; + C273C9001E83138F003EF1AB /* MPVASTAd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTAd.m; sourceTree = ""; }; + C273C9011E83138F003EF1AB /* MPVASTCompanionAd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTCompanionAd.h; sourceTree = ""; }; + C273C9021E83138F003EF1AB /* MPVASTCompanionAd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTCompanionAd.m; sourceTree = ""; }; + C273C9031E83138F003EF1AB /* MPVASTCreative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTCreative.h; sourceTree = ""; }; + C273C9041E83138F003EF1AB /* MPVASTCreative.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTCreative.m; sourceTree = ""; }; + C273C9051E83138F003EF1AB /* MPVASTDurationOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTDurationOffset.h; sourceTree = ""; }; + C273C9061E83138F003EF1AB /* MPVASTDurationOffset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTDurationOffset.m; sourceTree = ""; }; + C273C9071E83138F003EF1AB /* MPVASTIndustryIcon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTIndustryIcon.h; sourceTree = ""; }; + C273C9081E83138F003EF1AB /* MPVASTIndustryIcon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTIndustryIcon.m; sourceTree = ""; }; + C273C9091E83138F003EF1AB /* MPVASTInline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTInline.h; sourceTree = ""; }; + C273C90A1E83138F003EF1AB /* MPVASTInline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTInline.m; sourceTree = ""; }; + C273C90B1E83138F003EF1AB /* MPVASTLinearAd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTLinearAd.h; sourceTree = ""; }; + C273C90C1E83138F003EF1AB /* MPVASTLinearAd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTLinearAd.m; sourceTree = ""; }; + C273C90D1E83138F003EF1AB /* MPVASTMacroProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTMacroProcessor.h; sourceTree = ""; }; + C273C90E1E83138F003EF1AB /* MPVASTMacroProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTMacroProcessor.m; sourceTree = ""; }; + C273C90F1E83138F003EF1AB /* MPVASTManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTManager.h; sourceTree = ""; }; + C273C9101E83138F003EF1AB /* MPVASTManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTManager.m; sourceTree = ""; }; + C273C9111E83138F003EF1AB /* MPVASTMediaFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTMediaFile.h; sourceTree = ""; }; + C273C9121E83138F003EF1AB /* MPVASTMediaFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTMediaFile.m; sourceTree = ""; }; + C273C9131E83138F003EF1AB /* MPVASTModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTModel.h; sourceTree = ""; }; + C273C9141E83138F003EF1AB /* MPVASTModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTModel.m; sourceTree = ""; }; + C273C9151E83138F003EF1AB /* MPVASTResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTResource.h; sourceTree = ""; }; + C273C9161E83138F003EF1AB /* MPVASTResource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTResource.m; sourceTree = ""; }; + C273C9171E83138F003EF1AB /* MPVASTResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTResponse.h; sourceTree = ""; }; + C273C9181E83138F003EF1AB /* MPVASTResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTResponse.m; sourceTree = ""; }; + C273C9191E83138F003EF1AB /* MPVASTStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTStringUtilities.h; sourceTree = ""; }; + C273C91A1E83138F003EF1AB /* MPVASTStringUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTStringUtilities.m; sourceTree = ""; }; + C273C91B1E83138F003EF1AB /* MPVASTTrackingEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTTrackingEvent.h; sourceTree = ""; }; + C273C91C1E83138F003EF1AB /* MPVASTTrackingEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTTrackingEvent.m; sourceTree = ""; }; + C273C91D1E83138F003EF1AB /* MPVASTWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPVASTWrapper.h; sourceTree = ""; }; + C273C91E1E83138F003EF1AB /* MPVASTWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPVASTWrapper.m; sourceTree = ""; }; + C273C91F1E83138F003EF1AB /* libMoPubSDK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libMoPubSDK.a; sourceTree = ""; }; + C273C9201E83138F003EF1AB /* MoPub-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MoPub-Bridging-Header.h"; sourceTree = ""; }; + C273C9211E83138F003EF1AB /* MoPub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoPub.h; sourceTree = ""; }; + C273C9221E83138F003EF1AB /* MoPub.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MoPub.m; sourceTree = ""; }; + C273C9231E83138F003EF1AB /* MPAdConversionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdConversionTracker.h; sourceTree = ""; }; + C273C9241E83138F003EF1AB /* MPAdConversionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdConversionTracker.m; sourceTree = ""; }; + C273C9251E83138F003EF1AB /* MPAdView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdView.h; sourceTree = ""; }; + C273C9261E83138F003EF1AB /* MPAdView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdView.m; sourceTree = ""; }; + C273C9271E83138F003EF1AB /* MPBannerCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBannerCustomEvent.h; sourceTree = ""; }; + C273C9281E83138F003EF1AB /* MPBannerCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPBannerCustomEvent.m; sourceTree = ""; }; + C273C9291E83138F003EF1AB /* MPBannerCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPBannerCustomEventDelegate.h; sourceTree = ""; }; + C273C92A1E83138F003EF1AB /* MPConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPConstants.h; sourceTree = ""; }; + C273C92B1E83138F003EF1AB /* MPConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPConstants.m; sourceTree = ""; }; + C273C92C1E83138F003EF1AB /* MPInterstitialAdController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialAdController.h; sourceTree = ""; }; + C273C92D1E83138F003EF1AB /* MPInterstitialAdController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInterstitialAdController.m; sourceTree = ""; }; + C273C92E1E83138F003EF1AB /* MPInterstitialCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialCustomEvent.h; sourceTree = ""; }; + C273C92F1E83138F003EF1AB /* MPInterstitialCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPInterstitialCustomEvent.m; sourceTree = ""; }; + C273C9301E83138F003EF1AB /* MPInterstitialCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPInterstitialCustomEventDelegate.h; sourceTree = ""; }; + C273C9341E83138F003EF1AB /* MPNativeAdRequest+MPNativeAdSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPNativeAdRequest+MPNativeAdSource.h"; sourceTree = ""; }; + C273C9351E83138F003EF1AB /* MPAdPlacerInvocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdPlacerInvocation.h; sourceTree = ""; }; + C273C9361E83138F003EF1AB /* MPAdPlacerInvocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdPlacerInvocation.m; sourceTree = ""; }; + C273C9371E83138F003EF1AB /* MPCollectionViewAdPlacerCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCollectionViewAdPlacerCell.h; sourceTree = ""; }; + C273C9381E83138F003EF1AB /* MPCollectionViewAdPlacerCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCollectionViewAdPlacerCell.m; sourceTree = ""; }; + C273C9391E83138F003EF1AB /* MPDiskLRUCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDiskLRUCache.h; sourceTree = ""; }; + C273C93A1E83138F003EF1AB /* MPDiskLRUCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPDiskLRUCache.m; sourceTree = ""; }; + C273C93B1E83138F003EF1AB /* MPImageDownloadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPImageDownloadQueue.h; sourceTree = ""; }; + C273C93C1E83138F003EF1AB /* MPImageDownloadQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPImageDownloadQueue.m; sourceTree = ""; }; + C273C93D1E83138F003EF1AB /* MPMoPubNativeAdAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMoPubNativeAdAdapter.h; sourceTree = ""; }; + C273C93E1E83138F003EF1AB /* MPMoPubNativeAdAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMoPubNativeAdAdapter.m; sourceTree = ""; }; + C273C93F1E83138F003EF1AB /* MPMoPubNativeCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMoPubNativeCustomEvent.h; sourceTree = ""; }; + C273C9401E83138F003EF1AB /* MPMoPubNativeCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMoPubNativeCustomEvent.m; sourceTree = ""; }; + C273C9411E83138F003EF1AB /* MPNativeAd+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPNativeAd+Internal.h"; sourceTree = ""; }; + C273C9421E83138F003EF1AB /* MPNativeAd+Internal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPNativeAd+Internal.m"; sourceTree = ""; }; + C273C9431E83138F003EF1AB /* MPNativeAdRendererConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRendererConstants.h; sourceTree = ""; }; + C273C9441E83138F003EF1AB /* MPNativeAdRendererImageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRendererImageHandler.h; sourceTree = ""; }; + C273C9451E83138F003EF1AB /* MPNativeAdRendererImageHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdRendererImageHandler.m; sourceTree = ""; }; + C273C9461E83138F003EF1AB /* MPNativeAdSourceQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdSourceQueue.h; sourceTree = ""; }; + C273C9471E83138F003EF1AB /* MPNativeAdSourceQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdSourceQueue.m; sourceTree = ""; }; + C273C9481E83138F003EF1AB /* MPNativeAdUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdUtils.h; sourceTree = ""; }; + C273C9491E83138F003EF1AB /* MPNativeAdUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdUtils.m; sourceTree = ""; }; + C273C94A1E83138F003EF1AB /* MPNativeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeCache.h; sourceTree = ""; }; + C273C94B1E83138F003EF1AB /* MPNativeCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeCache.m; sourceTree = ""; }; + C273C94C1E83138F003EF1AB /* MPNativePositionResponseDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativePositionResponseDeserializer.h; sourceTree = ""; }; + C273C94D1E83138F003EF1AB /* MPNativePositionResponseDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativePositionResponseDeserializer.m; sourceTree = ""; }; + C273C94E1E83138F003EF1AB /* MPNativePositionSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativePositionSource.h; sourceTree = ""; }; + C273C94F1E83138F003EF1AB /* MPNativePositionSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativePositionSource.m; sourceTree = ""; }; + C273C9501E83138F003EF1AB /* MPNativeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeView.h; sourceTree = ""; }; + C273C9511E83138F003EF1AB /* MPNativeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeView.m; sourceTree = ""; }; + C273C9521E83138F003EF1AB /* MPStaticNativeAdImpressionTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStaticNativeAdImpressionTimer.h; sourceTree = ""; }; + C273C9531E83138F003EF1AB /* MPStaticNativeAdImpressionTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStaticNativeAdImpressionTimer.m; sourceTree = ""; }; + C273C9541E83138F003EF1AB /* MPTableViewAdPlacerCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTableViewAdPlacerCell.h; sourceTree = ""; }; + C273C9551E83138F003EF1AB /* MPTableViewAdPlacerCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTableViewAdPlacerCell.m; sourceTree = ""; }; + C273C9561E83138F003EF1AB /* MPTableViewCellImpressionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTableViewCellImpressionTracker.h; sourceTree = ""; }; + C273C9571E83138F003EF1AB /* MPTableViewCellImpressionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTableViewCellImpressionTracker.m; sourceTree = ""; }; + C273C9581E83138F003EF1AB /* MPAdPositioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAdPositioning.h; sourceTree = ""; }; + C273C9591E83138F003EF1AB /* MPAdPositioning.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAdPositioning.m; sourceTree = ""; }; + C273C95A1E83138F003EF1AB /* MPClientAdPositioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPClientAdPositioning.h; sourceTree = ""; }; + C273C95B1E83138F003EF1AB /* MPClientAdPositioning.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPClientAdPositioning.m; sourceTree = ""; }; + C273C95C1E83138F003EF1AB /* MPCollectionViewAdPlacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPCollectionViewAdPlacer.h; sourceTree = ""; }; + C273C95D1E83138F003EF1AB /* MPCollectionViewAdPlacer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPCollectionViewAdPlacer.m; sourceTree = ""; }; + C273C95E1E83138F003EF1AB /* MPNativeAd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAd.h; sourceTree = ""; }; + C273C95F1E83138F003EF1AB /* MPNativeAd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAd.m; sourceTree = ""; }; + C273C9601E83138F003EF1AB /* MPNativeAdAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdAdapter.h; sourceTree = ""; }; + C273C9611E83138F003EF1AB /* MPNativeAdConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdConstants.h; sourceTree = ""; }; + C273C9621E83138F003EF1AB /* MPNativeAdConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdConstants.m; sourceTree = ""; }; + C273C9631E83138F003EF1AB /* MPNativeAdData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdData.h; sourceTree = ""; }; + C273C9641E83138F003EF1AB /* MPNativeAdData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdData.m; sourceTree = ""; }; + C273C9651E83138F003EF1AB /* MPNativeAdDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdDelegate.h; sourceTree = ""; }; + C273C9661E83138F003EF1AB /* MPNativeAdError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdError.h; sourceTree = ""; }; + C273C9671E83138F003EF1AB /* MPNativeAdError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdError.m; sourceTree = ""; }; + C273C9681E83138F003EF1AB /* MPNativeAdRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRenderer.h; sourceTree = ""; }; + C273C9691E83138F003EF1AB /* MPNativeAdRendererConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRendererConfiguration.h; sourceTree = ""; }; + C273C96A1E83138F003EF1AB /* MPNativeAdRendererConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdRendererConfiguration.m; sourceTree = ""; }; + C273C96B1E83138F003EF1AB /* MPNativeAdRendererSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRendererSettings.h; sourceTree = ""; }; + C273C96C1E83138F003EF1AB /* MPNativeAdRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRendering.h; sourceTree = ""; }; + C273C96D1E83138F003EF1AB /* MPNativeAdRenderingImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRenderingImageLoader.h; sourceTree = ""; }; + C273C96E1E83138F003EF1AB /* MPNativeAdRenderingImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdRenderingImageLoader.m; sourceTree = ""; }; + C273C96F1E83138F003EF1AB /* MPNativeAdRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRequest.h; sourceTree = ""; }; + C273C9701E83138F003EF1AB /* MPNativeAdRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdRequest.m; sourceTree = ""; }; + C273C9711E83138F003EF1AB /* MPNativeAdRequestTargeting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdRequestTargeting.h; sourceTree = ""; }; + C273C9721E83138F003EF1AB /* MPNativeAdRequestTargeting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdRequestTargeting.m; sourceTree = ""; }; + C273C9731E83138F003EF1AB /* MPNativeAdSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdSource.h; sourceTree = ""; }; + C273C9741E83138F003EF1AB /* MPNativeAdSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeAdSource.m; sourceTree = ""; }; + C273C9751E83138F003EF1AB /* MPNativeAdSourceDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeAdSourceDelegate.h; sourceTree = ""; }; + C273C9761E83138F003EF1AB /* MPNativeCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeCustomEvent.h; sourceTree = ""; }; + C273C9771E83138F003EF1AB /* MPNativeCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNativeCustomEvent.m; sourceTree = ""; }; + C273C9781E83138F003EF1AB /* MPNativeCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNativeCustomEventDelegate.h; sourceTree = ""; }; + C273C9791E83138F003EF1AB /* MPServerAdPositioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPServerAdPositioning.h; sourceTree = ""; }; + C273C97A1E83138F003EF1AB /* MPServerAdPositioning.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPServerAdPositioning.m; sourceTree = ""; }; + C273C97B1E83138F003EF1AB /* MPStaticNativeAdRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStaticNativeAdRenderer.h; sourceTree = ""; }; + C273C97C1E83138F003EF1AB /* MPStaticNativeAdRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStaticNativeAdRenderer.m; sourceTree = ""; }; + C273C97D1E83138F003EF1AB /* MPStaticNativeAdRendererSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStaticNativeAdRendererSettings.h; sourceTree = ""; }; + C273C97E1E83138F003EF1AB /* MPStaticNativeAdRendererSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStaticNativeAdRendererSettings.m; sourceTree = ""; }; + C273C97F1E83138F003EF1AB /* MPStreamAdPlacementData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStreamAdPlacementData.h; sourceTree = ""; }; + C273C9801E83138F003EF1AB /* MPStreamAdPlacementData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStreamAdPlacementData.m; sourceTree = ""; }; + C273C9811E83138F003EF1AB /* MPStreamAdPlacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPStreamAdPlacer.h; sourceTree = ""; }; + C273C9821E83138F003EF1AB /* MPStreamAdPlacer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPStreamAdPlacer.m; sourceTree = ""; }; + C273C9831E83138F003EF1AB /* MPTableViewAdPlacer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTableViewAdPlacer.h; sourceTree = ""; }; + C273C9841E83138F003EF1AB /* MPTableViewAdPlacer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTableViewAdPlacer.m; sourceTree = ""; }; + C273C9871E83138F003EF1AB /* MOPUBActivityIndicatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBActivityIndicatorView.h; sourceTree = ""; }; + C273C9881E83138F003EF1AB /* MOPUBActivityIndicatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBActivityIndicatorView.m; sourceTree = ""; }; + C273C9891E83138F003EF1AB /* MOPUBAVPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBAVPlayer.h; sourceTree = ""; }; + C273C98A1E83138F003EF1AB /* MOPUBAVPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBAVPlayer.m; sourceTree = ""; }; + C273C98B1E83138F003EF1AB /* MOPUBAVPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBAVPlayerView.h; sourceTree = ""; }; + C273C98C1E83138F003EF1AB /* MOPUBAVPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBAVPlayerView.m; sourceTree = ""; }; + C273C98D1E83138F003EF1AB /* MOPUBFullscreenPlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBFullscreenPlayerViewController.h; sourceTree = ""; }; + C273C98E1E83138F003EF1AB /* MOPUBFullscreenPlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBFullscreenPlayerViewController.m; sourceTree = ""; }; + C273C98F1E83138F003EF1AB /* MOPUBNativeVideoAdAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoAdAdapter.h; sourceTree = ""; }; + C273C9901E83138F003EF1AB /* MOPUBNativeVideoAdAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoAdAdapter.m; sourceTree = ""; }; + C273C9911E83138F003EF1AB /* MOPUBNativeVideoAdConfigValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoAdConfigValues.h; sourceTree = ""; }; + C273C9921E83138F003EF1AB /* MOPUBNativeVideoAdConfigValues.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoAdConfigValues.m; sourceTree = ""; }; + C273C9931E83138F003EF1AB /* MOPUBNativeVideoCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoCustomEvent.h; sourceTree = ""; }; + C273C9941E83138F003EF1AB /* MOPUBNativeVideoCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoCustomEvent.m; sourceTree = ""; }; + C273C9951E83138F003EF1AB /* MOPUBNativeVideoImpressionAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoImpressionAgent.h; sourceTree = ""; }; + C273C9961E83138F003EF1AB /* MOPUBNativeVideoImpressionAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoImpressionAgent.m; sourceTree = ""; }; + C273C9971E83138F003EF1AB /* MOPUBPlayerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBPlayerManager.h; sourceTree = ""; }; + C273C9981E83138F003EF1AB /* MOPUBPlayerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBPlayerManager.m; sourceTree = ""; }; + C273C9991E83138F003EF1AB /* MOPUBPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBPlayerView.h; sourceTree = ""; }; + C273C99A1E83138F003EF1AB /* MOPUBPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBPlayerView.m; sourceTree = ""; }; + C273C99B1E83138F003EF1AB /* MOPUBPlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBPlayerViewController.h; sourceTree = ""; }; + C273C99C1E83138F003EF1AB /* MOPUBPlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBPlayerViewController.m; sourceTree = ""; }; + C273C99D1E83138F003EF1AB /* MOPUBReplayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBReplayView.h; sourceTree = ""; }; + C273C99E1E83138F003EF1AB /* MOPUBReplayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBReplayView.m; sourceTree = ""; }; + C273C99F1E83138F003EF1AB /* MOPUBNativeVideoAdRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoAdRenderer.h; sourceTree = ""; }; + C273C9A01E83138F003EF1AB /* MOPUBNativeVideoAdRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoAdRenderer.m; sourceTree = ""; }; + C273C9A11E83138F003EF1AB /* MOPUBNativeVideoAdRendererSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPUBNativeVideoAdRendererSettings.h; sourceTree = ""; }; + C273C9A21E83138F003EF1AB /* MOPUBNativeVideoAdRendererSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPUBNativeVideoAdRendererSettings.m; sourceTree = ""; }; + C273C9A41E83138F003EF1AB /* MPCloseBtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPCloseBtn.png; sourceTree = ""; }; + C273C9A51E83138F003EF1AB /* MPCloseBtn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPCloseBtn@2x.png"; sourceTree = ""; }; + C273C9A61E83138F003EF1AB /* MPCloseBtn@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPCloseBtn@3x.png"; sourceTree = ""; }; + C273C9A71E83138F003EF1AB /* MPCloseButtonX.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPCloseButtonX.png; sourceTree = ""; }; + C273C9A81E83138F003EF1AB /* MPCloseButtonX@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPCloseButtonX@2x.png"; sourceTree = ""; }; + C273C9A91E83138F003EF1AB /* MPCloseButtonX@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPCloseButtonX@3x.png"; sourceTree = ""; }; + C273C9AA1E83138F003EF1AB /* MPCountdownTimer.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = MPCountdownTimer.html; sourceTree = ""; }; + C273C9AB1E83138F003EF1AB /* MPDAAIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPDAAIcon.png; sourceTree = ""; }; + C273C9AC1E83138F003EF1AB /* MPDAAIcon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPDAAIcon@2x.png"; sourceTree = ""; }; + C273C9AD1E83138F003EF1AB /* MPDAAIcon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPDAAIcon@3x.png"; sourceTree = ""; }; + C273C9AE1E83138F003EF1AB /* MPMutedBtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPMutedBtn.png; sourceTree = ""; }; + C273C9AF1E83138F003EF1AB /* MPMutedBtn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPMutedBtn@2x.png"; sourceTree = ""; }; + C273C9B01E83138F003EF1AB /* MPMutedBtn@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPMutedBtn@3x.png"; sourceTree = ""; }; + C273C9B11E83138F003EF1AB /* MPPlayBtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPPlayBtn.png; sourceTree = ""; }; + C273C9B21E83138F003EF1AB /* MPPlayBtn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPPlayBtn@2x.png"; sourceTree = ""; }; + C273C9B31E83138F003EF1AB /* MPPlayBtn@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPPlayBtn@3x.png"; sourceTree = ""; }; + C273C9B41E83138F003EF1AB /* MPUnmutedBtn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MPUnmutedBtn.png; sourceTree = ""; }; + C273C9B51E83138F003EF1AB /* MPUnmutedBtn@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPUnmutedBtn@2x.png"; sourceTree = ""; }; + C273C9B61E83138F003EF1AB /* MPUnmutedBtn@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MPUnmutedBtn@3x.png"; sourceTree = ""; }; + C273C9B71E83138F003EF1AB /* MRAID.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MRAID.bundle; sourceTree = ""; }; + C273C9BA1E83138F003EF1AB /* MPMoPubRewardedPlayableCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMoPubRewardedPlayableCustomEvent.h; sourceTree = ""; }; + C273C9BB1E83138F003EF1AB /* MPMoPubRewardedPlayableCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMoPubRewardedPlayableCustomEvent.m; sourceTree = ""; }; + C273C9BC1E83138F003EF1AB /* MPMoPubRewardedVideoCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMoPubRewardedVideoCustomEvent.h; sourceTree = ""; }; + C273C9BD1E83138F003EF1AB /* MPMoPubRewardedVideoCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPMoPubRewardedVideoCustomEvent.m; sourceTree = ""; }; + C273C9BE1E83138F003EF1AB /* MPPrivateRewardedVideoCustomEventDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPrivateRewardedVideoCustomEventDelegate.h; sourceTree = ""; }; + C273C9BF1E83138F003EF1AB /* MPRewardedVideo+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPRewardedVideo+Internal.h"; sourceTree = ""; }; + C273C9C01E83138F003EF1AB /* MPRewardedVideoAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoAdapter.h; sourceTree = ""; }; + C273C9C11E83138F003EF1AB /* MPRewardedVideoAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoAdapter.m; sourceTree = ""; }; + C273C9C21E83138F003EF1AB /* MPRewardedVideoAdManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoAdManager.h; sourceTree = ""; }; + C273C9C31E83138F003EF1AB /* MPRewardedVideoAdManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoAdManager.m; sourceTree = ""; }; + C273C9C41E83138F003EF1AB /* MPRewardedVideoConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoConnection.h; sourceTree = ""; }; + C273C9C51E83138F003EF1AB /* MPRewardedVideoConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoConnection.m; sourceTree = ""; }; + C273C9C61E83138F003EF1AB /* MPMediationSettingsProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPMediationSettingsProtocol.h; sourceTree = ""; }; + C273C9C71E83138F003EF1AB /* MPRewardedVideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideo.h; sourceTree = ""; }; + C273C9C81E83138F003EF1AB /* MPRewardedVideo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideo.m; sourceTree = ""; }; + C273C9C91E83138F003EF1AB /* MPRewardedVideoCustomEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoCustomEvent.h; sourceTree = ""; }; + C273C9CA1E83138F003EF1AB /* MPRewardedVideoCustomEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoCustomEvent.m; sourceTree = ""; }; + C273C9CB1E83138F003EF1AB /* MPRewardedVideoError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoError.h; sourceTree = ""; }; + C273C9CC1E83138F003EF1AB /* MPRewardedVideoError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoError.m; sourceTree = ""; }; + C273C9CD1E83138F003EF1AB /* MPRewardedVideoReward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRewardedVideoReward.h; sourceTree = ""; }; + C273C9CE1E83138F003EF1AB /* MPRewardedVideoReward.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRewardedVideoReward.m; sourceTree = ""; }; + C273CA831E8313D7003EF1AB /* GoogleMobileAds.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = GoogleMobileAds.framework; sourceTree = ""; }; + C273CA851E8313F3003EF1AB /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; }; + C273CA871E831404003EF1AB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + C273CA881E831404003EF1AB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + C273CA891E831404003EF1AB /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; + C273CA8A1E831404003EF1AB /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + C273CA8B1E831404003EF1AB /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + C273CA8C1E831404003EF1AB /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; + C273CA931E831442003EF1AB /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; + C273CA941E831442003EF1AB /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + C273CA951E831442003EF1AB /* EventKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EventKit.framework; path = System/Library/Frameworks/EventKit.framework; sourceTree = SDKROOT; }; + C273CA961E831442003EF1AB /* EventKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EventKitUI.framework; path = System/Library/Frameworks/EventKitUI.framework; sourceTree = SDKROOT; }; + C273CA971E831442003EF1AB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + C273CA981E831442003EF1AB /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; + C273CA991E831442003EF1AB /* MediaToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaToolbox.framework; path = System/Library/Frameworks/MediaToolbox.framework; sourceTree = SDKROOT; }; + C273CA9A1E831442003EF1AB /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; + C273CA9B1E831442003EF1AB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + C273CA9C1E831442003EF1AB /* SafariServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SafariServices.framework; path = System/Library/Frameworks/SafariServices.framework; sourceTree = SDKROOT; }; + C273CA9D1E831442003EF1AB /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; + C273CA9E1E831442003EF1AB /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + C273CA9F1E831442003EF1AB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + C273CAAD1E83146F003EF1AB /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; + C273CAAF1E831486003EF1AB /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; + C273CAB11E83149D003EF1AB /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + C273CAB41E83175A003EF1AB /* BannerTestsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BannerTestsViewController.h; sourceTree = ""; }; + C273CAB51E83175A003EF1AB /* BannerTestsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BannerTestsViewController.m; sourceTree = ""; }; + C273CABA1E832451003EF1AB /* InterstitialTestsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterstitialTestsViewController.h; sourceTree = ""; }; + C273CABB1E832451003EF1AB /* InterstitialTestsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InterstitialTestsViewController.m; sourceTree = ""; }; + C273CABD1E832479003EF1AB /* NativeTestsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeTestsViewController.h; sourceTree = ""; }; + C273CABE1E832479003EF1AB /* NativeTestsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeTestsViewController.m; sourceTree = ""; }; + C273CAC01E832494003EF1AB /* VideoTestsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoTestsViewController.h; sourceTree = ""; }; + C273CAC11E832494003EF1AB /* VideoTestsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoTestsViewController.m; sourceTree = ""; }; + C2E809711E95425D00DC7732 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = ""; }; + C2E809721E95425D00DC7732 /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = ""; }; + C2E8097B1E95899800DC7732 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; + C2E8097C1E95899800DC7732 /* Constants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C273C8021E82DAAD003EF1AB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C273CAB21E83149D003EF1AB /* MobileCoreServices.framework in Frameworks */, + C273CAB01E831487003EF1AB /* GLKit.framework in Frameworks */, + C273CAAE1E83146F003EF1AB /* CoreMotion.framework in Frameworks */, + C273CAA01E831442003EF1AB /* AdSupport.framework in Frameworks */, + C273CAA11E831442003EF1AB /* AudioToolbox.framework in Frameworks */, + C273CAA21E831442003EF1AB /* EventKit.framework in Frameworks */, + C273CAA31E831442003EF1AB /* EventKitUI.framework in Frameworks */, + C273CAA41E831442003EF1AB /* Foundation.framework in Frameworks */, + C23386CB1EE5DAC9002FD404 /* PrebidMobile.framework in Frameworks */, + C273CAA51E831442003EF1AB /* MediaPlayer.framework in Frameworks */, + C273CAA61E831442003EF1AB /* MediaToolbox.framework in Frameworks */, + C273CAA71E831442003EF1AB /* MessageUI.framework in Frameworks */, + C273CAA81E831442003EF1AB /* QuartzCore.framework in Frameworks */, + C273CAA91E831442003EF1AB /* SafariServices.framework in Frameworks */, + C273CAAA1E831442003EF1AB /* StoreKit.framework in Frameworks */, + C273CAAB1E831442003EF1AB /* SystemConfiguration.framework in Frameworks */, + C273CAAC1E831442003EF1AB /* UIKit.framework in Frameworks */, + C273CA8D1E831404003EF1AB /* CoreFoundation.framework in Frameworks */, + C273CA8E1E831404003EF1AB /* CoreGraphics.framework in Frameworks */, + C273CA8F1E831404003EF1AB /* CoreImage.framework in Frameworks */, + C273CA901E831404003EF1AB /* CoreLocation.framework in Frameworks */, + C273CA911E831404003EF1AB /* CoreMedia.framework in Frameworks */, + C273CA921E831404003EF1AB /* CoreTelephony.framework in Frameworks */, + C273CA861E8313F3003EF1AB /* CoreBluetooth.framework in Frameworks */, + C273CA841E8313D7003EF1AB /* GoogleMobileAds.framework in Frameworks */, + C273CA2C1E83138F003EF1AB /* libMoPubSDK.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C273C81B1E82DAAE003EF1AB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + C23386C61EE5DAA7002FD404 /* Products */ = { + isa = PBXGroup; + children = ( + C23386CA1EE5DAA7002FD404 /* PrebidMobile.framework */, + ); + name = Products; + sourceTree = ""; + }; + C268CA861EA65FD7008656F2 /* features */ = { + isa = PBXGroup; + children = ( + C268CA881EA65FD7008656F2 /* steps */, + C268CA8A1EA65FD7008656F2 /* support */, + C268CA871EA65FD7008656F2 /* pbm_basic.feature */, + ); + path = features; + sourceTree = ""; + }; + C268CA881EA65FD7008656F2 /* steps */ = { + isa = PBXGroup; + children = ( + C268CA891EA65FD7008656F2 /* pbm_basic.rb */, + ); + path = steps; + sourceTree = ""; + }; + C268CA8A1EA65FD7008656F2 /* support */ = { + isa = PBXGroup; + children = ( + C268CA8E1EA65FD7008656F2 /* patches */, + C268CA8B1EA65FD7008656F2 /* 01_launch.rb */, + C268CA8C1EA65FD7008656F2 /* dry_run.rb */, + C268CA8D1EA65FD7008656F2 /* env.rb */, + ); + path = support; + sourceTree = ""; + }; + C268CA8E1EA65FD7008656F2 /* patches */ = { + isa = PBXGroup; + children = ( + C268CA8F1EA65FD7008656F2 /* cucumber.rb */, + ); + path = patches; + sourceTree = ""; + }; + C273C7FC1E82DAAD003EF1AB = { + isa = PBXGroup; + children = ( + C273C8071E82DAAD003EF1AB /* PrebidMobileDemo */, + C273C8211E82DAAE003EF1AB /* PrebidMobileDemoTests */, + C273C84F1E831300003EF1AB /* Frameworks */, + C273C8061E82DAAD003EF1AB /* Products */, + C268CA861EA65FD7008656F2 /* features */, + C23386C51EE5DAA7002FD404 /* PrebidMobile.xcodeproj */, + ); + sourceTree = ""; + }; + C273C8061E82DAAD003EF1AB /* Products */ = { + isa = PBXGroup; + children = ( + C273C8051E82DAAD003EF1AB /* PrebidMobileDemo.app */, + C273C81E1E82DAAE003EF1AB /* PrebidMobileDemoTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + C273C8071E82DAAD003EF1AB /* PrebidMobileDemo */ = { + isa = PBXGroup; + children = ( + C273CAB31E83168B003EF1AB /* BannerViewControllers */, + C273CAB71E83242B003EF1AB /* IntersitialViewControllers */, + C273CAB81E832435003EF1AB /* NativeViewControllers */, + C273C8081E82DAAD003EF1AB /* Supporting Files */, + C273CAB91E832440003EF1AB /* VideoViewControllers */, + C273C80B1E82DAAD003EF1AB /* AppDelegate.h */, + C273C80C1E82DAAD003EF1AB /* AppDelegate.m */, + C273C8141E82DAAE003EF1AB /* Assets.xcassets */, + C2E8097B1E95899800DC7732 /* Constants.h */, + C2E8097C1E95899800DC7732 /* Constants.m */, + C273C8191E82DAAE003EF1AB /* Info.plist */, + C273C8161E82DAAE003EF1AB /* LaunchScreen.storyboard */, + C273C8111E82DAAE003EF1AB /* Main.storyboard */, + C2E809711E95425D00DC7732 /* SettingsViewController.h */, + C2E809721E95425D00DC7732 /* SettingsViewController.m */, + ); + path = PrebidMobileDemo; + sourceTree = ""; + }; + C273C8081E82DAAD003EF1AB /* Supporting Files */ = { + isa = PBXGroup; + children = ( + C273C8091E82DAAD003EF1AB /* main.m */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + C273C8211E82DAAE003EF1AB /* PrebidMobileDemoTests */ = { + isa = PBXGroup; + children = ( + C273C8241E82DAAE003EF1AB /* Info.plist */, + C273C8221E82DAAE003EF1AB /* PrebidMobileDemoTests.m */, + ); + path = PrebidMobileDemoTests; + sourceTree = ""; + }; + C273C84F1E831300003EF1AB /* Frameworks */ = { + isa = PBXGroup; + children = ( + C273CAB11E83149D003EF1AB /* MobileCoreServices.framework */, + C273CAAF1E831486003EF1AB /* GLKit.framework */, + C273CAAD1E83146F003EF1AB /* CoreMotion.framework */, + C273CA931E831442003EF1AB /* AdSupport.framework */, + C273CA941E831442003EF1AB /* AudioToolbox.framework */, + C273CA951E831442003EF1AB /* EventKit.framework */, + C273CA961E831442003EF1AB /* EventKitUI.framework */, + C273CA971E831442003EF1AB /* Foundation.framework */, + C273CA981E831442003EF1AB /* MediaPlayer.framework */, + C273CA991E831442003EF1AB /* MediaToolbox.framework */, + C273CA9A1E831442003EF1AB /* MessageUI.framework */, + C273CA9B1E831442003EF1AB /* QuartzCore.framework */, + C273CA9C1E831442003EF1AB /* SafariServices.framework */, + C273CA9D1E831442003EF1AB /* StoreKit.framework */, + C273CA9E1E831442003EF1AB /* SystemConfiguration.framework */, + C273CA9F1E831442003EF1AB /* UIKit.framework */, + C273CA871E831404003EF1AB /* CoreFoundation.framework */, + C273CA881E831404003EF1AB /* CoreGraphics.framework */, + C273CA891E831404003EF1AB /* CoreImage.framework */, + C273CA8A1E831404003EF1AB /* CoreLocation.framework */, + C273CA8B1E831404003EF1AB /* CoreMedia.framework */, + C273CA8C1E831404003EF1AB /* CoreTelephony.framework */, + C273CA851E8313F3003EF1AB /* CoreBluetooth.framework */, + C273CA831E8313D7003EF1AB /* GoogleMobileAds.framework */, + C273C8541E83138F003EF1AB /* MoPubSDK */, + ); + name = Frameworks; + sourceTree = ""; + }; + C273C8541E83138F003EF1AB /* MoPubSDK */ = { + isa = PBXGroup; + children = ( + C273C8551E83138F003EF1AB /* Internal */, + C273C91F1E83138F003EF1AB /* libMoPubSDK.a */, + C273C9201E83138F003EF1AB /* MoPub-Bridging-Header.h */, + C273C9211E83138F003EF1AB /* MoPub.h */, + C273C9221E83138F003EF1AB /* MoPub.m */, + C273C9231E83138F003EF1AB /* MPAdConversionTracker.h */, + C273C9241E83138F003EF1AB /* MPAdConversionTracker.m */, + C273C9251E83138F003EF1AB /* MPAdView.h */, + C273C9261E83138F003EF1AB /* MPAdView.m */, + C273C9271E83138F003EF1AB /* MPBannerCustomEvent.h */, + C273C9281E83138F003EF1AB /* MPBannerCustomEvent.m */, + C273C9291E83138F003EF1AB /* MPBannerCustomEventDelegate.h */, + C273C92A1E83138F003EF1AB /* MPConstants.h */, + C273C92B1E83138F003EF1AB /* MPConstants.m */, + C273C92C1E83138F003EF1AB /* MPInterstitialAdController.h */, + C273C92D1E83138F003EF1AB /* MPInterstitialAdController.m */, + C273C92E1E83138F003EF1AB /* MPInterstitialCustomEvent.h */, + C273C92F1E83138F003EF1AB /* MPInterstitialCustomEvent.m */, + C273C9301E83138F003EF1AB /* MPInterstitialCustomEventDelegate.h */, + C273C9311E83138F003EF1AB /* Native Ads */, + C273C9851E83138F003EF1AB /* NativeVideo */, + C273C9A31E83138F003EF1AB /* Resources */, + C273C9B81E83138F003EF1AB /* RewardedVideo */, + ); + path = MoPubSDK; + sourceTree = ""; + }; + C273C8551E83138F003EF1AB /* Internal */ = { + isa = PBXGroup; + children = ( + C273C8561E83138F003EF1AB /* Banners */, + C273C85F1E83138F003EF1AB /* Common */, + C273C88B1E83138F003EF1AB /* Event Logging */, + C273C89A1E83138F003EF1AB /* HTML */, + C273C8A51E83138F003EF1AB /* Interstitials */, + C273C8B01E83138F003EF1AB /* MPCoreInstanceProvider.h */, + C273C8B11E83138F003EF1AB /* MPCoreInstanceProvider.m */, + C273C8B21E83138F003EF1AB /* MPInstanceProvider.h */, + C273C8B31E83138F003EF1AB /* MPInstanceProvider.m */, + C273C8B41E83138F003EF1AB /* MPVASTTracking.h */, + C273C8B51E83138F003EF1AB /* MPVASTTracking.m */, + C273C8B61E83138F003EF1AB /* MRAID */, + C273C8D21E83138F003EF1AB /* Utility */, + C273C8FE1E83138F003EF1AB /* VAST */, + ); + path = Internal; + sourceTree = ""; + }; + C273C8561E83138F003EF1AB /* Banners */ = { + isa = PBXGroup; + children = ( + C273C8571E83138F003EF1AB /* MPBannerAdManager.h */, + C273C8581E83138F003EF1AB /* MPBannerAdManager.m */, + C273C8591E83138F003EF1AB /* MPBannerAdManagerDelegate.h */, + C273C85A1E83138F003EF1AB /* MPBannerCustomEventAdapter.h */, + C273C85B1E83138F003EF1AB /* MPBannerCustomEventAdapter.m */, + C273C85C1E83138F003EF1AB /* MPBaseBannerAdapter.h */, + C273C85D1E83138F003EF1AB /* MPBaseBannerAdapter.m */, + C273C85E1E83138F003EF1AB /* MPPrivateBannerCustomEventDelegate.h */, + ); + path = Banners; + sourceTree = ""; + }; + C273C85F1E83138F003EF1AB /* Common */ = { + isa = PBXGroup; + children = ( + C273C8601E83138F003EF1AB /* AdAlerts */, + C273C8651E83138F003EF1AB /* MPActivityViewControllerHelper+TweetShare.h */, + C273C8661E83138F003EF1AB /* MPActivityViewControllerHelper+TweetShare.m */, + C273C8671E83138F003EF1AB /* MPActivityViewControllerHelper.h */, + C273C8681E83138F003EF1AB /* MPActivityViewControllerHelper.m */, + C273C8691E83138F003EF1AB /* MPAdBrowserController.h */, + C273C86A1E83138F003EF1AB /* MPAdBrowserController.m */, + C273C86B1E83138F003EF1AB /* MPAdBrowserController.xib */, + C273C86C1E83138F003EF1AB /* MPAdConfiguration.h */, + C273C86D1E83138F003EF1AB /* MPAdConfiguration.m */, + C273C86E1E83138F003EF1AB /* MPAdDestinationDisplayAgent.h */, + C273C86F1E83138F003EF1AB /* MPAdDestinationDisplayAgent.m */, + C273C8701E83138F003EF1AB /* MPAdServerCommunicator.h */, + C273C8711E83138F003EF1AB /* MPAdServerCommunicator.m */, + C273C8721E83138F003EF1AB /* MPAdServerURLBuilder.h */, + C273C8731E83138F003EF1AB /* MPAdServerURLBuilder.m */, + C273C8741E83138F003EF1AB /* MPAPIEndpoints.h */, + C273C8751E83138F003EF1AB /* MPAPIEndpoints.m */, + C273C8761E83138F003EF1AB /* MPClosableView.h */, + C273C8771E83138F003EF1AB /* MPClosableView.m */, + C273C8781E83138F003EF1AB /* MPCountdownTimerView.h */, + C273C8791E83138F003EF1AB /* MPCountdownTimerView.m */, + C273C87A1E83138F003EF1AB /* MPEnhancedDeeplinkRequest.h */, + C273C87B1E83138F003EF1AB /* MPEnhancedDeeplinkRequest.m */, + C273C87C1E83138F003EF1AB /* MPFacebookKeywordProvider.h */, + C273C87D1E83138F003EF1AB /* MPFacebookKeywordProvider.m */, + C273C87E1E83138F003EF1AB /* MPKeywordProvider.h */, + C273C87F1E83138F003EF1AB /* MPLastResortDelegate.h */, + C273C8801E83138F003EF1AB /* MPLastResortDelegate.m */, + C273C8811E83138F003EF1AB /* MPProgressOverlayView.h */, + C273C8821E83138F003EF1AB /* MPProgressOverlayView.m */, + C273C8831E83138F003EF1AB /* MPURLActionInfo.h */, + C273C8841E83138F003EF1AB /* MPURLActionInfo.m */, + C273C8851E83138F003EF1AB /* MPURLResolver.h */, + C273C8861E83138F003EF1AB /* MPURLResolver.m */, + C273C8871E83138F003EF1AB /* MPVideoConfig.h */, + C273C8881E83138F003EF1AB /* MPVideoConfig.m */, + C273C8891E83138F003EF1AB /* MPXMLParser.h */, + C273C88A1E83138F003EF1AB /* MPXMLParser.m */, + ); + path = Common; + sourceTree = ""; + }; + C273C8601E83138F003EF1AB /* AdAlerts */ = { + isa = PBXGroup; + children = ( + C273C8611E83138F003EF1AB /* MPAdAlertGestureRecognizer.h */, + C273C8621E83138F003EF1AB /* MPAdAlertGestureRecognizer.m */, + C273C8631E83138F003EF1AB /* MPAdAlertManager.h */, + C273C8641E83138F003EF1AB /* MPAdAlertManager.m */, + ); + path = AdAlerts; + sourceTree = ""; + }; + C273C88B1E83138F003EF1AB /* Event Logging */ = { + isa = PBXGroup; + children = ( + C273C88C1E83138F003EF1AB /* MPLogEvent+NativeVideo.h */, + C273C88D1E83138F003EF1AB /* MPLogEvent+NativeVideo.m */, + C273C88E1E83138F003EF1AB /* MPLogEvent.h */, + C273C88F1E83138F003EF1AB /* MPLogEvent.m */, + C273C8901E83138F003EF1AB /* MPLogEventCommunicator.h */, + C273C8911E83138F003EF1AB /* MPLogEventCommunicator.m */, + C273C8921E83138F003EF1AB /* MPLogEventRecorder.h */, + C273C8931E83138F003EF1AB /* MPLogEventRecorder.m */, + C273C8941E83138F003EF1AB /* MPNetworkManager.h */, + C273C8951E83138F003EF1AB /* MPNetworkManager.m */, + C273C8961E83138F003EF1AB /* MPQRunLoopOperation.h */, + C273C8971E83138F003EF1AB /* MPQRunLoopOperation.m */, + C273C8981E83138F003EF1AB /* MPRetryingHTTPOperation.h */, + C273C8991E83138F003EF1AB /* MPRetryingHTTPOperation.m */, + ); + path = "Event Logging"; + sourceTree = ""; + }; + C273C89A1E83138F003EF1AB /* HTML */ = { + isa = PBXGroup; + children = ( + C273C89B1E83138F003EF1AB /* MPAdWebViewAgent.h */, + C273C89C1E83138F003EF1AB /* MPAdWebViewAgent.m */, + C273C89D1E83138F003EF1AB /* MPHTMLBannerCustomEvent.h */, + C273C89E1E83138F003EF1AB /* MPHTMLBannerCustomEvent.m */, + C273C89F1E83138F003EF1AB /* MPHTMLInterstitialCustomEvent.h */, + C273C8A01E83138F003EF1AB /* MPHTMLInterstitialCustomEvent.m */, + C273C8A11E83138F003EF1AB /* MPHTMLInterstitialViewController.h */, + C273C8A21E83138F003EF1AB /* MPHTMLInterstitialViewController.m */, + C273C8A31E83138F003EF1AB /* MPWebView.h */, + C273C8A41E83138F003EF1AB /* MPWebView.m */, + ); + path = HTML; + sourceTree = ""; + }; + C273C8A51E83138F003EF1AB /* Interstitials */ = { + isa = PBXGroup; + children = ( + C273C8A61E83138F003EF1AB /* MPBaseInterstitialAdapter.h */, + C273C8A71E83138F003EF1AB /* MPBaseInterstitialAdapter.m */, + C273C8A81E83138F003EF1AB /* MPInterstitialAdManager.h */, + C273C8A91E83138F003EF1AB /* MPInterstitialAdManager.m */, + C273C8AA1E83138F003EF1AB /* MPInterstitialAdManagerDelegate.h */, + C273C8AB1E83138F003EF1AB /* MPInterstitialCustomEventAdapter.h */, + C273C8AC1E83138F003EF1AB /* MPInterstitialCustomEventAdapter.m */, + C273C8AD1E83138F003EF1AB /* MPInterstitialViewController.h */, + C273C8AE1E83138F003EF1AB /* MPInterstitialViewController.m */, + C273C8AF1E83138F003EF1AB /* MPPrivateInterstitialCustomEventDelegate.h */, + ); + path = Interstitials; + sourceTree = ""; + }; + C273C8B61E83138F003EF1AB /* MRAID */ = { + isa = PBXGroup; + children = ( + C273C8B71E83138F003EF1AB /* MPForceableOrientationProtocol.h */, + C273C8B81E83138F003EF1AB /* MPMRAIDBannerCustomEvent.h */, + C273C8B91E83138F003EF1AB /* MPMRAIDBannerCustomEvent.m */, + C273C8BA1E83138F003EF1AB /* MPMRAIDInterstitialCustomEvent.h */, + C273C8BB1E83138F003EF1AB /* MPMRAIDInterstitialCustomEvent.m */, + C273C8BC1E83138F003EF1AB /* MPMRAIDInterstitialViewController.h */, + C273C8BD1E83138F003EF1AB /* MPMRAIDInterstitialViewController.m */, + C273C8BE1E83138F003EF1AB /* MRBridge.h */, + C273C8BF1E83138F003EF1AB /* MRBridge.m */, + C273C8C01E83138F003EF1AB /* MRBundleManager.h */, + C273C8C11E83138F003EF1AB /* MRBundleManager.m */, + C273C8C21E83138F003EF1AB /* MRCommand.h */, + C273C8C31E83138F003EF1AB /* MRCommand.m */, + C273C8C41E83138F003EF1AB /* MRConstants.h */, + C273C8C51E83138F003EF1AB /* MRConstants.m */, + C273C8C61E83138F003EF1AB /* MRController.h */, + C273C8C71E83138F003EF1AB /* MRController.m */, + C273C8C81E83138F003EF1AB /* MRError.h */, + C273C8C91E83138F003EF1AB /* MRError.m */, + C273C8CA1E83138F003EF1AB /* MRExpandModalViewController.h */, + C273C8CB1E83138F003EF1AB /* MRExpandModalViewController.m */, + C273C8CC1E83138F003EF1AB /* MRNativeCommandHandler.h */, + C273C8CD1E83138F003EF1AB /* MRNativeCommandHandler.m */, + C273C8CE1E83138F003EF1AB /* MRProperty.h */, + C273C8CF1E83138F003EF1AB /* MRProperty.m */, + C273C8D01E83138F003EF1AB /* MRVideoPlayerManager.h */, + C273C8D11E83138F003EF1AB /* MRVideoPlayerManager.m */, + ); + path = MRAID; + sourceTree = ""; + }; + C273C8D21E83138F003EF1AB /* Utility */ = { + isa = PBXGroup; + children = ( + C273C8D31E83138F003EF1AB /* Categories */, + C273C8E41E83138F003EF1AB /* MPAnalyticsTracker.h */, + C273C8E51E83138F003EF1AB /* MPAnalyticsTracker.m */, + C273C8E61E83138F003EF1AB /* MPError.h */, + C273C8E71E83138F003EF1AB /* MPError.m */, + C273C8E81E83138F003EF1AB /* MPGeolocationProvider.h */, + C273C8E91E83138F003EF1AB /* MPGeolocationProvider.m */, + C273C8EA1E83138F003EF1AB /* MPGlobal.h */, + C273C8EB1E83138F003EF1AB /* MPGlobal.m */, + C273C8EC1E83138F003EF1AB /* MPIdentityProvider.h */, + C273C8ED1E83138F003EF1AB /* MPIdentityProvider.m */, + C273C8EE1E83138F003EF1AB /* MPInternalUtils.h */, + C273C8EF1E83138F003EF1AB /* MPInternalUtils.m */, + C273C8F01E83138F003EF1AB /* MPLogging.h */, + C273C8F11E83138F003EF1AB /* MPLogging.m */, + C273C8F21E83138F003EF1AB /* MPLogProvider.h */, + C273C8F31E83138F003EF1AB /* MPLogProvider.m */, + C273C8F41E83138F003EF1AB /* MPReachability.h */, + C273C8F51E83138F003EF1AB /* MPReachability.m */, + C273C8F61E83138F003EF1AB /* MPSessionTracker.h */, + C273C8F71E83138F003EF1AB /* MPSessionTracker.m */, + C273C8F81E83138F003EF1AB /* MPStoreKitProvider.h */, + C273C8F91E83138F003EF1AB /* MPStoreKitProvider.m */, + C273C8FA1E83138F003EF1AB /* MPTimer.h */, + C273C8FB1E83138F003EF1AB /* MPTimer.m */, + C273C8FC1E83138F003EF1AB /* MPUserInteractionGestureRecognizer.h */, + C273C8FD1E83138F003EF1AB /* MPUserInteractionGestureRecognizer.m */, + ); + path = Utility; + sourceTree = ""; + }; + C273C8D31E83138F003EF1AB /* Categories */ = { + isa = PBXGroup; + children = ( + C273C8D41E83138F003EF1AB /* NSBundle+MPAdditions.h */, + C273C8D51E83138F003EF1AB /* NSBundle+MPAdditions.m */, + C273C8D61E83138F003EF1AB /* NSHTTPURLResponse+MPAdditions.h */, + C273C8D71E83138F003EF1AB /* NSHTTPURLResponse+MPAdditions.m */, + C273C8D81E83138F003EF1AB /* NSJSONSerialization+MPAdditions.h */, + C273C8D91E83138F003EF1AB /* NSJSONSerialization+MPAdditions.m */, + C273C8DA1E83138F003EF1AB /* NSURL+MPAdditions.h */, + C273C8DB1E83138F003EF1AB /* NSURL+MPAdditions.m */, + C273C8DC1E83138F003EF1AB /* UIButton+MPAdditions.h */, + C273C8DD1E83138F003EF1AB /* UIButton+MPAdditions.m */, + C273C8DE1E83138F003EF1AB /* UIColor+MPAdditions.h */, + C273C8DF1E83138F003EF1AB /* UIColor+MPAdditions.m */, + C273C8E01E83138F003EF1AB /* UIView+MPAdditions.h */, + C273C8E11E83138F003EF1AB /* UIView+MPAdditions.m */, + C273C8E21E83138F003EF1AB /* UIWebView+MPAdditions.h */, + C273C8E31E83138F003EF1AB /* UIWebView+MPAdditions.m */, + ); + path = Categories; + sourceTree = ""; + }; + C273C8FE1E83138F003EF1AB /* VAST */ = { + isa = PBXGroup; + children = ( + C273C8FF1E83138F003EF1AB /* MPVASTAd.h */, + C273C9001E83138F003EF1AB /* MPVASTAd.m */, + C273C9011E83138F003EF1AB /* MPVASTCompanionAd.h */, + C273C9021E83138F003EF1AB /* MPVASTCompanionAd.m */, + C273C9031E83138F003EF1AB /* MPVASTCreative.h */, + C273C9041E83138F003EF1AB /* MPVASTCreative.m */, + C273C9051E83138F003EF1AB /* MPVASTDurationOffset.h */, + C273C9061E83138F003EF1AB /* MPVASTDurationOffset.m */, + C273C9071E83138F003EF1AB /* MPVASTIndustryIcon.h */, + C273C9081E83138F003EF1AB /* MPVASTIndustryIcon.m */, + C273C9091E83138F003EF1AB /* MPVASTInline.h */, + C273C90A1E83138F003EF1AB /* MPVASTInline.m */, + C273C90B1E83138F003EF1AB /* MPVASTLinearAd.h */, + C273C90C1E83138F003EF1AB /* MPVASTLinearAd.m */, + C273C90D1E83138F003EF1AB /* MPVASTMacroProcessor.h */, + C273C90E1E83138F003EF1AB /* MPVASTMacroProcessor.m */, + C273C90F1E83138F003EF1AB /* MPVASTManager.h */, + C273C9101E83138F003EF1AB /* MPVASTManager.m */, + C273C9111E83138F003EF1AB /* MPVASTMediaFile.h */, + C273C9121E83138F003EF1AB /* MPVASTMediaFile.m */, + C273C9131E83138F003EF1AB /* MPVASTModel.h */, + C273C9141E83138F003EF1AB /* MPVASTModel.m */, + C273C9151E83138F003EF1AB /* MPVASTResource.h */, + C273C9161E83138F003EF1AB /* MPVASTResource.m */, + C273C9171E83138F003EF1AB /* MPVASTResponse.h */, + C273C9181E83138F003EF1AB /* MPVASTResponse.m */, + C273C9191E83138F003EF1AB /* MPVASTStringUtilities.h */, + C273C91A1E83138F003EF1AB /* MPVASTStringUtilities.m */, + C273C91B1E83138F003EF1AB /* MPVASTTrackingEvent.h */, + C273C91C1E83138F003EF1AB /* MPVASTTrackingEvent.m */, + C273C91D1E83138F003EF1AB /* MPVASTWrapper.h */, + C273C91E1E83138F003EF1AB /* MPVASTWrapper.m */, + ); + path = VAST; + sourceTree = ""; + }; + C273C9311E83138F003EF1AB /* Native Ads */ = { + isa = PBXGroup; + children = ( + C273C9321E83138F003EF1AB /* Internal */, + C273C9581E83138F003EF1AB /* MPAdPositioning.h */, + C273C9591E83138F003EF1AB /* MPAdPositioning.m */, + C273C95A1E83138F003EF1AB /* MPClientAdPositioning.h */, + C273C95B1E83138F003EF1AB /* MPClientAdPositioning.m */, + C273C95C1E83138F003EF1AB /* MPCollectionViewAdPlacer.h */, + C273C95D1E83138F003EF1AB /* MPCollectionViewAdPlacer.m */, + C273C95E1E83138F003EF1AB /* MPNativeAd.h */, + C273C95F1E83138F003EF1AB /* MPNativeAd.m */, + C273C9601E83138F003EF1AB /* MPNativeAdAdapter.h */, + C273C9611E83138F003EF1AB /* MPNativeAdConstants.h */, + C273C9621E83138F003EF1AB /* MPNativeAdConstants.m */, + C273C9631E83138F003EF1AB /* MPNativeAdData.h */, + C273C9641E83138F003EF1AB /* MPNativeAdData.m */, + C273C9651E83138F003EF1AB /* MPNativeAdDelegate.h */, + C273C9661E83138F003EF1AB /* MPNativeAdError.h */, + C273C9671E83138F003EF1AB /* MPNativeAdError.m */, + C273C9681E83138F003EF1AB /* MPNativeAdRenderer.h */, + C273C9691E83138F003EF1AB /* MPNativeAdRendererConfiguration.h */, + C273C96A1E83138F003EF1AB /* MPNativeAdRendererConfiguration.m */, + C273C96B1E83138F003EF1AB /* MPNativeAdRendererSettings.h */, + C273C96C1E83138F003EF1AB /* MPNativeAdRendering.h */, + C273C96D1E83138F003EF1AB /* MPNativeAdRenderingImageLoader.h */, + C273C96E1E83138F003EF1AB /* MPNativeAdRenderingImageLoader.m */, + C273C96F1E83138F003EF1AB /* MPNativeAdRequest.h */, + C273C9701E83138F003EF1AB /* MPNativeAdRequest.m */, + C273C9711E83138F003EF1AB /* MPNativeAdRequestTargeting.h */, + C273C9721E83138F003EF1AB /* MPNativeAdRequestTargeting.m */, + C273C9731E83138F003EF1AB /* MPNativeAdSource.h */, + C273C9741E83138F003EF1AB /* MPNativeAdSource.m */, + C273C9751E83138F003EF1AB /* MPNativeAdSourceDelegate.h */, + C273C9761E83138F003EF1AB /* MPNativeCustomEvent.h */, + C273C9771E83138F003EF1AB /* MPNativeCustomEvent.m */, + C273C9781E83138F003EF1AB /* MPNativeCustomEventDelegate.h */, + C273C9791E83138F003EF1AB /* MPServerAdPositioning.h */, + C273C97A1E83138F003EF1AB /* MPServerAdPositioning.m */, + C273C97B1E83138F003EF1AB /* MPStaticNativeAdRenderer.h */, + C273C97C1E83138F003EF1AB /* MPStaticNativeAdRenderer.m */, + C273C97D1E83138F003EF1AB /* MPStaticNativeAdRendererSettings.h */, + C273C97E1E83138F003EF1AB /* MPStaticNativeAdRendererSettings.m */, + C273C97F1E83138F003EF1AB /* MPStreamAdPlacementData.h */, + C273C9801E83138F003EF1AB /* MPStreamAdPlacementData.m */, + C273C9811E83138F003EF1AB /* MPStreamAdPlacer.h */, + C273C9821E83138F003EF1AB /* MPStreamAdPlacer.m */, + C273C9831E83138F003EF1AB /* MPTableViewAdPlacer.h */, + C273C9841E83138F003EF1AB /* MPTableViewAdPlacer.m */, + ); + path = "Native Ads"; + sourceTree = ""; + }; + C273C9321E83138F003EF1AB /* Internal */ = { + isa = PBXGroup; + children = ( + C273C9331E83138F003EF1AB /* Categories */, + C273C9351E83138F003EF1AB /* MPAdPlacerInvocation.h */, + C273C9361E83138F003EF1AB /* MPAdPlacerInvocation.m */, + C273C9371E83138F003EF1AB /* MPCollectionViewAdPlacerCell.h */, + C273C9381E83138F003EF1AB /* MPCollectionViewAdPlacerCell.m */, + C273C9391E83138F003EF1AB /* MPDiskLRUCache.h */, + C273C93A1E83138F003EF1AB /* MPDiskLRUCache.m */, + C273C93B1E83138F003EF1AB /* MPImageDownloadQueue.h */, + C273C93C1E83138F003EF1AB /* MPImageDownloadQueue.m */, + C273C93D1E83138F003EF1AB /* MPMoPubNativeAdAdapter.h */, + C273C93E1E83138F003EF1AB /* MPMoPubNativeAdAdapter.m */, + C273C93F1E83138F003EF1AB /* MPMoPubNativeCustomEvent.h */, + C273C9401E83138F003EF1AB /* MPMoPubNativeCustomEvent.m */, + C273C9411E83138F003EF1AB /* MPNativeAd+Internal.h */, + C273C9421E83138F003EF1AB /* MPNativeAd+Internal.m */, + C273C9431E83138F003EF1AB /* MPNativeAdRendererConstants.h */, + C273C9441E83138F003EF1AB /* MPNativeAdRendererImageHandler.h */, + C273C9451E83138F003EF1AB /* MPNativeAdRendererImageHandler.m */, + C273C9461E83138F003EF1AB /* MPNativeAdSourceQueue.h */, + C273C9471E83138F003EF1AB /* MPNativeAdSourceQueue.m */, + C273C9481E83138F003EF1AB /* MPNativeAdUtils.h */, + C273C9491E83138F003EF1AB /* MPNativeAdUtils.m */, + C273C94A1E83138F003EF1AB /* MPNativeCache.h */, + C273C94B1E83138F003EF1AB /* MPNativeCache.m */, + C273C94C1E83138F003EF1AB /* MPNativePositionResponseDeserializer.h */, + C273C94D1E83138F003EF1AB /* MPNativePositionResponseDeserializer.m */, + C273C94E1E83138F003EF1AB /* MPNativePositionSource.h */, + C273C94F1E83138F003EF1AB /* MPNativePositionSource.m */, + C273C9501E83138F003EF1AB /* MPNativeView.h */, + C273C9511E83138F003EF1AB /* MPNativeView.m */, + C273C9521E83138F003EF1AB /* MPStaticNativeAdImpressionTimer.h */, + C273C9531E83138F003EF1AB /* MPStaticNativeAdImpressionTimer.m */, + C273C9541E83138F003EF1AB /* MPTableViewAdPlacerCell.h */, + C273C9551E83138F003EF1AB /* MPTableViewAdPlacerCell.m */, + C273C9561E83138F003EF1AB /* MPTableViewCellImpressionTracker.h */, + C273C9571E83138F003EF1AB /* MPTableViewCellImpressionTracker.m */, + ); + path = Internal; + sourceTree = ""; + }; + C273C9331E83138F003EF1AB /* Categories */ = { + isa = PBXGroup; + children = ( + C273C9341E83138F003EF1AB /* MPNativeAdRequest+MPNativeAdSource.h */, + ); + path = Categories; + sourceTree = ""; + }; + C273C9851E83138F003EF1AB /* NativeVideo */ = { + isa = PBXGroup; + children = ( + C273C9861E83138F003EF1AB /* Internal */, + C273C99F1E83138F003EF1AB /* MOPUBNativeVideoAdRenderer.h */, + C273C9A01E83138F003EF1AB /* MOPUBNativeVideoAdRenderer.m */, + C273C9A11E83138F003EF1AB /* MOPUBNativeVideoAdRendererSettings.h */, + C273C9A21E83138F003EF1AB /* MOPUBNativeVideoAdRendererSettings.m */, + ); + path = NativeVideo; + sourceTree = ""; + }; + C273C9861E83138F003EF1AB /* Internal */ = { + isa = PBXGroup; + children = ( + C273C9871E83138F003EF1AB /* MOPUBActivityIndicatorView.h */, + C273C9881E83138F003EF1AB /* MOPUBActivityIndicatorView.m */, + C273C9891E83138F003EF1AB /* MOPUBAVPlayer.h */, + C273C98A1E83138F003EF1AB /* MOPUBAVPlayer.m */, + C273C98B1E83138F003EF1AB /* MOPUBAVPlayerView.h */, + C273C98C1E83138F003EF1AB /* MOPUBAVPlayerView.m */, + C273C98D1E83138F003EF1AB /* MOPUBFullscreenPlayerViewController.h */, + C273C98E1E83138F003EF1AB /* MOPUBFullscreenPlayerViewController.m */, + C273C98F1E83138F003EF1AB /* MOPUBNativeVideoAdAdapter.h */, + C273C9901E83138F003EF1AB /* MOPUBNativeVideoAdAdapter.m */, + C273C9911E83138F003EF1AB /* MOPUBNativeVideoAdConfigValues.h */, + C273C9921E83138F003EF1AB /* MOPUBNativeVideoAdConfigValues.m */, + C273C9931E83138F003EF1AB /* MOPUBNativeVideoCustomEvent.h */, + C273C9941E83138F003EF1AB /* MOPUBNativeVideoCustomEvent.m */, + C273C9951E83138F003EF1AB /* MOPUBNativeVideoImpressionAgent.h */, + C273C9961E83138F003EF1AB /* MOPUBNativeVideoImpressionAgent.m */, + C273C9971E83138F003EF1AB /* MOPUBPlayerManager.h */, + C273C9981E83138F003EF1AB /* MOPUBPlayerManager.m */, + C273C9991E83138F003EF1AB /* MOPUBPlayerView.h */, + C273C99A1E83138F003EF1AB /* MOPUBPlayerView.m */, + C273C99B1E83138F003EF1AB /* MOPUBPlayerViewController.h */, + C273C99C1E83138F003EF1AB /* MOPUBPlayerViewController.m */, + C273C99D1E83138F003EF1AB /* MOPUBReplayView.h */, + C273C99E1E83138F003EF1AB /* MOPUBReplayView.m */, + ); + path = Internal; + sourceTree = ""; + }; + C273C9A31E83138F003EF1AB /* Resources */ = { + isa = PBXGroup; + children = ( + C273C9A41E83138F003EF1AB /* MPCloseBtn.png */, + C273C9A51E83138F003EF1AB /* MPCloseBtn@2x.png */, + C273C9A61E83138F003EF1AB /* MPCloseBtn@3x.png */, + C273C9A71E83138F003EF1AB /* MPCloseButtonX.png */, + C273C9A81E83138F003EF1AB /* MPCloseButtonX@2x.png */, + C273C9A91E83138F003EF1AB /* MPCloseButtonX@3x.png */, + C273C9AA1E83138F003EF1AB /* MPCountdownTimer.html */, + C273C9AB1E83138F003EF1AB /* MPDAAIcon.png */, + C273C9AC1E83138F003EF1AB /* MPDAAIcon@2x.png */, + C273C9AD1E83138F003EF1AB /* MPDAAIcon@3x.png */, + C273C9AE1E83138F003EF1AB /* MPMutedBtn.png */, + C273C9AF1E83138F003EF1AB /* MPMutedBtn@2x.png */, + C273C9B01E83138F003EF1AB /* MPMutedBtn@3x.png */, + C273C9B11E83138F003EF1AB /* MPPlayBtn.png */, + C273C9B21E83138F003EF1AB /* MPPlayBtn@2x.png */, + C273C9B31E83138F003EF1AB /* MPPlayBtn@3x.png */, + C273C9B41E83138F003EF1AB /* MPUnmutedBtn.png */, + C273C9B51E83138F003EF1AB /* MPUnmutedBtn@2x.png */, + C273C9B61E83138F003EF1AB /* MPUnmutedBtn@3x.png */, + C273C9B71E83138F003EF1AB /* MRAID.bundle */, + ); + path = Resources; + sourceTree = ""; + }; + C273C9B81E83138F003EF1AB /* RewardedVideo */ = { + isa = PBXGroup; + children = ( + C273C9B91E83138F003EF1AB /* Internal */, + C273C9C61E83138F003EF1AB /* MPMediationSettingsProtocol.h */, + C273C9C71E83138F003EF1AB /* MPRewardedVideo.h */, + C273C9C81E83138F003EF1AB /* MPRewardedVideo.m */, + C273C9C91E83138F003EF1AB /* MPRewardedVideoCustomEvent.h */, + C273C9CA1E83138F003EF1AB /* MPRewardedVideoCustomEvent.m */, + C273C9CB1E83138F003EF1AB /* MPRewardedVideoError.h */, + C273C9CC1E83138F003EF1AB /* MPRewardedVideoError.m */, + C273C9CD1E83138F003EF1AB /* MPRewardedVideoReward.h */, + C273C9CE1E83138F003EF1AB /* MPRewardedVideoReward.m */, + ); + path = RewardedVideo; + sourceTree = ""; + }; + C273C9B91E83138F003EF1AB /* Internal */ = { + isa = PBXGroup; + children = ( + C273C9BA1E83138F003EF1AB /* MPMoPubRewardedPlayableCustomEvent.h */, + C273C9BB1E83138F003EF1AB /* MPMoPubRewardedPlayableCustomEvent.m */, + C273C9BC1E83138F003EF1AB /* MPMoPubRewardedVideoCustomEvent.h */, + C273C9BD1E83138F003EF1AB /* MPMoPubRewardedVideoCustomEvent.m */, + C273C9BE1E83138F003EF1AB /* MPPrivateRewardedVideoCustomEventDelegate.h */, + C273C9BF1E83138F003EF1AB /* MPRewardedVideo+Internal.h */, + C273C9C01E83138F003EF1AB /* MPRewardedVideoAdapter.h */, + C273C9C11E83138F003EF1AB /* MPRewardedVideoAdapter.m */, + C273C9C21E83138F003EF1AB /* MPRewardedVideoAdManager.h */, + C273C9C31E83138F003EF1AB /* MPRewardedVideoAdManager.m */, + C273C9C41E83138F003EF1AB /* MPRewardedVideoConnection.h */, + C273C9C51E83138F003EF1AB /* MPRewardedVideoConnection.m */, + ); + path = Internal; + sourceTree = ""; + }; + C273CAB31E83168B003EF1AB /* BannerViewControllers */ = { + isa = PBXGroup; + children = ( + C273CAB41E83175A003EF1AB /* BannerTestsViewController.h */, + C273CAB51E83175A003EF1AB /* BannerTestsViewController.m */, + ); + path = BannerViewControllers; + sourceTree = ""; + }; + C273CAB71E83242B003EF1AB /* IntersitialViewControllers */ = { + isa = PBXGroup; + children = ( + C273CABA1E832451003EF1AB /* InterstitialTestsViewController.h */, + C273CABB1E832451003EF1AB /* InterstitialTestsViewController.m */, + ); + path = IntersitialViewControllers; + sourceTree = ""; + }; + C273CAB81E832435003EF1AB /* NativeViewControllers */ = { + isa = PBXGroup; + children = ( + C273CABD1E832479003EF1AB /* NativeTestsViewController.h */, + C273CABE1E832479003EF1AB /* NativeTestsViewController.m */, + ); + path = NativeViewControllers; + sourceTree = ""; + }; + C273CAB91E832440003EF1AB /* VideoViewControllers */ = { + isa = PBXGroup; + children = ( + C273CAC01E832494003EF1AB /* VideoTestsViewController.h */, + C273CAC11E832494003EF1AB /* VideoTestsViewController.m */, + ); + path = VideoViewControllers; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + C273C8041E82DAAD003EF1AB /* PrebidMobileDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = C273C8271E82DAAE003EF1AB /* Build configuration list for PBXNativeTarget "PrebidMobileDemo" */; + buildPhases = ( + C273C8011E82DAAD003EF1AB /* Sources */, + C273C8021E82DAAD003EF1AB /* Frameworks */, + C273C8031E82DAAD003EF1AB /* Resources */, + C23386CF1EE5DAC9002FD404 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + C23386CE1EE5DAC9002FD404 /* PBXTargetDependency */, + ); + name = PrebidMobileDemo; + productName = PrebidMobileDemo; + productReference = C273C8051E82DAAD003EF1AB /* PrebidMobileDemo.app */; + productType = "com.apple.product-type.application"; + }; + C273C81D1E82DAAE003EF1AB /* PrebidMobileDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = C273C82A1E82DAAE003EF1AB /* Build configuration list for PBXNativeTarget "PrebidMobileDemoTests" */; + buildPhases = ( + C273C81A1E82DAAE003EF1AB /* Sources */, + C273C81B1E82DAAE003EF1AB /* Frameworks */, + C273C81C1E82DAAE003EF1AB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C273C8201E82DAAE003EF1AB /* PBXTargetDependency */, + ); + name = PrebidMobileDemoTests; + productName = PrebidMobileDemoTests; + productReference = C273C81E1E82DAAE003EF1AB /* PrebidMobileDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C273C7FD1E82DAAD003EF1AB /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Nicole Hedley"; + TargetAttributes = { + C273C8041E82DAAD003EF1AB = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = HR94J6TSB3; + ProvisioningStyle = Automatic; + }; + C273C81D1E82DAAE003EF1AB = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = HR94J6TSB3; + ProvisioningStyle = Automatic; + TestTargetID = C273C8041E82DAAD003EF1AB; + }; + }; + }; + buildConfigurationList = C273C8001E82DAAD003EF1AB /* Build configuration list for PBXProject "PrebidMobileDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = C273C7FC1E82DAAD003EF1AB; + productRefGroup = C273C8061E82DAAD003EF1AB /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = C23386C61EE5DAA7002FD404 /* Products */; + ProjectRef = C23386C51EE5DAA7002FD404 /* PrebidMobile.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + C273C8041E82DAAD003EF1AB /* PrebidMobileDemo */, + C273C81D1E82DAAE003EF1AB /* PrebidMobileDemoTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + C23386CA1EE5DAA7002FD404 /* PrebidMobile.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = PrebidMobile.framework; + remoteRef = C23386C91EE5DAA7002FD404 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + C273C8031E82DAAD003EF1AB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C273CA6E1E83138F003EF1AB /* MPDAAIcon@2x.png in Resources */, + C273CA6D1E83138F003EF1AB /* MPDAAIcon.png in Resources */, + C273CA681E83138F003EF1AB /* MPCloseBtn@3x.png in Resources */, + C268CA961EA65FD7008656F2 /* cucumber.rb in Resources */, + C273CA741E83138F003EF1AB /* MPPlayBtn@2x.png in Resources */, + C273C9D71E83138F003EF1AB /* MPAdBrowserController.xib in Resources */, + C273CA751E83138F003EF1AB /* MPPlayBtn@3x.png in Resources */, + C273CA781E83138F003EF1AB /* MPUnmutedBtn@3x.png in Resources */, + C273CA6C1E83138F003EF1AB /* MPCountdownTimer.html in Resources */, + C273C8181E82DAAE003EF1AB /* LaunchScreen.storyboard in Resources */, + C273CA791E83138F003EF1AB /* MRAID.bundle in Resources */, + C273C8151E82DAAE003EF1AB /* Assets.xcassets in Resources */, + C273CA6A1E83138F003EF1AB /* MPCloseButtonX@2x.png in Resources */, + C268CA911EA65FD7008656F2 /* pbm_basic.feature in Resources */, + C273CA701E83138F003EF1AB /* MPMutedBtn.png in Resources */, + C273CA771E83138F003EF1AB /* MPUnmutedBtn@2x.png in Resources */, + C273CA731E83138F003EF1AB /* MPPlayBtn.png in Resources */, + C268CA951EA65FD7008656F2 /* env.rb in Resources */, + C273CA6F1E83138F003EF1AB /* MPDAAIcon@3x.png in Resources */, + C273CA691E83138F003EF1AB /* MPCloseButtonX.png in Resources */, + C273CA6B1E83138F003EF1AB /* MPCloseButtonX@3x.png in Resources */, + C273CA761E83138F003EF1AB /* MPUnmutedBtn.png in Resources */, + C273CA671E83138F003EF1AB /* MPCloseBtn@2x.png in Resources */, + C268CA931EA65FD7008656F2 /* 01_launch.rb in Resources */, + C273CA721E83138F003EF1AB /* MPMutedBtn@3x.png in Resources */, + C273C8131E82DAAE003EF1AB /* Main.storyboard in Resources */, + C268CA921EA65FD7008656F2 /* pbm_basic.rb in Resources */, + C273CA711E83138F003EF1AB /* MPMutedBtn@2x.png in Resources */, + C273CA661E83138F003EF1AB /* MPCloseBtn.png in Resources */, + C268CA941EA65FD7008656F2 /* dry_run.rb in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C273C81C1E82DAAE003EF1AB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C273C8011E82DAAD003EF1AB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C273CABC1E832451003EF1AB /* InterstitialTestsViewController.m in Sources */, + C273C80D1E82DAAD003EF1AB /* AppDelegate.m in Sources */, + C2E809731E95425D00DC7732 /* SettingsViewController.m in Sources */, + C273CABF1E832479003EF1AB /* NativeTestsViewController.m in Sources */, + C273CAB61E83175A003EF1AB /* BannerTestsViewController.m in Sources */, + C273C80A1E82DAAD003EF1AB /* main.m in Sources */, + C273CAC21E832494003EF1AB /* VideoTestsViewController.m in Sources */, + C2E8097D1E95899800DC7732 /* Constants.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C273C81A1E82DAAE003EF1AB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C273C8231E82DAAE003EF1AB /* PrebidMobileDemoTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + C23386CE1EE5DAC9002FD404 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PrebidMobile; + targetProxy = C23386CD1EE5DAC9002FD404 /* PBXContainerItemProxy */; + }; + C273C8201E82DAAE003EF1AB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C273C8041E82DAAD003EF1AB /* PrebidMobileDemo */; + targetProxy = C273C81F1E82DAAE003EF1AB /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + C273C8111E82DAAE003EF1AB /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + C273C8121E82DAAE003EF1AB /* Base */, + ); + name = Main.storyboard; + path = .; + sourceTree = ""; + }; + C273C8161E82DAAE003EF1AB /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + C273C8171E82DAAE003EF1AB /* Base */, + ); + name = LaunchScreen.storyboard; + path = .; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + C273C8251E82DAAE003EF1AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "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.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C273C8261E82DAAE003EF1AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + 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.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C273C8281E82DAAE003EF1AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = HR94J6TSB3; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../../sdk/**"; + INFOPLIST_FILE = PrebidMobileDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MoPubSDK", + "$(PROJECT_DIR)/../../sdk/**", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-force_load", + "\"$(SOURCE_ROOT)/calabash.framework/calabash\"", + "-framework", + CFNetwork, + ); + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + C273C8291E82DAAE003EF1AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = HR94J6TSB3; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../../sdk/**"; + INFOPLIST_FILE = PrebidMobileDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/MoPubSDK", + "$(PROJECT_DIR)/../../sdk/**", + ); + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + C273C82B1E82DAAE003EF1AB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = HR94J6TSB3; + INFOPLIST_FILE = PrebidMobileDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrebidMobileDemo.app/PrebidMobileDemo"; + }; + name = Debug; + }; + C273C82C1E82DAAE003EF1AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = HR94J6TSB3; + INFOPLIST_FILE = PrebidMobileDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PrebidMobileDemo.app/PrebidMobileDemo"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C273C8001E82DAAD003EF1AB /* Build configuration list for PBXProject "PrebidMobileDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C273C8251E82DAAE003EF1AB /* Debug */, + C273C8261E82DAAE003EF1AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C273C8271E82DAAE003EF1AB /* Build configuration list for PBXNativeTarget "PrebidMobileDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C273C8281E82DAAE003EF1AB /* Debug */, + C273C8291E82DAAE003EF1AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C273C82A1E82DAAE003EF1AB /* Build configuration list for PBXNativeTarget "PrebidMobileDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C273C82B1E82DAAE003EF1AB /* Debug */, + C273C82C1E82DAAE003EF1AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C273C7FD1E82DAAD003EF1AB /* Project object */; +} diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..9bab51df2 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/xcshareddata/xcschemes/PrebidMobileDemo.xcscheme b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/xcshareddata/xcschemes/PrebidMobileDemo.xcscheme new file mode 100644 index 000000000..e1f9cf922 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo.xcodeproj/xcshareddata/xcschemes/PrebidMobileDemo.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.h b/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.h new file mode 100644 index 000000000..0750fc56d --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.h @@ -0,0 +1,26 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import + +@interface AppDelegate : UIResponder + +@property(strong, nonatomic) UIWindow *window; + +@property (nonatomic, readwrite) CLLocationManager *locationManager; + +@end + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.m b/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.m new file mode 100644 index 000000000..c38a58c3a --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/AppDelegate.m @@ -0,0 +1,127 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "AppDelegate.h" + +#import +#import +#import +#import +#import +#import "Constants.h" +#import "SettingsViewController.h" + +@interface AppDelegate () + +@property (strong, nonatomic) UITabBarController *tabBarController; + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [self enablePrebidLogs]; + [self setupPrebidAndRegisterAdUnits]; + + SettingsViewController *settingsViewController = [[SettingsViewController alloc] init]; + settingsViewController.title = @"Ad Settings"; + UINavigationController *settingsNavController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + self.window.rootViewController = settingsNavController; + [self.window makeKeyAndVisible]; + + // Override point for customization after application launch. + return YES; +} + +- (void)enablePrebidLogs { + [PBLogManager setPBLogLevel:PBLogLevelAll]; +} + +- (BOOL)setupPrebidAndRegisterAdUnits { + @try { + // Prebid Mobile setup! + [self setupPrebidLocationManager]; + + PBBannerAdUnit *__nullable adUnit1 = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:kAdUnit1Id andConfigId:kAdUnit1ConfigId]; + PBInterstitialAdUnit *__nullable adUnit2 = [[PBInterstitialAdUnit alloc] initWithAdUnitIdentifier:kAdUnit2Id andConfigId:kAdUnit2ConfigId]; + [adUnit1 addSize:CGSizeMake(300, 250)]; + + [self setPrebidTargetingParams]; + + [PrebidMobile registerAdUnits:@[adUnit1, adUnit2] withAccountId:kAccountId]; + } @catch (PBException *ex) { + NSLog(@"%@",[ex reason]); + } @finally { + return YES; + } +} + +- (void)setupPrebidLocationManager { + self.locationManager = [[CLLocationManager alloc] init]; + self.locationManager.delegate = self; + self.locationManager.distanceFilter = kCLDistanceFilterNone; + self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; + // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. + if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { + [self.locationManager requestWhenInUseAuthorization]; + } + [self.locationManager startUpdatingLocation]; +} + +- (void)setPrebidTargetingParams { + [[PBTargetingParams sharedInstance] setAge:25]; + [[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderFemale]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"country" withValues:@[@"india", @"malaysia"]]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"race" withValues:@[@"asian", @"hispanic", @"asian"]]; +} + +// Location Manager Delegate Methods +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { + [[PBTargetingParams sharedInstance] setLocation:[locations lastObject]]; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/PrebidMobileDemo/PrebidMobileDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..1d060ed28 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.h b/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.h new file mode 100644 index 000000000..86b3d717c --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.h @@ -0,0 +1,22 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface BannerTestsViewController : UIViewController + +- (instancetype)initWithSettings:(NSDictionary *)settings; + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.m b/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.m new file mode 100644 index 000000000..5f62808f1 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/BannerViewControllers/BannerTestsViewController.m @@ -0,0 +1,99 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "BannerTestsViewController.h" +#import "Constants.h" +#import +#import "MPAdView.h" +#import "PrebidMobile/PrebidMobile.h" + +@interface BannerTestsViewController () + +@property (strong, nonatomic) MPAdView *mopubAdView; +@property (strong, nonatomic) DFPBannerView *dfpAdView; +@property (strong, nonatomic) UIView *adContainerView; +@property (strong, nonatomic) NSDictionary *settings; + +@end + +@implementation BannerTestsViewController + +- (instancetype)initWithSettings:(NSDictionary *)settings { + self = [super init]; + _settings = settings; + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + NSString *adServer = [self.settings objectForKey:kAdServer]; + self.title = [adServer stringByAppendingString:@" Banner"]; + + NSString *size = [self.settings objectForKey:kSize]; + NSArray *widthHeight = [size componentsSeparatedByString:@"x"]; + double width = [widthHeight[0] doubleValue]; + double height = [widthHeight[1] doubleValue]; + + _adContainerView = [[UIView alloc] initWithFrame:CGRectMake(([[UIScreen mainScreen] bounds].size.width - 320) / 2, 100, width, height)]; + [self.view addSubview:_adContainerView]; + + if ([adServer isEqualToString:kMoPubAdServer]) { + _mopubAdView = [[MPAdView alloc] initWithAdUnitId:kMoPubBannerAdUnitId + size:CGSizeMake(width, height)]; + [_adContainerView addSubview:_mopubAdView]; + + [PrebidMobile setBidKeywordsOnAdObject:self.mopubAdView withAdUnitId:kAdUnit1Id withTimeout:600 completionHandler:^{ + [self.mopubAdView loadAd]; + }]; + } else if ([adServer isEqualToString:kDFPAdServer]) { + _dfpAdView = [[DFPBannerView alloc] initWithAdSize:GADAdSizeFromCGSize(CGSizeMake(width, height))]; + _dfpAdView.adUnitID = kDFPBannerAdUnitId; + _dfpAdView.rootViewController = self; + _dfpAdView.delegate = self; + + [_adContainerView addSubview:_dfpAdView]; + + [PrebidMobile setBidKeywordsOnAdObject:_dfpAdView withAdUnitId:kAdUnit1Id withTimeout:600 completionHandler:^{ + [_dfpAdView loadRequest:[DFPRequest request]]; + }]; + } +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - GADBannerViewDelegate methods + +- (void)adViewDidReceiveAd:(DFPBannerView *)view { + NSLog(@"DFP: %@", NSStringFromSelector(_cmd)); +} + +- (void)adView:(DFPBannerView *)view didFailToReceiveAdWithError:(GADRequestError *)error { + NSLog(@"DFP: %@", NSStringFromSelector(_cmd)); +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/LaunchScreen.storyboard b/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/Main.storyboard b/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/Main.storyboard new file mode 100644 index 000000000..4529698c4 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.h b/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.h new file mode 100644 index 000000000..a0713b7ad --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.h @@ -0,0 +1,51 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface Constants : NSObject + +extern NSString *const kAdServer; +extern NSString *const kAdType; +extern NSString *const kPlacementId; +extern NSString *const kSize; + +extern NSString *const kDefaultPlacementId; +extern NSString *const kDefaultSize; + +extern NSString *const kBanner; +extern NSString *const kInterstitial; +extern NSString *const kNative; +extern NSString *const kVideo; + +#pragma mark - MoPub constants +extern NSString *const kMoPubAdServer; +extern NSString *const kMoPubBannerAdUnitId; +extern NSString *const kMoPubInterstitialAdUnitId; + +#pragma mark - DFP constants +extern NSString *const kDFPAdServer; +extern NSString *const kDFPBannerAdUnitId; +extern NSString *const kDFPInterstitialAdUnitId; + +#pragma mark - Prebid Mobile constants +extern NSString *const kAccountId; +extern NSString *const kAdUnit1ConfigId; +extern NSString *const kAdUnit2ConfigId; + +extern NSString *const kAdUnit1Id; +extern NSString *const kAdUnit2Id; + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.m b/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.m new file mode 100644 index 000000000..93bc78201 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Constants.m @@ -0,0 +1,52 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "Constants.h" + +@implementation Constants + +NSString *const kAdServer = @"Ad Server"; +NSString *const kAdType = @"Ad Type"; +NSString *const kPlacementId = @"Placement ID"; +NSString *const kSize = @"Size"; + +NSString *const kDefaultPlacementId = @"9373413"; +NSString *const kDefaultSize = @"300x250"; + +NSString *const kBanner = @"Banner"; +NSString *const kInterstitial = @"Interstitial"; +NSString *const kNative = @"Native"; +NSString *const kVideo = @"Video"; + +#pragma mark - MoPub constants +NSString *const kMoPubAdServer = @"MoPub"; +NSString *const kMoPubBannerAdUnitId = @"a9cb8ff85fef4b50b457e3b11119aabf"; +NSString *const kMoPubInterstitialAdUnitId = @"fc82df5c964945c79cceef4c5666e1e2"; + + +#pragma mark - DFP constants +NSString *const kDFPAdServer = @"DFP"; +NSString *const kDFPBannerAdUnitId = @"/19968336/PriceCheck_300x250"; +NSString *const kDFPInterstitialAdUnitId = @"/19968336/PriceCheck_Interstitial"; + +#pragma mark - Prebid Mobile constants +NSString *const kAccountId = @"aecd6ef7-b992-4e99-9bb8-65e2d984e1dd"; +NSString *const kAdUnit1ConfigId = @"afae26bf-300a-4914-91a7-fd703b2222e1"; +NSString *const kAdUnit2ConfigId = @"060edfb1-1da8-4e08-ab6b-34b8092ac097"; + +NSString *const kAdUnit1Id = @"HomeScreen"; +NSString *const kAdUnit2Id = @"NavScreen"; + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Info.plist b/examples/PrebidMobileDemo/PrebidMobileDemo/Info.plist new file mode 100644 index 000000000..627999ff2 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Info.plist @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.h b/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.h new file mode 100644 index 000000000..7b620ae89 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.h @@ -0,0 +1,22 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface InterstitialTestsViewController : UIViewController + +- (instancetype)initWithSettings:(NSDictionary *)settings; + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.m b/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.m new file mode 100644 index 000000000..82f538616 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/IntersitialViewControllers/InterstitialTestsViewController.m @@ -0,0 +1,101 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "Constants.h" +#import +#import "InterstitialTestsViewController.h" +#import "MPInterstitialAdController.h" +#import + +@interface InterstitialTestsViewController () + +@property (nonatomic, strong) MPInterstitialAdController *moPubInterstitial; +@property (nonatomic, strong) DFPInterstitial *dfpInterstitial; +@property (strong, nonatomic) NSDictionary *settings; + +@end + +@implementation InterstitialTestsViewController + +- (instancetype)initWithSettings:(NSDictionary *)settings { + self = [super init]; + _settings = settings; + return self; +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + NSString *adServer = [self.settings objectForKey:kAdServer]; + self.title = [adServer stringByAppendingString:@" Interstitial"]; + + if ([adServer isEqualToString:kMoPubAdServer]) { + _moPubInterstitial = [MPInterstitialAdController interstitialAdControllerForAdUnitId:kMoPubInterstitialAdUnitId]; + _moPubInterstitial.delegate = self; + [PrebidMobile setBidKeywordsOnAdObject:self.moPubInterstitial withAdUnitId:kAdUnit2Id withTimeout:600 completionHandler:^{ + [self.moPubInterstitial loadAd]; + }]; + } + else if ([adServer isEqualToString:kDFPAdServer]) { + self.dfpInterstitial = [[DFPInterstitial alloc] initWithAdUnitID:kDFPInterstitialAdUnitId]; + self.dfpInterstitial.delegate = self; + + [PrebidMobile setBidKeywordsOnAdObject:self.dfpInterstitial withAdUnitId:kAdUnit2Id withTimeout:600 completionHandler:^{ + [self.dfpInterstitial loadRequest:[DFPRequest request]]; + }]; + } + +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - MPInterstitialAdControllerDelegate + +- (void)interstitialDidLoadAd:(MPInterstitialAdController *)interstitial { + [self.moPubInterstitial showFromViewController:self]; +} + +- (void)interstitialDidFailToLoadAd:(MPInterstitialAdController *)interstitial { + +} + +- (void)interstitialDidExpire:(MPInterstitialAdController *)interstitial { + +} + +#pragma mark - GADInterstitialDelegate + +- (void)interstitialDidReceiveAd:(GADInterstitial *)ad { + if(self.dfpInterstitial.isReady){ + [self.dfpInterstitial presentFromRootViewController:self]; + }else { + NSLog(@"Ad wasn't ready"); + } +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.h b/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.h new file mode 100644 index 000000000..85fcaef18 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.h @@ -0,0 +1,20 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface NativeTestsViewController : UIViewController + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.m b/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.m new file mode 100644 index 000000000..4a23eaa7b --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/NativeViewControllers/NativeTestsViewController.m @@ -0,0 +1,44 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "NativeTestsViewController.h" + +@interface NativeTestsViewController () + +@end + +@implementation NativeTestsViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.h b/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.h new file mode 100644 index 000000000..2f3212606 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.h @@ -0,0 +1,20 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface SettingsViewController : UIViewController + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.m b/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.m new file mode 100644 index 000000000..8705fe5d5 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/SettingsViewController.m @@ -0,0 +1,153 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "BannerTestsViewController.h" +#import "Constants.h" +#import "InterstitialTestsViewController.h" +#import "SettingsViewController.h" +#import "VideoTestsViewController.h" + +static NSString *const kSeeAdButtonTitle = @"See Ad"; +static NSString *const kAdSettingsTableViewReuseId = @"AdSettingsTableItem"; +static CGFloat const kRightMargin = 15; + +@interface SettingsViewController () + +@property (strong, nonatomic) UITableView *settingsTableView; +@property (strong, nonatomic) NSArray *generalSettingsData; +@property (strong, nonatomic) NSArray *sectionHeaders; +@property (strong, nonatomic) NSMutableDictionary *generalSettingsFields; + +@end + +@implementation SettingsViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + _settingsTableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped]; + _settingsTableView.dataSource = self; + _settingsTableView.delegate = self; + [self.view addSubview:_settingsTableView]; + + _generalSettingsData = @[kAdServer, kAdType, kSize]; + [self initializeGeneralSettingsFields]; + + _sectionHeaders = @[@"General"];//, @"Targeting", @"Custom Keywords"]; + + UIBarButtonItem *previewAdButton = [[UIBarButtonItem alloc] initWithTitle:kSeeAdButtonTitle style:UIBarButtonItemStylePlain target:self action:@selector(previewAdButtonClicked:)]; + self.navigationItem.rightBarButtonItem = previewAdButton; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)initializeGeneralSettingsFields { + _generalSettingsFields = [[NSMutableDictionary alloc] init]; + + UISegmentedControl *adServerSegControl = [[UISegmentedControl alloc] initWithItems:@[kDFPAdServer, kMoPubAdServer]]; + adServerSegControl.selectedSegmentIndex = 0; + UISegmentedControl *adTypeSegControl = [[UISegmentedControl alloc] initWithItems:@[kBanner, kInterstitial, kVideo]]; + adTypeSegControl.selectedSegmentIndex = 0; + + UITextField *placementIdTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 120, 50)]; + placementIdTextField.placeholder = kDefaultPlacementId; + placementIdTextField.text = kDefaultPlacementId; + placementIdTextField.textAlignment = NSTextAlignmentRight; + + UITextField *sizeTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 120, 50)]; + sizeTextField.placeholder = kDefaultSize; + sizeTextField.text = kDefaultSize; + sizeTextField.textAlignment = NSTextAlignmentRight; + + [_generalSettingsFields setObject:adServerSegControl forKey:kAdServer]; + [_generalSettingsFields setObject:adTypeSegControl forKey:kAdType]; + [_generalSettingsFields setObject:placementIdTextField forKey:kPlacementId]; + [_generalSettingsFields setObject:sizeTextField forKey:kSize]; +} + +- (void)previewAdButtonClicked:(id)sender { + UISegmentedControl *adServerSegControl = [self.generalSettingsFields objectForKey:kAdServer]; + UISegmentedControl *adTypeSegControl = [self.generalSettingsFields objectForKey:kAdType]; + UITextField *placementIdField = [self.generalSettingsFields objectForKey:kPlacementId]; + UITextField *sizeIdField = [self.generalSettingsFields objectForKey:kSize]; + + NSString *adType =[adTypeSegControl titleForSegmentAtIndex:[adTypeSegControl selectedSegmentIndex]]; + + NSDictionary *settings = @{kAdServer : [adServerSegControl titleForSegmentAtIndex:[adServerSegControl selectedSegmentIndex]], + kPlacementId : [placementIdField text], + kSize : [sizeIdField text]}; + + UIViewController *vcToPush; + if ([adType isEqualToString:kBanner]) { + vcToPush = [[BannerTestsViewController alloc] initWithSettings:settings]; + } else if ([adType isEqualToString:kInterstitial]) { + vcToPush = [[InterstitialTestsViewController alloc] initWithSettings:settings]; + } else if ([adType isEqualToString:kVideo]) { + vcToPush = [[VideoTestsViewController alloc] init]; + } + + if (vcToPush != nil) { + vcToPush.hidesBottomBarWhenPushed = YES; + [self.navigationController pushViewController:vcToPush animated:NO]; + } +} + +- (void)adServerClicked:(id)sender { + +} + +#pragma mark UITableViewDataSource methods + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.sectionHeaders.count; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + return [self.sectionHeaders objectAtIndex:section]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.generalSettingsData.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + NSString *simpleTableIdentifier = kAdSettingsTableViewReuseId; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; + + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; + } + UIView *rightContentView = [self.generalSettingsFields objectForKey:[self.generalSettingsData objectAtIndex:indexPath.row]]; + + switch (indexPath.section) { + case 0: + cell.textLabel.text = [self.generalSettingsData objectAtIndex:indexPath.row]; + rightContentView.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - rightContentView.frame.size.width - kRightMargin, + (cell.contentView.frame.size.height - rightContentView.frame.size.height) / 2, + rightContentView.frame.size.width, + rightContentView.frame.size.height); + [cell.contentView addSubview:rightContentView]; + break; + default: + break; + } + return cell; +} + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/Supporting Files/main.m b/examples/PrebidMobileDemo/PrebidMobileDemo/Supporting Files/main.m new file mode 100644 index 000000000..6f66c855c --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/Supporting Files/main.m @@ -0,0 +1,16 @@ +// +// main.m +// PrebidMobileDemo +// +// Created by Nicole Hedley on 3/22/17. +// Copyright © 2017 Nicole Hedley. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.h b/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.h new file mode 100644 index 000000000..0dc1ccc6c --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.h @@ -0,0 +1,20 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface VideoTestsViewController : UIViewController + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.m b/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.m new file mode 100644 index 000000000..fbf8bc0e1 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemo/VideoViewControllers/VideoTestsViewController.m @@ -0,0 +1,44 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "VideoTestsViewController.h" + +@interface VideoTestsViewController () + +@end + +@implementation VideoTestsViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git a/examples/PrebidMobileDemo/PrebidMobileDemoTests/Info.plist b/examples/PrebidMobileDemo/PrebidMobileDemoTests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemoTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/examples/PrebidMobileDemo/PrebidMobileDemoTests/PrebidMobileDemoTests.m b/examples/PrebidMobileDemo/PrebidMobileDemoTests/PrebidMobileDemoTests.m new file mode 100644 index 000000000..2d96fff78 --- /dev/null +++ b/examples/PrebidMobileDemo/PrebidMobileDemoTests/PrebidMobileDemoTests.m @@ -0,0 +1,39 @@ +// +// PrebidMobileDemoTests.m +// PrebidMobileDemoTests +// +// Created by Nicole Hedley on 3/22/17. +// Copyright © 2017 Nicole Hedley. All rights reserved. +// + +#import + +@interface PrebidMobileDemoTests : XCTestCase + +@end + +@implementation PrebidMobileDemoTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/examples/PrebidMobileDemo/Products/ipa/PrebidMobileDemo.ipa b/examples/PrebidMobileDemo/Products/ipa/PrebidMobileDemo.ipa new file mode 100644 index 000000000..5ad48879b Binary files /dev/null and b/examples/PrebidMobileDemo/Products/ipa/PrebidMobileDemo.ipa differ diff --git a/examples/PrebidMobileDemo/bin/make/ipa.sh b/examples/PrebidMobileDemo/bin/make/ipa.sh new file mode 100755 index 000000000..00fc4a697 --- /dev/null +++ b/examples/PrebidMobileDemo/bin/make/ipa.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +function info { + echo "$(tput setaf 2)INFO: $1$(tput sgr0)" +} + +function error { + echo "$(tput setaf 1)ERROR: $1$(tput sgr0)" +} + +function banner { + echo "" + echo "$(tput setaf 5)######## $1 #######$(tput sgr0)" + echo "" +} + +function ditto_or_exit { + ditto "${1}" "${2}" + if [ "$?" != 0 ]; then + error "Could not copy:" + error " source: ${1}" + error " target: ${2}" + if [ ! -e "${1}" ]; then + error "The source file does not exist" + error "Did a previous xcodebuild step fail?" + fi + error "Exiting 1" + exit 1 + fi +} + +banner "Preparing" + +if [ "${XCPRETTY}" = "0" ]; then + USE_XCPRETTY= +else + USE_XCPRETTY=`which xcpretty | tr -d '\n'` +fi + +if [ ! -z ${USE_XCPRETTY} ]; then + XC_PIPE='xcpretty -c' +else + XC_PIPE='cat' +fi + +XC_TARGET="PrebidMobileDemo" +XC_PROJECT="PrebidMobileDemo.xcodeproj" +XC_SCHEME="${XC_TARGET}" +XC_CONFIG=Debug + +XC_BUILD_DIR="build/ipa" +INSTALL_DIR="Products/ipa" + +APP="${XC_TARGET}.app" +DSYM="${APP}.dSYM" +IPA="${XC_TARGET}.ipa" + +INSTALLED_APP="${INSTALL_DIR}/${APP}" +INSTALLED_DSYM="${INSTALL_DIR}/${DSYM}" +INSTALLED_IPA="${INSTALL_DIR}/${IPA}" + +rm -rf "${INSTALL_DIR}" +mkdir -p "${INSTALL_DIR}" + +info "Prepared install directory ${INSTALL_DIR}" + +BUILD_PRODUCTS_DIR="${XC_BUILD_DIR}/Build/Products/${XC_CONFIG}-iphoneos" +BUILD_PRODUCTS_APP="${BUILD_PRODUCTS_DIR}/${APP}" +BUILD_PRODUCTS_DSYM="${BUILD_PRODUCTS_DIR}/${DSYM}" + +rm -rf "${BUILD_PRODUCTS_APP}" +rm -rf "${BUILD_PRODUCTS_DSYM}" + +info "Prepared archive directory" + +banner "Building ${IPA}" + +if [ -z "${CODE_SIGN_IDENTITY}" ]; then + COMMAND_LINE_BUILD=1 xcrun xcodebuild \ + -SYMROOT="${XC_BUILD_DIR}" \ + -derivedDataPath "${XC_BUILD_DIR}" \ + -project "${XC_PROJECT}" \ + -scheme "${XC_TARGET}" \ + -configuration "${XC_CONFIG}" \ + -sdk iphoneos \ + ARCHS="armv7 armv7s arm64" \ + VALID_ARCHS="armv7 armv7s arm64" \ + ONLY_ACTIVE_ARCH=NO \ + build | $XC_PIPE +else + COMMAND_LINE_BUILD=1 xcrun xcodebuild \ + CODE_SIGN_IDENTITY="${CODE_SIGN_IDENTITY}" \ + -SYMROOT="${XC_BUILD_DIR}" \ + -derivedDataPath "${XC_BUILD_DIR}" \ + -project "${XC_PROJECT}" \ + -scheme "${XC_TARGET}" \ + -configuration "${XC_CONFIG}" \ + -sdk iphoneos \ + ARCHS="armv7 armv7s arm64" \ + VALID_ARCHS="armv7 armv7s arm64" \ + ONLY_ACTIVE_ARCH=NO \ + build | $XC_PIPE +fi + +EXIT_CODE=${PIPESTATUS[0]} + +if [ $EXIT_CODE != 0 ]; then + error "Building ipa failed." + exit $EXIT_CODE +else + info "Building ipa succeeded." +fi + +banner "Installing" + +ditto_or_exit "${BUILD_PRODUCTS_APP}" "${INSTALLED_APP}" +info "Installed ${INSTALLED_APP}" + +PAYLOAD_DIR="${INSTALL_DIR}/Payload" +mkdir -p "${PAYLOAD_DIR}" + +ditto_or_exit "${INSTALLED_APP}" "${PAYLOAD_DIR}/${APP}" + +xcrun ditto -ck --rsrc --sequesterRsrc --keepParent \ + "${PAYLOAD_DIR}" \ + "${INSTALLED_IPA}" + +info "Installed ${INSTALLED_IPA}" + +info "Done!" diff --git a/examples/PrebidMobileDemo/calabash.framework/Headers b/examples/PrebidMobileDemo/calabash.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/examples/PrebidMobileDemo/calabash.framework/Resources b/examples/PrebidMobileDemo/calabash.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/0.20.4 b/examples/PrebidMobileDemo/calabash.framework/Versions/0.20.4 new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/0.20.4 @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/CalabashServer.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/CalabashServer.h new file mode 100644 index 000000000..97bb25ba3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/CalabashServer.h @@ -0,0 +1,14 @@ +// Created by Karl Krukow on 11/08/11. +// Copyright 2011 LessPainful. All rights reserved. + +#import + +@class LPHTTPServer; + +@interface CalabashServer : NSObject { + LPHTTPServer *_httpServer; +} + ++ (void) start; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPCORSResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPCORSResponse.h new file mode 100644 index 000000000..e5b6343a4 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPCORSResponse.h @@ -0,0 +1,16 @@ +// +// LPCORSResponse.h +// LPSimpleExample +// +// Created by Karl Krukow on 3/3/14. +// Copyright (c) 2014 Xamarin. All rights reserved. +// + +#import +#import "LPHTTPResponse.h" +#import "LPHTTPDataResponse.h" + + +@interface LPCORSResponse : LPHTTPDataResponse + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPAsyncFileResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPAsyncFileResponse.h new file mode 100644 index 000000000..1f2db9979 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPAsyncFileResponse.h @@ -0,0 +1,75 @@ +#import +#import "LPHTTPResponse.h" + +@class LPHTTPConnection; + +/** + * This is an asynchronous version of LPHTTPFileResponse. + * It reads data from the given file asynchronously via GCD. + * + * It may be overridden to allow custom post-processing of the data that has been read from the file. + * An example of this is the HTTPDynamicFileResponse class. + **/ + +@interface LPHTTPAsyncFileResponse : NSObject { + LPHTTPConnection *connection; + + NSString *filePath; + UInt64 fileLength; + UInt64 fileOffset; // File offset as pertains to data given to connection + UInt64 readOffset; // File offset as pertains to data read from file (but maybe not returned to connection) + + BOOL aborted; + + NSData *data; + + int fileFD; + void *readBuffer; + NSUInteger readBufferSize; // Malloced size of readBuffer + NSUInteger readBufferOffset; // Offset within readBuffer where the end of existing data is + NSUInteger readRequestLength; + dispatch_queue_t readQueue; + dispatch_source_t readSource; + BOOL readSourceSuspended; +} + +- (id)initWithFilePath:(NSString *)filePath forConnection:(LPHTTPConnection *)connection; + +- (NSString *)filePath; + +@end + +/** + * Explanation of Variables (excluding those that are obvious) + * + * fileOffset + * This is the number of bytes that have been returned to the connection via the readDataOfLength method. + * If 1KB of data has been read from the file, but none of that data has yet been returned to the connection, + * then the fileOffset variable remains at zero. + * This variable is used in the calculation of the isDone method. + * Only after all data has been returned to the connection are we actually done. + * + * readOffset + * Represents the offset of the file descriptor. + * In other words, the file position indicator for our read stream. + * It might be easy to think of it as the total number of bytes that have been read from the file. + * However, this isn't entirely accurate, as the setOffset: method may have caused us to + * jump ahead in the file (lseek). + * + * readBuffer + * Malloc'd buffer to hold data read from the file. + * + * readBufferSize + * Total allocation size of malloc'd buffer. + * + * readBufferOffset + * Represents the position in the readBuffer where we should store new bytes. + * + * readRequestLength + * The total number of bytes that were requested from the connection. + * It's OK if we return a lesser number of bytes to the connection. + * It's NOT OK if we return a greater number of bytes to the connection. + * Doing so would disrupt proper support for range requests. + * If, however, the response is chunked then we don't need to worry about this. + * Chunked responses inheritly don't support range requests. + **/ diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDataResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDataResponse.h new file mode 100644 index 000000000..a03e61256 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDataResponse.h @@ -0,0 +1,12 @@ +#import +#import "LPHTTPResponse.h" + + +@interface LPHTTPDataResponse : NSObject { + NSUInteger offset; + NSData *data; +} + +- (id)initWithData:(NSData *)data; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDynamicFileResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDynamicFileResponse.h new file mode 100644 index 000000000..6566247a3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPDynamicFileResponse.h @@ -0,0 +1,52 @@ +#import +#import "LPHTTPResponse.h" +#import "LPHTTPAsyncFileResponse.h" + +@class LPHTTPConnection; +/** + * This class is designed to assist with dynamic content. + * Imagine you have a file that you want to make dynamic: + * + * + * + *

ComputerName Control Panel

+ * ... + *
  • System Time: SysTime
  • + * + * + * + * Now you could generate the entire file in Objective-C, + * but this would be a horribly tedious process. + * Beside, you want to design the file with professional tools to make it look pretty. + * + * So all you have to do is escape your dynamic content like this: + * + * ... + *

    %%ComputerName%% Control Panel

    + * ... + *
  • System Time: %%SysTime%%
  • + * + * And then you create an instance of this class with: + * + * - separator = @"%%" + * - replacementDictionary = { "ComputerName"="Black MacBook", "SysTime"="2010-04-30 03:18:24" } + * + * This class will then perform the replacements for you, on the fly, as it reads the file data. + * This class is also asynchronous, so it will perform the file IO using its own GCD queue. + * + * All keys for the replacementDictionary must be NSString's. + * Values for the replacementDictionary may be NSString's, or any object that + * returns what you want when its description method is invoked. + **/ + +@interface LPHTTPDynamicFileResponse : LPHTTPAsyncFileResponse { + NSData *separator; + NSDictionary *replacementDict; +} + +- (id)initWithFilePath:(NSString *)filePath + forConnection:(LPHTTPConnection *)connection + separator:(NSString *)separatorStr + replacementDictionary:(NSDictionary *)dictionary; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPFileResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPFileResponse.h new file mode 100644 index 000000000..70f6efee6 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPFileResponse.h @@ -0,0 +1,25 @@ +#import +#import "LPHTTPResponse.h" + +@class LPHTTPConnection; + + +@interface LPHTTPFileResponse : NSObject { + LPHTTPConnection *connection; + + NSString *filePath; + UInt64 fileLength; + UInt64 fileOffset; + + BOOL aborted; + + int fileFD; + void *buffer; + NSUInteger bufferSize; +} + +- (id)initWithFilePath:(NSString *)filePath forConnection:(LPHTTPConnection *)connection; + +- (NSString *)filePath; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPResponse.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPResponse.h new file mode 100644 index 000000000..682810327 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPHTTPResponse.h @@ -0,0 +1,162 @@ +#import + + +@protocol LPHTTPResponse + +/** Returns the length of the data in bytes. If you don't know the length in + * advance, implement the isChunked method and have it return YES. + **/ +- (UInt64)contentLength; + +/** The HTTP server supports range requests in order to allow things like file + * download resumption and optimized streaming on mobile devices. + **/ +- (UInt64)offset; + +- (void)setOffset:(UInt64)offset; + +/** Returns the data for the response. You do not have to return data of the + * exact length that is given. You may optionally return data of a lesser + * length. However, you must never return data of a greater length than + * requested. Doing so could disrupt proper support for range requests. + * + * To support asynchronous responses, read the discussion at the bottom of this + * header. + **/ +- (NSData *)readDataOfLength:(NSUInteger)length; + +/** Should only return YES after the HTTPConnection has read all available data. + * That is, all data for the response has been returned to the HTTPConnection + * via the readDataOfLength method. + **/ +- (BOOL)isDone; + +@optional + +/** If you need time to calculate any part of the HTTP response headers (status + * code or header fields), this method allows you to delay sending the headers + * so that you may asynchronously execute the calculations. Simply implement + * this method and return YES until you have everything you need concerning the + * headers. + * + * This method ties into the asynchronous response architecture of the + * HTTPConnection. You should read the full discussion at the bottom of this + * header. + * + * If you return YES from this method, the HTTPConnection will wait for you to + * invoke the responseHasAvailableData method. After you do, the HTTPConnection + * will again invoke this method to see if the response is ready to send the + * headers. + * + * You should only delay sending the headers until you have everything you need + * concerning just the headers. Asynchronously generating the body of the + * response is not an excuse to delay sending the headers. Instead you should + * tie into the asynchronous response architecture, and use techniques such as + * the isChunked method. + * + * Important: You should read the discussion at the bottom of this header. + **/ +- (BOOL)delayResponseHeaders; + +/** Status code for response. Allows for responses such as redirect (301), etc. + **/ +- (NSInteger)status; + +/** If you want to add any extra HTTP headers to the response, simply return + * them in a dictionary in this method. + **/ +- (NSDictionary *)httpHeaders; + +/** If you don't know the content-length in advance, implement this method in + * your custom response class and return YES. + * + * Important: You should read the discussion at the bottom of this header. + **/ +- (BOOL)isChunked; + +/** This method is called from the HTTPConnection class when the connection is + * closed, or when the connection is finished with the response. If your + * response is asynchronous, you should implement this method so you know not to + * invoke any methods on the HTTPConnection after this method is called (as the + * connection may be deallocated). + **/ +- (void)connectionDidClose; + +@end + + +/** Important notice to those implementing custom asynchronous and/or chunked + * responses: + * + * HTTPConnection supports asynchronous responses. All you have to do in your + * custom response class is asynchronously generate the response, and invoke + * HTTPConnection's responseHasAvailableData method. You don't have to wait + * until you have all of the response ready to invoke this method. For example, + * if you generate the response in incremental chunks, you could call + * responseHasAvailableData after generating each chunk. Please see the + * HTTPAsyncFileResponse class for an example of how to do this. + * + * The normal flow of events for an HTTPConnection while responding to a request + * is like this: - Send http response headers - Get data from response via + * readDataOfLength method. - Add data to asyncSocket's write queue. - Wait + * for asyncSocket to notify it that the data has been sent. - Get more data + * from response via readDataOfLength method. - ... continue this cycle until + * the entire response has been sent. + * + * With an asynchronous response, the flow is a little different. + * + * First the LPHTTPResponse is given the opportunity to postpone sending the + * HTTP response headers. This allows the response to asynchronously execute + * any code needed to calculate a part of the header. An example might be the + * response needs to generate some custom header fields, or perhaps the response + * needs to look for a resource on network-attached storage. Since the + * network-attached storage may be slow, the response doesn't know whether to + * send a 200 or 404 yet. In situations such as this, the LPHTTPResponse simply + * implements the delayResponseHeaders method and returns YES. After returning + * YES from this method, the HTTPConnection will wait until the response invokes + * its responseHasAvailableData method. After this occurs, the HTTPConnection + * will again query the delayResponseHeaders method to see if the response is + * ready to send the headers. This cycle will continue until the + * delayResponseHeaders method returns NO. + * + * You should only delay sending the response headers until you have everything + * you need concerning just the headers. Asynchronously generating the body of + * the response is not an excuse to delay sending the headers. + * + * After the response headers have been sent, the HTTPConnection calls your + * readDataOfLength method. You may or may not have any available data at this + * point. If you don't, then simply return nil. You should later invoke + * HTTPConnection's responseHasAvailableData when you have data to send. + * + * You don't have to keep track of when you return nil in the readDataOfLength + * method, or how many times you've invoked responseHasAvailableData. Just + * simply call responseHasAvailableData whenever you've generated new data, and + * return nil in your readDataOfLength whenever you don't have any available + * data in the requested range. HTTPConnection will automatically detect when + * it should be requesting new data and will act appropriately. + * + * It's important that you also keep in mind that the HTTP server supports range + * requests. The setOffset method is mandatory, and should not be ignored. + * Make sure you take into account the offset within the readDataOfLength + * method. You should also be aware that the HTTPConnection automatically sorts + * any range requests. So if your setOffset method is called with a value of + * 100, then you can safely release bytes 0-99. + * + * HTTPConnection can also help you keep your memory footprint small. Imagine + * you're dynamically generating a 10 MB response. You probably don't want to + * load all this data into RAM, and sit around waiting for HTTPConnection to + * slowly send it out over the network. All you need to do is pay attention to + * when HTTPConnection requests more data via readDataOfLength. This is because + * HTTPConnection will never allow asyncSocket's write queue to get much bigger + * than READ_CHUNKSIZE bytes. You should consider how you might be able to take + * advantage of this fact to generate your asynchronous response on demand, + * while at the same time keeping your memory footprint small, and your + * application lightning fast. + * + * If you don't know the content-length in advanced, you should also implement + * the isChunked method. This means the response will not include a + * Content-Length header, and will instead use "Transfer-Encoding: chunked". + * There's a good chance that if your response is asynchronous and dynamic, it's + * also chunked. If your response is chunked, you don't need to worry about + * range requests. + **/ diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRoute.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRoute.h new file mode 100644 index 000000000..ec8b95ed2 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRoute.h @@ -0,0 +1,25 @@ +// +// LPRoute.h +// +// Created by Karl Krukow on 13/08/11. +// Copyright 2011 LessPainful. All rights reserved. +// + +#import + +@class LPHTTPConnection; + +@protocol LPRoute + +@optional +- (void) setParameters:(NSDictionary *) parameters; + +- (void) setConnection:(LPHTTPConnection *) connection; + +- (BOOL) supportsMethod:(NSString *) method atPath:(NSString *) path; + +- (NSDictionary *) JSONResponseForMethod:(NSString *) method + URI:(NSString *) path + data:(NSDictionary *) data; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRouter.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRouter.h new file mode 100644 index 000000000..1a8f11d6a --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPRouter.h @@ -0,0 +1,15 @@ +// +// LPRouter.h +// Created by Karl Krukow on 13/08/11. +// Copyright 2011 LessPainful. All rights reserved. + +#import "LPHTTPConnection.h" +#import "LPRoute.h" + +@interface LPRouter : LPHTTPConnection + +- (NSData *) postData; + ++ (void) addRoute:(id ) route forPath:(NSString *) path; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPVersionRoute.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPVersionRoute.h new file mode 100644 index 000000000..9de75b4d3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPVersionRoute.h @@ -0,0 +1,28 @@ +// +// LPVersionRoute.h +// calabash +// +// Created by Karl Krukow on 22/06/12. +// Copyright (c) 2012 LessPainful. All rights reserved. +// + +#import +#import "LPRoute.h" + +/*** UNEXPECTED *** + We have tools that search the strings in the compiled binary for a match on + 'CALABASH VERSION'. + + eg. $ strings Briar-cal.app/Briar-cal | grep -E 'CALABASH VERSION' + + We use this information to determine the version of the server that is compiled + into binary. + + Do not change the 'CALABASH VERSION' portion of the following constant without + updating the ruby API. + ******************/ +#define kLPCALABASHVERSION @"CALABASH VERSION: 0.20.4" + +@interface LPVersionRoute : NSObject + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebQuery.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebQuery.h new file mode 100644 index 000000000..da990ec1e --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebQuery.h @@ -0,0 +1,32 @@ +// +// LPWebQuery.h +// CalabashJS +// +// Created by Karl Krukow on 27/06/12. +// Copyright (c) 2012 Xamarin. All rights reserved. +// + +#import +#import +#import "LPWebViewProtocol.h" +#import "UIWebView+LPWebView.h" + +static NSString *const LP_QUERY_JS = @"(function(){function isHostMethod(object,property){var t=typeof object[property];return t==='function'||(!!(t==='object'&&object[property]))||t==='unknown';}var NODE_TYPES={1:'ELEMENT_NODE',2:'ATTRIBUTE_NODE',3:'TEXT_NODE',9:'DOCUMENT_NODE'};function boundingClientRect(object){var rect=null,jsonRect=null;if(isHostMethod(object,'getBoundingClientRect')){rect=object.getBoundingClientRect(),jsonRect={left:rect.left,top:rect.top,width:rect.width,height:rect.height,x:rect.left+Math.floor(rect.width/2),y:rect.top+Math.floor(rect.height/2)};}return jsonRect;}function computeRectForNode(object,fullDump){var res={};res.rect=boundingClientRect(object);res.nodeType=NODE_TYPES[object.nodeType]||res.nodeType+' (Unexpected)';res.nodeName=object.nodeName;res.id=object.id||'';res['class']=object.className||'';if(object.href){res.href=object.href;}if(object.hasOwnProperty('value')){res.value=object.value||'';}if(fullDump||object.nodeType==3){res.textContent=object.textContent;}return res;}function toJSON(object,fullDump,queryFrame,queryWindow){var res,i,N,spanEl,parentEl;if(typeof object==='undefined'){throw {message:'Calling toJSON with undefined'};}else{if(object instanceof queryWindow.Text){parentEl=object.parentElement;if(parentEl){spanEl=queryFrame.createElement('calabash');spanEl.style.display='inline';spanEl.innerHTML=object.textContent;parentEl.replaceChild(spanEl,object);res=computeRectForNode(spanEl,fullDump);res.nodeType=NODE_TYPES[object.nodeType];res.textContent=object.textContent;delete res.nodeName;delete res.id;delete res['class'];parentEl.replaceChild(object,spanEl);}else{res=object;}}else{if(object instanceof queryWindow.Node){res=computeRectForNode(object,fullDump);}else{if(object instanceof queryWindow.NodeList||(typeof object=='object'&&object&&typeof object.length==='number'&&object.length>0&&typeof object[0]!=='undefined')){res=[];for(i=0,N=object.length;i *) webView + includeInvisible:(BOOL) includeInvisible; + ++ (NSDictionary *) dictionaryOfViewsInWebView:(UIView *) webView; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewProtocol.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewProtocol.h new file mode 100644 index 000000000..e755884c3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewProtocol.h @@ -0,0 +1,13 @@ +#import + +@protocol LPWebViewProtocol + +@required + +// The bridge between UIWebView and WKWebKit. +- (NSString *) calabashStringByEvaluatingJavaScript:(NSString *) javascript; + +- (BOOL) pointInside:(CGPoint) point withEvent:(UIEvent *) event; +- (UIScrollView *) scrollView; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewUtils.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewUtils.h new file mode 100644 index 000000000..956de81a3 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/LPWebViewUtils.h @@ -0,0 +1,8 @@ +#import + +@interface LPWebViewUtils : NSObject + ++ (BOOL) isWebView:(id) object; ++ (BOOL) isIFrameResult:(NSDictionary *)result; + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/UIWebView+LPWebView.h b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/UIWebView+LPWebView.h new file mode 100644 index 000000000..9840ea7ad --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Headers/UIWebView+LPWebView.h @@ -0,0 +1,6 @@ +#import +#import "LPWebViewProtocol.h" + +@interface UIWebView (UIWebView_LPWebView) + +@end diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/Resources/version b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Resources/version new file mode 100755 index 000000000..b6b94674a Binary files /dev/null and b/examples/PrebidMobileDemo/calabash.framework/Versions/A/Resources/version differ diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/A/calabash b/examples/PrebidMobileDemo/calabash.framework/Versions/A/calabash new file mode 100644 index 000000000..eb781141a Binary files /dev/null and b/examples/PrebidMobileDemo/calabash.framework/Versions/A/calabash differ diff --git a/examples/PrebidMobileDemo/calabash.framework/Versions/Current b/examples/PrebidMobileDemo/calabash.framework/Versions/Current new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/examples/PrebidMobileDemo/calabash.framework/calabash b/examples/PrebidMobileDemo/calabash.framework/calabash new file mode 120000 index 000000000..bccada38d --- /dev/null +++ b/examples/PrebidMobileDemo/calabash.framework/calabash @@ -0,0 +1 @@ +Versions/Current/calabash \ No newline at end of file diff --git a/examples/PrebidMobileDemo/features/pbm_basic.feature b/examples/PrebidMobileDemo/features/pbm_basic.feature new file mode 100644 index 000000000..21ea9fa9b --- /dev/null +++ b/examples/PrebidMobileDemo/features/pbm_basic.feature @@ -0,0 +1,17 @@ +Feature: Prebid Mobile + +Scenario: Test DFP Scenarios + Given the app has launched + When I touch "DFP" + And I touch "Banner" + And I touch the "See Ad" button + And I wait for 2 seconds + Then I should see an AppNexus ad + +Scenario: Test MoPub Scenarios + Given the app has launched + When I touch "MoPub" + And I touch "Banner" + And I touch the "See Ad" button + And I wait for 2 seconds + Then I should see an AppNexus ad diff --git a/examples/PrebidMobileDemo/features/steps/pbm_basic.rb b/examples/PrebidMobileDemo/features/steps/pbm_basic.rb new file mode 100644 index 000000000..25265f74f --- /dev/null +++ b/examples/PrebidMobileDemo/features/steps/pbm_basic.rb @@ -0,0 +1,49 @@ +Given(/^the app has launched$/) do + wait_for do + !query("*").empty? + end +end + +And(/^I have done a specific thing$/) do + # Example: Given I am logged in + # wait_for do + # !query("* marked:'username'").empty? + # end + # + # touch("* marked:'username'") + # wait_for_keyboard + # keyboard_enter_text("cleveruser27") + # + # touch("* marked:'password'") + # wait_for_keyboard + # keyboard_enter_text("pa$$w0rd") + # + # wait_for_element_exists("* marked:'Login'") + # touch("* marked:'Login'") + + # Remember: any Ruby is allowed in your step definitions + did_something = true + + unless did_something + fail 'Expected to have done something' + end +end + +When(/^I do something$/) do + # Example: When I create a new entry + # tap("* marked:'new_entry'") + # wait_for_keyboard + # keyboard_enter_text("* marked:'entry_title'", 'My Entry') + # + # tap("* marked:'submit'") +end + +Then(/^something should happen$/) do + # Example: Then I should see the entry on my home page + # wait_for_element_exists("* text:'My Entry'") +end + +Then(/^I should see an AppNexus ad$/) do + res = query("webView css:'body'") + expect(res[0]["textContent"].include? "showAdFromCacheId").to be_truthy +end diff --git a/examples/PrebidMobileDemo/features/support/01_launch.rb b/examples/PrebidMobileDemo/features/support/01_launch.rb new file mode 100644 index 000000000..ed233eea7 --- /dev/null +++ b/examples/PrebidMobileDemo/features/support/01_launch.rb @@ -0,0 +1,43 @@ +require 'calabash-cucumber/launcher' + +# You can find examples of more complicated launch hooks in these +# two repositories: +# +# https://github.com/calabash/ios-smoke-test-app/blob/master/CalSmokeApp/features/support/01_launch.rb +# https://github.com/calabash/ios-webview-test-app/blob/master/CalWebViewApp/features/support/01_launch.rb + +module Calabash::Launcher + @@launcher = nil + + def self.launcher + @@launcher ||= Calabash::Cucumber::Launcher.new + end + + def self.launcher=(launcher) + @@launcher = launcher + end +end + +Before do |scenario| + launcher = Calabash::Launcher.launcher + options = { + # Add launch options here. + } + + launcher.relaunch(options) +end + +After do |scenario| + # Calabash can shutdown the app cleanly by calling the app life cycle methods + # in the UIApplicationDelegate. This is really nice for CI environments, but + # not so good for local development. + # + # See the documentation for QUIT_APP_AFTER_SCENARIO for a nice debugging workflow + # + # http://calabashapi.xamarin.com/ios/file.ENVIRONMENT_VARIABLES.html#label-QUIT_APP_AFTER_SCENARIO + # http://calabashapi.xamarin.com/ios/Calabash/Cucumber/Core.html#console_attach-instance_method + if launcher.quit_app_after_scenario? + calabash_exit + end +end + diff --git a/examples/PrebidMobileDemo/features/support/dry_run.rb b/examples/PrebidMobileDemo/features/support/dry_run.rb new file mode 100644 index 000000000..b3c4649d3 --- /dev/null +++ b/examples/PrebidMobileDemo/features/support/dry_run.rb @@ -0,0 +1,19 @@ +require "calabash-cucumber" + +# Cucumber -d must pass, but support/env.rb is not eval'd on dry runs. +# We must detect that the user wants to use pre-defined steps. +dir = File.expand_path(File.dirname(__FILE__)) +env = File.join(dir, "env.rb") + +contents = File.read(env).force_encoding("UTF-8") + +contents.split($-0).each do |line| + + # Skip comments. + next if line.chars[0] == "#" + + if line[/calabash-cucumber\/cucumber/, 0] + require "calabash-cucumber/calabash_steps" + break + end +end diff --git a/examples/PrebidMobileDemo/features/support/env.rb b/examples/PrebidMobileDemo/features/support/env.rb new file mode 100644 index 000000000..20a70b485 --- /dev/null +++ b/examples/PrebidMobileDemo/features/support/env.rb @@ -0,0 +1,13 @@ +# Requiring this file will import: +# * the Calabash Cucumber API, +# * the Calabash Cucumber predefined Steps, +# * and the Calabash::Formatters::Html cucumber formatter. +require "calabash-cucumber/cucumber" + +# To use Calabash without the predefined Calabash Steps, uncomment these +# three lines and delete the require above. +require "calabash-cucumber/wait_helpers" +require "calabash-cucumber/operations" +World(Calabash::Cucumber::Operations) + +require 'rspec' diff --git a/examples/PrebidMobileDemo/features/support/patches/cucumber.rb b/examples/PrebidMobileDemo/features/support/patches/cucumber.rb new file mode 100644 index 000000000..aec5d8f4d --- /dev/null +++ b/examples/PrebidMobileDemo/features/support/patches/cucumber.rb @@ -0,0 +1,15 @@ +# override cucumber pending on the XTC +if ENV['XAMARIN_TEST_CLOUD'] == '1' + module Cucumber + module RbSupport + def pending(message = 'TODO') + raise "PENDING: #{message}" + end + + def ask(message, _) + raise "Cannot ask: '#{message}'; User interaction is not allowed on the XTC" + end + end + end + World(Cucumber::RbSupport) +end diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 000000000..0bc7a0993 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,13 @@ +## Build scripts directory for Prebid Mobile + +To build the Prebid Mobile framework run: + +``` +./buildPrebidMobile.sh +``` + +To test the Prebid Mobile framework run: + +``` +./testPrebidMobile.sh +``` diff --git a/scripts/buildPrebidMobile.sh b/scripts/buildPrebidMobile.sh new file mode 100755 index 000000000..903ab7a4f --- /dev/null +++ b/scripts/buildPrebidMobile.sh @@ -0,0 +1,56 @@ +# Merge Script +if [ -d "scripts" ]; then +cd scripts/ +fi + +# 1 +# Set bash script to exit immediately if any commands fail. +set -e + +# 2 +# Setup some constants for use later on. +FRAMEWORK_NAME="PrebidMobile" +LOGDIR=../build/out/log +mkdir -p "$LOGDIR" + +# 3 +# If remnants from a previous build exist, delete them. +if [ -d "build" ]; then +rm -rf "build" +fi + +cd ../sdk/ +LOGFILE="$LOGDIR"/prebid_mobile_build.log +touch "$LOGFILE" + +# 4 +# Build the framework for device and for simulator (using +# all needed architectures). +xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch arm64 -arch armv7 -arch armv7s only_active_arch=no defines_module=yes -sdk "iphoneos" > "$LOGFILE" 2>&1 || { echo "Error in build check log "$LOGFILE""; exit;} + +xcodebuild -target "${FRAMEWORK_NAME}" -configuration Release -arch x86_64 -arch i386 only_active_arch=no defines_module=yes -sdk "iphonesimulator" > "$LOGFILE" 2>&1 || { echo "Error in build check log "$LOGFILE""; exit;} + +# 5 +# Remove .framework file if exists on Desktop from previous run. +if [ -d "${HOME}/Desktop/${FRAMEWORK_NAME}.framework" ]; then +rm -rf "${HOME}/Desktop/${FRAMEWORK_NAME}.framework" +fi + +# 6 +# Copy the device version of framework to Desktop. +cp -r "build/Release-iphoneos/${FRAMEWORK_NAME}.framework" "${HOME}/Desktop/${FRAMEWORK_NAME}.framework" + +# 7 +# Replace the framework executable within the framework with +# a new version created by merging the device and simulator +# frameworks' executables with lipo. +lipo -create -output "${HOME}/Desktop/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "build/Release-iphoneos/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" "build/Release-iphonesimulator/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" + +echo "Done! You can find the Prebid Mobile framework on your Desktop" +echo "Build logs are also available in the build/out/log/ folder." + +# 8 +# Delete the most recent build. +if [ -d "build" ]; then +rm -rf "build" +fi diff --git a/scripts/testPrebidMobile.sh b/scripts/testPrebidMobile.sh new file mode 100755 index 000000000..f39ec2950 --- /dev/null +++ b/scripts/testPrebidMobile.sh @@ -0,0 +1,15 @@ +if [ -d "scripts" ]; then +cd scripts/ +fi + +cd ../sdk/ + +echo "Running unit tests" +gem install xcpretty +xcodebuild test -project PrebidMobile.xcodeproj -scheme "PrebidMobileTests" -destination 'platform=iOS Simulator,id=$IOS_SIMULATOR_UDID' | xcpretty + +echo "Running integration tests" +cd ../examples/PrebidMobileDemo/ +#make ipa +gem install xamarin-test-cloud +test-cloud submit Products/ipa/PrebidMobileDemo.ipa 435c130f3f6ff5256d19a790c21dd653 --devices 9f82ba1c --series "master" --locale "en_US" --app-name "AppNexus.PrebidMobileDemo" --user nhedley@appnexus.com diff --git a/sdk/PrebidMobile.podspec b/sdk/PrebidMobile.podspec new file mode 100644 index 000000000..a53304889 --- /dev/null +++ b/sdk/PrebidMobile.podspec @@ -0,0 +1,45 @@ +Pod::Spec.new do |s| + + s.name = "PrebidMobile" + s.version = "0.0.1" + s.summary = "PrebidMobile is a lightweight framework that integrates directly with Prebid Server." + + s.description = <<-DESC + Prebid-Mobile-SDK is a lightweight framework that integrates directly with Prebid Server to increase yield for publishers by adding more mobile buyers." + DESC + s.homepage = "https://www.prebid.org" + + + s.license = { :type => "Apache License, Version 2.0", :text => <<-LICENSE + Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + LICENSE + } + + s.author = { "Nicole Hedley" => "nhedley@appnexus.com" } + s.platform = :ios, "8.0" + s.source = { :git => "https://github.com/prebid/prebid-mobile-ios.git", :tag => "#{s.version}" } + s.source_files = "PrebidMobile", "PrebidMobile/**/*.{h,m}", "PrebidServerAdapter/**/*.{h,m}" + s.public_header_files = "PrebidServerAdapter/PBServerAdapter.h", "PrebidMobile/*.h", "PrebidMobile/Logging/*.h" + s.requires_arc = true + s.xcconfig = { +:LIBRARY_SEARCH_PATHS => '$(inherited)', +:OTHER_CFLAGS => '$(inherited)', +:OTHER_LDFLAGS => '$(inherited)', +:HEADER_SEARCH_PATHS => '$(inherited)', +:FRAMEWORK_SEARCH_PATHS => '$(inherited)' +} + s.framework = ['MediaPlayer', 'AVFoundation', 'EventKit', 'CoreTelephony', 'CoreData', 'SystemConfiguration', 'CoreGraphics', 'UIKit', 'Foundation', 'MessageUI', 'StoreKit'] + +end diff --git a/sdk/PrebidMobile.xcodeproj/project.pbxproj b/sdk/PrebidMobile.xcodeproj/project.pbxproj new file mode 100644 index 000000000..54ed8a81e --- /dev/null +++ b/sdk/PrebidMobile.xcodeproj/project.pbxproj @@ -0,0 +1,731 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + C22E7CE61EE70E19007B31F4 /* NSTimer+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E501EE1BEC4006304C0 /* NSTimer+Extension.m */; }; + C23386D21EE5DBFB002FD404 /* PrebidMobile.h in Headers */ = {isa = PBXBuildFile; fileRef = C23386D01EE5DBFB002FD404 /* PrebidMobile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C23386D31EE5DBFB002FD404 /* PrebidMobile.m in Sources */ = {isa = PBXBuildFile; fileRef = C23386D11EE5DBFB002FD404 /* PrebidMobile.m */; }; + C23386D61EE5DC95002FD404 /* PBAdUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = C23386D41EE5DC95002FD404 /* PBAdUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C23386D71EE5DC95002FD404 /* PBAdUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = C23386D51EE5DC95002FD404 /* PBAdUnit.m */; }; + C23386DA1EE5DCDB002FD404 /* PBServerAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = C23386D81EE5DCDB002FD404 /* PBServerAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C23386DB1EE5DCDB002FD404 /* PBServerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = C23386D91EE5DCDB002FD404 /* PBServerAdapter.m */; }; + C23FCCEA1EE5E3F500CFFEF0 /* PBLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = C23FCCE81EE5E3F500CFFEF0 /* PBLogging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C23FCCEB1EE5E3F500CFFEF0 /* PBLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = C23FCCE91EE5E3F500CFFEF0 /* PBLogging.m */; }; + C23FCCEE1EE5E41E00CFFEF0 /* PBLogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C23FCCEC1EE5E41E00CFFEF0 /* PBLogManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C23FCCEF1EE5E41E00CFFEF0 /* PBLogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C23FCCED1EE5E41E00CFFEF0 /* PBLogManager.m */; }; + C24B78C41EE7467E0045B454 /* NSObject+Prebid.h in Headers */ = {isa = PBXBuildFile; fileRef = C24B78C21EE7467E0045B454 /* NSObject+Prebid.h */; }; + C24B78C51EE7467E0045B454 /* NSObject+Prebid.m in Sources */ = {isa = PBXBuildFile; fileRef = C24B78C31EE7467E0045B454 /* NSObject+Prebid.m */; }; + C281E1811EE5EAF700F2F4A9 /* PrebidMobile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B16E1B1EE1BE69006304C0 /* PrebidMobile.framework */; }; + C281E1991EE5F2AD00F2F4A9 /* PBAdUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1941EE5F2AD00F2F4A9 /* PBAdUnitTests.m */; }; + C281E19A1EE5F2AD00F2F4A9 /* PBBidManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1951EE5F2AD00F2F4A9 /* PBBidManagerTests.m */; }; + C281E19B1EE5F2AD00F2F4A9 /* PBBidResponseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1961EE5F2AD00F2F4A9 /* PBBidResponseTests.m */; }; + C281E19D1EE5F2AD00F2F4A9 /* PBTargetingParamsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1981EE5F2AD00F2F4A9 /* PBTargetingParamsTests.m */; }; + C281E1A91EE5F2DA00F2F4A9 /* pbs_request.json in Resources */ = {isa = PBXBuildFile; fileRef = C281E19F1EE5F2DA00F2F4A9 /* pbs_request.json */; }; + C281E1AA1EE5F2DA00F2F4A9 /* pbs_response.json in Resources */ = {isa = PBXBuildFile; fileRef = C281E1A01EE5F2DA00F2F4A9 /* pbs_response.json */; }; + C281E1AB1EE5F2DA00F2F4A9 /* PCKeywordsManagerPriceIntervals.txt in Resources */ = {isa = PBXBuildFile; fileRef = C281E1A11EE5F2DA00F2F4A9 /* PCKeywordsManagerPriceIntervals.txt */; }; + C281E1AC1EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1A41EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.m */; }; + C281E1AD1EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1A61EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.m */; }; + C281E1AE1EE5F2DA00F2F4A9 /* ANURLConnectionStub.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1A81EE5F2DA00F2F4A9 /* ANURLConnectionStub.m */; }; + C281E1B21EE5F2E500F2F4A9 /* PBMockServerAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = C281E1B11EE5F2E500F2F4A9 /* PBMockServerAdapter.m */; }; + C2B16E341EE1BEA6006304C0 /* PBBannerAdUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E261EE1BEA6006304C0 /* PBBannerAdUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E351EE1BEA6006304C0 /* PBBannerAdUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E271EE1BEA6006304C0 /* PBBannerAdUnit.m */; }; + C2B16E361EE1BEA6006304C0 /* PBBidManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E281EE1BEA6006304C0 /* PBBidManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E371EE1BEA6006304C0 /* PBBidManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E291EE1BEA6006304C0 /* PBBidManager.m */; }; + C2B16E381EE1BEA6006304C0 /* PBBidResponseDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E2A1EE1BEA6006304C0 /* PBBidResponseDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E391EE1BEA6006304C0 /* PBException.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E2B1EE1BEA6006304C0 /* PBException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E3A1EE1BEA6006304C0 /* PBException.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E2C1EE1BEA6006304C0 /* PBException.m */; }; + C2B16E3B1EE1BEA6006304C0 /* PBInterstitialAdUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E2D1EE1BEA6006304C0 /* PBInterstitialAdUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E3C1EE1BEA6006304C0 /* PBInterstitialAdUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E2E1EE1BEA6006304C0 /* PBInterstitialAdUnit.m */; }; + C2B16E3D1EE1BEA6006304C0 /* PBKeywordsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E2F1EE1BEA6006304C0 /* PBKeywordsManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E3E1EE1BEA6006304C0 /* PBKeywordsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E301EE1BEA6006304C0 /* PBKeywordsManager.m */; }; + C2B16E3F1EE1BEA6006304C0 /* PBTargetingParams.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E311EE1BEA6006304C0 /* PBTargetingParams.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E401EE1BEA6006304C0 /* PBTargetingParams.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E321EE1BEA6006304C0 /* PBTargetingParams.m */; }; + C2B16E481EE1BEB6006304C0 /* PBBidResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E441EE1BEB6006304C0 /* PBBidResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C2B16E491EE1BEB6006304C0 /* PBBidResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E451EE1BEB6006304C0 /* PBBidResponse.m */; }; + C2B16E561EE1BEC4006304C0 /* NSDictionary+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E4C1EE1BEC4006304C0 /* NSDictionary+Extension.m */; }; + C2B16E581EE1BEC4006304C0 /* NSString+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E4E1EE1BEC4006304C0 /* NSString+Extension.m */; }; + C2B16E981EE1BF1A006304C0 /* PBServerFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E8C1EE1BF1A006304C0 /* PBServerFetcher.h */; }; + C2B16E991EE1BF1A006304C0 /* PBServerFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E8D1EE1BF1A006304C0 /* PBServerFetcher.m */; }; + C2B16E9B1EE1BF1A006304C0 /* PBServerGlobal.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E8F1EE1BF1A006304C0 /* PBServerGlobal.h */; }; + C2B16E9C1EE1BF1A006304C0 /* PBServerGlobal.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E901EE1BF1A006304C0 /* PBServerGlobal.m */; }; + C2B16E9D1EE1BF1A006304C0 /* PBServerLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E911EE1BF1A006304C0 /* PBServerLocation.h */; }; + C2B16E9E1EE1BF1A006304C0 /* PBServerLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E921EE1BF1A006304C0 /* PBServerLocation.m */; }; + C2B16E9F1EE1BF1A006304C0 /* PBServerReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B16E931EE1BF1A006304C0 /* PBServerReachability.h */; }; + C2B16EA01EE1BF1A006304C0 /* PBServerReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = C2B16E941EE1BF1A006304C0 /* PBServerReachability.m */; }; + C2B174711EE1E3AC006304C0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B1746D1EE1E3AC006304C0 /* CoreGraphics.framework */; }; + C2B174721EE1E3AC006304C0 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B1746E1EE1E3AC006304C0 /* CoreLocation.framework */; }; + C2B174731EE1E3AC006304C0 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B1746F1EE1E3AC006304C0 /* CoreMedia.framework */; }; + C2B174741EE1E3AC006304C0 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B174701EE1E3AC006304C0 /* CoreTelephony.framework */; }; + C2B174761EE1E3B6006304C0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B174751EE1E3B6006304C0 /* Foundation.framework */; }; + C2B174781EE1E3BC006304C0 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B174771EE1E3BC006304C0 /* MediaPlayer.framework */; }; + C2B1747A1EE1E3C3006304C0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B174791EE1E3C3006304C0 /* UIKit.framework */; }; + C2B1747C1EE1E3C9006304C0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B1747B1EE1E3C9006304C0 /* SystemConfiguration.framework */; }; + C2B1747E1EE1E3CE006304C0 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2B1747D1EE1E3CE006304C0 /* QuartzCore.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + C281E1821EE5EAF700F2F4A9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = C2B16E121EE1BE69006304C0 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2B16E1A1EE1BE69006304C0; + remoteInfo = PrebidMobile; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + C23386D01EE5DBFB002FD404 /* PrebidMobile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrebidMobile.h; sourceTree = ""; }; + C23386D11EE5DBFB002FD404 /* PrebidMobile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrebidMobile.m; sourceTree = ""; }; + C23386D41EE5DC95002FD404 /* PBAdUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBAdUnit.h; sourceTree = ""; }; + C23386D51EE5DC95002FD404 /* PBAdUnit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBAdUnit.m; sourceTree = ""; }; + C23386D81EE5DCDB002FD404 /* PBServerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServerAdapter.h; sourceTree = ""; }; + C23386D91EE5DCDB002FD404 /* PBServerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServerAdapter.m; sourceTree = ""; }; + C23FCCE81EE5E3F500CFFEF0 /* PBLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBLogging.h; sourceTree = ""; }; + C23FCCE91EE5E3F500CFFEF0 /* PBLogging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBLogging.m; sourceTree = ""; }; + C23FCCEC1EE5E41E00CFFEF0 /* PBLogManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBLogManager.h; sourceTree = ""; }; + C23FCCED1EE5E41E00CFFEF0 /* PBLogManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBLogManager.m; sourceTree = ""; }; + C23FCD501EE5EA6D00CFFEF0 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + C24B78C21EE7467E0045B454 /* NSObject+Prebid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Prebid.h"; sourceTree = ""; }; + C24B78C31EE7467E0045B454 /* NSObject+Prebid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+Prebid.m"; sourceTree = ""; }; + C281E17C1EE5EAF700F2F4A9 /* PrebidMobileTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PrebidMobileTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + C281E1941EE5F2AD00F2F4A9 /* PBAdUnitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBAdUnitTests.m; sourceTree = ""; }; + C281E1951EE5F2AD00F2F4A9 /* PBBidManagerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBBidManagerTests.m; sourceTree = ""; }; + C281E1961EE5F2AD00F2F4A9 /* PBBidResponseTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBBidResponseTests.m; sourceTree = ""; }; + C281E1981EE5F2AD00F2F4A9 /* PBTargetingParamsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBTargetingParamsTests.m; sourceTree = ""; }; + C281E19F1EE5F2DA00F2F4A9 /* pbs_request.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pbs_request.json; sourceTree = ""; }; + C281E1A01EE5F2DA00F2F4A9 /* pbs_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pbs_response.json; sourceTree = ""; }; + C281E1A11EE5F2DA00F2F4A9 /* PCKeywordsManagerPriceIntervals.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PCKeywordsManagerPriceIntervals.txt; sourceTree = ""; }; + C281E1A31EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANHTTPStubbingManager.h; sourceTree = ""; }; + C281E1A41EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANHTTPStubbingManager.m; sourceTree = ""; }; + C281E1A51EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANHTTPStubURLProtocol.h; sourceTree = ""; }; + C281E1A61EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANHTTPStubURLProtocol.m; sourceTree = ""; }; + C281E1A71EE5F2DA00F2F4A9 /* ANURLConnectionStub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ANURLConnectionStub.h; sourceTree = ""; }; + C281E1A81EE5F2DA00F2F4A9 /* ANURLConnectionStub.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ANURLConnectionStub.m; sourceTree = ""; }; + C281E1B01EE5F2E500F2F4A9 /* PBMockServerAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBMockServerAdapter.h; sourceTree = ""; }; + C281E1B11EE5F2E500F2F4A9 /* PBMockServerAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBMockServerAdapter.m; sourceTree = ""; }; + C2B16E1B1EE1BE69006304C0 /* PrebidMobile.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PrebidMobile.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C2B16E1F1EE1BE69006304C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C2B16E261EE1BEA6006304C0 /* PBBannerAdUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBBannerAdUnit.h; sourceTree = ""; }; + C2B16E271EE1BEA6006304C0 /* PBBannerAdUnit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBBannerAdUnit.m; sourceTree = ""; }; + C2B16E281EE1BEA6006304C0 /* PBBidManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBBidManager.h; sourceTree = ""; }; + C2B16E291EE1BEA6006304C0 /* PBBidManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBBidManager.m; sourceTree = ""; }; + C2B16E2A1EE1BEA6006304C0 /* PBBidResponseDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBBidResponseDelegate.h; sourceTree = ""; }; + C2B16E2B1EE1BEA6006304C0 /* PBException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBException.h; sourceTree = ""; }; + C2B16E2C1EE1BEA6006304C0 /* PBException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBException.m; sourceTree = ""; }; + C2B16E2D1EE1BEA6006304C0 /* PBInterstitialAdUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBInterstitialAdUnit.h; sourceTree = ""; }; + C2B16E2E1EE1BEA6006304C0 /* PBInterstitialAdUnit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBInterstitialAdUnit.m; sourceTree = ""; }; + C2B16E2F1EE1BEA6006304C0 /* PBKeywordsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBKeywordsManager.h; sourceTree = ""; }; + C2B16E301EE1BEA6006304C0 /* PBKeywordsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBKeywordsManager.m; sourceTree = ""; }; + C2B16E311EE1BEA6006304C0 /* PBTargetingParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBTargetingParams.h; sourceTree = ""; }; + C2B16E321EE1BEA6006304C0 /* PBTargetingParams.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBTargetingParams.m; sourceTree = ""; }; + C2B16E441EE1BEB6006304C0 /* PBBidResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBBidResponse.h; sourceTree = ""; }; + C2B16E451EE1BEB6006304C0 /* PBBidResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBBidResponse.m; sourceTree = ""; }; + C2B16E4B1EE1BEC4006304C0 /* NSDictionary+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+Extension.h"; sourceTree = ""; }; + C2B16E4C1EE1BEC4006304C0 /* NSDictionary+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+Extension.m"; sourceTree = ""; }; + C2B16E4D1EE1BEC4006304C0 /* NSString+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Extension.h"; sourceTree = ""; }; + C2B16E4E1EE1BEC4006304C0 /* NSString+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Extension.m"; sourceTree = ""; }; + C2B16E4F1EE1BEC4006304C0 /* NSTimer+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTimer+Extension.h"; sourceTree = ""; }; + C2B16E501EE1BEC4006304C0 /* NSTimer+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTimer+Extension.m"; sourceTree = ""; }; + C2B16E8C1EE1BF1A006304C0 /* PBServerFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServerFetcher.h; sourceTree = ""; }; + C2B16E8D1EE1BF1A006304C0 /* PBServerFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServerFetcher.m; sourceTree = ""; }; + C2B16E8F1EE1BF1A006304C0 /* PBServerGlobal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServerGlobal.h; sourceTree = ""; }; + C2B16E901EE1BF1A006304C0 /* PBServerGlobal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServerGlobal.m; sourceTree = ""; }; + C2B16E911EE1BF1A006304C0 /* PBServerLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServerLocation.h; sourceTree = ""; }; + C2B16E921EE1BF1A006304C0 /* PBServerLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServerLocation.m; sourceTree = ""; }; + C2B16E931EE1BF1A006304C0 /* PBServerReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServerReachability.h; sourceTree = ""; }; + C2B16E941EE1BF1A006304C0 /* PBServerReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServerReachability.m; sourceTree = ""; }; + C2B1746D1EE1E3AC006304C0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + C2B1746E1EE1E3AC006304C0 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; + C2B1746F1EE1E3AC006304C0 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + C2B174701EE1E3AC006304C0 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; + C2B174751EE1E3B6006304C0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + C2B174771EE1E3BC006304C0 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; + C2B174791EE1E3C3006304C0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + C2B1747B1EE1E3C9006304C0 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + C2B1747D1EE1E3CE006304C0 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + EFD3C940519B957467FE94E6 /* libPods-PrebidMobile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-PrebidMobile.a"; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + C281E1791EE5EAF700F2F4A9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C281E1811EE5EAF700F2F4A9 /* PrebidMobile.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B16E171EE1BE69006304C0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B1747E1EE1E3CE006304C0 /* QuartzCore.framework in Frameworks */, + C2B1747C1EE1E3C9006304C0 /* SystemConfiguration.framework in Frameworks */, + C2B1747A1EE1E3C3006304C0 /* UIKit.framework in Frameworks */, + C2B174781EE1E3BC006304C0 /* MediaPlayer.framework in Frameworks */, + C2B174761EE1E3B6006304C0 /* Foundation.framework in Frameworks */, + C2B174711EE1E3AC006304C0 /* CoreGraphics.framework in Frameworks */, + C2B174721EE1E3AC006304C0 /* CoreLocation.framework in Frameworks */, + C2B174731EE1E3AC006304C0 /* CoreMedia.framework in Frameworks */, + C2B174741EE1E3AC006304C0 /* CoreTelephony.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + C281E17D1EE5EAF700F2F4A9 /* PrebidMobileTests */ = { + isa = PBXGroup; + children = ( + C281E1931EE5F2AD00F2F4A9 /* PrebidMobileCoreTests */, + C281E1AF1EE5F2E500F2F4A9 /* MockObjects */, + C281E19E1EE5F2DA00F2F4A9 /* Resources */, + C281E1A21EE5F2DA00F2F4A9 /* Stubbing */, + ); + path = PrebidMobileTests; + sourceTree = ""; + }; + C281E1931EE5F2AD00F2F4A9 /* PrebidMobileCoreTests */ = { + isa = PBXGroup; + children = ( + C281E1941EE5F2AD00F2F4A9 /* PBAdUnitTests.m */, + C281E1951EE5F2AD00F2F4A9 /* PBBidManagerTests.m */, + C281E1961EE5F2AD00F2F4A9 /* PBBidResponseTests.m */, + C281E1981EE5F2AD00F2F4A9 /* PBTargetingParamsTests.m */, + ); + path = PrebidMobileCoreTests; + sourceTree = ""; + }; + C281E19E1EE5F2DA00F2F4A9 /* Resources */ = { + isa = PBXGroup; + children = ( + C281E19F1EE5F2DA00F2F4A9 /* pbs_request.json */, + C281E1A01EE5F2DA00F2F4A9 /* pbs_response.json */, + C281E1A11EE5F2DA00F2F4A9 /* PCKeywordsManagerPriceIntervals.txt */, + ); + path = Resources; + sourceTree = ""; + }; + C281E1A21EE5F2DA00F2F4A9 /* Stubbing */ = { + isa = PBXGroup; + children = ( + C281E1A31EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.h */, + C281E1A41EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.m */, + C281E1A51EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.h */, + C281E1A61EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.m */, + C281E1A71EE5F2DA00F2F4A9 /* ANURLConnectionStub.h */, + C281E1A81EE5F2DA00F2F4A9 /* ANURLConnectionStub.m */, + ); + path = Stubbing; + sourceTree = ""; + }; + C281E1AF1EE5F2E500F2F4A9 /* MockObjects */ = { + isa = PBXGroup; + children = ( + C281E1B01EE5F2E500F2F4A9 /* PBMockServerAdapter.h */, + C281E1B11EE5F2E500F2F4A9 /* PBMockServerAdapter.m */, + ); + path = MockObjects; + sourceTree = ""; + }; + C2B16E111EE1BE69006304C0 = { + isa = PBXGroup; + children = ( + C2B16E1D1EE1BE69006304C0 /* PrebidMobile */, + C2B16E881EE1BF1A006304C0 /* PrebidServerAdapter */, + C281E17D1EE5EAF700F2F4A9 /* PrebidMobileTests */, + C2B16EA21EE1BF8A006304C0 /* Frameworks */, + C2B16E1C1EE1BE69006304C0 /* Products */, + ); + sourceTree = ""; + }; + C2B16E1C1EE1BE69006304C0 /* Products */ = { + isa = PBXGroup; + children = ( + C2B16E1B1EE1BE69006304C0 /* PrebidMobile.framework */, + C281E17C1EE5EAF700F2F4A9 /* PrebidMobileTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + C2B16E1D1EE1BE69006304C0 /* PrebidMobile */ = { + isa = PBXGroup; + children = ( + C2B16E4A1EE1BEC4006304C0 /* Categories */, + C2B16E5F1EE1BECA006304C0 /* Logging */, + C2B16E1F1EE1BE69006304C0 /* Info.plist */, + C23386D41EE5DC95002FD404 /* PBAdUnit.h */, + C23386D51EE5DC95002FD404 /* PBAdUnit.m */, + C2B16E261EE1BEA6006304C0 /* PBBannerAdUnit.h */, + C2B16E271EE1BEA6006304C0 /* PBBannerAdUnit.m */, + C2B16E281EE1BEA6006304C0 /* PBBidManager.h */, + C2B16E291EE1BEA6006304C0 /* PBBidManager.m */, + C2B16E441EE1BEB6006304C0 /* PBBidResponse.h */, + C2B16E451EE1BEB6006304C0 /* PBBidResponse.m */, + C2B16E2A1EE1BEA6006304C0 /* PBBidResponseDelegate.h */, + C2B16E2B1EE1BEA6006304C0 /* PBException.h */, + C2B16E2C1EE1BEA6006304C0 /* PBException.m */, + C2B16E2D1EE1BEA6006304C0 /* PBInterstitialAdUnit.h */, + C2B16E2E1EE1BEA6006304C0 /* PBInterstitialAdUnit.m */, + C2B16E2F1EE1BEA6006304C0 /* PBKeywordsManager.h */, + C2B16E301EE1BEA6006304C0 /* PBKeywordsManager.m */, + C2B16E311EE1BEA6006304C0 /* PBTargetingParams.h */, + C2B16E321EE1BEA6006304C0 /* PBTargetingParams.m */, + C23386D01EE5DBFB002FD404 /* PrebidMobile.h */, + C23386D11EE5DBFB002FD404 /* PrebidMobile.m */, + ); + path = PrebidMobile; + sourceTree = ""; + }; + C2B16E4A1EE1BEC4006304C0 /* Categories */ = { + isa = PBXGroup; + children = ( + C2B16E4B1EE1BEC4006304C0 /* NSDictionary+Extension.h */, + C2B16E4C1EE1BEC4006304C0 /* NSDictionary+Extension.m */, + C2B16E4D1EE1BEC4006304C0 /* NSString+Extension.h */, + C2B16E4E1EE1BEC4006304C0 /* NSString+Extension.m */, + C2B16E4F1EE1BEC4006304C0 /* NSTimer+Extension.h */, + C2B16E501EE1BEC4006304C0 /* NSTimer+Extension.m */, + C24B78C21EE7467E0045B454 /* NSObject+Prebid.h */, + C24B78C31EE7467E0045B454 /* NSObject+Prebid.m */, + ); + path = Categories; + sourceTree = ""; + }; + C2B16E5F1EE1BECA006304C0 /* Logging */ = { + isa = PBXGroup; + children = ( + C23FCCEC1EE5E41E00CFFEF0 /* PBLogManager.h */, + C23FCCED1EE5E41E00CFFEF0 /* PBLogManager.m */, + C23FCCE81EE5E3F500CFFEF0 /* PBLogging.h */, + C23FCCE91EE5E3F500CFFEF0 /* PBLogging.m */, + ); + path = Logging; + sourceTree = ""; + }; + C2B16E881EE1BF1A006304C0 /* PrebidServerAdapter */ = { + isa = PBXGroup; + children = ( + C2B16EA11EE1BF4A006304C0 /* PrebidServerModule */, + C23386D81EE5DCDB002FD404 /* PBServerAdapter.h */, + C23386D91EE5DCDB002FD404 /* PBServerAdapter.m */, + ); + path = PrebidServerAdapter; + sourceTree = ""; + }; + C2B16EA11EE1BF4A006304C0 /* PrebidServerModule */ = { + isa = PBXGroup; + children = ( + C2B16E8C1EE1BF1A006304C0 /* PBServerFetcher.h */, + C2B16E8D1EE1BF1A006304C0 /* PBServerFetcher.m */, + C2B16E8F1EE1BF1A006304C0 /* PBServerGlobal.h */, + C2B16E901EE1BF1A006304C0 /* PBServerGlobal.m */, + C2B16E911EE1BF1A006304C0 /* PBServerLocation.h */, + C2B16E921EE1BF1A006304C0 /* PBServerLocation.m */, + C2B16E931EE1BF1A006304C0 /* PBServerReachability.h */, + C2B16E941EE1BF1A006304C0 /* PBServerReachability.m */, + ); + path = PrebidServerModule; + sourceTree = ""; + }; + C2B16EA21EE1BF8A006304C0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C23FCD501EE5EA6D00CFFEF0 /* XCTest.framework */, + C2B1747D1EE1E3CE006304C0 /* QuartzCore.framework */, + C2B1747B1EE1E3C9006304C0 /* SystemConfiguration.framework */, + C2B174791EE1E3C3006304C0 /* UIKit.framework */, + C2B174771EE1E3BC006304C0 /* MediaPlayer.framework */, + C2B174751EE1E3B6006304C0 /* Foundation.framework */, + C2B1746D1EE1E3AC006304C0 /* CoreGraphics.framework */, + C2B1746E1EE1E3AC006304C0 /* CoreLocation.framework */, + C2B1746F1EE1E3AC006304C0 /* CoreMedia.framework */, + C2B174701EE1E3AC006304C0 /* CoreTelephony.framework */, + EFD3C940519B957467FE94E6 /* libPods-PrebidMobile.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + C2B16E181EE1BE69006304C0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + C2B16E391EE1BEA6006304C0 /* PBException.h in Headers */, + C2B16E341EE1BEA6006304C0 /* PBBannerAdUnit.h in Headers */, + C2B16E481EE1BEB6006304C0 /* PBBidResponse.h in Headers */, + C2B16E381EE1BEA6006304C0 /* PBBidResponseDelegate.h in Headers */, + C2B16E3F1EE1BEA6006304C0 /* PBTargetingParams.h in Headers */, + C23FCCEA1EE5E3F500CFFEF0 /* PBLogging.h in Headers */, + C2B16E3D1EE1BEA6006304C0 /* PBKeywordsManager.h in Headers */, + C23FCCEE1EE5E41E00CFFEF0 /* PBLogManager.h in Headers */, + C23386DA1EE5DCDB002FD404 /* PBServerAdapter.h in Headers */, + C23386D61EE5DC95002FD404 /* PBAdUnit.h in Headers */, + C23386D21EE5DBFB002FD404 /* PrebidMobile.h in Headers */, + C2B16E361EE1BEA6006304C0 /* PBBidManager.h in Headers */, + C24B78C41EE7467E0045B454 /* NSObject+Prebid.h in Headers */, + C2B16E3B1EE1BEA6006304C0 /* PBInterstitialAdUnit.h in Headers */, + C2B16E9B1EE1BF1A006304C0 /* PBServerGlobal.h in Headers */, + C2B16E9F1EE1BF1A006304C0 /* PBServerReachability.h in Headers */, + C2B16E9D1EE1BF1A006304C0 /* PBServerLocation.h in Headers */, + C2B16E981EE1BF1A006304C0 /* PBServerFetcher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + C281E17B1EE5EAF700F2F4A9 /* PrebidMobileTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = C281E1861EE5EAF700F2F4A9 /* Build configuration list for PBXNativeTarget "PrebidMobileTests" */; + buildPhases = ( + C281E1781EE5EAF700F2F4A9 /* Sources */, + C281E1791EE5EAF700F2F4A9 /* Frameworks */, + C281E17A1EE5EAF700F2F4A9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C281E1831EE5EAF700F2F4A9 /* PBXTargetDependency */, + ); + name = PrebidMobileTests; + productName = PrebidMobileTests; + productReference = C281E17C1EE5EAF700F2F4A9 /* PrebidMobileTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + C2B16E1A1EE1BE69006304C0 /* PrebidMobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2B16E231EE1BE69006304C0 /* Build configuration list for PBXNativeTarget "PrebidMobile" */; + buildPhases = ( + C2B16E161EE1BE69006304C0 /* Sources */, + C2B16E171EE1BE69006304C0 /* Frameworks */, + C2B16E181EE1BE69006304C0 /* Headers */, + C2B16E191EE1BE69006304C0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PrebidMobile; + productName = PrebidMobile; + productReference = C2B16E1B1EE1BE69006304C0 /* PrebidMobile.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + C2B16E121EE1BE69006304C0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = "Nicole Hedley"; + TargetAttributes = { + C281E17B1EE5EAF700F2F4A9 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = HR94J6TSB3; + ProvisioningStyle = Automatic; + }; + C2B16E1A1EE1BE69006304C0 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = HR94J6TSB3; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = C2B16E151EE1BE69006304C0 /* Build configuration list for PBXProject "PrebidMobile" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = C2B16E111EE1BE69006304C0; + productRefGroup = C2B16E1C1EE1BE69006304C0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + C2B16E1A1EE1BE69006304C0 /* PrebidMobile */, + C281E17B1EE5EAF700F2F4A9 /* PrebidMobileTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + C281E17A1EE5EAF700F2F4A9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C281E1AB1EE5F2DA00F2F4A9 /* PCKeywordsManagerPriceIntervals.txt in Resources */, + C281E1AA1EE5F2DA00F2F4A9 /* pbs_response.json in Resources */, + C281E1A91EE5F2DA00F2F4A9 /* pbs_request.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B16E191EE1BE69006304C0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + C281E1781EE5EAF700F2F4A9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C281E1AE1EE5F2DA00F2F4A9 /* ANURLConnectionStub.m in Sources */, + C281E1AD1EE5F2DA00F2F4A9 /* ANHTTPStubURLProtocol.m in Sources */, + C281E1B21EE5F2E500F2F4A9 /* PBMockServerAdapter.m in Sources */, + C281E19B1EE5F2AD00F2F4A9 /* PBBidResponseTests.m in Sources */, + C281E19D1EE5F2AD00F2F4A9 /* PBTargetingParamsTests.m in Sources */, + C281E1991EE5F2AD00F2F4A9 /* PBAdUnitTests.m in Sources */, + C281E19A1EE5F2AD00F2F4A9 /* PBBidManagerTests.m in Sources */, + C281E1AC1EE5F2DA00F2F4A9 /* ANHTTPStubbingManager.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2B16E161EE1BE69006304C0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + C22E7CE61EE70E19007B31F4 /* NSTimer+Extension.m in Sources */, + C23386D31EE5DBFB002FD404 /* PrebidMobile.m in Sources */, + C2B16EA01EE1BF1A006304C0 /* PBServerReachability.m in Sources */, + C2B16E561EE1BEC4006304C0 /* NSDictionary+Extension.m in Sources */, + C23386DB1EE5DCDB002FD404 /* PBServerAdapter.m in Sources */, + C2B16E9C1EE1BF1A006304C0 /* PBServerGlobal.m in Sources */, + C2B16E3C1EE1BEA6006304C0 /* PBInterstitialAdUnit.m in Sources */, + C23FCCEB1EE5E3F500CFFEF0 /* PBLogging.m in Sources */, + C2B16E401EE1BEA6006304C0 /* PBTargetingParams.m in Sources */, + C2B16E9E1EE1BF1A006304C0 /* PBServerLocation.m in Sources */, + C2B16E351EE1BEA6006304C0 /* PBBannerAdUnit.m in Sources */, + C23386D71EE5DC95002FD404 /* PBAdUnit.m in Sources */, + C24B78C51EE7467E0045B454 /* NSObject+Prebid.m in Sources */, + C2B16E581EE1BEC4006304C0 /* NSString+Extension.m in Sources */, + C2B16E3A1EE1BEA6006304C0 /* PBException.m in Sources */, + C2B16E491EE1BEB6006304C0 /* PBBidResponse.m in Sources */, + C23FCCEF1EE5E41E00CFFEF0 /* PBLogManager.m in Sources */, + C2B16E371EE1BEA6006304C0 /* PBBidManager.m in Sources */, + C2B16E3E1EE1BEA6006304C0 /* PBKeywordsManager.m in Sources */, + C2B16E991EE1BF1A006304C0 /* PBServerFetcher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + C281E1831EE5EAF700F2F4A9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2B16E1A1EE1BE69006304C0 /* PrebidMobile */; + targetProxy = C281E1821EE5EAF700F2F4A9 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + C281E1841EE5EAF700F2F4A9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = HR94J6TSB3; + INFOPLIST_FILE = PrebidMobile/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + C281E1851EE5EAF700F2F4A9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = HR94J6TSB3; + INFOPLIST_FILE = PrebidMobile/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobileTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + C2B16E211EE1BE69006304C0 /* 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++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "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.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + C2B16E221EE1BE69006304C0 /* 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++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + 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.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C2B16E241EE1BE69006304C0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = HR94J6TSB3; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ""; + INFOPLIST_FILE = PrebidMobile/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/lib/DFPSDK $(PROJECT_DIR)/lib/MoPubSDK"; + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobile; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + C2B16E251EE1BE69006304C0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CODE_SIGN_IDENTITY = ""; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = HR94J6TSB3; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREPROCESSOR_DEFINITIONS = ""; + INFOPLIST_FILE = PrebidMobile/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/lib/DFPSDK $(PROJECT_DIR)/lib/MoPubSDK"; + MACH_O_TYPE = staticlib; + PRODUCT_BUNDLE_IDENTIFIER = AppNexus.PrebidMobile; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + C281E1861EE5EAF700F2F4A9 /* Build configuration list for PBXNativeTarget "PrebidMobileTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C281E1841EE5EAF700F2F4A9 /* Debug */, + C281E1851EE5EAF700F2F4A9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2B16E151EE1BE69006304C0 /* Build configuration list for PBXProject "PrebidMobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2B16E211EE1BE69006304C0 /* Debug */, + C2B16E221EE1BE69006304C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2B16E231EE1BE69006304C0 /* Build configuration list for PBXNativeTarget "PrebidMobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C2B16E241EE1BE69006304C0 /* Debug */, + C2B16E251EE1BE69006304C0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = C2B16E121EE1BE69006304C0 /* Project object */; +} diff --git a/sdk/PrebidMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sdk/PrebidMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..c8164f534 --- /dev/null +++ b/sdk/PrebidMobile.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/sdk/PrebidMobile.xcodeproj/xcshareddata/xcschemes/PrebidMobileTests.xcscheme b/sdk/PrebidMobile.xcodeproj/xcshareddata/xcschemes/PrebidMobileTests.xcscheme new file mode 100644 index 000000000..7bf31c92d --- /dev/null +++ b/sdk/PrebidMobile.xcodeproj/xcshareddata/xcschemes/PrebidMobileTests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/PrebidMobile/Categories/NSDictionary+Extension.h b/sdk/PrebidMobile/Categories/NSDictionary+Extension.h new file mode 100644 index 000000000..cce03e634 --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSDictionary+Extension.h @@ -0,0 +1,37 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDictionary (Extension) + ++ (nonnull instancetype)dictionaryWithString:(nonnull NSString *)string + withKeyValueSeparatedByString:(nonnull NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(nonnull NSString *)keyValuePairSeparator; + +- (nonnull instancetype)initWithString:(nonnull NSString *)string + keyValueSeparatedByString:(nonnull NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(nonnull NSString *)keyValuePairSeparator; + +- (nonnull NSArray *)arrayRepresentationOfKeyValueSeparatedByString:(nonnull NSString *)keyValueSeparator; + +- (nonnull NSString *)stringRepresentationOfKeyValueSeparatedByString:(nonnull NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(nonnull NSString *)keyValuePairSeparator; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/PrebidMobile/Categories/NSDictionary+Extension.m b/sdk/PrebidMobile/Categories/NSDictionary+Extension.m new file mode 100644 index 000000000..f0e8235cb --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSDictionary+Extension.m @@ -0,0 +1,69 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "NSDictionary+Extension.h" + +@implementation NSDictionary (Extension) + ++ (instancetype)dictionaryWithString:(NSString *)string + withKeyValueSeparatedByString:(NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(NSString *)keyValuePairSeparator { + NSDictionary *newDictionary = [[NSDictionary alloc] initWithString:string + keyValueSeparatedByString:keyValueSeparator + andKeyValuePairSeparatedByString:keyValuePairSeparator]; + return (newDictionary); +} + +- (instancetype)initWithString:(NSString *)string + keyValueSeparatedByString:(NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(NSString *)keyValuePairSeparator { + NSArray *__nonnull keyValueStrings = [string componentsSeparatedByString:@","]; + NSMutableArray *__nonnull keys = [[NSMutableArray alloc] initWithCapacity:[keyValueStrings count]]; + NSMutableArray *__nonnull values = [[NSMutableArray alloc] initWithCapacity:[keyValueStrings count]]; + + for (NSString *keyValueString in keyValueStrings) { + NSArray *__nonnull keyValuePair = [keyValueString componentsSeparatedByString:@":"]; + NSString *__nonnull key = keyValuePair[0]; + NSString *__nonnull value = keyValuePair[1]; + + [keys addObject:key]; + [values addObject:value]; + } + if ((self = [self initWithObjects:values forKeys:keys])) { + } + + return (self); +} + +- (NSArray *)arrayRepresentationOfKeyValueSeparatedByString:(NSString *)keyValueSeparator { + NSMutableArray *__nullable keyValueStrings = [[NSMutableArray alloc] initWithCapacity:[self count]]; + + for (NSString *__nonnull key in [self allKeys]) { + NSString *__nonnull value = self[key]; + NSString *__nonnull keyValueString = [[NSString alloc] initWithFormat:@"%@%@%@", key, keyValueSeparator, value]; + + [keyValueStrings addObject:keyValueString]; + } + return (keyValueStrings); +} + +- (NSString *)stringRepresentationOfKeyValueSeparatedByString:(NSString *)keyValueSeparator + andKeyValuePairSeparatedByString:(NSString *)keyValuePairSeparator { + NSArray *__nonnull keyValueStringArray = [self arrayRepresentationOfKeyValueSeparatedByString:keyValueSeparator]; + + return ([keyValueStringArray componentsJoinedByString:keyValuePairSeparator]); +} + +@end diff --git a/sdk/PrebidMobile/Categories/NSObject+Prebid.h b/sdk/PrebidMobile/Categories/NSObject+Prebid.h new file mode 100644 index 000000000..392783032 --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSObject+Prebid.h @@ -0,0 +1,23 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import "PBAdUnit.h" + +@interface NSObject (Prebid) + +@property (nonatomic) PBAdUnit *pb_identifier; + +@end diff --git a/sdk/PrebidMobile/Categories/NSObject+Prebid.m b/sdk/PrebidMobile/Categories/NSObject+Prebid.m new file mode 100644 index 000000000..ea22f90c0 --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSObject+Prebid.m @@ -0,0 +1,179 @@ + +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import "PBBidManager.h" +#import "NSObject+Prebid.h" +#import "NSString+Extension.h" +#import + +@implementation NSObject (Prebid) + +@dynamic pb_identifier; + ++ (void)load { + static dispatch_once_t loadToken; + dispatch_once(&loadToken, ^{ + dispatch_async(dispatch_get_main_queue(), ^{ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + [NSClassFromString(@"GADSlot") pb_swizzleInstanceSelector:@selector(requestParameters) + withSelector:@selector(pb_requestParameters)]; + [NSClassFromString(@"MPBannerAdManager") pb_swizzleInstanceSelector:@selector(loadAd) + withSelector:@selector(pb_loadAd)]; + [NSClassFromString(@"MPBannerAdManager") pb_swizzleInstanceSelector:@selector(forceRefreshAd) + withSelector:@selector(pb_forceRefreshAd)]; + [NSClassFromString(@"MPBannerAdManager") pb_swizzleInstanceSelector:@selector(applicationWillEnterForeground) + withSelector:@selector(pb_applicationWillEnterForeground)]; + [NSClassFromString(@"MPInterstitialAdManager") pb_swizzleInstanceSelector:@selector(loadInterstitialWithAdUnitID:keywords:location:testing:) + withSelector:@selector(pb_loadInterstitialWithAdUnitID:keywords:location:testing:)]; +#pragma clang diagnostic pop + }); + }); +} + ++ (void)pb_swizzleInstanceSelector:(SEL)originalSelector + withSelector:(SEL)swizzledSelector { + Class class = [self class]; + + Method originalMethod = class_getInstanceMethod(class, originalSelector); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); + + BOOL didAddMethod = class_addMethod(class, + originalSelector, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + if (didAddMethod) { + class_replaceMethod(class, + swizzledSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } +} + +// dfp ad slot +- (id)pb_requestParameters { + __block id requestParameters = [self pb_requestParameters]; + + SEL adEventDelegateSel = NSSelectorFromString(@"adEventDelegate"); + if ([self respondsToSelector:adEventDelegateSel]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id adEventDelegate = [self performSelector:adEventDelegateSel]; + NSDictionary *keywordsPairs; + + SEL getPb_identifier = NSSelectorFromString(@"pb_identifier"); + if ([adEventDelegate respondsToSelector:getPb_identifier]) { + PBAdUnit *adUnit = (PBAdUnit *)[adEventDelegate performSelector:getPb_identifier]; +#pragma clang diagnostic pop + + keywordsPairs = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:adUnit]; + requestParameters = [[PBBidManager sharedInstance] addPrebidParameters:requestParameters withKeywords:keywordsPairs]; + } + } + return requestParameters; +} + +// mopub banner +- (void)pb_applicationWillEnterForeground { + SEL getDelegate = NSSelectorFromString(@"delegate"); + if ([self respondsToSelector:getDelegate]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id delegate = [self performSelector:getDelegate]; + SEL getBannerAd = NSSelectorFromString(@"banner"); + if ([delegate respondsToSelector:getBannerAd]) { + NSObject *adView = [delegate performSelector:getBannerAd]; +#pragma clang diagnostic pop + [[PBBidManager sharedInstance] setBidOnAdObject:adView]; + [self pb_applicationWillEnterForeground]; + [[PBBidManager sharedInstance] clearBidOnAdObject:adView]; + } + }; +} + +- (void)pb_loadAd { + SEL getDelegate = NSSelectorFromString(@"delegate"); + if ([self respondsToSelector:getDelegate]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id delegate = [self performSelector:getDelegate]; + SEL getBannerAd = NSSelectorFromString(@"banner"); + if ([delegate respondsToSelector:getBannerAd]) { + NSObject *adView = [delegate performSelector:getBannerAd]; +#pragma clang diagnostic pop + [[PBBidManager sharedInstance] setBidOnAdObject:adView]; + [self pb_loadAd]; + [[PBBidManager sharedInstance] clearBidOnAdObject:adView]; + } + }; +} + +- (void)pb_forceRefreshAd { + SEL getDelegate = NSSelectorFromString(@"delegate"); + if ([self respondsToSelector:getDelegate]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id delegate = [self performSelector:getDelegate]; + SEL getBannerAd = NSSelectorFromString(@"banner"); + if ([delegate respondsToSelector:getBannerAd]) { + NSObject *adView = [delegate performSelector:getBannerAd]; +#pragma clang diagnostic pop + [[PBBidManager sharedInstance] setBidOnAdObject:adView]; + [self pb_forceRefreshAd]; + [[PBBidManager sharedInstance] clearBidOnAdObject:adView]; + } + }; +} + +// mopub interstitial +- (void)pb_loadInterstitialWithAdUnitID:(NSString *)ID keywords:(NSString *)keywords location:(CLLocation *)location testing:(BOOL)testing { + SEL getDelegate = NSSelectorFromString(@"delegate"); + if ([self respondsToSelector:getDelegate]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + id delegate = [self performSelector:getDelegate]; + SEL getInterstitialAd = NSSelectorFromString(@"interstitialAdController"); + if ([delegate respondsToSelector:getInterstitialAd]) { + NSObject *interstitialAd = [delegate performSelector:getInterstitialAd]; + SEL getAdUnitId = NSSelectorFromString(@"adUnitId"); + SEL getKeywords = NSSelectorFromString(@"keywords"); + SEL getLocation = NSSelectorFromString(@"location"); + if ([delegate respondsToSelector:getAdUnitId] && [delegate respondsToSelector:getKeywords] && [delegate respondsToSelector:getLocation]) { + NSString *adUnitId = (NSString *)[interstitialAd performSelector:getAdUnitId]; + CLLocation *location = (CLLocation *)[interstitialAd performSelector:getLocation]; + [[PBBidManager sharedInstance] setBidOnAdObject:interstitialAd]; + NSString *keywords = (NSString *)[interstitialAd performSelector:getKeywords]; + [self pb_loadInterstitialWithAdUnitID:adUnitId keywords:keywords location:location testing:testing]; +#pragma clang diagnostic pop + [[PBBidManager sharedInstance] clearBidOnAdObject:interstitialAd]; + } + } + }; +} + +- (void)setPb_identifier:(PBAdUnit *)pb_identifier { + objc_setAssociatedObject(self, @selector(pb_identifier), pb_identifier, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (PBAdUnit *)pb_identifier { + return objc_getAssociatedObject(self, @selector(pb_identifier)); +} + +@end diff --git a/sdk/PrebidMobile/Categories/NSString+Extension.h b/sdk/PrebidMobile/Categories/NSString+Extension.h new file mode 100644 index 000000000..9b2a9811e --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSString+Extension.h @@ -0,0 +1,23 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface NSString (Extension) + +- (NSString *)urlencode; +- (NSString *)urldecode; + +@end diff --git a/sdk/PrebidMobile/Categories/NSString+Extension.m b/sdk/PrebidMobile/Categories/NSString+Extension.m new file mode 100644 index 000000000..3c851f3eb --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSString+Extension.m @@ -0,0 +1,47 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "NSString+Extension.h" + +@implementation NSString (Extension) + +- (NSString *)urlencode { + + NSMutableString *output = [NSMutableString string]; + const unsigned char *source = (const unsigned char *)[self UTF8String]; + int sourceLen = (int)strlen((const char *)source); + for (int i = 0; i < sourceLen; ++i) { + const unsigned char thisChar = source[i]; + if (thisChar == ' ') { + [output appendString:@"+"]; + } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || + (thisChar >= 'a' && thisChar <= 'z') || + (thisChar >= 'A' && thisChar <= 'Z') || + (thisChar >= '0' && thisChar <= '9')) { + [output appendFormat:@"%c", thisChar]; + } else { + [output appendFormat:@"%%%02X", thisChar]; + } + } + return output; +} + +- (NSString *)urldecode { + NSString *result = [(NSString *)self stringByReplacingOccurrencesOfString:@"+" withString:@" "]; + result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + return result; +} + +@end diff --git a/sdk/PrebidMobile/Categories/NSTimer+Extension.h b/sdk/PrebidMobile/Categories/NSTimer+Extension.h new file mode 100644 index 000000000..1752073ee --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSTimer+Extension.h @@ -0,0 +1,24 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface NSTimer (Extension) + ++ (NSTimer *)pb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval + block:(void(^)())block + repeats:(BOOL)repeats; + +@end diff --git a/sdk/PrebidMobile/Categories/NSTimer+Extension.m b/sdk/PrebidMobile/Categories/NSTimer+Extension.m new file mode 100644 index 000000000..5301592d0 --- /dev/null +++ b/sdk/PrebidMobile/Categories/NSTimer+Extension.m @@ -0,0 +1,37 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "NSTimer+Extension.h" + +@implementation NSTimer (Extension) + ++ (NSTimer *)pb_scheduledTimerWithTimeInterval:(NSTimeInterval)interval + block:(void(^)())block + repeats:(BOOL)repeats { + return [self scheduledTimerWithTimeInterval:interval + target:self + selector:@selector(pb_blockInvoke:) + userInfo:[block copy] + repeats:repeats]; +} + ++ (void)pb_blockInvoke:(NSTimer *)timer { + if([timer userInfo]) { + void (^block)() = (void (^)())[timer userInfo]; + block(); + } +} + +@end diff --git a/sdk/PrebidMobile/Info.plist b/sdk/PrebidMobile/Info.plist new file mode 100644 index 000000000..fbe1e6b31 --- /dev/null +++ b/sdk/PrebidMobile/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/sdk/PrebidMobile/Logging/PBLogManager.h b/sdk/PrebidMobile/Logging/PBLogManager.h new file mode 100644 index 000000000..f6be71eb5 --- /dev/null +++ b/sdk/PrebidMobile/Logging/PBLogManager.h @@ -0,0 +1,49 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +/** + The lower the filter level, the more logs will be shown. + For example, `PBLogLevelInfo` will display messages from + `PBLogLevelInfo,` `PBLogLevelWarn,` and `PBLogLevelError.` + The default level is `PBLogLevelWarn` + */ + +#import + +typedef NS_ENUM(NSUInteger, PBLogLevel) { + PBLogLevelAll = 0, + PBLogLevelTrace = 10, + PBLogLevelDebug = 20, + PBLogLevelInfo = 30, + PBLogLevelWarn = 40, + PBLogLevelError = 50, + PBLogLevelOff = 60 +}; + +/** + Use the `PBLogManager` methods to set the desired level of log filter. + */ +@interface PBLogManager : NSObject + +/** + Gets the current log filter level. + */ ++ (PBLogLevel)getPBLogLevel; + +/** + Sets the log filter level. + */ ++ (void)setPBLogLevel:(PBLogLevel)level; + +@end diff --git a/sdk/PrebidMobile/Logging/PBLogManager.m b/sdk/PrebidMobile/Logging/PBLogManager.m new file mode 100644 index 000000000..344b2f8c2 --- /dev/null +++ b/sdk/PrebidMobile/Logging/PBLogManager.m @@ -0,0 +1,30 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBLogManager.h" + +static PBLogLevel PBLOG_LEVEL = PBLogLevelWarn; + +@implementation PBLogManager + ++ (PBLogLevel)getPBLogLevel { + return PBLOG_LEVEL; +} + ++ (void)setPBLogLevel:(PBLogLevel)level { + PBLOG_LEVEL = level; +} + +@end diff --git a/sdk/PrebidMobile/Logging/PBLogging.h b/sdk/PrebidMobile/Logging/PBLogging.h new file mode 100644 index 000000000..86a701042 --- /dev/null +++ b/sdk/PrebidMobile/Logging/PBLogging.h @@ -0,0 +1,51 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBLogManager.h" + +#define PB_DEBUG_MODE 1 + +/** + * the message that is logged by the logging module + */ +extern NSString *const kPBLogMessageKey; + +/** + * specifies if the information provided by the message is a info or warning or error + */ +extern NSString *const kPBLogMessageLevelKey; + +#if PB_DEBUG_MODE +void _PBLog(PBLogLevel level, NSString *format, ...) NS_FORMAT_FUNCTION(2, 3); +#define PBLogTrace(...) _PBLog(PBLogLevelTrace, __VA_ARGS__) +#define PBLogDebug(...) _PBLog(PBLogLevelDebug, __VA_ARGS__) +#define PBLogInfo(...) _PBLog(PBLogLevelInfo, __VA_ARGS__) +#define PBLogWarn(...) _PBLog(PBLogLevelWarn, __VA_ARGS__) +#define PBLogError(...) _PBLog(PBLogLevelError, __VA_ARGS__) + +#else + +#define PCLogTrace(...) \ +{} +#define PCLogDebug(...) \ +{} +#define PCLogInfo(...) \ +{} +#define PCLogWarn(...) \ +{} +#define PCLogError(...) \ +{} + +#endif diff --git a/sdk/PrebidMobile/Logging/PBLogging.m b/sdk/PrebidMobile/Logging/PBLogging.m new file mode 100644 index 000000000..a321c7078 --- /dev/null +++ b/sdk/PrebidMobile/Logging/PBLogging.m @@ -0,0 +1,32 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBLogging.h" + +NSString *const kPBLoggingNotification = @"kPBLoggingNotification"; +NSString *const kPBLogMessageKey = @"kPBLogMessageKey"; +NSString *const kPBLogMessageLevelKey = @"kPBLogMessageLevelKey"; + +void _PBLog(PBLogLevel level, NSString *format, ...) { + if ([PBLogManager getPBLogLevel] <= level) { + format = [NSString stringWithFormat:@"Prebid: %@", format]; + va_list args; + va_start(args, format); + NSString *fullString = [[NSString alloc] initWithFormat:format + arguments:args]; + va_end(args); + NSLog(@"%@", fullString); + } +} diff --git a/sdk/PrebidMobile/PBAdUnit.h b/sdk/PrebidMobile/PBAdUnit.h new file mode 100644 index 000000000..5d11a53a0 --- /dev/null +++ b/sdk/PrebidMobile/PBAdUnit.h @@ -0,0 +1,95 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@protocol CGSize; + +/** + * A generic ad unit object that the user creates to configure the ad sizes. These are passed to the + * prebid server adapter and ads are fetched for each ad unit + */ +@interface PBAdUnit : NSObject + +/** + * uuid is a auto generated id for each of the ad unit created. + */ +@property (nonatomic, readonly) NSString *__nullable uuid; + +/** + * identifier is the developer identity for an ad unit. identifier needs to be unique for each ad unit. + */ +@property (nonatomic, readonly) NSString *__nullable identifier; + +/** + * configId is the prebid server config id for an ad unit. configId needs to be unique for each ad unit. + */ +@property (nonatomic, readonly) NSString *__nullable configId; + +/** + * adSizes is a list of CGSizes (widths & heights) that needs to be fetched for the ad unit. + */ +@property (nonatomic, readonly) NSArray *__nullable adSizes; + +/** + * An enumeration object that holds different types of ad units available to be configured for + * the ad units can be configured only for banner, interstitial or native ads + */ +typedef NS_ENUM(NSInteger, PBAdUnitType) { + PBAdUnitTypeBanner, + PBAdUnitTypeInterstitial, + PBAdUnitTypeNative +}; + +@property (nonatomic, readonly) PBAdUnitType adType; + +/** + * initializes the PBAdUnit object with the identifier & the adUnit type + * @param identifier : identifier is the developer identity for the ad unit + * @param type : type of adUnit created. Can be banner, interstitial or native + * @param configId : config id for demand sources from prebid server + */ +- (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier andAdType:(PBAdUnitType)type andConfigId:(nonnull NSString *)configId; + +/** + * addSize adds the size object to the adUnit object created + * @param adSize : width & height of the ad that needs to be fetched + */ +- (void)addSize:(CGSize)adSize; + +/** + * generatesUUID generates a new uuid on the ad unit + */ +- (void)generateUUID; + +/** + * shouldExpireAllBids returns a boolean if the adUnit should expire all bids given a time + * @param time : time is the current time + */ +- (BOOL)shouldExpireAllBids:(NSTimeInterval)time; + +/** + * setTimeIntervalToExpireAllBids sets the expiryTime for all bids on this ad unit + * @param expiryTime : expiryTime is the time that the bids will all expire + */ +- (void)setTimeIntervalToExpireAllBids:(NSTimeInterval)expiryTime; + +/** + * isEqualToAdUnit tests for equality to another adUnit. + * two ad units are considered equal if their identifiers are equal + */ +- (BOOL)isEqualToAdUnit:(nonnull PBAdUnit *)otherAdUnit; + +@end diff --git a/sdk/PrebidMobile/PBAdUnit.m b/sdk/PrebidMobile/PBAdUnit.m new file mode 100644 index 000000000..b88b3ae92 --- /dev/null +++ b/sdk/PrebidMobile/PBAdUnit.m @@ -0,0 +1,79 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBAdUnit.h" + +@interface PBAdUnit () + +#pragma mark Properties +@property (nonatomic, readwrite, strong) NSString *__nonnull uuid; +@property (nonatomic, readwrite, strong) NSString *__nonnull identifier; +@property (nonatomic, readwrite, strong) NSString *__nonnull configId; +@property (nonatomic, readwrite, strong) NSMutableArray *__nullable adSizes; + +@property (nonatomic, assign) PBAdUnitType adType; +@property (nonatomic, assign) NSTimeInterval timeToExpireAllBids; + +@end + +@implementation PBAdUnit + +#pragma mark Initialization +- (nonnull instancetype)initWithIdentifier:(nonnull NSString *)identifier andAdType:(PBAdUnitType)type andConfigId:(nonnull NSString *)configId { + if ((self = [super init])) { + [self generateUUID]; + _identifier = [identifier copy]; + _adType = type; + _timeToExpireAllBids = 0; + _configId = configId; + } + return (self); +} + +#pragma mark Methods +- (NSArray *)adSizes { + return _adSizes; +} + +- (void)addSize:(CGSize)adSize { + if (_adSizes == nil) { + _adSizes = [[NSMutableArray alloc] init]; + } + [_adSizes addObject:[NSValue valueWithCGSize:adSize]]; +} + +- (void)setAdUnitType:(PBAdUnitType)type { + _adType = type; +} + +- (void)generateUUID { + _uuid = [[NSUUID UUID] UUIDString]; +} + +- (BOOL)shouldExpireAllBids:(NSTimeInterval)currentTime { + return currentTime > self.timeToExpireAllBids; +} + +- (void)setTimeIntervalToExpireAllBids:(NSTimeInterval)expiryTime { + if (expiryTime > self.timeToExpireAllBids) { + self.timeToExpireAllBids = expiryTime; + } +} + +- (BOOL)isEqualToAdUnit:(PBAdUnit *)otherAdUnit { + return [self.identifier isEqualToString:otherAdUnit.identifier]; +} + +@end diff --git a/sdk/PrebidMobile/PBBannerAdUnit.h b/sdk/PrebidMobile/PBBannerAdUnit.h new file mode 100644 index 000000000..de0d61632 --- /dev/null +++ b/sdk/PrebidMobile/PBBannerAdUnit.h @@ -0,0 +1,33 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBAdUnit.h" + +@interface PBBannerAdUnit : PBAdUnit + +/** + * Initializes the BannerAdUnit with an identifier + * @param identifier : the identifier is a developer specific identity given for each of the ad unit created + * @param configId : the config id with the demand sources from prebid server + */ +- (nonnull instancetype)initWithAdUnitIdentifier:(nonnull NSString *)identifier andConfigId:(nonnull NSString *)configId; + +/** + * addSize adds the size object to the BannerAdUnit object created + * @param adSize : width & height of the ad that needs to be fetched + */ +- (void)addSize:(CGSize)adSize; + +@end diff --git a/sdk/PrebidMobile/PBBannerAdUnit.m b/sdk/PrebidMobile/PBBannerAdUnit.m new file mode 100644 index 000000000..7e3c8048a --- /dev/null +++ b/sdk/PrebidMobile/PBBannerAdUnit.m @@ -0,0 +1,28 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBannerAdUnit.h" + +@implementation PBBannerAdUnit + +- (nonnull instancetype)initWithAdUnitIdentifier:(nonnull NSString *)identifier andConfigId:(nonnull NSString *)configId { + return [super initWithIdentifier:identifier andAdType:PBAdUnitTypeBanner andConfigId:configId]; +} + +- (void)addSize:(CGSize)adSize { + [super addSize:adSize]; +} + +@end diff --git a/sdk/PrebidMobile/PBBidManager.h b/sdk/PrebidMobile/PBBidManager.h new file mode 100644 index 000000000..e47a44fea --- /dev/null +++ b/sdk/PrebidMobile/PBBidManager.h @@ -0,0 +1,72 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBAdUnit.h" +#import "PBServerAdapter.h" + +@class PBBidResponse; + +static int const kPCAttachTopBidTimeoutIntervalMS = 50; +static int const kPCAttachTopBidMaxTimeoutMS = 1500; + +@interface PBBidManager : NSObject + +/** + * shared instance of the PBBidManager class + */ ++ (nonnull instancetype)sharedInstance; + +#ifdef DEBUG ++ (void)resetSharedInstance; +#endif + +/** + * Registers all the ad units with the prebid server account id, and starts the auction for each ad unit + */ +- (void)registerAdUnits:(nonnull NSArray *)adUnits withAccountId:(nonnull NSString *)accountId; + +/** + * Returns the ad unit for the string identifier + */ +- (nullable PBAdUnit *)adUnitByIdentifier:(nonnull NSString *)identifier; + +/** + * asserts that the AdUnit is registered before the bidding takes place + * @param identifier : the ad unit identity specified by the developer + */ +- (void)assertAdUnitRegistered:(nonnull NSString *)identifier; + +/** + * Returns the keywords pairs for the top bid of an adUnit + */ +- (nullable NSDictionary *)keywordsForWinningBidForAdUnit:(nonnull PBAdUnit *)adUnit; + +- (nonnull NSDictionary *)addPrebidParameters:(nonnull NSDictionary *)requestParameters + withKeywords:(nonnull NSDictionary *)keywordsPairs; + +/** + * helper method for ad server adapter attachTopBid method + * @param adUnitIdentifier : the ad unit id + * @param timeoutInMS : the timeout in milliseconds to wait for a bid + * @param handler : the code to be executed upon timeout or successful bid + */ +- (void)attachTopBidHelperForAdUnitId:(nonnull NSString *)adUnitIdentifier + andTimeout:(int)timeoutInMS + completionHandler:(nullable void (^)(void))handler; + +- (void)setBidOnAdObject:(nonnull NSObject *)adObject; +- (void)clearBidOnAdObject:(nonnull NSObject *)adObject; + +@end diff --git a/sdk/PrebidMobile/PBBidManager.m b/sdk/PrebidMobile/PBBidManager.m new file mode 100644 index 000000000..d26f17704 --- /dev/null +++ b/sdk/PrebidMobile/PBBidManager.m @@ -0,0 +1,334 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "NSObject+Prebid.h" +#import "NSString+Extension.h" +#import "NSTimer+Extension.h" +#import "PBBidManager.h" +#import "PBBidResponse.h" +#import "PBBidResponseDelegate.h" +#import "PBException.h" +#import "PBKeywordsManager.h" +#import "PBLogging.h" +#import "PBServerAdapter.h" + +static NSTimeInterval const kBidExpiryTimerInterval = 30; + +@interface PBBidManager () + +@property id delegate; +- (void)saveBidResponses:(nonnull NSArray *)bidResponse; + +@property (nonatomic, assign) NSTimeInterval topBidExpiryTime; +@property (nonatomic, strong) PBServerAdapter *demandAdapter; + +@property (nonatomic, strong) NSMutableSet *adUnits; +@property (nonatomic, strong) NSMutableDictionary *> *__nullable bidsMap; + +@end + +#pragma mark PBBidResponseDelegate Implementation + +@interface PBBidResponseDelegateImplementation : NSObject + +@end + +@implementation PBBidResponseDelegateImplementation + +- (void)didReceiveSuccessResponse:(nonnull NSArray *)bids { + [[PBBidManager sharedInstance] saveBidResponses:bids]; +} + +- (void)didCompleteWithError:(nonnull NSError *)error { + if (error) { + PBLogDebug(@"Bid Failure: %@", [error localizedDescription]); + } +} + +@end + +@implementation PBBidManager + +@synthesize delegate; + +static PBBidManager *sharedInstance = nil; +static dispatch_once_t onceToken; + +#pragma mark Public API Methods + ++ (instancetype)sharedInstance { + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + [sharedInstance setDelegate:[[PBBidResponseDelegateImplementation alloc] init]]; + }); + return sharedInstance; +} + ++ (void)resetSharedInstance { + onceToken = 0; + sharedInstance = nil; +} + +- (void)registerAdUnits:(nonnull NSArray *)adUnits withAccountId:(nonnull NSString *)accountId { + if (_adUnits == nil) { + _adUnits = [[NSMutableSet alloc] init]; + } + _bidsMap = [[NSMutableDictionary alloc] init]; + _demandAdapter = [[PBServerAdapter alloc] initWithAccountId:accountId]; + for (id adUnit in adUnits) { + [self registerAdUnit:adUnit]; + } + [self startPollingBidsExpiryTimer]; + [self requestBidsForAdUnits:adUnits]; +} + +- (nullable PBAdUnit *)adUnitByIdentifier:(nonnull NSString *)identifier { + NSArray *adUnits = [_adUnits allObjects]; + for (PBAdUnit *adUnit in adUnits) { + if ([[adUnit identifier] isEqualToString:identifier]) { + return adUnit; + } + } + return nil; +} + +- (void)assertAdUnitRegistered:(NSString *)identifier { + PBAdUnit *adUnit = [self adUnitByIdentifier:identifier]; + if (adUnit == nil) { + // If there is no registered ad unit we can't complete the bidding + // so throw an exception + @throw [PBException exceptionWithName:PBAdUnitNotRegisteredException]; + } +} + +- (nullable NSDictionary *)keywordsForWinningBidForAdUnit:(nonnull PBAdUnit *)adUnit { + NSArray *bids = [_bidsMap objectForKey:adUnit.identifier]; + PBBidResponse *bid = [self winningBidForAdUnit:adUnit]; + if (bid) { + PBLogDebug(@"Bid is available to create keywords"); + NSMutableDictionary *keywords = [[NSMutableDictionary alloc] init]; + for (PBBidResponse *bidResp in bids) { + [keywords addEntriesFromDictionary:bidResp.customKeywords]; + } + return keywords; + } + PBLogDebug(@"No bid available to create keywords"); + return nil; +} + +- (NSDictionary *)addPrebidParameters:(NSDictionary *)requestParameters + withKeywords:(NSDictionary *)keywordsPairs { + NSDictionary *existingExtras = requestParameters[@"extras"]; + if (keywordsPairs) { + NSMutableDictionary *mutableRequestParameters = [requestParameters mutableCopy]; + NSMutableDictionary *mutableExtras = [[NSMutableDictionary alloc] init]; + if (existingExtras) { + mutableExtras = [existingExtras mutableCopy]; + } + + for (id key in keywordsPairs) { + + id value = [keywordsPairs objectForKey:key]; + if ([key isEqualToString:@"pb_adurl_enc"]) { + value = [value urlencode]; + } + if (value) { + mutableExtras[key] = value; + } + } + + mutableRequestParameters[@"extras"] = [mutableExtras copy]; + requestParameters = [mutableRequestParameters copy]; + } + return requestParameters; +} + +- (void)attachTopBidHelperForAdUnitId:(nonnull NSString *)adUnitIdentifier + andTimeout:(int)timeoutInMS + completionHandler:(nullable void (^)(void))handler { + [self assertAdUnitRegistered:adUnitIdentifier]; + if (timeoutInMS > kPCAttachTopBidMaxTimeoutMS) { + timeoutInMS = kPCAttachTopBidMaxTimeoutMS; + } + if ([self isBidReady:adUnitIdentifier]) { + dispatch_async(dispatch_get_main_queue(), ^{ + PBLogDebug(@"Calling completionHandler on attachTopBidWhenReady"); + handler(); + }); + } else { + timeoutInMS = timeoutInMS - kPCAttachTopBidTimeoutIntervalMS; + if (timeoutInMS > 0) { + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC * kPCAttachTopBidTimeoutIntervalMS); + dispatch_after(delay, dispatch_get_main_queue(), ^(void) { + [self attachTopBidHelperForAdUnitId:adUnitIdentifier + andTimeout:timeoutInMS + completionHandler:handler]; + }); + } else { + PBLogDebug(@"Bidding failed to finish within timeout for ad unit %@", adUnitIdentifier); + PBLogDebug(@"Attempting to attach cached bid for ad unit %@", adUnitIdentifier); + PBLogDebug(@"Calling completionHandler on attachTopBidWhenReady"); + handler(); + } + } +} + +#pragma mark Internal Methods + +- (void)registerAdUnit:(PBAdUnit *)adUnit { + // Throw exceptions if size or demand source is not specified + if (adUnit.adSizes == nil && adUnit.adType == PBAdUnitTypeBanner) { + @throw [PBException exceptionWithName:PBAdUnitNoSizeException]; + } + // Check if adunit already exists, if so remove it + if ([_adUnits containsObject:adUnit]) { + [_adUnits removeObject:adUnit]; + } + [_adUnits addObject:adUnit]; + PBLogDebug(@"AdUnit %@ is registered with Prebid Mobile", adUnit.identifier); +} + +- (void)requestBidsForAdUnits:(NSArray *)adUnits { + [_demandAdapter requestBidsWithAdUnits:adUnits withDelegate:[self delegate]]; +} + +- (void)startNewAuction:(PBAdUnit *)adUnit { + [adUnit generateUUID]; + [_bidsMap removeObjectForKey:adUnit.identifier]; + [self requestBidsForAdUnits:@[adUnit]]; +} + +- (void)saveBidResponses:(NSArray *)bidResponses { + PBBidResponse *bid = (PBBidResponse *)bidResponses[0]; + [_bidsMap setObject:[bidResponses mutableCopy] forKey:bid.adUnitId]; + + // TODO: if prebid server returns expiry time for bids we need to change this implementation + NSTimeInterval timeToExpire = bid.timeToExpireAfter + [[NSDate date] timeIntervalSince1970]; + PBAdUnit *adUnit = [self adUnitByIdentifier:bid.adUnitId]; + [adUnit setTimeIntervalToExpireAllBids:timeToExpire]; +} + +- (void)startPollingBidsExpiryTimer { + __weak PBBidManager *weakSelf = self; + if ([[NSTimer class] respondsToSelector:@selector(pb_scheduledTimerWithTimeInterval:block:repeats:)]) { + [NSTimer pb_scheduledTimerWithTimeInterval:kBidExpiryTimerInterval + block:^{ + PBBidManager *strongSelf = weakSelf; + [strongSelf checkForBidsExpired]; + } + repeats:YES]; + } +} + +- (void)checkForBidsExpired { + if (_adUnits != nil && _adUnits.count > 0) { + NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; + for (PBAdUnit *adUnit in _adUnits) { + if ([adUnit shouldExpireAllBids:currentTime]) { + [self startNewAuction:adUnit]; + } + } + } +} + +- (PBBidResponse *)winningBidForAdUnit:(PBAdUnit *)adUnit { + NSMutableArray *bids = [_bidsMap objectForKey:adUnit.identifier]; + // can just take the first bid in the array because bids were already sorted server side + PBBidResponse *topBidResponse = bids[0]; + if (topBidResponse && topBidResponse.isExpired == NO) { + [self startNewAuction:adUnit]; + } else { + PBLogDebug(@"No bid responses for ad unit %@", adUnit.identifier); + } + return topBidResponse; +} + +- (BOOL)isBidReady:(NSString *)identifier { + if ([[_bidsMap allKeys] containsObject:identifier] && [_bidsMap objectForKey:identifier] != nil) { + PBLogDebug(@"Bid is ready for ad unit with identifier %@", identifier); + return YES; + } + return NO; +} + +- (void)setBidOnAdObject:(NSObject *)adObject { + [self clearBidOnAdObject:adObject]; + + if (adObject.pb_identifier) { + NSMutableArray *mutableKeywords; + NSString *keywords = @""; + SEL getKeywords = NSSelectorFromString(@"keywords"); + if ([adObject respondsToSelector:getKeywords]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + keywords = (NSString *)[adObject performSelector:getKeywords]; + } + if (keywords.length) { + mutableKeywords = [[keywords componentsSeparatedByString:@","] mutableCopy]; + } + if (!mutableKeywords) { + mutableKeywords = [[NSMutableArray alloc] init]; + } + PBAdUnit *adUnit = adObject.pb_identifier; + NSDictionary *keywordsPairs = [self keywordsForWinningBidForAdUnit:adUnit]; + for (id key in keywordsPairs) { + id value = [keywordsPairs objectForKey:key]; + if (value) { + [mutableKeywords addObject:[NSString stringWithFormat:@"%@:%@", key, value]]; + } + } + if ([[mutableKeywords componentsJoinedByString:@","] length] > 4000) { + PBLogDebug(@"Bid to MoPub is too long"); + } else { + SEL setKeywords = NSSelectorFromString(@"setKeywords:"); + if ([adObject respondsToSelector:setKeywords]) { + NSString *keywordsToSet = [mutableKeywords componentsJoinedByString:@","]; + [adObject performSelector:setKeywords withObject:keywordsToSet]; +#pragma clang diagnostic pop + } + } + } else { + PBLogDebug(@"No bid available to pass to MoPub"); + } +} + +- (void)clearBidOnAdObject:(NSObject *)adObject { + NSString *keywordsString = @""; + SEL getKeywords = NSSelectorFromString(@"keywords"); + if ([adObject respondsToSelector:getKeywords]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + keywordsString = (NSString *)[adObject performSelector:getKeywords]; + } + if (keywordsString.length) { + NSArray *keywords = [keywordsString componentsSeparatedByString:@","]; + NSMutableArray *mutableKeywords = [keywords mutableCopy]; + [keywords enumerateObjectsUsingBlock:^(NSString *keyword, NSUInteger idx, BOOL *stop) { + for (NSString *reservedKey in [PBKeywordsManager reservedKeys]) { + if ([keyword hasPrefix:reservedKey]) { + [mutableKeywords removeObject:keyword]; + return; + } + } + }]; + SEL setKeywords = NSSelectorFromString(@"setKeywords:"); + if ([adObject respondsToSelector:setKeywords]) { + [adObject performSelector:setKeywords withObject:[mutableKeywords componentsJoinedByString:@","]]; +#pragma clang diagnostic pop + } + } +} + +@end diff --git a/sdk/PrebidMobile/PBBidResponse.h b/sdk/PrebidMobile/PBBidResponse.h new file mode 100644 index 000000000..e6b5694ea --- /dev/null +++ b/sdk/PrebidMobile/PBBidResponse.h @@ -0,0 +1,52 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface PBBidResponse : NSObject + +/** + * the adUnitId is the adUnit identifier that the bid response corresponds to + */ +@property (nonatomic, readonly) NSString *__nullable adUnitId; + +/** + * customKeywords is a dictionary of all the response objects returned by the demand source that can be used in future + */ +@property (nonatomic, readonly) NSDictionary *__nullable customKeywords; + +/** + * the time within which the bid value should be used else will expire & the developer has to fetch new value from the source + */ +@property (nonatomic, assign) NSTimeInterval timeToExpireAfter; + +/** + * initialize method is to create BidResponse Object with the hbpb, cacheId, & adUnitId. + */ ++ (nonnull instancetype)bidResponseWithAdUnitId:(nonnull NSString *)adUnitId + adServerTargeting:(nonnull NSDictionary *)adServerTargeting; + +/** + * all the server response json objects are added as dictionary objects to the bid response object + */ +- (void)addCustomKeywordWithKey:(nonnull NSString *)key + value:(nonnull NSString *)value; + +/** + * method to check if the bid has expired or not. returns boolean true or false + */ +- (BOOL)isExpired; + +@end diff --git a/sdk/PrebidMobile/PBBidResponse.m b/sdk/PrebidMobile/PBBidResponse.m new file mode 100644 index 000000000..9bbc80313 --- /dev/null +++ b/sdk/PrebidMobile/PBBidResponse.m @@ -0,0 +1,66 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBidResponse.h" + +@interface PBBidResponse () + +@property (nonatomic, assign) NSTimeInterval createdTime; +@property (nonatomic, readwrite) NSMutableDictionary *__nullable customKeywords; + +@end + +static NSTimeInterval const kDefaultBidExpiryTime = 270; + + +@implementation PBBidResponse + +#pragma mark Class Methods + ++ (nonnull instancetype)bidResponseWithAdUnitId:(nonnull NSString *)adUnitId + adServerTargeting:(nonnull NSDictionary *)adServerTargeting { + PBBidResponse *newBidResponse = [[PBBidResponse alloc] initWithAdUnitId:adUnitId + adServerTargeting:adServerTargeting]; + return (newBidResponse); +} + +#pragma mark Instance Methods + +- (nonnull instancetype)initWithAdUnitId:(nonnull NSString *)adUnitId + adServerTargeting:(nonnull NSDictionary *)adServerTargeting { + if ((self = [super init])) { + _adUnitId = [adUnitId copy]; + _customKeywords = [adServerTargeting copy]; + + // Setting the default bid expiration time to be 4 minutes 30 seconds + _timeToExpireAfter = kDefaultBidExpiryTime; + _createdTime = [[NSDate date] timeIntervalSince1970]; + } + + return (self); +} + +- (void)addCustomKeywordWithKey:(NSString *)key value:(NSString *)value { + if (_customKeywords == nil) { + _customKeywords = [[NSMutableDictionary alloc] init]; + } + [_customKeywords setObject:value forKey:key]; +} + +- (BOOL)isExpired { + return ([[NSDate date] timeIntervalSince1970] - self.createdTime > self.timeToExpireAfter); +} + +@end diff --git a/sdk/PrebidMobile/PBBidResponseDelegate.h b/sdk/PrebidMobile/PBBidResponseDelegate.h new file mode 100644 index 000000000..685c47853 --- /dev/null +++ b/sdk/PrebidMobile/PBBidResponseDelegate.h @@ -0,0 +1,33 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +@class PBAdUnit; +@class PBBidResponse; + +@protocol PBBidResponseDelegate + +/** + * didReceiveSuccessResponse delegate method that returns a successful bid response with either an active bid or no bid + * @param bid : the BidResponse object that has the bid parameters + */ +- (void)didReceiveSuccessResponse:(nonnull NSArray *)bid; + +/** + * didCompleteWithError delegate method that sends the error object for the bid request failure + * @param error : NSError object that contains the details as to why the request failed + */ +- (void)didCompleteWithError:(nonnull NSError *)error; + +@end diff --git a/sdk/PrebidMobile/PBException.h b/sdk/PrebidMobile/PBException.h new file mode 100644 index 000000000..9637c5339 --- /dev/null +++ b/sdk/PrebidMobile/PBException.h @@ -0,0 +1,35 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface PBException : NSException + +/** + * implement price check exception handling. Currently price check will throw exception if the user fails to provide the size + * or demand source in the adunits. Additionally of the user has already registered the adunit & trying to register again + * then an exception is raised. + */ + +typedef enum PBRaiseException { + PBAdUnitNoSizeException, + PBAdUnitNoDemandConfigException, + PBAdUnitAlreadyRegisteredException, + PBAdUnitNotRegisteredException +} PBRaiseException; + ++ (NSException *)exceptionWithName:(enum PBRaiseException)exceptionName; + +@end diff --git a/sdk/PrebidMobile/PBException.m b/sdk/PrebidMobile/PBException.m new file mode 100644 index 000000000..d33108f59 --- /dev/null +++ b/sdk/PrebidMobile/PBException.m @@ -0,0 +1,45 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBException.h" + +@implementation PBException + ++ (NSException *)exceptionWithName:(enum PBRaiseException)exceptionName { + switch (exceptionName) { + case PBAdUnitNoSizeException: + return ([super exceptionWithName:@"PBAdUnitNoSizeException" reason:@"Ad unit size object is not specified" userInfo:nil]); + break; + case PBAdUnitNoDemandConfigException: + return ([super exceptionWithName:@"PBAdUnitNoDemandConfigException" reason:@"Ad unit config id is not set in prebid server" userInfo:nil]); + break; + case PBAdUnitAlreadyRegisteredException: + return ([super exceptionWithName:@"PBAdUnitAlreadyRegisteredException" reason:@"Ad unit is already registered" userInfo:nil]); + break; + case PBAdUnitNotRegisteredException: + return ([super exceptionWithName:@"PBAdUnitNotRegisteredException" reason:@"Ad unit is not registered." userInfo:nil]); + break; + default: + return ([super exceptionWithName:@"PrebidException" reason:@"" userInfo:nil]); + break; + } +} + ++ (nonnull NSException *)initWithName:(nonnull NSString *)aName reason:(nullable NSString *)aReason userInfo:(nullable NSDictionary *)aUserInfo { + + return ([super exceptionWithName:aName reason:aReason userInfo:aUserInfo]); +} + +@end diff --git a/sdk/PrebidMobile/PBInterstitialAdUnit.h b/sdk/PrebidMobile/PBInterstitialAdUnit.h new file mode 100644 index 000000000..2929065db --- /dev/null +++ b/sdk/PrebidMobile/PBInterstitialAdUnit.h @@ -0,0 +1,27 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBAdUnit.h" + +@interface PBInterstitialAdUnit : PBAdUnit + +/** + * Initializes the Interstitial AdUnit with an identifier + * @param identifier : the identifier is a developer specific identity given for each of the ad unit created + * @param configId : the config id with the demand sources from prebid server + */ +- (nonnull instancetype)initWithAdUnitIdentifier:(nonnull NSString *)identifier andConfigId:(nonnull NSString *)configId; + +@end diff --git a/sdk/PrebidMobile/PBInterstitialAdUnit.m b/sdk/PrebidMobile/PBInterstitialAdUnit.m new file mode 100644 index 000000000..e134004e5 --- /dev/null +++ b/sdk/PrebidMobile/PBInterstitialAdUnit.m @@ -0,0 +1,41 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBInterstitialAdUnit.h" + +static NSInteger const kNumSizes = 11; +static NSInteger const kSizeXY = 2; + +@implementation PBInterstitialAdUnit + +- (nonnull instancetype)initWithAdUnitIdentifier:(nonnull NSString *)identifier andConfigId:(nonnull NSString *)configId { + PBInterstitialAdUnit *interstitialAdUnit = [super initWithIdentifier:identifier andAdType:PBAdUnitTypeInterstitial andConfigId:configId]; + [self addSizesToInterstitialAdUnit:interstitialAdUnit]; + return interstitialAdUnit; +} + +- (void)addSizesToInterstitialAdUnit:(PBInterstitialAdUnit *)adUnit { + CGRect screenSize = [[UIScreen mainScreen] bounds]; + int size[kNumSizes][kSizeXY] = {{300, 250}, {300, 600}, {320, 250}, {254, 133}, {580, 400}, {320, 320}, {320, 160}, {320, 480}, {336, 280}, {320, 400}, {1, 1}}; + + for (int i = 0; i < kNumSizes; i++) { + CGSize sizeObj = CGSizeMake(size[i][0], size[i][1]); + if (sizeObj.width <= screenSize.size.width && sizeObj.height <= screenSize.size.height) { + [adUnit addSize:sizeObj]; + } + } +} + +@end diff --git a/sdk/PrebidMobile/PBKeywordsManager.h b/sdk/PrebidMobile/PBKeywordsManager.h new file mode 100644 index 000000000..b2a9c5312 --- /dev/null +++ b/sdk/PrebidMobile/PBKeywordsManager.h @@ -0,0 +1,32 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import + +@class PBBidResponse; + +/** + Keywords manager that can parse bid response to string pairs of keywords + */ + +@interface PBKeywordsManager : NSObject + +/** + * This method provides the list of keywords that prebid will pass values by default + */ ++ (nonnull NSArray *)reservedKeys; + +@end diff --git a/sdk/PrebidMobile/PBKeywordsManager.m b/sdk/PrebidMobile/PBKeywordsManager.m new file mode 100644 index 000000000..d9a1a3d91 --- /dev/null +++ b/sdk/PrebidMobile/PBKeywordsManager.m @@ -0,0 +1,39 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBidResponse.h" +#import "PBKeywordsManager.h" + +#pragma mark Constants +NSString *__nonnull const PBKeywordsManagerPreBidBidderCodeKey = @"hb_bidder"; +NSString *__nonnull const PBKeywordsManagerPreBidCacheIdKey = @"hb_cache_id"; +NSString *__nonnull const PBKeywordsManagerPriceHbpbKey = @"hb_pb"; + +#pragma mark + +@implementation PBKeywordsManager + ++ (NSArray *)reservedKeys { + static dispatch_once_t reservedKeysToken; + static NSArray *keys; + dispatch_once(&reservedKeysToken, ^{ + keys = @[PBKeywordsManagerPreBidBidderCodeKey, + PBKeywordsManagerPriceHbpbKey, + PBKeywordsManagerPreBidCacheIdKey]; + }); + return keys; +} + +@end diff --git a/sdk/PrebidMobile/PBTargetingParams.h b/sdk/PrebidMobile/PBTargetingParams.h new file mode 100644 index 000000000..0c2bc5575 --- /dev/null +++ b/sdk/PrebidMobile/PBTargetingParams.h @@ -0,0 +1,86 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +/** + * Gender selection enumerator to be passed in by the user + */ +typedef NS_ENUM(NSUInteger, PBTargetingParamsGender) { + PBTargetingParamsGenderFemale = 0, + PBTargetingParamsGenderMale, + PBTargetingParamsGenderUnknown +}; + +@interface PBTargetingParams : NSObject + ++ (nonnull instancetype)sharedInstance; + +#ifdef DEBUG ++ (void)resetSharedInstance; +#endif + +/** + * This property gets the age value set by the application developer + */ +@property (nonatomic, assign, readwrite) NSInteger age; + +/** + * This property gets the gender enum passed set by the developer + */ +@property (nonatomic, assign, readwrite) PBTargetingParamsGender gender; + +/** + * The application location for targeting + */ +@property (nonatomic, readwrite) CLLocation *__nullable location; + +/** + * The application location precision for targeting + */ +@property (nonatomic, readwrite) NSInteger locationPrecision; + +/** + * The itunes app id for targeting + */ +@property (nonatomic, readwrite) NSString *__nullable itunesID; + +/** + * This property stores the set of custom keywords that price check provides for targeting + */ +@property (nonatomic, strong, readonly) NSDictionary *__nullable customKeywords; + +/** + * This method obtains the custom keyword & value for targeting framed by the developer + */ +- (void)setCustomTargeting:(nonnull NSString *)key + withValue:(nonnull NSString *)value; +/** + * This method obtains the custom keyword & value set for targeting framed by the developer + */ +- (void)setCustomTargeting:(nonnull NSString *)key + withValues:(nonnull NSArray *)values; + +/** + * This method allows the developer to remove all the custom keywords set for targeting + */ +- (void)removeCustomKeywords; + +/** + * This method allows the developer to remove specific custom keyword & value set from targeting + */ +- (void)removeCustomKeywordWithKey:(nonnull NSString *)key; + +@end diff --git a/sdk/PrebidMobile/PBTargetingParams.m b/sdk/PrebidMobile/PBTargetingParams.m new file mode 100644 index 000000000..ca6448674 --- /dev/null +++ b/sdk/PrebidMobile/PBTargetingParams.m @@ -0,0 +1,103 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBTargetingParams.h" + +@interface PBTargetingParams () + +@property (nonatomic, strong, readwrite) NSMutableDictionary *__nullable customKeywords; + +@end + +@implementation PBTargetingParams + +- (instancetype)init { + if (self = [super init]) { + _locationPrecision = (NSInteger)-1; + } + return self; +} + +static PBTargetingParams *sharedInstance = nil; +static dispatch_once_t onceToken; + ++ (instancetype)sharedInstance { + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + ++ (void)resetSharedInstance { + onceToken = 0; + sharedInstance = nil; +} + +- (void)setCustomTargeting:(nonnull NSString *)key + withValue:(nonnull NSString *)value { + if (_customKeywords == nil) { + _customKeywords = [[NSMutableDictionary alloc] init]; + } + + NSArray *valueArray = [NSArray arrayWithObject:value]; + _customKeywords[key] = valueArray; +} + +- (void)setCustomTargeting:(nonnull NSString *)key + withValues:(nonnull NSArray *)values { + if (_customKeywords == nil) { + _customKeywords = [[NSMutableDictionary alloc] init]; + } + + // remove duplicate values from the array + NSArray *valueArray = [[NSSet setWithArray:values] allObjects]; + _customKeywords[key] = valueArray; +} + +- (nullable NSDictionary *)customKeywords { + return _customKeywords; +} + +- (void)removeCustomKeywords { + if (_customKeywords != nil) { + [_customKeywords removeAllObjects]; + _customKeywords = nil; + } +} + +- (void)removeCustomKeywordWithKey:(NSString *)key { + if (_customKeywords != nil) { + if (_customKeywords[key] != nil) { + [_customKeywords removeObjectForKey:key]; + } + if ([_customKeywords count] == 0) { + _customKeywords = nil; + } + } +} + +- (void)setLocation:(CLLocation *)location { + _location = location; +} + +- (void)setLocationPrecision:(NSInteger)locationPrecision { + _locationPrecision = locationPrecision; +} + +- (void)setItunesID:(NSString *)itunesID { + _itunesID = itunesID; +} + +@end diff --git a/sdk/PrebidMobile/PrebidMobile.h b/sdk/PrebidMobile/PrebidMobile.h new file mode 100644 index 000000000..3799e3a10 --- /dev/null +++ b/sdk/PrebidMobile/PrebidMobile.h @@ -0,0 +1,37 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import "PBLogging.h" + +@class PBAdUnit; + +@interface PrebidMobile : NSObject + +/** + * This method allows the developer to register the ad units created for Prebid Mobile + * @param adUnits : Array of AdUnits that can be registered + * @param accountId : Prebid server accountId + */ ++ (void)registerAdUnits:(nonnull NSArray *)adUnits withAccountId:(nonnull NSString *)accountId; + ++ (void)setBidKeywordsOnAdObject:(nonnull id)adObject withAdUnitId:(nonnull NSString *)adUnitId; + ++ (void)setBidKeywordsOnAdObject:(nonnull id)adObject + withAdUnitId:(nonnull NSString *)adUnitIdentifier + withTimeout:(int)timeoutInMilliseconds + completionHandler:(nullable void (^)(void))handler; + +@end diff --git a/sdk/PrebidMobile/PrebidMobile.m b/sdk/PrebidMobile/PrebidMobile.m new file mode 100644 index 000000000..c213d8cd9 --- /dev/null +++ b/sdk/PrebidMobile/PrebidMobile.m @@ -0,0 +1,53 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBidManager.h" +#import "PrebidMobile.h" + +@implementation PrebidMobile + ++ (void)registerAdUnits:(nonnull NSArray *)adUnits withAccountId:(nonnull NSString *)accountId { + [[PBBidManager sharedInstance] registerAdUnits:adUnits withAccountId:accountId]; +} + ++ (void)setBidKeywordsOnAdObject:(nonnull id)adObject + withAdUnitId:(nonnull NSString *)adUnitId { + PBLogDebug(@"Set bid keywords on ad object for ad unit %@", adUnitId); + PBAdUnit *__nullable adUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:adUnitId]; + [[PBBidManager sharedInstance] assertAdUnitRegistered:adUnitId]; + + SEL setPbIdentifier = NSSelectorFromString(@"setPb_identifier:"); + if ([adObject respondsToSelector:setPbIdentifier]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [adObject performSelector:setPbIdentifier withObject:adUnit]; +#pragma clang diagnostic pop + } +} + ++ (void)setBidKeywordsOnAdObject:(id)adObject + withAdUnitId:(NSString *)adUnitIdentifier + withTimeout:(int)timeoutInMilliseconds + completionHandler:(void (^)(void))handler { + void (^completionHandler)(void) = ^{ + [self setBidKeywordsOnAdObject:adObject withAdUnitId:adUnitIdentifier]; + handler(); + }; + [[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnitIdentifier + andTimeout:timeoutInMilliseconds + completionHandler:completionHandler]; +} + +@end diff --git a/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.h b/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.h new file mode 100644 index 000000000..f1f2a43dc --- /dev/null +++ b/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.h @@ -0,0 +1,20 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface PBMockServerAdapter : NSObject + +@end diff --git a/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.m b/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.m new file mode 100644 index 000000000..e248fac30 --- /dev/null +++ b/sdk/PrebidMobileTests/MockObjects/PBMockServerAdapter.m @@ -0,0 +1,29 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBAdUnit.h" +#import "PBBidResponseDelegate.h" +#import "PBMockServerAdapter.h" + +@implementation PBMockServerAdapter + +- (void)requestBidsWithAdUnits:(nullable NSArray *)adUnits + withDelegate:(nonnull id)delegate { + // mock any conditions necessary for testing + //[delegate bidSuccessful:bidResponse forAdUnit:adUnit]; + NSLog(@"mock server adapter request bids called"); +} + +@end diff --git a/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBAdUnitTests.m b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBAdUnitTests.m new file mode 100644 index 000000000..c222d89de --- /dev/null +++ b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBAdUnitTests.m @@ -0,0 +1,125 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import "PBAdUnit.h" +#import "PBBannerAdUnit.h" +#import "PBInterstitialAdUnit.h" +#import + +NSString *const kTestAdUnitId = @"TestAdUnit"; +NSString *const kTestBannerAdUnitId = @"TestBannerAdUnit"; +NSString *const kTestInterstitialAdUnitId = @"TestInterstitialAdUnit"; +NSString *const kTestConfigId = @"testconfigid"; + +@interface PCAdUnitTests : XCTestCase + +@end + +@implementation PCAdUnitTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testBannerAdCreation { + PBBannerAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:kTestBannerAdUnitId andConfigId:kTestConfigId]; + XCTAssertTrue(bannerAdUnit.adType == PBAdUnitTypeBanner); + XCTAssertTrue([kTestBannerAdUnitId isEqualToString:bannerAdUnit.identifier]); +} + +- (void)testInterstitialAdCreation { + PBInterstitialAdUnit *interstitialAdUnit = [[PBInterstitialAdUnit alloc] initWithAdUnitIdentifier:kTestInterstitialAdUnitId andConfigId:kTestConfigId]; + XCTAssertTrue(interstitialAdUnit.adType == PBAdUnitTypeInterstitial); + XCTAssertTrue([kTestInterstitialAdUnitId isEqualToString:interstitialAdUnit.identifier]); + + NSMutableArray *expectedSizeArray = [[NSMutableArray alloc] init]; + CGRect screenSize = [[UIScreen mainScreen] bounds]; + int size[11][2] = {{300, 250}, {300, 600}, {320, 250}, {254, 133}, {580, 400}, {320, 320}, {320, 160}, {320, 480}, {336, 280}, {320, 400}, {1, 1}}; + for (int i = 0; i < 11; i++) { + CGSize sizeObj = CGSizeMake(size[i][0], size[i][1]); + if (sizeObj.width <= screenSize.size.width && sizeObj.height <= screenSize.size.height) { + [expectedSizeArray addObject:[NSValue valueWithCGSize:sizeObj]]; + } + } + XCTAssertTrue([interstitialAdUnit.adSizes isEqualToArray:expectedSizeArray]); +} + +- (void)testAddSizeToAdUnit { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + + CGSize bannerSize = CGSizeMake(320, 50); + [adUnit addSize:bannerSize]; + + XCTAssertTrue(adUnit.adSizes.count == 1); + XCTAssertTrue([adUnit.adSizes containsObject:[NSValue valueWithCGSize:bannerSize]]); +} + +- (void)testAddMultipleSizesToAdUnit { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + + CGSize bannerSize = CGSizeMake(320, 50); + CGSize bannerSize2 = CGSizeMake(320, 250); + [adUnit addSize:bannerSize]; + [adUnit addSize:bannerSize2]; + + XCTAssertTrue(adUnit.adSizes.count == 2); + XCTAssertTrue([adUnit.adSizes containsObject:[NSValue valueWithCGSize:bannerSize]]); + XCTAssertTrue([adUnit.adSizes containsObject:[NSValue valueWithCGSize:bannerSize2]]); +} + +- (void)testGenerateUUIDForAdUnit { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + NSString *adUnitUUIDOriginal = adUnit.uuid; + + [adUnit generateUUID]; + XCTAssertFalse([adUnitUUIDOriginal isEqualToString:adUnit.uuid]); +} + +- (void)testIsEqualToAdUnit { + PBBannerAdUnit *bannerAdUnit1 = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:kTestBannerAdUnitId andConfigId:kTestConfigId]; + PBBannerAdUnit *bannerAdUnit2 = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:kTestBannerAdUnitId andConfigId:kTestConfigId]; + XCTAssertTrue([bannerAdUnit1 isEqualToAdUnit:bannerAdUnit2]); +} + +- (void)testShouldExpireAllBidsInitialAdUnit { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + XCTAssertTrue([adUnit shouldExpireAllBids:[NSDate date].timeIntervalSince1970]); +} + +- (void)testShouldExpireAllBidsAdUnitWithSetTimeToExpire { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + [adUnit setTimeIntervalToExpireAllBids:[NSDate dateWithTimeIntervalSinceNow:5].timeIntervalSince1970]; + XCTAssertFalse([adUnit shouldExpireAllBids:[NSDate date].timeIntervalSince1970]); +} + +- (void)testAdUnitSetTimeToExpireUsesLongerTimeToExpire { + PBAdUnit *adUnit = [[PBAdUnit alloc] initWithIdentifier:kTestAdUnitId andAdType:PBAdUnitTypeBanner andConfigId:kTestConfigId]; + + NSTimeInterval longTimeToExpire = [NSDate dateWithTimeIntervalSinceNow:270].timeIntervalSince1970; + NSTimeInterval shortTimeToExpire = [NSDate dateWithTimeIntervalSinceNow:2].timeIntervalSince1970; + NSTimeInterval timeInBetween = [NSDate dateWithTimeIntervalSinceNow:50].timeIntervalSince1970; + + [adUnit setTimeIntervalToExpireAllBids:longTimeToExpire]; + [adUnit setTimeIntervalToExpireAllBids:shortTimeToExpire]; + + XCTAssertFalse([adUnit shouldExpireAllBids:timeInBetween]); +} + +@end diff --git a/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidManagerTests.m b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidManagerTests.m new file mode 100644 index 000000000..5b3de96c1 --- /dev/null +++ b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidManagerTests.m @@ -0,0 +1,274 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBServerAdapter.h" +#import "PBAdUnit.h" +#import "PBBannerAdUnit.h" +#import "PBBidManager.h" +#import "PBBidResponse.h" +#import "PBException.h" +#import "PBInterstitialAdUnit.h" +#import "PBMockServerAdapter.h" +#import + +NSString *const kBidManagerTestAdUnitId = @"TestAdUnitId"; + +@interface PBBidManager (Testing) + +@property (nonatomic, strong) NSMutableSet *adUnits; +@property (nonatomic, strong) NSMutableDictionary *__nullable bidsMap; +@property (nonatomic, strong) PBServerAdapter *demandAdapter; +- (void)startNewAuction:(PBAdUnit *)adUnit; +- (void)saveBidResponses:(nonnull NSArray *)bidResponse; +- (void)checkForBidsExpired; +- (PBBidResponse *)winningBidForAdUnit:(PBAdUnit *)adUnit; + +@end + +@interface PBBidManagerTests : XCTestCase + +@property (nonatomic, strong) NSString *accountId; + +@end + +@implementation PBBidManagerTests + +- (void)setUp { + self.accountId = @"aecd6ef7-b992-4e99-9bb8-65e2d984e1dd"; + [super setUp]; +} + +- (void)tearDown { + [PBBidManager resetSharedInstance]; + [super tearDown]; +} + +#pragma mark - Test register ad units tests + +- (void)testRegisterBannerAdUnit { + PBAdUnit *returnedUnit = nil; + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt1" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit] withAccountId:self.accountId]; + returnedUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[bannerAdUnit identifier]]; + + XCTAssertNotNil(returnedUnit); + XCTAssertEqualObjects(returnedUnit.identifier, bannerAdUnit.identifier); +} + +- (void)testRegisterInterstitialAdUnit { + PBAdUnit *returnedUnit = nil; + PBAdUnit *interstitialAdUnit = [[PBInterstitialAdUnit alloc] initWithAdUnitIdentifier:@"bmt2" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + + [[PBBidManager sharedInstance] registerAdUnits:@[interstitialAdUnit] withAccountId:self.accountId]; + returnedUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[interstitialAdUnit identifier]]; + + XCTAssertNotNil(returnedUnit); + XCTAssertEqualObjects(returnedUnit.identifier, interstitialAdUnit.identifier); +} + +- (void)testRegisterMultipleAdUnits { + PBAdUnit *returnedAdUnit = nil; + PBAdUnit *returnedInterstitialAdUnit = nil; + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt3" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + PBAdUnit *interstitialAdUnit = [[PBInterstitialAdUnit alloc] initWithAdUnitIdentifier:@"bmt4" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit, interstitialAdUnit] withAccountId:self.accountId]; + returnedAdUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[bannerAdUnit identifier]]; + returnedInterstitialAdUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[interstitialAdUnit identifier]]; + + XCTAssertNotNil(returnedAdUnit); + XCTAssertEqualObjects(returnedAdUnit.identifier, bannerAdUnit.identifier); + XCTAssertNotNil(returnedInterstitialAdUnit); + XCTAssertEqualObjects(returnedInterstitialAdUnit.identifier, interstitialAdUnit.identifier); +} + +- (void)testRegisterBannerAdUnitNoSizeException { + PBBannerAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt4" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + @try { + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit] withAccountId:self.accountId]; + } @catch (PBException *exception) { + NSExceptionName expectedException = @"PBAdUnitNoSizeException"; + XCTAssertNotNil(exception); + XCTAssertEqual(exception.name, expectedException); + } + PBAdUnit *returnedAdUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[bannerAdUnit identifier]]; + XCTAssertNil(returnedAdUnit); +} + +#pragma mark - Test winning bid for ad unit + +- (void)testWinningBidForAdUnit { + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt45" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit] withAccountId:self.accountId]; + + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:bannerAdUnit.identifier adServerTargeting:testAdServerTargeting]; + NSDictionary *testAdServerTargeting2 = @{@"hb_pb_appnexus":@"0.14", @"hb_cache_id_appnexus":@"0000-0000-000-0000"}; + PBBidResponse *bidResponse2 = [PBBidResponse bidResponseWithAdUnitId:bannerAdUnit.identifier adServerTargeting:testAdServerTargeting2]; + [[PBBidManager sharedInstance] saveBidResponses:@[bidResponse, bidResponse2]]; + + PBBidResponse *winningBid = [[PBBidManager sharedInstance] winningBidForAdUnit:bannerAdUnit]; + XCTAssertEqual(winningBid.customKeywords[@"hb_pb"], bidResponse.customKeywords[@"hb_pb"]); +} + +#pragma mark - Test keywords for winning bid for ad unit tests + +- (void)testKeywordsForWinningBidForAdUnit { + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt5" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit] withAccountId:self.accountId]; + + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000", @"hb_bidder": @"appnexus"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:bannerAdUnit.identifier adServerTargeting:testAdServerTargeting]; + [[PBBidManager sharedInstance] saveBidResponses:@[bidResponse]]; + + NSDictionary *keywords = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:bannerAdUnit]; + NSDictionary *expectedKeywords = @{@"hb_pb": @"4.14", + @"hb_cache_id" : @"0000-0000-000-0000", + @"hb_bidder" : @"appnexus"}; + XCTAssertTrue([keywords isEqualToDictionary:expectedKeywords]); +} + +#pragma mark - Test assert ad unit registered tests + +- (void)testAssertAdUnitRegistered { + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt6" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[bannerAdUnit] withAccountId:self.accountId]; + [[PBBidManager sharedInstance] assertAdUnitRegistered:bannerAdUnit.identifier]; +} + +- (void)testAssertAdUnitNotRegistered { + PBAdUnit *bannerAdUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt7" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [bannerAdUnit addSize:CGSizeMake(320, 50)]; + @try { + [[PBBidManager sharedInstance] assertAdUnitRegistered:bannerAdUnit.identifier]; + } @catch (PBException *exception) { + NSExceptionName expectedException = @"PBAdUnitNotRegisteredException"; + XCTAssertNotNil(exception); + XCTAssertEqual(exception.name, expectedException); + } + PBAdUnit *returnedAdUnit = [[PBBidManager sharedInstance] adUnitByIdentifier:[bannerAdUnit identifier]]; + XCTAssertNil(returnedAdUnit); +} + +#pragma mark - Test attach top bid helper tests + +- (void)testAttachTopBidHelperWithReadyBid { + XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; + PBAdUnit *adUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt8" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [adUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId]; + + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000", @"hb_bidder": @"appnexus"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnit.identifier adServerTargeting:testAdServerTargeting]; + [[PBBidManager sharedInstance] saveBidResponses:@[bidResponse]]; + + [[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnit.identifier andTimeout:500 completionHandler:^{ + NSDictionary *bidKeywords = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:adUnit]; + XCTAssertNotNil(bidKeywords); + [expectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testAttachTopBidHelperWithReadyBidAfterSomeTime { + XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; + PBAdUnit *adUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt9" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [adUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId]; + + // Save a bid after 200 milliseconds - before the timeout of 500 ms but not immediately + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000", @"hb_bidder": @"appnexus"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnit.identifier adServerTargeting:testAdServerTargeting]; + NSArray *array = [NSArray arrayWithObjects:bidResponse, nil]; + [[PBBidManager sharedInstance] performSelector:@selector(saveBidResponses:) withObject:array afterDelay:0.2]; + + [[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnit.identifier andTimeout:500 completionHandler:^{ + NSDictionary *bidKeywords = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:adUnit]; + XCTAssertNotNil(bidKeywords); + [expectation fulfill]; + }]; + // Wait for the expectation for 1 second + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testAttachTopBidHelperWithNoReadyBid { + XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; + PBAdUnit *adUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt10" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [adUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId]; + + [[PBBidManager sharedInstance] attachTopBidHelperForAdUnitId:adUnit.identifier andTimeout:500 completionHandler:^{ + NSDictionary *bidKeywords = [[PBBidManager sharedInstance] keywordsForWinningBidForAdUnit:adUnit]; + XCTAssertNil(bidKeywords); + [expectation fulfill]; + }]; + // Wait for the expectation for 1 second + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +#pragma mark - Test start new auction tests + +- (void)testStartNewAuction { + PBAdUnit *adUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt11" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [adUnit addSize:CGSizeMake(320, 50)]; + NSString *originalUUID = adUnit.uuid; + [[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId]; + + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000", @"hb_bidder": @"appnexus"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnit.identifier adServerTargeting:testAdServerTargeting]; + [[PBBidManager sharedInstance] saveBidResponses:@[bidResponse]]; + + XCTAssertNotNil([[[PBBidManager sharedInstance] bidsMap] objectForKey:adUnit.identifier]); + + [[PBBidManager sharedInstance] startNewAuction:adUnit]; + + XCTAssertNil([[[PBBidManager sharedInstance] bidsMap] objectForKey:adUnit.identifier]); + XCTAssertFalse([originalUUID isEqualToString:adUnit.uuid]); +} + +#pragma mark - Test bids expired tests + +- (void)testCheckForBidsExpired { + XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; + PBAdUnit *adUnit = [[PBBannerAdUnit alloc] initWithAdUnitIdentifier:@"bmt12" andConfigId:@"0b33e7ae-cf61-4003-8404-0711eea6e673"]; + [adUnit addSize:CGSizeMake(320, 50)]; + [[PBBidManager sharedInstance] registerAdUnits:@[adUnit] withAccountId:self.accountId]; + + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"4.14", @"hb_cache_id":@"0000-0000-000-0000", @"hb_bidder": @"appnexus"}; + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnit.identifier adServerTargeting:testAdServerTargeting]; + bidResponse.timeToExpireAfter = 1; + [[PBBidManager sharedInstance] saveBidResponses:@[bidResponse]]; + + NSString *originalUUID = adUnit.uuid; + + double delayInSeconds = 2; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ + [[PBBidManager sharedInstance] checkForBidsExpired]; + [expectation fulfill]; + }); + + [self waitForExpectationsWithTimeout:3 handler:^(NSError *error){ + XCTAssertFalse([originalUUID isEqualToString:adUnit.uuid]); + }]; +} + +@end diff --git a/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidResponseTests.m b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidResponseTests.m new file mode 100644 index 000000000..d02006c98 --- /dev/null +++ b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBBidResponseTests.m @@ -0,0 +1,48 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBidResponse.h" +#import + +@interface PBBidResponseTests : XCTestCase + +@end + +@implementation PBBidResponseTests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testBidResponseObject { + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"3.14", @"hb_cache_id":@"0000-0000-000-0000"}; + PBBidResponse *response = [PBBidResponse bidResponseWithAdUnitId:@"testAdUnitID" adServerTargeting:testAdServerTargeting]; + XCTAssertNotNil(response); +} + +- (void)testBidResponseExpired { + NSDictionary *testAdServerTargeting = @{@"hb_pb":@"3.14", @"hb_cache_id":@"0000-0000-000-0000"}; + PBBidResponse *response = [PBBidResponse bidResponseWithAdUnitId:@"testAdUnitID" adServerTargeting:testAdServerTargeting]; + XCTAssertFalse([response isExpired]); + response.timeToExpireAfter = 1; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; + XCTAssertTrue([response isExpired]); +} + +@end diff --git a/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBTargetingParamsTests.m b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBTargetingParamsTests.m new file mode 100644 index 000000000..7464f219b --- /dev/null +++ b/sdk/PrebidMobileTests/PrebidMobileCoreTests/PBTargetingParamsTests.m @@ -0,0 +1,93 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBTargetingParams.h" +#import + +@interface PBTargetingParamsTests : XCTestCase + +@end + +@implementation PBTargetingParamsTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + [PBTargetingParams resetSharedInstance]; + [super tearDown]; +} + +- (void)testSetGenderTargeting { + [[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderFemale]; + XCTAssertEqual(PBTargetingParamsGenderFemale, [[PBTargetingParams sharedInstance] gender]); + [[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderMale]; + XCTAssertEqual(PBTargetingParamsGenderMale, [[PBTargetingParams sharedInstance] gender]); + [[PBTargetingParams sharedInstance] setGender:PBTargetingParamsGenderUnknown]; + XCTAssertEqual(PBTargetingParamsGenderUnknown, [[PBTargetingParams sharedInstance] gender]); +} + +- (void)testSetLocationTargeting { + CLLocation *location = [[CLLocation alloc] initWithLatitude:100.0 longitude:100.0]; + [[PBTargetingParams sharedInstance] setLocation:location]; + [[PBTargetingParams sharedInstance] setLocationPrecision:2]; + XCTAssertEqual(location, [[PBTargetingParams sharedInstance] location]); + XCTAssertEqual(2, [[PBTargetingParams sharedInstance] locationPrecision]); +} + +- (void)testSetCustomKeywordsWithValue { + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValue:@"value1"]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting2" withValue:@"value2"]; + NSDictionary *customKeywords = [[PBTargetingParams sharedInstance] customKeywords]; + NSDictionary *expectedCustomKeywords = @{@"targeting1" : @[@"value1"], @"targeting2" : @[@"value2"]}; + XCTAssertTrue([customKeywords isEqualToDictionary:expectedCustomKeywords]); +} + +- (void)testSetCustomKeywordsWithMultipleValues { + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValues:@[@"value1", @"value2", @"value3"]]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting2" withValue:@"value2"]; + NSDictionary *customKeywords = [[PBTargetingParams sharedInstance] customKeywords]; + NSDictionary *expectedCustomKeywords = @{@"targeting1" : @[@"value2", @"value1", @"value3"], @"targeting2" : @[@"value2"]}; + XCTAssertTrue([customKeywords isEqualToDictionary:expectedCustomKeywords]); +} + +- (void)testSetCustomKeywordsWithDuplicateValues { + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValues:@[@"value2", @"value1", @"value3"]]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValue:@"value2"]; + NSDictionary *customKeywords = [[PBTargetingParams sharedInstance] customKeywords]; + NSDictionary *expectedCustomKeywords = @{@"targeting1" : @[@"value2"]}; + XCTAssertTrue([customKeywords isEqualToDictionary:expectedCustomKeywords]); +} + +- (void)testRemoveCustomKeywordWithKey { + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValue:@"value1"]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting2" withValue:@"value2"]; + [[PBTargetingParams sharedInstance] removeCustomKeywordWithKey:@"targeting2"]; + NSDictionary *customKeywords = [[PBTargetingParams sharedInstance] customKeywords]; + NSDictionary *expectedCustomKeywords = @{@"targeting1" : @[@"value1"]}; + XCTAssertTrue([customKeywords isEqualToDictionary:expectedCustomKeywords]); +} + +- (void)testRemoveCustomKeywords { + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting1" withValue:@"value1"]; + [[PBTargetingParams sharedInstance] setCustomTargeting:@"targeting2" withValue:@"value2"]; + XCTAssertNotNil([[PBTargetingParams sharedInstance] customKeywords]); + [[PBTargetingParams sharedInstance] removeCustomKeywords]; + XCTAssertNil([[PBTargetingParams sharedInstance] customKeywords]); +} + +@end diff --git a/sdk/PrebidMobileTests/Resources/PCKeywordsManagerPriceIntervals.txt b/sdk/PrebidMobileTests/Resources/PCKeywordsManagerPriceIntervals.txt new file mode 100644 index 000000000..74bde15be --- /dev/null +++ b/sdk/PrebidMobileTests/Resources/PCKeywordsManagerPriceIntervals.txt @@ -0,0 +1,90002 @@ +Test keywords dictionaries for PCKeywordsManagerTests + +0.00 +pb_1c : 0.00 +pb_5c : 0.00 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.01 +pb_1c : 0.01 +pb_5c : 0.00 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.02 +pb_1c : 0.02 +pb_5c : 0.00 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.03 +pb_1c : 0.03 +pb_5c : 0.00 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.04 +pb_1c : 0.04 +pb_5c : 0.00 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.05 +pb_1c : 0.05 +pb_5c : 0.05 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.06 +pb_1c : 0.06 +pb_5c : 0.05 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.07 +pb_1c : 0.07 +pb_5c : 0.05 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.08 +pb_1c : 0.08 +pb_5c : 0.05 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.09 +pb_1c : 0.09 +pb_5c : 0.05 +pb_10c : 0.00 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.10 +pb_1c : 0.10 +pb_5c : 0.10 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.11 +pb_1c : 0.11 +pb_5c : 0.10 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.12 +pb_1c : 0.12 +pb_5c : 0.10 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.13 +pb_1c : 0.13 +pb_5c : 0.10 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.14 +pb_1c : 0.14 +pb_5c : 0.10 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.15 +pb_1c : 0.15 +pb_5c : 0.15 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.16 +pb_1c : 0.16 +pb_5c : 0.15 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.17 +pb_1c : 0.17 +pb_5c : 0.15 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.18 +pb_1c : 0.18 +pb_5c : 0.15 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.19 +pb_1c : 0.19 +pb_5c : 0.15 +pb_10c : 0.10 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.20 +pb_1c : 0.20 +pb_5c : 0.20 +pb_10c : 0.20 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.21 +pb_1c : 0.21 +pb_5c : 0.20 +pb_10c : 0.20 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.22 +pb_1c : 0.22 +pb_5c : 0.20 +pb_10c : 0.20 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.23 +pb_1c : 0.23 +pb_5c : 0.20 +pb_10c : 0.20 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.24 +pb_1c : 0.24 +pb_5c : 0.20 +pb_10c : 0.20 +pb_25c : 0.00 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.25 +pb_1c : 0.25 +pb_5c : 0.25 +pb_10c : 0.20 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.26 +pb_1c : 0.26 +pb_5c : 0.25 +pb_10c : 0.20 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.27 +pb_1c : 0.27 +pb_5c : 0.25 +pb_10c : 0.20 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.28 +pb_1c : 0.28 +pb_5c : 0.25 +pb_10c : 0.20 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.29 +pb_1c : 0.29 +pb_5c : 0.25 +pb_10c : 0.20 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.30 +pb_1c : 0.30 +pb_5c : 0.30 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.31 +pb_1c : 0.31 +pb_5c : 0.30 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.32 +pb_1c : 0.32 +pb_5c : 0.30 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.33 +pb_1c : 0.33 +pb_5c : 0.30 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.34 +pb_1c : 0.34 +pb_5c : 0.30 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.35 +pb_1c : 0.35 +pb_5c : 0.35 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.36 +pb_1c : 0.36 +pb_5c : 0.35 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.37 +pb_1c : 0.37 +pb_5c : 0.35 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.38 +pb_1c : 0.38 +pb_5c : 0.35 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.39 +pb_1c : 0.39 +pb_5c : 0.35 +pb_10c : 0.30 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.40 +pb_1c : 0.40 +pb_5c : 0.40 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.41 +pb_1c : 0.41 +pb_5c : 0.40 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.42 +pb_1c : 0.42 +pb_5c : 0.40 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.43 +pb_1c : 0.43 +pb_5c : 0.40 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.44 +pb_1c : 0.44 +pb_5c : 0.40 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.45 +pb_1c : 0.45 +pb_5c : 0.45 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.46 +pb_1c : 0.46 +pb_5c : 0.45 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.47 +pb_1c : 0.47 +pb_5c : 0.45 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.48 +pb_1c : 0.48 +pb_5c : 0.45 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.49 +pb_1c : 0.49 +pb_5c : 0.45 +pb_10c : 0.40 +pb_25c : 0.25 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.50 +pb_1c : 0.50 +pb_5c : 0.50 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.51 +pb_1c : 0.51 +pb_5c : 0.50 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.52 +pb_1c : 0.52 +pb_5c : 0.50 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.53 +pb_1c : 0.53 +pb_5c : 0.50 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.54 +pb_1c : 0.54 +pb_5c : 0.50 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.55 +pb_1c : 0.55 +pb_5c : 0.55 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.56 +pb_1c : 0.56 +pb_5c : 0.55 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.57 +pb_1c : 0.57 +pb_5c : 0.55 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.58 +pb_1c : 0.58 +pb_5c : 0.55 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.59 +pb_1c : 0.59 +pb_5c : 0.55 +pb_10c : 0.50 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.60 +pb_1c : 0.60 +pb_5c : 0.60 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.61 +pb_1c : 0.61 +pb_5c : 0.60 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.62 +pb_1c : 0.62 +pb_5c : 0.60 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.63 +pb_1c : 0.63 +pb_5c : 0.60 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.64 +pb_1c : 0.64 +pb_5c : 0.60 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.65 +pb_1c : 0.65 +pb_5c : 0.65 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.66 +pb_1c : 0.66 +pb_5c : 0.65 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.67 +pb_1c : 0.67 +pb_5c : 0.65 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.68 +pb_1c : 0.68 +pb_5c : 0.65 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.69 +pb_1c : 0.69 +pb_5c : 0.65 +pb_10c : 0.60 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.70 +pb_1c : 0.70 +pb_5c : 0.70 +pb_10c : 0.70 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.71 +pb_1c : 0.71 +pb_5c : 0.70 +pb_10c : 0.70 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.72 +pb_1c : 0.72 +pb_5c : 0.70 +pb_10c : 0.70 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.73 +pb_1c : 0.73 +pb_5c : 0.70 +pb_10c : 0.70 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.74 +pb_1c : 0.74 +pb_5c : 0.70 +pb_10c : 0.70 +pb_25c : 0.50 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.75 +pb_1c : 0.75 +pb_5c : 0.75 +pb_10c : 0.70 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.76 +pb_1c : 0.76 +pb_5c : 0.75 +pb_10c : 0.70 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.77 +pb_1c : 0.77 +pb_5c : 0.75 +pb_10c : 0.70 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.78 +pb_1c : 0.78 +pb_5c : 0.75 +pb_10c : 0.70 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.79 +pb_1c : 0.79 +pb_5c : 0.75 +pb_10c : 0.70 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.80 +pb_1c : 0.80 +pb_5c : 0.80 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.81 +pb_1c : 0.81 +pb_5c : 0.80 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.82 +pb_1c : 0.82 +pb_5c : 0.80 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.83 +pb_1c : 0.83 +pb_5c : 0.80 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.84 +pb_1c : 0.84 +pb_5c : 0.80 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.85 +pb_1c : 0.85 +pb_5c : 0.85 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.86 +pb_1c : 0.86 +pb_5c : 0.85 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.87 +pb_1c : 0.87 +pb_5c : 0.85 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.88 +pb_1c : 0.88 +pb_5c : 0.85 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.89 +pb_1c : 0.89 +pb_5c : 0.85 +pb_10c : 0.80 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.90 +pb_1c : 0.90 +pb_5c : 0.90 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.91 +pb_1c : 0.91 +pb_5c : 0.90 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.92 +pb_1c : 0.92 +pb_5c : 0.90 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.93 +pb_1c : 0.93 +pb_5c : 0.90 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.94 +pb_1c : 0.94 +pb_5c : 0.90 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.95 +pb_1c : 0.95 +pb_5c : 0.95 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.96 +pb_1c : 0.96 +pb_5c : 0.95 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.97 +pb_1c : 0.97 +pb_5c : 0.95 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.98 +pb_1c : 0.98 +pb_5c : 0.95 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +0.99 +pb_1c : 0.99 +pb_5c : 0.95 +pb_10c : 0.90 +pb_25c : 0.75 +pb_1d : 0.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.00 +pb_1c : 1.00 +pb_5c : 1.00 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.01 +pb_1c : 1.01 +pb_5c : 1.00 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.02 +pb_1c : 1.02 +pb_5c : 1.00 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.03 +pb_1c : 1.03 +pb_5c : 1.00 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.04 +pb_1c : 1.04 +pb_5c : 1.00 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.05 +pb_1c : 1.05 +pb_5c : 1.05 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.06 +pb_1c : 1.06 +pb_5c : 1.05 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.07 +pb_1c : 1.07 +pb_5c : 1.05 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.08 +pb_1c : 1.08 +pb_5c : 1.05 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.09 +pb_1c : 1.09 +pb_5c : 1.05 +pb_10c : 1.00 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.10 +pb_1c : 1.10 +pb_5c : 1.10 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.11 +pb_1c : 1.11 +pb_5c : 1.10 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.12 +pb_1c : 1.12 +pb_5c : 1.10 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.13 +pb_1c : 1.13 +pb_5c : 1.10 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.14 +pb_1c : 1.14 +pb_5c : 1.10 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.15 +pb_1c : 1.15 +pb_5c : 1.15 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.16 +pb_1c : 1.16 +pb_5c : 1.15 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.17 +pb_1c : 1.17 +pb_5c : 1.15 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.18 +pb_1c : 1.18 +pb_5c : 1.15 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.19 +pb_1c : 1.19 +pb_5c : 1.15 +pb_10c : 1.10 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.20 +pb_1c : 1.20 +pb_5c : 1.20 +pb_10c : 1.20 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.21 +pb_1c : 1.21 +pb_5c : 1.20 +pb_10c : 1.20 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.22 +pb_1c : 1.22 +pb_5c : 1.20 +pb_10c : 1.20 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.23 +pb_1c : 1.23 +pb_5c : 1.20 +pb_10c : 1.20 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.24 +pb_1c : 1.24 +pb_5c : 1.20 +pb_10c : 1.20 +pb_25c : 1.00 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.25 +pb_1c : 1.25 +pb_5c : 1.25 +pb_10c : 1.20 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.26 +pb_1c : 1.26 +pb_5c : 1.25 +pb_10c : 1.20 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.27 +pb_1c : 1.27 +pb_5c : 1.25 +pb_10c : 1.20 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.28 +pb_1c : 1.28 +pb_5c : 1.25 +pb_10c : 1.20 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.29 +pb_1c : 1.29 +pb_5c : 1.25 +pb_10c : 1.20 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.30 +pb_1c : 1.30 +pb_5c : 1.30 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.31 +pb_1c : 1.31 +pb_5c : 1.30 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.32 +pb_1c : 1.32 +pb_5c : 1.30 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.33 +pb_1c : 1.33 +pb_5c : 1.30 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.34 +pb_1c : 1.34 +pb_5c : 1.30 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.35 +pb_1c : 1.35 +pb_5c : 1.35 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.36 +pb_1c : 1.36 +pb_5c : 1.35 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.37 +pb_1c : 1.37 +pb_5c : 1.35 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.38 +pb_1c : 1.38 +pb_5c : 1.35 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.39 +pb_1c : 1.39 +pb_5c : 1.35 +pb_10c : 1.30 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.40 +pb_1c : 1.40 +pb_5c : 1.40 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.41 +pb_1c : 1.41 +pb_5c : 1.40 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.42 +pb_1c : 1.42 +pb_5c : 1.40 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.43 +pb_1c : 1.43 +pb_5c : 1.40 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.44 +pb_1c : 1.44 +pb_5c : 1.40 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.45 +pb_1c : 1.45 +pb_5c : 1.45 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.46 +pb_1c : 1.46 +pb_5c : 1.45 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.47 +pb_1c : 1.47 +pb_5c : 1.45 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.48 +pb_1c : 1.48 +pb_5c : 1.45 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.49 +pb_1c : 1.49 +pb_5c : 1.45 +pb_10c : 1.40 +pb_25c : 1.25 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.50 +pb_1c : 1.50 +pb_5c : 1.50 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.51 +pb_1c : 1.51 +pb_5c : 1.50 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.52 +pb_1c : 1.52 +pb_5c : 1.50 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.53 +pb_1c : 1.53 +pb_5c : 1.50 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.54 +pb_1c : 1.54 +pb_5c : 1.50 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.55 +pb_1c : 1.55 +pb_5c : 1.55 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.56 +pb_1c : 1.56 +pb_5c : 1.55 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.57 +pb_1c : 1.57 +pb_5c : 1.55 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.58 +pb_1c : 1.58 +pb_5c : 1.55 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.59 +pb_1c : 1.59 +pb_5c : 1.55 +pb_10c : 1.50 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.60 +pb_1c : 1.60 +pb_5c : 1.60 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.61 +pb_1c : 1.61 +pb_5c : 1.60 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.62 +pb_1c : 1.62 +pb_5c : 1.60 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.63 +pb_1c : 1.63 +pb_5c : 1.60 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.64 +pb_1c : 1.64 +pb_5c : 1.60 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.65 +pb_1c : 1.65 +pb_5c : 1.65 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.66 +pb_1c : 1.66 +pb_5c : 1.65 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.67 +pb_1c : 1.67 +pb_5c : 1.65 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.68 +pb_1c : 1.68 +pb_5c : 1.65 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.69 +pb_1c : 1.69 +pb_5c : 1.65 +pb_10c : 1.60 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.70 +pb_1c : 1.70 +pb_5c : 1.70 +pb_10c : 1.70 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.71 +pb_1c : 1.71 +pb_5c : 1.70 +pb_10c : 1.70 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.72 +pb_1c : 1.72 +pb_5c : 1.70 +pb_10c : 1.70 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.73 +pb_1c : 1.73 +pb_5c : 1.70 +pb_10c : 1.70 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.74 +pb_1c : 1.74 +pb_5c : 1.70 +pb_10c : 1.70 +pb_25c : 1.50 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.75 +pb_1c : 1.75 +pb_5c : 1.75 +pb_10c : 1.70 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.76 +pb_1c : 1.76 +pb_5c : 1.75 +pb_10c : 1.70 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.77 +pb_1c : 1.77 +pb_5c : 1.75 +pb_10c : 1.70 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.78 +pb_1c : 1.78 +pb_5c : 1.75 +pb_10c : 1.70 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.79 +pb_1c : 1.79 +pb_5c : 1.75 +pb_10c : 1.70 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.80 +pb_1c : 1.80 +pb_5c : 1.80 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.81 +pb_1c : 1.81 +pb_5c : 1.80 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.82 +pb_1c : 1.82 +pb_5c : 1.80 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.83 +pb_1c : 1.83 +pb_5c : 1.80 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.84 +pb_1c : 1.84 +pb_5c : 1.80 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.85 +pb_1c : 1.85 +pb_5c : 1.85 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.86 +pb_1c : 1.86 +pb_5c : 1.85 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.87 +pb_1c : 1.87 +pb_5c : 1.85 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.88 +pb_1c : 1.88 +pb_5c : 1.85 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.89 +pb_1c : 1.89 +pb_5c : 1.85 +pb_10c : 1.80 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.90 +pb_1c : 1.90 +pb_5c : 1.90 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.91 +pb_1c : 1.91 +pb_5c : 1.90 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.92 +pb_1c : 1.92 +pb_5c : 1.90 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.93 +pb_1c : 1.93 +pb_5c : 1.90 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.94 +pb_1c : 1.94 +pb_5c : 1.90 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.95 +pb_1c : 1.95 +pb_5c : 1.95 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.96 +pb_1c : 1.96 +pb_5c : 1.95 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.97 +pb_1c : 1.97 +pb_5c : 1.95 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.98 +pb_1c : 1.98 +pb_5c : 1.95 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +1.99 +pb_1c : 1.99 +pb_5c : 1.95 +pb_10c : 1.90 +pb_25c : 1.75 +pb_1d : 1.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.00 +pb_1c : 2.00 +pb_5c : 2.00 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.01 +pb_1c : 2.01 +pb_5c : 2.00 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.02 +pb_1c : 2.02 +pb_5c : 2.00 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.03 +pb_1c : 2.03 +pb_5c : 2.00 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.04 +pb_1c : 2.04 +pb_5c : 2.00 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.05 +pb_1c : 2.05 +pb_5c : 2.05 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.06 +pb_1c : 2.06 +pb_5c : 2.05 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.07 +pb_1c : 2.07 +pb_5c : 2.05 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.08 +pb_1c : 2.08 +pb_5c : 2.05 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.09 +pb_1c : 2.09 +pb_5c : 2.05 +pb_10c : 2.00 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.10 +pb_1c : 2.10 +pb_5c : 2.10 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.11 +pb_1c : 2.11 +pb_5c : 2.10 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.12 +pb_1c : 2.12 +pb_5c : 2.10 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.13 +pb_1c : 2.13 +pb_5c : 2.10 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.14 +pb_1c : 2.14 +pb_5c : 2.10 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.15 +pb_1c : 2.15 +pb_5c : 2.15 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.16 +pb_1c : 2.16 +pb_5c : 2.15 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.17 +pb_1c : 2.17 +pb_5c : 2.15 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.18 +pb_1c : 2.18 +pb_5c : 2.15 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.19 +pb_1c : 2.19 +pb_5c : 2.15 +pb_10c : 2.10 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.20 +pb_1c : 2.20 +pb_5c : 2.20 +pb_10c : 2.20 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.21 +pb_1c : 2.21 +pb_5c : 2.20 +pb_10c : 2.20 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.22 +pb_1c : 2.22 +pb_5c : 2.20 +pb_10c : 2.20 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.23 +pb_1c : 2.23 +pb_5c : 2.20 +pb_10c : 2.20 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.24 +pb_1c : 2.24 +pb_5c : 2.20 +pb_10c : 2.20 +pb_25c : 2.00 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.25 +pb_1c : 2.25 +pb_5c : 2.25 +pb_10c : 2.20 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.26 +pb_1c : 2.26 +pb_5c : 2.25 +pb_10c : 2.20 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.27 +pb_1c : 2.27 +pb_5c : 2.25 +pb_10c : 2.20 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.28 +pb_1c : 2.28 +pb_5c : 2.25 +pb_10c : 2.20 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.29 +pb_1c : 2.29 +pb_5c : 2.25 +pb_10c : 2.20 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.30 +pb_1c : 2.30 +pb_5c : 2.30 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.31 +pb_1c : 2.31 +pb_5c : 2.30 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.32 +pb_1c : 2.32 +pb_5c : 2.30 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.33 +pb_1c : 2.33 +pb_5c : 2.30 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.34 +pb_1c : 2.34 +pb_5c : 2.30 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.35 +pb_1c : 2.35 +pb_5c : 2.35 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.36 +pb_1c : 2.36 +pb_5c : 2.35 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.37 +pb_1c : 2.37 +pb_5c : 2.35 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.38 +pb_1c : 2.38 +pb_5c : 2.35 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.39 +pb_1c : 2.39 +pb_5c : 2.35 +pb_10c : 2.30 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.40 +pb_1c : 2.40 +pb_5c : 2.40 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.41 +pb_1c : 2.41 +pb_5c : 2.40 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.42 +pb_1c : 2.42 +pb_5c : 2.40 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.43 +pb_1c : 2.43 +pb_5c : 2.40 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.44 +pb_1c : 2.44 +pb_5c : 2.40 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.45 +pb_1c : 2.45 +pb_5c : 2.45 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.46 +pb_1c : 2.46 +pb_5c : 2.45 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.47 +pb_1c : 2.47 +pb_5c : 2.45 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.48 +pb_1c : 2.48 +pb_5c : 2.45 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.49 +pb_1c : 2.49 +pb_5c : 2.45 +pb_10c : 2.40 +pb_25c : 2.25 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.50 +pb_1c : 2.50 +pb_5c : 2.50 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.51 +pb_1c : 2.51 +pb_5c : 2.50 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.52 +pb_1c : 2.52 +pb_5c : 2.50 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.53 +pb_1c : 2.53 +pb_5c : 2.50 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.54 +pb_1c : 2.54 +pb_5c : 2.50 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.55 +pb_1c : 2.55 +pb_5c : 2.55 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.56 +pb_1c : 2.56 +pb_5c : 2.55 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.57 +pb_1c : 2.57 +pb_5c : 2.55 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.58 +pb_1c : 2.58 +pb_5c : 2.55 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.59 +pb_1c : 2.59 +pb_5c : 2.55 +pb_10c : 2.50 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.60 +pb_1c : 2.60 +pb_5c : 2.60 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.61 +pb_1c : 2.61 +pb_5c : 2.60 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.62 +pb_1c : 2.62 +pb_5c : 2.60 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.63 +pb_1c : 2.63 +pb_5c : 2.60 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.64 +pb_1c : 2.64 +pb_5c : 2.60 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.65 +pb_1c : 2.65 +pb_5c : 2.65 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.66 +pb_1c : 2.66 +pb_5c : 2.65 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.67 +pb_1c : 2.67 +pb_5c : 2.65 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.68 +pb_1c : 2.68 +pb_5c : 2.65 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.69 +pb_1c : 2.69 +pb_5c : 2.65 +pb_10c : 2.60 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.70 +pb_1c : 2.70 +pb_5c : 2.70 +pb_10c : 2.70 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.71 +pb_1c : 2.71 +pb_5c : 2.70 +pb_10c : 2.70 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.72 +pb_1c : 2.72 +pb_5c : 2.70 +pb_10c : 2.70 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.73 +pb_1c : 2.73 +pb_5c : 2.70 +pb_10c : 2.70 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.74 +pb_1c : 2.74 +pb_5c : 2.70 +pb_10c : 2.70 +pb_25c : 2.50 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.75 +pb_1c : 2.75 +pb_5c : 2.75 +pb_10c : 2.70 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.76 +pb_1c : 2.76 +pb_5c : 2.75 +pb_10c : 2.70 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.77 +pb_1c : 2.77 +pb_5c : 2.75 +pb_10c : 2.70 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.78 +pb_1c : 2.78 +pb_5c : 2.75 +pb_10c : 2.70 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.79 +pb_1c : 2.79 +pb_5c : 2.75 +pb_10c : 2.70 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.80 +pb_1c : 2.80 +pb_5c : 2.80 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.81 +pb_1c : 2.81 +pb_5c : 2.80 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.82 +pb_1c : 2.82 +pb_5c : 2.80 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.83 +pb_1c : 2.83 +pb_5c : 2.80 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.84 +pb_1c : 2.84 +pb_5c : 2.80 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.85 +pb_1c : 2.85 +pb_5c : 2.85 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.86 +pb_1c : 2.86 +pb_5c : 2.85 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.87 +pb_1c : 2.87 +pb_5c : 2.85 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.88 +pb_1c : 2.88 +pb_5c : 2.85 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.89 +pb_1c : 2.89 +pb_5c : 2.85 +pb_10c : 2.80 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.90 +pb_1c : 2.90 +pb_5c : 2.90 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.91 +pb_1c : 2.91 +pb_5c : 2.90 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.92 +pb_1c : 2.92 +pb_5c : 2.90 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.93 +pb_1c : 2.93 +pb_5c : 2.90 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.94 +pb_1c : 2.94 +pb_5c : 2.90 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.95 +pb_1c : 2.95 +pb_5c : 2.95 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.96 +pb_1c : 2.96 +pb_5c : 2.95 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.97 +pb_1c : 2.97 +pb_5c : 2.95 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.98 +pb_1c : 2.98 +pb_5c : 2.95 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +2.99 +pb_1c : 2.99 +pb_5c : 2.95 +pb_10c : 2.90 +pb_25c : 2.75 +pb_1d : 2.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.00 +pb_1c : 3.00 +pb_5c : 3.00 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.01 +pb_1c : 3.01 +pb_5c : 3.00 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.02 +pb_1c : 3.02 +pb_5c : 3.00 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.03 +pb_1c : 3.03 +pb_5c : 3.00 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.04 +pb_1c : 3.04 +pb_5c : 3.00 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.05 +pb_1c : 3.05 +pb_5c : 3.05 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.06 +pb_1c : 3.06 +pb_5c : 3.05 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.07 +pb_1c : 3.07 +pb_5c : 3.05 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.08 +pb_1c : 3.08 +pb_5c : 3.05 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.09 +pb_1c : 3.09 +pb_5c : 3.05 +pb_10c : 3.00 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.10 +pb_1c : 3.10 +pb_5c : 3.10 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.11 +pb_1c : 3.11 +pb_5c : 3.10 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.12 +pb_1c : 3.12 +pb_5c : 3.10 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.13 +pb_1c : 3.13 +pb_5c : 3.10 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.14 +pb_1c : 3.14 +pb_5c : 3.10 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.15 +pb_1c : 3.15 +pb_5c : 3.15 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.16 +pb_1c : 3.16 +pb_5c : 3.15 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.17 +pb_1c : 3.17 +pb_5c : 3.15 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.18 +pb_1c : 3.18 +pb_5c : 3.15 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.19 +pb_1c : 3.19 +pb_5c : 3.15 +pb_10c : 3.10 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.20 +pb_1c : 3.20 +pb_5c : 3.20 +pb_10c : 3.20 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.21 +pb_1c : 3.21 +pb_5c : 3.20 +pb_10c : 3.20 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.22 +pb_1c : 3.22 +pb_5c : 3.20 +pb_10c : 3.20 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.23 +pb_1c : 3.23 +pb_5c : 3.20 +pb_10c : 3.20 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.24 +pb_1c : 3.24 +pb_5c : 3.20 +pb_10c : 3.20 +pb_25c : 3.00 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.25 +pb_1c : 3.25 +pb_5c : 3.25 +pb_10c : 3.20 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.26 +pb_1c : 3.26 +pb_5c : 3.25 +pb_10c : 3.20 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.27 +pb_1c : 3.27 +pb_5c : 3.25 +pb_10c : 3.20 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.28 +pb_1c : 3.28 +pb_5c : 3.25 +pb_10c : 3.20 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.29 +pb_1c : 3.29 +pb_5c : 3.25 +pb_10c : 3.20 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.30 +pb_1c : 3.30 +pb_5c : 3.30 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.31 +pb_1c : 3.31 +pb_5c : 3.30 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.32 +pb_1c : 3.32 +pb_5c : 3.30 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.33 +pb_1c : 3.33 +pb_5c : 3.30 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.34 +pb_1c : 3.34 +pb_5c : 3.30 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.35 +pb_1c : 3.35 +pb_5c : 3.35 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.36 +pb_1c : 3.36 +pb_5c : 3.35 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.37 +pb_1c : 3.37 +pb_5c : 3.35 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.38 +pb_1c : 3.38 +pb_5c : 3.35 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.39 +pb_1c : 3.39 +pb_5c : 3.35 +pb_10c : 3.30 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.40 +pb_1c : 3.40 +pb_5c : 3.40 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.41 +pb_1c : 3.41 +pb_5c : 3.40 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.42 +pb_1c : 3.42 +pb_5c : 3.40 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.43 +pb_1c : 3.43 +pb_5c : 3.40 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.44 +pb_1c : 3.44 +pb_5c : 3.40 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.45 +pb_1c : 3.45 +pb_5c : 3.45 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.46 +pb_1c : 3.46 +pb_5c : 3.45 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.47 +pb_1c : 3.47 +pb_5c : 3.45 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.48 +pb_1c : 3.48 +pb_5c : 3.45 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.49 +pb_1c : 3.49 +pb_5c : 3.45 +pb_10c : 3.40 +pb_25c : 3.25 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.50 +pb_1c : 3.50 +pb_5c : 3.50 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.51 +pb_1c : 3.51 +pb_5c : 3.50 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.52 +pb_1c : 3.52 +pb_5c : 3.50 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.53 +pb_1c : 3.53 +pb_5c : 3.50 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.54 +pb_1c : 3.54 +pb_5c : 3.50 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.55 +pb_1c : 3.55 +pb_5c : 3.55 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.56 +pb_1c : 3.56 +pb_5c : 3.55 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.57 +pb_1c : 3.57 +pb_5c : 3.55 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.58 +pb_1c : 3.58 +pb_5c : 3.55 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.59 +pb_1c : 3.59 +pb_5c : 3.55 +pb_10c : 3.50 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.60 +pb_1c : 3.60 +pb_5c : 3.60 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.61 +pb_1c : 3.61 +pb_5c : 3.60 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.62 +pb_1c : 3.62 +pb_5c : 3.60 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.63 +pb_1c : 3.63 +pb_5c : 3.60 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.64 +pb_1c : 3.64 +pb_5c : 3.60 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.65 +pb_1c : 3.65 +pb_5c : 3.65 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.66 +pb_1c : 3.66 +pb_5c : 3.65 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.67 +pb_1c : 3.67 +pb_5c : 3.65 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.68 +pb_1c : 3.68 +pb_5c : 3.65 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.69 +pb_1c : 3.69 +pb_5c : 3.65 +pb_10c : 3.60 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.70 +pb_1c : 3.70 +pb_5c : 3.70 +pb_10c : 3.70 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.71 +pb_1c : 3.71 +pb_5c : 3.70 +pb_10c : 3.70 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.72 +pb_1c : 3.72 +pb_5c : 3.70 +pb_10c : 3.70 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.73 +pb_1c : 3.73 +pb_5c : 3.70 +pb_10c : 3.70 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.74 +pb_1c : 3.74 +pb_5c : 3.70 +pb_10c : 3.70 +pb_25c : 3.50 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.75 +pb_1c : 3.75 +pb_5c : 3.75 +pb_10c : 3.70 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.76 +pb_1c : 3.76 +pb_5c : 3.75 +pb_10c : 3.70 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.77 +pb_1c : 3.77 +pb_5c : 3.75 +pb_10c : 3.70 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.78 +pb_1c : 3.78 +pb_5c : 3.75 +pb_10c : 3.70 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.79 +pb_1c : 3.79 +pb_5c : 3.75 +pb_10c : 3.70 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.80 +pb_1c : 3.80 +pb_5c : 3.80 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.81 +pb_1c : 3.81 +pb_5c : 3.80 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.82 +pb_1c : 3.82 +pb_5c : 3.80 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.83 +pb_1c : 3.83 +pb_5c : 3.80 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.84 +pb_1c : 3.84 +pb_5c : 3.80 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.85 +pb_1c : 3.85 +pb_5c : 3.85 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.86 +pb_1c : 3.86 +pb_5c : 3.85 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.87 +pb_1c : 3.87 +pb_5c : 3.85 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.88 +pb_1c : 3.88 +pb_5c : 3.85 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.89 +pb_1c : 3.89 +pb_5c : 3.85 +pb_10c : 3.80 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.90 +pb_1c : 3.90 +pb_5c : 3.90 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.91 +pb_1c : 3.91 +pb_5c : 3.90 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.92 +pb_1c : 3.92 +pb_5c : 3.90 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.93 +pb_1c : 3.93 +pb_5c : 3.90 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.94 +pb_1c : 3.94 +pb_5c : 3.90 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.95 +pb_1c : 3.95 +pb_5c : 3.95 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.96 +pb_1c : 3.96 +pb_5c : 3.95 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.97 +pb_1c : 3.97 +pb_5c : 3.95 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.98 +pb_1c : 3.98 +pb_5c : 3.95 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +3.99 +pb_1c : 3.99 +pb_5c : 3.95 +pb_10c : 3.90 +pb_25c : 3.75 +pb_1d : 3.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.00 +pb_1c : 4.00 +pb_5c : 4.00 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.01 +pb_1c : 4.01 +pb_5c : 4.00 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.02 +pb_1c : 4.02 +pb_5c : 4.00 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.03 +pb_1c : 4.03 +pb_5c : 4.00 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.04 +pb_1c : 4.04 +pb_5c : 4.00 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.05 +pb_1c : 4.05 +pb_5c : 4.05 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.06 +pb_1c : 4.06 +pb_5c : 4.05 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.07 +pb_1c : 4.07 +pb_5c : 4.05 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.08 +pb_1c : 4.08 +pb_5c : 4.05 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.09 +pb_1c : 4.09 +pb_5c : 4.05 +pb_10c : 4.00 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.10 +pb_1c : 4.10 +pb_5c : 4.10 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.11 +pb_1c : 4.11 +pb_5c : 4.10 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.12 +pb_1c : 4.12 +pb_5c : 4.10 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.13 +pb_1c : 4.13 +pb_5c : 4.10 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.14 +pb_1c : 4.14 +pb_5c : 4.10 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.15 +pb_1c : 4.15 +pb_5c : 4.15 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.16 +pb_1c : 4.16 +pb_5c : 4.15 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.17 +pb_1c : 4.17 +pb_5c : 4.15 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.18 +pb_1c : 4.18 +pb_5c : 4.15 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.19 +pb_1c : 4.19 +pb_5c : 4.15 +pb_10c : 4.10 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.20 +pb_1c : 4.20 +pb_5c : 4.20 +pb_10c : 4.20 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.21 +pb_1c : 4.21 +pb_5c : 4.20 +pb_10c : 4.20 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.22 +pb_1c : 4.22 +pb_5c : 4.20 +pb_10c : 4.20 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.23 +pb_1c : 4.23 +pb_5c : 4.20 +pb_10c : 4.20 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.24 +pb_1c : 4.24 +pb_5c : 4.20 +pb_10c : 4.20 +pb_25c : 4.00 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.25 +pb_1c : 4.25 +pb_5c : 4.25 +pb_10c : 4.20 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.26 +pb_1c : 4.26 +pb_5c : 4.25 +pb_10c : 4.20 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.27 +pb_1c : 4.27 +pb_5c : 4.25 +pb_10c : 4.20 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.28 +pb_1c : 4.28 +pb_5c : 4.25 +pb_10c : 4.20 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.29 +pb_1c : 4.29 +pb_5c : 4.25 +pb_10c : 4.20 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.30 +pb_1c : 4.30 +pb_5c : 4.30 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.31 +pb_1c : 4.31 +pb_5c : 4.30 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.32 +pb_1c : 4.32 +pb_5c : 4.30 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.33 +pb_1c : 4.33 +pb_5c : 4.30 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.34 +pb_1c : 4.34 +pb_5c : 4.30 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.35 +pb_1c : 4.35 +pb_5c : 4.35 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.36 +pb_1c : 4.36 +pb_5c : 4.35 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.37 +pb_1c : 4.37 +pb_5c : 4.35 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.38 +pb_1c : 4.38 +pb_5c : 4.35 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.39 +pb_1c : 4.39 +pb_5c : 4.35 +pb_10c : 4.30 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.40 +pb_1c : 4.40 +pb_5c : 4.40 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.41 +pb_1c : 4.41 +pb_5c : 4.40 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.42 +pb_1c : 4.42 +pb_5c : 4.40 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.43 +pb_1c : 4.43 +pb_5c : 4.40 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.44 +pb_1c : 4.44 +pb_5c : 4.40 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.45 +pb_1c : 4.45 +pb_5c : 4.45 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.46 +pb_1c : 4.46 +pb_5c : 4.45 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.47 +pb_1c : 4.47 +pb_5c : 4.45 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.48 +pb_1c : 4.48 +pb_5c : 4.45 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.49 +pb_1c : 4.49 +pb_5c : 4.45 +pb_10c : 4.40 +pb_25c : 4.25 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.50 +pb_1c : 4.50 +pb_5c : 4.50 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.51 +pb_1c : 4.51 +pb_5c : 4.50 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.52 +pb_1c : 4.52 +pb_5c : 4.50 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.53 +pb_1c : 4.53 +pb_5c : 4.50 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.54 +pb_1c : 4.54 +pb_5c : 4.50 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.55 +pb_1c : 4.55 +pb_5c : 4.55 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.56 +pb_1c : 4.56 +pb_5c : 4.55 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.57 +pb_1c : 4.57 +pb_5c : 4.55 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.58 +pb_1c : 4.58 +pb_5c : 4.55 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.59 +pb_1c : 4.59 +pb_5c : 4.55 +pb_10c : 4.50 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.60 +pb_1c : 4.60 +pb_5c : 4.60 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.61 +pb_1c : 4.61 +pb_5c : 4.60 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.62 +pb_1c : 4.62 +pb_5c : 4.60 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.63 +pb_1c : 4.63 +pb_5c : 4.60 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.64 +pb_1c : 4.64 +pb_5c : 4.60 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.65 +pb_1c : 4.65 +pb_5c : 4.65 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.66 +pb_1c : 4.66 +pb_5c : 4.65 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.67 +pb_1c : 4.67 +pb_5c : 4.65 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.68 +pb_1c : 4.68 +pb_5c : 4.65 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.69 +pb_1c : 4.69 +pb_5c : 4.65 +pb_10c : 4.60 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.70 +pb_1c : 4.70 +pb_5c : 4.70 +pb_10c : 4.70 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.71 +pb_1c : 4.71 +pb_5c : 4.70 +pb_10c : 4.70 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.72 +pb_1c : 4.72 +pb_5c : 4.70 +pb_10c : 4.70 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.73 +pb_1c : 4.73 +pb_5c : 4.70 +pb_10c : 4.70 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.74 +pb_1c : 4.74 +pb_5c : 4.70 +pb_10c : 4.70 +pb_25c : 4.50 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.75 +pb_1c : 4.75 +pb_5c : 4.75 +pb_10c : 4.70 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.76 +pb_1c : 4.76 +pb_5c : 4.75 +pb_10c : 4.70 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.77 +pb_1c : 4.77 +pb_5c : 4.75 +pb_10c : 4.70 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.78 +pb_1c : 4.78 +pb_5c : 4.75 +pb_10c : 4.70 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.79 +pb_1c : 4.79 +pb_5c : 4.75 +pb_10c : 4.70 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.80 +pb_1c : 4.80 +pb_5c : 4.80 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.81 +pb_1c : 4.81 +pb_5c : 4.80 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.82 +pb_1c : 4.82 +pb_5c : 4.80 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.83 +pb_1c : 4.83 +pb_5c : 4.80 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.84 +pb_1c : 4.84 +pb_5c : 4.80 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.85 +pb_1c : 4.85 +pb_5c : 4.85 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.86 +pb_1c : 4.86 +pb_5c : 4.85 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.87 +pb_1c : 4.87 +pb_5c : 4.85 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.88 +pb_1c : 4.88 +pb_5c : 4.85 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.89 +pb_1c : 4.89 +pb_5c : 4.85 +pb_10c : 4.80 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.90 +pb_1c : 4.90 +pb_5c : 4.90 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.91 +pb_1c : 4.91 +pb_5c : 4.90 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.92 +pb_1c : 4.92 +pb_5c : 4.90 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.93 +pb_1c : 4.93 +pb_5c : 4.90 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.94 +pb_1c : 4.94 +pb_5c : 4.90 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.95 +pb_1c : 4.95 +pb_5c : 4.95 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.96 +pb_1c : 4.96 +pb_5c : 4.95 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.97 +pb_1c : 4.97 +pb_5c : 4.95 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.98 +pb_1c : 4.98 +pb_5c : 4.95 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +4.99 +pb_1c : 4.99 +pb_5c : 4.95 +pb_10c : 4.90 +pb_25c : 4.75 +pb_1d : 4.00 +pb_5d : 0.00 +pb_10d : 0.00 + +5.00 +pb_1c : 5.00 +pb_5c : 5.00 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.01 +pb_1c : 5.01 +pb_5c : 5.00 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.02 +pb_1c : 5.02 +pb_5c : 5.00 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.03 +pb_1c : 5.03 +pb_5c : 5.00 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.04 +pb_1c : 5.04 +pb_5c : 5.00 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.05 +pb_1c : 5.05 +pb_5c : 5.05 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.06 +pb_1c : 5.06 +pb_5c : 5.05 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.07 +pb_1c : 5.07 +pb_5c : 5.05 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.08 +pb_1c : 5.08 +pb_5c : 5.05 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.09 +pb_1c : 5.09 +pb_5c : 5.05 +pb_10c : 5.00 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.10 +pb_1c : 5.10 +pb_5c : 5.10 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.11 +pb_1c : 5.11 +pb_5c : 5.10 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.12 +pb_1c : 5.12 +pb_5c : 5.10 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.13 +pb_1c : 5.13 +pb_5c : 5.10 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.14 +pb_1c : 5.14 +pb_5c : 5.10 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.15 +pb_1c : 5.15 +pb_5c : 5.15 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.16 +pb_1c : 5.16 +pb_5c : 5.15 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.17 +pb_1c : 5.17 +pb_5c : 5.15 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.18 +pb_1c : 5.18 +pb_5c : 5.15 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.19 +pb_1c : 5.19 +pb_5c : 5.15 +pb_10c : 5.10 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.20 +pb_1c : 5.20 +pb_5c : 5.20 +pb_10c : 5.20 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.21 +pb_1c : 5.21 +pb_5c : 5.20 +pb_10c : 5.20 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.22 +pb_1c : 5.22 +pb_5c : 5.20 +pb_10c : 5.20 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.23 +pb_1c : 5.23 +pb_5c : 5.20 +pb_10c : 5.20 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.24 +pb_1c : 5.24 +pb_5c : 5.20 +pb_10c : 5.20 +pb_25c : 5.00 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.25 +pb_1c : 5.25 +pb_5c : 5.25 +pb_10c : 5.20 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.26 +pb_1c : 5.26 +pb_5c : 5.25 +pb_10c : 5.20 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.27 +pb_1c : 5.27 +pb_5c : 5.25 +pb_10c : 5.20 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.28 +pb_1c : 5.28 +pb_5c : 5.25 +pb_10c : 5.20 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.29 +pb_1c : 5.29 +pb_5c : 5.25 +pb_10c : 5.20 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.30 +pb_1c : 5.30 +pb_5c : 5.30 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.31 +pb_1c : 5.31 +pb_5c : 5.30 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.32 +pb_1c : 5.32 +pb_5c : 5.30 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.33 +pb_1c : 5.33 +pb_5c : 5.30 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.34 +pb_1c : 5.34 +pb_5c : 5.30 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.35 +pb_1c : 5.35 +pb_5c : 5.35 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.36 +pb_1c : 5.36 +pb_5c : 5.35 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.37 +pb_1c : 5.37 +pb_5c : 5.35 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.38 +pb_1c : 5.38 +pb_5c : 5.35 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.39 +pb_1c : 5.39 +pb_5c : 5.35 +pb_10c : 5.30 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.40 +pb_1c : 5.40 +pb_5c : 5.40 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.41 +pb_1c : 5.41 +pb_5c : 5.40 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.42 +pb_1c : 5.42 +pb_5c : 5.40 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.43 +pb_1c : 5.43 +pb_5c : 5.40 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.44 +pb_1c : 5.44 +pb_5c : 5.40 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.45 +pb_1c : 5.45 +pb_5c : 5.45 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.46 +pb_1c : 5.46 +pb_5c : 5.45 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.47 +pb_1c : 5.47 +pb_5c : 5.45 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.48 +pb_1c : 5.48 +pb_5c : 5.45 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.49 +pb_1c : 5.49 +pb_5c : 5.45 +pb_10c : 5.40 +pb_25c : 5.25 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.50 +pb_1c : 5.50 +pb_5c : 5.50 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.51 +pb_1c : 5.51 +pb_5c : 5.50 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.52 +pb_1c : 5.52 +pb_5c : 5.50 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.53 +pb_1c : 5.53 +pb_5c : 5.50 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.54 +pb_1c : 5.54 +pb_5c : 5.50 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.55 +pb_1c : 5.55 +pb_5c : 5.55 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.56 +pb_1c : 5.56 +pb_5c : 5.55 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.57 +pb_1c : 5.57 +pb_5c : 5.55 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.58 +pb_1c : 5.58 +pb_5c : 5.55 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.59 +pb_1c : 5.59 +pb_5c : 5.55 +pb_10c : 5.50 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.60 +pb_1c : 5.60 +pb_5c : 5.60 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.61 +pb_1c : 5.61 +pb_5c : 5.60 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.62 +pb_1c : 5.62 +pb_5c : 5.60 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.63 +pb_1c : 5.63 +pb_5c : 5.60 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.64 +pb_1c : 5.64 +pb_5c : 5.60 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.65 +pb_1c : 5.65 +pb_5c : 5.65 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.66 +pb_1c : 5.66 +pb_5c : 5.65 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.67 +pb_1c : 5.67 +pb_5c : 5.65 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.68 +pb_1c : 5.68 +pb_5c : 5.65 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.69 +pb_1c : 5.69 +pb_5c : 5.65 +pb_10c : 5.60 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.70 +pb_1c : 5.70 +pb_5c : 5.70 +pb_10c : 5.70 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.71 +pb_1c : 5.71 +pb_5c : 5.70 +pb_10c : 5.70 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.72 +pb_1c : 5.72 +pb_5c : 5.70 +pb_10c : 5.70 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.73 +pb_1c : 5.73 +pb_5c : 5.70 +pb_10c : 5.70 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.74 +pb_1c : 5.74 +pb_5c : 5.70 +pb_10c : 5.70 +pb_25c : 5.50 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.75 +pb_1c : 5.75 +pb_5c : 5.75 +pb_10c : 5.70 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.76 +pb_1c : 5.76 +pb_5c : 5.75 +pb_10c : 5.70 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.77 +pb_1c : 5.77 +pb_5c : 5.75 +pb_10c : 5.70 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.78 +pb_1c : 5.78 +pb_5c : 5.75 +pb_10c : 5.70 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.79 +pb_1c : 5.79 +pb_5c : 5.75 +pb_10c : 5.70 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.80 +pb_1c : 5.80 +pb_5c : 5.80 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.81 +pb_1c : 5.81 +pb_5c : 5.80 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.82 +pb_1c : 5.82 +pb_5c : 5.80 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.83 +pb_1c : 5.83 +pb_5c : 5.80 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.84 +pb_1c : 5.84 +pb_5c : 5.80 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.85 +pb_1c : 5.85 +pb_5c : 5.85 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.86 +pb_1c : 5.86 +pb_5c : 5.85 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.87 +pb_1c : 5.87 +pb_5c : 5.85 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.88 +pb_1c : 5.88 +pb_5c : 5.85 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.89 +pb_1c : 5.89 +pb_5c : 5.85 +pb_10c : 5.80 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.90 +pb_1c : 5.90 +pb_5c : 5.90 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.91 +pb_1c : 5.91 +pb_5c : 5.90 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.92 +pb_1c : 5.92 +pb_5c : 5.90 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.93 +pb_1c : 5.93 +pb_5c : 5.90 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.94 +pb_1c : 5.94 +pb_5c : 5.90 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.95 +pb_1c : 5.95 +pb_5c : 5.95 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.96 +pb_1c : 5.96 +pb_5c : 5.95 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.97 +pb_1c : 5.97 +pb_5c : 5.95 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.98 +pb_1c : 5.98 +pb_5c : 5.95 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +5.99 +pb_1c : 5.99 +pb_5c : 5.95 +pb_10c : 5.90 +pb_25c : 5.75 +pb_1d : 5.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.00 +pb_1c : 6.00 +pb_5c : 6.00 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.01 +pb_1c : 6.01 +pb_5c : 6.00 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.02 +pb_1c : 6.02 +pb_5c : 6.00 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.03 +pb_1c : 6.03 +pb_5c : 6.00 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.04 +pb_1c : 6.04 +pb_5c : 6.00 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.05 +pb_1c : 6.05 +pb_5c : 6.05 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.06 +pb_1c : 6.06 +pb_5c : 6.05 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.07 +pb_1c : 6.07 +pb_5c : 6.05 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.08 +pb_1c : 6.08 +pb_5c : 6.05 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.09 +pb_1c : 6.09 +pb_5c : 6.05 +pb_10c : 6.00 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.10 +pb_1c : 6.10 +pb_5c : 6.10 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.11 +pb_1c : 6.11 +pb_5c : 6.10 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.12 +pb_1c : 6.12 +pb_5c : 6.10 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.13 +pb_1c : 6.13 +pb_5c : 6.10 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.14 +pb_1c : 6.14 +pb_5c : 6.10 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.15 +pb_1c : 6.15 +pb_5c : 6.15 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.16 +pb_1c : 6.16 +pb_5c : 6.15 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.17 +pb_1c : 6.17 +pb_5c : 6.15 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.18 +pb_1c : 6.18 +pb_5c : 6.15 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.19 +pb_1c : 6.19 +pb_5c : 6.15 +pb_10c : 6.10 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.20 +pb_1c : 6.20 +pb_5c : 6.20 +pb_10c : 6.20 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.21 +pb_1c : 6.21 +pb_5c : 6.20 +pb_10c : 6.20 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.22 +pb_1c : 6.22 +pb_5c : 6.20 +pb_10c : 6.20 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.23 +pb_1c : 6.23 +pb_5c : 6.20 +pb_10c : 6.20 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.24 +pb_1c : 6.24 +pb_5c : 6.20 +pb_10c : 6.20 +pb_25c : 6.00 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.25 +pb_1c : 6.25 +pb_5c : 6.25 +pb_10c : 6.20 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.26 +pb_1c : 6.26 +pb_5c : 6.25 +pb_10c : 6.20 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.27 +pb_1c : 6.27 +pb_5c : 6.25 +pb_10c : 6.20 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.28 +pb_1c : 6.28 +pb_5c : 6.25 +pb_10c : 6.20 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.29 +pb_1c : 6.29 +pb_5c : 6.25 +pb_10c : 6.20 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.30 +pb_1c : 6.30 +pb_5c : 6.30 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.31 +pb_1c : 6.31 +pb_5c : 6.30 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.32 +pb_1c : 6.32 +pb_5c : 6.30 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.33 +pb_1c : 6.33 +pb_5c : 6.30 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.34 +pb_1c : 6.34 +pb_5c : 6.30 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.35 +pb_1c : 6.35 +pb_5c : 6.35 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.36 +pb_1c : 6.36 +pb_5c : 6.35 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.37 +pb_1c : 6.37 +pb_5c : 6.35 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.38 +pb_1c : 6.38 +pb_5c : 6.35 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.39 +pb_1c : 6.39 +pb_5c : 6.35 +pb_10c : 6.30 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.40 +pb_1c : 6.40 +pb_5c : 6.40 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.41 +pb_1c : 6.41 +pb_5c : 6.40 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.42 +pb_1c : 6.42 +pb_5c : 6.40 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.43 +pb_1c : 6.43 +pb_5c : 6.40 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.44 +pb_1c : 6.44 +pb_5c : 6.40 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.45 +pb_1c : 6.45 +pb_5c : 6.45 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.46 +pb_1c : 6.46 +pb_5c : 6.45 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.47 +pb_1c : 6.47 +pb_5c : 6.45 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.48 +pb_1c : 6.48 +pb_5c : 6.45 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.49 +pb_1c : 6.49 +pb_5c : 6.45 +pb_10c : 6.40 +pb_25c : 6.25 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.50 +pb_1c : 6.50 +pb_5c : 6.50 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.51 +pb_1c : 6.51 +pb_5c : 6.50 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.52 +pb_1c : 6.52 +pb_5c : 6.50 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.53 +pb_1c : 6.53 +pb_5c : 6.50 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.54 +pb_1c : 6.54 +pb_5c : 6.50 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.55 +pb_1c : 6.55 +pb_5c : 6.55 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.56 +pb_1c : 6.56 +pb_5c : 6.55 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.57 +pb_1c : 6.57 +pb_5c : 6.55 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.58 +pb_1c : 6.58 +pb_5c : 6.55 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.59 +pb_1c : 6.59 +pb_5c : 6.55 +pb_10c : 6.50 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.60 +pb_1c : 6.60 +pb_5c : 6.60 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.61 +pb_1c : 6.61 +pb_5c : 6.60 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.62 +pb_1c : 6.62 +pb_5c : 6.60 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.63 +pb_1c : 6.63 +pb_5c : 6.60 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.64 +pb_1c : 6.64 +pb_5c : 6.60 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.65 +pb_1c : 6.65 +pb_5c : 6.65 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.66 +pb_1c : 6.66 +pb_5c : 6.65 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.67 +pb_1c : 6.67 +pb_5c : 6.65 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.68 +pb_1c : 6.68 +pb_5c : 6.65 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.69 +pb_1c : 6.69 +pb_5c : 6.65 +pb_10c : 6.60 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.70 +pb_1c : 6.70 +pb_5c : 6.70 +pb_10c : 6.70 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.71 +pb_1c : 6.71 +pb_5c : 6.70 +pb_10c : 6.70 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.72 +pb_1c : 6.72 +pb_5c : 6.70 +pb_10c : 6.70 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.73 +pb_1c : 6.73 +pb_5c : 6.70 +pb_10c : 6.70 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.74 +pb_1c : 6.74 +pb_5c : 6.70 +pb_10c : 6.70 +pb_25c : 6.50 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.75 +pb_1c : 6.75 +pb_5c : 6.75 +pb_10c : 6.70 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.76 +pb_1c : 6.76 +pb_5c : 6.75 +pb_10c : 6.70 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.77 +pb_1c : 6.77 +pb_5c : 6.75 +pb_10c : 6.70 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.78 +pb_1c : 6.78 +pb_5c : 6.75 +pb_10c : 6.70 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.79 +pb_1c : 6.79 +pb_5c : 6.75 +pb_10c : 6.70 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.80 +pb_1c : 6.80 +pb_5c : 6.80 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.81 +pb_1c : 6.81 +pb_5c : 6.80 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.82 +pb_1c : 6.82 +pb_5c : 6.80 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.83 +pb_1c : 6.83 +pb_5c : 6.80 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.84 +pb_1c : 6.84 +pb_5c : 6.80 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.85 +pb_1c : 6.85 +pb_5c : 6.85 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.86 +pb_1c : 6.86 +pb_5c : 6.85 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.87 +pb_1c : 6.87 +pb_5c : 6.85 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.88 +pb_1c : 6.88 +pb_5c : 6.85 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.89 +pb_1c : 6.89 +pb_5c : 6.85 +pb_10c : 6.80 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.90 +pb_1c : 6.90 +pb_5c : 6.90 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.91 +pb_1c : 6.91 +pb_5c : 6.90 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.92 +pb_1c : 6.92 +pb_5c : 6.90 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.93 +pb_1c : 6.93 +pb_5c : 6.90 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.94 +pb_1c : 6.94 +pb_5c : 6.90 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.95 +pb_1c : 6.95 +pb_5c : 6.95 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.96 +pb_1c : 6.96 +pb_5c : 6.95 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.97 +pb_1c : 6.97 +pb_5c : 6.95 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.98 +pb_1c : 6.98 +pb_5c : 6.95 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +6.99 +pb_1c : 6.99 +pb_5c : 6.95 +pb_10c : 6.90 +pb_25c : 6.75 +pb_1d : 6.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.00 +pb_1c : 7.00 +pb_5c : 7.00 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.01 +pb_1c : 7.01 +pb_5c : 7.00 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.02 +pb_1c : 7.02 +pb_5c : 7.00 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.03 +pb_1c : 7.03 +pb_5c : 7.00 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.04 +pb_1c : 7.04 +pb_5c : 7.00 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.05 +pb_1c : 7.05 +pb_5c : 7.05 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.06 +pb_1c : 7.06 +pb_5c : 7.05 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.07 +pb_1c : 7.07 +pb_5c : 7.05 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.08 +pb_1c : 7.08 +pb_5c : 7.05 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.09 +pb_1c : 7.09 +pb_5c : 7.05 +pb_10c : 7.00 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.10 +pb_1c : 7.10 +pb_5c : 7.10 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.11 +pb_1c : 7.11 +pb_5c : 7.10 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.12 +pb_1c : 7.12 +pb_5c : 7.10 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.13 +pb_1c : 7.13 +pb_5c : 7.10 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.14 +pb_1c : 7.14 +pb_5c : 7.10 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.15 +pb_1c : 7.15 +pb_5c : 7.15 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.16 +pb_1c : 7.16 +pb_5c : 7.15 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.17 +pb_1c : 7.17 +pb_5c : 7.15 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.18 +pb_1c : 7.18 +pb_5c : 7.15 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.19 +pb_1c : 7.19 +pb_5c : 7.15 +pb_10c : 7.10 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.20 +pb_1c : 7.20 +pb_5c : 7.20 +pb_10c : 7.20 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.21 +pb_1c : 7.21 +pb_5c : 7.20 +pb_10c : 7.20 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.22 +pb_1c : 7.22 +pb_5c : 7.20 +pb_10c : 7.20 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.23 +pb_1c : 7.23 +pb_5c : 7.20 +pb_10c : 7.20 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.24 +pb_1c : 7.24 +pb_5c : 7.20 +pb_10c : 7.20 +pb_25c : 7.00 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.25 +pb_1c : 7.25 +pb_5c : 7.25 +pb_10c : 7.20 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.26 +pb_1c : 7.26 +pb_5c : 7.25 +pb_10c : 7.20 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.27 +pb_1c : 7.27 +pb_5c : 7.25 +pb_10c : 7.20 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.28 +pb_1c : 7.28 +pb_5c : 7.25 +pb_10c : 7.20 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.29 +pb_1c : 7.29 +pb_5c : 7.25 +pb_10c : 7.20 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.30 +pb_1c : 7.30 +pb_5c : 7.30 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.31 +pb_1c : 7.31 +pb_5c : 7.30 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.32 +pb_1c : 7.32 +pb_5c : 7.30 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.33 +pb_1c : 7.33 +pb_5c : 7.30 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.34 +pb_1c : 7.34 +pb_5c : 7.30 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.35 +pb_1c : 7.35 +pb_5c : 7.35 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.36 +pb_1c : 7.36 +pb_5c : 7.35 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.37 +pb_1c : 7.37 +pb_5c : 7.35 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.38 +pb_1c : 7.38 +pb_5c : 7.35 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.39 +pb_1c : 7.39 +pb_5c : 7.35 +pb_10c : 7.30 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.40 +pb_1c : 7.40 +pb_5c : 7.40 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.41 +pb_1c : 7.41 +pb_5c : 7.40 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.42 +pb_1c : 7.42 +pb_5c : 7.40 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.43 +pb_1c : 7.43 +pb_5c : 7.40 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.44 +pb_1c : 7.44 +pb_5c : 7.40 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.45 +pb_1c : 7.45 +pb_5c : 7.45 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.46 +pb_1c : 7.46 +pb_5c : 7.45 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.47 +pb_1c : 7.47 +pb_5c : 7.45 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.48 +pb_1c : 7.48 +pb_5c : 7.45 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.49 +pb_1c : 7.49 +pb_5c : 7.45 +pb_10c : 7.40 +pb_25c : 7.25 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.50 +pb_1c : 7.50 +pb_5c : 7.50 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.51 +pb_1c : 7.51 +pb_5c : 7.50 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.52 +pb_1c : 7.52 +pb_5c : 7.50 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.53 +pb_1c : 7.53 +pb_5c : 7.50 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.54 +pb_1c : 7.54 +pb_5c : 7.50 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.55 +pb_1c : 7.55 +pb_5c : 7.55 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.56 +pb_1c : 7.56 +pb_5c : 7.55 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.57 +pb_1c : 7.57 +pb_5c : 7.55 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.58 +pb_1c : 7.58 +pb_5c : 7.55 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.59 +pb_1c : 7.59 +pb_5c : 7.55 +pb_10c : 7.50 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.60 +pb_1c : 7.60 +pb_5c : 7.60 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.61 +pb_1c : 7.61 +pb_5c : 7.60 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.62 +pb_1c : 7.62 +pb_5c : 7.60 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.63 +pb_1c : 7.63 +pb_5c : 7.60 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.64 +pb_1c : 7.64 +pb_5c : 7.60 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.65 +pb_1c : 7.65 +pb_5c : 7.65 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.66 +pb_1c : 7.66 +pb_5c : 7.65 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.67 +pb_1c : 7.67 +pb_5c : 7.65 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.68 +pb_1c : 7.68 +pb_5c : 7.65 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.69 +pb_1c : 7.69 +pb_5c : 7.65 +pb_10c : 7.60 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.70 +pb_1c : 7.70 +pb_5c : 7.70 +pb_10c : 7.70 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.71 +pb_1c : 7.71 +pb_5c : 7.70 +pb_10c : 7.70 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.72 +pb_1c : 7.72 +pb_5c : 7.70 +pb_10c : 7.70 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.73 +pb_1c : 7.73 +pb_5c : 7.70 +pb_10c : 7.70 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.74 +pb_1c : 7.74 +pb_5c : 7.70 +pb_10c : 7.70 +pb_25c : 7.50 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.75 +pb_1c : 7.75 +pb_5c : 7.75 +pb_10c : 7.70 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.76 +pb_1c : 7.76 +pb_5c : 7.75 +pb_10c : 7.70 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.77 +pb_1c : 7.77 +pb_5c : 7.75 +pb_10c : 7.70 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.78 +pb_1c : 7.78 +pb_5c : 7.75 +pb_10c : 7.70 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.79 +pb_1c : 7.79 +pb_5c : 7.75 +pb_10c : 7.70 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.80 +pb_1c : 7.80 +pb_5c : 7.80 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.81 +pb_1c : 7.81 +pb_5c : 7.80 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.82 +pb_1c : 7.82 +pb_5c : 7.80 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.83 +pb_1c : 7.83 +pb_5c : 7.80 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.84 +pb_1c : 7.84 +pb_5c : 7.80 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.85 +pb_1c : 7.85 +pb_5c : 7.85 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.86 +pb_1c : 7.86 +pb_5c : 7.85 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.87 +pb_1c : 7.87 +pb_5c : 7.85 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.88 +pb_1c : 7.88 +pb_5c : 7.85 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.89 +pb_1c : 7.89 +pb_5c : 7.85 +pb_10c : 7.80 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.90 +pb_1c : 7.90 +pb_5c : 7.90 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.91 +pb_1c : 7.91 +pb_5c : 7.90 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.92 +pb_1c : 7.92 +pb_5c : 7.90 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.93 +pb_1c : 7.93 +pb_5c : 7.90 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.94 +pb_1c : 7.94 +pb_5c : 7.90 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.95 +pb_1c : 7.95 +pb_5c : 7.95 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.96 +pb_1c : 7.96 +pb_5c : 7.95 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.97 +pb_1c : 7.97 +pb_5c : 7.95 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.98 +pb_1c : 7.98 +pb_5c : 7.95 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +7.99 +pb_1c : 7.99 +pb_5c : 7.95 +pb_10c : 7.90 +pb_25c : 7.75 +pb_1d : 7.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.00 +pb_1c : 8.00 +pb_5c : 8.00 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.01 +pb_1c : 8.01 +pb_5c : 8.00 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.02 +pb_1c : 8.02 +pb_5c : 8.00 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.03 +pb_1c : 8.03 +pb_5c : 8.00 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.04 +pb_1c : 8.04 +pb_5c : 8.00 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.05 +pb_1c : 8.05 +pb_5c : 8.05 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.06 +pb_1c : 8.06 +pb_5c : 8.05 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.07 +pb_1c : 8.07 +pb_5c : 8.05 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.08 +pb_1c : 8.08 +pb_5c : 8.05 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.09 +pb_1c : 8.09 +pb_5c : 8.05 +pb_10c : 8.00 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.10 +pb_1c : 8.10 +pb_5c : 8.10 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.11 +pb_1c : 8.11 +pb_5c : 8.10 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.12 +pb_1c : 8.12 +pb_5c : 8.10 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.13 +pb_1c : 8.13 +pb_5c : 8.10 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.14 +pb_1c : 8.14 +pb_5c : 8.10 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.15 +pb_1c : 8.15 +pb_5c : 8.15 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.16 +pb_1c : 8.16 +pb_5c : 8.15 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.17 +pb_1c : 8.17 +pb_5c : 8.15 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.18 +pb_1c : 8.18 +pb_5c : 8.15 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.19 +pb_1c : 8.19 +pb_5c : 8.15 +pb_10c : 8.10 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.20 +pb_1c : 8.20 +pb_5c : 8.20 +pb_10c : 8.20 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.21 +pb_1c : 8.21 +pb_5c : 8.20 +pb_10c : 8.20 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.22 +pb_1c : 8.22 +pb_5c : 8.20 +pb_10c : 8.20 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.23 +pb_1c : 8.23 +pb_5c : 8.20 +pb_10c : 8.20 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.24 +pb_1c : 8.24 +pb_5c : 8.20 +pb_10c : 8.20 +pb_25c : 8.00 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.25 +pb_1c : 8.25 +pb_5c : 8.25 +pb_10c : 8.20 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.26 +pb_1c : 8.26 +pb_5c : 8.25 +pb_10c : 8.20 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.27 +pb_1c : 8.27 +pb_5c : 8.25 +pb_10c : 8.20 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.28 +pb_1c : 8.28 +pb_5c : 8.25 +pb_10c : 8.20 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.29 +pb_1c : 8.29 +pb_5c : 8.25 +pb_10c : 8.20 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.30 +pb_1c : 8.30 +pb_5c : 8.30 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.31 +pb_1c : 8.31 +pb_5c : 8.30 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.32 +pb_1c : 8.32 +pb_5c : 8.30 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.33 +pb_1c : 8.33 +pb_5c : 8.30 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.34 +pb_1c : 8.34 +pb_5c : 8.30 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.35 +pb_1c : 8.35 +pb_5c : 8.35 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.36 +pb_1c : 8.36 +pb_5c : 8.35 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.37 +pb_1c : 8.37 +pb_5c : 8.35 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.38 +pb_1c : 8.38 +pb_5c : 8.35 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.39 +pb_1c : 8.39 +pb_5c : 8.35 +pb_10c : 8.30 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.40 +pb_1c : 8.40 +pb_5c : 8.40 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.41 +pb_1c : 8.41 +pb_5c : 8.40 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.42 +pb_1c : 8.42 +pb_5c : 8.40 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.43 +pb_1c : 8.43 +pb_5c : 8.40 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.44 +pb_1c : 8.44 +pb_5c : 8.40 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.45 +pb_1c : 8.45 +pb_5c : 8.45 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.46 +pb_1c : 8.46 +pb_5c : 8.45 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.47 +pb_1c : 8.47 +pb_5c : 8.45 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.48 +pb_1c : 8.48 +pb_5c : 8.45 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.49 +pb_1c : 8.49 +pb_5c : 8.45 +pb_10c : 8.40 +pb_25c : 8.25 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.50 +pb_1c : 8.50 +pb_5c : 8.50 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.51 +pb_1c : 8.51 +pb_5c : 8.50 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.52 +pb_1c : 8.52 +pb_5c : 8.50 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.53 +pb_1c : 8.53 +pb_5c : 8.50 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.54 +pb_1c : 8.54 +pb_5c : 8.50 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.55 +pb_1c : 8.55 +pb_5c : 8.55 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.56 +pb_1c : 8.56 +pb_5c : 8.55 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.57 +pb_1c : 8.57 +pb_5c : 8.55 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.58 +pb_1c : 8.58 +pb_5c : 8.55 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.59 +pb_1c : 8.59 +pb_5c : 8.55 +pb_10c : 8.50 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.60 +pb_1c : 8.60 +pb_5c : 8.60 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.61 +pb_1c : 8.61 +pb_5c : 8.60 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.62 +pb_1c : 8.62 +pb_5c : 8.60 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.63 +pb_1c : 8.63 +pb_5c : 8.60 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.64 +pb_1c : 8.64 +pb_5c : 8.60 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.65 +pb_1c : 8.65 +pb_5c : 8.65 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.66 +pb_1c : 8.66 +pb_5c : 8.65 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.67 +pb_1c : 8.67 +pb_5c : 8.65 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.68 +pb_1c : 8.68 +pb_5c : 8.65 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.69 +pb_1c : 8.69 +pb_5c : 8.65 +pb_10c : 8.60 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.70 +pb_1c : 8.70 +pb_5c : 8.70 +pb_10c : 8.70 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.71 +pb_1c : 8.71 +pb_5c : 8.70 +pb_10c : 8.70 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.72 +pb_1c : 8.72 +pb_5c : 8.70 +pb_10c : 8.70 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.73 +pb_1c : 8.73 +pb_5c : 8.70 +pb_10c : 8.70 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.74 +pb_1c : 8.74 +pb_5c : 8.70 +pb_10c : 8.70 +pb_25c : 8.50 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.75 +pb_1c : 8.75 +pb_5c : 8.75 +pb_10c : 8.70 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.76 +pb_1c : 8.76 +pb_5c : 8.75 +pb_10c : 8.70 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.77 +pb_1c : 8.77 +pb_5c : 8.75 +pb_10c : 8.70 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.78 +pb_1c : 8.78 +pb_5c : 8.75 +pb_10c : 8.70 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.79 +pb_1c : 8.79 +pb_5c : 8.75 +pb_10c : 8.70 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.80 +pb_1c : 8.80 +pb_5c : 8.80 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.81 +pb_1c : 8.81 +pb_5c : 8.80 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.82 +pb_1c : 8.82 +pb_5c : 8.80 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.83 +pb_1c : 8.83 +pb_5c : 8.80 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.84 +pb_1c : 8.84 +pb_5c : 8.80 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.85 +pb_1c : 8.85 +pb_5c : 8.85 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.86 +pb_1c : 8.86 +pb_5c : 8.85 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.87 +pb_1c : 8.87 +pb_5c : 8.85 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.88 +pb_1c : 8.88 +pb_5c : 8.85 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.89 +pb_1c : 8.89 +pb_5c : 8.85 +pb_10c : 8.80 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.90 +pb_1c : 8.90 +pb_5c : 8.90 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.91 +pb_1c : 8.91 +pb_5c : 8.90 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.92 +pb_1c : 8.92 +pb_5c : 8.90 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.93 +pb_1c : 8.93 +pb_5c : 8.90 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.94 +pb_1c : 8.94 +pb_5c : 8.90 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.95 +pb_1c : 8.95 +pb_5c : 8.95 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.96 +pb_1c : 8.96 +pb_5c : 8.95 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.97 +pb_1c : 8.97 +pb_5c : 8.95 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.98 +pb_1c : 8.98 +pb_5c : 8.95 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +8.99 +pb_1c : 8.99 +pb_5c : 8.95 +pb_10c : 8.90 +pb_25c : 8.75 +pb_1d : 8.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.00 +pb_1c : 9.00 +pb_5c : 9.00 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.01 +pb_1c : 9.01 +pb_5c : 9.00 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.02 +pb_1c : 9.02 +pb_5c : 9.00 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.03 +pb_1c : 9.03 +pb_5c : 9.00 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.04 +pb_1c : 9.04 +pb_5c : 9.00 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.05 +pb_1c : 9.05 +pb_5c : 9.05 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.06 +pb_1c : 9.06 +pb_5c : 9.05 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.07 +pb_1c : 9.07 +pb_5c : 9.05 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.08 +pb_1c : 9.08 +pb_5c : 9.05 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.09 +pb_1c : 9.09 +pb_5c : 9.05 +pb_10c : 9.00 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.10 +pb_1c : 9.10 +pb_5c : 9.10 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.11 +pb_1c : 9.11 +pb_5c : 9.10 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.12 +pb_1c : 9.12 +pb_5c : 9.10 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.13 +pb_1c : 9.13 +pb_5c : 9.10 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.14 +pb_1c : 9.14 +pb_5c : 9.10 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.15 +pb_1c : 9.15 +pb_5c : 9.15 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.16 +pb_1c : 9.16 +pb_5c : 9.15 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.17 +pb_1c : 9.17 +pb_5c : 9.15 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.18 +pb_1c : 9.18 +pb_5c : 9.15 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.19 +pb_1c : 9.19 +pb_5c : 9.15 +pb_10c : 9.10 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.20 +pb_1c : 9.20 +pb_5c : 9.20 +pb_10c : 9.20 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.21 +pb_1c : 9.21 +pb_5c : 9.20 +pb_10c : 9.20 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.22 +pb_1c : 9.22 +pb_5c : 9.20 +pb_10c : 9.20 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.23 +pb_1c : 9.23 +pb_5c : 9.20 +pb_10c : 9.20 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.24 +pb_1c : 9.24 +pb_5c : 9.20 +pb_10c : 9.20 +pb_25c : 9.00 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.25 +pb_1c : 9.25 +pb_5c : 9.25 +pb_10c : 9.20 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.26 +pb_1c : 9.26 +pb_5c : 9.25 +pb_10c : 9.20 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.27 +pb_1c : 9.27 +pb_5c : 9.25 +pb_10c : 9.20 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.28 +pb_1c : 9.28 +pb_5c : 9.25 +pb_10c : 9.20 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.29 +pb_1c : 9.29 +pb_5c : 9.25 +pb_10c : 9.20 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.30 +pb_1c : 9.30 +pb_5c : 9.30 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.31 +pb_1c : 9.31 +pb_5c : 9.30 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.32 +pb_1c : 9.32 +pb_5c : 9.30 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.33 +pb_1c : 9.33 +pb_5c : 9.30 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.34 +pb_1c : 9.34 +pb_5c : 9.30 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.35 +pb_1c : 9.35 +pb_5c : 9.35 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.36 +pb_1c : 9.36 +pb_5c : 9.35 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.37 +pb_1c : 9.37 +pb_5c : 9.35 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.38 +pb_1c : 9.38 +pb_5c : 9.35 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.39 +pb_1c : 9.39 +pb_5c : 9.35 +pb_10c : 9.30 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.40 +pb_1c : 9.40 +pb_5c : 9.40 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.41 +pb_1c : 9.41 +pb_5c : 9.40 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.42 +pb_1c : 9.42 +pb_5c : 9.40 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.43 +pb_1c : 9.43 +pb_5c : 9.40 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.44 +pb_1c : 9.44 +pb_5c : 9.40 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.45 +pb_1c : 9.45 +pb_5c : 9.45 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.46 +pb_1c : 9.46 +pb_5c : 9.45 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.47 +pb_1c : 9.47 +pb_5c : 9.45 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.48 +pb_1c : 9.48 +pb_5c : 9.45 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.49 +pb_1c : 9.49 +pb_5c : 9.45 +pb_10c : 9.40 +pb_25c : 9.25 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.50 +pb_1c : 9.50 +pb_5c : 9.50 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.51 +pb_1c : 9.51 +pb_5c : 9.50 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.52 +pb_1c : 9.52 +pb_5c : 9.50 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.53 +pb_1c : 9.53 +pb_5c : 9.50 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.54 +pb_1c : 9.54 +pb_5c : 9.50 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.55 +pb_1c : 9.55 +pb_5c : 9.55 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.56 +pb_1c : 9.56 +pb_5c : 9.55 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.57 +pb_1c : 9.57 +pb_5c : 9.55 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.58 +pb_1c : 9.58 +pb_5c : 9.55 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.59 +pb_1c : 9.59 +pb_5c : 9.55 +pb_10c : 9.50 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.60 +pb_1c : 9.60 +pb_5c : 9.60 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.61 +pb_1c : 9.61 +pb_5c : 9.60 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.62 +pb_1c : 9.62 +pb_5c : 9.60 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.63 +pb_1c : 9.63 +pb_5c : 9.60 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.64 +pb_1c : 9.64 +pb_5c : 9.60 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.65 +pb_1c : 9.65 +pb_5c : 9.65 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.66 +pb_1c : 9.66 +pb_5c : 9.65 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.67 +pb_1c : 9.67 +pb_5c : 9.65 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.68 +pb_1c : 9.68 +pb_5c : 9.65 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.69 +pb_1c : 9.69 +pb_5c : 9.65 +pb_10c : 9.60 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.70 +pb_1c : 9.70 +pb_5c : 9.70 +pb_10c : 9.70 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.71 +pb_1c : 9.71 +pb_5c : 9.70 +pb_10c : 9.70 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.72 +pb_1c : 9.72 +pb_5c : 9.70 +pb_10c : 9.70 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.73 +pb_1c : 9.73 +pb_5c : 9.70 +pb_10c : 9.70 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.74 +pb_1c : 9.74 +pb_5c : 9.70 +pb_10c : 9.70 +pb_25c : 9.50 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.75 +pb_1c : 9.75 +pb_5c : 9.75 +pb_10c : 9.70 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.76 +pb_1c : 9.76 +pb_5c : 9.75 +pb_10c : 9.70 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.77 +pb_1c : 9.77 +pb_5c : 9.75 +pb_10c : 9.70 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.78 +pb_1c : 9.78 +pb_5c : 9.75 +pb_10c : 9.70 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.79 +pb_1c : 9.79 +pb_5c : 9.75 +pb_10c : 9.70 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.80 +pb_1c : 9.80 +pb_5c : 9.80 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.81 +pb_1c : 9.81 +pb_5c : 9.80 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.82 +pb_1c : 9.82 +pb_5c : 9.80 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.83 +pb_1c : 9.83 +pb_5c : 9.80 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.84 +pb_1c : 9.84 +pb_5c : 9.80 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.85 +pb_1c : 9.85 +pb_5c : 9.85 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.86 +pb_1c : 9.86 +pb_5c : 9.85 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.87 +pb_1c : 9.87 +pb_5c : 9.85 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.88 +pb_1c : 9.88 +pb_5c : 9.85 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.89 +pb_1c : 9.89 +pb_5c : 9.85 +pb_10c : 9.80 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.90 +pb_1c : 9.90 +pb_5c : 9.90 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.91 +pb_1c : 9.91 +pb_5c : 9.90 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.92 +pb_1c : 9.92 +pb_5c : 9.90 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.93 +pb_1c : 9.93 +pb_5c : 9.90 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.94 +pb_1c : 9.94 +pb_5c : 9.90 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.95 +pb_1c : 9.95 +pb_5c : 9.95 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.96 +pb_1c : 9.96 +pb_5c : 9.95 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.97 +pb_1c : 9.97 +pb_5c : 9.95 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.98 +pb_1c : 9.98 +pb_5c : 9.95 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +9.99 +pb_1c : 9.99 +pb_5c : 9.95 +pb_10c : 9.90 +pb_25c : 9.75 +pb_1d : 9.00 +pb_5d : 5.00 +pb_10d : 0.00 + +10.00 +pb_1c : 10.00 +pb_5c : 10.00 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.01 +pb_1c : 10.01 +pb_5c : 10.00 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.02 +pb_1c : 10.02 +pb_5c : 10.00 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.03 +pb_1c : 10.03 +pb_5c : 10.00 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.04 +pb_1c : 10.04 +pb_5c : 10.00 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.05 +pb_1c : 10.05 +pb_5c : 10.05 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.06 +pb_1c : 10.06 +pb_5c : 10.05 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.07 +pb_1c : 10.07 +pb_5c : 10.05 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.08 +pb_1c : 10.08 +pb_5c : 10.05 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.09 +pb_1c : 10.09 +pb_5c : 10.05 +pb_10c : 10.00 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.10 +pb_1c : 10.10 +pb_5c : 10.10 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.11 +pb_1c : 10.11 +pb_5c : 10.10 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.12 +pb_1c : 10.12 +pb_5c : 10.10 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.13 +pb_1c : 10.13 +pb_5c : 10.10 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.14 +pb_1c : 10.14 +pb_5c : 10.10 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.15 +pb_1c : 10.15 +pb_5c : 10.15 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.16 +pb_1c : 10.16 +pb_5c : 10.15 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.17 +pb_1c : 10.17 +pb_5c : 10.15 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.18 +pb_1c : 10.18 +pb_5c : 10.15 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.19 +pb_1c : 10.19 +pb_5c : 10.15 +pb_10c : 10.10 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.20 +pb_1c : 10.20 +pb_5c : 10.20 +pb_10c : 10.20 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.21 +pb_1c : 10.21 +pb_5c : 10.20 +pb_10c : 10.20 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.22 +pb_1c : 10.22 +pb_5c : 10.20 +pb_10c : 10.20 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.23 +pb_1c : 10.23 +pb_5c : 10.20 +pb_10c : 10.20 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.24 +pb_1c : 10.24 +pb_5c : 10.20 +pb_10c : 10.20 +pb_25c : 10.00 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.25 +pb_1c : 10.25 +pb_5c : 10.25 +pb_10c : 10.20 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.26 +pb_1c : 10.26 +pb_5c : 10.25 +pb_10c : 10.20 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.27 +pb_1c : 10.27 +pb_5c : 10.25 +pb_10c : 10.20 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.28 +pb_1c : 10.28 +pb_5c : 10.25 +pb_10c : 10.20 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.29 +pb_1c : 10.29 +pb_5c : 10.25 +pb_10c : 10.20 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.30 +pb_1c : 10.30 +pb_5c : 10.30 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.31 +pb_1c : 10.31 +pb_5c : 10.30 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.32 +pb_1c : 10.32 +pb_5c : 10.30 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.33 +pb_1c : 10.33 +pb_5c : 10.30 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.34 +pb_1c : 10.34 +pb_5c : 10.30 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.35 +pb_1c : 10.35 +pb_5c : 10.35 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.36 +pb_1c : 10.36 +pb_5c : 10.35 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.37 +pb_1c : 10.37 +pb_5c : 10.35 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.38 +pb_1c : 10.38 +pb_5c : 10.35 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.39 +pb_1c : 10.39 +pb_5c : 10.35 +pb_10c : 10.30 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.40 +pb_1c : 10.40 +pb_5c : 10.40 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.41 +pb_1c : 10.41 +pb_5c : 10.40 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.42 +pb_1c : 10.42 +pb_5c : 10.40 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.43 +pb_1c : 10.43 +pb_5c : 10.40 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.44 +pb_1c : 10.44 +pb_5c : 10.40 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.45 +pb_1c : 10.45 +pb_5c : 10.45 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.46 +pb_1c : 10.46 +pb_5c : 10.45 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.47 +pb_1c : 10.47 +pb_5c : 10.45 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.48 +pb_1c : 10.48 +pb_5c : 10.45 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.49 +pb_1c : 10.49 +pb_5c : 10.45 +pb_10c : 10.40 +pb_25c : 10.25 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.50 +pb_1c : 10.50 +pb_5c : 10.50 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.51 +pb_1c : 10.51 +pb_5c : 10.50 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.52 +pb_1c : 10.52 +pb_5c : 10.50 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.53 +pb_1c : 10.53 +pb_5c : 10.50 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.54 +pb_1c : 10.54 +pb_5c : 10.50 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.55 +pb_1c : 10.55 +pb_5c : 10.55 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.56 +pb_1c : 10.56 +pb_5c : 10.55 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.57 +pb_1c : 10.57 +pb_5c : 10.55 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.58 +pb_1c : 10.58 +pb_5c : 10.55 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.59 +pb_1c : 10.59 +pb_5c : 10.55 +pb_10c : 10.50 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.60 +pb_1c : 10.60 +pb_5c : 10.60 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.61 +pb_1c : 10.61 +pb_5c : 10.60 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.62 +pb_1c : 10.62 +pb_5c : 10.60 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.63 +pb_1c : 10.63 +pb_5c : 10.60 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.64 +pb_1c : 10.64 +pb_5c : 10.60 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.65 +pb_1c : 10.65 +pb_5c : 10.65 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.66 +pb_1c : 10.66 +pb_5c : 10.65 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.67 +pb_1c : 10.67 +pb_5c : 10.65 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.68 +pb_1c : 10.68 +pb_5c : 10.65 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.69 +pb_1c : 10.69 +pb_5c : 10.65 +pb_10c : 10.60 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.70 +pb_1c : 10.70 +pb_5c : 10.70 +pb_10c : 10.70 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.71 +pb_1c : 10.71 +pb_5c : 10.70 +pb_10c : 10.70 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.72 +pb_1c : 10.72 +pb_5c : 10.70 +pb_10c : 10.70 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.73 +pb_1c : 10.73 +pb_5c : 10.70 +pb_10c : 10.70 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.74 +pb_1c : 10.74 +pb_5c : 10.70 +pb_10c : 10.70 +pb_25c : 10.50 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.75 +pb_1c : 10.75 +pb_5c : 10.75 +pb_10c : 10.70 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.76 +pb_1c : 10.76 +pb_5c : 10.75 +pb_10c : 10.70 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.77 +pb_1c : 10.77 +pb_5c : 10.75 +pb_10c : 10.70 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.78 +pb_1c : 10.78 +pb_5c : 10.75 +pb_10c : 10.70 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.79 +pb_1c : 10.79 +pb_5c : 10.75 +pb_10c : 10.70 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.80 +pb_1c : 10.80 +pb_5c : 10.80 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.81 +pb_1c : 10.81 +pb_5c : 10.80 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.82 +pb_1c : 10.82 +pb_5c : 10.80 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.83 +pb_1c : 10.83 +pb_5c : 10.80 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.84 +pb_1c : 10.84 +pb_5c : 10.80 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.85 +pb_1c : 10.85 +pb_5c : 10.85 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.86 +pb_1c : 10.86 +pb_5c : 10.85 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.87 +pb_1c : 10.87 +pb_5c : 10.85 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.88 +pb_1c : 10.88 +pb_5c : 10.85 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.89 +pb_1c : 10.89 +pb_5c : 10.85 +pb_10c : 10.80 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.90 +pb_1c : 10.90 +pb_5c : 10.90 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.91 +pb_1c : 10.91 +pb_5c : 10.90 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.92 +pb_1c : 10.92 +pb_5c : 10.90 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.93 +pb_1c : 10.93 +pb_5c : 10.90 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.94 +pb_1c : 10.94 +pb_5c : 10.90 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.95 +pb_1c : 10.95 +pb_5c : 10.95 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.96 +pb_1c : 10.96 +pb_5c : 10.95 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.97 +pb_1c : 10.97 +pb_5c : 10.95 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.98 +pb_1c : 10.98 +pb_5c : 10.95 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +10.99 +pb_1c : 10.99 +pb_5c : 10.95 +pb_10c : 10.90 +pb_25c : 10.75 +pb_1d : 10.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.00 +pb_1c : 11.00 +pb_5c : 11.00 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.01 +pb_1c : 11.01 +pb_5c : 11.00 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.02 +pb_1c : 11.02 +pb_5c : 11.00 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.03 +pb_1c : 11.03 +pb_5c : 11.00 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.04 +pb_1c : 11.04 +pb_5c : 11.00 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.05 +pb_1c : 11.05 +pb_5c : 11.05 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.06 +pb_1c : 11.06 +pb_5c : 11.05 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.07 +pb_1c : 11.07 +pb_5c : 11.05 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.08 +pb_1c : 11.08 +pb_5c : 11.05 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.09 +pb_1c : 11.09 +pb_5c : 11.05 +pb_10c : 11.00 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.10 +pb_1c : 11.10 +pb_5c : 11.10 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.11 +pb_1c : 11.11 +pb_5c : 11.10 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.12 +pb_1c : 11.12 +pb_5c : 11.10 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.13 +pb_1c : 11.13 +pb_5c : 11.10 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.14 +pb_1c : 11.14 +pb_5c : 11.10 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.15 +pb_1c : 11.15 +pb_5c : 11.15 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.16 +pb_1c : 11.16 +pb_5c : 11.15 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.17 +pb_1c : 11.17 +pb_5c : 11.15 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.18 +pb_1c : 11.18 +pb_5c : 11.15 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.19 +pb_1c : 11.19 +pb_5c : 11.15 +pb_10c : 11.10 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.20 +pb_1c : 11.20 +pb_5c : 11.20 +pb_10c : 11.20 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.21 +pb_1c : 11.21 +pb_5c : 11.20 +pb_10c : 11.20 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.22 +pb_1c : 11.22 +pb_5c : 11.20 +pb_10c : 11.20 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.23 +pb_1c : 11.23 +pb_5c : 11.20 +pb_10c : 11.20 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.24 +pb_1c : 11.24 +pb_5c : 11.20 +pb_10c : 11.20 +pb_25c : 11.00 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.25 +pb_1c : 11.25 +pb_5c : 11.25 +pb_10c : 11.20 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.26 +pb_1c : 11.26 +pb_5c : 11.25 +pb_10c : 11.20 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.27 +pb_1c : 11.27 +pb_5c : 11.25 +pb_10c : 11.20 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.28 +pb_1c : 11.28 +pb_5c : 11.25 +pb_10c : 11.20 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.29 +pb_1c : 11.29 +pb_5c : 11.25 +pb_10c : 11.20 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.30 +pb_1c : 11.30 +pb_5c : 11.30 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.31 +pb_1c : 11.31 +pb_5c : 11.30 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.32 +pb_1c : 11.32 +pb_5c : 11.30 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.33 +pb_1c : 11.33 +pb_5c : 11.30 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.34 +pb_1c : 11.34 +pb_5c : 11.30 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.35 +pb_1c : 11.35 +pb_5c : 11.35 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.36 +pb_1c : 11.36 +pb_5c : 11.35 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.37 +pb_1c : 11.37 +pb_5c : 11.35 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.38 +pb_1c : 11.38 +pb_5c : 11.35 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.39 +pb_1c : 11.39 +pb_5c : 11.35 +pb_10c : 11.30 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.40 +pb_1c : 11.40 +pb_5c : 11.40 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.41 +pb_1c : 11.41 +pb_5c : 11.40 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.42 +pb_1c : 11.42 +pb_5c : 11.40 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.43 +pb_1c : 11.43 +pb_5c : 11.40 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.44 +pb_1c : 11.44 +pb_5c : 11.40 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.45 +pb_1c : 11.45 +pb_5c : 11.45 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.46 +pb_1c : 11.46 +pb_5c : 11.45 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.47 +pb_1c : 11.47 +pb_5c : 11.45 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.48 +pb_1c : 11.48 +pb_5c : 11.45 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.49 +pb_1c : 11.49 +pb_5c : 11.45 +pb_10c : 11.40 +pb_25c : 11.25 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.50 +pb_1c : 11.50 +pb_5c : 11.50 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.51 +pb_1c : 11.51 +pb_5c : 11.50 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.52 +pb_1c : 11.52 +pb_5c : 11.50 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.53 +pb_1c : 11.53 +pb_5c : 11.50 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.54 +pb_1c : 11.54 +pb_5c : 11.50 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.55 +pb_1c : 11.55 +pb_5c : 11.55 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.56 +pb_1c : 11.56 +pb_5c : 11.55 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.57 +pb_1c : 11.57 +pb_5c : 11.55 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.58 +pb_1c : 11.58 +pb_5c : 11.55 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.59 +pb_1c : 11.59 +pb_5c : 11.55 +pb_10c : 11.50 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.60 +pb_1c : 11.60 +pb_5c : 11.60 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.61 +pb_1c : 11.61 +pb_5c : 11.60 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.62 +pb_1c : 11.62 +pb_5c : 11.60 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.63 +pb_1c : 11.63 +pb_5c : 11.60 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.64 +pb_1c : 11.64 +pb_5c : 11.60 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.65 +pb_1c : 11.65 +pb_5c : 11.65 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.66 +pb_1c : 11.66 +pb_5c : 11.65 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.67 +pb_1c : 11.67 +pb_5c : 11.65 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.68 +pb_1c : 11.68 +pb_5c : 11.65 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.69 +pb_1c : 11.69 +pb_5c : 11.65 +pb_10c : 11.60 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.70 +pb_1c : 11.70 +pb_5c : 11.70 +pb_10c : 11.70 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.71 +pb_1c : 11.71 +pb_5c : 11.70 +pb_10c : 11.70 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.72 +pb_1c : 11.72 +pb_5c : 11.70 +pb_10c : 11.70 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.73 +pb_1c : 11.73 +pb_5c : 11.70 +pb_10c : 11.70 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.74 +pb_1c : 11.74 +pb_5c : 11.70 +pb_10c : 11.70 +pb_25c : 11.50 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.75 +pb_1c : 11.75 +pb_5c : 11.75 +pb_10c : 11.70 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.76 +pb_1c : 11.76 +pb_5c : 11.75 +pb_10c : 11.70 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.77 +pb_1c : 11.77 +pb_5c : 11.75 +pb_10c : 11.70 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.78 +pb_1c : 11.78 +pb_5c : 11.75 +pb_10c : 11.70 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.79 +pb_1c : 11.79 +pb_5c : 11.75 +pb_10c : 11.70 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.80 +pb_1c : 11.80 +pb_5c : 11.80 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.81 +pb_1c : 11.81 +pb_5c : 11.80 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.82 +pb_1c : 11.82 +pb_5c : 11.80 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.83 +pb_1c : 11.83 +pb_5c : 11.80 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.84 +pb_1c : 11.84 +pb_5c : 11.80 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.85 +pb_1c : 11.85 +pb_5c : 11.85 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.86 +pb_1c : 11.86 +pb_5c : 11.85 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.87 +pb_1c : 11.87 +pb_5c : 11.85 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.88 +pb_1c : 11.88 +pb_5c : 11.85 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.89 +pb_1c : 11.89 +pb_5c : 11.85 +pb_10c : 11.80 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.90 +pb_1c : 11.90 +pb_5c : 11.90 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.91 +pb_1c : 11.91 +pb_5c : 11.90 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.92 +pb_1c : 11.92 +pb_5c : 11.90 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.93 +pb_1c : 11.93 +pb_5c : 11.90 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.94 +pb_1c : 11.94 +pb_5c : 11.90 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.95 +pb_1c : 11.95 +pb_5c : 11.95 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.96 +pb_1c : 11.96 +pb_5c : 11.95 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.97 +pb_1c : 11.97 +pb_5c : 11.95 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.98 +pb_1c : 11.98 +pb_5c : 11.95 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +11.99 +pb_1c : 11.99 +pb_5c : 11.95 +pb_10c : 11.90 +pb_25c : 11.75 +pb_1d : 11.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.00 +pb_1c : 12.00 +pb_5c : 12.00 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.01 +pb_1c : 12.01 +pb_5c : 12.00 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.02 +pb_1c : 12.02 +pb_5c : 12.00 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.03 +pb_1c : 12.03 +pb_5c : 12.00 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.04 +pb_1c : 12.04 +pb_5c : 12.00 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.05 +pb_1c : 12.05 +pb_5c : 12.05 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.06 +pb_1c : 12.06 +pb_5c : 12.05 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.07 +pb_1c : 12.07 +pb_5c : 12.05 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.08 +pb_1c : 12.08 +pb_5c : 12.05 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.09 +pb_1c : 12.09 +pb_5c : 12.05 +pb_10c : 12.00 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.10 +pb_1c : 12.10 +pb_5c : 12.10 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.11 +pb_1c : 12.11 +pb_5c : 12.10 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.12 +pb_1c : 12.12 +pb_5c : 12.10 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.13 +pb_1c : 12.13 +pb_5c : 12.10 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.14 +pb_1c : 12.14 +pb_5c : 12.10 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.15 +pb_1c : 12.15 +pb_5c : 12.15 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.16 +pb_1c : 12.16 +pb_5c : 12.15 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.17 +pb_1c : 12.17 +pb_5c : 12.15 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.18 +pb_1c : 12.18 +pb_5c : 12.15 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.19 +pb_1c : 12.19 +pb_5c : 12.15 +pb_10c : 12.10 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.20 +pb_1c : 12.20 +pb_5c : 12.20 +pb_10c : 12.20 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.21 +pb_1c : 12.21 +pb_5c : 12.20 +pb_10c : 12.20 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.22 +pb_1c : 12.22 +pb_5c : 12.20 +pb_10c : 12.20 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.23 +pb_1c : 12.23 +pb_5c : 12.20 +pb_10c : 12.20 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.24 +pb_1c : 12.24 +pb_5c : 12.20 +pb_10c : 12.20 +pb_25c : 12.00 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.25 +pb_1c : 12.25 +pb_5c : 12.25 +pb_10c : 12.20 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.26 +pb_1c : 12.26 +pb_5c : 12.25 +pb_10c : 12.20 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.27 +pb_1c : 12.27 +pb_5c : 12.25 +pb_10c : 12.20 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.28 +pb_1c : 12.28 +pb_5c : 12.25 +pb_10c : 12.20 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.29 +pb_1c : 12.29 +pb_5c : 12.25 +pb_10c : 12.20 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.30 +pb_1c : 12.30 +pb_5c : 12.30 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.31 +pb_1c : 12.31 +pb_5c : 12.30 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.32 +pb_1c : 12.32 +pb_5c : 12.30 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.33 +pb_1c : 12.33 +pb_5c : 12.30 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.34 +pb_1c : 12.34 +pb_5c : 12.30 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.35 +pb_1c : 12.35 +pb_5c : 12.35 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.36 +pb_1c : 12.36 +pb_5c : 12.35 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.37 +pb_1c : 12.37 +pb_5c : 12.35 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.38 +pb_1c : 12.38 +pb_5c : 12.35 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.39 +pb_1c : 12.39 +pb_5c : 12.35 +pb_10c : 12.30 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.40 +pb_1c : 12.40 +pb_5c : 12.40 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.41 +pb_1c : 12.41 +pb_5c : 12.40 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.42 +pb_1c : 12.42 +pb_5c : 12.40 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.43 +pb_1c : 12.43 +pb_5c : 12.40 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.44 +pb_1c : 12.44 +pb_5c : 12.40 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.45 +pb_1c : 12.45 +pb_5c : 12.45 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.46 +pb_1c : 12.46 +pb_5c : 12.45 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.47 +pb_1c : 12.47 +pb_5c : 12.45 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.48 +pb_1c : 12.48 +pb_5c : 12.45 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.49 +pb_1c : 12.49 +pb_5c : 12.45 +pb_10c : 12.40 +pb_25c : 12.25 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.50 +pb_1c : 12.50 +pb_5c : 12.50 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.51 +pb_1c : 12.51 +pb_5c : 12.50 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.52 +pb_1c : 12.52 +pb_5c : 12.50 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.53 +pb_1c : 12.53 +pb_5c : 12.50 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.54 +pb_1c : 12.54 +pb_5c : 12.50 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.55 +pb_1c : 12.55 +pb_5c : 12.55 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.56 +pb_1c : 12.56 +pb_5c : 12.55 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.57 +pb_1c : 12.57 +pb_5c : 12.55 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.58 +pb_1c : 12.58 +pb_5c : 12.55 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.59 +pb_1c : 12.59 +pb_5c : 12.55 +pb_10c : 12.50 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.60 +pb_1c : 12.60 +pb_5c : 12.60 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.61 +pb_1c : 12.61 +pb_5c : 12.60 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.62 +pb_1c : 12.62 +pb_5c : 12.60 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.63 +pb_1c : 12.63 +pb_5c : 12.60 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.64 +pb_1c : 12.64 +pb_5c : 12.60 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.65 +pb_1c : 12.65 +pb_5c : 12.65 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.66 +pb_1c : 12.66 +pb_5c : 12.65 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.67 +pb_1c : 12.67 +pb_5c : 12.65 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.68 +pb_1c : 12.68 +pb_5c : 12.65 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.69 +pb_1c : 12.69 +pb_5c : 12.65 +pb_10c : 12.60 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.70 +pb_1c : 12.70 +pb_5c : 12.70 +pb_10c : 12.70 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.71 +pb_1c : 12.71 +pb_5c : 12.70 +pb_10c : 12.70 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.72 +pb_1c : 12.72 +pb_5c : 12.70 +pb_10c : 12.70 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.73 +pb_1c : 12.73 +pb_5c : 12.70 +pb_10c : 12.70 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.74 +pb_1c : 12.74 +pb_5c : 12.70 +pb_10c : 12.70 +pb_25c : 12.50 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.75 +pb_1c : 12.75 +pb_5c : 12.75 +pb_10c : 12.70 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.76 +pb_1c : 12.76 +pb_5c : 12.75 +pb_10c : 12.70 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.77 +pb_1c : 12.77 +pb_5c : 12.75 +pb_10c : 12.70 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.78 +pb_1c : 12.78 +pb_5c : 12.75 +pb_10c : 12.70 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.79 +pb_1c : 12.79 +pb_5c : 12.75 +pb_10c : 12.70 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.80 +pb_1c : 12.80 +pb_5c : 12.80 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.81 +pb_1c : 12.81 +pb_5c : 12.80 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.82 +pb_1c : 12.82 +pb_5c : 12.80 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.83 +pb_1c : 12.83 +pb_5c : 12.80 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.84 +pb_1c : 12.84 +pb_5c : 12.80 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.85 +pb_1c : 12.85 +pb_5c : 12.85 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.86 +pb_1c : 12.86 +pb_5c : 12.85 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.87 +pb_1c : 12.87 +pb_5c : 12.85 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.88 +pb_1c : 12.88 +pb_5c : 12.85 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.89 +pb_1c : 12.89 +pb_5c : 12.85 +pb_10c : 12.80 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.90 +pb_1c : 12.90 +pb_5c : 12.90 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.91 +pb_1c : 12.91 +pb_5c : 12.90 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.92 +pb_1c : 12.92 +pb_5c : 12.90 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.93 +pb_1c : 12.93 +pb_5c : 12.90 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.94 +pb_1c : 12.94 +pb_5c : 12.90 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.95 +pb_1c : 12.95 +pb_5c : 12.95 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.96 +pb_1c : 12.96 +pb_5c : 12.95 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.97 +pb_1c : 12.97 +pb_5c : 12.95 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.98 +pb_1c : 12.98 +pb_5c : 12.95 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +12.99 +pb_1c : 12.99 +pb_5c : 12.95 +pb_10c : 12.90 +pb_25c : 12.75 +pb_1d : 12.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.00 +pb_1c : 13.00 +pb_5c : 13.00 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.01 +pb_1c : 13.01 +pb_5c : 13.00 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.02 +pb_1c : 13.02 +pb_5c : 13.00 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.03 +pb_1c : 13.03 +pb_5c : 13.00 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.04 +pb_1c : 13.04 +pb_5c : 13.00 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.05 +pb_1c : 13.05 +pb_5c : 13.05 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.06 +pb_1c : 13.06 +pb_5c : 13.05 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.07 +pb_1c : 13.07 +pb_5c : 13.05 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.08 +pb_1c : 13.08 +pb_5c : 13.05 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.09 +pb_1c : 13.09 +pb_5c : 13.05 +pb_10c : 13.00 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.10 +pb_1c : 13.10 +pb_5c : 13.10 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.11 +pb_1c : 13.11 +pb_5c : 13.10 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.12 +pb_1c : 13.12 +pb_5c : 13.10 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.13 +pb_1c : 13.13 +pb_5c : 13.10 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.14 +pb_1c : 13.14 +pb_5c : 13.10 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.15 +pb_1c : 13.15 +pb_5c : 13.15 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.16 +pb_1c : 13.16 +pb_5c : 13.15 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.17 +pb_1c : 13.17 +pb_5c : 13.15 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.18 +pb_1c : 13.18 +pb_5c : 13.15 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.19 +pb_1c : 13.19 +pb_5c : 13.15 +pb_10c : 13.10 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.20 +pb_1c : 13.20 +pb_5c : 13.20 +pb_10c : 13.20 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.21 +pb_1c : 13.21 +pb_5c : 13.20 +pb_10c : 13.20 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.22 +pb_1c : 13.22 +pb_5c : 13.20 +pb_10c : 13.20 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.23 +pb_1c : 13.23 +pb_5c : 13.20 +pb_10c : 13.20 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.24 +pb_1c : 13.24 +pb_5c : 13.20 +pb_10c : 13.20 +pb_25c : 13.00 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.25 +pb_1c : 13.25 +pb_5c : 13.25 +pb_10c : 13.20 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.26 +pb_1c : 13.26 +pb_5c : 13.25 +pb_10c : 13.20 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.27 +pb_1c : 13.27 +pb_5c : 13.25 +pb_10c : 13.20 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.28 +pb_1c : 13.28 +pb_5c : 13.25 +pb_10c : 13.20 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.29 +pb_1c : 13.29 +pb_5c : 13.25 +pb_10c : 13.20 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.30 +pb_1c : 13.30 +pb_5c : 13.30 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.31 +pb_1c : 13.31 +pb_5c : 13.30 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.32 +pb_1c : 13.32 +pb_5c : 13.30 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.33 +pb_1c : 13.33 +pb_5c : 13.30 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.34 +pb_1c : 13.34 +pb_5c : 13.30 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.35 +pb_1c : 13.35 +pb_5c : 13.35 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.36 +pb_1c : 13.36 +pb_5c : 13.35 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.37 +pb_1c : 13.37 +pb_5c : 13.35 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.38 +pb_1c : 13.38 +pb_5c : 13.35 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.39 +pb_1c : 13.39 +pb_5c : 13.35 +pb_10c : 13.30 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.40 +pb_1c : 13.40 +pb_5c : 13.40 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.41 +pb_1c : 13.41 +pb_5c : 13.40 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.42 +pb_1c : 13.42 +pb_5c : 13.40 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.43 +pb_1c : 13.43 +pb_5c : 13.40 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.44 +pb_1c : 13.44 +pb_5c : 13.40 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.45 +pb_1c : 13.45 +pb_5c : 13.45 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.46 +pb_1c : 13.46 +pb_5c : 13.45 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.47 +pb_1c : 13.47 +pb_5c : 13.45 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.48 +pb_1c : 13.48 +pb_5c : 13.45 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.49 +pb_1c : 13.49 +pb_5c : 13.45 +pb_10c : 13.40 +pb_25c : 13.25 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.50 +pb_1c : 13.50 +pb_5c : 13.50 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.51 +pb_1c : 13.51 +pb_5c : 13.50 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.52 +pb_1c : 13.52 +pb_5c : 13.50 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.53 +pb_1c : 13.53 +pb_5c : 13.50 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.54 +pb_1c : 13.54 +pb_5c : 13.50 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.55 +pb_1c : 13.55 +pb_5c : 13.55 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.56 +pb_1c : 13.56 +pb_5c : 13.55 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.57 +pb_1c : 13.57 +pb_5c : 13.55 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.58 +pb_1c : 13.58 +pb_5c : 13.55 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.59 +pb_1c : 13.59 +pb_5c : 13.55 +pb_10c : 13.50 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.60 +pb_1c : 13.60 +pb_5c : 13.60 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.61 +pb_1c : 13.61 +pb_5c : 13.60 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.62 +pb_1c : 13.62 +pb_5c : 13.60 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.63 +pb_1c : 13.63 +pb_5c : 13.60 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.64 +pb_1c : 13.64 +pb_5c : 13.60 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.65 +pb_1c : 13.65 +pb_5c : 13.65 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.66 +pb_1c : 13.66 +pb_5c : 13.65 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.67 +pb_1c : 13.67 +pb_5c : 13.65 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.68 +pb_1c : 13.68 +pb_5c : 13.65 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.69 +pb_1c : 13.69 +pb_5c : 13.65 +pb_10c : 13.60 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.70 +pb_1c : 13.70 +pb_5c : 13.70 +pb_10c : 13.70 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.71 +pb_1c : 13.71 +pb_5c : 13.70 +pb_10c : 13.70 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.72 +pb_1c : 13.72 +pb_5c : 13.70 +pb_10c : 13.70 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.73 +pb_1c : 13.73 +pb_5c : 13.70 +pb_10c : 13.70 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.74 +pb_1c : 13.74 +pb_5c : 13.70 +pb_10c : 13.70 +pb_25c : 13.50 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.75 +pb_1c : 13.75 +pb_5c : 13.75 +pb_10c : 13.70 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.76 +pb_1c : 13.76 +pb_5c : 13.75 +pb_10c : 13.70 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.77 +pb_1c : 13.77 +pb_5c : 13.75 +pb_10c : 13.70 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.78 +pb_1c : 13.78 +pb_5c : 13.75 +pb_10c : 13.70 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.79 +pb_1c : 13.79 +pb_5c : 13.75 +pb_10c : 13.70 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.80 +pb_1c : 13.80 +pb_5c : 13.80 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.81 +pb_1c : 13.81 +pb_5c : 13.80 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.82 +pb_1c : 13.82 +pb_5c : 13.80 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.83 +pb_1c : 13.83 +pb_5c : 13.80 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.84 +pb_1c : 13.84 +pb_5c : 13.80 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.85 +pb_1c : 13.85 +pb_5c : 13.85 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.86 +pb_1c : 13.86 +pb_5c : 13.85 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.87 +pb_1c : 13.87 +pb_5c : 13.85 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.88 +pb_1c : 13.88 +pb_5c : 13.85 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.89 +pb_1c : 13.89 +pb_5c : 13.85 +pb_10c : 13.80 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.90 +pb_1c : 13.90 +pb_5c : 13.90 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.91 +pb_1c : 13.91 +pb_5c : 13.90 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.92 +pb_1c : 13.92 +pb_5c : 13.90 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.93 +pb_1c : 13.93 +pb_5c : 13.90 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.94 +pb_1c : 13.94 +pb_5c : 13.90 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.95 +pb_1c : 13.95 +pb_5c : 13.95 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.96 +pb_1c : 13.96 +pb_5c : 13.95 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.97 +pb_1c : 13.97 +pb_5c : 13.95 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.98 +pb_1c : 13.98 +pb_5c : 13.95 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +13.99 +pb_1c : 13.99 +pb_5c : 13.95 +pb_10c : 13.90 +pb_25c : 13.75 +pb_1d : 13.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.00 +pb_1c : 14.00 +pb_5c : 14.00 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.01 +pb_1c : 14.01 +pb_5c : 14.00 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.02 +pb_1c : 14.02 +pb_5c : 14.00 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.03 +pb_1c : 14.03 +pb_5c : 14.00 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.04 +pb_1c : 14.04 +pb_5c : 14.00 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.05 +pb_1c : 14.05 +pb_5c : 14.05 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.06 +pb_1c : 14.06 +pb_5c : 14.05 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.07 +pb_1c : 14.07 +pb_5c : 14.05 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.08 +pb_1c : 14.08 +pb_5c : 14.05 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.09 +pb_1c : 14.09 +pb_5c : 14.05 +pb_10c : 14.00 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.10 +pb_1c : 14.10 +pb_5c : 14.10 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.11 +pb_1c : 14.11 +pb_5c : 14.10 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.12 +pb_1c : 14.12 +pb_5c : 14.10 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.13 +pb_1c : 14.13 +pb_5c : 14.10 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.14 +pb_1c : 14.14 +pb_5c : 14.10 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.15 +pb_1c : 14.15 +pb_5c : 14.15 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.16 +pb_1c : 14.16 +pb_5c : 14.15 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.17 +pb_1c : 14.17 +pb_5c : 14.15 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.18 +pb_1c : 14.18 +pb_5c : 14.15 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.19 +pb_1c : 14.19 +pb_5c : 14.15 +pb_10c : 14.10 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.20 +pb_1c : 14.20 +pb_5c : 14.20 +pb_10c : 14.20 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.21 +pb_1c : 14.21 +pb_5c : 14.20 +pb_10c : 14.20 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.22 +pb_1c : 14.22 +pb_5c : 14.20 +pb_10c : 14.20 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.23 +pb_1c : 14.23 +pb_5c : 14.20 +pb_10c : 14.20 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.24 +pb_1c : 14.24 +pb_5c : 14.20 +pb_10c : 14.20 +pb_25c : 14.00 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.25 +pb_1c : 14.25 +pb_5c : 14.25 +pb_10c : 14.20 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.26 +pb_1c : 14.26 +pb_5c : 14.25 +pb_10c : 14.20 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.27 +pb_1c : 14.27 +pb_5c : 14.25 +pb_10c : 14.20 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.28 +pb_1c : 14.28 +pb_5c : 14.25 +pb_10c : 14.20 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.29 +pb_1c : 14.29 +pb_5c : 14.25 +pb_10c : 14.20 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.30 +pb_1c : 14.30 +pb_5c : 14.30 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.31 +pb_1c : 14.31 +pb_5c : 14.30 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.32 +pb_1c : 14.32 +pb_5c : 14.30 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.33 +pb_1c : 14.33 +pb_5c : 14.30 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.34 +pb_1c : 14.34 +pb_5c : 14.30 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.35 +pb_1c : 14.35 +pb_5c : 14.35 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.36 +pb_1c : 14.36 +pb_5c : 14.35 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.37 +pb_1c : 14.37 +pb_5c : 14.35 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.38 +pb_1c : 14.38 +pb_5c : 14.35 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.39 +pb_1c : 14.39 +pb_5c : 14.35 +pb_10c : 14.30 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.40 +pb_1c : 14.40 +pb_5c : 14.40 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.41 +pb_1c : 14.41 +pb_5c : 14.40 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.42 +pb_1c : 14.42 +pb_5c : 14.40 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.43 +pb_1c : 14.43 +pb_5c : 14.40 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.44 +pb_1c : 14.44 +pb_5c : 14.40 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.45 +pb_1c : 14.45 +pb_5c : 14.45 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.46 +pb_1c : 14.46 +pb_5c : 14.45 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.47 +pb_1c : 14.47 +pb_5c : 14.45 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.48 +pb_1c : 14.48 +pb_5c : 14.45 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.49 +pb_1c : 14.49 +pb_5c : 14.45 +pb_10c : 14.40 +pb_25c : 14.25 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.50 +pb_1c : 14.50 +pb_5c : 14.50 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.51 +pb_1c : 14.51 +pb_5c : 14.50 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.52 +pb_1c : 14.52 +pb_5c : 14.50 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.53 +pb_1c : 14.53 +pb_5c : 14.50 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.54 +pb_1c : 14.54 +pb_5c : 14.50 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.55 +pb_1c : 14.55 +pb_5c : 14.55 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.56 +pb_1c : 14.56 +pb_5c : 14.55 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.57 +pb_1c : 14.57 +pb_5c : 14.55 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.58 +pb_1c : 14.58 +pb_5c : 14.55 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.59 +pb_1c : 14.59 +pb_5c : 14.55 +pb_10c : 14.50 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.60 +pb_1c : 14.60 +pb_5c : 14.60 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.61 +pb_1c : 14.61 +pb_5c : 14.60 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.62 +pb_1c : 14.62 +pb_5c : 14.60 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.63 +pb_1c : 14.63 +pb_5c : 14.60 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.64 +pb_1c : 14.64 +pb_5c : 14.60 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.65 +pb_1c : 14.65 +pb_5c : 14.65 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.66 +pb_1c : 14.66 +pb_5c : 14.65 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.67 +pb_1c : 14.67 +pb_5c : 14.65 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.68 +pb_1c : 14.68 +pb_5c : 14.65 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.69 +pb_1c : 14.69 +pb_5c : 14.65 +pb_10c : 14.60 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.70 +pb_1c : 14.70 +pb_5c : 14.70 +pb_10c : 14.70 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.71 +pb_1c : 14.71 +pb_5c : 14.70 +pb_10c : 14.70 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.72 +pb_1c : 14.72 +pb_5c : 14.70 +pb_10c : 14.70 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.73 +pb_1c : 14.73 +pb_5c : 14.70 +pb_10c : 14.70 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.74 +pb_1c : 14.74 +pb_5c : 14.70 +pb_10c : 14.70 +pb_25c : 14.50 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.75 +pb_1c : 14.75 +pb_5c : 14.75 +pb_10c : 14.70 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.76 +pb_1c : 14.76 +pb_5c : 14.75 +pb_10c : 14.70 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.77 +pb_1c : 14.77 +pb_5c : 14.75 +pb_10c : 14.70 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.78 +pb_1c : 14.78 +pb_5c : 14.75 +pb_10c : 14.70 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.79 +pb_1c : 14.79 +pb_5c : 14.75 +pb_10c : 14.70 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.80 +pb_1c : 14.80 +pb_5c : 14.80 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.81 +pb_1c : 14.81 +pb_5c : 14.80 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.82 +pb_1c : 14.82 +pb_5c : 14.80 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.83 +pb_1c : 14.83 +pb_5c : 14.80 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.84 +pb_1c : 14.84 +pb_5c : 14.80 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.85 +pb_1c : 14.85 +pb_5c : 14.85 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.86 +pb_1c : 14.86 +pb_5c : 14.85 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.87 +pb_1c : 14.87 +pb_5c : 14.85 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.88 +pb_1c : 14.88 +pb_5c : 14.85 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.89 +pb_1c : 14.89 +pb_5c : 14.85 +pb_10c : 14.80 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.90 +pb_1c : 14.90 +pb_5c : 14.90 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.91 +pb_1c : 14.91 +pb_5c : 14.90 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.92 +pb_1c : 14.92 +pb_5c : 14.90 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.93 +pb_1c : 14.93 +pb_5c : 14.90 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.94 +pb_1c : 14.94 +pb_5c : 14.90 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.95 +pb_1c : 14.95 +pb_5c : 14.95 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.96 +pb_1c : 14.96 +pb_5c : 14.95 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.97 +pb_1c : 14.97 +pb_5c : 14.95 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.98 +pb_1c : 14.98 +pb_5c : 14.95 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +14.99 +pb_1c : 14.99 +pb_5c : 14.95 +pb_10c : 14.90 +pb_25c : 14.75 +pb_1d : 14.00 +pb_5d : 10.00 +pb_10d : 10.00 + +15.00 +pb_1c : 15.00 +pb_5c : 15.00 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.01 +pb_1c : 15.01 +pb_5c : 15.00 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.02 +pb_1c : 15.02 +pb_5c : 15.00 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.03 +pb_1c : 15.03 +pb_5c : 15.00 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.04 +pb_1c : 15.04 +pb_5c : 15.00 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.05 +pb_1c : 15.05 +pb_5c : 15.05 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.06 +pb_1c : 15.06 +pb_5c : 15.05 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.07 +pb_1c : 15.07 +pb_5c : 15.05 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.08 +pb_1c : 15.08 +pb_5c : 15.05 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.09 +pb_1c : 15.09 +pb_5c : 15.05 +pb_10c : 15.00 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.10 +pb_1c : 15.10 +pb_5c : 15.10 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.11 +pb_1c : 15.11 +pb_5c : 15.10 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.12 +pb_1c : 15.12 +pb_5c : 15.10 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.13 +pb_1c : 15.13 +pb_5c : 15.10 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.14 +pb_1c : 15.14 +pb_5c : 15.10 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.15 +pb_1c : 15.15 +pb_5c : 15.15 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.16 +pb_1c : 15.16 +pb_5c : 15.15 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.17 +pb_1c : 15.17 +pb_5c : 15.15 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.18 +pb_1c : 15.18 +pb_5c : 15.15 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.19 +pb_1c : 15.19 +pb_5c : 15.15 +pb_10c : 15.10 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.20 +pb_1c : 15.20 +pb_5c : 15.20 +pb_10c : 15.20 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.21 +pb_1c : 15.21 +pb_5c : 15.20 +pb_10c : 15.20 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.22 +pb_1c : 15.22 +pb_5c : 15.20 +pb_10c : 15.20 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.23 +pb_1c : 15.23 +pb_5c : 15.20 +pb_10c : 15.20 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.24 +pb_1c : 15.24 +pb_5c : 15.20 +pb_10c : 15.20 +pb_25c : 15.00 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.25 +pb_1c : 15.25 +pb_5c : 15.25 +pb_10c : 15.20 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.26 +pb_1c : 15.26 +pb_5c : 15.25 +pb_10c : 15.20 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.27 +pb_1c : 15.27 +pb_5c : 15.25 +pb_10c : 15.20 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.28 +pb_1c : 15.28 +pb_5c : 15.25 +pb_10c : 15.20 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.29 +pb_1c : 15.29 +pb_5c : 15.25 +pb_10c : 15.20 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.30 +pb_1c : 15.30 +pb_5c : 15.30 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.31 +pb_1c : 15.31 +pb_5c : 15.30 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.32 +pb_1c : 15.32 +pb_5c : 15.30 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.33 +pb_1c : 15.33 +pb_5c : 15.30 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.34 +pb_1c : 15.34 +pb_5c : 15.30 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.35 +pb_1c : 15.35 +pb_5c : 15.35 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.36 +pb_1c : 15.36 +pb_5c : 15.35 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.37 +pb_1c : 15.37 +pb_5c : 15.35 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.38 +pb_1c : 15.38 +pb_5c : 15.35 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.39 +pb_1c : 15.39 +pb_5c : 15.35 +pb_10c : 15.30 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.40 +pb_1c : 15.40 +pb_5c : 15.40 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.41 +pb_1c : 15.41 +pb_5c : 15.40 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.42 +pb_1c : 15.42 +pb_5c : 15.40 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.43 +pb_1c : 15.43 +pb_5c : 15.40 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.44 +pb_1c : 15.44 +pb_5c : 15.40 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.45 +pb_1c : 15.45 +pb_5c : 15.45 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.46 +pb_1c : 15.46 +pb_5c : 15.45 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.47 +pb_1c : 15.47 +pb_5c : 15.45 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.48 +pb_1c : 15.48 +pb_5c : 15.45 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.49 +pb_1c : 15.49 +pb_5c : 15.45 +pb_10c : 15.40 +pb_25c : 15.25 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.50 +pb_1c : 15.50 +pb_5c : 15.50 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.51 +pb_1c : 15.51 +pb_5c : 15.50 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.52 +pb_1c : 15.52 +pb_5c : 15.50 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.53 +pb_1c : 15.53 +pb_5c : 15.50 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.54 +pb_1c : 15.54 +pb_5c : 15.50 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.55 +pb_1c : 15.55 +pb_5c : 15.55 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.56 +pb_1c : 15.56 +pb_5c : 15.55 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.57 +pb_1c : 15.57 +pb_5c : 15.55 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.58 +pb_1c : 15.58 +pb_5c : 15.55 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.59 +pb_1c : 15.59 +pb_5c : 15.55 +pb_10c : 15.50 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.60 +pb_1c : 15.60 +pb_5c : 15.60 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.61 +pb_1c : 15.61 +pb_5c : 15.60 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.62 +pb_1c : 15.62 +pb_5c : 15.60 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.63 +pb_1c : 15.63 +pb_5c : 15.60 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.64 +pb_1c : 15.64 +pb_5c : 15.60 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.65 +pb_1c : 15.65 +pb_5c : 15.65 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.66 +pb_1c : 15.66 +pb_5c : 15.65 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.67 +pb_1c : 15.67 +pb_5c : 15.65 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.68 +pb_1c : 15.68 +pb_5c : 15.65 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.69 +pb_1c : 15.69 +pb_5c : 15.65 +pb_10c : 15.60 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.70 +pb_1c : 15.70 +pb_5c : 15.70 +pb_10c : 15.70 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.71 +pb_1c : 15.71 +pb_5c : 15.70 +pb_10c : 15.70 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.72 +pb_1c : 15.72 +pb_5c : 15.70 +pb_10c : 15.70 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.73 +pb_1c : 15.73 +pb_5c : 15.70 +pb_10c : 15.70 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.74 +pb_1c : 15.74 +pb_5c : 15.70 +pb_10c : 15.70 +pb_25c : 15.50 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.75 +pb_1c : 15.75 +pb_5c : 15.75 +pb_10c : 15.70 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.76 +pb_1c : 15.76 +pb_5c : 15.75 +pb_10c : 15.70 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.77 +pb_1c : 15.77 +pb_5c : 15.75 +pb_10c : 15.70 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.78 +pb_1c : 15.78 +pb_5c : 15.75 +pb_10c : 15.70 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.79 +pb_1c : 15.79 +pb_5c : 15.75 +pb_10c : 15.70 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.80 +pb_1c : 15.80 +pb_5c : 15.80 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.81 +pb_1c : 15.81 +pb_5c : 15.80 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.82 +pb_1c : 15.82 +pb_5c : 15.80 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.83 +pb_1c : 15.83 +pb_5c : 15.80 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.84 +pb_1c : 15.84 +pb_5c : 15.80 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.85 +pb_1c : 15.85 +pb_5c : 15.85 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.86 +pb_1c : 15.86 +pb_5c : 15.85 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.87 +pb_1c : 15.87 +pb_5c : 15.85 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.88 +pb_1c : 15.88 +pb_5c : 15.85 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.89 +pb_1c : 15.89 +pb_5c : 15.85 +pb_10c : 15.80 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.90 +pb_1c : 15.90 +pb_5c : 15.90 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.91 +pb_1c : 15.91 +pb_5c : 15.90 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.92 +pb_1c : 15.92 +pb_5c : 15.90 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.93 +pb_1c : 15.93 +pb_5c : 15.90 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.94 +pb_1c : 15.94 +pb_5c : 15.90 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.95 +pb_1c : 15.95 +pb_5c : 15.95 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.96 +pb_1c : 15.96 +pb_5c : 15.95 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.97 +pb_1c : 15.97 +pb_5c : 15.95 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.98 +pb_1c : 15.98 +pb_5c : 15.95 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +15.99 +pb_1c : 15.99 +pb_5c : 15.95 +pb_10c : 15.90 +pb_25c : 15.75 +pb_1d : 15.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.00 +pb_1c : 16.00 +pb_5c : 16.00 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.01 +pb_1c : 16.01 +pb_5c : 16.00 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.02 +pb_1c : 16.02 +pb_5c : 16.00 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.03 +pb_1c : 16.03 +pb_5c : 16.00 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.04 +pb_1c : 16.04 +pb_5c : 16.00 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.05 +pb_1c : 16.05 +pb_5c : 16.05 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.06 +pb_1c : 16.06 +pb_5c : 16.05 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.07 +pb_1c : 16.07 +pb_5c : 16.05 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.08 +pb_1c : 16.08 +pb_5c : 16.05 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.09 +pb_1c : 16.09 +pb_5c : 16.05 +pb_10c : 16.00 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.10 +pb_1c : 16.10 +pb_5c : 16.10 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.11 +pb_1c : 16.11 +pb_5c : 16.10 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.12 +pb_1c : 16.12 +pb_5c : 16.10 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.13 +pb_1c : 16.13 +pb_5c : 16.10 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.14 +pb_1c : 16.14 +pb_5c : 16.10 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.15 +pb_1c : 16.15 +pb_5c : 16.15 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.16 +pb_1c : 16.16 +pb_5c : 16.15 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.17 +pb_1c : 16.17 +pb_5c : 16.15 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.18 +pb_1c : 16.18 +pb_5c : 16.15 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.19 +pb_1c : 16.19 +pb_5c : 16.15 +pb_10c : 16.10 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.20 +pb_1c : 16.20 +pb_5c : 16.20 +pb_10c : 16.20 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.21 +pb_1c : 16.21 +pb_5c : 16.20 +pb_10c : 16.20 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.22 +pb_1c : 16.22 +pb_5c : 16.20 +pb_10c : 16.20 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.23 +pb_1c : 16.23 +pb_5c : 16.20 +pb_10c : 16.20 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.24 +pb_1c : 16.24 +pb_5c : 16.20 +pb_10c : 16.20 +pb_25c : 16.00 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.25 +pb_1c : 16.25 +pb_5c : 16.25 +pb_10c : 16.20 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.26 +pb_1c : 16.26 +pb_5c : 16.25 +pb_10c : 16.20 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.27 +pb_1c : 16.27 +pb_5c : 16.25 +pb_10c : 16.20 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.28 +pb_1c : 16.28 +pb_5c : 16.25 +pb_10c : 16.20 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.29 +pb_1c : 16.29 +pb_5c : 16.25 +pb_10c : 16.20 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.30 +pb_1c : 16.30 +pb_5c : 16.30 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.31 +pb_1c : 16.31 +pb_5c : 16.30 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.32 +pb_1c : 16.32 +pb_5c : 16.30 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.33 +pb_1c : 16.33 +pb_5c : 16.30 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.34 +pb_1c : 16.34 +pb_5c : 16.30 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.35 +pb_1c : 16.35 +pb_5c : 16.35 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.36 +pb_1c : 16.36 +pb_5c : 16.35 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.37 +pb_1c : 16.37 +pb_5c : 16.35 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.38 +pb_1c : 16.38 +pb_5c : 16.35 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.39 +pb_1c : 16.39 +pb_5c : 16.35 +pb_10c : 16.30 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.40 +pb_1c : 16.40 +pb_5c : 16.40 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.41 +pb_1c : 16.41 +pb_5c : 16.40 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.42 +pb_1c : 16.42 +pb_5c : 16.40 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.43 +pb_1c : 16.43 +pb_5c : 16.40 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.44 +pb_1c : 16.44 +pb_5c : 16.40 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.45 +pb_1c : 16.45 +pb_5c : 16.45 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.46 +pb_1c : 16.46 +pb_5c : 16.45 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.47 +pb_1c : 16.47 +pb_5c : 16.45 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.48 +pb_1c : 16.48 +pb_5c : 16.45 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.49 +pb_1c : 16.49 +pb_5c : 16.45 +pb_10c : 16.40 +pb_25c : 16.25 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.50 +pb_1c : 16.50 +pb_5c : 16.50 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.51 +pb_1c : 16.51 +pb_5c : 16.50 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.52 +pb_1c : 16.52 +pb_5c : 16.50 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.53 +pb_1c : 16.53 +pb_5c : 16.50 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.54 +pb_1c : 16.54 +pb_5c : 16.50 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.55 +pb_1c : 16.55 +pb_5c : 16.55 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.56 +pb_1c : 16.56 +pb_5c : 16.55 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.57 +pb_1c : 16.57 +pb_5c : 16.55 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.58 +pb_1c : 16.58 +pb_5c : 16.55 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.59 +pb_1c : 16.59 +pb_5c : 16.55 +pb_10c : 16.50 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.60 +pb_1c : 16.60 +pb_5c : 16.60 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.61 +pb_1c : 16.61 +pb_5c : 16.60 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.62 +pb_1c : 16.62 +pb_5c : 16.60 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.63 +pb_1c : 16.63 +pb_5c : 16.60 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.64 +pb_1c : 16.64 +pb_5c : 16.60 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.65 +pb_1c : 16.65 +pb_5c : 16.65 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.66 +pb_1c : 16.66 +pb_5c : 16.65 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.67 +pb_1c : 16.67 +pb_5c : 16.65 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.68 +pb_1c : 16.68 +pb_5c : 16.65 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.69 +pb_1c : 16.69 +pb_5c : 16.65 +pb_10c : 16.60 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.70 +pb_1c : 16.70 +pb_5c : 16.70 +pb_10c : 16.70 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.71 +pb_1c : 16.71 +pb_5c : 16.70 +pb_10c : 16.70 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.72 +pb_1c : 16.72 +pb_5c : 16.70 +pb_10c : 16.70 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.73 +pb_1c : 16.73 +pb_5c : 16.70 +pb_10c : 16.70 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.74 +pb_1c : 16.74 +pb_5c : 16.70 +pb_10c : 16.70 +pb_25c : 16.50 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.75 +pb_1c : 16.75 +pb_5c : 16.75 +pb_10c : 16.70 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.76 +pb_1c : 16.76 +pb_5c : 16.75 +pb_10c : 16.70 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.77 +pb_1c : 16.77 +pb_5c : 16.75 +pb_10c : 16.70 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.78 +pb_1c : 16.78 +pb_5c : 16.75 +pb_10c : 16.70 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.79 +pb_1c : 16.79 +pb_5c : 16.75 +pb_10c : 16.70 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.80 +pb_1c : 16.80 +pb_5c : 16.80 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.81 +pb_1c : 16.81 +pb_5c : 16.80 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.82 +pb_1c : 16.82 +pb_5c : 16.80 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.83 +pb_1c : 16.83 +pb_5c : 16.80 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.84 +pb_1c : 16.84 +pb_5c : 16.80 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.85 +pb_1c : 16.85 +pb_5c : 16.85 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.86 +pb_1c : 16.86 +pb_5c : 16.85 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.87 +pb_1c : 16.87 +pb_5c : 16.85 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.88 +pb_1c : 16.88 +pb_5c : 16.85 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.89 +pb_1c : 16.89 +pb_5c : 16.85 +pb_10c : 16.80 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.90 +pb_1c : 16.90 +pb_5c : 16.90 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.91 +pb_1c : 16.91 +pb_5c : 16.90 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.92 +pb_1c : 16.92 +pb_5c : 16.90 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.93 +pb_1c : 16.93 +pb_5c : 16.90 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.94 +pb_1c : 16.94 +pb_5c : 16.90 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.95 +pb_1c : 16.95 +pb_5c : 16.95 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.96 +pb_1c : 16.96 +pb_5c : 16.95 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.97 +pb_1c : 16.97 +pb_5c : 16.95 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.98 +pb_1c : 16.98 +pb_5c : 16.95 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +16.99 +pb_1c : 16.99 +pb_5c : 16.95 +pb_10c : 16.90 +pb_25c : 16.75 +pb_1d : 16.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.00 +pb_1c : 17.00 +pb_5c : 17.00 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.01 +pb_1c : 17.01 +pb_5c : 17.00 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.02 +pb_1c : 17.02 +pb_5c : 17.00 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.03 +pb_1c : 17.03 +pb_5c : 17.00 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.04 +pb_1c : 17.04 +pb_5c : 17.00 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.05 +pb_1c : 17.05 +pb_5c : 17.05 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.06 +pb_1c : 17.06 +pb_5c : 17.05 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.07 +pb_1c : 17.07 +pb_5c : 17.05 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.08 +pb_1c : 17.08 +pb_5c : 17.05 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.09 +pb_1c : 17.09 +pb_5c : 17.05 +pb_10c : 17.00 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.10 +pb_1c : 17.10 +pb_5c : 17.10 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.11 +pb_1c : 17.11 +pb_5c : 17.10 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.12 +pb_1c : 17.12 +pb_5c : 17.10 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.13 +pb_1c : 17.13 +pb_5c : 17.10 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.14 +pb_1c : 17.14 +pb_5c : 17.10 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.15 +pb_1c : 17.15 +pb_5c : 17.15 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.16 +pb_1c : 17.16 +pb_5c : 17.15 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.17 +pb_1c : 17.17 +pb_5c : 17.15 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.18 +pb_1c : 17.18 +pb_5c : 17.15 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.19 +pb_1c : 17.19 +pb_5c : 17.15 +pb_10c : 17.10 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.20 +pb_1c : 17.20 +pb_5c : 17.20 +pb_10c : 17.20 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.21 +pb_1c : 17.21 +pb_5c : 17.20 +pb_10c : 17.20 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.22 +pb_1c : 17.22 +pb_5c : 17.20 +pb_10c : 17.20 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.23 +pb_1c : 17.23 +pb_5c : 17.20 +pb_10c : 17.20 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.24 +pb_1c : 17.24 +pb_5c : 17.20 +pb_10c : 17.20 +pb_25c : 17.00 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.25 +pb_1c : 17.25 +pb_5c : 17.25 +pb_10c : 17.20 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.26 +pb_1c : 17.26 +pb_5c : 17.25 +pb_10c : 17.20 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.27 +pb_1c : 17.27 +pb_5c : 17.25 +pb_10c : 17.20 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.28 +pb_1c : 17.28 +pb_5c : 17.25 +pb_10c : 17.20 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.29 +pb_1c : 17.29 +pb_5c : 17.25 +pb_10c : 17.20 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.30 +pb_1c : 17.30 +pb_5c : 17.30 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.31 +pb_1c : 17.31 +pb_5c : 17.30 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.32 +pb_1c : 17.32 +pb_5c : 17.30 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.33 +pb_1c : 17.33 +pb_5c : 17.30 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.34 +pb_1c : 17.34 +pb_5c : 17.30 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.35 +pb_1c : 17.35 +pb_5c : 17.35 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.36 +pb_1c : 17.36 +pb_5c : 17.35 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.37 +pb_1c : 17.37 +pb_5c : 17.35 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.38 +pb_1c : 17.38 +pb_5c : 17.35 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.39 +pb_1c : 17.39 +pb_5c : 17.35 +pb_10c : 17.30 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.40 +pb_1c : 17.40 +pb_5c : 17.40 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.41 +pb_1c : 17.41 +pb_5c : 17.40 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.42 +pb_1c : 17.42 +pb_5c : 17.40 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.43 +pb_1c : 17.43 +pb_5c : 17.40 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.44 +pb_1c : 17.44 +pb_5c : 17.40 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.45 +pb_1c : 17.45 +pb_5c : 17.45 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.46 +pb_1c : 17.46 +pb_5c : 17.45 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.47 +pb_1c : 17.47 +pb_5c : 17.45 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.48 +pb_1c : 17.48 +pb_5c : 17.45 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.49 +pb_1c : 17.49 +pb_5c : 17.45 +pb_10c : 17.40 +pb_25c : 17.25 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.50 +pb_1c : 17.50 +pb_5c : 17.50 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.51 +pb_1c : 17.51 +pb_5c : 17.50 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.52 +pb_1c : 17.52 +pb_5c : 17.50 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.53 +pb_1c : 17.53 +pb_5c : 17.50 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.54 +pb_1c : 17.54 +pb_5c : 17.50 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.55 +pb_1c : 17.55 +pb_5c : 17.55 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.56 +pb_1c : 17.56 +pb_5c : 17.55 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.57 +pb_1c : 17.57 +pb_5c : 17.55 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.58 +pb_1c : 17.58 +pb_5c : 17.55 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.59 +pb_1c : 17.59 +pb_5c : 17.55 +pb_10c : 17.50 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.60 +pb_1c : 17.60 +pb_5c : 17.60 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.61 +pb_1c : 17.61 +pb_5c : 17.60 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.62 +pb_1c : 17.62 +pb_5c : 17.60 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.63 +pb_1c : 17.63 +pb_5c : 17.60 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.64 +pb_1c : 17.64 +pb_5c : 17.60 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.65 +pb_1c : 17.65 +pb_5c : 17.65 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.66 +pb_1c : 17.66 +pb_5c : 17.65 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.67 +pb_1c : 17.67 +pb_5c : 17.65 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.68 +pb_1c : 17.68 +pb_5c : 17.65 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.69 +pb_1c : 17.69 +pb_5c : 17.65 +pb_10c : 17.60 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.70 +pb_1c : 17.70 +pb_5c : 17.70 +pb_10c : 17.70 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.71 +pb_1c : 17.71 +pb_5c : 17.70 +pb_10c : 17.70 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.72 +pb_1c : 17.72 +pb_5c : 17.70 +pb_10c : 17.70 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.73 +pb_1c : 17.73 +pb_5c : 17.70 +pb_10c : 17.70 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.74 +pb_1c : 17.74 +pb_5c : 17.70 +pb_10c : 17.70 +pb_25c : 17.50 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.75 +pb_1c : 17.75 +pb_5c : 17.75 +pb_10c : 17.70 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.76 +pb_1c : 17.76 +pb_5c : 17.75 +pb_10c : 17.70 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.77 +pb_1c : 17.77 +pb_5c : 17.75 +pb_10c : 17.70 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.78 +pb_1c : 17.78 +pb_5c : 17.75 +pb_10c : 17.70 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.79 +pb_1c : 17.79 +pb_5c : 17.75 +pb_10c : 17.70 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.80 +pb_1c : 17.80 +pb_5c : 17.80 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.81 +pb_1c : 17.81 +pb_5c : 17.80 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.82 +pb_1c : 17.82 +pb_5c : 17.80 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.83 +pb_1c : 17.83 +pb_5c : 17.80 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.84 +pb_1c : 17.84 +pb_5c : 17.80 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.85 +pb_1c : 17.85 +pb_5c : 17.85 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.86 +pb_1c : 17.86 +pb_5c : 17.85 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.87 +pb_1c : 17.87 +pb_5c : 17.85 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.88 +pb_1c : 17.88 +pb_5c : 17.85 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.89 +pb_1c : 17.89 +pb_5c : 17.85 +pb_10c : 17.80 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.90 +pb_1c : 17.90 +pb_5c : 17.90 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.91 +pb_1c : 17.91 +pb_5c : 17.90 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.92 +pb_1c : 17.92 +pb_5c : 17.90 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.93 +pb_1c : 17.93 +pb_5c : 17.90 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.94 +pb_1c : 17.94 +pb_5c : 17.90 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.95 +pb_1c : 17.95 +pb_5c : 17.95 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.96 +pb_1c : 17.96 +pb_5c : 17.95 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.97 +pb_1c : 17.97 +pb_5c : 17.95 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.98 +pb_1c : 17.98 +pb_5c : 17.95 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +17.99 +pb_1c : 17.99 +pb_5c : 17.95 +pb_10c : 17.90 +pb_25c : 17.75 +pb_1d : 17.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.00 +pb_1c : 18.00 +pb_5c : 18.00 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.01 +pb_1c : 18.01 +pb_5c : 18.00 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.02 +pb_1c : 18.02 +pb_5c : 18.00 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.03 +pb_1c : 18.03 +pb_5c : 18.00 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.04 +pb_1c : 18.04 +pb_5c : 18.00 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.05 +pb_1c : 18.05 +pb_5c : 18.05 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.06 +pb_1c : 18.06 +pb_5c : 18.05 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.07 +pb_1c : 18.07 +pb_5c : 18.05 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.08 +pb_1c : 18.08 +pb_5c : 18.05 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.09 +pb_1c : 18.09 +pb_5c : 18.05 +pb_10c : 18.00 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.10 +pb_1c : 18.10 +pb_5c : 18.10 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.11 +pb_1c : 18.11 +pb_5c : 18.10 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.12 +pb_1c : 18.12 +pb_5c : 18.10 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.13 +pb_1c : 18.13 +pb_5c : 18.10 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.14 +pb_1c : 18.14 +pb_5c : 18.10 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.15 +pb_1c : 18.15 +pb_5c : 18.15 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.16 +pb_1c : 18.16 +pb_5c : 18.15 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.17 +pb_1c : 18.17 +pb_5c : 18.15 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.18 +pb_1c : 18.18 +pb_5c : 18.15 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.19 +pb_1c : 18.19 +pb_5c : 18.15 +pb_10c : 18.10 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.20 +pb_1c : 18.20 +pb_5c : 18.20 +pb_10c : 18.20 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.21 +pb_1c : 18.21 +pb_5c : 18.20 +pb_10c : 18.20 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.22 +pb_1c : 18.22 +pb_5c : 18.20 +pb_10c : 18.20 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.23 +pb_1c : 18.23 +pb_5c : 18.20 +pb_10c : 18.20 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.24 +pb_1c : 18.24 +pb_5c : 18.20 +pb_10c : 18.20 +pb_25c : 18.00 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.25 +pb_1c : 18.25 +pb_5c : 18.25 +pb_10c : 18.20 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.26 +pb_1c : 18.26 +pb_5c : 18.25 +pb_10c : 18.20 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.27 +pb_1c : 18.27 +pb_5c : 18.25 +pb_10c : 18.20 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.28 +pb_1c : 18.28 +pb_5c : 18.25 +pb_10c : 18.20 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.29 +pb_1c : 18.29 +pb_5c : 18.25 +pb_10c : 18.20 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.30 +pb_1c : 18.30 +pb_5c : 18.30 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.31 +pb_1c : 18.31 +pb_5c : 18.30 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.32 +pb_1c : 18.32 +pb_5c : 18.30 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.33 +pb_1c : 18.33 +pb_5c : 18.30 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.34 +pb_1c : 18.34 +pb_5c : 18.30 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.35 +pb_1c : 18.35 +pb_5c : 18.35 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.36 +pb_1c : 18.36 +pb_5c : 18.35 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.37 +pb_1c : 18.37 +pb_5c : 18.35 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.38 +pb_1c : 18.38 +pb_5c : 18.35 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.39 +pb_1c : 18.39 +pb_5c : 18.35 +pb_10c : 18.30 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.40 +pb_1c : 18.40 +pb_5c : 18.40 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.41 +pb_1c : 18.41 +pb_5c : 18.40 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.42 +pb_1c : 18.42 +pb_5c : 18.40 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.43 +pb_1c : 18.43 +pb_5c : 18.40 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.44 +pb_1c : 18.44 +pb_5c : 18.40 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.45 +pb_1c : 18.45 +pb_5c : 18.45 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.46 +pb_1c : 18.46 +pb_5c : 18.45 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.47 +pb_1c : 18.47 +pb_5c : 18.45 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.48 +pb_1c : 18.48 +pb_5c : 18.45 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.49 +pb_1c : 18.49 +pb_5c : 18.45 +pb_10c : 18.40 +pb_25c : 18.25 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.50 +pb_1c : 18.50 +pb_5c : 18.50 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.51 +pb_1c : 18.51 +pb_5c : 18.50 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.52 +pb_1c : 18.52 +pb_5c : 18.50 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.53 +pb_1c : 18.53 +pb_5c : 18.50 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.54 +pb_1c : 18.54 +pb_5c : 18.50 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.55 +pb_1c : 18.55 +pb_5c : 18.55 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.56 +pb_1c : 18.56 +pb_5c : 18.55 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.57 +pb_1c : 18.57 +pb_5c : 18.55 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.58 +pb_1c : 18.58 +pb_5c : 18.55 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.59 +pb_1c : 18.59 +pb_5c : 18.55 +pb_10c : 18.50 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.60 +pb_1c : 18.60 +pb_5c : 18.60 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.61 +pb_1c : 18.61 +pb_5c : 18.60 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.62 +pb_1c : 18.62 +pb_5c : 18.60 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.63 +pb_1c : 18.63 +pb_5c : 18.60 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.64 +pb_1c : 18.64 +pb_5c : 18.60 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.65 +pb_1c : 18.65 +pb_5c : 18.65 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.66 +pb_1c : 18.66 +pb_5c : 18.65 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.67 +pb_1c : 18.67 +pb_5c : 18.65 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.68 +pb_1c : 18.68 +pb_5c : 18.65 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.69 +pb_1c : 18.69 +pb_5c : 18.65 +pb_10c : 18.60 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.70 +pb_1c : 18.70 +pb_5c : 18.70 +pb_10c : 18.70 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.71 +pb_1c : 18.71 +pb_5c : 18.70 +pb_10c : 18.70 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.72 +pb_1c : 18.72 +pb_5c : 18.70 +pb_10c : 18.70 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.73 +pb_1c : 18.73 +pb_5c : 18.70 +pb_10c : 18.70 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.74 +pb_1c : 18.74 +pb_5c : 18.70 +pb_10c : 18.70 +pb_25c : 18.50 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.75 +pb_1c : 18.75 +pb_5c : 18.75 +pb_10c : 18.70 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.76 +pb_1c : 18.76 +pb_5c : 18.75 +pb_10c : 18.70 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.77 +pb_1c : 18.77 +pb_5c : 18.75 +pb_10c : 18.70 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.78 +pb_1c : 18.78 +pb_5c : 18.75 +pb_10c : 18.70 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.79 +pb_1c : 18.79 +pb_5c : 18.75 +pb_10c : 18.70 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.80 +pb_1c : 18.80 +pb_5c : 18.80 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.81 +pb_1c : 18.81 +pb_5c : 18.80 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.82 +pb_1c : 18.82 +pb_5c : 18.80 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.83 +pb_1c : 18.83 +pb_5c : 18.80 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.84 +pb_1c : 18.84 +pb_5c : 18.80 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.85 +pb_1c : 18.85 +pb_5c : 18.85 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.86 +pb_1c : 18.86 +pb_5c : 18.85 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.87 +pb_1c : 18.87 +pb_5c : 18.85 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.88 +pb_1c : 18.88 +pb_5c : 18.85 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.89 +pb_1c : 18.89 +pb_5c : 18.85 +pb_10c : 18.80 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.90 +pb_1c : 18.90 +pb_5c : 18.90 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.91 +pb_1c : 18.91 +pb_5c : 18.90 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.92 +pb_1c : 18.92 +pb_5c : 18.90 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.93 +pb_1c : 18.93 +pb_5c : 18.90 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.94 +pb_1c : 18.94 +pb_5c : 18.90 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.95 +pb_1c : 18.95 +pb_5c : 18.95 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.96 +pb_1c : 18.96 +pb_5c : 18.95 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.97 +pb_1c : 18.97 +pb_5c : 18.95 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.98 +pb_1c : 18.98 +pb_5c : 18.95 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +18.99 +pb_1c : 18.99 +pb_5c : 18.95 +pb_10c : 18.90 +pb_25c : 18.75 +pb_1d : 18.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.00 +pb_1c : 19.00 +pb_5c : 19.00 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.01 +pb_1c : 19.01 +pb_5c : 19.00 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.02 +pb_1c : 19.02 +pb_5c : 19.00 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.03 +pb_1c : 19.03 +pb_5c : 19.00 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.04 +pb_1c : 19.04 +pb_5c : 19.00 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.05 +pb_1c : 19.05 +pb_5c : 19.05 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.06 +pb_1c : 19.06 +pb_5c : 19.05 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.07 +pb_1c : 19.07 +pb_5c : 19.05 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.08 +pb_1c : 19.08 +pb_5c : 19.05 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.09 +pb_1c : 19.09 +pb_5c : 19.05 +pb_10c : 19.00 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.10 +pb_1c : 19.10 +pb_5c : 19.10 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.11 +pb_1c : 19.11 +pb_5c : 19.10 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.12 +pb_1c : 19.12 +pb_5c : 19.10 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.13 +pb_1c : 19.13 +pb_5c : 19.10 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.14 +pb_1c : 19.14 +pb_5c : 19.10 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.15 +pb_1c : 19.15 +pb_5c : 19.15 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.16 +pb_1c : 19.16 +pb_5c : 19.15 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.17 +pb_1c : 19.17 +pb_5c : 19.15 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.18 +pb_1c : 19.18 +pb_5c : 19.15 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.19 +pb_1c : 19.19 +pb_5c : 19.15 +pb_10c : 19.10 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.20 +pb_1c : 19.20 +pb_5c : 19.20 +pb_10c : 19.20 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.21 +pb_1c : 19.21 +pb_5c : 19.20 +pb_10c : 19.20 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.22 +pb_1c : 19.22 +pb_5c : 19.20 +pb_10c : 19.20 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.23 +pb_1c : 19.23 +pb_5c : 19.20 +pb_10c : 19.20 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.24 +pb_1c : 19.24 +pb_5c : 19.20 +pb_10c : 19.20 +pb_25c : 19.00 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.25 +pb_1c : 19.25 +pb_5c : 19.25 +pb_10c : 19.20 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.26 +pb_1c : 19.26 +pb_5c : 19.25 +pb_10c : 19.20 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.27 +pb_1c : 19.27 +pb_5c : 19.25 +pb_10c : 19.20 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.28 +pb_1c : 19.28 +pb_5c : 19.25 +pb_10c : 19.20 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.29 +pb_1c : 19.29 +pb_5c : 19.25 +pb_10c : 19.20 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.30 +pb_1c : 19.30 +pb_5c : 19.30 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.31 +pb_1c : 19.31 +pb_5c : 19.30 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.32 +pb_1c : 19.32 +pb_5c : 19.30 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.33 +pb_1c : 19.33 +pb_5c : 19.30 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.34 +pb_1c : 19.34 +pb_5c : 19.30 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.35 +pb_1c : 19.35 +pb_5c : 19.35 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.36 +pb_1c : 19.36 +pb_5c : 19.35 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.37 +pb_1c : 19.37 +pb_5c : 19.35 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.38 +pb_1c : 19.38 +pb_5c : 19.35 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.39 +pb_1c : 19.39 +pb_5c : 19.35 +pb_10c : 19.30 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.40 +pb_1c : 19.40 +pb_5c : 19.40 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.41 +pb_1c : 19.41 +pb_5c : 19.40 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.42 +pb_1c : 19.42 +pb_5c : 19.40 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.43 +pb_1c : 19.43 +pb_5c : 19.40 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.44 +pb_1c : 19.44 +pb_5c : 19.40 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.45 +pb_1c : 19.45 +pb_5c : 19.45 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.46 +pb_1c : 19.46 +pb_5c : 19.45 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.47 +pb_1c : 19.47 +pb_5c : 19.45 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.48 +pb_1c : 19.48 +pb_5c : 19.45 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.49 +pb_1c : 19.49 +pb_5c : 19.45 +pb_10c : 19.40 +pb_25c : 19.25 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.50 +pb_1c : 19.50 +pb_5c : 19.50 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.51 +pb_1c : 19.51 +pb_5c : 19.50 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.52 +pb_1c : 19.52 +pb_5c : 19.50 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.53 +pb_1c : 19.53 +pb_5c : 19.50 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.54 +pb_1c : 19.54 +pb_5c : 19.50 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.55 +pb_1c : 19.55 +pb_5c : 19.55 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.56 +pb_1c : 19.56 +pb_5c : 19.55 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.57 +pb_1c : 19.57 +pb_5c : 19.55 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.58 +pb_1c : 19.58 +pb_5c : 19.55 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.59 +pb_1c : 19.59 +pb_5c : 19.55 +pb_10c : 19.50 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.60 +pb_1c : 19.60 +pb_5c : 19.60 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.61 +pb_1c : 19.61 +pb_5c : 19.60 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.62 +pb_1c : 19.62 +pb_5c : 19.60 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.63 +pb_1c : 19.63 +pb_5c : 19.60 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.64 +pb_1c : 19.64 +pb_5c : 19.60 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.65 +pb_1c : 19.65 +pb_5c : 19.65 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.66 +pb_1c : 19.66 +pb_5c : 19.65 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.67 +pb_1c : 19.67 +pb_5c : 19.65 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.68 +pb_1c : 19.68 +pb_5c : 19.65 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.69 +pb_1c : 19.69 +pb_5c : 19.65 +pb_10c : 19.60 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.70 +pb_1c : 19.70 +pb_5c : 19.70 +pb_10c : 19.70 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.71 +pb_1c : 19.71 +pb_5c : 19.70 +pb_10c : 19.70 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.72 +pb_1c : 19.72 +pb_5c : 19.70 +pb_10c : 19.70 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.73 +pb_1c : 19.73 +pb_5c : 19.70 +pb_10c : 19.70 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.74 +pb_1c : 19.74 +pb_5c : 19.70 +pb_10c : 19.70 +pb_25c : 19.50 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.75 +pb_1c : 19.75 +pb_5c : 19.75 +pb_10c : 19.70 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.76 +pb_1c : 19.76 +pb_5c : 19.75 +pb_10c : 19.70 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.77 +pb_1c : 19.77 +pb_5c : 19.75 +pb_10c : 19.70 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.78 +pb_1c : 19.78 +pb_5c : 19.75 +pb_10c : 19.70 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.79 +pb_1c : 19.79 +pb_5c : 19.75 +pb_10c : 19.70 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.80 +pb_1c : 19.80 +pb_5c : 19.80 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.81 +pb_1c : 19.81 +pb_5c : 19.80 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.82 +pb_1c : 19.82 +pb_5c : 19.80 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.83 +pb_1c : 19.83 +pb_5c : 19.80 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.84 +pb_1c : 19.84 +pb_5c : 19.80 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.85 +pb_1c : 19.85 +pb_5c : 19.85 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.86 +pb_1c : 19.86 +pb_5c : 19.85 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.87 +pb_1c : 19.87 +pb_5c : 19.85 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.88 +pb_1c : 19.88 +pb_5c : 19.85 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.89 +pb_1c : 19.89 +pb_5c : 19.85 +pb_10c : 19.80 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.90 +pb_1c : 19.90 +pb_5c : 19.90 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.91 +pb_1c : 19.91 +pb_5c : 19.90 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.92 +pb_1c : 19.92 +pb_5c : 19.90 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.93 +pb_1c : 19.93 +pb_5c : 19.90 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.94 +pb_1c : 19.94 +pb_5c : 19.90 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.95 +pb_1c : 19.95 +pb_5c : 19.95 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.96 +pb_1c : 19.96 +pb_5c : 19.95 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.97 +pb_1c : 19.97 +pb_5c : 19.95 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.98 +pb_1c : 19.98 +pb_5c : 19.95 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +19.99 +pb_1c : 19.99 +pb_5c : 19.95 +pb_10c : 19.90 +pb_25c : 19.75 +pb_1d : 19.00 +pb_5d : 15.00 +pb_10d : 10.00 + +20.00 +pb_1c : 20.00 +pb_5c : 20.00 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.01 +pb_1c : 20.01 +pb_5c : 20.00 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.02 +pb_1c : 20.02 +pb_5c : 20.00 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.03 +pb_1c : 20.03 +pb_5c : 20.00 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.04 +pb_1c : 20.04 +pb_5c : 20.00 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.05 +pb_1c : 20.05 +pb_5c : 20.05 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.06 +pb_1c : 20.06 +pb_5c : 20.05 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.07 +pb_1c : 20.07 +pb_5c : 20.05 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.08 +pb_1c : 20.08 +pb_5c : 20.05 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.09 +pb_1c : 20.09 +pb_5c : 20.05 +pb_10c : 20.00 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.10 +pb_1c : 20.10 +pb_5c : 20.10 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.11 +pb_1c : 20.11 +pb_5c : 20.10 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.12 +pb_1c : 20.12 +pb_5c : 20.10 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.13 +pb_1c : 20.13 +pb_5c : 20.10 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.14 +pb_1c : 20.14 +pb_5c : 20.10 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.15 +pb_1c : 20.15 +pb_5c : 20.15 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.16 +pb_1c : 20.16 +pb_5c : 20.15 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.17 +pb_1c : 20.17 +pb_5c : 20.15 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.18 +pb_1c : 20.18 +pb_5c : 20.15 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.19 +pb_1c : 20.19 +pb_5c : 20.15 +pb_10c : 20.10 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.20 +pb_1c : 20.20 +pb_5c : 20.20 +pb_10c : 20.20 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.21 +pb_1c : 20.21 +pb_5c : 20.20 +pb_10c : 20.20 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.22 +pb_1c : 20.22 +pb_5c : 20.20 +pb_10c : 20.20 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.23 +pb_1c : 20.23 +pb_5c : 20.20 +pb_10c : 20.20 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.24 +pb_1c : 20.24 +pb_5c : 20.20 +pb_10c : 20.20 +pb_25c : 20.00 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.25 +pb_1c : 20.25 +pb_5c : 20.25 +pb_10c : 20.20 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.26 +pb_1c : 20.26 +pb_5c : 20.25 +pb_10c : 20.20 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.27 +pb_1c : 20.27 +pb_5c : 20.25 +pb_10c : 20.20 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.28 +pb_1c : 20.28 +pb_5c : 20.25 +pb_10c : 20.20 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.29 +pb_1c : 20.29 +pb_5c : 20.25 +pb_10c : 20.20 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.30 +pb_1c : 20.30 +pb_5c : 20.30 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.31 +pb_1c : 20.31 +pb_5c : 20.30 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.32 +pb_1c : 20.32 +pb_5c : 20.30 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.33 +pb_1c : 20.33 +pb_5c : 20.30 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.34 +pb_1c : 20.34 +pb_5c : 20.30 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.35 +pb_1c : 20.35 +pb_5c : 20.35 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.36 +pb_1c : 20.36 +pb_5c : 20.35 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.37 +pb_1c : 20.37 +pb_5c : 20.35 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.38 +pb_1c : 20.38 +pb_5c : 20.35 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.39 +pb_1c : 20.39 +pb_5c : 20.35 +pb_10c : 20.30 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.40 +pb_1c : 20.40 +pb_5c : 20.40 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.41 +pb_1c : 20.41 +pb_5c : 20.40 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.42 +pb_1c : 20.42 +pb_5c : 20.40 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.43 +pb_1c : 20.43 +pb_5c : 20.40 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.44 +pb_1c : 20.44 +pb_5c : 20.40 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.45 +pb_1c : 20.45 +pb_5c : 20.45 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.46 +pb_1c : 20.46 +pb_5c : 20.45 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.47 +pb_1c : 20.47 +pb_5c : 20.45 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.48 +pb_1c : 20.48 +pb_5c : 20.45 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.49 +pb_1c : 20.49 +pb_5c : 20.45 +pb_10c : 20.40 +pb_25c : 20.25 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.50 +pb_1c : 20.50 +pb_5c : 20.50 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.51 +pb_1c : 20.51 +pb_5c : 20.50 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.52 +pb_1c : 20.52 +pb_5c : 20.50 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.53 +pb_1c : 20.53 +pb_5c : 20.50 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.54 +pb_1c : 20.54 +pb_5c : 20.50 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.55 +pb_1c : 20.55 +pb_5c : 20.55 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.56 +pb_1c : 20.56 +pb_5c : 20.55 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.57 +pb_1c : 20.57 +pb_5c : 20.55 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.58 +pb_1c : 20.58 +pb_5c : 20.55 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.59 +pb_1c : 20.59 +pb_5c : 20.55 +pb_10c : 20.50 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.60 +pb_1c : 20.60 +pb_5c : 20.60 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.61 +pb_1c : 20.61 +pb_5c : 20.60 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.62 +pb_1c : 20.62 +pb_5c : 20.60 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.63 +pb_1c : 20.63 +pb_5c : 20.60 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.64 +pb_1c : 20.64 +pb_5c : 20.60 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.65 +pb_1c : 20.65 +pb_5c : 20.65 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.66 +pb_1c : 20.66 +pb_5c : 20.65 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.67 +pb_1c : 20.67 +pb_5c : 20.65 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.68 +pb_1c : 20.68 +pb_5c : 20.65 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.69 +pb_1c : 20.69 +pb_5c : 20.65 +pb_10c : 20.60 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.70 +pb_1c : 20.70 +pb_5c : 20.70 +pb_10c : 20.70 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.71 +pb_1c : 20.71 +pb_5c : 20.70 +pb_10c : 20.70 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.72 +pb_1c : 20.72 +pb_5c : 20.70 +pb_10c : 20.70 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.73 +pb_1c : 20.73 +pb_5c : 20.70 +pb_10c : 20.70 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.74 +pb_1c : 20.74 +pb_5c : 20.70 +pb_10c : 20.70 +pb_25c : 20.50 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.75 +pb_1c : 20.75 +pb_5c : 20.75 +pb_10c : 20.70 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.76 +pb_1c : 20.76 +pb_5c : 20.75 +pb_10c : 20.70 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.77 +pb_1c : 20.77 +pb_5c : 20.75 +pb_10c : 20.70 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.78 +pb_1c : 20.78 +pb_5c : 20.75 +pb_10c : 20.70 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.79 +pb_1c : 20.79 +pb_5c : 20.75 +pb_10c : 20.70 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.80 +pb_1c : 20.80 +pb_5c : 20.80 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.81 +pb_1c : 20.81 +pb_5c : 20.80 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.82 +pb_1c : 20.82 +pb_5c : 20.80 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.83 +pb_1c : 20.83 +pb_5c : 20.80 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.84 +pb_1c : 20.84 +pb_5c : 20.80 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.85 +pb_1c : 20.85 +pb_5c : 20.85 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.86 +pb_1c : 20.86 +pb_5c : 20.85 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.87 +pb_1c : 20.87 +pb_5c : 20.85 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.88 +pb_1c : 20.88 +pb_5c : 20.85 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.89 +pb_1c : 20.89 +pb_5c : 20.85 +pb_10c : 20.80 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.90 +pb_1c : 20.90 +pb_5c : 20.90 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.91 +pb_1c : 20.91 +pb_5c : 20.90 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.92 +pb_1c : 20.92 +pb_5c : 20.90 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.93 +pb_1c : 20.93 +pb_5c : 20.90 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.94 +pb_1c : 20.94 +pb_5c : 20.90 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.95 +pb_1c : 20.95 +pb_5c : 20.95 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.96 +pb_1c : 20.96 +pb_5c : 20.95 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.97 +pb_1c : 20.97 +pb_5c : 20.95 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.98 +pb_1c : 20.98 +pb_5c : 20.95 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +20.99 +pb_1c : 20.99 +pb_5c : 20.95 +pb_10c : 20.90 +pb_25c : 20.75 +pb_1d : 20.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.00 +pb_1c : 21.00 +pb_5c : 21.00 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.01 +pb_1c : 21.01 +pb_5c : 21.00 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.02 +pb_1c : 21.02 +pb_5c : 21.00 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.03 +pb_1c : 21.03 +pb_5c : 21.00 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.04 +pb_1c : 21.04 +pb_5c : 21.00 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.05 +pb_1c : 21.05 +pb_5c : 21.05 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.06 +pb_1c : 21.06 +pb_5c : 21.05 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.07 +pb_1c : 21.07 +pb_5c : 21.05 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.08 +pb_1c : 21.08 +pb_5c : 21.05 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.09 +pb_1c : 21.09 +pb_5c : 21.05 +pb_10c : 21.00 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.10 +pb_1c : 21.10 +pb_5c : 21.10 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.11 +pb_1c : 21.11 +pb_5c : 21.10 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.12 +pb_1c : 21.12 +pb_5c : 21.10 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.13 +pb_1c : 21.13 +pb_5c : 21.10 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.14 +pb_1c : 21.14 +pb_5c : 21.10 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.15 +pb_1c : 21.15 +pb_5c : 21.15 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.16 +pb_1c : 21.16 +pb_5c : 21.15 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.17 +pb_1c : 21.17 +pb_5c : 21.15 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.18 +pb_1c : 21.18 +pb_5c : 21.15 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.19 +pb_1c : 21.19 +pb_5c : 21.15 +pb_10c : 21.10 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.20 +pb_1c : 21.20 +pb_5c : 21.20 +pb_10c : 21.20 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.21 +pb_1c : 21.21 +pb_5c : 21.20 +pb_10c : 21.20 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.22 +pb_1c : 21.22 +pb_5c : 21.20 +pb_10c : 21.20 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.23 +pb_1c : 21.23 +pb_5c : 21.20 +pb_10c : 21.20 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.24 +pb_1c : 21.24 +pb_5c : 21.20 +pb_10c : 21.20 +pb_25c : 21.00 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.25 +pb_1c : 21.25 +pb_5c : 21.25 +pb_10c : 21.20 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.26 +pb_1c : 21.26 +pb_5c : 21.25 +pb_10c : 21.20 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.27 +pb_1c : 21.27 +pb_5c : 21.25 +pb_10c : 21.20 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.28 +pb_1c : 21.28 +pb_5c : 21.25 +pb_10c : 21.20 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.29 +pb_1c : 21.29 +pb_5c : 21.25 +pb_10c : 21.20 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.30 +pb_1c : 21.30 +pb_5c : 21.30 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.31 +pb_1c : 21.31 +pb_5c : 21.30 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.32 +pb_1c : 21.32 +pb_5c : 21.30 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.33 +pb_1c : 21.33 +pb_5c : 21.30 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.34 +pb_1c : 21.34 +pb_5c : 21.30 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.35 +pb_1c : 21.35 +pb_5c : 21.35 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.36 +pb_1c : 21.36 +pb_5c : 21.35 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.37 +pb_1c : 21.37 +pb_5c : 21.35 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.38 +pb_1c : 21.38 +pb_5c : 21.35 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.39 +pb_1c : 21.39 +pb_5c : 21.35 +pb_10c : 21.30 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.40 +pb_1c : 21.40 +pb_5c : 21.40 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.41 +pb_1c : 21.41 +pb_5c : 21.40 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.42 +pb_1c : 21.42 +pb_5c : 21.40 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.43 +pb_1c : 21.43 +pb_5c : 21.40 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.44 +pb_1c : 21.44 +pb_5c : 21.40 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.45 +pb_1c : 21.45 +pb_5c : 21.45 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.46 +pb_1c : 21.46 +pb_5c : 21.45 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.47 +pb_1c : 21.47 +pb_5c : 21.45 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.48 +pb_1c : 21.48 +pb_5c : 21.45 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.49 +pb_1c : 21.49 +pb_5c : 21.45 +pb_10c : 21.40 +pb_25c : 21.25 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.50 +pb_1c : 21.50 +pb_5c : 21.50 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.51 +pb_1c : 21.51 +pb_5c : 21.50 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.52 +pb_1c : 21.52 +pb_5c : 21.50 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.53 +pb_1c : 21.53 +pb_5c : 21.50 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.54 +pb_1c : 21.54 +pb_5c : 21.50 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.55 +pb_1c : 21.55 +pb_5c : 21.55 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.56 +pb_1c : 21.56 +pb_5c : 21.55 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.57 +pb_1c : 21.57 +pb_5c : 21.55 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.58 +pb_1c : 21.58 +pb_5c : 21.55 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.59 +pb_1c : 21.59 +pb_5c : 21.55 +pb_10c : 21.50 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.60 +pb_1c : 21.60 +pb_5c : 21.60 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.61 +pb_1c : 21.61 +pb_5c : 21.60 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.62 +pb_1c : 21.62 +pb_5c : 21.60 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.63 +pb_1c : 21.63 +pb_5c : 21.60 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.64 +pb_1c : 21.64 +pb_5c : 21.60 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.65 +pb_1c : 21.65 +pb_5c : 21.65 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.66 +pb_1c : 21.66 +pb_5c : 21.65 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.67 +pb_1c : 21.67 +pb_5c : 21.65 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.68 +pb_1c : 21.68 +pb_5c : 21.65 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.69 +pb_1c : 21.69 +pb_5c : 21.65 +pb_10c : 21.60 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.70 +pb_1c : 21.70 +pb_5c : 21.70 +pb_10c : 21.70 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.71 +pb_1c : 21.71 +pb_5c : 21.70 +pb_10c : 21.70 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.72 +pb_1c : 21.72 +pb_5c : 21.70 +pb_10c : 21.70 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.73 +pb_1c : 21.73 +pb_5c : 21.70 +pb_10c : 21.70 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.74 +pb_1c : 21.74 +pb_5c : 21.70 +pb_10c : 21.70 +pb_25c : 21.50 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.75 +pb_1c : 21.75 +pb_5c : 21.75 +pb_10c : 21.70 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.76 +pb_1c : 21.76 +pb_5c : 21.75 +pb_10c : 21.70 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.77 +pb_1c : 21.77 +pb_5c : 21.75 +pb_10c : 21.70 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.78 +pb_1c : 21.78 +pb_5c : 21.75 +pb_10c : 21.70 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.79 +pb_1c : 21.79 +pb_5c : 21.75 +pb_10c : 21.70 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.80 +pb_1c : 21.80 +pb_5c : 21.80 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.81 +pb_1c : 21.81 +pb_5c : 21.80 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.82 +pb_1c : 21.82 +pb_5c : 21.80 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.83 +pb_1c : 21.83 +pb_5c : 21.80 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.84 +pb_1c : 21.84 +pb_5c : 21.80 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.85 +pb_1c : 21.85 +pb_5c : 21.85 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.86 +pb_1c : 21.86 +pb_5c : 21.85 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.87 +pb_1c : 21.87 +pb_5c : 21.85 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.88 +pb_1c : 21.88 +pb_5c : 21.85 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.89 +pb_1c : 21.89 +pb_5c : 21.85 +pb_10c : 21.80 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.90 +pb_1c : 21.90 +pb_5c : 21.90 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.91 +pb_1c : 21.91 +pb_5c : 21.90 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.92 +pb_1c : 21.92 +pb_5c : 21.90 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.93 +pb_1c : 21.93 +pb_5c : 21.90 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.94 +pb_1c : 21.94 +pb_5c : 21.90 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.95 +pb_1c : 21.95 +pb_5c : 21.95 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.96 +pb_1c : 21.96 +pb_5c : 21.95 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.97 +pb_1c : 21.97 +pb_5c : 21.95 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.98 +pb_1c : 21.98 +pb_5c : 21.95 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +21.99 +pb_1c : 21.99 +pb_5c : 21.95 +pb_10c : 21.90 +pb_25c : 21.75 +pb_1d : 21.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.00 +pb_1c : 22.00 +pb_5c : 22.00 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.01 +pb_1c : 22.01 +pb_5c : 22.00 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.02 +pb_1c : 22.02 +pb_5c : 22.00 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.03 +pb_1c : 22.03 +pb_5c : 22.00 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.04 +pb_1c : 22.04 +pb_5c : 22.00 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.05 +pb_1c : 22.05 +pb_5c : 22.05 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.06 +pb_1c : 22.06 +pb_5c : 22.05 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.07 +pb_1c : 22.07 +pb_5c : 22.05 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.08 +pb_1c : 22.08 +pb_5c : 22.05 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.09 +pb_1c : 22.09 +pb_5c : 22.05 +pb_10c : 22.00 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.10 +pb_1c : 22.10 +pb_5c : 22.10 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.11 +pb_1c : 22.11 +pb_5c : 22.10 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.12 +pb_1c : 22.12 +pb_5c : 22.10 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.13 +pb_1c : 22.13 +pb_5c : 22.10 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.14 +pb_1c : 22.14 +pb_5c : 22.10 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.15 +pb_1c : 22.15 +pb_5c : 22.15 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.16 +pb_1c : 22.16 +pb_5c : 22.15 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.17 +pb_1c : 22.17 +pb_5c : 22.15 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.18 +pb_1c : 22.18 +pb_5c : 22.15 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.19 +pb_1c : 22.19 +pb_5c : 22.15 +pb_10c : 22.10 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.20 +pb_1c : 22.20 +pb_5c : 22.20 +pb_10c : 22.20 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.21 +pb_1c : 22.21 +pb_5c : 22.20 +pb_10c : 22.20 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.22 +pb_1c : 22.22 +pb_5c : 22.20 +pb_10c : 22.20 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.23 +pb_1c : 22.23 +pb_5c : 22.20 +pb_10c : 22.20 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.24 +pb_1c : 22.24 +pb_5c : 22.20 +pb_10c : 22.20 +pb_25c : 22.00 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.25 +pb_1c : 22.25 +pb_5c : 22.25 +pb_10c : 22.20 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.26 +pb_1c : 22.26 +pb_5c : 22.25 +pb_10c : 22.20 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.27 +pb_1c : 22.27 +pb_5c : 22.25 +pb_10c : 22.20 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.28 +pb_1c : 22.28 +pb_5c : 22.25 +pb_10c : 22.20 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.29 +pb_1c : 22.29 +pb_5c : 22.25 +pb_10c : 22.20 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.30 +pb_1c : 22.30 +pb_5c : 22.30 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.31 +pb_1c : 22.31 +pb_5c : 22.30 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.32 +pb_1c : 22.32 +pb_5c : 22.30 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.33 +pb_1c : 22.33 +pb_5c : 22.30 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.34 +pb_1c : 22.34 +pb_5c : 22.30 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.35 +pb_1c : 22.35 +pb_5c : 22.35 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.36 +pb_1c : 22.36 +pb_5c : 22.35 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.37 +pb_1c : 22.37 +pb_5c : 22.35 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.38 +pb_1c : 22.38 +pb_5c : 22.35 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.39 +pb_1c : 22.39 +pb_5c : 22.35 +pb_10c : 22.30 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.40 +pb_1c : 22.40 +pb_5c : 22.40 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.41 +pb_1c : 22.41 +pb_5c : 22.40 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.42 +pb_1c : 22.42 +pb_5c : 22.40 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.43 +pb_1c : 22.43 +pb_5c : 22.40 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.44 +pb_1c : 22.44 +pb_5c : 22.40 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.45 +pb_1c : 22.45 +pb_5c : 22.45 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.46 +pb_1c : 22.46 +pb_5c : 22.45 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.47 +pb_1c : 22.47 +pb_5c : 22.45 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.48 +pb_1c : 22.48 +pb_5c : 22.45 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.49 +pb_1c : 22.49 +pb_5c : 22.45 +pb_10c : 22.40 +pb_25c : 22.25 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.50 +pb_1c : 22.50 +pb_5c : 22.50 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.51 +pb_1c : 22.51 +pb_5c : 22.50 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.52 +pb_1c : 22.52 +pb_5c : 22.50 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.53 +pb_1c : 22.53 +pb_5c : 22.50 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.54 +pb_1c : 22.54 +pb_5c : 22.50 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.55 +pb_1c : 22.55 +pb_5c : 22.55 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.56 +pb_1c : 22.56 +pb_5c : 22.55 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.57 +pb_1c : 22.57 +pb_5c : 22.55 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.58 +pb_1c : 22.58 +pb_5c : 22.55 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.59 +pb_1c : 22.59 +pb_5c : 22.55 +pb_10c : 22.50 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.60 +pb_1c : 22.60 +pb_5c : 22.60 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.61 +pb_1c : 22.61 +pb_5c : 22.60 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.62 +pb_1c : 22.62 +pb_5c : 22.60 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.63 +pb_1c : 22.63 +pb_5c : 22.60 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.64 +pb_1c : 22.64 +pb_5c : 22.60 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.65 +pb_1c : 22.65 +pb_5c : 22.65 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.66 +pb_1c : 22.66 +pb_5c : 22.65 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.67 +pb_1c : 22.67 +pb_5c : 22.65 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.68 +pb_1c : 22.68 +pb_5c : 22.65 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.69 +pb_1c : 22.69 +pb_5c : 22.65 +pb_10c : 22.60 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.70 +pb_1c : 22.70 +pb_5c : 22.70 +pb_10c : 22.70 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.71 +pb_1c : 22.71 +pb_5c : 22.70 +pb_10c : 22.70 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.72 +pb_1c : 22.72 +pb_5c : 22.70 +pb_10c : 22.70 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.73 +pb_1c : 22.73 +pb_5c : 22.70 +pb_10c : 22.70 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.74 +pb_1c : 22.74 +pb_5c : 22.70 +pb_10c : 22.70 +pb_25c : 22.50 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.75 +pb_1c : 22.75 +pb_5c : 22.75 +pb_10c : 22.70 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.76 +pb_1c : 22.76 +pb_5c : 22.75 +pb_10c : 22.70 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.77 +pb_1c : 22.77 +pb_5c : 22.75 +pb_10c : 22.70 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.78 +pb_1c : 22.78 +pb_5c : 22.75 +pb_10c : 22.70 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.79 +pb_1c : 22.79 +pb_5c : 22.75 +pb_10c : 22.70 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.80 +pb_1c : 22.80 +pb_5c : 22.80 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.81 +pb_1c : 22.81 +pb_5c : 22.80 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.82 +pb_1c : 22.82 +pb_5c : 22.80 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.83 +pb_1c : 22.83 +pb_5c : 22.80 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.84 +pb_1c : 22.84 +pb_5c : 22.80 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.85 +pb_1c : 22.85 +pb_5c : 22.85 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.86 +pb_1c : 22.86 +pb_5c : 22.85 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.87 +pb_1c : 22.87 +pb_5c : 22.85 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.88 +pb_1c : 22.88 +pb_5c : 22.85 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.89 +pb_1c : 22.89 +pb_5c : 22.85 +pb_10c : 22.80 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.90 +pb_1c : 22.90 +pb_5c : 22.90 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.91 +pb_1c : 22.91 +pb_5c : 22.90 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.92 +pb_1c : 22.92 +pb_5c : 22.90 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.93 +pb_1c : 22.93 +pb_5c : 22.90 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.94 +pb_1c : 22.94 +pb_5c : 22.90 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.95 +pb_1c : 22.95 +pb_5c : 22.95 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.96 +pb_1c : 22.96 +pb_5c : 22.95 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.97 +pb_1c : 22.97 +pb_5c : 22.95 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.98 +pb_1c : 22.98 +pb_5c : 22.95 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +22.99 +pb_1c : 22.99 +pb_5c : 22.95 +pb_10c : 22.90 +pb_25c : 22.75 +pb_1d : 22.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.00 +pb_1c : 23.00 +pb_5c : 23.00 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.01 +pb_1c : 23.01 +pb_5c : 23.00 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.02 +pb_1c : 23.02 +pb_5c : 23.00 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.03 +pb_1c : 23.03 +pb_5c : 23.00 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.04 +pb_1c : 23.04 +pb_5c : 23.00 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.05 +pb_1c : 23.05 +pb_5c : 23.05 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.06 +pb_1c : 23.06 +pb_5c : 23.05 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.07 +pb_1c : 23.07 +pb_5c : 23.05 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.08 +pb_1c : 23.08 +pb_5c : 23.05 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.09 +pb_1c : 23.09 +pb_5c : 23.05 +pb_10c : 23.00 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.10 +pb_1c : 23.10 +pb_5c : 23.10 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.11 +pb_1c : 23.11 +pb_5c : 23.10 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.12 +pb_1c : 23.12 +pb_5c : 23.10 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.13 +pb_1c : 23.13 +pb_5c : 23.10 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.14 +pb_1c : 23.14 +pb_5c : 23.10 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.15 +pb_1c : 23.15 +pb_5c : 23.15 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.16 +pb_1c : 23.16 +pb_5c : 23.15 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.17 +pb_1c : 23.17 +pb_5c : 23.15 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.18 +pb_1c : 23.18 +pb_5c : 23.15 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.19 +pb_1c : 23.19 +pb_5c : 23.15 +pb_10c : 23.10 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.20 +pb_1c : 23.20 +pb_5c : 23.20 +pb_10c : 23.20 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.21 +pb_1c : 23.21 +pb_5c : 23.20 +pb_10c : 23.20 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.22 +pb_1c : 23.22 +pb_5c : 23.20 +pb_10c : 23.20 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.23 +pb_1c : 23.23 +pb_5c : 23.20 +pb_10c : 23.20 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.24 +pb_1c : 23.24 +pb_5c : 23.20 +pb_10c : 23.20 +pb_25c : 23.00 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.25 +pb_1c : 23.25 +pb_5c : 23.25 +pb_10c : 23.20 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.26 +pb_1c : 23.26 +pb_5c : 23.25 +pb_10c : 23.20 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.27 +pb_1c : 23.27 +pb_5c : 23.25 +pb_10c : 23.20 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.28 +pb_1c : 23.28 +pb_5c : 23.25 +pb_10c : 23.20 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.29 +pb_1c : 23.29 +pb_5c : 23.25 +pb_10c : 23.20 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.30 +pb_1c : 23.30 +pb_5c : 23.30 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.31 +pb_1c : 23.31 +pb_5c : 23.30 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.32 +pb_1c : 23.32 +pb_5c : 23.30 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.33 +pb_1c : 23.33 +pb_5c : 23.30 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.34 +pb_1c : 23.34 +pb_5c : 23.30 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.35 +pb_1c : 23.35 +pb_5c : 23.35 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.36 +pb_1c : 23.36 +pb_5c : 23.35 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.37 +pb_1c : 23.37 +pb_5c : 23.35 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.38 +pb_1c : 23.38 +pb_5c : 23.35 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.39 +pb_1c : 23.39 +pb_5c : 23.35 +pb_10c : 23.30 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.40 +pb_1c : 23.40 +pb_5c : 23.40 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.41 +pb_1c : 23.41 +pb_5c : 23.40 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.42 +pb_1c : 23.42 +pb_5c : 23.40 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.43 +pb_1c : 23.43 +pb_5c : 23.40 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.44 +pb_1c : 23.44 +pb_5c : 23.40 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.45 +pb_1c : 23.45 +pb_5c : 23.45 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.46 +pb_1c : 23.46 +pb_5c : 23.45 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.47 +pb_1c : 23.47 +pb_5c : 23.45 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.48 +pb_1c : 23.48 +pb_5c : 23.45 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.49 +pb_1c : 23.49 +pb_5c : 23.45 +pb_10c : 23.40 +pb_25c : 23.25 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.50 +pb_1c : 23.50 +pb_5c : 23.50 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.51 +pb_1c : 23.51 +pb_5c : 23.50 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.52 +pb_1c : 23.52 +pb_5c : 23.50 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.53 +pb_1c : 23.53 +pb_5c : 23.50 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.54 +pb_1c : 23.54 +pb_5c : 23.50 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.55 +pb_1c : 23.55 +pb_5c : 23.55 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.56 +pb_1c : 23.56 +pb_5c : 23.55 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.57 +pb_1c : 23.57 +pb_5c : 23.55 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.58 +pb_1c : 23.58 +pb_5c : 23.55 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.59 +pb_1c : 23.59 +pb_5c : 23.55 +pb_10c : 23.50 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.60 +pb_1c : 23.60 +pb_5c : 23.60 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.61 +pb_1c : 23.61 +pb_5c : 23.60 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.62 +pb_1c : 23.62 +pb_5c : 23.60 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.63 +pb_1c : 23.63 +pb_5c : 23.60 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.64 +pb_1c : 23.64 +pb_5c : 23.60 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.65 +pb_1c : 23.65 +pb_5c : 23.65 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.66 +pb_1c : 23.66 +pb_5c : 23.65 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.67 +pb_1c : 23.67 +pb_5c : 23.65 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.68 +pb_1c : 23.68 +pb_5c : 23.65 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.69 +pb_1c : 23.69 +pb_5c : 23.65 +pb_10c : 23.60 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.70 +pb_1c : 23.70 +pb_5c : 23.70 +pb_10c : 23.70 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.71 +pb_1c : 23.71 +pb_5c : 23.70 +pb_10c : 23.70 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.72 +pb_1c : 23.72 +pb_5c : 23.70 +pb_10c : 23.70 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.73 +pb_1c : 23.73 +pb_5c : 23.70 +pb_10c : 23.70 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.74 +pb_1c : 23.74 +pb_5c : 23.70 +pb_10c : 23.70 +pb_25c : 23.50 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.75 +pb_1c : 23.75 +pb_5c : 23.75 +pb_10c : 23.70 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.76 +pb_1c : 23.76 +pb_5c : 23.75 +pb_10c : 23.70 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.77 +pb_1c : 23.77 +pb_5c : 23.75 +pb_10c : 23.70 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.78 +pb_1c : 23.78 +pb_5c : 23.75 +pb_10c : 23.70 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.79 +pb_1c : 23.79 +pb_5c : 23.75 +pb_10c : 23.70 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.80 +pb_1c : 23.80 +pb_5c : 23.80 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.81 +pb_1c : 23.81 +pb_5c : 23.80 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.82 +pb_1c : 23.82 +pb_5c : 23.80 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.83 +pb_1c : 23.83 +pb_5c : 23.80 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.84 +pb_1c : 23.84 +pb_5c : 23.80 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.85 +pb_1c : 23.85 +pb_5c : 23.85 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.86 +pb_1c : 23.86 +pb_5c : 23.85 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.87 +pb_1c : 23.87 +pb_5c : 23.85 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.88 +pb_1c : 23.88 +pb_5c : 23.85 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.89 +pb_1c : 23.89 +pb_5c : 23.85 +pb_10c : 23.80 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.90 +pb_1c : 23.90 +pb_5c : 23.90 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.91 +pb_1c : 23.91 +pb_5c : 23.90 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.92 +pb_1c : 23.92 +pb_5c : 23.90 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.93 +pb_1c : 23.93 +pb_5c : 23.90 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.94 +pb_1c : 23.94 +pb_5c : 23.90 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.95 +pb_1c : 23.95 +pb_5c : 23.95 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.96 +pb_1c : 23.96 +pb_5c : 23.95 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.97 +pb_1c : 23.97 +pb_5c : 23.95 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.98 +pb_1c : 23.98 +pb_5c : 23.95 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +23.99 +pb_1c : 23.99 +pb_5c : 23.95 +pb_10c : 23.90 +pb_25c : 23.75 +pb_1d : 23.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.00 +pb_1c : 24.00 +pb_5c : 24.00 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.01 +pb_1c : 24.01 +pb_5c : 24.00 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.02 +pb_1c : 24.02 +pb_5c : 24.00 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.03 +pb_1c : 24.03 +pb_5c : 24.00 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.04 +pb_1c : 24.04 +pb_5c : 24.00 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.05 +pb_1c : 24.05 +pb_5c : 24.05 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.06 +pb_1c : 24.06 +pb_5c : 24.05 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.07 +pb_1c : 24.07 +pb_5c : 24.05 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.08 +pb_1c : 24.08 +pb_5c : 24.05 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.09 +pb_1c : 24.09 +pb_5c : 24.05 +pb_10c : 24.00 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.10 +pb_1c : 24.10 +pb_5c : 24.10 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.11 +pb_1c : 24.11 +pb_5c : 24.10 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.12 +pb_1c : 24.12 +pb_5c : 24.10 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.13 +pb_1c : 24.13 +pb_5c : 24.10 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.14 +pb_1c : 24.14 +pb_5c : 24.10 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.15 +pb_1c : 24.15 +pb_5c : 24.15 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.16 +pb_1c : 24.16 +pb_5c : 24.15 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.17 +pb_1c : 24.17 +pb_5c : 24.15 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.18 +pb_1c : 24.18 +pb_5c : 24.15 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.19 +pb_1c : 24.19 +pb_5c : 24.15 +pb_10c : 24.10 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.20 +pb_1c : 24.20 +pb_5c : 24.20 +pb_10c : 24.20 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.21 +pb_1c : 24.21 +pb_5c : 24.20 +pb_10c : 24.20 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.22 +pb_1c : 24.22 +pb_5c : 24.20 +pb_10c : 24.20 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.23 +pb_1c : 24.23 +pb_5c : 24.20 +pb_10c : 24.20 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.24 +pb_1c : 24.24 +pb_5c : 24.20 +pb_10c : 24.20 +pb_25c : 24.00 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.25 +pb_1c : 24.25 +pb_5c : 24.25 +pb_10c : 24.20 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.26 +pb_1c : 24.26 +pb_5c : 24.25 +pb_10c : 24.20 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.27 +pb_1c : 24.27 +pb_5c : 24.25 +pb_10c : 24.20 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.28 +pb_1c : 24.28 +pb_5c : 24.25 +pb_10c : 24.20 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.29 +pb_1c : 24.29 +pb_5c : 24.25 +pb_10c : 24.20 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.30 +pb_1c : 24.30 +pb_5c : 24.30 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.31 +pb_1c : 24.31 +pb_5c : 24.30 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.32 +pb_1c : 24.32 +pb_5c : 24.30 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.33 +pb_1c : 24.33 +pb_5c : 24.30 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.34 +pb_1c : 24.34 +pb_5c : 24.30 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.35 +pb_1c : 24.35 +pb_5c : 24.35 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.36 +pb_1c : 24.36 +pb_5c : 24.35 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.37 +pb_1c : 24.37 +pb_5c : 24.35 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.38 +pb_1c : 24.38 +pb_5c : 24.35 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.39 +pb_1c : 24.39 +pb_5c : 24.35 +pb_10c : 24.30 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.40 +pb_1c : 24.40 +pb_5c : 24.40 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.41 +pb_1c : 24.41 +pb_5c : 24.40 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.42 +pb_1c : 24.42 +pb_5c : 24.40 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.43 +pb_1c : 24.43 +pb_5c : 24.40 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.44 +pb_1c : 24.44 +pb_5c : 24.40 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.45 +pb_1c : 24.45 +pb_5c : 24.45 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.46 +pb_1c : 24.46 +pb_5c : 24.45 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.47 +pb_1c : 24.47 +pb_5c : 24.45 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.48 +pb_1c : 24.48 +pb_5c : 24.45 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.49 +pb_1c : 24.49 +pb_5c : 24.45 +pb_10c : 24.40 +pb_25c : 24.25 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.50 +pb_1c : 24.50 +pb_5c : 24.50 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.51 +pb_1c : 24.51 +pb_5c : 24.50 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.52 +pb_1c : 24.52 +pb_5c : 24.50 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.53 +pb_1c : 24.53 +pb_5c : 24.50 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.54 +pb_1c : 24.54 +pb_5c : 24.50 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.55 +pb_1c : 24.55 +pb_5c : 24.55 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.56 +pb_1c : 24.56 +pb_5c : 24.55 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.57 +pb_1c : 24.57 +pb_5c : 24.55 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.58 +pb_1c : 24.58 +pb_5c : 24.55 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.59 +pb_1c : 24.59 +pb_5c : 24.55 +pb_10c : 24.50 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.60 +pb_1c : 24.60 +pb_5c : 24.60 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.61 +pb_1c : 24.61 +pb_5c : 24.60 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.62 +pb_1c : 24.62 +pb_5c : 24.60 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.63 +pb_1c : 24.63 +pb_5c : 24.60 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.64 +pb_1c : 24.64 +pb_5c : 24.60 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.65 +pb_1c : 24.65 +pb_5c : 24.65 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.66 +pb_1c : 24.66 +pb_5c : 24.65 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.67 +pb_1c : 24.67 +pb_5c : 24.65 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.68 +pb_1c : 24.68 +pb_5c : 24.65 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.69 +pb_1c : 24.69 +pb_5c : 24.65 +pb_10c : 24.60 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.70 +pb_1c : 24.70 +pb_5c : 24.70 +pb_10c : 24.70 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.71 +pb_1c : 24.71 +pb_5c : 24.70 +pb_10c : 24.70 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.72 +pb_1c : 24.72 +pb_5c : 24.70 +pb_10c : 24.70 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.73 +pb_1c : 24.73 +pb_5c : 24.70 +pb_10c : 24.70 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.74 +pb_1c : 24.74 +pb_5c : 24.70 +pb_10c : 24.70 +pb_25c : 24.50 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.75 +pb_1c : 24.75 +pb_5c : 24.75 +pb_10c : 24.70 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.76 +pb_1c : 24.76 +pb_5c : 24.75 +pb_10c : 24.70 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.77 +pb_1c : 24.77 +pb_5c : 24.75 +pb_10c : 24.70 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.78 +pb_1c : 24.78 +pb_5c : 24.75 +pb_10c : 24.70 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.79 +pb_1c : 24.79 +pb_5c : 24.75 +pb_10c : 24.70 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.80 +pb_1c : 24.80 +pb_5c : 24.80 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.81 +pb_1c : 24.81 +pb_5c : 24.80 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.82 +pb_1c : 24.82 +pb_5c : 24.80 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.83 +pb_1c : 24.83 +pb_5c : 24.80 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.84 +pb_1c : 24.84 +pb_5c : 24.80 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.85 +pb_1c : 24.85 +pb_5c : 24.85 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.86 +pb_1c : 24.86 +pb_5c : 24.85 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.87 +pb_1c : 24.87 +pb_5c : 24.85 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.88 +pb_1c : 24.88 +pb_5c : 24.85 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.89 +pb_1c : 24.89 +pb_5c : 24.85 +pb_10c : 24.80 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.90 +pb_1c : 24.90 +pb_5c : 24.90 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.91 +pb_1c : 24.91 +pb_5c : 24.90 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.92 +pb_1c : 24.92 +pb_5c : 24.90 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.93 +pb_1c : 24.93 +pb_5c : 24.90 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.94 +pb_1c : 24.94 +pb_5c : 24.90 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.95 +pb_1c : 24.95 +pb_5c : 24.95 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.96 +pb_1c : 24.96 +pb_5c : 24.95 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.97 +pb_1c : 24.97 +pb_5c : 24.95 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.98 +pb_1c : 24.98 +pb_5c : 24.95 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +24.99 +pb_1c : 24.99 +pb_5c : 24.95 +pb_10c : 24.90 +pb_25c : 24.75 +pb_1d : 24.00 +pb_5d : 20.00 +pb_10d : 20.00 + +25.00 +pb_1c : 25.00 +pb_5c : 25.00 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.01 +pb_1c : 25.01 +pb_5c : 25.00 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.02 +pb_1c : 25.02 +pb_5c : 25.00 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.03 +pb_1c : 25.03 +pb_5c : 25.00 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.04 +pb_1c : 25.04 +pb_5c : 25.00 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.05 +pb_1c : 25.05 +pb_5c : 25.05 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.06 +pb_1c : 25.06 +pb_5c : 25.05 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.07 +pb_1c : 25.07 +pb_5c : 25.05 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.08 +pb_1c : 25.08 +pb_5c : 25.05 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.09 +pb_1c : 25.09 +pb_5c : 25.05 +pb_10c : 25.00 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.10 +pb_1c : 25.10 +pb_5c : 25.10 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.11 +pb_1c : 25.11 +pb_5c : 25.10 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.12 +pb_1c : 25.12 +pb_5c : 25.10 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.13 +pb_1c : 25.13 +pb_5c : 25.10 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.14 +pb_1c : 25.14 +pb_5c : 25.10 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.15 +pb_1c : 25.15 +pb_5c : 25.15 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.16 +pb_1c : 25.16 +pb_5c : 25.15 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.17 +pb_1c : 25.17 +pb_5c : 25.15 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.18 +pb_1c : 25.18 +pb_5c : 25.15 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.19 +pb_1c : 25.19 +pb_5c : 25.15 +pb_10c : 25.10 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.20 +pb_1c : 25.20 +pb_5c : 25.20 +pb_10c : 25.20 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.21 +pb_1c : 25.21 +pb_5c : 25.20 +pb_10c : 25.20 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.22 +pb_1c : 25.22 +pb_5c : 25.20 +pb_10c : 25.20 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.23 +pb_1c : 25.23 +pb_5c : 25.20 +pb_10c : 25.20 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.24 +pb_1c : 25.24 +pb_5c : 25.20 +pb_10c : 25.20 +pb_25c : 25.00 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.25 +pb_1c : 25.25 +pb_5c : 25.25 +pb_10c : 25.20 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.26 +pb_1c : 25.26 +pb_5c : 25.25 +pb_10c : 25.20 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.27 +pb_1c : 25.27 +pb_5c : 25.25 +pb_10c : 25.20 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.28 +pb_1c : 25.28 +pb_5c : 25.25 +pb_10c : 25.20 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.29 +pb_1c : 25.29 +pb_5c : 25.25 +pb_10c : 25.20 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.30 +pb_1c : 25.30 +pb_5c : 25.30 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.31 +pb_1c : 25.31 +pb_5c : 25.30 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.32 +pb_1c : 25.32 +pb_5c : 25.30 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.33 +pb_1c : 25.33 +pb_5c : 25.30 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.34 +pb_1c : 25.34 +pb_5c : 25.30 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.35 +pb_1c : 25.35 +pb_5c : 25.35 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.36 +pb_1c : 25.36 +pb_5c : 25.35 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.37 +pb_1c : 25.37 +pb_5c : 25.35 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.38 +pb_1c : 25.38 +pb_5c : 25.35 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.39 +pb_1c : 25.39 +pb_5c : 25.35 +pb_10c : 25.30 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.40 +pb_1c : 25.40 +pb_5c : 25.40 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.41 +pb_1c : 25.41 +pb_5c : 25.40 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.42 +pb_1c : 25.42 +pb_5c : 25.40 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.43 +pb_1c : 25.43 +pb_5c : 25.40 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.44 +pb_1c : 25.44 +pb_5c : 25.40 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.45 +pb_1c : 25.45 +pb_5c : 25.45 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.46 +pb_1c : 25.46 +pb_5c : 25.45 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.47 +pb_1c : 25.47 +pb_5c : 25.45 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.48 +pb_1c : 25.48 +pb_5c : 25.45 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.49 +pb_1c : 25.49 +pb_5c : 25.45 +pb_10c : 25.40 +pb_25c : 25.25 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.50 +pb_1c : 25.50 +pb_5c : 25.50 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.51 +pb_1c : 25.51 +pb_5c : 25.50 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.52 +pb_1c : 25.52 +pb_5c : 25.50 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.53 +pb_1c : 25.53 +pb_5c : 25.50 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.54 +pb_1c : 25.54 +pb_5c : 25.50 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.55 +pb_1c : 25.55 +pb_5c : 25.55 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.56 +pb_1c : 25.56 +pb_5c : 25.55 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.57 +pb_1c : 25.57 +pb_5c : 25.55 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.58 +pb_1c : 25.58 +pb_5c : 25.55 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.59 +pb_1c : 25.59 +pb_5c : 25.55 +pb_10c : 25.50 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.60 +pb_1c : 25.60 +pb_5c : 25.60 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.61 +pb_1c : 25.61 +pb_5c : 25.60 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.62 +pb_1c : 25.62 +pb_5c : 25.60 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.63 +pb_1c : 25.63 +pb_5c : 25.60 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.64 +pb_1c : 25.64 +pb_5c : 25.60 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.65 +pb_1c : 25.65 +pb_5c : 25.65 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.66 +pb_1c : 25.66 +pb_5c : 25.65 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.67 +pb_1c : 25.67 +pb_5c : 25.65 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.68 +pb_1c : 25.68 +pb_5c : 25.65 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.69 +pb_1c : 25.69 +pb_5c : 25.65 +pb_10c : 25.60 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.70 +pb_1c : 25.70 +pb_5c : 25.70 +pb_10c : 25.70 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.71 +pb_1c : 25.71 +pb_5c : 25.70 +pb_10c : 25.70 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.72 +pb_1c : 25.72 +pb_5c : 25.70 +pb_10c : 25.70 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.73 +pb_1c : 25.73 +pb_5c : 25.70 +pb_10c : 25.70 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.74 +pb_1c : 25.74 +pb_5c : 25.70 +pb_10c : 25.70 +pb_25c : 25.50 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.75 +pb_1c : 25.75 +pb_5c : 25.75 +pb_10c : 25.70 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.76 +pb_1c : 25.76 +pb_5c : 25.75 +pb_10c : 25.70 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.77 +pb_1c : 25.77 +pb_5c : 25.75 +pb_10c : 25.70 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.78 +pb_1c : 25.78 +pb_5c : 25.75 +pb_10c : 25.70 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.79 +pb_1c : 25.79 +pb_5c : 25.75 +pb_10c : 25.70 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.80 +pb_1c : 25.80 +pb_5c : 25.80 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.81 +pb_1c : 25.81 +pb_5c : 25.80 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.82 +pb_1c : 25.82 +pb_5c : 25.80 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.83 +pb_1c : 25.83 +pb_5c : 25.80 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.84 +pb_1c : 25.84 +pb_5c : 25.80 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.85 +pb_1c : 25.85 +pb_5c : 25.85 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.86 +pb_1c : 25.86 +pb_5c : 25.85 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.87 +pb_1c : 25.87 +pb_5c : 25.85 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.88 +pb_1c : 25.88 +pb_5c : 25.85 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.89 +pb_1c : 25.89 +pb_5c : 25.85 +pb_10c : 25.80 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.90 +pb_1c : 25.90 +pb_5c : 25.90 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.91 +pb_1c : 25.91 +pb_5c : 25.90 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.92 +pb_1c : 25.92 +pb_5c : 25.90 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.93 +pb_1c : 25.93 +pb_5c : 25.90 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.94 +pb_1c : 25.94 +pb_5c : 25.90 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.95 +pb_1c : 25.95 +pb_5c : 25.95 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.96 +pb_1c : 25.96 +pb_5c : 25.95 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.97 +pb_1c : 25.97 +pb_5c : 25.95 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.98 +pb_1c : 25.98 +pb_5c : 25.95 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +25.99 +pb_1c : 25.99 +pb_5c : 25.95 +pb_10c : 25.90 +pb_25c : 25.75 +pb_1d : 25.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.00 +pb_1c : 26.00 +pb_5c : 26.00 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.01 +pb_1c : 26.01 +pb_5c : 26.00 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.02 +pb_1c : 26.02 +pb_5c : 26.00 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.03 +pb_1c : 26.03 +pb_5c : 26.00 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.04 +pb_1c : 26.04 +pb_5c : 26.00 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.05 +pb_1c : 26.05 +pb_5c : 26.05 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.06 +pb_1c : 26.06 +pb_5c : 26.05 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.07 +pb_1c : 26.07 +pb_5c : 26.05 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.08 +pb_1c : 26.08 +pb_5c : 26.05 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.09 +pb_1c : 26.09 +pb_5c : 26.05 +pb_10c : 26.00 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.10 +pb_1c : 26.10 +pb_5c : 26.10 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.11 +pb_1c : 26.11 +pb_5c : 26.10 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.12 +pb_1c : 26.12 +pb_5c : 26.10 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.13 +pb_1c : 26.13 +pb_5c : 26.10 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.14 +pb_1c : 26.14 +pb_5c : 26.10 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.15 +pb_1c : 26.15 +pb_5c : 26.15 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.16 +pb_1c : 26.16 +pb_5c : 26.15 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.17 +pb_1c : 26.17 +pb_5c : 26.15 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.18 +pb_1c : 26.18 +pb_5c : 26.15 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.19 +pb_1c : 26.19 +pb_5c : 26.15 +pb_10c : 26.10 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.20 +pb_1c : 26.20 +pb_5c : 26.20 +pb_10c : 26.20 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.21 +pb_1c : 26.21 +pb_5c : 26.20 +pb_10c : 26.20 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.22 +pb_1c : 26.22 +pb_5c : 26.20 +pb_10c : 26.20 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.23 +pb_1c : 26.23 +pb_5c : 26.20 +pb_10c : 26.20 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.24 +pb_1c : 26.24 +pb_5c : 26.20 +pb_10c : 26.20 +pb_25c : 26.00 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.25 +pb_1c : 26.25 +pb_5c : 26.25 +pb_10c : 26.20 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.26 +pb_1c : 26.26 +pb_5c : 26.25 +pb_10c : 26.20 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.27 +pb_1c : 26.27 +pb_5c : 26.25 +pb_10c : 26.20 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.28 +pb_1c : 26.28 +pb_5c : 26.25 +pb_10c : 26.20 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.29 +pb_1c : 26.29 +pb_5c : 26.25 +pb_10c : 26.20 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.30 +pb_1c : 26.30 +pb_5c : 26.30 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.31 +pb_1c : 26.31 +pb_5c : 26.30 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.32 +pb_1c : 26.32 +pb_5c : 26.30 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.33 +pb_1c : 26.33 +pb_5c : 26.30 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.34 +pb_1c : 26.34 +pb_5c : 26.30 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.35 +pb_1c : 26.35 +pb_5c : 26.35 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.36 +pb_1c : 26.36 +pb_5c : 26.35 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.37 +pb_1c : 26.37 +pb_5c : 26.35 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.38 +pb_1c : 26.38 +pb_5c : 26.35 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.39 +pb_1c : 26.39 +pb_5c : 26.35 +pb_10c : 26.30 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.40 +pb_1c : 26.40 +pb_5c : 26.40 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.41 +pb_1c : 26.41 +pb_5c : 26.40 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.42 +pb_1c : 26.42 +pb_5c : 26.40 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.43 +pb_1c : 26.43 +pb_5c : 26.40 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.44 +pb_1c : 26.44 +pb_5c : 26.40 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.45 +pb_1c : 26.45 +pb_5c : 26.45 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.46 +pb_1c : 26.46 +pb_5c : 26.45 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.47 +pb_1c : 26.47 +pb_5c : 26.45 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.48 +pb_1c : 26.48 +pb_5c : 26.45 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.49 +pb_1c : 26.49 +pb_5c : 26.45 +pb_10c : 26.40 +pb_25c : 26.25 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.50 +pb_1c : 26.50 +pb_5c : 26.50 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.51 +pb_1c : 26.51 +pb_5c : 26.50 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.52 +pb_1c : 26.52 +pb_5c : 26.50 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.53 +pb_1c : 26.53 +pb_5c : 26.50 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.54 +pb_1c : 26.54 +pb_5c : 26.50 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.55 +pb_1c : 26.55 +pb_5c : 26.55 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.56 +pb_1c : 26.56 +pb_5c : 26.55 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.57 +pb_1c : 26.57 +pb_5c : 26.55 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.58 +pb_1c : 26.58 +pb_5c : 26.55 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.59 +pb_1c : 26.59 +pb_5c : 26.55 +pb_10c : 26.50 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.60 +pb_1c : 26.60 +pb_5c : 26.60 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.61 +pb_1c : 26.61 +pb_5c : 26.60 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.62 +pb_1c : 26.62 +pb_5c : 26.60 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.63 +pb_1c : 26.63 +pb_5c : 26.60 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.64 +pb_1c : 26.64 +pb_5c : 26.60 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.65 +pb_1c : 26.65 +pb_5c : 26.65 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.66 +pb_1c : 26.66 +pb_5c : 26.65 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.67 +pb_1c : 26.67 +pb_5c : 26.65 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.68 +pb_1c : 26.68 +pb_5c : 26.65 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.69 +pb_1c : 26.69 +pb_5c : 26.65 +pb_10c : 26.60 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.70 +pb_1c : 26.70 +pb_5c : 26.70 +pb_10c : 26.70 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.71 +pb_1c : 26.71 +pb_5c : 26.70 +pb_10c : 26.70 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.72 +pb_1c : 26.72 +pb_5c : 26.70 +pb_10c : 26.70 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.73 +pb_1c : 26.73 +pb_5c : 26.70 +pb_10c : 26.70 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.74 +pb_1c : 26.74 +pb_5c : 26.70 +pb_10c : 26.70 +pb_25c : 26.50 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.75 +pb_1c : 26.75 +pb_5c : 26.75 +pb_10c : 26.70 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.76 +pb_1c : 26.76 +pb_5c : 26.75 +pb_10c : 26.70 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.77 +pb_1c : 26.77 +pb_5c : 26.75 +pb_10c : 26.70 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.78 +pb_1c : 26.78 +pb_5c : 26.75 +pb_10c : 26.70 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.79 +pb_1c : 26.79 +pb_5c : 26.75 +pb_10c : 26.70 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.80 +pb_1c : 26.80 +pb_5c : 26.80 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.81 +pb_1c : 26.81 +pb_5c : 26.80 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.82 +pb_1c : 26.82 +pb_5c : 26.80 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.83 +pb_1c : 26.83 +pb_5c : 26.80 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.84 +pb_1c : 26.84 +pb_5c : 26.80 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.85 +pb_1c : 26.85 +pb_5c : 26.85 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.86 +pb_1c : 26.86 +pb_5c : 26.85 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.87 +pb_1c : 26.87 +pb_5c : 26.85 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.88 +pb_1c : 26.88 +pb_5c : 26.85 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.89 +pb_1c : 26.89 +pb_5c : 26.85 +pb_10c : 26.80 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.90 +pb_1c : 26.90 +pb_5c : 26.90 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.91 +pb_1c : 26.91 +pb_5c : 26.90 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.92 +pb_1c : 26.92 +pb_5c : 26.90 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.93 +pb_1c : 26.93 +pb_5c : 26.90 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.94 +pb_1c : 26.94 +pb_5c : 26.90 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.95 +pb_1c : 26.95 +pb_5c : 26.95 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.96 +pb_1c : 26.96 +pb_5c : 26.95 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.97 +pb_1c : 26.97 +pb_5c : 26.95 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.98 +pb_1c : 26.98 +pb_5c : 26.95 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +26.99 +pb_1c : 26.99 +pb_5c : 26.95 +pb_10c : 26.90 +pb_25c : 26.75 +pb_1d : 26.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.00 +pb_1c : 27.00 +pb_5c : 27.00 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.01 +pb_1c : 27.01 +pb_5c : 27.00 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.02 +pb_1c : 27.02 +pb_5c : 27.00 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.03 +pb_1c : 27.03 +pb_5c : 27.00 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.04 +pb_1c : 27.04 +pb_5c : 27.00 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.05 +pb_1c : 27.05 +pb_5c : 27.05 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.06 +pb_1c : 27.06 +pb_5c : 27.05 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.07 +pb_1c : 27.07 +pb_5c : 27.05 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.08 +pb_1c : 27.08 +pb_5c : 27.05 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.09 +pb_1c : 27.09 +pb_5c : 27.05 +pb_10c : 27.00 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.10 +pb_1c : 27.10 +pb_5c : 27.10 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.11 +pb_1c : 27.11 +pb_5c : 27.10 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.12 +pb_1c : 27.12 +pb_5c : 27.10 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.13 +pb_1c : 27.13 +pb_5c : 27.10 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.14 +pb_1c : 27.14 +pb_5c : 27.10 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.15 +pb_1c : 27.15 +pb_5c : 27.15 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.16 +pb_1c : 27.16 +pb_5c : 27.15 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.17 +pb_1c : 27.17 +pb_5c : 27.15 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.18 +pb_1c : 27.18 +pb_5c : 27.15 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.19 +pb_1c : 27.19 +pb_5c : 27.15 +pb_10c : 27.10 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.20 +pb_1c : 27.20 +pb_5c : 27.20 +pb_10c : 27.20 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.21 +pb_1c : 27.21 +pb_5c : 27.20 +pb_10c : 27.20 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.22 +pb_1c : 27.22 +pb_5c : 27.20 +pb_10c : 27.20 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.23 +pb_1c : 27.23 +pb_5c : 27.20 +pb_10c : 27.20 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.24 +pb_1c : 27.24 +pb_5c : 27.20 +pb_10c : 27.20 +pb_25c : 27.00 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.25 +pb_1c : 27.25 +pb_5c : 27.25 +pb_10c : 27.20 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.26 +pb_1c : 27.26 +pb_5c : 27.25 +pb_10c : 27.20 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.27 +pb_1c : 27.27 +pb_5c : 27.25 +pb_10c : 27.20 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.28 +pb_1c : 27.28 +pb_5c : 27.25 +pb_10c : 27.20 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.29 +pb_1c : 27.29 +pb_5c : 27.25 +pb_10c : 27.20 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.30 +pb_1c : 27.30 +pb_5c : 27.30 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.31 +pb_1c : 27.31 +pb_5c : 27.30 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.32 +pb_1c : 27.32 +pb_5c : 27.30 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.33 +pb_1c : 27.33 +pb_5c : 27.30 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.34 +pb_1c : 27.34 +pb_5c : 27.30 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.35 +pb_1c : 27.35 +pb_5c : 27.35 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.36 +pb_1c : 27.36 +pb_5c : 27.35 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.37 +pb_1c : 27.37 +pb_5c : 27.35 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.38 +pb_1c : 27.38 +pb_5c : 27.35 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.39 +pb_1c : 27.39 +pb_5c : 27.35 +pb_10c : 27.30 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.40 +pb_1c : 27.40 +pb_5c : 27.40 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.41 +pb_1c : 27.41 +pb_5c : 27.40 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.42 +pb_1c : 27.42 +pb_5c : 27.40 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.43 +pb_1c : 27.43 +pb_5c : 27.40 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.44 +pb_1c : 27.44 +pb_5c : 27.40 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.45 +pb_1c : 27.45 +pb_5c : 27.45 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.46 +pb_1c : 27.46 +pb_5c : 27.45 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.47 +pb_1c : 27.47 +pb_5c : 27.45 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.48 +pb_1c : 27.48 +pb_5c : 27.45 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.49 +pb_1c : 27.49 +pb_5c : 27.45 +pb_10c : 27.40 +pb_25c : 27.25 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.50 +pb_1c : 27.50 +pb_5c : 27.50 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.51 +pb_1c : 27.51 +pb_5c : 27.50 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.52 +pb_1c : 27.52 +pb_5c : 27.50 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.53 +pb_1c : 27.53 +pb_5c : 27.50 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.54 +pb_1c : 27.54 +pb_5c : 27.50 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.55 +pb_1c : 27.55 +pb_5c : 27.55 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.56 +pb_1c : 27.56 +pb_5c : 27.55 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.57 +pb_1c : 27.57 +pb_5c : 27.55 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.58 +pb_1c : 27.58 +pb_5c : 27.55 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.59 +pb_1c : 27.59 +pb_5c : 27.55 +pb_10c : 27.50 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.60 +pb_1c : 27.60 +pb_5c : 27.60 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.61 +pb_1c : 27.61 +pb_5c : 27.60 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.62 +pb_1c : 27.62 +pb_5c : 27.60 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.63 +pb_1c : 27.63 +pb_5c : 27.60 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.64 +pb_1c : 27.64 +pb_5c : 27.60 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.65 +pb_1c : 27.65 +pb_5c : 27.65 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.66 +pb_1c : 27.66 +pb_5c : 27.65 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.67 +pb_1c : 27.67 +pb_5c : 27.65 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.68 +pb_1c : 27.68 +pb_5c : 27.65 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.69 +pb_1c : 27.69 +pb_5c : 27.65 +pb_10c : 27.60 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.70 +pb_1c : 27.70 +pb_5c : 27.70 +pb_10c : 27.70 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.71 +pb_1c : 27.71 +pb_5c : 27.70 +pb_10c : 27.70 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.72 +pb_1c : 27.72 +pb_5c : 27.70 +pb_10c : 27.70 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.73 +pb_1c : 27.73 +pb_5c : 27.70 +pb_10c : 27.70 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.74 +pb_1c : 27.74 +pb_5c : 27.70 +pb_10c : 27.70 +pb_25c : 27.50 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.75 +pb_1c : 27.75 +pb_5c : 27.75 +pb_10c : 27.70 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.76 +pb_1c : 27.76 +pb_5c : 27.75 +pb_10c : 27.70 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.77 +pb_1c : 27.77 +pb_5c : 27.75 +pb_10c : 27.70 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.78 +pb_1c : 27.78 +pb_5c : 27.75 +pb_10c : 27.70 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.79 +pb_1c : 27.79 +pb_5c : 27.75 +pb_10c : 27.70 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.80 +pb_1c : 27.80 +pb_5c : 27.80 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.81 +pb_1c : 27.81 +pb_5c : 27.80 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.82 +pb_1c : 27.82 +pb_5c : 27.80 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.83 +pb_1c : 27.83 +pb_5c : 27.80 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.84 +pb_1c : 27.84 +pb_5c : 27.80 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.85 +pb_1c : 27.85 +pb_5c : 27.85 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.86 +pb_1c : 27.86 +pb_5c : 27.85 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.87 +pb_1c : 27.87 +pb_5c : 27.85 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.88 +pb_1c : 27.88 +pb_5c : 27.85 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.89 +pb_1c : 27.89 +pb_5c : 27.85 +pb_10c : 27.80 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.90 +pb_1c : 27.90 +pb_5c : 27.90 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.91 +pb_1c : 27.91 +pb_5c : 27.90 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.92 +pb_1c : 27.92 +pb_5c : 27.90 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.93 +pb_1c : 27.93 +pb_5c : 27.90 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.94 +pb_1c : 27.94 +pb_5c : 27.90 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.95 +pb_1c : 27.95 +pb_5c : 27.95 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.96 +pb_1c : 27.96 +pb_5c : 27.95 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.97 +pb_1c : 27.97 +pb_5c : 27.95 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.98 +pb_1c : 27.98 +pb_5c : 27.95 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +27.99 +pb_1c : 27.99 +pb_5c : 27.95 +pb_10c : 27.90 +pb_25c : 27.75 +pb_1d : 27.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.00 +pb_1c : 28.00 +pb_5c : 28.00 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.01 +pb_1c : 28.01 +pb_5c : 28.00 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.02 +pb_1c : 28.02 +pb_5c : 28.00 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.03 +pb_1c : 28.03 +pb_5c : 28.00 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.04 +pb_1c : 28.04 +pb_5c : 28.00 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.05 +pb_1c : 28.05 +pb_5c : 28.05 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.06 +pb_1c : 28.06 +pb_5c : 28.05 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.07 +pb_1c : 28.07 +pb_5c : 28.05 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.08 +pb_1c : 28.08 +pb_5c : 28.05 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.09 +pb_1c : 28.09 +pb_5c : 28.05 +pb_10c : 28.00 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.10 +pb_1c : 28.10 +pb_5c : 28.10 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.11 +pb_1c : 28.11 +pb_5c : 28.10 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.12 +pb_1c : 28.12 +pb_5c : 28.10 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.13 +pb_1c : 28.13 +pb_5c : 28.10 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.14 +pb_1c : 28.14 +pb_5c : 28.10 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.15 +pb_1c : 28.15 +pb_5c : 28.15 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.16 +pb_1c : 28.16 +pb_5c : 28.15 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.17 +pb_1c : 28.17 +pb_5c : 28.15 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.18 +pb_1c : 28.18 +pb_5c : 28.15 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.19 +pb_1c : 28.19 +pb_5c : 28.15 +pb_10c : 28.10 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.20 +pb_1c : 28.20 +pb_5c : 28.20 +pb_10c : 28.20 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.21 +pb_1c : 28.21 +pb_5c : 28.20 +pb_10c : 28.20 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.22 +pb_1c : 28.22 +pb_5c : 28.20 +pb_10c : 28.20 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.23 +pb_1c : 28.23 +pb_5c : 28.20 +pb_10c : 28.20 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.24 +pb_1c : 28.24 +pb_5c : 28.20 +pb_10c : 28.20 +pb_25c : 28.00 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.25 +pb_1c : 28.25 +pb_5c : 28.25 +pb_10c : 28.20 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.26 +pb_1c : 28.26 +pb_5c : 28.25 +pb_10c : 28.20 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.27 +pb_1c : 28.27 +pb_5c : 28.25 +pb_10c : 28.20 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.28 +pb_1c : 28.28 +pb_5c : 28.25 +pb_10c : 28.20 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.29 +pb_1c : 28.29 +pb_5c : 28.25 +pb_10c : 28.20 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.30 +pb_1c : 28.30 +pb_5c : 28.30 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.31 +pb_1c : 28.31 +pb_5c : 28.30 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.32 +pb_1c : 28.32 +pb_5c : 28.30 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.33 +pb_1c : 28.33 +pb_5c : 28.30 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.34 +pb_1c : 28.34 +pb_5c : 28.30 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.35 +pb_1c : 28.35 +pb_5c : 28.35 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.36 +pb_1c : 28.36 +pb_5c : 28.35 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.37 +pb_1c : 28.37 +pb_5c : 28.35 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.38 +pb_1c : 28.38 +pb_5c : 28.35 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.39 +pb_1c : 28.39 +pb_5c : 28.35 +pb_10c : 28.30 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.40 +pb_1c : 28.40 +pb_5c : 28.40 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.41 +pb_1c : 28.41 +pb_5c : 28.40 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.42 +pb_1c : 28.42 +pb_5c : 28.40 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.43 +pb_1c : 28.43 +pb_5c : 28.40 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.44 +pb_1c : 28.44 +pb_5c : 28.40 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.45 +pb_1c : 28.45 +pb_5c : 28.45 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.46 +pb_1c : 28.46 +pb_5c : 28.45 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.47 +pb_1c : 28.47 +pb_5c : 28.45 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.48 +pb_1c : 28.48 +pb_5c : 28.45 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.49 +pb_1c : 28.49 +pb_5c : 28.45 +pb_10c : 28.40 +pb_25c : 28.25 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.50 +pb_1c : 28.50 +pb_5c : 28.50 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.51 +pb_1c : 28.51 +pb_5c : 28.50 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.52 +pb_1c : 28.52 +pb_5c : 28.50 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.53 +pb_1c : 28.53 +pb_5c : 28.50 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.54 +pb_1c : 28.54 +pb_5c : 28.50 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.55 +pb_1c : 28.55 +pb_5c : 28.55 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.56 +pb_1c : 28.56 +pb_5c : 28.55 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.57 +pb_1c : 28.57 +pb_5c : 28.55 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.58 +pb_1c : 28.58 +pb_5c : 28.55 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.59 +pb_1c : 28.59 +pb_5c : 28.55 +pb_10c : 28.50 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.60 +pb_1c : 28.60 +pb_5c : 28.60 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.61 +pb_1c : 28.61 +pb_5c : 28.60 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.62 +pb_1c : 28.62 +pb_5c : 28.60 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.63 +pb_1c : 28.63 +pb_5c : 28.60 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.64 +pb_1c : 28.64 +pb_5c : 28.60 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.65 +pb_1c : 28.65 +pb_5c : 28.65 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.66 +pb_1c : 28.66 +pb_5c : 28.65 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.67 +pb_1c : 28.67 +pb_5c : 28.65 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.68 +pb_1c : 28.68 +pb_5c : 28.65 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.69 +pb_1c : 28.69 +pb_5c : 28.65 +pb_10c : 28.60 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.70 +pb_1c : 28.70 +pb_5c : 28.70 +pb_10c : 28.70 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.71 +pb_1c : 28.71 +pb_5c : 28.70 +pb_10c : 28.70 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.72 +pb_1c : 28.72 +pb_5c : 28.70 +pb_10c : 28.70 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.73 +pb_1c : 28.73 +pb_5c : 28.70 +pb_10c : 28.70 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.74 +pb_1c : 28.74 +pb_5c : 28.70 +pb_10c : 28.70 +pb_25c : 28.50 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.75 +pb_1c : 28.75 +pb_5c : 28.75 +pb_10c : 28.70 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.76 +pb_1c : 28.76 +pb_5c : 28.75 +pb_10c : 28.70 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.77 +pb_1c : 28.77 +pb_5c : 28.75 +pb_10c : 28.70 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.78 +pb_1c : 28.78 +pb_5c : 28.75 +pb_10c : 28.70 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.79 +pb_1c : 28.79 +pb_5c : 28.75 +pb_10c : 28.70 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.80 +pb_1c : 28.80 +pb_5c : 28.80 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.81 +pb_1c : 28.81 +pb_5c : 28.80 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.82 +pb_1c : 28.82 +pb_5c : 28.80 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.83 +pb_1c : 28.83 +pb_5c : 28.80 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.84 +pb_1c : 28.84 +pb_5c : 28.80 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.85 +pb_1c : 28.85 +pb_5c : 28.85 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.86 +pb_1c : 28.86 +pb_5c : 28.85 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.87 +pb_1c : 28.87 +pb_5c : 28.85 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.88 +pb_1c : 28.88 +pb_5c : 28.85 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.89 +pb_1c : 28.89 +pb_5c : 28.85 +pb_10c : 28.80 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.90 +pb_1c : 28.90 +pb_5c : 28.90 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.91 +pb_1c : 28.91 +pb_5c : 28.90 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.92 +pb_1c : 28.92 +pb_5c : 28.90 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.93 +pb_1c : 28.93 +pb_5c : 28.90 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.94 +pb_1c : 28.94 +pb_5c : 28.90 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.95 +pb_1c : 28.95 +pb_5c : 28.95 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.96 +pb_1c : 28.96 +pb_5c : 28.95 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.97 +pb_1c : 28.97 +pb_5c : 28.95 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.98 +pb_1c : 28.98 +pb_5c : 28.95 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +28.99 +pb_1c : 28.99 +pb_5c : 28.95 +pb_10c : 28.90 +pb_25c : 28.75 +pb_1d : 28.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.00 +pb_1c : 29.00 +pb_5c : 29.00 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.01 +pb_1c : 29.01 +pb_5c : 29.00 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.02 +pb_1c : 29.02 +pb_5c : 29.00 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.03 +pb_1c : 29.03 +pb_5c : 29.00 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.04 +pb_1c : 29.04 +pb_5c : 29.00 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.05 +pb_1c : 29.05 +pb_5c : 29.05 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.06 +pb_1c : 29.06 +pb_5c : 29.05 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.07 +pb_1c : 29.07 +pb_5c : 29.05 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.08 +pb_1c : 29.08 +pb_5c : 29.05 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.09 +pb_1c : 29.09 +pb_5c : 29.05 +pb_10c : 29.00 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.10 +pb_1c : 29.10 +pb_5c : 29.10 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.11 +pb_1c : 29.11 +pb_5c : 29.10 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.12 +pb_1c : 29.12 +pb_5c : 29.10 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.13 +pb_1c : 29.13 +pb_5c : 29.10 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.14 +pb_1c : 29.14 +pb_5c : 29.10 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.15 +pb_1c : 29.15 +pb_5c : 29.15 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.16 +pb_1c : 29.16 +pb_5c : 29.15 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.17 +pb_1c : 29.17 +pb_5c : 29.15 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.18 +pb_1c : 29.18 +pb_5c : 29.15 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.19 +pb_1c : 29.19 +pb_5c : 29.15 +pb_10c : 29.10 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.20 +pb_1c : 29.20 +pb_5c : 29.20 +pb_10c : 29.20 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.21 +pb_1c : 29.21 +pb_5c : 29.20 +pb_10c : 29.20 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.22 +pb_1c : 29.22 +pb_5c : 29.20 +pb_10c : 29.20 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.23 +pb_1c : 29.23 +pb_5c : 29.20 +pb_10c : 29.20 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.24 +pb_1c : 29.24 +pb_5c : 29.20 +pb_10c : 29.20 +pb_25c : 29.00 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.25 +pb_1c : 29.25 +pb_5c : 29.25 +pb_10c : 29.20 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.26 +pb_1c : 29.26 +pb_5c : 29.25 +pb_10c : 29.20 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.27 +pb_1c : 29.27 +pb_5c : 29.25 +pb_10c : 29.20 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.28 +pb_1c : 29.28 +pb_5c : 29.25 +pb_10c : 29.20 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.29 +pb_1c : 29.29 +pb_5c : 29.25 +pb_10c : 29.20 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.30 +pb_1c : 29.30 +pb_5c : 29.30 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.31 +pb_1c : 29.31 +pb_5c : 29.30 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.32 +pb_1c : 29.32 +pb_5c : 29.30 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.33 +pb_1c : 29.33 +pb_5c : 29.30 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.34 +pb_1c : 29.34 +pb_5c : 29.30 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.35 +pb_1c : 29.35 +pb_5c : 29.35 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.36 +pb_1c : 29.36 +pb_5c : 29.35 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.37 +pb_1c : 29.37 +pb_5c : 29.35 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.38 +pb_1c : 29.38 +pb_5c : 29.35 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.39 +pb_1c : 29.39 +pb_5c : 29.35 +pb_10c : 29.30 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.40 +pb_1c : 29.40 +pb_5c : 29.40 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.41 +pb_1c : 29.41 +pb_5c : 29.40 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.42 +pb_1c : 29.42 +pb_5c : 29.40 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.43 +pb_1c : 29.43 +pb_5c : 29.40 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.44 +pb_1c : 29.44 +pb_5c : 29.40 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.45 +pb_1c : 29.45 +pb_5c : 29.45 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.46 +pb_1c : 29.46 +pb_5c : 29.45 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.47 +pb_1c : 29.47 +pb_5c : 29.45 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.48 +pb_1c : 29.48 +pb_5c : 29.45 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.49 +pb_1c : 29.49 +pb_5c : 29.45 +pb_10c : 29.40 +pb_25c : 29.25 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.50 +pb_1c : 29.50 +pb_5c : 29.50 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.51 +pb_1c : 29.51 +pb_5c : 29.50 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.52 +pb_1c : 29.52 +pb_5c : 29.50 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.53 +pb_1c : 29.53 +pb_5c : 29.50 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.54 +pb_1c : 29.54 +pb_5c : 29.50 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.55 +pb_1c : 29.55 +pb_5c : 29.55 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.56 +pb_1c : 29.56 +pb_5c : 29.55 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.57 +pb_1c : 29.57 +pb_5c : 29.55 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.58 +pb_1c : 29.58 +pb_5c : 29.55 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.59 +pb_1c : 29.59 +pb_5c : 29.55 +pb_10c : 29.50 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.60 +pb_1c : 29.60 +pb_5c : 29.60 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.61 +pb_1c : 29.61 +pb_5c : 29.60 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.62 +pb_1c : 29.62 +pb_5c : 29.60 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.63 +pb_1c : 29.63 +pb_5c : 29.60 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.64 +pb_1c : 29.64 +pb_5c : 29.60 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.65 +pb_1c : 29.65 +pb_5c : 29.65 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.66 +pb_1c : 29.66 +pb_5c : 29.65 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.67 +pb_1c : 29.67 +pb_5c : 29.65 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.68 +pb_1c : 29.68 +pb_5c : 29.65 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.69 +pb_1c : 29.69 +pb_5c : 29.65 +pb_10c : 29.60 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.70 +pb_1c : 29.70 +pb_5c : 29.70 +pb_10c : 29.70 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.71 +pb_1c : 29.71 +pb_5c : 29.70 +pb_10c : 29.70 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.72 +pb_1c : 29.72 +pb_5c : 29.70 +pb_10c : 29.70 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.73 +pb_1c : 29.73 +pb_5c : 29.70 +pb_10c : 29.70 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.74 +pb_1c : 29.74 +pb_5c : 29.70 +pb_10c : 29.70 +pb_25c : 29.50 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.75 +pb_1c : 29.75 +pb_5c : 29.75 +pb_10c : 29.70 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.76 +pb_1c : 29.76 +pb_5c : 29.75 +pb_10c : 29.70 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.77 +pb_1c : 29.77 +pb_5c : 29.75 +pb_10c : 29.70 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.78 +pb_1c : 29.78 +pb_5c : 29.75 +pb_10c : 29.70 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.79 +pb_1c : 29.79 +pb_5c : 29.75 +pb_10c : 29.70 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.80 +pb_1c : 29.80 +pb_5c : 29.80 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.81 +pb_1c : 29.81 +pb_5c : 29.80 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.82 +pb_1c : 29.82 +pb_5c : 29.80 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.83 +pb_1c : 29.83 +pb_5c : 29.80 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.84 +pb_1c : 29.84 +pb_5c : 29.80 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.85 +pb_1c : 29.85 +pb_5c : 29.85 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.86 +pb_1c : 29.86 +pb_5c : 29.85 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.87 +pb_1c : 29.87 +pb_5c : 29.85 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.88 +pb_1c : 29.88 +pb_5c : 29.85 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.89 +pb_1c : 29.89 +pb_5c : 29.85 +pb_10c : 29.80 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.90 +pb_1c : 29.90 +pb_5c : 29.90 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.91 +pb_1c : 29.91 +pb_5c : 29.90 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.92 +pb_1c : 29.92 +pb_5c : 29.90 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.93 +pb_1c : 29.93 +pb_5c : 29.90 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.94 +pb_1c : 29.94 +pb_5c : 29.90 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.95 +pb_1c : 29.95 +pb_5c : 29.95 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.96 +pb_1c : 29.96 +pb_5c : 29.95 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.97 +pb_1c : 29.97 +pb_5c : 29.95 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.98 +pb_1c : 29.98 +pb_5c : 29.95 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +29.99 +pb_1c : 29.99 +pb_5c : 29.95 +pb_10c : 29.90 +pb_25c : 29.75 +pb_1d : 29.00 +pb_5d : 25.00 +pb_10d : 20.00 + +30.00 +pb_1c : 30.00 +pb_5c : 30.00 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.01 +pb_1c : 30.01 +pb_5c : 30.00 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.02 +pb_1c : 30.02 +pb_5c : 30.00 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.03 +pb_1c : 30.03 +pb_5c : 30.00 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.04 +pb_1c : 30.04 +pb_5c : 30.00 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.05 +pb_1c : 30.05 +pb_5c : 30.05 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.06 +pb_1c : 30.06 +pb_5c : 30.05 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.07 +pb_1c : 30.07 +pb_5c : 30.05 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.08 +pb_1c : 30.08 +pb_5c : 30.05 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.09 +pb_1c : 30.09 +pb_5c : 30.05 +pb_10c : 30.00 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.10 +pb_1c : 30.10 +pb_5c : 30.10 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.11 +pb_1c : 30.11 +pb_5c : 30.10 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.12 +pb_1c : 30.12 +pb_5c : 30.10 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.13 +pb_1c : 30.13 +pb_5c : 30.10 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.14 +pb_1c : 30.14 +pb_5c : 30.10 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.15 +pb_1c : 30.15 +pb_5c : 30.15 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.16 +pb_1c : 30.16 +pb_5c : 30.15 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.17 +pb_1c : 30.17 +pb_5c : 30.15 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.18 +pb_1c : 30.18 +pb_5c : 30.15 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.19 +pb_1c : 30.19 +pb_5c : 30.15 +pb_10c : 30.10 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.20 +pb_1c : 30.20 +pb_5c : 30.20 +pb_10c : 30.20 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.21 +pb_1c : 30.21 +pb_5c : 30.20 +pb_10c : 30.20 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.22 +pb_1c : 30.22 +pb_5c : 30.20 +pb_10c : 30.20 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.23 +pb_1c : 30.23 +pb_5c : 30.20 +pb_10c : 30.20 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.24 +pb_1c : 30.24 +pb_5c : 30.20 +pb_10c : 30.20 +pb_25c : 30.00 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.25 +pb_1c : 30.25 +pb_5c : 30.25 +pb_10c : 30.20 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.26 +pb_1c : 30.26 +pb_5c : 30.25 +pb_10c : 30.20 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.27 +pb_1c : 30.27 +pb_5c : 30.25 +pb_10c : 30.20 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.28 +pb_1c : 30.28 +pb_5c : 30.25 +pb_10c : 30.20 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.29 +pb_1c : 30.29 +pb_5c : 30.25 +pb_10c : 30.20 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.30 +pb_1c : 30.30 +pb_5c : 30.30 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.31 +pb_1c : 30.31 +pb_5c : 30.30 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.32 +pb_1c : 30.32 +pb_5c : 30.30 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.33 +pb_1c : 30.33 +pb_5c : 30.30 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.34 +pb_1c : 30.34 +pb_5c : 30.30 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.35 +pb_1c : 30.35 +pb_5c : 30.35 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.36 +pb_1c : 30.36 +pb_5c : 30.35 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.37 +pb_1c : 30.37 +pb_5c : 30.35 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.38 +pb_1c : 30.38 +pb_5c : 30.35 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.39 +pb_1c : 30.39 +pb_5c : 30.35 +pb_10c : 30.30 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.40 +pb_1c : 30.40 +pb_5c : 30.40 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.41 +pb_1c : 30.41 +pb_5c : 30.40 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.42 +pb_1c : 30.42 +pb_5c : 30.40 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.43 +pb_1c : 30.43 +pb_5c : 30.40 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.44 +pb_1c : 30.44 +pb_5c : 30.40 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.45 +pb_1c : 30.45 +pb_5c : 30.45 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.46 +pb_1c : 30.46 +pb_5c : 30.45 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.47 +pb_1c : 30.47 +pb_5c : 30.45 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.48 +pb_1c : 30.48 +pb_5c : 30.45 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.49 +pb_1c : 30.49 +pb_5c : 30.45 +pb_10c : 30.40 +pb_25c : 30.25 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.50 +pb_1c : 30.50 +pb_5c : 30.50 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.51 +pb_1c : 30.51 +pb_5c : 30.50 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.52 +pb_1c : 30.52 +pb_5c : 30.50 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.53 +pb_1c : 30.53 +pb_5c : 30.50 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.54 +pb_1c : 30.54 +pb_5c : 30.50 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.55 +pb_1c : 30.55 +pb_5c : 30.55 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.56 +pb_1c : 30.56 +pb_5c : 30.55 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.57 +pb_1c : 30.57 +pb_5c : 30.55 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.58 +pb_1c : 30.58 +pb_5c : 30.55 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.59 +pb_1c : 30.59 +pb_5c : 30.55 +pb_10c : 30.50 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.60 +pb_1c : 30.60 +pb_5c : 30.60 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.61 +pb_1c : 30.61 +pb_5c : 30.60 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.62 +pb_1c : 30.62 +pb_5c : 30.60 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.63 +pb_1c : 30.63 +pb_5c : 30.60 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.64 +pb_1c : 30.64 +pb_5c : 30.60 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.65 +pb_1c : 30.65 +pb_5c : 30.65 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.66 +pb_1c : 30.66 +pb_5c : 30.65 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.67 +pb_1c : 30.67 +pb_5c : 30.65 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.68 +pb_1c : 30.68 +pb_5c : 30.65 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.69 +pb_1c : 30.69 +pb_5c : 30.65 +pb_10c : 30.60 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.70 +pb_1c : 30.70 +pb_5c : 30.70 +pb_10c : 30.70 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.71 +pb_1c : 30.71 +pb_5c : 30.70 +pb_10c : 30.70 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.72 +pb_1c : 30.72 +pb_5c : 30.70 +pb_10c : 30.70 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.73 +pb_1c : 30.73 +pb_5c : 30.70 +pb_10c : 30.70 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.74 +pb_1c : 30.74 +pb_5c : 30.70 +pb_10c : 30.70 +pb_25c : 30.50 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.75 +pb_1c : 30.75 +pb_5c : 30.75 +pb_10c : 30.70 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.76 +pb_1c : 30.76 +pb_5c : 30.75 +pb_10c : 30.70 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.77 +pb_1c : 30.77 +pb_5c : 30.75 +pb_10c : 30.70 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.78 +pb_1c : 30.78 +pb_5c : 30.75 +pb_10c : 30.70 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.79 +pb_1c : 30.79 +pb_5c : 30.75 +pb_10c : 30.70 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.80 +pb_1c : 30.80 +pb_5c : 30.80 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.81 +pb_1c : 30.81 +pb_5c : 30.80 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.82 +pb_1c : 30.82 +pb_5c : 30.80 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.83 +pb_1c : 30.83 +pb_5c : 30.80 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.84 +pb_1c : 30.84 +pb_5c : 30.80 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.85 +pb_1c : 30.85 +pb_5c : 30.85 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.86 +pb_1c : 30.86 +pb_5c : 30.85 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.87 +pb_1c : 30.87 +pb_5c : 30.85 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.88 +pb_1c : 30.88 +pb_5c : 30.85 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.89 +pb_1c : 30.89 +pb_5c : 30.85 +pb_10c : 30.80 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.90 +pb_1c : 30.90 +pb_5c : 30.90 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.91 +pb_1c : 30.91 +pb_5c : 30.90 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.92 +pb_1c : 30.92 +pb_5c : 30.90 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.93 +pb_1c : 30.93 +pb_5c : 30.90 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.94 +pb_1c : 30.94 +pb_5c : 30.90 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.95 +pb_1c : 30.95 +pb_5c : 30.95 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.96 +pb_1c : 30.96 +pb_5c : 30.95 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.97 +pb_1c : 30.97 +pb_5c : 30.95 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.98 +pb_1c : 30.98 +pb_5c : 30.95 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +30.99 +pb_1c : 30.99 +pb_5c : 30.95 +pb_10c : 30.90 +pb_25c : 30.75 +pb_1d : 30.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.00 +pb_1c : 31.00 +pb_5c : 31.00 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.01 +pb_1c : 31.01 +pb_5c : 31.00 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.02 +pb_1c : 31.02 +pb_5c : 31.00 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.03 +pb_1c : 31.03 +pb_5c : 31.00 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.04 +pb_1c : 31.04 +pb_5c : 31.00 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.05 +pb_1c : 31.05 +pb_5c : 31.05 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.06 +pb_1c : 31.06 +pb_5c : 31.05 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.07 +pb_1c : 31.07 +pb_5c : 31.05 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.08 +pb_1c : 31.08 +pb_5c : 31.05 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.09 +pb_1c : 31.09 +pb_5c : 31.05 +pb_10c : 31.00 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.10 +pb_1c : 31.10 +pb_5c : 31.10 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.11 +pb_1c : 31.11 +pb_5c : 31.10 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.12 +pb_1c : 31.12 +pb_5c : 31.10 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.13 +pb_1c : 31.13 +pb_5c : 31.10 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.14 +pb_1c : 31.14 +pb_5c : 31.10 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.15 +pb_1c : 31.15 +pb_5c : 31.15 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.16 +pb_1c : 31.16 +pb_5c : 31.15 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.17 +pb_1c : 31.17 +pb_5c : 31.15 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.18 +pb_1c : 31.18 +pb_5c : 31.15 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.19 +pb_1c : 31.19 +pb_5c : 31.15 +pb_10c : 31.10 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.20 +pb_1c : 31.20 +pb_5c : 31.20 +pb_10c : 31.20 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.21 +pb_1c : 31.21 +pb_5c : 31.20 +pb_10c : 31.20 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.22 +pb_1c : 31.22 +pb_5c : 31.20 +pb_10c : 31.20 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.23 +pb_1c : 31.23 +pb_5c : 31.20 +pb_10c : 31.20 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.24 +pb_1c : 31.24 +pb_5c : 31.20 +pb_10c : 31.20 +pb_25c : 31.00 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.25 +pb_1c : 31.25 +pb_5c : 31.25 +pb_10c : 31.20 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.26 +pb_1c : 31.26 +pb_5c : 31.25 +pb_10c : 31.20 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.27 +pb_1c : 31.27 +pb_5c : 31.25 +pb_10c : 31.20 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.28 +pb_1c : 31.28 +pb_5c : 31.25 +pb_10c : 31.20 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.29 +pb_1c : 31.29 +pb_5c : 31.25 +pb_10c : 31.20 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.30 +pb_1c : 31.30 +pb_5c : 31.30 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.31 +pb_1c : 31.31 +pb_5c : 31.30 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.32 +pb_1c : 31.32 +pb_5c : 31.30 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.33 +pb_1c : 31.33 +pb_5c : 31.30 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.34 +pb_1c : 31.34 +pb_5c : 31.30 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.35 +pb_1c : 31.35 +pb_5c : 31.35 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.36 +pb_1c : 31.36 +pb_5c : 31.35 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.37 +pb_1c : 31.37 +pb_5c : 31.35 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.38 +pb_1c : 31.38 +pb_5c : 31.35 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.39 +pb_1c : 31.39 +pb_5c : 31.35 +pb_10c : 31.30 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.40 +pb_1c : 31.40 +pb_5c : 31.40 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.41 +pb_1c : 31.41 +pb_5c : 31.40 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.42 +pb_1c : 31.42 +pb_5c : 31.40 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.43 +pb_1c : 31.43 +pb_5c : 31.40 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.44 +pb_1c : 31.44 +pb_5c : 31.40 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.45 +pb_1c : 31.45 +pb_5c : 31.45 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.46 +pb_1c : 31.46 +pb_5c : 31.45 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.47 +pb_1c : 31.47 +pb_5c : 31.45 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.48 +pb_1c : 31.48 +pb_5c : 31.45 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.49 +pb_1c : 31.49 +pb_5c : 31.45 +pb_10c : 31.40 +pb_25c : 31.25 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.50 +pb_1c : 31.50 +pb_5c : 31.50 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.51 +pb_1c : 31.51 +pb_5c : 31.50 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.52 +pb_1c : 31.52 +pb_5c : 31.50 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.53 +pb_1c : 31.53 +pb_5c : 31.50 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.54 +pb_1c : 31.54 +pb_5c : 31.50 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.55 +pb_1c : 31.55 +pb_5c : 31.55 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.56 +pb_1c : 31.56 +pb_5c : 31.55 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.57 +pb_1c : 31.57 +pb_5c : 31.55 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.58 +pb_1c : 31.58 +pb_5c : 31.55 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.59 +pb_1c : 31.59 +pb_5c : 31.55 +pb_10c : 31.50 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.60 +pb_1c : 31.60 +pb_5c : 31.60 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.61 +pb_1c : 31.61 +pb_5c : 31.60 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.62 +pb_1c : 31.62 +pb_5c : 31.60 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.63 +pb_1c : 31.63 +pb_5c : 31.60 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.64 +pb_1c : 31.64 +pb_5c : 31.60 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.65 +pb_1c : 31.65 +pb_5c : 31.65 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.66 +pb_1c : 31.66 +pb_5c : 31.65 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.67 +pb_1c : 31.67 +pb_5c : 31.65 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.68 +pb_1c : 31.68 +pb_5c : 31.65 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.69 +pb_1c : 31.69 +pb_5c : 31.65 +pb_10c : 31.60 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.70 +pb_1c : 31.70 +pb_5c : 31.70 +pb_10c : 31.70 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.71 +pb_1c : 31.71 +pb_5c : 31.70 +pb_10c : 31.70 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.72 +pb_1c : 31.72 +pb_5c : 31.70 +pb_10c : 31.70 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.73 +pb_1c : 31.73 +pb_5c : 31.70 +pb_10c : 31.70 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.74 +pb_1c : 31.74 +pb_5c : 31.70 +pb_10c : 31.70 +pb_25c : 31.50 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.75 +pb_1c : 31.75 +pb_5c : 31.75 +pb_10c : 31.70 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.76 +pb_1c : 31.76 +pb_5c : 31.75 +pb_10c : 31.70 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.77 +pb_1c : 31.77 +pb_5c : 31.75 +pb_10c : 31.70 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.78 +pb_1c : 31.78 +pb_5c : 31.75 +pb_10c : 31.70 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.79 +pb_1c : 31.79 +pb_5c : 31.75 +pb_10c : 31.70 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.80 +pb_1c : 31.80 +pb_5c : 31.80 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.81 +pb_1c : 31.81 +pb_5c : 31.80 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.82 +pb_1c : 31.82 +pb_5c : 31.80 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.83 +pb_1c : 31.83 +pb_5c : 31.80 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.84 +pb_1c : 31.84 +pb_5c : 31.80 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.85 +pb_1c : 31.85 +pb_5c : 31.85 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.86 +pb_1c : 31.86 +pb_5c : 31.85 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.87 +pb_1c : 31.87 +pb_5c : 31.85 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.88 +pb_1c : 31.88 +pb_5c : 31.85 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.89 +pb_1c : 31.89 +pb_5c : 31.85 +pb_10c : 31.80 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.90 +pb_1c : 31.90 +pb_5c : 31.90 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.91 +pb_1c : 31.91 +pb_5c : 31.90 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.92 +pb_1c : 31.92 +pb_5c : 31.90 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.93 +pb_1c : 31.93 +pb_5c : 31.90 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.94 +pb_1c : 31.94 +pb_5c : 31.90 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.95 +pb_1c : 31.95 +pb_5c : 31.95 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.96 +pb_1c : 31.96 +pb_5c : 31.95 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.97 +pb_1c : 31.97 +pb_5c : 31.95 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.98 +pb_1c : 31.98 +pb_5c : 31.95 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +31.99 +pb_1c : 31.99 +pb_5c : 31.95 +pb_10c : 31.90 +pb_25c : 31.75 +pb_1d : 31.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.00 +pb_1c : 32.00 +pb_5c : 32.00 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.01 +pb_1c : 32.01 +pb_5c : 32.00 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.02 +pb_1c : 32.02 +pb_5c : 32.00 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.03 +pb_1c : 32.03 +pb_5c : 32.00 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.04 +pb_1c : 32.04 +pb_5c : 32.00 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.05 +pb_1c : 32.05 +pb_5c : 32.05 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.06 +pb_1c : 32.06 +pb_5c : 32.05 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.07 +pb_1c : 32.07 +pb_5c : 32.05 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.08 +pb_1c : 32.08 +pb_5c : 32.05 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.09 +pb_1c : 32.09 +pb_5c : 32.05 +pb_10c : 32.00 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.10 +pb_1c : 32.10 +pb_5c : 32.10 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.11 +pb_1c : 32.11 +pb_5c : 32.10 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.12 +pb_1c : 32.12 +pb_5c : 32.10 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.13 +pb_1c : 32.13 +pb_5c : 32.10 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.14 +pb_1c : 32.14 +pb_5c : 32.10 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.15 +pb_1c : 32.15 +pb_5c : 32.15 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.16 +pb_1c : 32.16 +pb_5c : 32.15 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.17 +pb_1c : 32.17 +pb_5c : 32.15 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.18 +pb_1c : 32.18 +pb_5c : 32.15 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.19 +pb_1c : 32.19 +pb_5c : 32.15 +pb_10c : 32.10 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.20 +pb_1c : 32.20 +pb_5c : 32.20 +pb_10c : 32.20 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.21 +pb_1c : 32.21 +pb_5c : 32.20 +pb_10c : 32.20 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.22 +pb_1c : 32.22 +pb_5c : 32.20 +pb_10c : 32.20 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.23 +pb_1c : 32.23 +pb_5c : 32.20 +pb_10c : 32.20 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.24 +pb_1c : 32.24 +pb_5c : 32.20 +pb_10c : 32.20 +pb_25c : 32.00 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.25 +pb_1c : 32.25 +pb_5c : 32.25 +pb_10c : 32.20 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.26 +pb_1c : 32.26 +pb_5c : 32.25 +pb_10c : 32.20 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.27 +pb_1c : 32.27 +pb_5c : 32.25 +pb_10c : 32.20 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.28 +pb_1c : 32.28 +pb_5c : 32.25 +pb_10c : 32.20 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.29 +pb_1c : 32.29 +pb_5c : 32.25 +pb_10c : 32.20 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.30 +pb_1c : 32.30 +pb_5c : 32.30 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.31 +pb_1c : 32.31 +pb_5c : 32.30 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.32 +pb_1c : 32.32 +pb_5c : 32.30 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.33 +pb_1c : 32.33 +pb_5c : 32.30 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.34 +pb_1c : 32.34 +pb_5c : 32.30 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.35 +pb_1c : 32.35 +pb_5c : 32.35 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.36 +pb_1c : 32.36 +pb_5c : 32.35 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.37 +pb_1c : 32.37 +pb_5c : 32.35 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.38 +pb_1c : 32.38 +pb_5c : 32.35 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.39 +pb_1c : 32.39 +pb_5c : 32.35 +pb_10c : 32.30 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.40 +pb_1c : 32.40 +pb_5c : 32.40 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.41 +pb_1c : 32.41 +pb_5c : 32.40 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.42 +pb_1c : 32.42 +pb_5c : 32.40 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.43 +pb_1c : 32.43 +pb_5c : 32.40 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.44 +pb_1c : 32.44 +pb_5c : 32.40 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.45 +pb_1c : 32.45 +pb_5c : 32.45 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.46 +pb_1c : 32.46 +pb_5c : 32.45 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.47 +pb_1c : 32.47 +pb_5c : 32.45 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.48 +pb_1c : 32.48 +pb_5c : 32.45 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.49 +pb_1c : 32.49 +pb_5c : 32.45 +pb_10c : 32.40 +pb_25c : 32.25 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.50 +pb_1c : 32.50 +pb_5c : 32.50 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.51 +pb_1c : 32.51 +pb_5c : 32.50 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.52 +pb_1c : 32.52 +pb_5c : 32.50 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.53 +pb_1c : 32.53 +pb_5c : 32.50 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.54 +pb_1c : 32.54 +pb_5c : 32.50 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.55 +pb_1c : 32.55 +pb_5c : 32.55 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.56 +pb_1c : 32.56 +pb_5c : 32.55 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.57 +pb_1c : 32.57 +pb_5c : 32.55 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.58 +pb_1c : 32.58 +pb_5c : 32.55 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.59 +pb_1c : 32.59 +pb_5c : 32.55 +pb_10c : 32.50 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.60 +pb_1c : 32.60 +pb_5c : 32.60 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.61 +pb_1c : 32.61 +pb_5c : 32.60 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.62 +pb_1c : 32.62 +pb_5c : 32.60 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.63 +pb_1c : 32.63 +pb_5c : 32.60 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.64 +pb_1c : 32.64 +pb_5c : 32.60 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.65 +pb_1c : 32.65 +pb_5c : 32.65 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.66 +pb_1c : 32.66 +pb_5c : 32.65 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.67 +pb_1c : 32.67 +pb_5c : 32.65 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.68 +pb_1c : 32.68 +pb_5c : 32.65 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.69 +pb_1c : 32.69 +pb_5c : 32.65 +pb_10c : 32.60 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.70 +pb_1c : 32.70 +pb_5c : 32.70 +pb_10c : 32.70 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.71 +pb_1c : 32.71 +pb_5c : 32.70 +pb_10c : 32.70 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.72 +pb_1c : 32.72 +pb_5c : 32.70 +pb_10c : 32.70 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.73 +pb_1c : 32.73 +pb_5c : 32.70 +pb_10c : 32.70 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.74 +pb_1c : 32.74 +pb_5c : 32.70 +pb_10c : 32.70 +pb_25c : 32.50 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.75 +pb_1c : 32.75 +pb_5c : 32.75 +pb_10c : 32.70 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.76 +pb_1c : 32.76 +pb_5c : 32.75 +pb_10c : 32.70 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.77 +pb_1c : 32.77 +pb_5c : 32.75 +pb_10c : 32.70 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.78 +pb_1c : 32.78 +pb_5c : 32.75 +pb_10c : 32.70 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.79 +pb_1c : 32.79 +pb_5c : 32.75 +pb_10c : 32.70 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.80 +pb_1c : 32.80 +pb_5c : 32.80 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.81 +pb_1c : 32.81 +pb_5c : 32.80 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.82 +pb_1c : 32.82 +pb_5c : 32.80 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.83 +pb_1c : 32.83 +pb_5c : 32.80 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.84 +pb_1c : 32.84 +pb_5c : 32.80 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.85 +pb_1c : 32.85 +pb_5c : 32.85 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.86 +pb_1c : 32.86 +pb_5c : 32.85 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.87 +pb_1c : 32.87 +pb_5c : 32.85 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.88 +pb_1c : 32.88 +pb_5c : 32.85 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.89 +pb_1c : 32.89 +pb_5c : 32.85 +pb_10c : 32.80 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.90 +pb_1c : 32.90 +pb_5c : 32.90 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.91 +pb_1c : 32.91 +pb_5c : 32.90 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.92 +pb_1c : 32.92 +pb_5c : 32.90 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.93 +pb_1c : 32.93 +pb_5c : 32.90 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.94 +pb_1c : 32.94 +pb_5c : 32.90 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.95 +pb_1c : 32.95 +pb_5c : 32.95 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.96 +pb_1c : 32.96 +pb_5c : 32.95 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.97 +pb_1c : 32.97 +pb_5c : 32.95 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.98 +pb_1c : 32.98 +pb_5c : 32.95 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +32.99 +pb_1c : 32.99 +pb_5c : 32.95 +pb_10c : 32.90 +pb_25c : 32.75 +pb_1d : 32.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.00 +pb_1c : 33.00 +pb_5c : 33.00 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.01 +pb_1c : 33.01 +pb_5c : 33.00 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.02 +pb_1c : 33.02 +pb_5c : 33.00 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.03 +pb_1c : 33.03 +pb_5c : 33.00 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.04 +pb_1c : 33.04 +pb_5c : 33.00 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.05 +pb_1c : 33.05 +pb_5c : 33.05 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.06 +pb_1c : 33.06 +pb_5c : 33.05 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.07 +pb_1c : 33.07 +pb_5c : 33.05 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.08 +pb_1c : 33.08 +pb_5c : 33.05 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.09 +pb_1c : 33.09 +pb_5c : 33.05 +pb_10c : 33.00 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.10 +pb_1c : 33.10 +pb_5c : 33.10 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.11 +pb_1c : 33.11 +pb_5c : 33.10 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.12 +pb_1c : 33.12 +pb_5c : 33.10 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.13 +pb_1c : 33.13 +pb_5c : 33.10 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.14 +pb_1c : 33.14 +pb_5c : 33.10 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.15 +pb_1c : 33.15 +pb_5c : 33.15 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.16 +pb_1c : 33.16 +pb_5c : 33.15 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.17 +pb_1c : 33.17 +pb_5c : 33.15 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.18 +pb_1c : 33.18 +pb_5c : 33.15 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.19 +pb_1c : 33.19 +pb_5c : 33.15 +pb_10c : 33.10 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.20 +pb_1c : 33.20 +pb_5c : 33.20 +pb_10c : 33.20 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.21 +pb_1c : 33.21 +pb_5c : 33.20 +pb_10c : 33.20 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.22 +pb_1c : 33.22 +pb_5c : 33.20 +pb_10c : 33.20 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.23 +pb_1c : 33.23 +pb_5c : 33.20 +pb_10c : 33.20 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.24 +pb_1c : 33.24 +pb_5c : 33.20 +pb_10c : 33.20 +pb_25c : 33.00 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.25 +pb_1c : 33.25 +pb_5c : 33.25 +pb_10c : 33.20 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.26 +pb_1c : 33.26 +pb_5c : 33.25 +pb_10c : 33.20 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.27 +pb_1c : 33.27 +pb_5c : 33.25 +pb_10c : 33.20 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.28 +pb_1c : 33.28 +pb_5c : 33.25 +pb_10c : 33.20 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.29 +pb_1c : 33.29 +pb_5c : 33.25 +pb_10c : 33.20 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.30 +pb_1c : 33.30 +pb_5c : 33.30 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.31 +pb_1c : 33.31 +pb_5c : 33.30 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.32 +pb_1c : 33.32 +pb_5c : 33.30 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.33 +pb_1c : 33.33 +pb_5c : 33.30 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.34 +pb_1c : 33.34 +pb_5c : 33.30 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.35 +pb_1c : 33.35 +pb_5c : 33.35 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.36 +pb_1c : 33.36 +pb_5c : 33.35 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.37 +pb_1c : 33.37 +pb_5c : 33.35 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.38 +pb_1c : 33.38 +pb_5c : 33.35 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.39 +pb_1c : 33.39 +pb_5c : 33.35 +pb_10c : 33.30 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.40 +pb_1c : 33.40 +pb_5c : 33.40 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.41 +pb_1c : 33.41 +pb_5c : 33.40 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.42 +pb_1c : 33.42 +pb_5c : 33.40 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.43 +pb_1c : 33.43 +pb_5c : 33.40 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.44 +pb_1c : 33.44 +pb_5c : 33.40 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.45 +pb_1c : 33.45 +pb_5c : 33.45 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.46 +pb_1c : 33.46 +pb_5c : 33.45 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.47 +pb_1c : 33.47 +pb_5c : 33.45 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.48 +pb_1c : 33.48 +pb_5c : 33.45 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.49 +pb_1c : 33.49 +pb_5c : 33.45 +pb_10c : 33.40 +pb_25c : 33.25 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.50 +pb_1c : 33.50 +pb_5c : 33.50 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.51 +pb_1c : 33.51 +pb_5c : 33.50 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.52 +pb_1c : 33.52 +pb_5c : 33.50 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.53 +pb_1c : 33.53 +pb_5c : 33.50 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.54 +pb_1c : 33.54 +pb_5c : 33.50 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.55 +pb_1c : 33.55 +pb_5c : 33.55 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.56 +pb_1c : 33.56 +pb_5c : 33.55 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.57 +pb_1c : 33.57 +pb_5c : 33.55 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.58 +pb_1c : 33.58 +pb_5c : 33.55 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.59 +pb_1c : 33.59 +pb_5c : 33.55 +pb_10c : 33.50 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.60 +pb_1c : 33.60 +pb_5c : 33.60 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.61 +pb_1c : 33.61 +pb_5c : 33.60 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.62 +pb_1c : 33.62 +pb_5c : 33.60 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.63 +pb_1c : 33.63 +pb_5c : 33.60 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.64 +pb_1c : 33.64 +pb_5c : 33.60 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.65 +pb_1c : 33.65 +pb_5c : 33.65 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.66 +pb_1c : 33.66 +pb_5c : 33.65 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.67 +pb_1c : 33.67 +pb_5c : 33.65 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.68 +pb_1c : 33.68 +pb_5c : 33.65 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.69 +pb_1c : 33.69 +pb_5c : 33.65 +pb_10c : 33.60 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.70 +pb_1c : 33.70 +pb_5c : 33.70 +pb_10c : 33.70 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.71 +pb_1c : 33.71 +pb_5c : 33.70 +pb_10c : 33.70 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.72 +pb_1c : 33.72 +pb_5c : 33.70 +pb_10c : 33.70 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.73 +pb_1c : 33.73 +pb_5c : 33.70 +pb_10c : 33.70 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.74 +pb_1c : 33.74 +pb_5c : 33.70 +pb_10c : 33.70 +pb_25c : 33.50 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.75 +pb_1c : 33.75 +pb_5c : 33.75 +pb_10c : 33.70 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.76 +pb_1c : 33.76 +pb_5c : 33.75 +pb_10c : 33.70 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.77 +pb_1c : 33.77 +pb_5c : 33.75 +pb_10c : 33.70 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.78 +pb_1c : 33.78 +pb_5c : 33.75 +pb_10c : 33.70 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.79 +pb_1c : 33.79 +pb_5c : 33.75 +pb_10c : 33.70 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.80 +pb_1c : 33.80 +pb_5c : 33.80 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.81 +pb_1c : 33.81 +pb_5c : 33.80 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.82 +pb_1c : 33.82 +pb_5c : 33.80 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.83 +pb_1c : 33.83 +pb_5c : 33.80 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.84 +pb_1c : 33.84 +pb_5c : 33.80 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.85 +pb_1c : 33.85 +pb_5c : 33.85 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.86 +pb_1c : 33.86 +pb_5c : 33.85 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.87 +pb_1c : 33.87 +pb_5c : 33.85 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.88 +pb_1c : 33.88 +pb_5c : 33.85 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.89 +pb_1c : 33.89 +pb_5c : 33.85 +pb_10c : 33.80 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.90 +pb_1c : 33.90 +pb_5c : 33.90 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.91 +pb_1c : 33.91 +pb_5c : 33.90 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.92 +pb_1c : 33.92 +pb_5c : 33.90 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.93 +pb_1c : 33.93 +pb_5c : 33.90 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.94 +pb_1c : 33.94 +pb_5c : 33.90 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.95 +pb_1c : 33.95 +pb_5c : 33.95 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.96 +pb_1c : 33.96 +pb_5c : 33.95 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.97 +pb_1c : 33.97 +pb_5c : 33.95 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.98 +pb_1c : 33.98 +pb_5c : 33.95 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +33.99 +pb_1c : 33.99 +pb_5c : 33.95 +pb_10c : 33.90 +pb_25c : 33.75 +pb_1d : 33.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.00 +pb_1c : 34.00 +pb_5c : 34.00 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.01 +pb_1c : 34.01 +pb_5c : 34.00 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.02 +pb_1c : 34.02 +pb_5c : 34.00 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.03 +pb_1c : 34.03 +pb_5c : 34.00 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.04 +pb_1c : 34.04 +pb_5c : 34.00 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.05 +pb_1c : 34.05 +pb_5c : 34.05 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.06 +pb_1c : 34.06 +pb_5c : 34.05 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.07 +pb_1c : 34.07 +pb_5c : 34.05 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.08 +pb_1c : 34.08 +pb_5c : 34.05 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.09 +pb_1c : 34.09 +pb_5c : 34.05 +pb_10c : 34.00 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.10 +pb_1c : 34.10 +pb_5c : 34.10 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.11 +pb_1c : 34.11 +pb_5c : 34.10 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.12 +pb_1c : 34.12 +pb_5c : 34.10 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.13 +pb_1c : 34.13 +pb_5c : 34.10 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.14 +pb_1c : 34.14 +pb_5c : 34.10 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.15 +pb_1c : 34.15 +pb_5c : 34.15 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.16 +pb_1c : 34.16 +pb_5c : 34.15 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.17 +pb_1c : 34.17 +pb_5c : 34.15 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.18 +pb_1c : 34.18 +pb_5c : 34.15 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.19 +pb_1c : 34.19 +pb_5c : 34.15 +pb_10c : 34.10 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.20 +pb_1c : 34.20 +pb_5c : 34.20 +pb_10c : 34.20 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.21 +pb_1c : 34.21 +pb_5c : 34.20 +pb_10c : 34.20 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.22 +pb_1c : 34.22 +pb_5c : 34.20 +pb_10c : 34.20 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.23 +pb_1c : 34.23 +pb_5c : 34.20 +pb_10c : 34.20 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.24 +pb_1c : 34.24 +pb_5c : 34.20 +pb_10c : 34.20 +pb_25c : 34.00 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.25 +pb_1c : 34.25 +pb_5c : 34.25 +pb_10c : 34.20 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.26 +pb_1c : 34.26 +pb_5c : 34.25 +pb_10c : 34.20 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.27 +pb_1c : 34.27 +pb_5c : 34.25 +pb_10c : 34.20 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.28 +pb_1c : 34.28 +pb_5c : 34.25 +pb_10c : 34.20 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.29 +pb_1c : 34.29 +pb_5c : 34.25 +pb_10c : 34.20 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.30 +pb_1c : 34.30 +pb_5c : 34.30 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.31 +pb_1c : 34.31 +pb_5c : 34.30 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.32 +pb_1c : 34.32 +pb_5c : 34.30 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.33 +pb_1c : 34.33 +pb_5c : 34.30 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.34 +pb_1c : 34.34 +pb_5c : 34.30 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.35 +pb_1c : 34.35 +pb_5c : 34.35 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.36 +pb_1c : 34.36 +pb_5c : 34.35 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.37 +pb_1c : 34.37 +pb_5c : 34.35 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.38 +pb_1c : 34.38 +pb_5c : 34.35 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.39 +pb_1c : 34.39 +pb_5c : 34.35 +pb_10c : 34.30 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.40 +pb_1c : 34.40 +pb_5c : 34.40 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.41 +pb_1c : 34.41 +pb_5c : 34.40 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.42 +pb_1c : 34.42 +pb_5c : 34.40 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.43 +pb_1c : 34.43 +pb_5c : 34.40 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.44 +pb_1c : 34.44 +pb_5c : 34.40 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.45 +pb_1c : 34.45 +pb_5c : 34.45 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.46 +pb_1c : 34.46 +pb_5c : 34.45 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.47 +pb_1c : 34.47 +pb_5c : 34.45 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.48 +pb_1c : 34.48 +pb_5c : 34.45 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.49 +pb_1c : 34.49 +pb_5c : 34.45 +pb_10c : 34.40 +pb_25c : 34.25 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.50 +pb_1c : 34.50 +pb_5c : 34.50 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.51 +pb_1c : 34.51 +pb_5c : 34.50 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.52 +pb_1c : 34.52 +pb_5c : 34.50 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.53 +pb_1c : 34.53 +pb_5c : 34.50 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.54 +pb_1c : 34.54 +pb_5c : 34.50 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.55 +pb_1c : 34.55 +pb_5c : 34.55 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.56 +pb_1c : 34.56 +pb_5c : 34.55 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.57 +pb_1c : 34.57 +pb_5c : 34.55 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.58 +pb_1c : 34.58 +pb_5c : 34.55 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.59 +pb_1c : 34.59 +pb_5c : 34.55 +pb_10c : 34.50 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.60 +pb_1c : 34.60 +pb_5c : 34.60 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.61 +pb_1c : 34.61 +pb_5c : 34.60 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.62 +pb_1c : 34.62 +pb_5c : 34.60 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.63 +pb_1c : 34.63 +pb_5c : 34.60 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.64 +pb_1c : 34.64 +pb_5c : 34.60 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.65 +pb_1c : 34.65 +pb_5c : 34.65 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.66 +pb_1c : 34.66 +pb_5c : 34.65 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.67 +pb_1c : 34.67 +pb_5c : 34.65 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.68 +pb_1c : 34.68 +pb_5c : 34.65 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.69 +pb_1c : 34.69 +pb_5c : 34.65 +pb_10c : 34.60 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.70 +pb_1c : 34.70 +pb_5c : 34.70 +pb_10c : 34.70 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.71 +pb_1c : 34.71 +pb_5c : 34.70 +pb_10c : 34.70 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.72 +pb_1c : 34.72 +pb_5c : 34.70 +pb_10c : 34.70 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.73 +pb_1c : 34.73 +pb_5c : 34.70 +pb_10c : 34.70 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.74 +pb_1c : 34.74 +pb_5c : 34.70 +pb_10c : 34.70 +pb_25c : 34.50 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.75 +pb_1c : 34.75 +pb_5c : 34.75 +pb_10c : 34.70 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.76 +pb_1c : 34.76 +pb_5c : 34.75 +pb_10c : 34.70 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.77 +pb_1c : 34.77 +pb_5c : 34.75 +pb_10c : 34.70 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.78 +pb_1c : 34.78 +pb_5c : 34.75 +pb_10c : 34.70 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.79 +pb_1c : 34.79 +pb_5c : 34.75 +pb_10c : 34.70 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.80 +pb_1c : 34.80 +pb_5c : 34.80 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.81 +pb_1c : 34.81 +pb_5c : 34.80 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.82 +pb_1c : 34.82 +pb_5c : 34.80 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.83 +pb_1c : 34.83 +pb_5c : 34.80 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.84 +pb_1c : 34.84 +pb_5c : 34.80 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.85 +pb_1c : 34.85 +pb_5c : 34.85 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.86 +pb_1c : 34.86 +pb_5c : 34.85 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.87 +pb_1c : 34.87 +pb_5c : 34.85 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.88 +pb_1c : 34.88 +pb_5c : 34.85 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.89 +pb_1c : 34.89 +pb_5c : 34.85 +pb_10c : 34.80 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.90 +pb_1c : 34.90 +pb_5c : 34.90 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.91 +pb_1c : 34.91 +pb_5c : 34.90 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.92 +pb_1c : 34.92 +pb_5c : 34.90 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.93 +pb_1c : 34.93 +pb_5c : 34.90 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.94 +pb_1c : 34.94 +pb_5c : 34.90 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.95 +pb_1c : 34.95 +pb_5c : 34.95 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.96 +pb_1c : 34.96 +pb_5c : 34.95 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.97 +pb_1c : 34.97 +pb_5c : 34.95 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.98 +pb_1c : 34.98 +pb_5c : 34.95 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +34.99 +pb_1c : 34.99 +pb_5c : 34.95 +pb_10c : 34.90 +pb_25c : 34.75 +pb_1d : 34.00 +pb_5d : 30.00 +pb_10d : 30.00 + +35.00 +pb_1c : 35.00 +pb_5c : 35.00 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.01 +pb_1c : 35.01 +pb_5c : 35.00 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.02 +pb_1c : 35.02 +pb_5c : 35.00 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.03 +pb_1c : 35.03 +pb_5c : 35.00 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.04 +pb_1c : 35.04 +pb_5c : 35.00 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.05 +pb_1c : 35.05 +pb_5c : 35.05 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.06 +pb_1c : 35.06 +pb_5c : 35.05 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.07 +pb_1c : 35.07 +pb_5c : 35.05 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.08 +pb_1c : 35.08 +pb_5c : 35.05 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.09 +pb_1c : 35.09 +pb_5c : 35.05 +pb_10c : 35.00 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.10 +pb_1c : 35.10 +pb_5c : 35.10 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.11 +pb_1c : 35.11 +pb_5c : 35.10 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.12 +pb_1c : 35.12 +pb_5c : 35.10 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.13 +pb_1c : 35.13 +pb_5c : 35.10 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.14 +pb_1c : 35.14 +pb_5c : 35.10 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.15 +pb_1c : 35.15 +pb_5c : 35.15 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.16 +pb_1c : 35.16 +pb_5c : 35.15 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.17 +pb_1c : 35.17 +pb_5c : 35.15 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.18 +pb_1c : 35.18 +pb_5c : 35.15 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.19 +pb_1c : 35.19 +pb_5c : 35.15 +pb_10c : 35.10 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.20 +pb_1c : 35.20 +pb_5c : 35.20 +pb_10c : 35.20 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.21 +pb_1c : 35.21 +pb_5c : 35.20 +pb_10c : 35.20 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.22 +pb_1c : 35.22 +pb_5c : 35.20 +pb_10c : 35.20 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.23 +pb_1c : 35.23 +pb_5c : 35.20 +pb_10c : 35.20 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.24 +pb_1c : 35.24 +pb_5c : 35.20 +pb_10c : 35.20 +pb_25c : 35.00 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.25 +pb_1c : 35.25 +pb_5c : 35.25 +pb_10c : 35.20 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.26 +pb_1c : 35.26 +pb_5c : 35.25 +pb_10c : 35.20 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.27 +pb_1c : 35.27 +pb_5c : 35.25 +pb_10c : 35.20 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.28 +pb_1c : 35.28 +pb_5c : 35.25 +pb_10c : 35.20 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.29 +pb_1c : 35.29 +pb_5c : 35.25 +pb_10c : 35.20 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.30 +pb_1c : 35.30 +pb_5c : 35.30 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.31 +pb_1c : 35.31 +pb_5c : 35.30 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.32 +pb_1c : 35.32 +pb_5c : 35.30 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.33 +pb_1c : 35.33 +pb_5c : 35.30 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.34 +pb_1c : 35.34 +pb_5c : 35.30 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.35 +pb_1c : 35.35 +pb_5c : 35.35 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.36 +pb_1c : 35.36 +pb_5c : 35.35 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.37 +pb_1c : 35.37 +pb_5c : 35.35 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.38 +pb_1c : 35.38 +pb_5c : 35.35 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.39 +pb_1c : 35.39 +pb_5c : 35.35 +pb_10c : 35.30 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.40 +pb_1c : 35.40 +pb_5c : 35.40 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.41 +pb_1c : 35.41 +pb_5c : 35.40 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.42 +pb_1c : 35.42 +pb_5c : 35.40 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.43 +pb_1c : 35.43 +pb_5c : 35.40 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.44 +pb_1c : 35.44 +pb_5c : 35.40 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.45 +pb_1c : 35.45 +pb_5c : 35.45 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.46 +pb_1c : 35.46 +pb_5c : 35.45 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.47 +pb_1c : 35.47 +pb_5c : 35.45 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.48 +pb_1c : 35.48 +pb_5c : 35.45 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.49 +pb_1c : 35.49 +pb_5c : 35.45 +pb_10c : 35.40 +pb_25c : 35.25 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.50 +pb_1c : 35.50 +pb_5c : 35.50 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.51 +pb_1c : 35.51 +pb_5c : 35.50 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.52 +pb_1c : 35.52 +pb_5c : 35.50 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.53 +pb_1c : 35.53 +pb_5c : 35.50 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.54 +pb_1c : 35.54 +pb_5c : 35.50 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.55 +pb_1c : 35.55 +pb_5c : 35.55 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.56 +pb_1c : 35.56 +pb_5c : 35.55 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.57 +pb_1c : 35.57 +pb_5c : 35.55 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.58 +pb_1c : 35.58 +pb_5c : 35.55 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.59 +pb_1c : 35.59 +pb_5c : 35.55 +pb_10c : 35.50 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.60 +pb_1c : 35.60 +pb_5c : 35.60 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.61 +pb_1c : 35.61 +pb_5c : 35.60 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.62 +pb_1c : 35.62 +pb_5c : 35.60 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.63 +pb_1c : 35.63 +pb_5c : 35.60 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.64 +pb_1c : 35.64 +pb_5c : 35.60 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.65 +pb_1c : 35.65 +pb_5c : 35.65 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.66 +pb_1c : 35.66 +pb_5c : 35.65 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.67 +pb_1c : 35.67 +pb_5c : 35.65 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.68 +pb_1c : 35.68 +pb_5c : 35.65 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.69 +pb_1c : 35.69 +pb_5c : 35.65 +pb_10c : 35.60 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.70 +pb_1c : 35.70 +pb_5c : 35.70 +pb_10c : 35.70 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.71 +pb_1c : 35.71 +pb_5c : 35.70 +pb_10c : 35.70 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.72 +pb_1c : 35.72 +pb_5c : 35.70 +pb_10c : 35.70 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.73 +pb_1c : 35.73 +pb_5c : 35.70 +pb_10c : 35.70 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.74 +pb_1c : 35.74 +pb_5c : 35.70 +pb_10c : 35.70 +pb_25c : 35.50 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.75 +pb_1c : 35.75 +pb_5c : 35.75 +pb_10c : 35.70 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.76 +pb_1c : 35.76 +pb_5c : 35.75 +pb_10c : 35.70 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.77 +pb_1c : 35.77 +pb_5c : 35.75 +pb_10c : 35.70 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.78 +pb_1c : 35.78 +pb_5c : 35.75 +pb_10c : 35.70 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.79 +pb_1c : 35.79 +pb_5c : 35.75 +pb_10c : 35.70 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.80 +pb_1c : 35.80 +pb_5c : 35.80 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.81 +pb_1c : 35.81 +pb_5c : 35.80 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.82 +pb_1c : 35.82 +pb_5c : 35.80 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.83 +pb_1c : 35.83 +pb_5c : 35.80 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.84 +pb_1c : 35.84 +pb_5c : 35.80 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.85 +pb_1c : 35.85 +pb_5c : 35.85 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.86 +pb_1c : 35.86 +pb_5c : 35.85 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.87 +pb_1c : 35.87 +pb_5c : 35.85 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.88 +pb_1c : 35.88 +pb_5c : 35.85 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.89 +pb_1c : 35.89 +pb_5c : 35.85 +pb_10c : 35.80 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.90 +pb_1c : 35.90 +pb_5c : 35.90 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.91 +pb_1c : 35.91 +pb_5c : 35.90 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.92 +pb_1c : 35.92 +pb_5c : 35.90 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.93 +pb_1c : 35.93 +pb_5c : 35.90 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.94 +pb_1c : 35.94 +pb_5c : 35.90 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.95 +pb_1c : 35.95 +pb_5c : 35.95 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.96 +pb_1c : 35.96 +pb_5c : 35.95 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.97 +pb_1c : 35.97 +pb_5c : 35.95 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.98 +pb_1c : 35.98 +pb_5c : 35.95 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +35.99 +pb_1c : 35.99 +pb_5c : 35.95 +pb_10c : 35.90 +pb_25c : 35.75 +pb_1d : 35.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.00 +pb_1c : 36.00 +pb_5c : 36.00 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.01 +pb_1c : 36.01 +pb_5c : 36.00 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.02 +pb_1c : 36.02 +pb_5c : 36.00 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.03 +pb_1c : 36.03 +pb_5c : 36.00 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.04 +pb_1c : 36.04 +pb_5c : 36.00 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.05 +pb_1c : 36.05 +pb_5c : 36.05 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.06 +pb_1c : 36.06 +pb_5c : 36.05 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.07 +pb_1c : 36.07 +pb_5c : 36.05 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.08 +pb_1c : 36.08 +pb_5c : 36.05 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.09 +pb_1c : 36.09 +pb_5c : 36.05 +pb_10c : 36.00 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.10 +pb_1c : 36.10 +pb_5c : 36.10 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.11 +pb_1c : 36.11 +pb_5c : 36.10 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.12 +pb_1c : 36.12 +pb_5c : 36.10 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.13 +pb_1c : 36.13 +pb_5c : 36.10 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.14 +pb_1c : 36.14 +pb_5c : 36.10 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.15 +pb_1c : 36.15 +pb_5c : 36.15 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.16 +pb_1c : 36.16 +pb_5c : 36.15 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.17 +pb_1c : 36.17 +pb_5c : 36.15 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.18 +pb_1c : 36.18 +pb_5c : 36.15 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.19 +pb_1c : 36.19 +pb_5c : 36.15 +pb_10c : 36.10 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.20 +pb_1c : 36.20 +pb_5c : 36.20 +pb_10c : 36.20 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.21 +pb_1c : 36.21 +pb_5c : 36.20 +pb_10c : 36.20 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.22 +pb_1c : 36.22 +pb_5c : 36.20 +pb_10c : 36.20 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.23 +pb_1c : 36.23 +pb_5c : 36.20 +pb_10c : 36.20 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.24 +pb_1c : 36.24 +pb_5c : 36.20 +pb_10c : 36.20 +pb_25c : 36.00 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.25 +pb_1c : 36.25 +pb_5c : 36.25 +pb_10c : 36.20 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.26 +pb_1c : 36.26 +pb_5c : 36.25 +pb_10c : 36.20 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.27 +pb_1c : 36.27 +pb_5c : 36.25 +pb_10c : 36.20 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.28 +pb_1c : 36.28 +pb_5c : 36.25 +pb_10c : 36.20 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.29 +pb_1c : 36.29 +pb_5c : 36.25 +pb_10c : 36.20 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.30 +pb_1c : 36.30 +pb_5c : 36.30 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.31 +pb_1c : 36.31 +pb_5c : 36.30 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.32 +pb_1c : 36.32 +pb_5c : 36.30 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.33 +pb_1c : 36.33 +pb_5c : 36.30 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.34 +pb_1c : 36.34 +pb_5c : 36.30 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.35 +pb_1c : 36.35 +pb_5c : 36.35 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.36 +pb_1c : 36.36 +pb_5c : 36.35 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.37 +pb_1c : 36.37 +pb_5c : 36.35 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.38 +pb_1c : 36.38 +pb_5c : 36.35 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.39 +pb_1c : 36.39 +pb_5c : 36.35 +pb_10c : 36.30 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.40 +pb_1c : 36.40 +pb_5c : 36.40 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.41 +pb_1c : 36.41 +pb_5c : 36.40 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.42 +pb_1c : 36.42 +pb_5c : 36.40 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.43 +pb_1c : 36.43 +pb_5c : 36.40 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.44 +pb_1c : 36.44 +pb_5c : 36.40 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.45 +pb_1c : 36.45 +pb_5c : 36.45 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.46 +pb_1c : 36.46 +pb_5c : 36.45 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.47 +pb_1c : 36.47 +pb_5c : 36.45 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.48 +pb_1c : 36.48 +pb_5c : 36.45 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.49 +pb_1c : 36.49 +pb_5c : 36.45 +pb_10c : 36.40 +pb_25c : 36.25 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.50 +pb_1c : 36.50 +pb_5c : 36.50 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.51 +pb_1c : 36.51 +pb_5c : 36.50 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.52 +pb_1c : 36.52 +pb_5c : 36.50 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.53 +pb_1c : 36.53 +pb_5c : 36.50 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.54 +pb_1c : 36.54 +pb_5c : 36.50 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.55 +pb_1c : 36.55 +pb_5c : 36.55 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.56 +pb_1c : 36.56 +pb_5c : 36.55 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.57 +pb_1c : 36.57 +pb_5c : 36.55 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.58 +pb_1c : 36.58 +pb_5c : 36.55 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.59 +pb_1c : 36.59 +pb_5c : 36.55 +pb_10c : 36.50 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.60 +pb_1c : 36.60 +pb_5c : 36.60 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.61 +pb_1c : 36.61 +pb_5c : 36.60 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.62 +pb_1c : 36.62 +pb_5c : 36.60 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.63 +pb_1c : 36.63 +pb_5c : 36.60 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.64 +pb_1c : 36.64 +pb_5c : 36.60 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.65 +pb_1c : 36.65 +pb_5c : 36.65 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.66 +pb_1c : 36.66 +pb_5c : 36.65 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.67 +pb_1c : 36.67 +pb_5c : 36.65 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.68 +pb_1c : 36.68 +pb_5c : 36.65 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.69 +pb_1c : 36.69 +pb_5c : 36.65 +pb_10c : 36.60 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.70 +pb_1c : 36.70 +pb_5c : 36.70 +pb_10c : 36.70 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.71 +pb_1c : 36.71 +pb_5c : 36.70 +pb_10c : 36.70 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.72 +pb_1c : 36.72 +pb_5c : 36.70 +pb_10c : 36.70 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.73 +pb_1c : 36.73 +pb_5c : 36.70 +pb_10c : 36.70 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.74 +pb_1c : 36.74 +pb_5c : 36.70 +pb_10c : 36.70 +pb_25c : 36.50 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.75 +pb_1c : 36.75 +pb_5c : 36.75 +pb_10c : 36.70 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.76 +pb_1c : 36.76 +pb_5c : 36.75 +pb_10c : 36.70 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.77 +pb_1c : 36.77 +pb_5c : 36.75 +pb_10c : 36.70 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.78 +pb_1c : 36.78 +pb_5c : 36.75 +pb_10c : 36.70 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.79 +pb_1c : 36.79 +pb_5c : 36.75 +pb_10c : 36.70 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.80 +pb_1c : 36.80 +pb_5c : 36.80 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.81 +pb_1c : 36.81 +pb_5c : 36.80 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.82 +pb_1c : 36.82 +pb_5c : 36.80 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.83 +pb_1c : 36.83 +pb_5c : 36.80 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.84 +pb_1c : 36.84 +pb_5c : 36.80 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.85 +pb_1c : 36.85 +pb_5c : 36.85 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.86 +pb_1c : 36.86 +pb_5c : 36.85 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.87 +pb_1c : 36.87 +pb_5c : 36.85 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.88 +pb_1c : 36.88 +pb_5c : 36.85 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.89 +pb_1c : 36.89 +pb_5c : 36.85 +pb_10c : 36.80 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.90 +pb_1c : 36.90 +pb_5c : 36.90 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.91 +pb_1c : 36.91 +pb_5c : 36.90 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.92 +pb_1c : 36.92 +pb_5c : 36.90 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.93 +pb_1c : 36.93 +pb_5c : 36.90 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.94 +pb_1c : 36.94 +pb_5c : 36.90 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.95 +pb_1c : 36.95 +pb_5c : 36.95 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.96 +pb_1c : 36.96 +pb_5c : 36.95 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.97 +pb_1c : 36.97 +pb_5c : 36.95 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.98 +pb_1c : 36.98 +pb_5c : 36.95 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +36.99 +pb_1c : 36.99 +pb_5c : 36.95 +pb_10c : 36.90 +pb_25c : 36.75 +pb_1d : 36.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.00 +pb_1c : 37.00 +pb_5c : 37.00 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.01 +pb_1c : 37.01 +pb_5c : 37.00 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.02 +pb_1c : 37.02 +pb_5c : 37.00 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.03 +pb_1c : 37.03 +pb_5c : 37.00 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.04 +pb_1c : 37.04 +pb_5c : 37.00 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.05 +pb_1c : 37.05 +pb_5c : 37.05 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.06 +pb_1c : 37.06 +pb_5c : 37.05 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.07 +pb_1c : 37.07 +pb_5c : 37.05 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.08 +pb_1c : 37.08 +pb_5c : 37.05 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.09 +pb_1c : 37.09 +pb_5c : 37.05 +pb_10c : 37.00 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.10 +pb_1c : 37.10 +pb_5c : 37.10 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.11 +pb_1c : 37.11 +pb_5c : 37.10 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.12 +pb_1c : 37.12 +pb_5c : 37.10 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.13 +pb_1c : 37.13 +pb_5c : 37.10 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.14 +pb_1c : 37.14 +pb_5c : 37.10 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.15 +pb_1c : 37.15 +pb_5c : 37.15 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.16 +pb_1c : 37.16 +pb_5c : 37.15 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.17 +pb_1c : 37.17 +pb_5c : 37.15 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.18 +pb_1c : 37.18 +pb_5c : 37.15 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.19 +pb_1c : 37.19 +pb_5c : 37.15 +pb_10c : 37.10 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.20 +pb_1c : 37.20 +pb_5c : 37.20 +pb_10c : 37.20 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.21 +pb_1c : 37.21 +pb_5c : 37.20 +pb_10c : 37.20 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.22 +pb_1c : 37.22 +pb_5c : 37.20 +pb_10c : 37.20 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.23 +pb_1c : 37.23 +pb_5c : 37.20 +pb_10c : 37.20 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.24 +pb_1c : 37.24 +pb_5c : 37.20 +pb_10c : 37.20 +pb_25c : 37.00 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.25 +pb_1c : 37.25 +pb_5c : 37.25 +pb_10c : 37.20 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.26 +pb_1c : 37.26 +pb_5c : 37.25 +pb_10c : 37.20 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.27 +pb_1c : 37.27 +pb_5c : 37.25 +pb_10c : 37.20 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.28 +pb_1c : 37.28 +pb_5c : 37.25 +pb_10c : 37.20 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.29 +pb_1c : 37.29 +pb_5c : 37.25 +pb_10c : 37.20 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.30 +pb_1c : 37.30 +pb_5c : 37.30 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.31 +pb_1c : 37.31 +pb_5c : 37.30 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.32 +pb_1c : 37.32 +pb_5c : 37.30 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.33 +pb_1c : 37.33 +pb_5c : 37.30 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.34 +pb_1c : 37.34 +pb_5c : 37.30 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.35 +pb_1c : 37.35 +pb_5c : 37.35 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.36 +pb_1c : 37.36 +pb_5c : 37.35 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.37 +pb_1c : 37.37 +pb_5c : 37.35 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.38 +pb_1c : 37.38 +pb_5c : 37.35 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.39 +pb_1c : 37.39 +pb_5c : 37.35 +pb_10c : 37.30 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.40 +pb_1c : 37.40 +pb_5c : 37.40 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.41 +pb_1c : 37.41 +pb_5c : 37.40 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.42 +pb_1c : 37.42 +pb_5c : 37.40 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.43 +pb_1c : 37.43 +pb_5c : 37.40 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.44 +pb_1c : 37.44 +pb_5c : 37.40 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.45 +pb_1c : 37.45 +pb_5c : 37.45 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.46 +pb_1c : 37.46 +pb_5c : 37.45 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.47 +pb_1c : 37.47 +pb_5c : 37.45 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.48 +pb_1c : 37.48 +pb_5c : 37.45 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.49 +pb_1c : 37.49 +pb_5c : 37.45 +pb_10c : 37.40 +pb_25c : 37.25 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.50 +pb_1c : 37.50 +pb_5c : 37.50 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.51 +pb_1c : 37.51 +pb_5c : 37.50 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.52 +pb_1c : 37.52 +pb_5c : 37.50 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.53 +pb_1c : 37.53 +pb_5c : 37.50 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.54 +pb_1c : 37.54 +pb_5c : 37.50 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.55 +pb_1c : 37.55 +pb_5c : 37.55 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.56 +pb_1c : 37.56 +pb_5c : 37.55 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.57 +pb_1c : 37.57 +pb_5c : 37.55 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.58 +pb_1c : 37.58 +pb_5c : 37.55 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.59 +pb_1c : 37.59 +pb_5c : 37.55 +pb_10c : 37.50 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.60 +pb_1c : 37.60 +pb_5c : 37.60 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.61 +pb_1c : 37.61 +pb_5c : 37.60 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.62 +pb_1c : 37.62 +pb_5c : 37.60 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.63 +pb_1c : 37.63 +pb_5c : 37.60 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.64 +pb_1c : 37.64 +pb_5c : 37.60 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.65 +pb_1c : 37.65 +pb_5c : 37.65 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.66 +pb_1c : 37.66 +pb_5c : 37.65 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.67 +pb_1c : 37.67 +pb_5c : 37.65 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.68 +pb_1c : 37.68 +pb_5c : 37.65 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.69 +pb_1c : 37.69 +pb_5c : 37.65 +pb_10c : 37.60 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.70 +pb_1c : 37.70 +pb_5c : 37.70 +pb_10c : 37.70 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.71 +pb_1c : 37.71 +pb_5c : 37.70 +pb_10c : 37.70 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.72 +pb_1c : 37.72 +pb_5c : 37.70 +pb_10c : 37.70 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.73 +pb_1c : 37.73 +pb_5c : 37.70 +pb_10c : 37.70 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.74 +pb_1c : 37.74 +pb_5c : 37.70 +pb_10c : 37.70 +pb_25c : 37.50 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.75 +pb_1c : 37.75 +pb_5c : 37.75 +pb_10c : 37.70 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.76 +pb_1c : 37.76 +pb_5c : 37.75 +pb_10c : 37.70 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.77 +pb_1c : 37.77 +pb_5c : 37.75 +pb_10c : 37.70 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.78 +pb_1c : 37.78 +pb_5c : 37.75 +pb_10c : 37.70 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.79 +pb_1c : 37.79 +pb_5c : 37.75 +pb_10c : 37.70 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.80 +pb_1c : 37.80 +pb_5c : 37.80 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.81 +pb_1c : 37.81 +pb_5c : 37.80 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.82 +pb_1c : 37.82 +pb_5c : 37.80 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.83 +pb_1c : 37.83 +pb_5c : 37.80 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.84 +pb_1c : 37.84 +pb_5c : 37.80 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.85 +pb_1c : 37.85 +pb_5c : 37.85 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.86 +pb_1c : 37.86 +pb_5c : 37.85 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.87 +pb_1c : 37.87 +pb_5c : 37.85 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.88 +pb_1c : 37.88 +pb_5c : 37.85 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.89 +pb_1c : 37.89 +pb_5c : 37.85 +pb_10c : 37.80 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.90 +pb_1c : 37.90 +pb_5c : 37.90 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.91 +pb_1c : 37.91 +pb_5c : 37.90 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.92 +pb_1c : 37.92 +pb_5c : 37.90 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.93 +pb_1c : 37.93 +pb_5c : 37.90 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.94 +pb_1c : 37.94 +pb_5c : 37.90 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.95 +pb_1c : 37.95 +pb_5c : 37.95 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.96 +pb_1c : 37.96 +pb_5c : 37.95 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.97 +pb_1c : 37.97 +pb_5c : 37.95 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.98 +pb_1c : 37.98 +pb_5c : 37.95 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +37.99 +pb_1c : 37.99 +pb_5c : 37.95 +pb_10c : 37.90 +pb_25c : 37.75 +pb_1d : 37.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.00 +pb_1c : 38.00 +pb_5c : 38.00 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.01 +pb_1c : 38.01 +pb_5c : 38.00 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.02 +pb_1c : 38.02 +pb_5c : 38.00 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.03 +pb_1c : 38.03 +pb_5c : 38.00 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.04 +pb_1c : 38.04 +pb_5c : 38.00 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.05 +pb_1c : 38.05 +pb_5c : 38.05 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.06 +pb_1c : 38.06 +pb_5c : 38.05 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.07 +pb_1c : 38.07 +pb_5c : 38.05 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.08 +pb_1c : 38.08 +pb_5c : 38.05 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.09 +pb_1c : 38.09 +pb_5c : 38.05 +pb_10c : 38.00 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.10 +pb_1c : 38.10 +pb_5c : 38.10 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.11 +pb_1c : 38.11 +pb_5c : 38.10 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.12 +pb_1c : 38.12 +pb_5c : 38.10 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.13 +pb_1c : 38.13 +pb_5c : 38.10 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.14 +pb_1c : 38.14 +pb_5c : 38.10 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.15 +pb_1c : 38.15 +pb_5c : 38.15 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.16 +pb_1c : 38.16 +pb_5c : 38.15 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.17 +pb_1c : 38.17 +pb_5c : 38.15 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.18 +pb_1c : 38.18 +pb_5c : 38.15 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.19 +pb_1c : 38.19 +pb_5c : 38.15 +pb_10c : 38.10 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.20 +pb_1c : 38.20 +pb_5c : 38.20 +pb_10c : 38.20 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.21 +pb_1c : 38.21 +pb_5c : 38.20 +pb_10c : 38.20 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.22 +pb_1c : 38.22 +pb_5c : 38.20 +pb_10c : 38.20 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.23 +pb_1c : 38.23 +pb_5c : 38.20 +pb_10c : 38.20 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.24 +pb_1c : 38.24 +pb_5c : 38.20 +pb_10c : 38.20 +pb_25c : 38.00 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.25 +pb_1c : 38.25 +pb_5c : 38.25 +pb_10c : 38.20 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.26 +pb_1c : 38.26 +pb_5c : 38.25 +pb_10c : 38.20 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.27 +pb_1c : 38.27 +pb_5c : 38.25 +pb_10c : 38.20 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.28 +pb_1c : 38.28 +pb_5c : 38.25 +pb_10c : 38.20 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.29 +pb_1c : 38.29 +pb_5c : 38.25 +pb_10c : 38.20 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.30 +pb_1c : 38.30 +pb_5c : 38.30 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.31 +pb_1c : 38.31 +pb_5c : 38.30 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.32 +pb_1c : 38.32 +pb_5c : 38.30 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.33 +pb_1c : 38.33 +pb_5c : 38.30 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.34 +pb_1c : 38.34 +pb_5c : 38.30 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.35 +pb_1c : 38.35 +pb_5c : 38.35 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.36 +pb_1c : 38.36 +pb_5c : 38.35 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.37 +pb_1c : 38.37 +pb_5c : 38.35 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.38 +pb_1c : 38.38 +pb_5c : 38.35 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.39 +pb_1c : 38.39 +pb_5c : 38.35 +pb_10c : 38.30 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.40 +pb_1c : 38.40 +pb_5c : 38.40 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.41 +pb_1c : 38.41 +pb_5c : 38.40 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.42 +pb_1c : 38.42 +pb_5c : 38.40 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.43 +pb_1c : 38.43 +pb_5c : 38.40 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.44 +pb_1c : 38.44 +pb_5c : 38.40 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.45 +pb_1c : 38.45 +pb_5c : 38.45 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.46 +pb_1c : 38.46 +pb_5c : 38.45 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.47 +pb_1c : 38.47 +pb_5c : 38.45 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.48 +pb_1c : 38.48 +pb_5c : 38.45 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.49 +pb_1c : 38.49 +pb_5c : 38.45 +pb_10c : 38.40 +pb_25c : 38.25 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.50 +pb_1c : 38.50 +pb_5c : 38.50 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.51 +pb_1c : 38.51 +pb_5c : 38.50 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.52 +pb_1c : 38.52 +pb_5c : 38.50 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.53 +pb_1c : 38.53 +pb_5c : 38.50 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.54 +pb_1c : 38.54 +pb_5c : 38.50 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.55 +pb_1c : 38.55 +pb_5c : 38.55 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.56 +pb_1c : 38.56 +pb_5c : 38.55 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.57 +pb_1c : 38.57 +pb_5c : 38.55 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.58 +pb_1c : 38.58 +pb_5c : 38.55 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.59 +pb_1c : 38.59 +pb_5c : 38.55 +pb_10c : 38.50 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.60 +pb_1c : 38.60 +pb_5c : 38.60 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.61 +pb_1c : 38.61 +pb_5c : 38.60 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.62 +pb_1c : 38.62 +pb_5c : 38.60 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.63 +pb_1c : 38.63 +pb_5c : 38.60 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.64 +pb_1c : 38.64 +pb_5c : 38.60 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.65 +pb_1c : 38.65 +pb_5c : 38.65 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.66 +pb_1c : 38.66 +pb_5c : 38.65 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.67 +pb_1c : 38.67 +pb_5c : 38.65 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.68 +pb_1c : 38.68 +pb_5c : 38.65 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.69 +pb_1c : 38.69 +pb_5c : 38.65 +pb_10c : 38.60 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.70 +pb_1c : 38.70 +pb_5c : 38.70 +pb_10c : 38.70 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.71 +pb_1c : 38.71 +pb_5c : 38.70 +pb_10c : 38.70 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.72 +pb_1c : 38.72 +pb_5c : 38.70 +pb_10c : 38.70 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.73 +pb_1c : 38.73 +pb_5c : 38.70 +pb_10c : 38.70 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.74 +pb_1c : 38.74 +pb_5c : 38.70 +pb_10c : 38.70 +pb_25c : 38.50 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.75 +pb_1c : 38.75 +pb_5c : 38.75 +pb_10c : 38.70 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.76 +pb_1c : 38.76 +pb_5c : 38.75 +pb_10c : 38.70 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.77 +pb_1c : 38.77 +pb_5c : 38.75 +pb_10c : 38.70 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.78 +pb_1c : 38.78 +pb_5c : 38.75 +pb_10c : 38.70 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.79 +pb_1c : 38.79 +pb_5c : 38.75 +pb_10c : 38.70 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.80 +pb_1c : 38.80 +pb_5c : 38.80 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.81 +pb_1c : 38.81 +pb_5c : 38.80 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.82 +pb_1c : 38.82 +pb_5c : 38.80 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.83 +pb_1c : 38.83 +pb_5c : 38.80 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.84 +pb_1c : 38.84 +pb_5c : 38.80 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.85 +pb_1c : 38.85 +pb_5c : 38.85 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.86 +pb_1c : 38.86 +pb_5c : 38.85 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.87 +pb_1c : 38.87 +pb_5c : 38.85 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.88 +pb_1c : 38.88 +pb_5c : 38.85 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.89 +pb_1c : 38.89 +pb_5c : 38.85 +pb_10c : 38.80 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.90 +pb_1c : 38.90 +pb_5c : 38.90 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.91 +pb_1c : 38.91 +pb_5c : 38.90 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.92 +pb_1c : 38.92 +pb_5c : 38.90 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.93 +pb_1c : 38.93 +pb_5c : 38.90 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.94 +pb_1c : 38.94 +pb_5c : 38.90 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.95 +pb_1c : 38.95 +pb_5c : 38.95 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.96 +pb_1c : 38.96 +pb_5c : 38.95 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.97 +pb_1c : 38.97 +pb_5c : 38.95 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.98 +pb_1c : 38.98 +pb_5c : 38.95 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +38.99 +pb_1c : 38.99 +pb_5c : 38.95 +pb_10c : 38.90 +pb_25c : 38.75 +pb_1d : 38.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.00 +pb_1c : 39.00 +pb_5c : 39.00 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.01 +pb_1c : 39.01 +pb_5c : 39.00 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.02 +pb_1c : 39.02 +pb_5c : 39.00 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.03 +pb_1c : 39.03 +pb_5c : 39.00 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.04 +pb_1c : 39.04 +pb_5c : 39.00 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.05 +pb_1c : 39.05 +pb_5c : 39.05 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.06 +pb_1c : 39.06 +pb_5c : 39.05 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.07 +pb_1c : 39.07 +pb_5c : 39.05 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.08 +pb_1c : 39.08 +pb_5c : 39.05 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.09 +pb_1c : 39.09 +pb_5c : 39.05 +pb_10c : 39.00 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.10 +pb_1c : 39.10 +pb_5c : 39.10 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.11 +pb_1c : 39.11 +pb_5c : 39.10 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.12 +pb_1c : 39.12 +pb_5c : 39.10 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.13 +pb_1c : 39.13 +pb_5c : 39.10 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.14 +pb_1c : 39.14 +pb_5c : 39.10 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.15 +pb_1c : 39.15 +pb_5c : 39.15 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.16 +pb_1c : 39.16 +pb_5c : 39.15 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.17 +pb_1c : 39.17 +pb_5c : 39.15 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.18 +pb_1c : 39.18 +pb_5c : 39.15 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.19 +pb_1c : 39.19 +pb_5c : 39.15 +pb_10c : 39.10 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.20 +pb_1c : 39.20 +pb_5c : 39.20 +pb_10c : 39.20 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.21 +pb_1c : 39.21 +pb_5c : 39.20 +pb_10c : 39.20 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.22 +pb_1c : 39.22 +pb_5c : 39.20 +pb_10c : 39.20 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.23 +pb_1c : 39.23 +pb_5c : 39.20 +pb_10c : 39.20 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.24 +pb_1c : 39.24 +pb_5c : 39.20 +pb_10c : 39.20 +pb_25c : 39.00 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.25 +pb_1c : 39.25 +pb_5c : 39.25 +pb_10c : 39.20 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.26 +pb_1c : 39.26 +pb_5c : 39.25 +pb_10c : 39.20 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.27 +pb_1c : 39.27 +pb_5c : 39.25 +pb_10c : 39.20 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.28 +pb_1c : 39.28 +pb_5c : 39.25 +pb_10c : 39.20 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.29 +pb_1c : 39.29 +pb_5c : 39.25 +pb_10c : 39.20 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.30 +pb_1c : 39.30 +pb_5c : 39.30 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.31 +pb_1c : 39.31 +pb_5c : 39.30 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.32 +pb_1c : 39.32 +pb_5c : 39.30 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.33 +pb_1c : 39.33 +pb_5c : 39.30 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.34 +pb_1c : 39.34 +pb_5c : 39.30 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.35 +pb_1c : 39.35 +pb_5c : 39.35 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.36 +pb_1c : 39.36 +pb_5c : 39.35 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.37 +pb_1c : 39.37 +pb_5c : 39.35 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.38 +pb_1c : 39.38 +pb_5c : 39.35 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.39 +pb_1c : 39.39 +pb_5c : 39.35 +pb_10c : 39.30 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.40 +pb_1c : 39.40 +pb_5c : 39.40 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.41 +pb_1c : 39.41 +pb_5c : 39.40 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.42 +pb_1c : 39.42 +pb_5c : 39.40 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.43 +pb_1c : 39.43 +pb_5c : 39.40 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.44 +pb_1c : 39.44 +pb_5c : 39.40 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.45 +pb_1c : 39.45 +pb_5c : 39.45 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.46 +pb_1c : 39.46 +pb_5c : 39.45 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.47 +pb_1c : 39.47 +pb_5c : 39.45 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.48 +pb_1c : 39.48 +pb_5c : 39.45 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.49 +pb_1c : 39.49 +pb_5c : 39.45 +pb_10c : 39.40 +pb_25c : 39.25 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.50 +pb_1c : 39.50 +pb_5c : 39.50 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.51 +pb_1c : 39.51 +pb_5c : 39.50 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.52 +pb_1c : 39.52 +pb_5c : 39.50 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.53 +pb_1c : 39.53 +pb_5c : 39.50 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.54 +pb_1c : 39.54 +pb_5c : 39.50 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.55 +pb_1c : 39.55 +pb_5c : 39.55 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.56 +pb_1c : 39.56 +pb_5c : 39.55 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.57 +pb_1c : 39.57 +pb_5c : 39.55 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.58 +pb_1c : 39.58 +pb_5c : 39.55 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.59 +pb_1c : 39.59 +pb_5c : 39.55 +pb_10c : 39.50 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.60 +pb_1c : 39.60 +pb_5c : 39.60 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.61 +pb_1c : 39.61 +pb_5c : 39.60 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.62 +pb_1c : 39.62 +pb_5c : 39.60 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.63 +pb_1c : 39.63 +pb_5c : 39.60 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.64 +pb_1c : 39.64 +pb_5c : 39.60 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.65 +pb_1c : 39.65 +pb_5c : 39.65 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.66 +pb_1c : 39.66 +pb_5c : 39.65 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.67 +pb_1c : 39.67 +pb_5c : 39.65 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.68 +pb_1c : 39.68 +pb_5c : 39.65 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.69 +pb_1c : 39.69 +pb_5c : 39.65 +pb_10c : 39.60 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.70 +pb_1c : 39.70 +pb_5c : 39.70 +pb_10c : 39.70 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.71 +pb_1c : 39.71 +pb_5c : 39.70 +pb_10c : 39.70 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.72 +pb_1c : 39.72 +pb_5c : 39.70 +pb_10c : 39.70 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.73 +pb_1c : 39.73 +pb_5c : 39.70 +pb_10c : 39.70 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.74 +pb_1c : 39.74 +pb_5c : 39.70 +pb_10c : 39.70 +pb_25c : 39.50 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.75 +pb_1c : 39.75 +pb_5c : 39.75 +pb_10c : 39.70 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.76 +pb_1c : 39.76 +pb_5c : 39.75 +pb_10c : 39.70 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.77 +pb_1c : 39.77 +pb_5c : 39.75 +pb_10c : 39.70 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.78 +pb_1c : 39.78 +pb_5c : 39.75 +pb_10c : 39.70 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.79 +pb_1c : 39.79 +pb_5c : 39.75 +pb_10c : 39.70 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.80 +pb_1c : 39.80 +pb_5c : 39.80 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.81 +pb_1c : 39.81 +pb_5c : 39.80 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.82 +pb_1c : 39.82 +pb_5c : 39.80 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.83 +pb_1c : 39.83 +pb_5c : 39.80 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.84 +pb_1c : 39.84 +pb_5c : 39.80 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.85 +pb_1c : 39.85 +pb_5c : 39.85 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.86 +pb_1c : 39.86 +pb_5c : 39.85 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.87 +pb_1c : 39.87 +pb_5c : 39.85 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.88 +pb_1c : 39.88 +pb_5c : 39.85 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.89 +pb_1c : 39.89 +pb_5c : 39.85 +pb_10c : 39.80 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.90 +pb_1c : 39.90 +pb_5c : 39.90 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.91 +pb_1c : 39.91 +pb_5c : 39.90 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.92 +pb_1c : 39.92 +pb_5c : 39.90 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.93 +pb_1c : 39.93 +pb_5c : 39.90 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.94 +pb_1c : 39.94 +pb_5c : 39.90 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.95 +pb_1c : 39.95 +pb_5c : 39.95 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.96 +pb_1c : 39.96 +pb_5c : 39.95 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.97 +pb_1c : 39.97 +pb_5c : 39.95 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.98 +pb_1c : 39.98 +pb_5c : 39.95 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +39.99 +pb_1c : 39.99 +pb_5c : 39.95 +pb_10c : 39.90 +pb_25c : 39.75 +pb_1d : 39.00 +pb_5d : 35.00 +pb_10d : 30.00 + +40.00 +pb_1c : 40.00 +pb_5c : 40.00 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.01 +pb_1c : 40.01 +pb_5c : 40.00 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.02 +pb_1c : 40.02 +pb_5c : 40.00 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.03 +pb_1c : 40.03 +pb_5c : 40.00 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.04 +pb_1c : 40.04 +pb_5c : 40.00 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.05 +pb_1c : 40.05 +pb_5c : 40.05 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.06 +pb_1c : 40.06 +pb_5c : 40.05 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.07 +pb_1c : 40.07 +pb_5c : 40.05 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.08 +pb_1c : 40.08 +pb_5c : 40.05 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.09 +pb_1c : 40.09 +pb_5c : 40.05 +pb_10c : 40.00 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.10 +pb_1c : 40.10 +pb_5c : 40.10 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.11 +pb_1c : 40.11 +pb_5c : 40.10 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.12 +pb_1c : 40.12 +pb_5c : 40.10 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.13 +pb_1c : 40.13 +pb_5c : 40.10 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.14 +pb_1c : 40.14 +pb_5c : 40.10 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.15 +pb_1c : 40.15 +pb_5c : 40.15 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.16 +pb_1c : 40.16 +pb_5c : 40.15 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.17 +pb_1c : 40.17 +pb_5c : 40.15 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.18 +pb_1c : 40.18 +pb_5c : 40.15 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.19 +pb_1c : 40.19 +pb_5c : 40.15 +pb_10c : 40.10 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.20 +pb_1c : 40.20 +pb_5c : 40.20 +pb_10c : 40.20 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.21 +pb_1c : 40.21 +pb_5c : 40.20 +pb_10c : 40.20 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.22 +pb_1c : 40.22 +pb_5c : 40.20 +pb_10c : 40.20 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.23 +pb_1c : 40.23 +pb_5c : 40.20 +pb_10c : 40.20 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.24 +pb_1c : 40.24 +pb_5c : 40.20 +pb_10c : 40.20 +pb_25c : 40.00 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.25 +pb_1c : 40.25 +pb_5c : 40.25 +pb_10c : 40.20 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.26 +pb_1c : 40.26 +pb_5c : 40.25 +pb_10c : 40.20 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.27 +pb_1c : 40.27 +pb_5c : 40.25 +pb_10c : 40.20 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.28 +pb_1c : 40.28 +pb_5c : 40.25 +pb_10c : 40.20 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.29 +pb_1c : 40.29 +pb_5c : 40.25 +pb_10c : 40.20 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.30 +pb_1c : 40.30 +pb_5c : 40.30 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.31 +pb_1c : 40.31 +pb_5c : 40.30 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.32 +pb_1c : 40.32 +pb_5c : 40.30 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.33 +pb_1c : 40.33 +pb_5c : 40.30 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.34 +pb_1c : 40.34 +pb_5c : 40.30 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.35 +pb_1c : 40.35 +pb_5c : 40.35 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.36 +pb_1c : 40.36 +pb_5c : 40.35 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.37 +pb_1c : 40.37 +pb_5c : 40.35 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.38 +pb_1c : 40.38 +pb_5c : 40.35 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.39 +pb_1c : 40.39 +pb_5c : 40.35 +pb_10c : 40.30 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.40 +pb_1c : 40.40 +pb_5c : 40.40 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.41 +pb_1c : 40.41 +pb_5c : 40.40 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.42 +pb_1c : 40.42 +pb_5c : 40.40 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.43 +pb_1c : 40.43 +pb_5c : 40.40 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.44 +pb_1c : 40.44 +pb_5c : 40.40 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.45 +pb_1c : 40.45 +pb_5c : 40.45 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.46 +pb_1c : 40.46 +pb_5c : 40.45 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.47 +pb_1c : 40.47 +pb_5c : 40.45 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.48 +pb_1c : 40.48 +pb_5c : 40.45 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.49 +pb_1c : 40.49 +pb_5c : 40.45 +pb_10c : 40.40 +pb_25c : 40.25 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.50 +pb_1c : 40.50 +pb_5c : 40.50 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.51 +pb_1c : 40.51 +pb_5c : 40.50 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.52 +pb_1c : 40.52 +pb_5c : 40.50 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.53 +pb_1c : 40.53 +pb_5c : 40.50 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.54 +pb_1c : 40.54 +pb_5c : 40.50 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.55 +pb_1c : 40.55 +pb_5c : 40.55 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.56 +pb_1c : 40.56 +pb_5c : 40.55 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.57 +pb_1c : 40.57 +pb_5c : 40.55 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.58 +pb_1c : 40.58 +pb_5c : 40.55 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.59 +pb_1c : 40.59 +pb_5c : 40.55 +pb_10c : 40.50 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.60 +pb_1c : 40.60 +pb_5c : 40.60 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.61 +pb_1c : 40.61 +pb_5c : 40.60 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.62 +pb_1c : 40.62 +pb_5c : 40.60 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.63 +pb_1c : 40.63 +pb_5c : 40.60 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.64 +pb_1c : 40.64 +pb_5c : 40.60 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.65 +pb_1c : 40.65 +pb_5c : 40.65 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.66 +pb_1c : 40.66 +pb_5c : 40.65 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.67 +pb_1c : 40.67 +pb_5c : 40.65 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.68 +pb_1c : 40.68 +pb_5c : 40.65 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.69 +pb_1c : 40.69 +pb_5c : 40.65 +pb_10c : 40.60 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.70 +pb_1c : 40.70 +pb_5c : 40.70 +pb_10c : 40.70 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.71 +pb_1c : 40.71 +pb_5c : 40.70 +pb_10c : 40.70 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.72 +pb_1c : 40.72 +pb_5c : 40.70 +pb_10c : 40.70 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.73 +pb_1c : 40.73 +pb_5c : 40.70 +pb_10c : 40.70 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.74 +pb_1c : 40.74 +pb_5c : 40.70 +pb_10c : 40.70 +pb_25c : 40.50 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.75 +pb_1c : 40.75 +pb_5c : 40.75 +pb_10c : 40.70 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.76 +pb_1c : 40.76 +pb_5c : 40.75 +pb_10c : 40.70 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.77 +pb_1c : 40.77 +pb_5c : 40.75 +pb_10c : 40.70 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.78 +pb_1c : 40.78 +pb_5c : 40.75 +pb_10c : 40.70 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.79 +pb_1c : 40.79 +pb_5c : 40.75 +pb_10c : 40.70 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.80 +pb_1c : 40.80 +pb_5c : 40.80 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.81 +pb_1c : 40.81 +pb_5c : 40.80 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.82 +pb_1c : 40.82 +pb_5c : 40.80 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.83 +pb_1c : 40.83 +pb_5c : 40.80 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.84 +pb_1c : 40.84 +pb_5c : 40.80 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.85 +pb_1c : 40.85 +pb_5c : 40.85 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.86 +pb_1c : 40.86 +pb_5c : 40.85 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.87 +pb_1c : 40.87 +pb_5c : 40.85 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.88 +pb_1c : 40.88 +pb_5c : 40.85 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.89 +pb_1c : 40.89 +pb_5c : 40.85 +pb_10c : 40.80 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.90 +pb_1c : 40.90 +pb_5c : 40.90 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.91 +pb_1c : 40.91 +pb_5c : 40.90 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.92 +pb_1c : 40.92 +pb_5c : 40.90 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.93 +pb_1c : 40.93 +pb_5c : 40.90 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.94 +pb_1c : 40.94 +pb_5c : 40.90 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.95 +pb_1c : 40.95 +pb_5c : 40.95 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.96 +pb_1c : 40.96 +pb_5c : 40.95 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.97 +pb_1c : 40.97 +pb_5c : 40.95 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.98 +pb_1c : 40.98 +pb_5c : 40.95 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +40.99 +pb_1c : 40.99 +pb_5c : 40.95 +pb_10c : 40.90 +pb_25c : 40.75 +pb_1d : 40.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.00 +pb_1c : 41.00 +pb_5c : 41.00 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.01 +pb_1c : 41.01 +pb_5c : 41.00 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.02 +pb_1c : 41.02 +pb_5c : 41.00 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.03 +pb_1c : 41.03 +pb_5c : 41.00 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.04 +pb_1c : 41.04 +pb_5c : 41.00 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.05 +pb_1c : 41.05 +pb_5c : 41.05 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.06 +pb_1c : 41.06 +pb_5c : 41.05 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.07 +pb_1c : 41.07 +pb_5c : 41.05 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.08 +pb_1c : 41.08 +pb_5c : 41.05 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.09 +pb_1c : 41.09 +pb_5c : 41.05 +pb_10c : 41.00 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.10 +pb_1c : 41.10 +pb_5c : 41.10 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.11 +pb_1c : 41.11 +pb_5c : 41.10 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.12 +pb_1c : 41.12 +pb_5c : 41.10 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.13 +pb_1c : 41.13 +pb_5c : 41.10 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.14 +pb_1c : 41.14 +pb_5c : 41.10 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.15 +pb_1c : 41.15 +pb_5c : 41.15 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.16 +pb_1c : 41.16 +pb_5c : 41.15 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.17 +pb_1c : 41.17 +pb_5c : 41.15 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.18 +pb_1c : 41.18 +pb_5c : 41.15 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.19 +pb_1c : 41.19 +pb_5c : 41.15 +pb_10c : 41.10 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.20 +pb_1c : 41.20 +pb_5c : 41.20 +pb_10c : 41.20 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.21 +pb_1c : 41.21 +pb_5c : 41.20 +pb_10c : 41.20 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.22 +pb_1c : 41.22 +pb_5c : 41.20 +pb_10c : 41.20 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.23 +pb_1c : 41.23 +pb_5c : 41.20 +pb_10c : 41.20 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.24 +pb_1c : 41.24 +pb_5c : 41.20 +pb_10c : 41.20 +pb_25c : 41.00 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.25 +pb_1c : 41.25 +pb_5c : 41.25 +pb_10c : 41.20 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.26 +pb_1c : 41.26 +pb_5c : 41.25 +pb_10c : 41.20 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.27 +pb_1c : 41.27 +pb_5c : 41.25 +pb_10c : 41.20 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.28 +pb_1c : 41.28 +pb_5c : 41.25 +pb_10c : 41.20 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.29 +pb_1c : 41.29 +pb_5c : 41.25 +pb_10c : 41.20 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.30 +pb_1c : 41.30 +pb_5c : 41.30 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.31 +pb_1c : 41.31 +pb_5c : 41.30 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.32 +pb_1c : 41.32 +pb_5c : 41.30 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.33 +pb_1c : 41.33 +pb_5c : 41.30 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.34 +pb_1c : 41.34 +pb_5c : 41.30 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.35 +pb_1c : 41.35 +pb_5c : 41.35 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.36 +pb_1c : 41.36 +pb_5c : 41.35 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.37 +pb_1c : 41.37 +pb_5c : 41.35 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.38 +pb_1c : 41.38 +pb_5c : 41.35 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.39 +pb_1c : 41.39 +pb_5c : 41.35 +pb_10c : 41.30 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.40 +pb_1c : 41.40 +pb_5c : 41.40 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.41 +pb_1c : 41.41 +pb_5c : 41.40 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.42 +pb_1c : 41.42 +pb_5c : 41.40 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.43 +pb_1c : 41.43 +pb_5c : 41.40 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.44 +pb_1c : 41.44 +pb_5c : 41.40 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.45 +pb_1c : 41.45 +pb_5c : 41.45 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.46 +pb_1c : 41.46 +pb_5c : 41.45 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.47 +pb_1c : 41.47 +pb_5c : 41.45 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.48 +pb_1c : 41.48 +pb_5c : 41.45 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.49 +pb_1c : 41.49 +pb_5c : 41.45 +pb_10c : 41.40 +pb_25c : 41.25 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.50 +pb_1c : 41.50 +pb_5c : 41.50 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.51 +pb_1c : 41.51 +pb_5c : 41.50 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.52 +pb_1c : 41.52 +pb_5c : 41.50 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.53 +pb_1c : 41.53 +pb_5c : 41.50 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.54 +pb_1c : 41.54 +pb_5c : 41.50 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.55 +pb_1c : 41.55 +pb_5c : 41.55 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.56 +pb_1c : 41.56 +pb_5c : 41.55 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.57 +pb_1c : 41.57 +pb_5c : 41.55 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.58 +pb_1c : 41.58 +pb_5c : 41.55 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.59 +pb_1c : 41.59 +pb_5c : 41.55 +pb_10c : 41.50 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.60 +pb_1c : 41.60 +pb_5c : 41.60 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.61 +pb_1c : 41.61 +pb_5c : 41.60 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.62 +pb_1c : 41.62 +pb_5c : 41.60 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.63 +pb_1c : 41.63 +pb_5c : 41.60 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.64 +pb_1c : 41.64 +pb_5c : 41.60 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.65 +pb_1c : 41.65 +pb_5c : 41.65 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.66 +pb_1c : 41.66 +pb_5c : 41.65 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.67 +pb_1c : 41.67 +pb_5c : 41.65 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.68 +pb_1c : 41.68 +pb_5c : 41.65 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.69 +pb_1c : 41.69 +pb_5c : 41.65 +pb_10c : 41.60 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.70 +pb_1c : 41.70 +pb_5c : 41.70 +pb_10c : 41.70 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.71 +pb_1c : 41.71 +pb_5c : 41.70 +pb_10c : 41.70 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.72 +pb_1c : 41.72 +pb_5c : 41.70 +pb_10c : 41.70 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.73 +pb_1c : 41.73 +pb_5c : 41.70 +pb_10c : 41.70 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.74 +pb_1c : 41.74 +pb_5c : 41.70 +pb_10c : 41.70 +pb_25c : 41.50 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.75 +pb_1c : 41.75 +pb_5c : 41.75 +pb_10c : 41.70 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.76 +pb_1c : 41.76 +pb_5c : 41.75 +pb_10c : 41.70 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.77 +pb_1c : 41.77 +pb_5c : 41.75 +pb_10c : 41.70 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.78 +pb_1c : 41.78 +pb_5c : 41.75 +pb_10c : 41.70 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.79 +pb_1c : 41.79 +pb_5c : 41.75 +pb_10c : 41.70 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.80 +pb_1c : 41.80 +pb_5c : 41.80 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.81 +pb_1c : 41.81 +pb_5c : 41.80 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.82 +pb_1c : 41.82 +pb_5c : 41.80 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.83 +pb_1c : 41.83 +pb_5c : 41.80 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.84 +pb_1c : 41.84 +pb_5c : 41.80 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.85 +pb_1c : 41.85 +pb_5c : 41.85 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.86 +pb_1c : 41.86 +pb_5c : 41.85 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.87 +pb_1c : 41.87 +pb_5c : 41.85 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.88 +pb_1c : 41.88 +pb_5c : 41.85 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.89 +pb_1c : 41.89 +pb_5c : 41.85 +pb_10c : 41.80 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.90 +pb_1c : 41.90 +pb_5c : 41.90 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.91 +pb_1c : 41.91 +pb_5c : 41.90 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.92 +pb_1c : 41.92 +pb_5c : 41.90 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.93 +pb_1c : 41.93 +pb_5c : 41.90 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.94 +pb_1c : 41.94 +pb_5c : 41.90 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.95 +pb_1c : 41.95 +pb_5c : 41.95 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.96 +pb_1c : 41.96 +pb_5c : 41.95 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.97 +pb_1c : 41.97 +pb_5c : 41.95 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.98 +pb_1c : 41.98 +pb_5c : 41.95 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +41.99 +pb_1c : 41.99 +pb_5c : 41.95 +pb_10c : 41.90 +pb_25c : 41.75 +pb_1d : 41.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.00 +pb_1c : 42.00 +pb_5c : 42.00 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.01 +pb_1c : 42.01 +pb_5c : 42.00 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.02 +pb_1c : 42.02 +pb_5c : 42.00 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.03 +pb_1c : 42.03 +pb_5c : 42.00 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.04 +pb_1c : 42.04 +pb_5c : 42.00 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.05 +pb_1c : 42.05 +pb_5c : 42.05 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.06 +pb_1c : 42.06 +pb_5c : 42.05 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.07 +pb_1c : 42.07 +pb_5c : 42.05 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.08 +pb_1c : 42.08 +pb_5c : 42.05 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.09 +pb_1c : 42.09 +pb_5c : 42.05 +pb_10c : 42.00 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.10 +pb_1c : 42.10 +pb_5c : 42.10 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.11 +pb_1c : 42.11 +pb_5c : 42.10 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.12 +pb_1c : 42.12 +pb_5c : 42.10 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.13 +pb_1c : 42.13 +pb_5c : 42.10 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.14 +pb_1c : 42.14 +pb_5c : 42.10 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.15 +pb_1c : 42.15 +pb_5c : 42.15 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.16 +pb_1c : 42.16 +pb_5c : 42.15 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.17 +pb_1c : 42.17 +pb_5c : 42.15 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.18 +pb_1c : 42.18 +pb_5c : 42.15 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.19 +pb_1c : 42.19 +pb_5c : 42.15 +pb_10c : 42.10 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.20 +pb_1c : 42.20 +pb_5c : 42.20 +pb_10c : 42.20 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.21 +pb_1c : 42.21 +pb_5c : 42.20 +pb_10c : 42.20 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.22 +pb_1c : 42.22 +pb_5c : 42.20 +pb_10c : 42.20 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.23 +pb_1c : 42.23 +pb_5c : 42.20 +pb_10c : 42.20 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.24 +pb_1c : 42.24 +pb_5c : 42.20 +pb_10c : 42.20 +pb_25c : 42.00 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.25 +pb_1c : 42.25 +pb_5c : 42.25 +pb_10c : 42.20 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.26 +pb_1c : 42.26 +pb_5c : 42.25 +pb_10c : 42.20 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.27 +pb_1c : 42.27 +pb_5c : 42.25 +pb_10c : 42.20 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.28 +pb_1c : 42.28 +pb_5c : 42.25 +pb_10c : 42.20 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.29 +pb_1c : 42.29 +pb_5c : 42.25 +pb_10c : 42.20 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.30 +pb_1c : 42.30 +pb_5c : 42.30 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.31 +pb_1c : 42.31 +pb_5c : 42.30 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.32 +pb_1c : 42.32 +pb_5c : 42.30 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.33 +pb_1c : 42.33 +pb_5c : 42.30 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.34 +pb_1c : 42.34 +pb_5c : 42.30 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.35 +pb_1c : 42.35 +pb_5c : 42.35 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.36 +pb_1c : 42.36 +pb_5c : 42.35 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.37 +pb_1c : 42.37 +pb_5c : 42.35 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.38 +pb_1c : 42.38 +pb_5c : 42.35 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.39 +pb_1c : 42.39 +pb_5c : 42.35 +pb_10c : 42.30 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.40 +pb_1c : 42.40 +pb_5c : 42.40 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.41 +pb_1c : 42.41 +pb_5c : 42.40 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.42 +pb_1c : 42.42 +pb_5c : 42.40 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.43 +pb_1c : 42.43 +pb_5c : 42.40 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.44 +pb_1c : 42.44 +pb_5c : 42.40 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.45 +pb_1c : 42.45 +pb_5c : 42.45 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.46 +pb_1c : 42.46 +pb_5c : 42.45 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.47 +pb_1c : 42.47 +pb_5c : 42.45 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.48 +pb_1c : 42.48 +pb_5c : 42.45 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.49 +pb_1c : 42.49 +pb_5c : 42.45 +pb_10c : 42.40 +pb_25c : 42.25 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.50 +pb_1c : 42.50 +pb_5c : 42.50 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.51 +pb_1c : 42.51 +pb_5c : 42.50 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.52 +pb_1c : 42.52 +pb_5c : 42.50 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.53 +pb_1c : 42.53 +pb_5c : 42.50 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.54 +pb_1c : 42.54 +pb_5c : 42.50 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.55 +pb_1c : 42.55 +pb_5c : 42.55 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.56 +pb_1c : 42.56 +pb_5c : 42.55 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.57 +pb_1c : 42.57 +pb_5c : 42.55 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.58 +pb_1c : 42.58 +pb_5c : 42.55 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.59 +pb_1c : 42.59 +pb_5c : 42.55 +pb_10c : 42.50 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.60 +pb_1c : 42.60 +pb_5c : 42.60 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.61 +pb_1c : 42.61 +pb_5c : 42.60 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.62 +pb_1c : 42.62 +pb_5c : 42.60 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.63 +pb_1c : 42.63 +pb_5c : 42.60 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.64 +pb_1c : 42.64 +pb_5c : 42.60 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.65 +pb_1c : 42.65 +pb_5c : 42.65 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.66 +pb_1c : 42.66 +pb_5c : 42.65 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.67 +pb_1c : 42.67 +pb_5c : 42.65 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.68 +pb_1c : 42.68 +pb_5c : 42.65 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.69 +pb_1c : 42.69 +pb_5c : 42.65 +pb_10c : 42.60 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.70 +pb_1c : 42.70 +pb_5c : 42.70 +pb_10c : 42.70 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.71 +pb_1c : 42.71 +pb_5c : 42.70 +pb_10c : 42.70 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.72 +pb_1c : 42.72 +pb_5c : 42.70 +pb_10c : 42.70 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.73 +pb_1c : 42.73 +pb_5c : 42.70 +pb_10c : 42.70 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.74 +pb_1c : 42.74 +pb_5c : 42.70 +pb_10c : 42.70 +pb_25c : 42.50 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.75 +pb_1c : 42.75 +pb_5c : 42.75 +pb_10c : 42.70 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.76 +pb_1c : 42.76 +pb_5c : 42.75 +pb_10c : 42.70 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.77 +pb_1c : 42.77 +pb_5c : 42.75 +pb_10c : 42.70 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.78 +pb_1c : 42.78 +pb_5c : 42.75 +pb_10c : 42.70 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.79 +pb_1c : 42.79 +pb_5c : 42.75 +pb_10c : 42.70 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.80 +pb_1c : 42.80 +pb_5c : 42.80 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.81 +pb_1c : 42.81 +pb_5c : 42.80 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.82 +pb_1c : 42.82 +pb_5c : 42.80 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.83 +pb_1c : 42.83 +pb_5c : 42.80 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.84 +pb_1c : 42.84 +pb_5c : 42.80 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.85 +pb_1c : 42.85 +pb_5c : 42.85 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.86 +pb_1c : 42.86 +pb_5c : 42.85 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.87 +pb_1c : 42.87 +pb_5c : 42.85 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.88 +pb_1c : 42.88 +pb_5c : 42.85 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.89 +pb_1c : 42.89 +pb_5c : 42.85 +pb_10c : 42.80 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.90 +pb_1c : 42.90 +pb_5c : 42.90 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.91 +pb_1c : 42.91 +pb_5c : 42.90 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.92 +pb_1c : 42.92 +pb_5c : 42.90 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.93 +pb_1c : 42.93 +pb_5c : 42.90 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.94 +pb_1c : 42.94 +pb_5c : 42.90 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.95 +pb_1c : 42.95 +pb_5c : 42.95 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.96 +pb_1c : 42.96 +pb_5c : 42.95 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.97 +pb_1c : 42.97 +pb_5c : 42.95 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.98 +pb_1c : 42.98 +pb_5c : 42.95 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +42.99 +pb_1c : 42.99 +pb_5c : 42.95 +pb_10c : 42.90 +pb_25c : 42.75 +pb_1d : 42.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.00 +pb_1c : 43.00 +pb_5c : 43.00 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.01 +pb_1c : 43.01 +pb_5c : 43.00 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.02 +pb_1c : 43.02 +pb_5c : 43.00 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.03 +pb_1c : 43.03 +pb_5c : 43.00 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.04 +pb_1c : 43.04 +pb_5c : 43.00 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.05 +pb_1c : 43.05 +pb_5c : 43.05 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.06 +pb_1c : 43.06 +pb_5c : 43.05 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.07 +pb_1c : 43.07 +pb_5c : 43.05 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.08 +pb_1c : 43.08 +pb_5c : 43.05 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.09 +pb_1c : 43.09 +pb_5c : 43.05 +pb_10c : 43.00 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.10 +pb_1c : 43.10 +pb_5c : 43.10 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.11 +pb_1c : 43.11 +pb_5c : 43.10 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.12 +pb_1c : 43.12 +pb_5c : 43.10 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.13 +pb_1c : 43.13 +pb_5c : 43.10 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.14 +pb_1c : 43.14 +pb_5c : 43.10 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.15 +pb_1c : 43.15 +pb_5c : 43.15 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.16 +pb_1c : 43.16 +pb_5c : 43.15 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.17 +pb_1c : 43.17 +pb_5c : 43.15 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.18 +pb_1c : 43.18 +pb_5c : 43.15 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.19 +pb_1c : 43.19 +pb_5c : 43.15 +pb_10c : 43.10 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.20 +pb_1c : 43.20 +pb_5c : 43.20 +pb_10c : 43.20 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.21 +pb_1c : 43.21 +pb_5c : 43.20 +pb_10c : 43.20 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.22 +pb_1c : 43.22 +pb_5c : 43.20 +pb_10c : 43.20 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.23 +pb_1c : 43.23 +pb_5c : 43.20 +pb_10c : 43.20 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.24 +pb_1c : 43.24 +pb_5c : 43.20 +pb_10c : 43.20 +pb_25c : 43.00 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.25 +pb_1c : 43.25 +pb_5c : 43.25 +pb_10c : 43.20 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.26 +pb_1c : 43.26 +pb_5c : 43.25 +pb_10c : 43.20 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.27 +pb_1c : 43.27 +pb_5c : 43.25 +pb_10c : 43.20 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.28 +pb_1c : 43.28 +pb_5c : 43.25 +pb_10c : 43.20 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.29 +pb_1c : 43.29 +pb_5c : 43.25 +pb_10c : 43.20 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.30 +pb_1c : 43.30 +pb_5c : 43.30 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.31 +pb_1c : 43.31 +pb_5c : 43.30 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.32 +pb_1c : 43.32 +pb_5c : 43.30 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.33 +pb_1c : 43.33 +pb_5c : 43.30 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.34 +pb_1c : 43.34 +pb_5c : 43.30 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.35 +pb_1c : 43.35 +pb_5c : 43.35 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.36 +pb_1c : 43.36 +pb_5c : 43.35 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.37 +pb_1c : 43.37 +pb_5c : 43.35 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.38 +pb_1c : 43.38 +pb_5c : 43.35 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.39 +pb_1c : 43.39 +pb_5c : 43.35 +pb_10c : 43.30 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.40 +pb_1c : 43.40 +pb_5c : 43.40 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.41 +pb_1c : 43.41 +pb_5c : 43.40 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.42 +pb_1c : 43.42 +pb_5c : 43.40 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.43 +pb_1c : 43.43 +pb_5c : 43.40 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.44 +pb_1c : 43.44 +pb_5c : 43.40 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.45 +pb_1c : 43.45 +pb_5c : 43.45 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.46 +pb_1c : 43.46 +pb_5c : 43.45 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.47 +pb_1c : 43.47 +pb_5c : 43.45 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.48 +pb_1c : 43.48 +pb_5c : 43.45 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.49 +pb_1c : 43.49 +pb_5c : 43.45 +pb_10c : 43.40 +pb_25c : 43.25 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.50 +pb_1c : 43.50 +pb_5c : 43.50 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.51 +pb_1c : 43.51 +pb_5c : 43.50 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.52 +pb_1c : 43.52 +pb_5c : 43.50 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.53 +pb_1c : 43.53 +pb_5c : 43.50 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.54 +pb_1c : 43.54 +pb_5c : 43.50 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.55 +pb_1c : 43.55 +pb_5c : 43.55 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.56 +pb_1c : 43.56 +pb_5c : 43.55 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.57 +pb_1c : 43.57 +pb_5c : 43.55 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.58 +pb_1c : 43.58 +pb_5c : 43.55 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.59 +pb_1c : 43.59 +pb_5c : 43.55 +pb_10c : 43.50 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.60 +pb_1c : 43.60 +pb_5c : 43.60 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.61 +pb_1c : 43.61 +pb_5c : 43.60 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.62 +pb_1c : 43.62 +pb_5c : 43.60 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.63 +pb_1c : 43.63 +pb_5c : 43.60 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.64 +pb_1c : 43.64 +pb_5c : 43.60 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.65 +pb_1c : 43.65 +pb_5c : 43.65 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.66 +pb_1c : 43.66 +pb_5c : 43.65 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.67 +pb_1c : 43.67 +pb_5c : 43.65 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.68 +pb_1c : 43.68 +pb_5c : 43.65 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.69 +pb_1c : 43.69 +pb_5c : 43.65 +pb_10c : 43.60 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.70 +pb_1c : 43.70 +pb_5c : 43.70 +pb_10c : 43.70 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.71 +pb_1c : 43.71 +pb_5c : 43.70 +pb_10c : 43.70 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.72 +pb_1c : 43.72 +pb_5c : 43.70 +pb_10c : 43.70 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.73 +pb_1c : 43.73 +pb_5c : 43.70 +pb_10c : 43.70 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.74 +pb_1c : 43.74 +pb_5c : 43.70 +pb_10c : 43.70 +pb_25c : 43.50 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.75 +pb_1c : 43.75 +pb_5c : 43.75 +pb_10c : 43.70 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.76 +pb_1c : 43.76 +pb_5c : 43.75 +pb_10c : 43.70 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.77 +pb_1c : 43.77 +pb_5c : 43.75 +pb_10c : 43.70 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.78 +pb_1c : 43.78 +pb_5c : 43.75 +pb_10c : 43.70 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.79 +pb_1c : 43.79 +pb_5c : 43.75 +pb_10c : 43.70 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.80 +pb_1c : 43.80 +pb_5c : 43.80 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.81 +pb_1c : 43.81 +pb_5c : 43.80 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.82 +pb_1c : 43.82 +pb_5c : 43.80 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.83 +pb_1c : 43.83 +pb_5c : 43.80 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.84 +pb_1c : 43.84 +pb_5c : 43.80 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.85 +pb_1c : 43.85 +pb_5c : 43.85 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.86 +pb_1c : 43.86 +pb_5c : 43.85 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.87 +pb_1c : 43.87 +pb_5c : 43.85 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.88 +pb_1c : 43.88 +pb_5c : 43.85 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.89 +pb_1c : 43.89 +pb_5c : 43.85 +pb_10c : 43.80 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.90 +pb_1c : 43.90 +pb_5c : 43.90 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.91 +pb_1c : 43.91 +pb_5c : 43.90 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.92 +pb_1c : 43.92 +pb_5c : 43.90 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.93 +pb_1c : 43.93 +pb_5c : 43.90 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.94 +pb_1c : 43.94 +pb_5c : 43.90 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.95 +pb_1c : 43.95 +pb_5c : 43.95 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.96 +pb_1c : 43.96 +pb_5c : 43.95 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.97 +pb_1c : 43.97 +pb_5c : 43.95 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.98 +pb_1c : 43.98 +pb_5c : 43.95 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +43.99 +pb_1c : 43.99 +pb_5c : 43.95 +pb_10c : 43.90 +pb_25c : 43.75 +pb_1d : 43.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.00 +pb_1c : 44.00 +pb_5c : 44.00 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.01 +pb_1c : 44.01 +pb_5c : 44.00 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.02 +pb_1c : 44.02 +pb_5c : 44.00 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.03 +pb_1c : 44.03 +pb_5c : 44.00 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.04 +pb_1c : 44.04 +pb_5c : 44.00 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.05 +pb_1c : 44.05 +pb_5c : 44.05 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.06 +pb_1c : 44.06 +pb_5c : 44.05 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.07 +pb_1c : 44.07 +pb_5c : 44.05 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.08 +pb_1c : 44.08 +pb_5c : 44.05 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.09 +pb_1c : 44.09 +pb_5c : 44.05 +pb_10c : 44.00 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.10 +pb_1c : 44.10 +pb_5c : 44.10 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.11 +pb_1c : 44.11 +pb_5c : 44.10 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.12 +pb_1c : 44.12 +pb_5c : 44.10 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.13 +pb_1c : 44.13 +pb_5c : 44.10 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.14 +pb_1c : 44.14 +pb_5c : 44.10 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.15 +pb_1c : 44.15 +pb_5c : 44.15 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.16 +pb_1c : 44.16 +pb_5c : 44.15 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.17 +pb_1c : 44.17 +pb_5c : 44.15 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.18 +pb_1c : 44.18 +pb_5c : 44.15 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.19 +pb_1c : 44.19 +pb_5c : 44.15 +pb_10c : 44.10 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.20 +pb_1c : 44.20 +pb_5c : 44.20 +pb_10c : 44.20 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.21 +pb_1c : 44.21 +pb_5c : 44.20 +pb_10c : 44.20 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.22 +pb_1c : 44.22 +pb_5c : 44.20 +pb_10c : 44.20 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.23 +pb_1c : 44.23 +pb_5c : 44.20 +pb_10c : 44.20 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.24 +pb_1c : 44.24 +pb_5c : 44.20 +pb_10c : 44.20 +pb_25c : 44.00 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.25 +pb_1c : 44.25 +pb_5c : 44.25 +pb_10c : 44.20 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.26 +pb_1c : 44.26 +pb_5c : 44.25 +pb_10c : 44.20 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.27 +pb_1c : 44.27 +pb_5c : 44.25 +pb_10c : 44.20 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.28 +pb_1c : 44.28 +pb_5c : 44.25 +pb_10c : 44.20 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.29 +pb_1c : 44.29 +pb_5c : 44.25 +pb_10c : 44.20 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.30 +pb_1c : 44.30 +pb_5c : 44.30 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.31 +pb_1c : 44.31 +pb_5c : 44.30 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.32 +pb_1c : 44.32 +pb_5c : 44.30 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.33 +pb_1c : 44.33 +pb_5c : 44.30 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.34 +pb_1c : 44.34 +pb_5c : 44.30 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.35 +pb_1c : 44.35 +pb_5c : 44.35 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.36 +pb_1c : 44.36 +pb_5c : 44.35 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.37 +pb_1c : 44.37 +pb_5c : 44.35 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.38 +pb_1c : 44.38 +pb_5c : 44.35 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.39 +pb_1c : 44.39 +pb_5c : 44.35 +pb_10c : 44.30 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.40 +pb_1c : 44.40 +pb_5c : 44.40 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.41 +pb_1c : 44.41 +pb_5c : 44.40 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.42 +pb_1c : 44.42 +pb_5c : 44.40 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.43 +pb_1c : 44.43 +pb_5c : 44.40 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.44 +pb_1c : 44.44 +pb_5c : 44.40 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.45 +pb_1c : 44.45 +pb_5c : 44.45 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.46 +pb_1c : 44.46 +pb_5c : 44.45 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.47 +pb_1c : 44.47 +pb_5c : 44.45 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.48 +pb_1c : 44.48 +pb_5c : 44.45 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.49 +pb_1c : 44.49 +pb_5c : 44.45 +pb_10c : 44.40 +pb_25c : 44.25 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.50 +pb_1c : 44.50 +pb_5c : 44.50 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.51 +pb_1c : 44.51 +pb_5c : 44.50 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.52 +pb_1c : 44.52 +pb_5c : 44.50 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.53 +pb_1c : 44.53 +pb_5c : 44.50 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.54 +pb_1c : 44.54 +pb_5c : 44.50 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.55 +pb_1c : 44.55 +pb_5c : 44.55 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.56 +pb_1c : 44.56 +pb_5c : 44.55 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.57 +pb_1c : 44.57 +pb_5c : 44.55 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.58 +pb_1c : 44.58 +pb_5c : 44.55 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.59 +pb_1c : 44.59 +pb_5c : 44.55 +pb_10c : 44.50 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.60 +pb_1c : 44.60 +pb_5c : 44.60 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.61 +pb_1c : 44.61 +pb_5c : 44.60 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.62 +pb_1c : 44.62 +pb_5c : 44.60 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.63 +pb_1c : 44.63 +pb_5c : 44.60 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.64 +pb_1c : 44.64 +pb_5c : 44.60 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.65 +pb_1c : 44.65 +pb_5c : 44.65 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.66 +pb_1c : 44.66 +pb_5c : 44.65 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.67 +pb_1c : 44.67 +pb_5c : 44.65 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.68 +pb_1c : 44.68 +pb_5c : 44.65 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.69 +pb_1c : 44.69 +pb_5c : 44.65 +pb_10c : 44.60 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.70 +pb_1c : 44.70 +pb_5c : 44.70 +pb_10c : 44.70 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.71 +pb_1c : 44.71 +pb_5c : 44.70 +pb_10c : 44.70 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.72 +pb_1c : 44.72 +pb_5c : 44.70 +pb_10c : 44.70 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.73 +pb_1c : 44.73 +pb_5c : 44.70 +pb_10c : 44.70 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.74 +pb_1c : 44.74 +pb_5c : 44.70 +pb_10c : 44.70 +pb_25c : 44.50 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.75 +pb_1c : 44.75 +pb_5c : 44.75 +pb_10c : 44.70 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.76 +pb_1c : 44.76 +pb_5c : 44.75 +pb_10c : 44.70 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.77 +pb_1c : 44.77 +pb_5c : 44.75 +pb_10c : 44.70 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.78 +pb_1c : 44.78 +pb_5c : 44.75 +pb_10c : 44.70 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.79 +pb_1c : 44.79 +pb_5c : 44.75 +pb_10c : 44.70 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.80 +pb_1c : 44.80 +pb_5c : 44.80 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.81 +pb_1c : 44.81 +pb_5c : 44.80 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.82 +pb_1c : 44.82 +pb_5c : 44.80 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.83 +pb_1c : 44.83 +pb_5c : 44.80 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.84 +pb_1c : 44.84 +pb_5c : 44.80 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.85 +pb_1c : 44.85 +pb_5c : 44.85 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.86 +pb_1c : 44.86 +pb_5c : 44.85 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.87 +pb_1c : 44.87 +pb_5c : 44.85 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.88 +pb_1c : 44.88 +pb_5c : 44.85 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.89 +pb_1c : 44.89 +pb_5c : 44.85 +pb_10c : 44.80 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.90 +pb_1c : 44.90 +pb_5c : 44.90 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.91 +pb_1c : 44.91 +pb_5c : 44.90 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.92 +pb_1c : 44.92 +pb_5c : 44.90 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.93 +pb_1c : 44.93 +pb_5c : 44.90 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.94 +pb_1c : 44.94 +pb_5c : 44.90 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.95 +pb_1c : 44.95 +pb_5c : 44.95 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.96 +pb_1c : 44.96 +pb_5c : 44.95 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.97 +pb_1c : 44.97 +pb_5c : 44.95 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.98 +pb_1c : 44.98 +pb_5c : 44.95 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +44.99 +pb_1c : 44.99 +pb_5c : 44.95 +pb_10c : 44.90 +pb_25c : 44.75 +pb_1d : 44.00 +pb_5d : 40.00 +pb_10d : 40.00 + +45.00 +pb_1c : 45.00 +pb_5c : 45.00 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.01 +pb_1c : 45.01 +pb_5c : 45.00 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.02 +pb_1c : 45.02 +pb_5c : 45.00 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.03 +pb_1c : 45.03 +pb_5c : 45.00 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.04 +pb_1c : 45.04 +pb_5c : 45.00 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.05 +pb_1c : 45.05 +pb_5c : 45.05 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.06 +pb_1c : 45.06 +pb_5c : 45.05 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.07 +pb_1c : 45.07 +pb_5c : 45.05 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.08 +pb_1c : 45.08 +pb_5c : 45.05 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.09 +pb_1c : 45.09 +pb_5c : 45.05 +pb_10c : 45.00 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.10 +pb_1c : 45.10 +pb_5c : 45.10 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.11 +pb_1c : 45.11 +pb_5c : 45.10 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.12 +pb_1c : 45.12 +pb_5c : 45.10 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.13 +pb_1c : 45.13 +pb_5c : 45.10 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.14 +pb_1c : 45.14 +pb_5c : 45.10 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.15 +pb_1c : 45.15 +pb_5c : 45.15 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.16 +pb_1c : 45.16 +pb_5c : 45.15 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.17 +pb_1c : 45.17 +pb_5c : 45.15 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.18 +pb_1c : 45.18 +pb_5c : 45.15 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.19 +pb_1c : 45.19 +pb_5c : 45.15 +pb_10c : 45.10 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.20 +pb_1c : 45.20 +pb_5c : 45.20 +pb_10c : 45.20 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.21 +pb_1c : 45.21 +pb_5c : 45.20 +pb_10c : 45.20 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.22 +pb_1c : 45.22 +pb_5c : 45.20 +pb_10c : 45.20 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.23 +pb_1c : 45.23 +pb_5c : 45.20 +pb_10c : 45.20 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.24 +pb_1c : 45.24 +pb_5c : 45.20 +pb_10c : 45.20 +pb_25c : 45.00 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.25 +pb_1c : 45.25 +pb_5c : 45.25 +pb_10c : 45.20 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.26 +pb_1c : 45.26 +pb_5c : 45.25 +pb_10c : 45.20 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.27 +pb_1c : 45.27 +pb_5c : 45.25 +pb_10c : 45.20 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.28 +pb_1c : 45.28 +pb_5c : 45.25 +pb_10c : 45.20 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.29 +pb_1c : 45.29 +pb_5c : 45.25 +pb_10c : 45.20 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.30 +pb_1c : 45.30 +pb_5c : 45.30 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.31 +pb_1c : 45.31 +pb_5c : 45.30 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.32 +pb_1c : 45.32 +pb_5c : 45.30 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.33 +pb_1c : 45.33 +pb_5c : 45.30 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.34 +pb_1c : 45.34 +pb_5c : 45.30 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.35 +pb_1c : 45.35 +pb_5c : 45.35 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.36 +pb_1c : 45.36 +pb_5c : 45.35 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.37 +pb_1c : 45.37 +pb_5c : 45.35 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.38 +pb_1c : 45.38 +pb_5c : 45.35 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.39 +pb_1c : 45.39 +pb_5c : 45.35 +pb_10c : 45.30 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.40 +pb_1c : 45.40 +pb_5c : 45.40 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.41 +pb_1c : 45.41 +pb_5c : 45.40 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.42 +pb_1c : 45.42 +pb_5c : 45.40 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.43 +pb_1c : 45.43 +pb_5c : 45.40 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.44 +pb_1c : 45.44 +pb_5c : 45.40 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.45 +pb_1c : 45.45 +pb_5c : 45.45 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.46 +pb_1c : 45.46 +pb_5c : 45.45 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.47 +pb_1c : 45.47 +pb_5c : 45.45 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.48 +pb_1c : 45.48 +pb_5c : 45.45 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.49 +pb_1c : 45.49 +pb_5c : 45.45 +pb_10c : 45.40 +pb_25c : 45.25 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.50 +pb_1c : 45.50 +pb_5c : 45.50 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.51 +pb_1c : 45.51 +pb_5c : 45.50 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.52 +pb_1c : 45.52 +pb_5c : 45.50 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.53 +pb_1c : 45.53 +pb_5c : 45.50 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.54 +pb_1c : 45.54 +pb_5c : 45.50 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.55 +pb_1c : 45.55 +pb_5c : 45.55 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.56 +pb_1c : 45.56 +pb_5c : 45.55 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.57 +pb_1c : 45.57 +pb_5c : 45.55 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.58 +pb_1c : 45.58 +pb_5c : 45.55 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.59 +pb_1c : 45.59 +pb_5c : 45.55 +pb_10c : 45.50 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.60 +pb_1c : 45.60 +pb_5c : 45.60 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.61 +pb_1c : 45.61 +pb_5c : 45.60 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.62 +pb_1c : 45.62 +pb_5c : 45.60 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.63 +pb_1c : 45.63 +pb_5c : 45.60 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.64 +pb_1c : 45.64 +pb_5c : 45.60 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.65 +pb_1c : 45.65 +pb_5c : 45.65 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.66 +pb_1c : 45.66 +pb_5c : 45.65 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.67 +pb_1c : 45.67 +pb_5c : 45.65 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.68 +pb_1c : 45.68 +pb_5c : 45.65 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.69 +pb_1c : 45.69 +pb_5c : 45.65 +pb_10c : 45.60 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.70 +pb_1c : 45.70 +pb_5c : 45.70 +pb_10c : 45.70 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.71 +pb_1c : 45.71 +pb_5c : 45.70 +pb_10c : 45.70 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.72 +pb_1c : 45.72 +pb_5c : 45.70 +pb_10c : 45.70 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.73 +pb_1c : 45.73 +pb_5c : 45.70 +pb_10c : 45.70 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.74 +pb_1c : 45.74 +pb_5c : 45.70 +pb_10c : 45.70 +pb_25c : 45.50 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.75 +pb_1c : 45.75 +pb_5c : 45.75 +pb_10c : 45.70 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.76 +pb_1c : 45.76 +pb_5c : 45.75 +pb_10c : 45.70 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.77 +pb_1c : 45.77 +pb_5c : 45.75 +pb_10c : 45.70 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.78 +pb_1c : 45.78 +pb_5c : 45.75 +pb_10c : 45.70 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.79 +pb_1c : 45.79 +pb_5c : 45.75 +pb_10c : 45.70 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.80 +pb_1c : 45.80 +pb_5c : 45.80 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.81 +pb_1c : 45.81 +pb_5c : 45.80 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.82 +pb_1c : 45.82 +pb_5c : 45.80 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.83 +pb_1c : 45.83 +pb_5c : 45.80 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.84 +pb_1c : 45.84 +pb_5c : 45.80 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.85 +pb_1c : 45.85 +pb_5c : 45.85 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.86 +pb_1c : 45.86 +pb_5c : 45.85 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.87 +pb_1c : 45.87 +pb_5c : 45.85 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.88 +pb_1c : 45.88 +pb_5c : 45.85 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.89 +pb_1c : 45.89 +pb_5c : 45.85 +pb_10c : 45.80 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.90 +pb_1c : 45.90 +pb_5c : 45.90 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.91 +pb_1c : 45.91 +pb_5c : 45.90 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.92 +pb_1c : 45.92 +pb_5c : 45.90 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.93 +pb_1c : 45.93 +pb_5c : 45.90 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.94 +pb_1c : 45.94 +pb_5c : 45.90 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.95 +pb_1c : 45.95 +pb_5c : 45.95 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.96 +pb_1c : 45.96 +pb_5c : 45.95 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.97 +pb_1c : 45.97 +pb_5c : 45.95 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.98 +pb_1c : 45.98 +pb_5c : 45.95 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +45.99 +pb_1c : 45.99 +pb_5c : 45.95 +pb_10c : 45.90 +pb_25c : 45.75 +pb_1d : 45.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.00 +pb_1c : 46.00 +pb_5c : 46.00 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.01 +pb_1c : 46.01 +pb_5c : 46.00 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.02 +pb_1c : 46.02 +pb_5c : 46.00 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.03 +pb_1c : 46.03 +pb_5c : 46.00 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.04 +pb_1c : 46.04 +pb_5c : 46.00 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.05 +pb_1c : 46.05 +pb_5c : 46.05 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.06 +pb_1c : 46.06 +pb_5c : 46.05 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.07 +pb_1c : 46.07 +pb_5c : 46.05 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.08 +pb_1c : 46.08 +pb_5c : 46.05 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.09 +pb_1c : 46.09 +pb_5c : 46.05 +pb_10c : 46.00 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.10 +pb_1c : 46.10 +pb_5c : 46.10 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.11 +pb_1c : 46.11 +pb_5c : 46.10 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.12 +pb_1c : 46.12 +pb_5c : 46.10 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.13 +pb_1c : 46.13 +pb_5c : 46.10 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.14 +pb_1c : 46.14 +pb_5c : 46.10 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.15 +pb_1c : 46.15 +pb_5c : 46.15 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.16 +pb_1c : 46.16 +pb_5c : 46.15 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.17 +pb_1c : 46.17 +pb_5c : 46.15 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.18 +pb_1c : 46.18 +pb_5c : 46.15 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.19 +pb_1c : 46.19 +pb_5c : 46.15 +pb_10c : 46.10 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.20 +pb_1c : 46.20 +pb_5c : 46.20 +pb_10c : 46.20 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.21 +pb_1c : 46.21 +pb_5c : 46.20 +pb_10c : 46.20 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.22 +pb_1c : 46.22 +pb_5c : 46.20 +pb_10c : 46.20 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.23 +pb_1c : 46.23 +pb_5c : 46.20 +pb_10c : 46.20 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.24 +pb_1c : 46.24 +pb_5c : 46.20 +pb_10c : 46.20 +pb_25c : 46.00 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.25 +pb_1c : 46.25 +pb_5c : 46.25 +pb_10c : 46.20 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.26 +pb_1c : 46.26 +pb_5c : 46.25 +pb_10c : 46.20 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.27 +pb_1c : 46.27 +pb_5c : 46.25 +pb_10c : 46.20 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.28 +pb_1c : 46.28 +pb_5c : 46.25 +pb_10c : 46.20 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.29 +pb_1c : 46.29 +pb_5c : 46.25 +pb_10c : 46.20 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.30 +pb_1c : 46.30 +pb_5c : 46.30 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.31 +pb_1c : 46.31 +pb_5c : 46.30 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.32 +pb_1c : 46.32 +pb_5c : 46.30 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.33 +pb_1c : 46.33 +pb_5c : 46.30 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.34 +pb_1c : 46.34 +pb_5c : 46.30 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.35 +pb_1c : 46.35 +pb_5c : 46.35 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.36 +pb_1c : 46.36 +pb_5c : 46.35 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.37 +pb_1c : 46.37 +pb_5c : 46.35 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.38 +pb_1c : 46.38 +pb_5c : 46.35 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.39 +pb_1c : 46.39 +pb_5c : 46.35 +pb_10c : 46.30 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.40 +pb_1c : 46.40 +pb_5c : 46.40 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.41 +pb_1c : 46.41 +pb_5c : 46.40 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.42 +pb_1c : 46.42 +pb_5c : 46.40 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.43 +pb_1c : 46.43 +pb_5c : 46.40 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.44 +pb_1c : 46.44 +pb_5c : 46.40 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.45 +pb_1c : 46.45 +pb_5c : 46.45 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.46 +pb_1c : 46.46 +pb_5c : 46.45 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.47 +pb_1c : 46.47 +pb_5c : 46.45 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.48 +pb_1c : 46.48 +pb_5c : 46.45 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.49 +pb_1c : 46.49 +pb_5c : 46.45 +pb_10c : 46.40 +pb_25c : 46.25 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.50 +pb_1c : 46.50 +pb_5c : 46.50 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.51 +pb_1c : 46.51 +pb_5c : 46.50 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.52 +pb_1c : 46.52 +pb_5c : 46.50 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.53 +pb_1c : 46.53 +pb_5c : 46.50 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.54 +pb_1c : 46.54 +pb_5c : 46.50 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.55 +pb_1c : 46.55 +pb_5c : 46.55 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.56 +pb_1c : 46.56 +pb_5c : 46.55 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.57 +pb_1c : 46.57 +pb_5c : 46.55 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.58 +pb_1c : 46.58 +pb_5c : 46.55 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.59 +pb_1c : 46.59 +pb_5c : 46.55 +pb_10c : 46.50 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.60 +pb_1c : 46.60 +pb_5c : 46.60 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.61 +pb_1c : 46.61 +pb_5c : 46.60 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.62 +pb_1c : 46.62 +pb_5c : 46.60 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.63 +pb_1c : 46.63 +pb_5c : 46.60 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.64 +pb_1c : 46.64 +pb_5c : 46.60 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.65 +pb_1c : 46.65 +pb_5c : 46.65 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.66 +pb_1c : 46.66 +pb_5c : 46.65 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.67 +pb_1c : 46.67 +pb_5c : 46.65 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.68 +pb_1c : 46.68 +pb_5c : 46.65 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.69 +pb_1c : 46.69 +pb_5c : 46.65 +pb_10c : 46.60 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.70 +pb_1c : 46.70 +pb_5c : 46.70 +pb_10c : 46.70 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.71 +pb_1c : 46.71 +pb_5c : 46.70 +pb_10c : 46.70 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.72 +pb_1c : 46.72 +pb_5c : 46.70 +pb_10c : 46.70 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.73 +pb_1c : 46.73 +pb_5c : 46.70 +pb_10c : 46.70 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.74 +pb_1c : 46.74 +pb_5c : 46.70 +pb_10c : 46.70 +pb_25c : 46.50 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.75 +pb_1c : 46.75 +pb_5c : 46.75 +pb_10c : 46.70 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.76 +pb_1c : 46.76 +pb_5c : 46.75 +pb_10c : 46.70 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.77 +pb_1c : 46.77 +pb_5c : 46.75 +pb_10c : 46.70 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.78 +pb_1c : 46.78 +pb_5c : 46.75 +pb_10c : 46.70 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.79 +pb_1c : 46.79 +pb_5c : 46.75 +pb_10c : 46.70 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.80 +pb_1c : 46.80 +pb_5c : 46.80 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.81 +pb_1c : 46.81 +pb_5c : 46.80 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.82 +pb_1c : 46.82 +pb_5c : 46.80 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.83 +pb_1c : 46.83 +pb_5c : 46.80 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.84 +pb_1c : 46.84 +pb_5c : 46.80 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.85 +pb_1c : 46.85 +pb_5c : 46.85 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.86 +pb_1c : 46.86 +pb_5c : 46.85 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.87 +pb_1c : 46.87 +pb_5c : 46.85 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.88 +pb_1c : 46.88 +pb_5c : 46.85 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.89 +pb_1c : 46.89 +pb_5c : 46.85 +pb_10c : 46.80 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.90 +pb_1c : 46.90 +pb_5c : 46.90 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.91 +pb_1c : 46.91 +pb_5c : 46.90 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.92 +pb_1c : 46.92 +pb_5c : 46.90 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.93 +pb_1c : 46.93 +pb_5c : 46.90 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.94 +pb_1c : 46.94 +pb_5c : 46.90 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.95 +pb_1c : 46.95 +pb_5c : 46.95 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.96 +pb_1c : 46.96 +pb_5c : 46.95 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.97 +pb_1c : 46.97 +pb_5c : 46.95 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.98 +pb_1c : 46.98 +pb_5c : 46.95 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +46.99 +pb_1c : 46.99 +pb_5c : 46.95 +pb_10c : 46.90 +pb_25c : 46.75 +pb_1d : 46.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.00 +pb_1c : 47.00 +pb_5c : 47.00 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.01 +pb_1c : 47.01 +pb_5c : 47.00 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.02 +pb_1c : 47.02 +pb_5c : 47.00 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.03 +pb_1c : 47.03 +pb_5c : 47.00 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.04 +pb_1c : 47.04 +pb_5c : 47.00 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.05 +pb_1c : 47.05 +pb_5c : 47.05 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.06 +pb_1c : 47.06 +pb_5c : 47.05 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.07 +pb_1c : 47.07 +pb_5c : 47.05 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.08 +pb_1c : 47.08 +pb_5c : 47.05 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.09 +pb_1c : 47.09 +pb_5c : 47.05 +pb_10c : 47.00 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.10 +pb_1c : 47.10 +pb_5c : 47.10 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.11 +pb_1c : 47.11 +pb_5c : 47.10 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.12 +pb_1c : 47.12 +pb_5c : 47.10 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.13 +pb_1c : 47.13 +pb_5c : 47.10 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.14 +pb_1c : 47.14 +pb_5c : 47.10 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.15 +pb_1c : 47.15 +pb_5c : 47.15 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.16 +pb_1c : 47.16 +pb_5c : 47.15 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.17 +pb_1c : 47.17 +pb_5c : 47.15 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.18 +pb_1c : 47.18 +pb_5c : 47.15 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.19 +pb_1c : 47.19 +pb_5c : 47.15 +pb_10c : 47.10 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.20 +pb_1c : 47.20 +pb_5c : 47.20 +pb_10c : 47.20 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.21 +pb_1c : 47.21 +pb_5c : 47.20 +pb_10c : 47.20 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.22 +pb_1c : 47.22 +pb_5c : 47.20 +pb_10c : 47.20 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.23 +pb_1c : 47.23 +pb_5c : 47.20 +pb_10c : 47.20 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.24 +pb_1c : 47.24 +pb_5c : 47.20 +pb_10c : 47.20 +pb_25c : 47.00 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.25 +pb_1c : 47.25 +pb_5c : 47.25 +pb_10c : 47.20 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.26 +pb_1c : 47.26 +pb_5c : 47.25 +pb_10c : 47.20 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.27 +pb_1c : 47.27 +pb_5c : 47.25 +pb_10c : 47.20 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.28 +pb_1c : 47.28 +pb_5c : 47.25 +pb_10c : 47.20 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.29 +pb_1c : 47.29 +pb_5c : 47.25 +pb_10c : 47.20 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.30 +pb_1c : 47.30 +pb_5c : 47.30 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.31 +pb_1c : 47.31 +pb_5c : 47.30 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.32 +pb_1c : 47.32 +pb_5c : 47.30 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.33 +pb_1c : 47.33 +pb_5c : 47.30 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.34 +pb_1c : 47.34 +pb_5c : 47.30 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.35 +pb_1c : 47.35 +pb_5c : 47.35 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.36 +pb_1c : 47.36 +pb_5c : 47.35 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.37 +pb_1c : 47.37 +pb_5c : 47.35 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.38 +pb_1c : 47.38 +pb_5c : 47.35 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.39 +pb_1c : 47.39 +pb_5c : 47.35 +pb_10c : 47.30 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.40 +pb_1c : 47.40 +pb_5c : 47.40 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.41 +pb_1c : 47.41 +pb_5c : 47.40 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.42 +pb_1c : 47.42 +pb_5c : 47.40 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.43 +pb_1c : 47.43 +pb_5c : 47.40 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.44 +pb_1c : 47.44 +pb_5c : 47.40 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.45 +pb_1c : 47.45 +pb_5c : 47.45 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.46 +pb_1c : 47.46 +pb_5c : 47.45 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.47 +pb_1c : 47.47 +pb_5c : 47.45 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.48 +pb_1c : 47.48 +pb_5c : 47.45 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.49 +pb_1c : 47.49 +pb_5c : 47.45 +pb_10c : 47.40 +pb_25c : 47.25 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.50 +pb_1c : 47.50 +pb_5c : 47.50 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.51 +pb_1c : 47.51 +pb_5c : 47.50 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.52 +pb_1c : 47.52 +pb_5c : 47.50 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.53 +pb_1c : 47.53 +pb_5c : 47.50 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.54 +pb_1c : 47.54 +pb_5c : 47.50 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.55 +pb_1c : 47.55 +pb_5c : 47.55 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.56 +pb_1c : 47.56 +pb_5c : 47.55 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.57 +pb_1c : 47.57 +pb_5c : 47.55 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.58 +pb_1c : 47.58 +pb_5c : 47.55 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.59 +pb_1c : 47.59 +pb_5c : 47.55 +pb_10c : 47.50 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.60 +pb_1c : 47.60 +pb_5c : 47.60 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.61 +pb_1c : 47.61 +pb_5c : 47.60 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.62 +pb_1c : 47.62 +pb_5c : 47.60 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.63 +pb_1c : 47.63 +pb_5c : 47.60 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.64 +pb_1c : 47.64 +pb_5c : 47.60 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.65 +pb_1c : 47.65 +pb_5c : 47.65 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.66 +pb_1c : 47.66 +pb_5c : 47.65 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.67 +pb_1c : 47.67 +pb_5c : 47.65 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.68 +pb_1c : 47.68 +pb_5c : 47.65 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.69 +pb_1c : 47.69 +pb_5c : 47.65 +pb_10c : 47.60 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.70 +pb_1c : 47.70 +pb_5c : 47.70 +pb_10c : 47.70 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.71 +pb_1c : 47.71 +pb_5c : 47.70 +pb_10c : 47.70 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.72 +pb_1c : 47.72 +pb_5c : 47.70 +pb_10c : 47.70 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.73 +pb_1c : 47.73 +pb_5c : 47.70 +pb_10c : 47.70 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.74 +pb_1c : 47.74 +pb_5c : 47.70 +pb_10c : 47.70 +pb_25c : 47.50 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.75 +pb_1c : 47.75 +pb_5c : 47.75 +pb_10c : 47.70 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.76 +pb_1c : 47.76 +pb_5c : 47.75 +pb_10c : 47.70 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.77 +pb_1c : 47.77 +pb_5c : 47.75 +pb_10c : 47.70 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.78 +pb_1c : 47.78 +pb_5c : 47.75 +pb_10c : 47.70 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.79 +pb_1c : 47.79 +pb_5c : 47.75 +pb_10c : 47.70 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.80 +pb_1c : 47.80 +pb_5c : 47.80 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.81 +pb_1c : 47.81 +pb_5c : 47.80 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.82 +pb_1c : 47.82 +pb_5c : 47.80 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.83 +pb_1c : 47.83 +pb_5c : 47.80 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.84 +pb_1c : 47.84 +pb_5c : 47.80 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.85 +pb_1c : 47.85 +pb_5c : 47.85 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.86 +pb_1c : 47.86 +pb_5c : 47.85 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.87 +pb_1c : 47.87 +pb_5c : 47.85 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.88 +pb_1c : 47.88 +pb_5c : 47.85 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.89 +pb_1c : 47.89 +pb_5c : 47.85 +pb_10c : 47.80 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.90 +pb_1c : 47.90 +pb_5c : 47.90 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.91 +pb_1c : 47.91 +pb_5c : 47.90 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.92 +pb_1c : 47.92 +pb_5c : 47.90 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.93 +pb_1c : 47.93 +pb_5c : 47.90 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.94 +pb_1c : 47.94 +pb_5c : 47.90 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.95 +pb_1c : 47.95 +pb_5c : 47.95 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.96 +pb_1c : 47.96 +pb_5c : 47.95 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.97 +pb_1c : 47.97 +pb_5c : 47.95 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.98 +pb_1c : 47.98 +pb_5c : 47.95 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +47.99 +pb_1c : 47.99 +pb_5c : 47.95 +pb_10c : 47.90 +pb_25c : 47.75 +pb_1d : 47.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.00 +pb_1c : 48.00 +pb_5c : 48.00 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.01 +pb_1c : 48.01 +pb_5c : 48.00 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.02 +pb_1c : 48.02 +pb_5c : 48.00 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.03 +pb_1c : 48.03 +pb_5c : 48.00 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.04 +pb_1c : 48.04 +pb_5c : 48.00 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.05 +pb_1c : 48.05 +pb_5c : 48.05 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.06 +pb_1c : 48.06 +pb_5c : 48.05 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.07 +pb_1c : 48.07 +pb_5c : 48.05 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.08 +pb_1c : 48.08 +pb_5c : 48.05 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.09 +pb_1c : 48.09 +pb_5c : 48.05 +pb_10c : 48.00 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.10 +pb_1c : 48.10 +pb_5c : 48.10 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.11 +pb_1c : 48.11 +pb_5c : 48.10 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.12 +pb_1c : 48.12 +pb_5c : 48.10 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.13 +pb_1c : 48.13 +pb_5c : 48.10 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.14 +pb_1c : 48.14 +pb_5c : 48.10 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.15 +pb_1c : 48.15 +pb_5c : 48.15 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.16 +pb_1c : 48.16 +pb_5c : 48.15 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.17 +pb_1c : 48.17 +pb_5c : 48.15 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.18 +pb_1c : 48.18 +pb_5c : 48.15 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.19 +pb_1c : 48.19 +pb_5c : 48.15 +pb_10c : 48.10 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.20 +pb_1c : 48.20 +pb_5c : 48.20 +pb_10c : 48.20 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.21 +pb_1c : 48.21 +pb_5c : 48.20 +pb_10c : 48.20 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.22 +pb_1c : 48.22 +pb_5c : 48.20 +pb_10c : 48.20 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.23 +pb_1c : 48.23 +pb_5c : 48.20 +pb_10c : 48.20 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.24 +pb_1c : 48.24 +pb_5c : 48.20 +pb_10c : 48.20 +pb_25c : 48.00 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.25 +pb_1c : 48.25 +pb_5c : 48.25 +pb_10c : 48.20 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.26 +pb_1c : 48.26 +pb_5c : 48.25 +pb_10c : 48.20 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.27 +pb_1c : 48.27 +pb_5c : 48.25 +pb_10c : 48.20 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.28 +pb_1c : 48.28 +pb_5c : 48.25 +pb_10c : 48.20 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.29 +pb_1c : 48.29 +pb_5c : 48.25 +pb_10c : 48.20 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.30 +pb_1c : 48.30 +pb_5c : 48.30 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.31 +pb_1c : 48.31 +pb_5c : 48.30 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.32 +pb_1c : 48.32 +pb_5c : 48.30 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.33 +pb_1c : 48.33 +pb_5c : 48.30 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.34 +pb_1c : 48.34 +pb_5c : 48.30 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.35 +pb_1c : 48.35 +pb_5c : 48.35 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.36 +pb_1c : 48.36 +pb_5c : 48.35 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.37 +pb_1c : 48.37 +pb_5c : 48.35 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.38 +pb_1c : 48.38 +pb_5c : 48.35 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.39 +pb_1c : 48.39 +pb_5c : 48.35 +pb_10c : 48.30 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.40 +pb_1c : 48.40 +pb_5c : 48.40 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.41 +pb_1c : 48.41 +pb_5c : 48.40 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.42 +pb_1c : 48.42 +pb_5c : 48.40 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.43 +pb_1c : 48.43 +pb_5c : 48.40 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.44 +pb_1c : 48.44 +pb_5c : 48.40 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.45 +pb_1c : 48.45 +pb_5c : 48.45 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.46 +pb_1c : 48.46 +pb_5c : 48.45 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.47 +pb_1c : 48.47 +pb_5c : 48.45 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.48 +pb_1c : 48.48 +pb_5c : 48.45 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.49 +pb_1c : 48.49 +pb_5c : 48.45 +pb_10c : 48.40 +pb_25c : 48.25 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.50 +pb_1c : 48.50 +pb_5c : 48.50 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.51 +pb_1c : 48.51 +pb_5c : 48.50 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.52 +pb_1c : 48.52 +pb_5c : 48.50 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.53 +pb_1c : 48.53 +pb_5c : 48.50 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.54 +pb_1c : 48.54 +pb_5c : 48.50 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.55 +pb_1c : 48.55 +pb_5c : 48.55 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.56 +pb_1c : 48.56 +pb_5c : 48.55 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.57 +pb_1c : 48.57 +pb_5c : 48.55 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.58 +pb_1c : 48.58 +pb_5c : 48.55 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.59 +pb_1c : 48.59 +pb_5c : 48.55 +pb_10c : 48.50 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.60 +pb_1c : 48.60 +pb_5c : 48.60 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.61 +pb_1c : 48.61 +pb_5c : 48.60 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.62 +pb_1c : 48.62 +pb_5c : 48.60 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.63 +pb_1c : 48.63 +pb_5c : 48.60 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.64 +pb_1c : 48.64 +pb_5c : 48.60 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.65 +pb_1c : 48.65 +pb_5c : 48.65 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.66 +pb_1c : 48.66 +pb_5c : 48.65 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.67 +pb_1c : 48.67 +pb_5c : 48.65 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.68 +pb_1c : 48.68 +pb_5c : 48.65 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.69 +pb_1c : 48.69 +pb_5c : 48.65 +pb_10c : 48.60 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.70 +pb_1c : 48.70 +pb_5c : 48.70 +pb_10c : 48.70 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.71 +pb_1c : 48.71 +pb_5c : 48.70 +pb_10c : 48.70 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.72 +pb_1c : 48.72 +pb_5c : 48.70 +pb_10c : 48.70 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.73 +pb_1c : 48.73 +pb_5c : 48.70 +pb_10c : 48.70 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.74 +pb_1c : 48.74 +pb_5c : 48.70 +pb_10c : 48.70 +pb_25c : 48.50 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.75 +pb_1c : 48.75 +pb_5c : 48.75 +pb_10c : 48.70 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.76 +pb_1c : 48.76 +pb_5c : 48.75 +pb_10c : 48.70 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.77 +pb_1c : 48.77 +pb_5c : 48.75 +pb_10c : 48.70 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.78 +pb_1c : 48.78 +pb_5c : 48.75 +pb_10c : 48.70 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.79 +pb_1c : 48.79 +pb_5c : 48.75 +pb_10c : 48.70 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.80 +pb_1c : 48.80 +pb_5c : 48.80 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.81 +pb_1c : 48.81 +pb_5c : 48.80 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.82 +pb_1c : 48.82 +pb_5c : 48.80 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.83 +pb_1c : 48.83 +pb_5c : 48.80 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.84 +pb_1c : 48.84 +pb_5c : 48.80 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.85 +pb_1c : 48.85 +pb_5c : 48.85 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.86 +pb_1c : 48.86 +pb_5c : 48.85 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.87 +pb_1c : 48.87 +pb_5c : 48.85 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.88 +pb_1c : 48.88 +pb_5c : 48.85 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.89 +pb_1c : 48.89 +pb_5c : 48.85 +pb_10c : 48.80 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.90 +pb_1c : 48.90 +pb_5c : 48.90 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.91 +pb_1c : 48.91 +pb_5c : 48.90 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.92 +pb_1c : 48.92 +pb_5c : 48.90 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.93 +pb_1c : 48.93 +pb_5c : 48.90 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.94 +pb_1c : 48.94 +pb_5c : 48.90 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.95 +pb_1c : 48.95 +pb_5c : 48.95 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.96 +pb_1c : 48.96 +pb_5c : 48.95 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.97 +pb_1c : 48.97 +pb_5c : 48.95 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.98 +pb_1c : 48.98 +pb_5c : 48.95 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +48.99 +pb_1c : 48.99 +pb_5c : 48.95 +pb_10c : 48.90 +pb_25c : 48.75 +pb_1d : 48.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.00 +pb_1c : 49.00 +pb_5c : 49.00 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.01 +pb_1c : 49.01 +pb_5c : 49.00 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.02 +pb_1c : 49.02 +pb_5c : 49.00 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.03 +pb_1c : 49.03 +pb_5c : 49.00 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.04 +pb_1c : 49.04 +pb_5c : 49.00 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.05 +pb_1c : 49.05 +pb_5c : 49.05 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.06 +pb_1c : 49.06 +pb_5c : 49.05 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.07 +pb_1c : 49.07 +pb_5c : 49.05 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.08 +pb_1c : 49.08 +pb_5c : 49.05 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.09 +pb_1c : 49.09 +pb_5c : 49.05 +pb_10c : 49.00 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.10 +pb_1c : 49.10 +pb_5c : 49.10 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.11 +pb_1c : 49.11 +pb_5c : 49.10 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.12 +pb_1c : 49.12 +pb_5c : 49.10 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.13 +pb_1c : 49.13 +pb_5c : 49.10 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.14 +pb_1c : 49.14 +pb_5c : 49.10 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.15 +pb_1c : 49.15 +pb_5c : 49.15 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.16 +pb_1c : 49.16 +pb_5c : 49.15 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.17 +pb_1c : 49.17 +pb_5c : 49.15 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.18 +pb_1c : 49.18 +pb_5c : 49.15 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.19 +pb_1c : 49.19 +pb_5c : 49.15 +pb_10c : 49.10 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.20 +pb_1c : 49.20 +pb_5c : 49.20 +pb_10c : 49.20 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.21 +pb_1c : 49.21 +pb_5c : 49.20 +pb_10c : 49.20 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.22 +pb_1c : 49.22 +pb_5c : 49.20 +pb_10c : 49.20 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.23 +pb_1c : 49.23 +pb_5c : 49.20 +pb_10c : 49.20 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.24 +pb_1c : 49.24 +pb_5c : 49.20 +pb_10c : 49.20 +pb_25c : 49.00 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.25 +pb_1c : 49.25 +pb_5c : 49.25 +pb_10c : 49.20 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.26 +pb_1c : 49.26 +pb_5c : 49.25 +pb_10c : 49.20 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.27 +pb_1c : 49.27 +pb_5c : 49.25 +pb_10c : 49.20 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.28 +pb_1c : 49.28 +pb_5c : 49.25 +pb_10c : 49.20 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.29 +pb_1c : 49.29 +pb_5c : 49.25 +pb_10c : 49.20 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.30 +pb_1c : 49.30 +pb_5c : 49.30 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.31 +pb_1c : 49.31 +pb_5c : 49.30 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.32 +pb_1c : 49.32 +pb_5c : 49.30 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.33 +pb_1c : 49.33 +pb_5c : 49.30 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.34 +pb_1c : 49.34 +pb_5c : 49.30 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.35 +pb_1c : 49.35 +pb_5c : 49.35 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.36 +pb_1c : 49.36 +pb_5c : 49.35 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.37 +pb_1c : 49.37 +pb_5c : 49.35 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.38 +pb_1c : 49.38 +pb_5c : 49.35 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.39 +pb_1c : 49.39 +pb_5c : 49.35 +pb_10c : 49.30 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.40 +pb_1c : 49.40 +pb_5c : 49.40 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.41 +pb_1c : 49.41 +pb_5c : 49.40 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.42 +pb_1c : 49.42 +pb_5c : 49.40 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.43 +pb_1c : 49.43 +pb_5c : 49.40 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.44 +pb_1c : 49.44 +pb_5c : 49.40 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.45 +pb_1c : 49.45 +pb_5c : 49.45 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.46 +pb_1c : 49.46 +pb_5c : 49.45 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.47 +pb_1c : 49.47 +pb_5c : 49.45 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.48 +pb_1c : 49.48 +pb_5c : 49.45 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.49 +pb_1c : 49.49 +pb_5c : 49.45 +pb_10c : 49.40 +pb_25c : 49.25 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.50 +pb_1c : 49.50 +pb_5c : 49.50 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.51 +pb_1c : 49.51 +pb_5c : 49.50 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.52 +pb_1c : 49.52 +pb_5c : 49.50 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.53 +pb_1c : 49.53 +pb_5c : 49.50 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.54 +pb_1c : 49.54 +pb_5c : 49.50 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.55 +pb_1c : 49.55 +pb_5c : 49.55 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.56 +pb_1c : 49.56 +pb_5c : 49.55 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.57 +pb_1c : 49.57 +pb_5c : 49.55 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.58 +pb_1c : 49.58 +pb_5c : 49.55 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.59 +pb_1c : 49.59 +pb_5c : 49.55 +pb_10c : 49.50 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.60 +pb_1c : 49.60 +pb_5c : 49.60 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.61 +pb_1c : 49.61 +pb_5c : 49.60 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.62 +pb_1c : 49.62 +pb_5c : 49.60 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.63 +pb_1c : 49.63 +pb_5c : 49.60 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.64 +pb_1c : 49.64 +pb_5c : 49.60 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.65 +pb_1c : 49.65 +pb_5c : 49.65 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.66 +pb_1c : 49.66 +pb_5c : 49.65 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.67 +pb_1c : 49.67 +pb_5c : 49.65 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.68 +pb_1c : 49.68 +pb_5c : 49.65 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.69 +pb_1c : 49.69 +pb_5c : 49.65 +pb_10c : 49.60 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.70 +pb_1c : 49.70 +pb_5c : 49.70 +pb_10c : 49.70 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.71 +pb_1c : 49.71 +pb_5c : 49.70 +pb_10c : 49.70 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.72 +pb_1c : 49.72 +pb_5c : 49.70 +pb_10c : 49.70 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.73 +pb_1c : 49.73 +pb_5c : 49.70 +pb_10c : 49.70 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.74 +pb_1c : 49.74 +pb_5c : 49.70 +pb_10c : 49.70 +pb_25c : 49.50 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.75 +pb_1c : 49.75 +pb_5c : 49.75 +pb_10c : 49.70 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.76 +pb_1c : 49.76 +pb_5c : 49.75 +pb_10c : 49.70 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.77 +pb_1c : 49.77 +pb_5c : 49.75 +pb_10c : 49.70 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.78 +pb_1c : 49.78 +pb_5c : 49.75 +pb_10c : 49.70 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.79 +pb_1c : 49.79 +pb_5c : 49.75 +pb_10c : 49.70 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.80 +pb_1c : 49.80 +pb_5c : 49.80 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.81 +pb_1c : 49.81 +pb_5c : 49.80 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.82 +pb_1c : 49.82 +pb_5c : 49.80 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.83 +pb_1c : 49.83 +pb_5c : 49.80 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.84 +pb_1c : 49.84 +pb_5c : 49.80 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.85 +pb_1c : 49.85 +pb_5c : 49.85 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.86 +pb_1c : 49.86 +pb_5c : 49.85 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.87 +pb_1c : 49.87 +pb_5c : 49.85 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.88 +pb_1c : 49.88 +pb_5c : 49.85 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.89 +pb_1c : 49.89 +pb_5c : 49.85 +pb_10c : 49.80 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.90 +pb_1c : 49.90 +pb_5c : 49.90 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.91 +pb_1c : 49.91 +pb_5c : 49.90 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.92 +pb_1c : 49.92 +pb_5c : 49.90 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.93 +pb_1c : 49.93 +pb_5c : 49.90 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.94 +pb_1c : 49.94 +pb_5c : 49.90 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.95 +pb_1c : 49.95 +pb_5c : 49.95 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.96 +pb_1c : 49.96 +pb_5c : 49.95 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.97 +pb_1c : 49.97 +pb_5c : 49.95 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.98 +pb_1c : 49.98 +pb_5c : 49.95 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +49.99 +pb_1c : 49.99 +pb_5c : 49.95 +pb_10c : 49.90 +pb_25c : 49.75 +pb_1d : 49.00 +pb_5d : 45.00 +pb_10d : 40.00 + +50.00 +pb_1c : 50.00 +pb_5c : 50.00 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.01 +pb_1c : 50.01 +pb_5c : 50.00 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.02 +pb_1c : 50.02 +pb_5c : 50.00 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.03 +pb_1c : 50.03 +pb_5c : 50.00 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.04 +pb_1c : 50.04 +pb_5c : 50.00 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.05 +pb_1c : 50.05 +pb_5c : 50.05 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.06 +pb_1c : 50.06 +pb_5c : 50.05 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.07 +pb_1c : 50.07 +pb_5c : 50.05 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.08 +pb_1c : 50.08 +pb_5c : 50.05 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.09 +pb_1c : 50.09 +pb_5c : 50.05 +pb_10c : 50.00 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.10 +pb_1c : 50.10 +pb_5c : 50.10 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.11 +pb_1c : 50.11 +pb_5c : 50.10 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.12 +pb_1c : 50.12 +pb_5c : 50.10 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.13 +pb_1c : 50.13 +pb_5c : 50.10 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.14 +pb_1c : 50.14 +pb_5c : 50.10 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.15 +pb_1c : 50.15 +pb_5c : 50.15 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.16 +pb_1c : 50.16 +pb_5c : 50.15 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.17 +pb_1c : 50.17 +pb_5c : 50.15 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.18 +pb_1c : 50.18 +pb_5c : 50.15 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.19 +pb_1c : 50.19 +pb_5c : 50.15 +pb_10c : 50.10 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.20 +pb_1c : 50.20 +pb_5c : 50.20 +pb_10c : 50.20 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.21 +pb_1c : 50.21 +pb_5c : 50.20 +pb_10c : 50.20 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.22 +pb_1c : 50.22 +pb_5c : 50.20 +pb_10c : 50.20 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.23 +pb_1c : 50.23 +pb_5c : 50.20 +pb_10c : 50.20 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.24 +pb_1c : 50.24 +pb_5c : 50.20 +pb_10c : 50.20 +pb_25c : 50.00 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.25 +pb_1c : 50.25 +pb_5c : 50.25 +pb_10c : 50.20 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.26 +pb_1c : 50.26 +pb_5c : 50.25 +pb_10c : 50.20 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.27 +pb_1c : 50.27 +pb_5c : 50.25 +pb_10c : 50.20 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.28 +pb_1c : 50.28 +pb_5c : 50.25 +pb_10c : 50.20 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.29 +pb_1c : 50.29 +pb_5c : 50.25 +pb_10c : 50.20 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.30 +pb_1c : 50.30 +pb_5c : 50.30 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.31 +pb_1c : 50.31 +pb_5c : 50.30 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.32 +pb_1c : 50.32 +pb_5c : 50.30 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.33 +pb_1c : 50.33 +pb_5c : 50.30 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.34 +pb_1c : 50.34 +pb_5c : 50.30 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.35 +pb_1c : 50.35 +pb_5c : 50.35 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.36 +pb_1c : 50.36 +pb_5c : 50.35 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.37 +pb_1c : 50.37 +pb_5c : 50.35 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.38 +pb_1c : 50.38 +pb_5c : 50.35 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.39 +pb_1c : 50.39 +pb_5c : 50.35 +pb_10c : 50.30 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.40 +pb_1c : 50.40 +pb_5c : 50.40 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.41 +pb_1c : 50.41 +pb_5c : 50.40 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.42 +pb_1c : 50.42 +pb_5c : 50.40 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.43 +pb_1c : 50.43 +pb_5c : 50.40 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.44 +pb_1c : 50.44 +pb_5c : 50.40 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.45 +pb_1c : 50.45 +pb_5c : 50.45 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.46 +pb_1c : 50.46 +pb_5c : 50.45 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.47 +pb_1c : 50.47 +pb_5c : 50.45 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.48 +pb_1c : 50.48 +pb_5c : 50.45 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.49 +pb_1c : 50.49 +pb_5c : 50.45 +pb_10c : 50.40 +pb_25c : 50.25 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.50 +pb_1c : 50.50 +pb_5c : 50.50 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.51 +pb_1c : 50.51 +pb_5c : 50.50 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.52 +pb_1c : 50.52 +pb_5c : 50.50 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.53 +pb_1c : 50.53 +pb_5c : 50.50 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.54 +pb_1c : 50.54 +pb_5c : 50.50 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.55 +pb_1c : 50.55 +pb_5c : 50.55 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.56 +pb_1c : 50.56 +pb_5c : 50.55 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.57 +pb_1c : 50.57 +pb_5c : 50.55 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.58 +pb_1c : 50.58 +pb_5c : 50.55 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.59 +pb_1c : 50.59 +pb_5c : 50.55 +pb_10c : 50.50 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.60 +pb_1c : 50.60 +pb_5c : 50.60 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.61 +pb_1c : 50.61 +pb_5c : 50.60 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.62 +pb_1c : 50.62 +pb_5c : 50.60 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.63 +pb_1c : 50.63 +pb_5c : 50.60 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.64 +pb_1c : 50.64 +pb_5c : 50.60 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.65 +pb_1c : 50.65 +pb_5c : 50.65 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.66 +pb_1c : 50.66 +pb_5c : 50.65 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.67 +pb_1c : 50.67 +pb_5c : 50.65 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.68 +pb_1c : 50.68 +pb_5c : 50.65 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.69 +pb_1c : 50.69 +pb_5c : 50.65 +pb_10c : 50.60 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.70 +pb_1c : 50.70 +pb_5c : 50.70 +pb_10c : 50.70 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.71 +pb_1c : 50.71 +pb_5c : 50.70 +pb_10c : 50.70 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.72 +pb_1c : 50.72 +pb_5c : 50.70 +pb_10c : 50.70 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.73 +pb_1c : 50.73 +pb_5c : 50.70 +pb_10c : 50.70 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.74 +pb_1c : 50.74 +pb_5c : 50.70 +pb_10c : 50.70 +pb_25c : 50.50 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.75 +pb_1c : 50.75 +pb_5c : 50.75 +pb_10c : 50.70 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.76 +pb_1c : 50.76 +pb_5c : 50.75 +pb_10c : 50.70 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.77 +pb_1c : 50.77 +pb_5c : 50.75 +pb_10c : 50.70 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.78 +pb_1c : 50.78 +pb_5c : 50.75 +pb_10c : 50.70 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.79 +pb_1c : 50.79 +pb_5c : 50.75 +pb_10c : 50.70 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.80 +pb_1c : 50.80 +pb_5c : 50.80 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.81 +pb_1c : 50.81 +pb_5c : 50.80 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.82 +pb_1c : 50.82 +pb_5c : 50.80 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.83 +pb_1c : 50.83 +pb_5c : 50.80 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.84 +pb_1c : 50.84 +pb_5c : 50.80 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.85 +pb_1c : 50.85 +pb_5c : 50.85 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.86 +pb_1c : 50.86 +pb_5c : 50.85 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.87 +pb_1c : 50.87 +pb_5c : 50.85 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.88 +pb_1c : 50.88 +pb_5c : 50.85 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.89 +pb_1c : 50.89 +pb_5c : 50.85 +pb_10c : 50.80 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.90 +pb_1c : 50.90 +pb_5c : 50.90 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.91 +pb_1c : 50.91 +pb_5c : 50.90 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.92 +pb_1c : 50.92 +pb_5c : 50.90 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.93 +pb_1c : 50.93 +pb_5c : 50.90 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.94 +pb_1c : 50.94 +pb_5c : 50.90 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.95 +pb_1c : 50.95 +pb_5c : 50.95 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.96 +pb_1c : 50.96 +pb_5c : 50.95 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.97 +pb_1c : 50.97 +pb_5c : 50.95 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.98 +pb_1c : 50.98 +pb_5c : 50.95 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +50.99 +pb_1c : 50.99 +pb_5c : 50.95 +pb_10c : 50.90 +pb_25c : 50.75 +pb_1d : 50.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.00 +pb_1c : 51.00 +pb_5c : 51.00 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.01 +pb_1c : 51.01 +pb_5c : 51.00 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.02 +pb_1c : 51.02 +pb_5c : 51.00 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.03 +pb_1c : 51.03 +pb_5c : 51.00 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.04 +pb_1c : 51.04 +pb_5c : 51.00 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.05 +pb_1c : 51.05 +pb_5c : 51.05 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.06 +pb_1c : 51.06 +pb_5c : 51.05 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.07 +pb_1c : 51.07 +pb_5c : 51.05 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.08 +pb_1c : 51.08 +pb_5c : 51.05 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.09 +pb_1c : 51.09 +pb_5c : 51.05 +pb_10c : 51.00 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.10 +pb_1c : 51.10 +pb_5c : 51.10 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.11 +pb_1c : 51.11 +pb_5c : 51.10 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.12 +pb_1c : 51.12 +pb_5c : 51.10 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.13 +pb_1c : 51.13 +pb_5c : 51.10 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.14 +pb_1c : 51.14 +pb_5c : 51.10 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.15 +pb_1c : 51.15 +pb_5c : 51.15 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.16 +pb_1c : 51.16 +pb_5c : 51.15 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.17 +pb_1c : 51.17 +pb_5c : 51.15 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.18 +pb_1c : 51.18 +pb_5c : 51.15 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.19 +pb_1c : 51.19 +pb_5c : 51.15 +pb_10c : 51.10 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.20 +pb_1c : 51.20 +pb_5c : 51.20 +pb_10c : 51.20 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.21 +pb_1c : 51.21 +pb_5c : 51.20 +pb_10c : 51.20 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.22 +pb_1c : 51.22 +pb_5c : 51.20 +pb_10c : 51.20 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.23 +pb_1c : 51.23 +pb_5c : 51.20 +pb_10c : 51.20 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.24 +pb_1c : 51.24 +pb_5c : 51.20 +pb_10c : 51.20 +pb_25c : 51.00 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.25 +pb_1c : 51.25 +pb_5c : 51.25 +pb_10c : 51.20 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.26 +pb_1c : 51.26 +pb_5c : 51.25 +pb_10c : 51.20 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.27 +pb_1c : 51.27 +pb_5c : 51.25 +pb_10c : 51.20 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.28 +pb_1c : 51.28 +pb_5c : 51.25 +pb_10c : 51.20 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.29 +pb_1c : 51.29 +pb_5c : 51.25 +pb_10c : 51.20 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.30 +pb_1c : 51.30 +pb_5c : 51.30 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.31 +pb_1c : 51.31 +pb_5c : 51.30 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.32 +pb_1c : 51.32 +pb_5c : 51.30 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.33 +pb_1c : 51.33 +pb_5c : 51.30 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.34 +pb_1c : 51.34 +pb_5c : 51.30 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.35 +pb_1c : 51.35 +pb_5c : 51.35 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.36 +pb_1c : 51.36 +pb_5c : 51.35 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.37 +pb_1c : 51.37 +pb_5c : 51.35 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.38 +pb_1c : 51.38 +pb_5c : 51.35 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.39 +pb_1c : 51.39 +pb_5c : 51.35 +pb_10c : 51.30 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.40 +pb_1c : 51.40 +pb_5c : 51.40 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.41 +pb_1c : 51.41 +pb_5c : 51.40 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.42 +pb_1c : 51.42 +pb_5c : 51.40 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.43 +pb_1c : 51.43 +pb_5c : 51.40 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.44 +pb_1c : 51.44 +pb_5c : 51.40 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.45 +pb_1c : 51.45 +pb_5c : 51.45 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.46 +pb_1c : 51.46 +pb_5c : 51.45 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.47 +pb_1c : 51.47 +pb_5c : 51.45 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.48 +pb_1c : 51.48 +pb_5c : 51.45 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.49 +pb_1c : 51.49 +pb_5c : 51.45 +pb_10c : 51.40 +pb_25c : 51.25 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.50 +pb_1c : 51.50 +pb_5c : 51.50 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.51 +pb_1c : 51.51 +pb_5c : 51.50 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.52 +pb_1c : 51.52 +pb_5c : 51.50 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.53 +pb_1c : 51.53 +pb_5c : 51.50 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.54 +pb_1c : 51.54 +pb_5c : 51.50 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.55 +pb_1c : 51.55 +pb_5c : 51.55 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.56 +pb_1c : 51.56 +pb_5c : 51.55 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.57 +pb_1c : 51.57 +pb_5c : 51.55 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.58 +pb_1c : 51.58 +pb_5c : 51.55 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.59 +pb_1c : 51.59 +pb_5c : 51.55 +pb_10c : 51.50 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.60 +pb_1c : 51.60 +pb_5c : 51.60 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.61 +pb_1c : 51.61 +pb_5c : 51.60 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.62 +pb_1c : 51.62 +pb_5c : 51.60 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.63 +pb_1c : 51.63 +pb_5c : 51.60 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.64 +pb_1c : 51.64 +pb_5c : 51.60 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.65 +pb_1c : 51.65 +pb_5c : 51.65 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.66 +pb_1c : 51.66 +pb_5c : 51.65 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.67 +pb_1c : 51.67 +pb_5c : 51.65 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.68 +pb_1c : 51.68 +pb_5c : 51.65 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.69 +pb_1c : 51.69 +pb_5c : 51.65 +pb_10c : 51.60 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.70 +pb_1c : 51.70 +pb_5c : 51.70 +pb_10c : 51.70 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.71 +pb_1c : 51.71 +pb_5c : 51.70 +pb_10c : 51.70 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.72 +pb_1c : 51.72 +pb_5c : 51.70 +pb_10c : 51.70 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.73 +pb_1c : 51.73 +pb_5c : 51.70 +pb_10c : 51.70 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.74 +pb_1c : 51.74 +pb_5c : 51.70 +pb_10c : 51.70 +pb_25c : 51.50 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.75 +pb_1c : 51.75 +pb_5c : 51.75 +pb_10c : 51.70 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.76 +pb_1c : 51.76 +pb_5c : 51.75 +pb_10c : 51.70 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.77 +pb_1c : 51.77 +pb_5c : 51.75 +pb_10c : 51.70 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.78 +pb_1c : 51.78 +pb_5c : 51.75 +pb_10c : 51.70 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.79 +pb_1c : 51.79 +pb_5c : 51.75 +pb_10c : 51.70 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.80 +pb_1c : 51.80 +pb_5c : 51.80 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.81 +pb_1c : 51.81 +pb_5c : 51.80 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.82 +pb_1c : 51.82 +pb_5c : 51.80 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.83 +pb_1c : 51.83 +pb_5c : 51.80 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.84 +pb_1c : 51.84 +pb_5c : 51.80 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.85 +pb_1c : 51.85 +pb_5c : 51.85 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.86 +pb_1c : 51.86 +pb_5c : 51.85 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.87 +pb_1c : 51.87 +pb_5c : 51.85 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.88 +pb_1c : 51.88 +pb_5c : 51.85 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.89 +pb_1c : 51.89 +pb_5c : 51.85 +pb_10c : 51.80 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.90 +pb_1c : 51.90 +pb_5c : 51.90 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.91 +pb_1c : 51.91 +pb_5c : 51.90 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.92 +pb_1c : 51.92 +pb_5c : 51.90 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.93 +pb_1c : 51.93 +pb_5c : 51.90 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.94 +pb_1c : 51.94 +pb_5c : 51.90 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.95 +pb_1c : 51.95 +pb_5c : 51.95 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.96 +pb_1c : 51.96 +pb_5c : 51.95 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.97 +pb_1c : 51.97 +pb_5c : 51.95 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.98 +pb_1c : 51.98 +pb_5c : 51.95 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +51.99 +pb_1c : 51.99 +pb_5c : 51.95 +pb_10c : 51.90 +pb_25c : 51.75 +pb_1d : 51.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.00 +pb_1c : 52.00 +pb_5c : 52.00 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.01 +pb_1c : 52.01 +pb_5c : 52.00 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.02 +pb_1c : 52.02 +pb_5c : 52.00 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.03 +pb_1c : 52.03 +pb_5c : 52.00 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.04 +pb_1c : 52.04 +pb_5c : 52.00 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.05 +pb_1c : 52.05 +pb_5c : 52.05 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.06 +pb_1c : 52.06 +pb_5c : 52.05 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.07 +pb_1c : 52.07 +pb_5c : 52.05 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.08 +pb_1c : 52.08 +pb_5c : 52.05 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.09 +pb_1c : 52.09 +pb_5c : 52.05 +pb_10c : 52.00 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.10 +pb_1c : 52.10 +pb_5c : 52.10 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.11 +pb_1c : 52.11 +pb_5c : 52.10 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.12 +pb_1c : 52.12 +pb_5c : 52.10 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.13 +pb_1c : 52.13 +pb_5c : 52.10 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.14 +pb_1c : 52.14 +pb_5c : 52.10 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.15 +pb_1c : 52.15 +pb_5c : 52.15 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.16 +pb_1c : 52.16 +pb_5c : 52.15 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.17 +pb_1c : 52.17 +pb_5c : 52.15 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.18 +pb_1c : 52.18 +pb_5c : 52.15 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.19 +pb_1c : 52.19 +pb_5c : 52.15 +pb_10c : 52.10 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.20 +pb_1c : 52.20 +pb_5c : 52.20 +pb_10c : 52.20 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.21 +pb_1c : 52.21 +pb_5c : 52.20 +pb_10c : 52.20 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.22 +pb_1c : 52.22 +pb_5c : 52.20 +pb_10c : 52.20 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.23 +pb_1c : 52.23 +pb_5c : 52.20 +pb_10c : 52.20 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.24 +pb_1c : 52.24 +pb_5c : 52.20 +pb_10c : 52.20 +pb_25c : 52.00 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.25 +pb_1c : 52.25 +pb_5c : 52.25 +pb_10c : 52.20 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.26 +pb_1c : 52.26 +pb_5c : 52.25 +pb_10c : 52.20 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.27 +pb_1c : 52.27 +pb_5c : 52.25 +pb_10c : 52.20 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.28 +pb_1c : 52.28 +pb_5c : 52.25 +pb_10c : 52.20 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.29 +pb_1c : 52.29 +pb_5c : 52.25 +pb_10c : 52.20 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.30 +pb_1c : 52.30 +pb_5c : 52.30 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.31 +pb_1c : 52.31 +pb_5c : 52.30 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.32 +pb_1c : 52.32 +pb_5c : 52.30 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.33 +pb_1c : 52.33 +pb_5c : 52.30 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.34 +pb_1c : 52.34 +pb_5c : 52.30 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.35 +pb_1c : 52.35 +pb_5c : 52.35 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.36 +pb_1c : 52.36 +pb_5c : 52.35 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.37 +pb_1c : 52.37 +pb_5c : 52.35 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.38 +pb_1c : 52.38 +pb_5c : 52.35 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.39 +pb_1c : 52.39 +pb_5c : 52.35 +pb_10c : 52.30 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.40 +pb_1c : 52.40 +pb_5c : 52.40 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.41 +pb_1c : 52.41 +pb_5c : 52.40 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.42 +pb_1c : 52.42 +pb_5c : 52.40 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.43 +pb_1c : 52.43 +pb_5c : 52.40 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.44 +pb_1c : 52.44 +pb_5c : 52.40 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.45 +pb_1c : 52.45 +pb_5c : 52.45 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.46 +pb_1c : 52.46 +pb_5c : 52.45 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.47 +pb_1c : 52.47 +pb_5c : 52.45 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.48 +pb_1c : 52.48 +pb_5c : 52.45 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.49 +pb_1c : 52.49 +pb_5c : 52.45 +pb_10c : 52.40 +pb_25c : 52.25 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.50 +pb_1c : 52.50 +pb_5c : 52.50 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.51 +pb_1c : 52.51 +pb_5c : 52.50 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.52 +pb_1c : 52.52 +pb_5c : 52.50 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.53 +pb_1c : 52.53 +pb_5c : 52.50 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.54 +pb_1c : 52.54 +pb_5c : 52.50 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.55 +pb_1c : 52.55 +pb_5c : 52.55 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.56 +pb_1c : 52.56 +pb_5c : 52.55 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.57 +pb_1c : 52.57 +pb_5c : 52.55 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.58 +pb_1c : 52.58 +pb_5c : 52.55 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.59 +pb_1c : 52.59 +pb_5c : 52.55 +pb_10c : 52.50 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.60 +pb_1c : 52.60 +pb_5c : 52.60 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.61 +pb_1c : 52.61 +pb_5c : 52.60 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.62 +pb_1c : 52.62 +pb_5c : 52.60 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.63 +pb_1c : 52.63 +pb_5c : 52.60 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.64 +pb_1c : 52.64 +pb_5c : 52.60 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.65 +pb_1c : 52.65 +pb_5c : 52.65 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.66 +pb_1c : 52.66 +pb_5c : 52.65 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.67 +pb_1c : 52.67 +pb_5c : 52.65 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.68 +pb_1c : 52.68 +pb_5c : 52.65 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.69 +pb_1c : 52.69 +pb_5c : 52.65 +pb_10c : 52.60 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.70 +pb_1c : 52.70 +pb_5c : 52.70 +pb_10c : 52.70 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.71 +pb_1c : 52.71 +pb_5c : 52.70 +pb_10c : 52.70 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.72 +pb_1c : 52.72 +pb_5c : 52.70 +pb_10c : 52.70 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.73 +pb_1c : 52.73 +pb_5c : 52.70 +pb_10c : 52.70 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.74 +pb_1c : 52.74 +pb_5c : 52.70 +pb_10c : 52.70 +pb_25c : 52.50 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.75 +pb_1c : 52.75 +pb_5c : 52.75 +pb_10c : 52.70 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.76 +pb_1c : 52.76 +pb_5c : 52.75 +pb_10c : 52.70 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.77 +pb_1c : 52.77 +pb_5c : 52.75 +pb_10c : 52.70 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.78 +pb_1c : 52.78 +pb_5c : 52.75 +pb_10c : 52.70 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.79 +pb_1c : 52.79 +pb_5c : 52.75 +pb_10c : 52.70 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.80 +pb_1c : 52.80 +pb_5c : 52.80 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.81 +pb_1c : 52.81 +pb_5c : 52.80 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.82 +pb_1c : 52.82 +pb_5c : 52.80 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.83 +pb_1c : 52.83 +pb_5c : 52.80 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.84 +pb_1c : 52.84 +pb_5c : 52.80 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.85 +pb_1c : 52.85 +pb_5c : 52.85 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.86 +pb_1c : 52.86 +pb_5c : 52.85 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.87 +pb_1c : 52.87 +pb_5c : 52.85 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.88 +pb_1c : 52.88 +pb_5c : 52.85 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.89 +pb_1c : 52.89 +pb_5c : 52.85 +pb_10c : 52.80 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.90 +pb_1c : 52.90 +pb_5c : 52.90 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.91 +pb_1c : 52.91 +pb_5c : 52.90 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.92 +pb_1c : 52.92 +pb_5c : 52.90 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.93 +pb_1c : 52.93 +pb_5c : 52.90 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.94 +pb_1c : 52.94 +pb_5c : 52.90 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.95 +pb_1c : 52.95 +pb_5c : 52.95 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.96 +pb_1c : 52.96 +pb_5c : 52.95 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.97 +pb_1c : 52.97 +pb_5c : 52.95 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.98 +pb_1c : 52.98 +pb_5c : 52.95 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +52.99 +pb_1c : 52.99 +pb_5c : 52.95 +pb_10c : 52.90 +pb_25c : 52.75 +pb_1d : 52.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.00 +pb_1c : 53.00 +pb_5c : 53.00 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.01 +pb_1c : 53.01 +pb_5c : 53.00 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.02 +pb_1c : 53.02 +pb_5c : 53.00 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.03 +pb_1c : 53.03 +pb_5c : 53.00 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.04 +pb_1c : 53.04 +pb_5c : 53.00 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.05 +pb_1c : 53.05 +pb_5c : 53.05 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.06 +pb_1c : 53.06 +pb_5c : 53.05 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.07 +pb_1c : 53.07 +pb_5c : 53.05 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.08 +pb_1c : 53.08 +pb_5c : 53.05 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.09 +pb_1c : 53.09 +pb_5c : 53.05 +pb_10c : 53.00 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.10 +pb_1c : 53.10 +pb_5c : 53.10 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.11 +pb_1c : 53.11 +pb_5c : 53.10 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.12 +pb_1c : 53.12 +pb_5c : 53.10 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.13 +pb_1c : 53.13 +pb_5c : 53.10 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.14 +pb_1c : 53.14 +pb_5c : 53.10 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.15 +pb_1c : 53.15 +pb_5c : 53.15 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.16 +pb_1c : 53.16 +pb_5c : 53.15 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.17 +pb_1c : 53.17 +pb_5c : 53.15 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.18 +pb_1c : 53.18 +pb_5c : 53.15 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.19 +pb_1c : 53.19 +pb_5c : 53.15 +pb_10c : 53.10 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.20 +pb_1c : 53.20 +pb_5c : 53.20 +pb_10c : 53.20 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.21 +pb_1c : 53.21 +pb_5c : 53.20 +pb_10c : 53.20 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.22 +pb_1c : 53.22 +pb_5c : 53.20 +pb_10c : 53.20 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.23 +pb_1c : 53.23 +pb_5c : 53.20 +pb_10c : 53.20 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.24 +pb_1c : 53.24 +pb_5c : 53.20 +pb_10c : 53.20 +pb_25c : 53.00 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.25 +pb_1c : 53.25 +pb_5c : 53.25 +pb_10c : 53.20 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.26 +pb_1c : 53.26 +pb_5c : 53.25 +pb_10c : 53.20 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.27 +pb_1c : 53.27 +pb_5c : 53.25 +pb_10c : 53.20 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.28 +pb_1c : 53.28 +pb_5c : 53.25 +pb_10c : 53.20 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.29 +pb_1c : 53.29 +pb_5c : 53.25 +pb_10c : 53.20 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.30 +pb_1c : 53.30 +pb_5c : 53.30 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.31 +pb_1c : 53.31 +pb_5c : 53.30 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.32 +pb_1c : 53.32 +pb_5c : 53.30 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.33 +pb_1c : 53.33 +pb_5c : 53.30 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.34 +pb_1c : 53.34 +pb_5c : 53.30 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.35 +pb_1c : 53.35 +pb_5c : 53.35 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.36 +pb_1c : 53.36 +pb_5c : 53.35 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.37 +pb_1c : 53.37 +pb_5c : 53.35 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.38 +pb_1c : 53.38 +pb_5c : 53.35 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.39 +pb_1c : 53.39 +pb_5c : 53.35 +pb_10c : 53.30 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.40 +pb_1c : 53.40 +pb_5c : 53.40 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.41 +pb_1c : 53.41 +pb_5c : 53.40 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.42 +pb_1c : 53.42 +pb_5c : 53.40 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.43 +pb_1c : 53.43 +pb_5c : 53.40 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.44 +pb_1c : 53.44 +pb_5c : 53.40 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.45 +pb_1c : 53.45 +pb_5c : 53.45 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.46 +pb_1c : 53.46 +pb_5c : 53.45 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.47 +pb_1c : 53.47 +pb_5c : 53.45 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.48 +pb_1c : 53.48 +pb_5c : 53.45 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.49 +pb_1c : 53.49 +pb_5c : 53.45 +pb_10c : 53.40 +pb_25c : 53.25 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.50 +pb_1c : 53.50 +pb_5c : 53.50 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.51 +pb_1c : 53.51 +pb_5c : 53.50 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.52 +pb_1c : 53.52 +pb_5c : 53.50 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.53 +pb_1c : 53.53 +pb_5c : 53.50 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.54 +pb_1c : 53.54 +pb_5c : 53.50 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.55 +pb_1c : 53.55 +pb_5c : 53.55 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.56 +pb_1c : 53.56 +pb_5c : 53.55 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.57 +pb_1c : 53.57 +pb_5c : 53.55 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.58 +pb_1c : 53.58 +pb_5c : 53.55 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.59 +pb_1c : 53.59 +pb_5c : 53.55 +pb_10c : 53.50 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.60 +pb_1c : 53.60 +pb_5c : 53.60 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.61 +pb_1c : 53.61 +pb_5c : 53.60 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.62 +pb_1c : 53.62 +pb_5c : 53.60 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.63 +pb_1c : 53.63 +pb_5c : 53.60 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.64 +pb_1c : 53.64 +pb_5c : 53.60 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.65 +pb_1c : 53.65 +pb_5c : 53.65 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.66 +pb_1c : 53.66 +pb_5c : 53.65 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.67 +pb_1c : 53.67 +pb_5c : 53.65 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.68 +pb_1c : 53.68 +pb_5c : 53.65 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.69 +pb_1c : 53.69 +pb_5c : 53.65 +pb_10c : 53.60 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.70 +pb_1c : 53.70 +pb_5c : 53.70 +pb_10c : 53.70 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.71 +pb_1c : 53.71 +pb_5c : 53.70 +pb_10c : 53.70 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.72 +pb_1c : 53.72 +pb_5c : 53.70 +pb_10c : 53.70 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.73 +pb_1c : 53.73 +pb_5c : 53.70 +pb_10c : 53.70 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.74 +pb_1c : 53.74 +pb_5c : 53.70 +pb_10c : 53.70 +pb_25c : 53.50 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.75 +pb_1c : 53.75 +pb_5c : 53.75 +pb_10c : 53.70 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.76 +pb_1c : 53.76 +pb_5c : 53.75 +pb_10c : 53.70 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.77 +pb_1c : 53.77 +pb_5c : 53.75 +pb_10c : 53.70 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.78 +pb_1c : 53.78 +pb_5c : 53.75 +pb_10c : 53.70 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.79 +pb_1c : 53.79 +pb_5c : 53.75 +pb_10c : 53.70 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.80 +pb_1c : 53.80 +pb_5c : 53.80 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.81 +pb_1c : 53.81 +pb_5c : 53.80 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.82 +pb_1c : 53.82 +pb_5c : 53.80 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.83 +pb_1c : 53.83 +pb_5c : 53.80 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.84 +pb_1c : 53.84 +pb_5c : 53.80 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.85 +pb_1c : 53.85 +pb_5c : 53.85 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.86 +pb_1c : 53.86 +pb_5c : 53.85 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.87 +pb_1c : 53.87 +pb_5c : 53.85 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.88 +pb_1c : 53.88 +pb_5c : 53.85 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.89 +pb_1c : 53.89 +pb_5c : 53.85 +pb_10c : 53.80 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.90 +pb_1c : 53.90 +pb_5c : 53.90 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.91 +pb_1c : 53.91 +pb_5c : 53.90 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.92 +pb_1c : 53.92 +pb_5c : 53.90 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.93 +pb_1c : 53.93 +pb_5c : 53.90 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.94 +pb_1c : 53.94 +pb_5c : 53.90 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.95 +pb_1c : 53.95 +pb_5c : 53.95 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.96 +pb_1c : 53.96 +pb_5c : 53.95 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.97 +pb_1c : 53.97 +pb_5c : 53.95 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.98 +pb_1c : 53.98 +pb_5c : 53.95 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +53.99 +pb_1c : 53.99 +pb_5c : 53.95 +pb_10c : 53.90 +pb_25c : 53.75 +pb_1d : 53.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.00 +pb_1c : 54.00 +pb_5c : 54.00 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.01 +pb_1c : 54.01 +pb_5c : 54.00 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.02 +pb_1c : 54.02 +pb_5c : 54.00 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.03 +pb_1c : 54.03 +pb_5c : 54.00 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.04 +pb_1c : 54.04 +pb_5c : 54.00 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.05 +pb_1c : 54.05 +pb_5c : 54.05 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.06 +pb_1c : 54.06 +pb_5c : 54.05 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.07 +pb_1c : 54.07 +pb_5c : 54.05 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.08 +pb_1c : 54.08 +pb_5c : 54.05 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.09 +pb_1c : 54.09 +pb_5c : 54.05 +pb_10c : 54.00 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.10 +pb_1c : 54.10 +pb_5c : 54.10 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.11 +pb_1c : 54.11 +pb_5c : 54.10 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.12 +pb_1c : 54.12 +pb_5c : 54.10 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.13 +pb_1c : 54.13 +pb_5c : 54.10 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.14 +pb_1c : 54.14 +pb_5c : 54.10 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.15 +pb_1c : 54.15 +pb_5c : 54.15 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.16 +pb_1c : 54.16 +pb_5c : 54.15 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.17 +pb_1c : 54.17 +pb_5c : 54.15 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.18 +pb_1c : 54.18 +pb_5c : 54.15 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.19 +pb_1c : 54.19 +pb_5c : 54.15 +pb_10c : 54.10 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.20 +pb_1c : 54.20 +pb_5c : 54.20 +pb_10c : 54.20 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.21 +pb_1c : 54.21 +pb_5c : 54.20 +pb_10c : 54.20 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.22 +pb_1c : 54.22 +pb_5c : 54.20 +pb_10c : 54.20 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.23 +pb_1c : 54.23 +pb_5c : 54.20 +pb_10c : 54.20 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.24 +pb_1c : 54.24 +pb_5c : 54.20 +pb_10c : 54.20 +pb_25c : 54.00 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.25 +pb_1c : 54.25 +pb_5c : 54.25 +pb_10c : 54.20 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.26 +pb_1c : 54.26 +pb_5c : 54.25 +pb_10c : 54.20 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.27 +pb_1c : 54.27 +pb_5c : 54.25 +pb_10c : 54.20 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.28 +pb_1c : 54.28 +pb_5c : 54.25 +pb_10c : 54.20 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.29 +pb_1c : 54.29 +pb_5c : 54.25 +pb_10c : 54.20 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.30 +pb_1c : 54.30 +pb_5c : 54.30 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.31 +pb_1c : 54.31 +pb_5c : 54.30 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.32 +pb_1c : 54.32 +pb_5c : 54.30 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.33 +pb_1c : 54.33 +pb_5c : 54.30 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.34 +pb_1c : 54.34 +pb_5c : 54.30 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.35 +pb_1c : 54.35 +pb_5c : 54.35 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.36 +pb_1c : 54.36 +pb_5c : 54.35 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.37 +pb_1c : 54.37 +pb_5c : 54.35 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.38 +pb_1c : 54.38 +pb_5c : 54.35 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.39 +pb_1c : 54.39 +pb_5c : 54.35 +pb_10c : 54.30 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.40 +pb_1c : 54.40 +pb_5c : 54.40 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.41 +pb_1c : 54.41 +pb_5c : 54.40 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.42 +pb_1c : 54.42 +pb_5c : 54.40 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.43 +pb_1c : 54.43 +pb_5c : 54.40 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.44 +pb_1c : 54.44 +pb_5c : 54.40 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.45 +pb_1c : 54.45 +pb_5c : 54.45 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.46 +pb_1c : 54.46 +pb_5c : 54.45 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.47 +pb_1c : 54.47 +pb_5c : 54.45 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.48 +pb_1c : 54.48 +pb_5c : 54.45 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.49 +pb_1c : 54.49 +pb_5c : 54.45 +pb_10c : 54.40 +pb_25c : 54.25 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.50 +pb_1c : 54.50 +pb_5c : 54.50 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.51 +pb_1c : 54.51 +pb_5c : 54.50 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.52 +pb_1c : 54.52 +pb_5c : 54.50 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.53 +pb_1c : 54.53 +pb_5c : 54.50 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.54 +pb_1c : 54.54 +pb_5c : 54.50 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.55 +pb_1c : 54.55 +pb_5c : 54.55 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.56 +pb_1c : 54.56 +pb_5c : 54.55 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.57 +pb_1c : 54.57 +pb_5c : 54.55 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.58 +pb_1c : 54.58 +pb_5c : 54.55 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.59 +pb_1c : 54.59 +pb_5c : 54.55 +pb_10c : 54.50 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.60 +pb_1c : 54.60 +pb_5c : 54.60 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.61 +pb_1c : 54.61 +pb_5c : 54.60 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.62 +pb_1c : 54.62 +pb_5c : 54.60 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.63 +pb_1c : 54.63 +pb_5c : 54.60 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.64 +pb_1c : 54.64 +pb_5c : 54.60 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.65 +pb_1c : 54.65 +pb_5c : 54.65 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.66 +pb_1c : 54.66 +pb_5c : 54.65 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.67 +pb_1c : 54.67 +pb_5c : 54.65 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.68 +pb_1c : 54.68 +pb_5c : 54.65 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.69 +pb_1c : 54.69 +pb_5c : 54.65 +pb_10c : 54.60 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.70 +pb_1c : 54.70 +pb_5c : 54.70 +pb_10c : 54.70 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.71 +pb_1c : 54.71 +pb_5c : 54.70 +pb_10c : 54.70 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.72 +pb_1c : 54.72 +pb_5c : 54.70 +pb_10c : 54.70 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.73 +pb_1c : 54.73 +pb_5c : 54.70 +pb_10c : 54.70 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.74 +pb_1c : 54.74 +pb_5c : 54.70 +pb_10c : 54.70 +pb_25c : 54.50 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.75 +pb_1c : 54.75 +pb_5c : 54.75 +pb_10c : 54.70 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.76 +pb_1c : 54.76 +pb_5c : 54.75 +pb_10c : 54.70 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.77 +pb_1c : 54.77 +pb_5c : 54.75 +pb_10c : 54.70 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.78 +pb_1c : 54.78 +pb_5c : 54.75 +pb_10c : 54.70 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.79 +pb_1c : 54.79 +pb_5c : 54.75 +pb_10c : 54.70 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.80 +pb_1c : 54.80 +pb_5c : 54.80 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.81 +pb_1c : 54.81 +pb_5c : 54.80 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.82 +pb_1c : 54.82 +pb_5c : 54.80 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.83 +pb_1c : 54.83 +pb_5c : 54.80 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.84 +pb_1c : 54.84 +pb_5c : 54.80 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.85 +pb_1c : 54.85 +pb_5c : 54.85 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.86 +pb_1c : 54.86 +pb_5c : 54.85 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.87 +pb_1c : 54.87 +pb_5c : 54.85 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.88 +pb_1c : 54.88 +pb_5c : 54.85 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.89 +pb_1c : 54.89 +pb_5c : 54.85 +pb_10c : 54.80 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.90 +pb_1c : 54.90 +pb_5c : 54.90 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.91 +pb_1c : 54.91 +pb_5c : 54.90 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.92 +pb_1c : 54.92 +pb_5c : 54.90 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.93 +pb_1c : 54.93 +pb_5c : 54.90 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.94 +pb_1c : 54.94 +pb_5c : 54.90 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.95 +pb_1c : 54.95 +pb_5c : 54.95 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.96 +pb_1c : 54.96 +pb_5c : 54.95 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.97 +pb_1c : 54.97 +pb_5c : 54.95 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.98 +pb_1c : 54.98 +pb_5c : 54.95 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +54.99 +pb_1c : 54.99 +pb_5c : 54.95 +pb_10c : 54.90 +pb_25c : 54.75 +pb_1d : 54.00 +pb_5d : 50.00 +pb_10d : 50.00 + +55.00 +pb_1c : 55.00 +pb_5c : 55.00 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.01 +pb_1c : 55.01 +pb_5c : 55.00 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.02 +pb_1c : 55.02 +pb_5c : 55.00 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.03 +pb_1c : 55.03 +pb_5c : 55.00 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.04 +pb_1c : 55.04 +pb_5c : 55.00 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.05 +pb_1c : 55.05 +pb_5c : 55.05 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.06 +pb_1c : 55.06 +pb_5c : 55.05 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.07 +pb_1c : 55.07 +pb_5c : 55.05 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.08 +pb_1c : 55.08 +pb_5c : 55.05 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.09 +pb_1c : 55.09 +pb_5c : 55.05 +pb_10c : 55.00 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.10 +pb_1c : 55.10 +pb_5c : 55.10 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.11 +pb_1c : 55.11 +pb_5c : 55.10 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.12 +pb_1c : 55.12 +pb_5c : 55.10 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.13 +pb_1c : 55.13 +pb_5c : 55.10 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.14 +pb_1c : 55.14 +pb_5c : 55.10 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.15 +pb_1c : 55.15 +pb_5c : 55.15 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.16 +pb_1c : 55.16 +pb_5c : 55.15 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.17 +pb_1c : 55.17 +pb_5c : 55.15 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.18 +pb_1c : 55.18 +pb_5c : 55.15 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.19 +pb_1c : 55.19 +pb_5c : 55.15 +pb_10c : 55.10 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.20 +pb_1c : 55.20 +pb_5c : 55.20 +pb_10c : 55.20 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.21 +pb_1c : 55.21 +pb_5c : 55.20 +pb_10c : 55.20 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.22 +pb_1c : 55.22 +pb_5c : 55.20 +pb_10c : 55.20 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.23 +pb_1c : 55.23 +pb_5c : 55.20 +pb_10c : 55.20 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.24 +pb_1c : 55.24 +pb_5c : 55.20 +pb_10c : 55.20 +pb_25c : 55.00 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.25 +pb_1c : 55.25 +pb_5c : 55.25 +pb_10c : 55.20 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.26 +pb_1c : 55.26 +pb_5c : 55.25 +pb_10c : 55.20 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.27 +pb_1c : 55.27 +pb_5c : 55.25 +pb_10c : 55.20 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.28 +pb_1c : 55.28 +pb_5c : 55.25 +pb_10c : 55.20 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.29 +pb_1c : 55.29 +pb_5c : 55.25 +pb_10c : 55.20 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.30 +pb_1c : 55.30 +pb_5c : 55.30 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.31 +pb_1c : 55.31 +pb_5c : 55.30 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.32 +pb_1c : 55.32 +pb_5c : 55.30 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.33 +pb_1c : 55.33 +pb_5c : 55.30 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.34 +pb_1c : 55.34 +pb_5c : 55.30 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.35 +pb_1c : 55.35 +pb_5c : 55.35 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.36 +pb_1c : 55.36 +pb_5c : 55.35 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.37 +pb_1c : 55.37 +pb_5c : 55.35 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.38 +pb_1c : 55.38 +pb_5c : 55.35 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.39 +pb_1c : 55.39 +pb_5c : 55.35 +pb_10c : 55.30 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.40 +pb_1c : 55.40 +pb_5c : 55.40 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.41 +pb_1c : 55.41 +pb_5c : 55.40 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.42 +pb_1c : 55.42 +pb_5c : 55.40 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.43 +pb_1c : 55.43 +pb_5c : 55.40 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.44 +pb_1c : 55.44 +pb_5c : 55.40 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.45 +pb_1c : 55.45 +pb_5c : 55.45 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.46 +pb_1c : 55.46 +pb_5c : 55.45 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.47 +pb_1c : 55.47 +pb_5c : 55.45 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.48 +pb_1c : 55.48 +pb_5c : 55.45 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.49 +pb_1c : 55.49 +pb_5c : 55.45 +pb_10c : 55.40 +pb_25c : 55.25 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.50 +pb_1c : 55.50 +pb_5c : 55.50 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.51 +pb_1c : 55.51 +pb_5c : 55.50 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.52 +pb_1c : 55.52 +pb_5c : 55.50 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.53 +pb_1c : 55.53 +pb_5c : 55.50 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.54 +pb_1c : 55.54 +pb_5c : 55.50 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.55 +pb_1c : 55.55 +pb_5c : 55.55 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.56 +pb_1c : 55.56 +pb_5c : 55.55 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.57 +pb_1c : 55.57 +pb_5c : 55.55 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.58 +pb_1c : 55.58 +pb_5c : 55.55 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.59 +pb_1c : 55.59 +pb_5c : 55.55 +pb_10c : 55.50 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.60 +pb_1c : 55.60 +pb_5c : 55.60 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.61 +pb_1c : 55.61 +pb_5c : 55.60 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.62 +pb_1c : 55.62 +pb_5c : 55.60 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.63 +pb_1c : 55.63 +pb_5c : 55.60 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.64 +pb_1c : 55.64 +pb_5c : 55.60 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.65 +pb_1c : 55.65 +pb_5c : 55.65 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.66 +pb_1c : 55.66 +pb_5c : 55.65 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.67 +pb_1c : 55.67 +pb_5c : 55.65 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.68 +pb_1c : 55.68 +pb_5c : 55.65 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.69 +pb_1c : 55.69 +pb_5c : 55.65 +pb_10c : 55.60 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.70 +pb_1c : 55.70 +pb_5c : 55.70 +pb_10c : 55.70 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.71 +pb_1c : 55.71 +pb_5c : 55.70 +pb_10c : 55.70 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.72 +pb_1c : 55.72 +pb_5c : 55.70 +pb_10c : 55.70 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.73 +pb_1c : 55.73 +pb_5c : 55.70 +pb_10c : 55.70 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.74 +pb_1c : 55.74 +pb_5c : 55.70 +pb_10c : 55.70 +pb_25c : 55.50 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.75 +pb_1c : 55.75 +pb_5c : 55.75 +pb_10c : 55.70 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.76 +pb_1c : 55.76 +pb_5c : 55.75 +pb_10c : 55.70 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.77 +pb_1c : 55.77 +pb_5c : 55.75 +pb_10c : 55.70 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.78 +pb_1c : 55.78 +pb_5c : 55.75 +pb_10c : 55.70 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.79 +pb_1c : 55.79 +pb_5c : 55.75 +pb_10c : 55.70 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.80 +pb_1c : 55.80 +pb_5c : 55.80 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.81 +pb_1c : 55.81 +pb_5c : 55.80 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.82 +pb_1c : 55.82 +pb_5c : 55.80 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.83 +pb_1c : 55.83 +pb_5c : 55.80 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.84 +pb_1c : 55.84 +pb_5c : 55.80 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.85 +pb_1c : 55.85 +pb_5c : 55.85 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.86 +pb_1c : 55.86 +pb_5c : 55.85 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.87 +pb_1c : 55.87 +pb_5c : 55.85 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.88 +pb_1c : 55.88 +pb_5c : 55.85 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.89 +pb_1c : 55.89 +pb_5c : 55.85 +pb_10c : 55.80 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.90 +pb_1c : 55.90 +pb_5c : 55.90 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.91 +pb_1c : 55.91 +pb_5c : 55.90 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.92 +pb_1c : 55.92 +pb_5c : 55.90 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.93 +pb_1c : 55.93 +pb_5c : 55.90 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.94 +pb_1c : 55.94 +pb_5c : 55.90 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.95 +pb_1c : 55.95 +pb_5c : 55.95 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.96 +pb_1c : 55.96 +pb_5c : 55.95 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.97 +pb_1c : 55.97 +pb_5c : 55.95 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.98 +pb_1c : 55.98 +pb_5c : 55.95 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +55.99 +pb_1c : 55.99 +pb_5c : 55.95 +pb_10c : 55.90 +pb_25c : 55.75 +pb_1d : 55.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.00 +pb_1c : 56.00 +pb_5c : 56.00 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.01 +pb_1c : 56.01 +pb_5c : 56.00 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.02 +pb_1c : 56.02 +pb_5c : 56.00 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.03 +pb_1c : 56.03 +pb_5c : 56.00 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.04 +pb_1c : 56.04 +pb_5c : 56.00 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.05 +pb_1c : 56.05 +pb_5c : 56.05 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.06 +pb_1c : 56.06 +pb_5c : 56.05 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.07 +pb_1c : 56.07 +pb_5c : 56.05 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.08 +pb_1c : 56.08 +pb_5c : 56.05 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.09 +pb_1c : 56.09 +pb_5c : 56.05 +pb_10c : 56.00 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.10 +pb_1c : 56.10 +pb_5c : 56.10 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.11 +pb_1c : 56.11 +pb_5c : 56.10 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.12 +pb_1c : 56.12 +pb_5c : 56.10 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.13 +pb_1c : 56.13 +pb_5c : 56.10 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.14 +pb_1c : 56.14 +pb_5c : 56.10 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.15 +pb_1c : 56.15 +pb_5c : 56.15 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.16 +pb_1c : 56.16 +pb_5c : 56.15 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.17 +pb_1c : 56.17 +pb_5c : 56.15 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.18 +pb_1c : 56.18 +pb_5c : 56.15 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.19 +pb_1c : 56.19 +pb_5c : 56.15 +pb_10c : 56.10 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.20 +pb_1c : 56.20 +pb_5c : 56.20 +pb_10c : 56.20 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.21 +pb_1c : 56.21 +pb_5c : 56.20 +pb_10c : 56.20 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.22 +pb_1c : 56.22 +pb_5c : 56.20 +pb_10c : 56.20 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.23 +pb_1c : 56.23 +pb_5c : 56.20 +pb_10c : 56.20 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.24 +pb_1c : 56.24 +pb_5c : 56.20 +pb_10c : 56.20 +pb_25c : 56.00 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.25 +pb_1c : 56.25 +pb_5c : 56.25 +pb_10c : 56.20 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.26 +pb_1c : 56.26 +pb_5c : 56.25 +pb_10c : 56.20 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.27 +pb_1c : 56.27 +pb_5c : 56.25 +pb_10c : 56.20 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.28 +pb_1c : 56.28 +pb_5c : 56.25 +pb_10c : 56.20 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.29 +pb_1c : 56.29 +pb_5c : 56.25 +pb_10c : 56.20 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.30 +pb_1c : 56.30 +pb_5c : 56.30 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.31 +pb_1c : 56.31 +pb_5c : 56.30 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.32 +pb_1c : 56.32 +pb_5c : 56.30 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.33 +pb_1c : 56.33 +pb_5c : 56.30 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.34 +pb_1c : 56.34 +pb_5c : 56.30 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.35 +pb_1c : 56.35 +pb_5c : 56.35 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.36 +pb_1c : 56.36 +pb_5c : 56.35 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.37 +pb_1c : 56.37 +pb_5c : 56.35 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.38 +pb_1c : 56.38 +pb_5c : 56.35 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.39 +pb_1c : 56.39 +pb_5c : 56.35 +pb_10c : 56.30 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.40 +pb_1c : 56.40 +pb_5c : 56.40 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.41 +pb_1c : 56.41 +pb_5c : 56.40 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.42 +pb_1c : 56.42 +pb_5c : 56.40 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.43 +pb_1c : 56.43 +pb_5c : 56.40 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.44 +pb_1c : 56.44 +pb_5c : 56.40 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.45 +pb_1c : 56.45 +pb_5c : 56.45 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.46 +pb_1c : 56.46 +pb_5c : 56.45 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.47 +pb_1c : 56.47 +pb_5c : 56.45 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.48 +pb_1c : 56.48 +pb_5c : 56.45 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.49 +pb_1c : 56.49 +pb_5c : 56.45 +pb_10c : 56.40 +pb_25c : 56.25 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.50 +pb_1c : 56.50 +pb_5c : 56.50 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.51 +pb_1c : 56.51 +pb_5c : 56.50 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.52 +pb_1c : 56.52 +pb_5c : 56.50 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.53 +pb_1c : 56.53 +pb_5c : 56.50 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.54 +pb_1c : 56.54 +pb_5c : 56.50 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.55 +pb_1c : 56.55 +pb_5c : 56.55 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.56 +pb_1c : 56.56 +pb_5c : 56.55 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.57 +pb_1c : 56.57 +pb_5c : 56.55 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.58 +pb_1c : 56.58 +pb_5c : 56.55 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.59 +pb_1c : 56.59 +pb_5c : 56.55 +pb_10c : 56.50 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.60 +pb_1c : 56.60 +pb_5c : 56.60 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.61 +pb_1c : 56.61 +pb_5c : 56.60 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.62 +pb_1c : 56.62 +pb_5c : 56.60 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.63 +pb_1c : 56.63 +pb_5c : 56.60 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.64 +pb_1c : 56.64 +pb_5c : 56.60 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.65 +pb_1c : 56.65 +pb_5c : 56.65 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.66 +pb_1c : 56.66 +pb_5c : 56.65 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.67 +pb_1c : 56.67 +pb_5c : 56.65 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.68 +pb_1c : 56.68 +pb_5c : 56.65 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.69 +pb_1c : 56.69 +pb_5c : 56.65 +pb_10c : 56.60 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.70 +pb_1c : 56.70 +pb_5c : 56.70 +pb_10c : 56.70 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.71 +pb_1c : 56.71 +pb_5c : 56.70 +pb_10c : 56.70 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.72 +pb_1c : 56.72 +pb_5c : 56.70 +pb_10c : 56.70 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.73 +pb_1c : 56.73 +pb_5c : 56.70 +pb_10c : 56.70 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.74 +pb_1c : 56.74 +pb_5c : 56.70 +pb_10c : 56.70 +pb_25c : 56.50 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.75 +pb_1c : 56.75 +pb_5c : 56.75 +pb_10c : 56.70 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.76 +pb_1c : 56.76 +pb_5c : 56.75 +pb_10c : 56.70 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.77 +pb_1c : 56.77 +pb_5c : 56.75 +pb_10c : 56.70 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.78 +pb_1c : 56.78 +pb_5c : 56.75 +pb_10c : 56.70 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.79 +pb_1c : 56.79 +pb_5c : 56.75 +pb_10c : 56.70 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.80 +pb_1c : 56.80 +pb_5c : 56.80 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.81 +pb_1c : 56.81 +pb_5c : 56.80 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.82 +pb_1c : 56.82 +pb_5c : 56.80 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.83 +pb_1c : 56.83 +pb_5c : 56.80 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.84 +pb_1c : 56.84 +pb_5c : 56.80 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.85 +pb_1c : 56.85 +pb_5c : 56.85 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.86 +pb_1c : 56.86 +pb_5c : 56.85 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.87 +pb_1c : 56.87 +pb_5c : 56.85 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.88 +pb_1c : 56.88 +pb_5c : 56.85 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.89 +pb_1c : 56.89 +pb_5c : 56.85 +pb_10c : 56.80 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.90 +pb_1c : 56.90 +pb_5c : 56.90 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.91 +pb_1c : 56.91 +pb_5c : 56.90 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.92 +pb_1c : 56.92 +pb_5c : 56.90 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.93 +pb_1c : 56.93 +pb_5c : 56.90 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.94 +pb_1c : 56.94 +pb_5c : 56.90 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.95 +pb_1c : 56.95 +pb_5c : 56.95 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.96 +pb_1c : 56.96 +pb_5c : 56.95 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.97 +pb_1c : 56.97 +pb_5c : 56.95 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.98 +pb_1c : 56.98 +pb_5c : 56.95 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +56.99 +pb_1c : 56.99 +pb_5c : 56.95 +pb_10c : 56.90 +pb_25c : 56.75 +pb_1d : 56.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.00 +pb_1c : 57.00 +pb_5c : 57.00 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.01 +pb_1c : 57.01 +pb_5c : 57.00 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.02 +pb_1c : 57.02 +pb_5c : 57.00 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.03 +pb_1c : 57.03 +pb_5c : 57.00 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.04 +pb_1c : 57.04 +pb_5c : 57.00 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.05 +pb_1c : 57.05 +pb_5c : 57.05 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.06 +pb_1c : 57.06 +pb_5c : 57.05 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.07 +pb_1c : 57.07 +pb_5c : 57.05 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.08 +pb_1c : 57.08 +pb_5c : 57.05 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.09 +pb_1c : 57.09 +pb_5c : 57.05 +pb_10c : 57.00 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.10 +pb_1c : 57.10 +pb_5c : 57.10 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.11 +pb_1c : 57.11 +pb_5c : 57.10 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.12 +pb_1c : 57.12 +pb_5c : 57.10 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.13 +pb_1c : 57.13 +pb_5c : 57.10 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.14 +pb_1c : 57.14 +pb_5c : 57.10 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.15 +pb_1c : 57.15 +pb_5c : 57.15 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.16 +pb_1c : 57.16 +pb_5c : 57.15 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.17 +pb_1c : 57.17 +pb_5c : 57.15 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.18 +pb_1c : 57.18 +pb_5c : 57.15 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.19 +pb_1c : 57.19 +pb_5c : 57.15 +pb_10c : 57.10 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.20 +pb_1c : 57.20 +pb_5c : 57.20 +pb_10c : 57.20 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.21 +pb_1c : 57.21 +pb_5c : 57.20 +pb_10c : 57.20 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.22 +pb_1c : 57.22 +pb_5c : 57.20 +pb_10c : 57.20 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.23 +pb_1c : 57.23 +pb_5c : 57.20 +pb_10c : 57.20 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.24 +pb_1c : 57.24 +pb_5c : 57.20 +pb_10c : 57.20 +pb_25c : 57.00 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.25 +pb_1c : 57.25 +pb_5c : 57.25 +pb_10c : 57.20 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.26 +pb_1c : 57.26 +pb_5c : 57.25 +pb_10c : 57.20 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.27 +pb_1c : 57.27 +pb_5c : 57.25 +pb_10c : 57.20 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.28 +pb_1c : 57.28 +pb_5c : 57.25 +pb_10c : 57.20 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.29 +pb_1c : 57.29 +pb_5c : 57.25 +pb_10c : 57.20 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.30 +pb_1c : 57.30 +pb_5c : 57.30 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.31 +pb_1c : 57.31 +pb_5c : 57.30 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.32 +pb_1c : 57.32 +pb_5c : 57.30 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.33 +pb_1c : 57.33 +pb_5c : 57.30 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.34 +pb_1c : 57.34 +pb_5c : 57.30 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.35 +pb_1c : 57.35 +pb_5c : 57.35 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.36 +pb_1c : 57.36 +pb_5c : 57.35 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.37 +pb_1c : 57.37 +pb_5c : 57.35 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.38 +pb_1c : 57.38 +pb_5c : 57.35 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.39 +pb_1c : 57.39 +pb_5c : 57.35 +pb_10c : 57.30 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.40 +pb_1c : 57.40 +pb_5c : 57.40 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.41 +pb_1c : 57.41 +pb_5c : 57.40 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.42 +pb_1c : 57.42 +pb_5c : 57.40 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.43 +pb_1c : 57.43 +pb_5c : 57.40 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.44 +pb_1c : 57.44 +pb_5c : 57.40 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.45 +pb_1c : 57.45 +pb_5c : 57.45 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.46 +pb_1c : 57.46 +pb_5c : 57.45 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.47 +pb_1c : 57.47 +pb_5c : 57.45 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.48 +pb_1c : 57.48 +pb_5c : 57.45 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.49 +pb_1c : 57.49 +pb_5c : 57.45 +pb_10c : 57.40 +pb_25c : 57.25 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.50 +pb_1c : 57.50 +pb_5c : 57.50 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.51 +pb_1c : 57.51 +pb_5c : 57.50 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.52 +pb_1c : 57.52 +pb_5c : 57.50 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.53 +pb_1c : 57.53 +pb_5c : 57.50 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.54 +pb_1c : 57.54 +pb_5c : 57.50 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.55 +pb_1c : 57.55 +pb_5c : 57.55 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.56 +pb_1c : 57.56 +pb_5c : 57.55 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.57 +pb_1c : 57.57 +pb_5c : 57.55 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.58 +pb_1c : 57.58 +pb_5c : 57.55 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.59 +pb_1c : 57.59 +pb_5c : 57.55 +pb_10c : 57.50 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.60 +pb_1c : 57.60 +pb_5c : 57.60 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.61 +pb_1c : 57.61 +pb_5c : 57.60 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.62 +pb_1c : 57.62 +pb_5c : 57.60 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.63 +pb_1c : 57.63 +pb_5c : 57.60 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.64 +pb_1c : 57.64 +pb_5c : 57.60 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.65 +pb_1c : 57.65 +pb_5c : 57.65 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.66 +pb_1c : 57.66 +pb_5c : 57.65 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.67 +pb_1c : 57.67 +pb_5c : 57.65 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.68 +pb_1c : 57.68 +pb_5c : 57.65 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.69 +pb_1c : 57.69 +pb_5c : 57.65 +pb_10c : 57.60 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.70 +pb_1c : 57.70 +pb_5c : 57.70 +pb_10c : 57.70 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.71 +pb_1c : 57.71 +pb_5c : 57.70 +pb_10c : 57.70 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.72 +pb_1c : 57.72 +pb_5c : 57.70 +pb_10c : 57.70 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.73 +pb_1c : 57.73 +pb_5c : 57.70 +pb_10c : 57.70 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.74 +pb_1c : 57.74 +pb_5c : 57.70 +pb_10c : 57.70 +pb_25c : 57.50 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.75 +pb_1c : 57.75 +pb_5c : 57.75 +pb_10c : 57.70 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.76 +pb_1c : 57.76 +pb_5c : 57.75 +pb_10c : 57.70 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.77 +pb_1c : 57.77 +pb_5c : 57.75 +pb_10c : 57.70 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.78 +pb_1c : 57.78 +pb_5c : 57.75 +pb_10c : 57.70 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.79 +pb_1c : 57.79 +pb_5c : 57.75 +pb_10c : 57.70 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.80 +pb_1c : 57.80 +pb_5c : 57.80 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.81 +pb_1c : 57.81 +pb_5c : 57.80 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.82 +pb_1c : 57.82 +pb_5c : 57.80 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.83 +pb_1c : 57.83 +pb_5c : 57.80 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.84 +pb_1c : 57.84 +pb_5c : 57.80 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.85 +pb_1c : 57.85 +pb_5c : 57.85 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.86 +pb_1c : 57.86 +pb_5c : 57.85 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.87 +pb_1c : 57.87 +pb_5c : 57.85 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.88 +pb_1c : 57.88 +pb_5c : 57.85 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.89 +pb_1c : 57.89 +pb_5c : 57.85 +pb_10c : 57.80 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.90 +pb_1c : 57.90 +pb_5c : 57.90 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.91 +pb_1c : 57.91 +pb_5c : 57.90 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.92 +pb_1c : 57.92 +pb_5c : 57.90 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.93 +pb_1c : 57.93 +pb_5c : 57.90 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.94 +pb_1c : 57.94 +pb_5c : 57.90 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.95 +pb_1c : 57.95 +pb_5c : 57.95 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.96 +pb_1c : 57.96 +pb_5c : 57.95 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.97 +pb_1c : 57.97 +pb_5c : 57.95 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.98 +pb_1c : 57.98 +pb_5c : 57.95 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +57.99 +pb_1c : 57.99 +pb_5c : 57.95 +pb_10c : 57.90 +pb_25c : 57.75 +pb_1d : 57.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.00 +pb_1c : 58.00 +pb_5c : 58.00 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.01 +pb_1c : 58.01 +pb_5c : 58.00 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.02 +pb_1c : 58.02 +pb_5c : 58.00 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.03 +pb_1c : 58.03 +pb_5c : 58.00 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.04 +pb_1c : 58.04 +pb_5c : 58.00 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.05 +pb_1c : 58.05 +pb_5c : 58.05 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.06 +pb_1c : 58.06 +pb_5c : 58.05 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.07 +pb_1c : 58.07 +pb_5c : 58.05 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.08 +pb_1c : 58.08 +pb_5c : 58.05 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.09 +pb_1c : 58.09 +pb_5c : 58.05 +pb_10c : 58.00 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.10 +pb_1c : 58.10 +pb_5c : 58.10 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.11 +pb_1c : 58.11 +pb_5c : 58.10 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.12 +pb_1c : 58.12 +pb_5c : 58.10 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.13 +pb_1c : 58.13 +pb_5c : 58.10 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.14 +pb_1c : 58.14 +pb_5c : 58.10 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.15 +pb_1c : 58.15 +pb_5c : 58.15 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.16 +pb_1c : 58.16 +pb_5c : 58.15 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.17 +pb_1c : 58.17 +pb_5c : 58.15 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.18 +pb_1c : 58.18 +pb_5c : 58.15 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.19 +pb_1c : 58.19 +pb_5c : 58.15 +pb_10c : 58.10 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.20 +pb_1c : 58.20 +pb_5c : 58.20 +pb_10c : 58.20 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.21 +pb_1c : 58.21 +pb_5c : 58.20 +pb_10c : 58.20 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.22 +pb_1c : 58.22 +pb_5c : 58.20 +pb_10c : 58.20 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.23 +pb_1c : 58.23 +pb_5c : 58.20 +pb_10c : 58.20 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.24 +pb_1c : 58.24 +pb_5c : 58.20 +pb_10c : 58.20 +pb_25c : 58.00 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.25 +pb_1c : 58.25 +pb_5c : 58.25 +pb_10c : 58.20 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.26 +pb_1c : 58.26 +pb_5c : 58.25 +pb_10c : 58.20 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.27 +pb_1c : 58.27 +pb_5c : 58.25 +pb_10c : 58.20 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.28 +pb_1c : 58.28 +pb_5c : 58.25 +pb_10c : 58.20 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.29 +pb_1c : 58.29 +pb_5c : 58.25 +pb_10c : 58.20 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.30 +pb_1c : 58.30 +pb_5c : 58.30 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.31 +pb_1c : 58.31 +pb_5c : 58.30 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.32 +pb_1c : 58.32 +pb_5c : 58.30 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.33 +pb_1c : 58.33 +pb_5c : 58.30 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.34 +pb_1c : 58.34 +pb_5c : 58.30 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.35 +pb_1c : 58.35 +pb_5c : 58.35 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.36 +pb_1c : 58.36 +pb_5c : 58.35 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.37 +pb_1c : 58.37 +pb_5c : 58.35 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.38 +pb_1c : 58.38 +pb_5c : 58.35 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.39 +pb_1c : 58.39 +pb_5c : 58.35 +pb_10c : 58.30 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.40 +pb_1c : 58.40 +pb_5c : 58.40 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.41 +pb_1c : 58.41 +pb_5c : 58.40 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.42 +pb_1c : 58.42 +pb_5c : 58.40 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.43 +pb_1c : 58.43 +pb_5c : 58.40 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.44 +pb_1c : 58.44 +pb_5c : 58.40 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.45 +pb_1c : 58.45 +pb_5c : 58.45 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.46 +pb_1c : 58.46 +pb_5c : 58.45 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.47 +pb_1c : 58.47 +pb_5c : 58.45 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.48 +pb_1c : 58.48 +pb_5c : 58.45 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.49 +pb_1c : 58.49 +pb_5c : 58.45 +pb_10c : 58.40 +pb_25c : 58.25 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.50 +pb_1c : 58.50 +pb_5c : 58.50 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.51 +pb_1c : 58.51 +pb_5c : 58.50 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.52 +pb_1c : 58.52 +pb_5c : 58.50 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.53 +pb_1c : 58.53 +pb_5c : 58.50 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.54 +pb_1c : 58.54 +pb_5c : 58.50 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.55 +pb_1c : 58.55 +pb_5c : 58.55 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.56 +pb_1c : 58.56 +pb_5c : 58.55 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.57 +pb_1c : 58.57 +pb_5c : 58.55 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.58 +pb_1c : 58.58 +pb_5c : 58.55 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.59 +pb_1c : 58.59 +pb_5c : 58.55 +pb_10c : 58.50 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.60 +pb_1c : 58.60 +pb_5c : 58.60 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.61 +pb_1c : 58.61 +pb_5c : 58.60 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.62 +pb_1c : 58.62 +pb_5c : 58.60 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.63 +pb_1c : 58.63 +pb_5c : 58.60 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.64 +pb_1c : 58.64 +pb_5c : 58.60 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.65 +pb_1c : 58.65 +pb_5c : 58.65 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.66 +pb_1c : 58.66 +pb_5c : 58.65 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.67 +pb_1c : 58.67 +pb_5c : 58.65 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.68 +pb_1c : 58.68 +pb_5c : 58.65 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.69 +pb_1c : 58.69 +pb_5c : 58.65 +pb_10c : 58.60 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.70 +pb_1c : 58.70 +pb_5c : 58.70 +pb_10c : 58.70 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.71 +pb_1c : 58.71 +pb_5c : 58.70 +pb_10c : 58.70 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.72 +pb_1c : 58.72 +pb_5c : 58.70 +pb_10c : 58.70 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.73 +pb_1c : 58.73 +pb_5c : 58.70 +pb_10c : 58.70 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.74 +pb_1c : 58.74 +pb_5c : 58.70 +pb_10c : 58.70 +pb_25c : 58.50 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.75 +pb_1c : 58.75 +pb_5c : 58.75 +pb_10c : 58.70 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.76 +pb_1c : 58.76 +pb_5c : 58.75 +pb_10c : 58.70 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.77 +pb_1c : 58.77 +pb_5c : 58.75 +pb_10c : 58.70 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.78 +pb_1c : 58.78 +pb_5c : 58.75 +pb_10c : 58.70 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.79 +pb_1c : 58.79 +pb_5c : 58.75 +pb_10c : 58.70 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.80 +pb_1c : 58.80 +pb_5c : 58.80 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.81 +pb_1c : 58.81 +pb_5c : 58.80 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.82 +pb_1c : 58.82 +pb_5c : 58.80 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.83 +pb_1c : 58.83 +pb_5c : 58.80 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.84 +pb_1c : 58.84 +pb_5c : 58.80 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.85 +pb_1c : 58.85 +pb_5c : 58.85 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.86 +pb_1c : 58.86 +pb_5c : 58.85 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.87 +pb_1c : 58.87 +pb_5c : 58.85 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.88 +pb_1c : 58.88 +pb_5c : 58.85 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.89 +pb_1c : 58.89 +pb_5c : 58.85 +pb_10c : 58.80 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.90 +pb_1c : 58.90 +pb_5c : 58.90 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.91 +pb_1c : 58.91 +pb_5c : 58.90 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.92 +pb_1c : 58.92 +pb_5c : 58.90 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.93 +pb_1c : 58.93 +pb_5c : 58.90 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.94 +pb_1c : 58.94 +pb_5c : 58.90 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.95 +pb_1c : 58.95 +pb_5c : 58.95 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.96 +pb_1c : 58.96 +pb_5c : 58.95 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.97 +pb_1c : 58.97 +pb_5c : 58.95 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.98 +pb_1c : 58.98 +pb_5c : 58.95 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +58.99 +pb_1c : 58.99 +pb_5c : 58.95 +pb_10c : 58.90 +pb_25c : 58.75 +pb_1d : 58.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.00 +pb_1c : 59.00 +pb_5c : 59.00 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.01 +pb_1c : 59.01 +pb_5c : 59.00 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.02 +pb_1c : 59.02 +pb_5c : 59.00 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.03 +pb_1c : 59.03 +pb_5c : 59.00 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.04 +pb_1c : 59.04 +pb_5c : 59.00 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.05 +pb_1c : 59.05 +pb_5c : 59.05 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.06 +pb_1c : 59.06 +pb_5c : 59.05 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.07 +pb_1c : 59.07 +pb_5c : 59.05 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.08 +pb_1c : 59.08 +pb_5c : 59.05 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.09 +pb_1c : 59.09 +pb_5c : 59.05 +pb_10c : 59.00 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.10 +pb_1c : 59.10 +pb_5c : 59.10 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.11 +pb_1c : 59.11 +pb_5c : 59.10 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.12 +pb_1c : 59.12 +pb_5c : 59.10 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.13 +pb_1c : 59.13 +pb_5c : 59.10 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.14 +pb_1c : 59.14 +pb_5c : 59.10 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.15 +pb_1c : 59.15 +pb_5c : 59.15 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.16 +pb_1c : 59.16 +pb_5c : 59.15 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.17 +pb_1c : 59.17 +pb_5c : 59.15 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.18 +pb_1c : 59.18 +pb_5c : 59.15 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.19 +pb_1c : 59.19 +pb_5c : 59.15 +pb_10c : 59.10 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.20 +pb_1c : 59.20 +pb_5c : 59.20 +pb_10c : 59.20 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.21 +pb_1c : 59.21 +pb_5c : 59.20 +pb_10c : 59.20 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.22 +pb_1c : 59.22 +pb_5c : 59.20 +pb_10c : 59.20 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.23 +pb_1c : 59.23 +pb_5c : 59.20 +pb_10c : 59.20 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.24 +pb_1c : 59.24 +pb_5c : 59.20 +pb_10c : 59.20 +pb_25c : 59.00 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.25 +pb_1c : 59.25 +pb_5c : 59.25 +pb_10c : 59.20 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.26 +pb_1c : 59.26 +pb_5c : 59.25 +pb_10c : 59.20 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.27 +pb_1c : 59.27 +pb_5c : 59.25 +pb_10c : 59.20 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.28 +pb_1c : 59.28 +pb_5c : 59.25 +pb_10c : 59.20 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.29 +pb_1c : 59.29 +pb_5c : 59.25 +pb_10c : 59.20 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.30 +pb_1c : 59.30 +pb_5c : 59.30 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.31 +pb_1c : 59.31 +pb_5c : 59.30 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.32 +pb_1c : 59.32 +pb_5c : 59.30 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.33 +pb_1c : 59.33 +pb_5c : 59.30 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.34 +pb_1c : 59.34 +pb_5c : 59.30 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.35 +pb_1c : 59.35 +pb_5c : 59.35 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.36 +pb_1c : 59.36 +pb_5c : 59.35 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.37 +pb_1c : 59.37 +pb_5c : 59.35 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.38 +pb_1c : 59.38 +pb_5c : 59.35 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.39 +pb_1c : 59.39 +pb_5c : 59.35 +pb_10c : 59.30 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.40 +pb_1c : 59.40 +pb_5c : 59.40 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.41 +pb_1c : 59.41 +pb_5c : 59.40 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.42 +pb_1c : 59.42 +pb_5c : 59.40 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.43 +pb_1c : 59.43 +pb_5c : 59.40 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.44 +pb_1c : 59.44 +pb_5c : 59.40 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.45 +pb_1c : 59.45 +pb_5c : 59.45 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.46 +pb_1c : 59.46 +pb_5c : 59.45 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.47 +pb_1c : 59.47 +pb_5c : 59.45 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.48 +pb_1c : 59.48 +pb_5c : 59.45 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.49 +pb_1c : 59.49 +pb_5c : 59.45 +pb_10c : 59.40 +pb_25c : 59.25 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.50 +pb_1c : 59.50 +pb_5c : 59.50 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.51 +pb_1c : 59.51 +pb_5c : 59.50 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.52 +pb_1c : 59.52 +pb_5c : 59.50 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.53 +pb_1c : 59.53 +pb_5c : 59.50 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.54 +pb_1c : 59.54 +pb_5c : 59.50 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.55 +pb_1c : 59.55 +pb_5c : 59.55 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.56 +pb_1c : 59.56 +pb_5c : 59.55 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.57 +pb_1c : 59.57 +pb_5c : 59.55 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.58 +pb_1c : 59.58 +pb_5c : 59.55 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.59 +pb_1c : 59.59 +pb_5c : 59.55 +pb_10c : 59.50 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.60 +pb_1c : 59.60 +pb_5c : 59.60 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.61 +pb_1c : 59.61 +pb_5c : 59.60 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.62 +pb_1c : 59.62 +pb_5c : 59.60 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.63 +pb_1c : 59.63 +pb_5c : 59.60 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.64 +pb_1c : 59.64 +pb_5c : 59.60 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.65 +pb_1c : 59.65 +pb_5c : 59.65 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.66 +pb_1c : 59.66 +pb_5c : 59.65 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.67 +pb_1c : 59.67 +pb_5c : 59.65 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.68 +pb_1c : 59.68 +pb_5c : 59.65 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.69 +pb_1c : 59.69 +pb_5c : 59.65 +pb_10c : 59.60 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.70 +pb_1c : 59.70 +pb_5c : 59.70 +pb_10c : 59.70 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.71 +pb_1c : 59.71 +pb_5c : 59.70 +pb_10c : 59.70 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.72 +pb_1c : 59.72 +pb_5c : 59.70 +pb_10c : 59.70 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.73 +pb_1c : 59.73 +pb_5c : 59.70 +pb_10c : 59.70 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.74 +pb_1c : 59.74 +pb_5c : 59.70 +pb_10c : 59.70 +pb_25c : 59.50 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.75 +pb_1c : 59.75 +pb_5c : 59.75 +pb_10c : 59.70 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.76 +pb_1c : 59.76 +pb_5c : 59.75 +pb_10c : 59.70 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.77 +pb_1c : 59.77 +pb_5c : 59.75 +pb_10c : 59.70 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.78 +pb_1c : 59.78 +pb_5c : 59.75 +pb_10c : 59.70 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.79 +pb_1c : 59.79 +pb_5c : 59.75 +pb_10c : 59.70 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.80 +pb_1c : 59.80 +pb_5c : 59.80 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.81 +pb_1c : 59.81 +pb_5c : 59.80 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.82 +pb_1c : 59.82 +pb_5c : 59.80 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.83 +pb_1c : 59.83 +pb_5c : 59.80 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.84 +pb_1c : 59.84 +pb_5c : 59.80 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.85 +pb_1c : 59.85 +pb_5c : 59.85 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.86 +pb_1c : 59.86 +pb_5c : 59.85 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.87 +pb_1c : 59.87 +pb_5c : 59.85 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.88 +pb_1c : 59.88 +pb_5c : 59.85 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.89 +pb_1c : 59.89 +pb_5c : 59.85 +pb_10c : 59.80 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.90 +pb_1c : 59.90 +pb_5c : 59.90 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.91 +pb_1c : 59.91 +pb_5c : 59.90 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.92 +pb_1c : 59.92 +pb_5c : 59.90 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.93 +pb_1c : 59.93 +pb_5c : 59.90 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.94 +pb_1c : 59.94 +pb_5c : 59.90 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.95 +pb_1c : 59.95 +pb_5c : 59.95 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.96 +pb_1c : 59.96 +pb_5c : 59.95 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.97 +pb_1c : 59.97 +pb_5c : 59.95 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.98 +pb_1c : 59.98 +pb_5c : 59.95 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +59.99 +pb_1c : 59.99 +pb_5c : 59.95 +pb_10c : 59.90 +pb_25c : 59.75 +pb_1d : 59.00 +pb_5d : 55.00 +pb_10d : 50.00 + +60.00 +pb_1c : 60.00 +pb_5c : 60.00 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.01 +pb_1c : 60.01 +pb_5c : 60.00 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.02 +pb_1c : 60.02 +pb_5c : 60.00 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.03 +pb_1c : 60.03 +pb_5c : 60.00 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.04 +pb_1c : 60.04 +pb_5c : 60.00 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.05 +pb_1c : 60.05 +pb_5c : 60.05 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.06 +pb_1c : 60.06 +pb_5c : 60.05 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.07 +pb_1c : 60.07 +pb_5c : 60.05 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.08 +pb_1c : 60.08 +pb_5c : 60.05 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.09 +pb_1c : 60.09 +pb_5c : 60.05 +pb_10c : 60.00 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.10 +pb_1c : 60.10 +pb_5c : 60.10 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.11 +pb_1c : 60.11 +pb_5c : 60.10 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.12 +pb_1c : 60.12 +pb_5c : 60.10 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.13 +pb_1c : 60.13 +pb_5c : 60.10 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.14 +pb_1c : 60.14 +pb_5c : 60.10 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.15 +pb_1c : 60.15 +pb_5c : 60.15 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.16 +pb_1c : 60.16 +pb_5c : 60.15 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.17 +pb_1c : 60.17 +pb_5c : 60.15 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.18 +pb_1c : 60.18 +pb_5c : 60.15 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.19 +pb_1c : 60.19 +pb_5c : 60.15 +pb_10c : 60.10 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.20 +pb_1c : 60.20 +pb_5c : 60.20 +pb_10c : 60.20 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.21 +pb_1c : 60.21 +pb_5c : 60.20 +pb_10c : 60.20 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.22 +pb_1c : 60.22 +pb_5c : 60.20 +pb_10c : 60.20 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.23 +pb_1c : 60.23 +pb_5c : 60.20 +pb_10c : 60.20 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.24 +pb_1c : 60.24 +pb_5c : 60.20 +pb_10c : 60.20 +pb_25c : 60.00 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.25 +pb_1c : 60.25 +pb_5c : 60.25 +pb_10c : 60.20 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.26 +pb_1c : 60.26 +pb_5c : 60.25 +pb_10c : 60.20 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.27 +pb_1c : 60.27 +pb_5c : 60.25 +pb_10c : 60.20 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.28 +pb_1c : 60.28 +pb_5c : 60.25 +pb_10c : 60.20 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.29 +pb_1c : 60.29 +pb_5c : 60.25 +pb_10c : 60.20 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.30 +pb_1c : 60.30 +pb_5c : 60.30 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.31 +pb_1c : 60.31 +pb_5c : 60.30 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.32 +pb_1c : 60.32 +pb_5c : 60.30 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.33 +pb_1c : 60.33 +pb_5c : 60.30 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.34 +pb_1c : 60.34 +pb_5c : 60.30 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.35 +pb_1c : 60.35 +pb_5c : 60.35 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.36 +pb_1c : 60.36 +pb_5c : 60.35 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.37 +pb_1c : 60.37 +pb_5c : 60.35 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.38 +pb_1c : 60.38 +pb_5c : 60.35 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.39 +pb_1c : 60.39 +pb_5c : 60.35 +pb_10c : 60.30 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.40 +pb_1c : 60.40 +pb_5c : 60.40 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.41 +pb_1c : 60.41 +pb_5c : 60.40 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.42 +pb_1c : 60.42 +pb_5c : 60.40 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.43 +pb_1c : 60.43 +pb_5c : 60.40 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.44 +pb_1c : 60.44 +pb_5c : 60.40 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.45 +pb_1c : 60.45 +pb_5c : 60.45 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.46 +pb_1c : 60.46 +pb_5c : 60.45 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.47 +pb_1c : 60.47 +pb_5c : 60.45 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.48 +pb_1c : 60.48 +pb_5c : 60.45 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.49 +pb_1c : 60.49 +pb_5c : 60.45 +pb_10c : 60.40 +pb_25c : 60.25 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.50 +pb_1c : 60.50 +pb_5c : 60.50 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.51 +pb_1c : 60.51 +pb_5c : 60.50 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.52 +pb_1c : 60.52 +pb_5c : 60.50 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.53 +pb_1c : 60.53 +pb_5c : 60.50 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.54 +pb_1c : 60.54 +pb_5c : 60.50 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.55 +pb_1c : 60.55 +pb_5c : 60.55 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.56 +pb_1c : 60.56 +pb_5c : 60.55 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.57 +pb_1c : 60.57 +pb_5c : 60.55 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.58 +pb_1c : 60.58 +pb_5c : 60.55 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.59 +pb_1c : 60.59 +pb_5c : 60.55 +pb_10c : 60.50 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.60 +pb_1c : 60.60 +pb_5c : 60.60 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.61 +pb_1c : 60.61 +pb_5c : 60.60 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.62 +pb_1c : 60.62 +pb_5c : 60.60 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.63 +pb_1c : 60.63 +pb_5c : 60.60 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.64 +pb_1c : 60.64 +pb_5c : 60.60 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.65 +pb_1c : 60.65 +pb_5c : 60.65 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.66 +pb_1c : 60.66 +pb_5c : 60.65 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.67 +pb_1c : 60.67 +pb_5c : 60.65 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.68 +pb_1c : 60.68 +pb_5c : 60.65 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.69 +pb_1c : 60.69 +pb_5c : 60.65 +pb_10c : 60.60 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.70 +pb_1c : 60.70 +pb_5c : 60.70 +pb_10c : 60.70 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.71 +pb_1c : 60.71 +pb_5c : 60.70 +pb_10c : 60.70 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.72 +pb_1c : 60.72 +pb_5c : 60.70 +pb_10c : 60.70 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.73 +pb_1c : 60.73 +pb_5c : 60.70 +pb_10c : 60.70 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.74 +pb_1c : 60.74 +pb_5c : 60.70 +pb_10c : 60.70 +pb_25c : 60.50 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.75 +pb_1c : 60.75 +pb_5c : 60.75 +pb_10c : 60.70 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.76 +pb_1c : 60.76 +pb_5c : 60.75 +pb_10c : 60.70 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.77 +pb_1c : 60.77 +pb_5c : 60.75 +pb_10c : 60.70 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.78 +pb_1c : 60.78 +pb_5c : 60.75 +pb_10c : 60.70 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.79 +pb_1c : 60.79 +pb_5c : 60.75 +pb_10c : 60.70 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.80 +pb_1c : 60.80 +pb_5c : 60.80 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.81 +pb_1c : 60.81 +pb_5c : 60.80 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.82 +pb_1c : 60.82 +pb_5c : 60.80 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.83 +pb_1c : 60.83 +pb_5c : 60.80 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.84 +pb_1c : 60.84 +pb_5c : 60.80 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.85 +pb_1c : 60.85 +pb_5c : 60.85 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.86 +pb_1c : 60.86 +pb_5c : 60.85 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.87 +pb_1c : 60.87 +pb_5c : 60.85 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.88 +pb_1c : 60.88 +pb_5c : 60.85 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.89 +pb_1c : 60.89 +pb_5c : 60.85 +pb_10c : 60.80 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.90 +pb_1c : 60.90 +pb_5c : 60.90 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.91 +pb_1c : 60.91 +pb_5c : 60.90 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.92 +pb_1c : 60.92 +pb_5c : 60.90 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.93 +pb_1c : 60.93 +pb_5c : 60.90 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.94 +pb_1c : 60.94 +pb_5c : 60.90 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.95 +pb_1c : 60.95 +pb_5c : 60.95 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.96 +pb_1c : 60.96 +pb_5c : 60.95 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.97 +pb_1c : 60.97 +pb_5c : 60.95 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.98 +pb_1c : 60.98 +pb_5c : 60.95 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +60.99 +pb_1c : 60.99 +pb_5c : 60.95 +pb_10c : 60.90 +pb_25c : 60.75 +pb_1d : 60.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.00 +pb_1c : 61.00 +pb_5c : 61.00 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.01 +pb_1c : 61.01 +pb_5c : 61.00 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.02 +pb_1c : 61.02 +pb_5c : 61.00 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.03 +pb_1c : 61.03 +pb_5c : 61.00 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.04 +pb_1c : 61.04 +pb_5c : 61.00 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.05 +pb_1c : 61.05 +pb_5c : 61.05 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.06 +pb_1c : 61.06 +pb_5c : 61.05 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.07 +pb_1c : 61.07 +pb_5c : 61.05 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.08 +pb_1c : 61.08 +pb_5c : 61.05 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.09 +pb_1c : 61.09 +pb_5c : 61.05 +pb_10c : 61.00 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.10 +pb_1c : 61.10 +pb_5c : 61.10 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.11 +pb_1c : 61.11 +pb_5c : 61.10 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.12 +pb_1c : 61.12 +pb_5c : 61.10 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.13 +pb_1c : 61.13 +pb_5c : 61.10 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.14 +pb_1c : 61.14 +pb_5c : 61.10 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.15 +pb_1c : 61.15 +pb_5c : 61.15 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.16 +pb_1c : 61.16 +pb_5c : 61.15 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.17 +pb_1c : 61.17 +pb_5c : 61.15 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.18 +pb_1c : 61.18 +pb_5c : 61.15 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.19 +pb_1c : 61.19 +pb_5c : 61.15 +pb_10c : 61.10 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.20 +pb_1c : 61.20 +pb_5c : 61.20 +pb_10c : 61.20 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.21 +pb_1c : 61.21 +pb_5c : 61.20 +pb_10c : 61.20 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.22 +pb_1c : 61.22 +pb_5c : 61.20 +pb_10c : 61.20 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.23 +pb_1c : 61.23 +pb_5c : 61.20 +pb_10c : 61.20 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.24 +pb_1c : 61.24 +pb_5c : 61.20 +pb_10c : 61.20 +pb_25c : 61.00 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.25 +pb_1c : 61.25 +pb_5c : 61.25 +pb_10c : 61.20 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.26 +pb_1c : 61.26 +pb_5c : 61.25 +pb_10c : 61.20 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.27 +pb_1c : 61.27 +pb_5c : 61.25 +pb_10c : 61.20 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.28 +pb_1c : 61.28 +pb_5c : 61.25 +pb_10c : 61.20 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.29 +pb_1c : 61.29 +pb_5c : 61.25 +pb_10c : 61.20 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.30 +pb_1c : 61.30 +pb_5c : 61.30 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.31 +pb_1c : 61.31 +pb_5c : 61.30 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.32 +pb_1c : 61.32 +pb_5c : 61.30 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.33 +pb_1c : 61.33 +pb_5c : 61.30 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.34 +pb_1c : 61.34 +pb_5c : 61.30 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.35 +pb_1c : 61.35 +pb_5c : 61.35 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.36 +pb_1c : 61.36 +pb_5c : 61.35 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.37 +pb_1c : 61.37 +pb_5c : 61.35 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.38 +pb_1c : 61.38 +pb_5c : 61.35 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.39 +pb_1c : 61.39 +pb_5c : 61.35 +pb_10c : 61.30 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.40 +pb_1c : 61.40 +pb_5c : 61.40 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.41 +pb_1c : 61.41 +pb_5c : 61.40 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.42 +pb_1c : 61.42 +pb_5c : 61.40 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.43 +pb_1c : 61.43 +pb_5c : 61.40 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.44 +pb_1c : 61.44 +pb_5c : 61.40 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.45 +pb_1c : 61.45 +pb_5c : 61.45 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.46 +pb_1c : 61.46 +pb_5c : 61.45 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.47 +pb_1c : 61.47 +pb_5c : 61.45 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.48 +pb_1c : 61.48 +pb_5c : 61.45 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.49 +pb_1c : 61.49 +pb_5c : 61.45 +pb_10c : 61.40 +pb_25c : 61.25 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.50 +pb_1c : 61.50 +pb_5c : 61.50 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.51 +pb_1c : 61.51 +pb_5c : 61.50 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.52 +pb_1c : 61.52 +pb_5c : 61.50 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.53 +pb_1c : 61.53 +pb_5c : 61.50 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.54 +pb_1c : 61.54 +pb_5c : 61.50 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.55 +pb_1c : 61.55 +pb_5c : 61.55 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.56 +pb_1c : 61.56 +pb_5c : 61.55 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.57 +pb_1c : 61.57 +pb_5c : 61.55 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.58 +pb_1c : 61.58 +pb_5c : 61.55 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.59 +pb_1c : 61.59 +pb_5c : 61.55 +pb_10c : 61.50 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.60 +pb_1c : 61.60 +pb_5c : 61.60 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.61 +pb_1c : 61.61 +pb_5c : 61.60 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.62 +pb_1c : 61.62 +pb_5c : 61.60 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.63 +pb_1c : 61.63 +pb_5c : 61.60 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.64 +pb_1c : 61.64 +pb_5c : 61.60 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.65 +pb_1c : 61.65 +pb_5c : 61.65 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.66 +pb_1c : 61.66 +pb_5c : 61.65 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.67 +pb_1c : 61.67 +pb_5c : 61.65 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.68 +pb_1c : 61.68 +pb_5c : 61.65 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.69 +pb_1c : 61.69 +pb_5c : 61.65 +pb_10c : 61.60 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.70 +pb_1c : 61.70 +pb_5c : 61.70 +pb_10c : 61.70 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.71 +pb_1c : 61.71 +pb_5c : 61.70 +pb_10c : 61.70 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.72 +pb_1c : 61.72 +pb_5c : 61.70 +pb_10c : 61.70 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.73 +pb_1c : 61.73 +pb_5c : 61.70 +pb_10c : 61.70 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.74 +pb_1c : 61.74 +pb_5c : 61.70 +pb_10c : 61.70 +pb_25c : 61.50 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.75 +pb_1c : 61.75 +pb_5c : 61.75 +pb_10c : 61.70 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.76 +pb_1c : 61.76 +pb_5c : 61.75 +pb_10c : 61.70 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.77 +pb_1c : 61.77 +pb_5c : 61.75 +pb_10c : 61.70 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.78 +pb_1c : 61.78 +pb_5c : 61.75 +pb_10c : 61.70 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.79 +pb_1c : 61.79 +pb_5c : 61.75 +pb_10c : 61.70 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.80 +pb_1c : 61.80 +pb_5c : 61.80 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.81 +pb_1c : 61.81 +pb_5c : 61.80 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.82 +pb_1c : 61.82 +pb_5c : 61.80 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.83 +pb_1c : 61.83 +pb_5c : 61.80 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.84 +pb_1c : 61.84 +pb_5c : 61.80 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.85 +pb_1c : 61.85 +pb_5c : 61.85 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.86 +pb_1c : 61.86 +pb_5c : 61.85 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.87 +pb_1c : 61.87 +pb_5c : 61.85 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.88 +pb_1c : 61.88 +pb_5c : 61.85 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.89 +pb_1c : 61.89 +pb_5c : 61.85 +pb_10c : 61.80 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.90 +pb_1c : 61.90 +pb_5c : 61.90 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.91 +pb_1c : 61.91 +pb_5c : 61.90 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.92 +pb_1c : 61.92 +pb_5c : 61.90 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.93 +pb_1c : 61.93 +pb_5c : 61.90 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.94 +pb_1c : 61.94 +pb_5c : 61.90 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.95 +pb_1c : 61.95 +pb_5c : 61.95 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.96 +pb_1c : 61.96 +pb_5c : 61.95 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.97 +pb_1c : 61.97 +pb_5c : 61.95 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.98 +pb_1c : 61.98 +pb_5c : 61.95 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +61.99 +pb_1c : 61.99 +pb_5c : 61.95 +pb_10c : 61.90 +pb_25c : 61.75 +pb_1d : 61.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.00 +pb_1c : 62.00 +pb_5c : 62.00 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.01 +pb_1c : 62.01 +pb_5c : 62.00 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.02 +pb_1c : 62.02 +pb_5c : 62.00 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.03 +pb_1c : 62.03 +pb_5c : 62.00 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.04 +pb_1c : 62.04 +pb_5c : 62.00 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.05 +pb_1c : 62.05 +pb_5c : 62.05 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.06 +pb_1c : 62.06 +pb_5c : 62.05 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.07 +pb_1c : 62.07 +pb_5c : 62.05 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.08 +pb_1c : 62.08 +pb_5c : 62.05 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.09 +pb_1c : 62.09 +pb_5c : 62.05 +pb_10c : 62.00 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.10 +pb_1c : 62.10 +pb_5c : 62.10 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.11 +pb_1c : 62.11 +pb_5c : 62.10 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.12 +pb_1c : 62.12 +pb_5c : 62.10 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.13 +pb_1c : 62.13 +pb_5c : 62.10 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.14 +pb_1c : 62.14 +pb_5c : 62.10 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.15 +pb_1c : 62.15 +pb_5c : 62.15 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.16 +pb_1c : 62.16 +pb_5c : 62.15 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.17 +pb_1c : 62.17 +pb_5c : 62.15 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.18 +pb_1c : 62.18 +pb_5c : 62.15 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.19 +pb_1c : 62.19 +pb_5c : 62.15 +pb_10c : 62.10 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.20 +pb_1c : 62.20 +pb_5c : 62.20 +pb_10c : 62.20 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.21 +pb_1c : 62.21 +pb_5c : 62.20 +pb_10c : 62.20 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.22 +pb_1c : 62.22 +pb_5c : 62.20 +pb_10c : 62.20 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.23 +pb_1c : 62.23 +pb_5c : 62.20 +pb_10c : 62.20 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.24 +pb_1c : 62.24 +pb_5c : 62.20 +pb_10c : 62.20 +pb_25c : 62.00 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.25 +pb_1c : 62.25 +pb_5c : 62.25 +pb_10c : 62.20 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.26 +pb_1c : 62.26 +pb_5c : 62.25 +pb_10c : 62.20 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.27 +pb_1c : 62.27 +pb_5c : 62.25 +pb_10c : 62.20 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.28 +pb_1c : 62.28 +pb_5c : 62.25 +pb_10c : 62.20 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.29 +pb_1c : 62.29 +pb_5c : 62.25 +pb_10c : 62.20 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.30 +pb_1c : 62.30 +pb_5c : 62.30 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.31 +pb_1c : 62.31 +pb_5c : 62.30 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.32 +pb_1c : 62.32 +pb_5c : 62.30 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.33 +pb_1c : 62.33 +pb_5c : 62.30 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.34 +pb_1c : 62.34 +pb_5c : 62.30 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.35 +pb_1c : 62.35 +pb_5c : 62.35 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.36 +pb_1c : 62.36 +pb_5c : 62.35 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.37 +pb_1c : 62.37 +pb_5c : 62.35 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.38 +pb_1c : 62.38 +pb_5c : 62.35 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.39 +pb_1c : 62.39 +pb_5c : 62.35 +pb_10c : 62.30 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.40 +pb_1c : 62.40 +pb_5c : 62.40 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.41 +pb_1c : 62.41 +pb_5c : 62.40 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.42 +pb_1c : 62.42 +pb_5c : 62.40 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.43 +pb_1c : 62.43 +pb_5c : 62.40 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.44 +pb_1c : 62.44 +pb_5c : 62.40 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.45 +pb_1c : 62.45 +pb_5c : 62.45 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.46 +pb_1c : 62.46 +pb_5c : 62.45 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.47 +pb_1c : 62.47 +pb_5c : 62.45 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.48 +pb_1c : 62.48 +pb_5c : 62.45 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.49 +pb_1c : 62.49 +pb_5c : 62.45 +pb_10c : 62.40 +pb_25c : 62.25 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.50 +pb_1c : 62.50 +pb_5c : 62.50 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.51 +pb_1c : 62.51 +pb_5c : 62.50 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.52 +pb_1c : 62.52 +pb_5c : 62.50 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.53 +pb_1c : 62.53 +pb_5c : 62.50 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.54 +pb_1c : 62.54 +pb_5c : 62.50 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.55 +pb_1c : 62.55 +pb_5c : 62.55 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.56 +pb_1c : 62.56 +pb_5c : 62.55 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.57 +pb_1c : 62.57 +pb_5c : 62.55 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.58 +pb_1c : 62.58 +pb_5c : 62.55 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.59 +pb_1c : 62.59 +pb_5c : 62.55 +pb_10c : 62.50 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.60 +pb_1c : 62.60 +pb_5c : 62.60 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.61 +pb_1c : 62.61 +pb_5c : 62.60 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.62 +pb_1c : 62.62 +pb_5c : 62.60 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.63 +pb_1c : 62.63 +pb_5c : 62.60 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.64 +pb_1c : 62.64 +pb_5c : 62.60 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.65 +pb_1c : 62.65 +pb_5c : 62.65 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.66 +pb_1c : 62.66 +pb_5c : 62.65 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.67 +pb_1c : 62.67 +pb_5c : 62.65 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.68 +pb_1c : 62.68 +pb_5c : 62.65 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.69 +pb_1c : 62.69 +pb_5c : 62.65 +pb_10c : 62.60 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.70 +pb_1c : 62.70 +pb_5c : 62.70 +pb_10c : 62.70 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.71 +pb_1c : 62.71 +pb_5c : 62.70 +pb_10c : 62.70 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.72 +pb_1c : 62.72 +pb_5c : 62.70 +pb_10c : 62.70 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.73 +pb_1c : 62.73 +pb_5c : 62.70 +pb_10c : 62.70 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.74 +pb_1c : 62.74 +pb_5c : 62.70 +pb_10c : 62.70 +pb_25c : 62.50 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.75 +pb_1c : 62.75 +pb_5c : 62.75 +pb_10c : 62.70 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.76 +pb_1c : 62.76 +pb_5c : 62.75 +pb_10c : 62.70 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.77 +pb_1c : 62.77 +pb_5c : 62.75 +pb_10c : 62.70 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.78 +pb_1c : 62.78 +pb_5c : 62.75 +pb_10c : 62.70 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.79 +pb_1c : 62.79 +pb_5c : 62.75 +pb_10c : 62.70 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.80 +pb_1c : 62.80 +pb_5c : 62.80 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.81 +pb_1c : 62.81 +pb_5c : 62.80 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.82 +pb_1c : 62.82 +pb_5c : 62.80 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.83 +pb_1c : 62.83 +pb_5c : 62.80 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.84 +pb_1c : 62.84 +pb_5c : 62.80 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.85 +pb_1c : 62.85 +pb_5c : 62.85 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.86 +pb_1c : 62.86 +pb_5c : 62.85 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.87 +pb_1c : 62.87 +pb_5c : 62.85 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.88 +pb_1c : 62.88 +pb_5c : 62.85 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.89 +pb_1c : 62.89 +pb_5c : 62.85 +pb_10c : 62.80 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.90 +pb_1c : 62.90 +pb_5c : 62.90 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.91 +pb_1c : 62.91 +pb_5c : 62.90 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.92 +pb_1c : 62.92 +pb_5c : 62.90 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.93 +pb_1c : 62.93 +pb_5c : 62.90 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.94 +pb_1c : 62.94 +pb_5c : 62.90 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.95 +pb_1c : 62.95 +pb_5c : 62.95 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.96 +pb_1c : 62.96 +pb_5c : 62.95 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.97 +pb_1c : 62.97 +pb_5c : 62.95 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.98 +pb_1c : 62.98 +pb_5c : 62.95 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +62.99 +pb_1c : 62.99 +pb_5c : 62.95 +pb_10c : 62.90 +pb_25c : 62.75 +pb_1d : 62.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.00 +pb_1c : 63.00 +pb_5c : 63.00 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.01 +pb_1c : 63.01 +pb_5c : 63.00 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.02 +pb_1c : 63.02 +pb_5c : 63.00 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.03 +pb_1c : 63.03 +pb_5c : 63.00 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.04 +pb_1c : 63.04 +pb_5c : 63.00 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.05 +pb_1c : 63.05 +pb_5c : 63.05 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.06 +pb_1c : 63.06 +pb_5c : 63.05 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.07 +pb_1c : 63.07 +pb_5c : 63.05 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.08 +pb_1c : 63.08 +pb_5c : 63.05 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.09 +pb_1c : 63.09 +pb_5c : 63.05 +pb_10c : 63.00 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.10 +pb_1c : 63.10 +pb_5c : 63.10 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.11 +pb_1c : 63.11 +pb_5c : 63.10 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.12 +pb_1c : 63.12 +pb_5c : 63.10 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.13 +pb_1c : 63.13 +pb_5c : 63.10 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.14 +pb_1c : 63.14 +pb_5c : 63.10 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.15 +pb_1c : 63.15 +pb_5c : 63.15 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.16 +pb_1c : 63.16 +pb_5c : 63.15 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.17 +pb_1c : 63.17 +pb_5c : 63.15 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.18 +pb_1c : 63.18 +pb_5c : 63.15 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.19 +pb_1c : 63.19 +pb_5c : 63.15 +pb_10c : 63.10 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.20 +pb_1c : 63.20 +pb_5c : 63.20 +pb_10c : 63.20 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.21 +pb_1c : 63.21 +pb_5c : 63.20 +pb_10c : 63.20 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.22 +pb_1c : 63.22 +pb_5c : 63.20 +pb_10c : 63.20 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.23 +pb_1c : 63.23 +pb_5c : 63.20 +pb_10c : 63.20 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.24 +pb_1c : 63.24 +pb_5c : 63.20 +pb_10c : 63.20 +pb_25c : 63.00 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.25 +pb_1c : 63.25 +pb_5c : 63.25 +pb_10c : 63.20 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.26 +pb_1c : 63.26 +pb_5c : 63.25 +pb_10c : 63.20 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.27 +pb_1c : 63.27 +pb_5c : 63.25 +pb_10c : 63.20 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.28 +pb_1c : 63.28 +pb_5c : 63.25 +pb_10c : 63.20 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.29 +pb_1c : 63.29 +pb_5c : 63.25 +pb_10c : 63.20 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.30 +pb_1c : 63.30 +pb_5c : 63.30 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.31 +pb_1c : 63.31 +pb_5c : 63.30 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.32 +pb_1c : 63.32 +pb_5c : 63.30 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.33 +pb_1c : 63.33 +pb_5c : 63.30 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.34 +pb_1c : 63.34 +pb_5c : 63.30 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.35 +pb_1c : 63.35 +pb_5c : 63.35 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.36 +pb_1c : 63.36 +pb_5c : 63.35 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.37 +pb_1c : 63.37 +pb_5c : 63.35 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.38 +pb_1c : 63.38 +pb_5c : 63.35 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.39 +pb_1c : 63.39 +pb_5c : 63.35 +pb_10c : 63.30 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.40 +pb_1c : 63.40 +pb_5c : 63.40 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.41 +pb_1c : 63.41 +pb_5c : 63.40 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.42 +pb_1c : 63.42 +pb_5c : 63.40 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.43 +pb_1c : 63.43 +pb_5c : 63.40 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.44 +pb_1c : 63.44 +pb_5c : 63.40 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.45 +pb_1c : 63.45 +pb_5c : 63.45 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.46 +pb_1c : 63.46 +pb_5c : 63.45 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.47 +pb_1c : 63.47 +pb_5c : 63.45 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.48 +pb_1c : 63.48 +pb_5c : 63.45 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.49 +pb_1c : 63.49 +pb_5c : 63.45 +pb_10c : 63.40 +pb_25c : 63.25 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.50 +pb_1c : 63.50 +pb_5c : 63.50 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.51 +pb_1c : 63.51 +pb_5c : 63.50 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.52 +pb_1c : 63.52 +pb_5c : 63.50 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.53 +pb_1c : 63.53 +pb_5c : 63.50 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.54 +pb_1c : 63.54 +pb_5c : 63.50 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.55 +pb_1c : 63.55 +pb_5c : 63.55 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.56 +pb_1c : 63.56 +pb_5c : 63.55 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.57 +pb_1c : 63.57 +pb_5c : 63.55 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.58 +pb_1c : 63.58 +pb_5c : 63.55 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.59 +pb_1c : 63.59 +pb_5c : 63.55 +pb_10c : 63.50 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.60 +pb_1c : 63.60 +pb_5c : 63.60 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.61 +pb_1c : 63.61 +pb_5c : 63.60 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.62 +pb_1c : 63.62 +pb_5c : 63.60 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.63 +pb_1c : 63.63 +pb_5c : 63.60 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.64 +pb_1c : 63.64 +pb_5c : 63.60 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.65 +pb_1c : 63.65 +pb_5c : 63.65 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.66 +pb_1c : 63.66 +pb_5c : 63.65 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.67 +pb_1c : 63.67 +pb_5c : 63.65 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.68 +pb_1c : 63.68 +pb_5c : 63.65 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.69 +pb_1c : 63.69 +pb_5c : 63.65 +pb_10c : 63.60 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.70 +pb_1c : 63.70 +pb_5c : 63.70 +pb_10c : 63.70 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.71 +pb_1c : 63.71 +pb_5c : 63.70 +pb_10c : 63.70 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.72 +pb_1c : 63.72 +pb_5c : 63.70 +pb_10c : 63.70 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.73 +pb_1c : 63.73 +pb_5c : 63.70 +pb_10c : 63.70 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.74 +pb_1c : 63.74 +pb_5c : 63.70 +pb_10c : 63.70 +pb_25c : 63.50 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.75 +pb_1c : 63.75 +pb_5c : 63.75 +pb_10c : 63.70 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.76 +pb_1c : 63.76 +pb_5c : 63.75 +pb_10c : 63.70 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.77 +pb_1c : 63.77 +pb_5c : 63.75 +pb_10c : 63.70 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.78 +pb_1c : 63.78 +pb_5c : 63.75 +pb_10c : 63.70 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.79 +pb_1c : 63.79 +pb_5c : 63.75 +pb_10c : 63.70 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.80 +pb_1c : 63.80 +pb_5c : 63.80 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.81 +pb_1c : 63.81 +pb_5c : 63.80 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.82 +pb_1c : 63.82 +pb_5c : 63.80 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.83 +pb_1c : 63.83 +pb_5c : 63.80 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.84 +pb_1c : 63.84 +pb_5c : 63.80 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.85 +pb_1c : 63.85 +pb_5c : 63.85 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.86 +pb_1c : 63.86 +pb_5c : 63.85 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.87 +pb_1c : 63.87 +pb_5c : 63.85 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.88 +pb_1c : 63.88 +pb_5c : 63.85 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.89 +pb_1c : 63.89 +pb_5c : 63.85 +pb_10c : 63.80 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.90 +pb_1c : 63.90 +pb_5c : 63.90 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.91 +pb_1c : 63.91 +pb_5c : 63.90 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.92 +pb_1c : 63.92 +pb_5c : 63.90 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.93 +pb_1c : 63.93 +pb_5c : 63.90 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.94 +pb_1c : 63.94 +pb_5c : 63.90 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.95 +pb_1c : 63.95 +pb_5c : 63.95 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.96 +pb_1c : 63.96 +pb_5c : 63.95 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.97 +pb_1c : 63.97 +pb_5c : 63.95 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.98 +pb_1c : 63.98 +pb_5c : 63.95 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +63.99 +pb_1c : 63.99 +pb_5c : 63.95 +pb_10c : 63.90 +pb_25c : 63.75 +pb_1d : 63.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.00 +pb_1c : 64.00 +pb_5c : 64.00 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.01 +pb_1c : 64.01 +pb_5c : 64.00 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.02 +pb_1c : 64.02 +pb_5c : 64.00 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.03 +pb_1c : 64.03 +pb_5c : 64.00 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.04 +pb_1c : 64.04 +pb_5c : 64.00 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.05 +pb_1c : 64.05 +pb_5c : 64.05 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.06 +pb_1c : 64.06 +pb_5c : 64.05 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.07 +pb_1c : 64.07 +pb_5c : 64.05 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.08 +pb_1c : 64.08 +pb_5c : 64.05 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.09 +pb_1c : 64.09 +pb_5c : 64.05 +pb_10c : 64.00 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.10 +pb_1c : 64.10 +pb_5c : 64.10 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.11 +pb_1c : 64.11 +pb_5c : 64.10 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.12 +pb_1c : 64.12 +pb_5c : 64.10 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.13 +pb_1c : 64.13 +pb_5c : 64.10 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.14 +pb_1c : 64.14 +pb_5c : 64.10 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.15 +pb_1c : 64.15 +pb_5c : 64.15 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.16 +pb_1c : 64.16 +pb_5c : 64.15 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.17 +pb_1c : 64.17 +pb_5c : 64.15 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.18 +pb_1c : 64.18 +pb_5c : 64.15 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.19 +pb_1c : 64.19 +pb_5c : 64.15 +pb_10c : 64.10 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.20 +pb_1c : 64.20 +pb_5c : 64.20 +pb_10c : 64.20 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.21 +pb_1c : 64.21 +pb_5c : 64.20 +pb_10c : 64.20 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.22 +pb_1c : 64.22 +pb_5c : 64.20 +pb_10c : 64.20 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.23 +pb_1c : 64.23 +pb_5c : 64.20 +pb_10c : 64.20 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.24 +pb_1c : 64.24 +pb_5c : 64.20 +pb_10c : 64.20 +pb_25c : 64.00 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.25 +pb_1c : 64.25 +pb_5c : 64.25 +pb_10c : 64.20 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.26 +pb_1c : 64.26 +pb_5c : 64.25 +pb_10c : 64.20 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.27 +pb_1c : 64.27 +pb_5c : 64.25 +pb_10c : 64.20 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.28 +pb_1c : 64.28 +pb_5c : 64.25 +pb_10c : 64.20 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.29 +pb_1c : 64.29 +pb_5c : 64.25 +pb_10c : 64.20 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.30 +pb_1c : 64.30 +pb_5c : 64.30 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.31 +pb_1c : 64.31 +pb_5c : 64.30 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.32 +pb_1c : 64.32 +pb_5c : 64.30 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.33 +pb_1c : 64.33 +pb_5c : 64.30 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.34 +pb_1c : 64.34 +pb_5c : 64.30 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.35 +pb_1c : 64.35 +pb_5c : 64.35 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.36 +pb_1c : 64.36 +pb_5c : 64.35 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.37 +pb_1c : 64.37 +pb_5c : 64.35 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.38 +pb_1c : 64.38 +pb_5c : 64.35 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.39 +pb_1c : 64.39 +pb_5c : 64.35 +pb_10c : 64.30 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.40 +pb_1c : 64.40 +pb_5c : 64.40 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.41 +pb_1c : 64.41 +pb_5c : 64.40 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.42 +pb_1c : 64.42 +pb_5c : 64.40 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.43 +pb_1c : 64.43 +pb_5c : 64.40 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.44 +pb_1c : 64.44 +pb_5c : 64.40 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.45 +pb_1c : 64.45 +pb_5c : 64.45 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.46 +pb_1c : 64.46 +pb_5c : 64.45 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.47 +pb_1c : 64.47 +pb_5c : 64.45 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.48 +pb_1c : 64.48 +pb_5c : 64.45 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.49 +pb_1c : 64.49 +pb_5c : 64.45 +pb_10c : 64.40 +pb_25c : 64.25 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.50 +pb_1c : 64.50 +pb_5c : 64.50 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.51 +pb_1c : 64.51 +pb_5c : 64.50 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.52 +pb_1c : 64.52 +pb_5c : 64.50 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.53 +pb_1c : 64.53 +pb_5c : 64.50 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.54 +pb_1c : 64.54 +pb_5c : 64.50 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.55 +pb_1c : 64.55 +pb_5c : 64.55 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.56 +pb_1c : 64.56 +pb_5c : 64.55 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.57 +pb_1c : 64.57 +pb_5c : 64.55 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.58 +pb_1c : 64.58 +pb_5c : 64.55 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.59 +pb_1c : 64.59 +pb_5c : 64.55 +pb_10c : 64.50 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.60 +pb_1c : 64.60 +pb_5c : 64.60 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.61 +pb_1c : 64.61 +pb_5c : 64.60 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.62 +pb_1c : 64.62 +pb_5c : 64.60 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.63 +pb_1c : 64.63 +pb_5c : 64.60 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.64 +pb_1c : 64.64 +pb_5c : 64.60 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.65 +pb_1c : 64.65 +pb_5c : 64.65 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.66 +pb_1c : 64.66 +pb_5c : 64.65 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.67 +pb_1c : 64.67 +pb_5c : 64.65 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.68 +pb_1c : 64.68 +pb_5c : 64.65 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.69 +pb_1c : 64.69 +pb_5c : 64.65 +pb_10c : 64.60 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.70 +pb_1c : 64.70 +pb_5c : 64.70 +pb_10c : 64.70 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.71 +pb_1c : 64.71 +pb_5c : 64.70 +pb_10c : 64.70 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.72 +pb_1c : 64.72 +pb_5c : 64.70 +pb_10c : 64.70 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.73 +pb_1c : 64.73 +pb_5c : 64.70 +pb_10c : 64.70 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.74 +pb_1c : 64.74 +pb_5c : 64.70 +pb_10c : 64.70 +pb_25c : 64.50 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.75 +pb_1c : 64.75 +pb_5c : 64.75 +pb_10c : 64.70 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.76 +pb_1c : 64.76 +pb_5c : 64.75 +pb_10c : 64.70 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.77 +pb_1c : 64.77 +pb_5c : 64.75 +pb_10c : 64.70 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.78 +pb_1c : 64.78 +pb_5c : 64.75 +pb_10c : 64.70 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.79 +pb_1c : 64.79 +pb_5c : 64.75 +pb_10c : 64.70 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.80 +pb_1c : 64.80 +pb_5c : 64.80 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.81 +pb_1c : 64.81 +pb_5c : 64.80 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.82 +pb_1c : 64.82 +pb_5c : 64.80 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.83 +pb_1c : 64.83 +pb_5c : 64.80 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.84 +pb_1c : 64.84 +pb_5c : 64.80 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.85 +pb_1c : 64.85 +pb_5c : 64.85 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.86 +pb_1c : 64.86 +pb_5c : 64.85 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.87 +pb_1c : 64.87 +pb_5c : 64.85 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.88 +pb_1c : 64.88 +pb_5c : 64.85 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.89 +pb_1c : 64.89 +pb_5c : 64.85 +pb_10c : 64.80 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.90 +pb_1c : 64.90 +pb_5c : 64.90 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.91 +pb_1c : 64.91 +pb_5c : 64.90 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.92 +pb_1c : 64.92 +pb_5c : 64.90 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.93 +pb_1c : 64.93 +pb_5c : 64.90 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.94 +pb_1c : 64.94 +pb_5c : 64.90 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.95 +pb_1c : 64.95 +pb_5c : 64.95 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.96 +pb_1c : 64.96 +pb_5c : 64.95 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.97 +pb_1c : 64.97 +pb_5c : 64.95 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.98 +pb_1c : 64.98 +pb_5c : 64.95 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +64.99 +pb_1c : 64.99 +pb_5c : 64.95 +pb_10c : 64.90 +pb_25c : 64.75 +pb_1d : 64.00 +pb_5d : 60.00 +pb_10d : 60.00 + +65.00 +pb_1c : 65.00 +pb_5c : 65.00 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.01 +pb_1c : 65.01 +pb_5c : 65.00 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.02 +pb_1c : 65.02 +pb_5c : 65.00 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.03 +pb_1c : 65.03 +pb_5c : 65.00 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.04 +pb_1c : 65.04 +pb_5c : 65.00 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.05 +pb_1c : 65.05 +pb_5c : 65.05 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.06 +pb_1c : 65.06 +pb_5c : 65.05 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.07 +pb_1c : 65.07 +pb_5c : 65.05 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.08 +pb_1c : 65.08 +pb_5c : 65.05 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.09 +pb_1c : 65.09 +pb_5c : 65.05 +pb_10c : 65.00 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.10 +pb_1c : 65.10 +pb_5c : 65.10 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.11 +pb_1c : 65.11 +pb_5c : 65.10 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.12 +pb_1c : 65.12 +pb_5c : 65.10 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.13 +pb_1c : 65.13 +pb_5c : 65.10 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.14 +pb_1c : 65.14 +pb_5c : 65.10 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.15 +pb_1c : 65.15 +pb_5c : 65.15 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.16 +pb_1c : 65.16 +pb_5c : 65.15 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.17 +pb_1c : 65.17 +pb_5c : 65.15 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.18 +pb_1c : 65.18 +pb_5c : 65.15 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.19 +pb_1c : 65.19 +pb_5c : 65.15 +pb_10c : 65.10 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.20 +pb_1c : 65.20 +pb_5c : 65.20 +pb_10c : 65.20 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.21 +pb_1c : 65.21 +pb_5c : 65.20 +pb_10c : 65.20 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.22 +pb_1c : 65.22 +pb_5c : 65.20 +pb_10c : 65.20 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.23 +pb_1c : 65.23 +pb_5c : 65.20 +pb_10c : 65.20 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.24 +pb_1c : 65.24 +pb_5c : 65.20 +pb_10c : 65.20 +pb_25c : 65.00 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.25 +pb_1c : 65.25 +pb_5c : 65.25 +pb_10c : 65.20 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.26 +pb_1c : 65.26 +pb_5c : 65.25 +pb_10c : 65.20 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.27 +pb_1c : 65.27 +pb_5c : 65.25 +pb_10c : 65.20 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.28 +pb_1c : 65.28 +pb_5c : 65.25 +pb_10c : 65.20 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.29 +pb_1c : 65.29 +pb_5c : 65.25 +pb_10c : 65.20 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.30 +pb_1c : 65.30 +pb_5c : 65.30 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.31 +pb_1c : 65.31 +pb_5c : 65.30 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.32 +pb_1c : 65.32 +pb_5c : 65.30 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.33 +pb_1c : 65.33 +pb_5c : 65.30 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.34 +pb_1c : 65.34 +pb_5c : 65.30 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.35 +pb_1c : 65.35 +pb_5c : 65.35 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.36 +pb_1c : 65.36 +pb_5c : 65.35 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.37 +pb_1c : 65.37 +pb_5c : 65.35 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.38 +pb_1c : 65.38 +pb_5c : 65.35 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.39 +pb_1c : 65.39 +pb_5c : 65.35 +pb_10c : 65.30 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.40 +pb_1c : 65.40 +pb_5c : 65.40 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.41 +pb_1c : 65.41 +pb_5c : 65.40 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.42 +pb_1c : 65.42 +pb_5c : 65.40 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.43 +pb_1c : 65.43 +pb_5c : 65.40 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.44 +pb_1c : 65.44 +pb_5c : 65.40 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.45 +pb_1c : 65.45 +pb_5c : 65.45 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.46 +pb_1c : 65.46 +pb_5c : 65.45 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.47 +pb_1c : 65.47 +pb_5c : 65.45 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.48 +pb_1c : 65.48 +pb_5c : 65.45 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.49 +pb_1c : 65.49 +pb_5c : 65.45 +pb_10c : 65.40 +pb_25c : 65.25 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.50 +pb_1c : 65.50 +pb_5c : 65.50 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.51 +pb_1c : 65.51 +pb_5c : 65.50 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.52 +pb_1c : 65.52 +pb_5c : 65.50 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.53 +pb_1c : 65.53 +pb_5c : 65.50 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.54 +pb_1c : 65.54 +pb_5c : 65.50 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.55 +pb_1c : 65.55 +pb_5c : 65.55 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.56 +pb_1c : 65.56 +pb_5c : 65.55 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.57 +pb_1c : 65.57 +pb_5c : 65.55 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.58 +pb_1c : 65.58 +pb_5c : 65.55 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.59 +pb_1c : 65.59 +pb_5c : 65.55 +pb_10c : 65.50 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.60 +pb_1c : 65.60 +pb_5c : 65.60 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.61 +pb_1c : 65.61 +pb_5c : 65.60 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.62 +pb_1c : 65.62 +pb_5c : 65.60 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.63 +pb_1c : 65.63 +pb_5c : 65.60 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.64 +pb_1c : 65.64 +pb_5c : 65.60 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.65 +pb_1c : 65.65 +pb_5c : 65.65 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.66 +pb_1c : 65.66 +pb_5c : 65.65 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.67 +pb_1c : 65.67 +pb_5c : 65.65 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.68 +pb_1c : 65.68 +pb_5c : 65.65 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.69 +pb_1c : 65.69 +pb_5c : 65.65 +pb_10c : 65.60 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.70 +pb_1c : 65.70 +pb_5c : 65.70 +pb_10c : 65.70 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.71 +pb_1c : 65.71 +pb_5c : 65.70 +pb_10c : 65.70 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.72 +pb_1c : 65.72 +pb_5c : 65.70 +pb_10c : 65.70 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.73 +pb_1c : 65.73 +pb_5c : 65.70 +pb_10c : 65.70 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.74 +pb_1c : 65.74 +pb_5c : 65.70 +pb_10c : 65.70 +pb_25c : 65.50 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.75 +pb_1c : 65.75 +pb_5c : 65.75 +pb_10c : 65.70 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.76 +pb_1c : 65.76 +pb_5c : 65.75 +pb_10c : 65.70 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.77 +pb_1c : 65.77 +pb_5c : 65.75 +pb_10c : 65.70 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.78 +pb_1c : 65.78 +pb_5c : 65.75 +pb_10c : 65.70 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.79 +pb_1c : 65.79 +pb_5c : 65.75 +pb_10c : 65.70 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.80 +pb_1c : 65.80 +pb_5c : 65.80 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.81 +pb_1c : 65.81 +pb_5c : 65.80 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.82 +pb_1c : 65.82 +pb_5c : 65.80 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.83 +pb_1c : 65.83 +pb_5c : 65.80 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.84 +pb_1c : 65.84 +pb_5c : 65.80 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.85 +pb_1c : 65.85 +pb_5c : 65.85 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.86 +pb_1c : 65.86 +pb_5c : 65.85 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.87 +pb_1c : 65.87 +pb_5c : 65.85 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.88 +pb_1c : 65.88 +pb_5c : 65.85 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.89 +pb_1c : 65.89 +pb_5c : 65.85 +pb_10c : 65.80 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.90 +pb_1c : 65.90 +pb_5c : 65.90 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.91 +pb_1c : 65.91 +pb_5c : 65.90 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.92 +pb_1c : 65.92 +pb_5c : 65.90 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.93 +pb_1c : 65.93 +pb_5c : 65.90 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.94 +pb_1c : 65.94 +pb_5c : 65.90 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.95 +pb_1c : 65.95 +pb_5c : 65.95 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.96 +pb_1c : 65.96 +pb_5c : 65.95 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.97 +pb_1c : 65.97 +pb_5c : 65.95 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.98 +pb_1c : 65.98 +pb_5c : 65.95 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +65.99 +pb_1c : 65.99 +pb_5c : 65.95 +pb_10c : 65.90 +pb_25c : 65.75 +pb_1d : 65.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.00 +pb_1c : 66.00 +pb_5c : 66.00 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.01 +pb_1c : 66.01 +pb_5c : 66.00 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.02 +pb_1c : 66.02 +pb_5c : 66.00 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.03 +pb_1c : 66.03 +pb_5c : 66.00 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.04 +pb_1c : 66.04 +pb_5c : 66.00 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.05 +pb_1c : 66.05 +pb_5c : 66.05 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.06 +pb_1c : 66.06 +pb_5c : 66.05 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.07 +pb_1c : 66.07 +pb_5c : 66.05 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.08 +pb_1c : 66.08 +pb_5c : 66.05 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.09 +pb_1c : 66.09 +pb_5c : 66.05 +pb_10c : 66.00 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.10 +pb_1c : 66.10 +pb_5c : 66.10 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.11 +pb_1c : 66.11 +pb_5c : 66.10 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.12 +pb_1c : 66.12 +pb_5c : 66.10 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.13 +pb_1c : 66.13 +pb_5c : 66.10 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.14 +pb_1c : 66.14 +pb_5c : 66.10 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.15 +pb_1c : 66.15 +pb_5c : 66.15 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.16 +pb_1c : 66.16 +pb_5c : 66.15 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.17 +pb_1c : 66.17 +pb_5c : 66.15 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.18 +pb_1c : 66.18 +pb_5c : 66.15 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.19 +pb_1c : 66.19 +pb_5c : 66.15 +pb_10c : 66.10 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.20 +pb_1c : 66.20 +pb_5c : 66.20 +pb_10c : 66.20 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.21 +pb_1c : 66.21 +pb_5c : 66.20 +pb_10c : 66.20 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.22 +pb_1c : 66.22 +pb_5c : 66.20 +pb_10c : 66.20 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.23 +pb_1c : 66.23 +pb_5c : 66.20 +pb_10c : 66.20 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.24 +pb_1c : 66.24 +pb_5c : 66.20 +pb_10c : 66.20 +pb_25c : 66.00 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.25 +pb_1c : 66.25 +pb_5c : 66.25 +pb_10c : 66.20 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.26 +pb_1c : 66.26 +pb_5c : 66.25 +pb_10c : 66.20 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.27 +pb_1c : 66.27 +pb_5c : 66.25 +pb_10c : 66.20 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.28 +pb_1c : 66.28 +pb_5c : 66.25 +pb_10c : 66.20 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.29 +pb_1c : 66.29 +pb_5c : 66.25 +pb_10c : 66.20 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.30 +pb_1c : 66.30 +pb_5c : 66.30 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.31 +pb_1c : 66.31 +pb_5c : 66.30 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.32 +pb_1c : 66.32 +pb_5c : 66.30 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.33 +pb_1c : 66.33 +pb_5c : 66.30 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.34 +pb_1c : 66.34 +pb_5c : 66.30 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.35 +pb_1c : 66.35 +pb_5c : 66.35 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.36 +pb_1c : 66.36 +pb_5c : 66.35 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.37 +pb_1c : 66.37 +pb_5c : 66.35 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.38 +pb_1c : 66.38 +pb_5c : 66.35 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.39 +pb_1c : 66.39 +pb_5c : 66.35 +pb_10c : 66.30 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.40 +pb_1c : 66.40 +pb_5c : 66.40 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.41 +pb_1c : 66.41 +pb_5c : 66.40 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.42 +pb_1c : 66.42 +pb_5c : 66.40 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.43 +pb_1c : 66.43 +pb_5c : 66.40 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.44 +pb_1c : 66.44 +pb_5c : 66.40 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.45 +pb_1c : 66.45 +pb_5c : 66.45 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.46 +pb_1c : 66.46 +pb_5c : 66.45 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.47 +pb_1c : 66.47 +pb_5c : 66.45 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.48 +pb_1c : 66.48 +pb_5c : 66.45 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.49 +pb_1c : 66.49 +pb_5c : 66.45 +pb_10c : 66.40 +pb_25c : 66.25 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.50 +pb_1c : 66.50 +pb_5c : 66.50 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.51 +pb_1c : 66.51 +pb_5c : 66.50 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.52 +pb_1c : 66.52 +pb_5c : 66.50 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.53 +pb_1c : 66.53 +pb_5c : 66.50 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.54 +pb_1c : 66.54 +pb_5c : 66.50 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.55 +pb_1c : 66.55 +pb_5c : 66.55 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.56 +pb_1c : 66.56 +pb_5c : 66.55 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.57 +pb_1c : 66.57 +pb_5c : 66.55 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.58 +pb_1c : 66.58 +pb_5c : 66.55 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.59 +pb_1c : 66.59 +pb_5c : 66.55 +pb_10c : 66.50 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.60 +pb_1c : 66.60 +pb_5c : 66.60 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.61 +pb_1c : 66.61 +pb_5c : 66.60 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.62 +pb_1c : 66.62 +pb_5c : 66.60 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.63 +pb_1c : 66.63 +pb_5c : 66.60 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.64 +pb_1c : 66.64 +pb_5c : 66.60 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.65 +pb_1c : 66.65 +pb_5c : 66.65 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.66 +pb_1c : 66.66 +pb_5c : 66.65 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.67 +pb_1c : 66.67 +pb_5c : 66.65 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.68 +pb_1c : 66.68 +pb_5c : 66.65 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.69 +pb_1c : 66.69 +pb_5c : 66.65 +pb_10c : 66.60 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.70 +pb_1c : 66.70 +pb_5c : 66.70 +pb_10c : 66.70 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.71 +pb_1c : 66.71 +pb_5c : 66.70 +pb_10c : 66.70 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.72 +pb_1c : 66.72 +pb_5c : 66.70 +pb_10c : 66.70 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.73 +pb_1c : 66.73 +pb_5c : 66.70 +pb_10c : 66.70 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.74 +pb_1c : 66.74 +pb_5c : 66.70 +pb_10c : 66.70 +pb_25c : 66.50 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.75 +pb_1c : 66.75 +pb_5c : 66.75 +pb_10c : 66.70 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.76 +pb_1c : 66.76 +pb_5c : 66.75 +pb_10c : 66.70 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.77 +pb_1c : 66.77 +pb_5c : 66.75 +pb_10c : 66.70 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.78 +pb_1c : 66.78 +pb_5c : 66.75 +pb_10c : 66.70 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.79 +pb_1c : 66.79 +pb_5c : 66.75 +pb_10c : 66.70 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.80 +pb_1c : 66.80 +pb_5c : 66.80 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.81 +pb_1c : 66.81 +pb_5c : 66.80 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.82 +pb_1c : 66.82 +pb_5c : 66.80 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.83 +pb_1c : 66.83 +pb_5c : 66.80 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.84 +pb_1c : 66.84 +pb_5c : 66.80 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.85 +pb_1c : 66.85 +pb_5c : 66.85 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.86 +pb_1c : 66.86 +pb_5c : 66.85 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.87 +pb_1c : 66.87 +pb_5c : 66.85 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.88 +pb_1c : 66.88 +pb_5c : 66.85 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.89 +pb_1c : 66.89 +pb_5c : 66.85 +pb_10c : 66.80 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.90 +pb_1c : 66.90 +pb_5c : 66.90 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.91 +pb_1c : 66.91 +pb_5c : 66.90 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.92 +pb_1c : 66.92 +pb_5c : 66.90 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.93 +pb_1c : 66.93 +pb_5c : 66.90 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.94 +pb_1c : 66.94 +pb_5c : 66.90 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.95 +pb_1c : 66.95 +pb_5c : 66.95 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.96 +pb_1c : 66.96 +pb_5c : 66.95 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.97 +pb_1c : 66.97 +pb_5c : 66.95 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.98 +pb_1c : 66.98 +pb_5c : 66.95 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +66.99 +pb_1c : 66.99 +pb_5c : 66.95 +pb_10c : 66.90 +pb_25c : 66.75 +pb_1d : 66.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.00 +pb_1c : 67.00 +pb_5c : 67.00 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.01 +pb_1c : 67.01 +pb_5c : 67.00 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.02 +pb_1c : 67.02 +pb_5c : 67.00 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.03 +pb_1c : 67.03 +pb_5c : 67.00 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.04 +pb_1c : 67.04 +pb_5c : 67.00 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.05 +pb_1c : 67.05 +pb_5c : 67.05 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.06 +pb_1c : 67.06 +pb_5c : 67.05 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.07 +pb_1c : 67.07 +pb_5c : 67.05 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.08 +pb_1c : 67.08 +pb_5c : 67.05 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.09 +pb_1c : 67.09 +pb_5c : 67.05 +pb_10c : 67.00 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.10 +pb_1c : 67.10 +pb_5c : 67.10 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.11 +pb_1c : 67.11 +pb_5c : 67.10 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.12 +pb_1c : 67.12 +pb_5c : 67.10 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.13 +pb_1c : 67.13 +pb_5c : 67.10 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.14 +pb_1c : 67.14 +pb_5c : 67.10 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.15 +pb_1c : 67.15 +pb_5c : 67.15 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.16 +pb_1c : 67.16 +pb_5c : 67.15 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.17 +pb_1c : 67.17 +pb_5c : 67.15 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.18 +pb_1c : 67.18 +pb_5c : 67.15 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.19 +pb_1c : 67.19 +pb_5c : 67.15 +pb_10c : 67.10 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.20 +pb_1c : 67.20 +pb_5c : 67.20 +pb_10c : 67.20 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.21 +pb_1c : 67.21 +pb_5c : 67.20 +pb_10c : 67.20 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.22 +pb_1c : 67.22 +pb_5c : 67.20 +pb_10c : 67.20 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.23 +pb_1c : 67.23 +pb_5c : 67.20 +pb_10c : 67.20 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.24 +pb_1c : 67.24 +pb_5c : 67.20 +pb_10c : 67.20 +pb_25c : 67.00 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.25 +pb_1c : 67.25 +pb_5c : 67.25 +pb_10c : 67.20 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.26 +pb_1c : 67.26 +pb_5c : 67.25 +pb_10c : 67.20 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.27 +pb_1c : 67.27 +pb_5c : 67.25 +pb_10c : 67.20 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.28 +pb_1c : 67.28 +pb_5c : 67.25 +pb_10c : 67.20 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.29 +pb_1c : 67.29 +pb_5c : 67.25 +pb_10c : 67.20 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.30 +pb_1c : 67.30 +pb_5c : 67.30 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.31 +pb_1c : 67.31 +pb_5c : 67.30 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.32 +pb_1c : 67.32 +pb_5c : 67.30 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.33 +pb_1c : 67.33 +pb_5c : 67.30 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.34 +pb_1c : 67.34 +pb_5c : 67.30 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.35 +pb_1c : 67.35 +pb_5c : 67.35 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.36 +pb_1c : 67.36 +pb_5c : 67.35 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.37 +pb_1c : 67.37 +pb_5c : 67.35 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.38 +pb_1c : 67.38 +pb_5c : 67.35 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.39 +pb_1c : 67.39 +pb_5c : 67.35 +pb_10c : 67.30 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.40 +pb_1c : 67.40 +pb_5c : 67.40 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.41 +pb_1c : 67.41 +pb_5c : 67.40 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.42 +pb_1c : 67.42 +pb_5c : 67.40 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.43 +pb_1c : 67.43 +pb_5c : 67.40 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.44 +pb_1c : 67.44 +pb_5c : 67.40 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.45 +pb_1c : 67.45 +pb_5c : 67.45 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.46 +pb_1c : 67.46 +pb_5c : 67.45 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.47 +pb_1c : 67.47 +pb_5c : 67.45 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.48 +pb_1c : 67.48 +pb_5c : 67.45 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.49 +pb_1c : 67.49 +pb_5c : 67.45 +pb_10c : 67.40 +pb_25c : 67.25 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.50 +pb_1c : 67.50 +pb_5c : 67.50 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.51 +pb_1c : 67.51 +pb_5c : 67.50 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.52 +pb_1c : 67.52 +pb_5c : 67.50 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.53 +pb_1c : 67.53 +pb_5c : 67.50 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.54 +pb_1c : 67.54 +pb_5c : 67.50 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.55 +pb_1c : 67.55 +pb_5c : 67.55 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.56 +pb_1c : 67.56 +pb_5c : 67.55 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.57 +pb_1c : 67.57 +pb_5c : 67.55 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.58 +pb_1c : 67.58 +pb_5c : 67.55 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.59 +pb_1c : 67.59 +pb_5c : 67.55 +pb_10c : 67.50 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.60 +pb_1c : 67.60 +pb_5c : 67.60 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.61 +pb_1c : 67.61 +pb_5c : 67.60 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.62 +pb_1c : 67.62 +pb_5c : 67.60 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.63 +pb_1c : 67.63 +pb_5c : 67.60 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.64 +pb_1c : 67.64 +pb_5c : 67.60 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.65 +pb_1c : 67.65 +pb_5c : 67.65 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.66 +pb_1c : 67.66 +pb_5c : 67.65 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.67 +pb_1c : 67.67 +pb_5c : 67.65 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.68 +pb_1c : 67.68 +pb_5c : 67.65 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.69 +pb_1c : 67.69 +pb_5c : 67.65 +pb_10c : 67.60 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.70 +pb_1c : 67.70 +pb_5c : 67.70 +pb_10c : 67.70 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.71 +pb_1c : 67.71 +pb_5c : 67.70 +pb_10c : 67.70 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.72 +pb_1c : 67.72 +pb_5c : 67.70 +pb_10c : 67.70 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.73 +pb_1c : 67.73 +pb_5c : 67.70 +pb_10c : 67.70 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.74 +pb_1c : 67.74 +pb_5c : 67.70 +pb_10c : 67.70 +pb_25c : 67.50 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.75 +pb_1c : 67.75 +pb_5c : 67.75 +pb_10c : 67.70 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.76 +pb_1c : 67.76 +pb_5c : 67.75 +pb_10c : 67.70 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.77 +pb_1c : 67.77 +pb_5c : 67.75 +pb_10c : 67.70 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.78 +pb_1c : 67.78 +pb_5c : 67.75 +pb_10c : 67.70 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.79 +pb_1c : 67.79 +pb_5c : 67.75 +pb_10c : 67.70 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.80 +pb_1c : 67.80 +pb_5c : 67.80 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.81 +pb_1c : 67.81 +pb_5c : 67.80 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.82 +pb_1c : 67.82 +pb_5c : 67.80 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.83 +pb_1c : 67.83 +pb_5c : 67.80 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.84 +pb_1c : 67.84 +pb_5c : 67.80 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.85 +pb_1c : 67.85 +pb_5c : 67.85 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.86 +pb_1c : 67.86 +pb_5c : 67.85 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.87 +pb_1c : 67.87 +pb_5c : 67.85 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.88 +pb_1c : 67.88 +pb_5c : 67.85 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.89 +pb_1c : 67.89 +pb_5c : 67.85 +pb_10c : 67.80 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.90 +pb_1c : 67.90 +pb_5c : 67.90 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.91 +pb_1c : 67.91 +pb_5c : 67.90 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.92 +pb_1c : 67.92 +pb_5c : 67.90 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.93 +pb_1c : 67.93 +pb_5c : 67.90 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.94 +pb_1c : 67.94 +pb_5c : 67.90 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.95 +pb_1c : 67.95 +pb_5c : 67.95 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.96 +pb_1c : 67.96 +pb_5c : 67.95 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.97 +pb_1c : 67.97 +pb_5c : 67.95 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.98 +pb_1c : 67.98 +pb_5c : 67.95 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +67.99 +pb_1c : 67.99 +pb_5c : 67.95 +pb_10c : 67.90 +pb_25c : 67.75 +pb_1d : 67.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.00 +pb_1c : 68.00 +pb_5c : 68.00 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.01 +pb_1c : 68.01 +pb_5c : 68.00 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.02 +pb_1c : 68.02 +pb_5c : 68.00 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.03 +pb_1c : 68.03 +pb_5c : 68.00 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.04 +pb_1c : 68.04 +pb_5c : 68.00 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.05 +pb_1c : 68.05 +pb_5c : 68.05 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.06 +pb_1c : 68.06 +pb_5c : 68.05 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.07 +pb_1c : 68.07 +pb_5c : 68.05 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.08 +pb_1c : 68.08 +pb_5c : 68.05 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.09 +pb_1c : 68.09 +pb_5c : 68.05 +pb_10c : 68.00 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.10 +pb_1c : 68.10 +pb_5c : 68.10 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.11 +pb_1c : 68.11 +pb_5c : 68.10 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.12 +pb_1c : 68.12 +pb_5c : 68.10 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.13 +pb_1c : 68.13 +pb_5c : 68.10 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.14 +pb_1c : 68.14 +pb_5c : 68.10 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.15 +pb_1c : 68.15 +pb_5c : 68.15 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.16 +pb_1c : 68.16 +pb_5c : 68.15 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.17 +pb_1c : 68.17 +pb_5c : 68.15 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.18 +pb_1c : 68.18 +pb_5c : 68.15 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.19 +pb_1c : 68.19 +pb_5c : 68.15 +pb_10c : 68.10 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.20 +pb_1c : 68.20 +pb_5c : 68.20 +pb_10c : 68.20 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.21 +pb_1c : 68.21 +pb_5c : 68.20 +pb_10c : 68.20 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.22 +pb_1c : 68.22 +pb_5c : 68.20 +pb_10c : 68.20 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.23 +pb_1c : 68.23 +pb_5c : 68.20 +pb_10c : 68.20 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.24 +pb_1c : 68.24 +pb_5c : 68.20 +pb_10c : 68.20 +pb_25c : 68.00 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.25 +pb_1c : 68.25 +pb_5c : 68.25 +pb_10c : 68.20 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.26 +pb_1c : 68.26 +pb_5c : 68.25 +pb_10c : 68.20 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.27 +pb_1c : 68.27 +pb_5c : 68.25 +pb_10c : 68.20 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.28 +pb_1c : 68.28 +pb_5c : 68.25 +pb_10c : 68.20 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.29 +pb_1c : 68.29 +pb_5c : 68.25 +pb_10c : 68.20 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.30 +pb_1c : 68.30 +pb_5c : 68.30 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.31 +pb_1c : 68.31 +pb_5c : 68.30 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.32 +pb_1c : 68.32 +pb_5c : 68.30 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.33 +pb_1c : 68.33 +pb_5c : 68.30 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.34 +pb_1c : 68.34 +pb_5c : 68.30 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.35 +pb_1c : 68.35 +pb_5c : 68.35 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.36 +pb_1c : 68.36 +pb_5c : 68.35 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.37 +pb_1c : 68.37 +pb_5c : 68.35 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.38 +pb_1c : 68.38 +pb_5c : 68.35 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.39 +pb_1c : 68.39 +pb_5c : 68.35 +pb_10c : 68.30 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.40 +pb_1c : 68.40 +pb_5c : 68.40 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.41 +pb_1c : 68.41 +pb_5c : 68.40 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.42 +pb_1c : 68.42 +pb_5c : 68.40 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.43 +pb_1c : 68.43 +pb_5c : 68.40 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.44 +pb_1c : 68.44 +pb_5c : 68.40 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.45 +pb_1c : 68.45 +pb_5c : 68.45 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.46 +pb_1c : 68.46 +pb_5c : 68.45 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.47 +pb_1c : 68.47 +pb_5c : 68.45 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.48 +pb_1c : 68.48 +pb_5c : 68.45 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.49 +pb_1c : 68.49 +pb_5c : 68.45 +pb_10c : 68.40 +pb_25c : 68.25 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.50 +pb_1c : 68.50 +pb_5c : 68.50 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.51 +pb_1c : 68.51 +pb_5c : 68.50 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.52 +pb_1c : 68.52 +pb_5c : 68.50 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.53 +pb_1c : 68.53 +pb_5c : 68.50 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.54 +pb_1c : 68.54 +pb_5c : 68.50 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.55 +pb_1c : 68.55 +pb_5c : 68.55 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.56 +pb_1c : 68.56 +pb_5c : 68.55 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.57 +pb_1c : 68.57 +pb_5c : 68.55 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.58 +pb_1c : 68.58 +pb_5c : 68.55 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.59 +pb_1c : 68.59 +pb_5c : 68.55 +pb_10c : 68.50 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.60 +pb_1c : 68.60 +pb_5c : 68.60 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.61 +pb_1c : 68.61 +pb_5c : 68.60 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.62 +pb_1c : 68.62 +pb_5c : 68.60 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.63 +pb_1c : 68.63 +pb_5c : 68.60 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.64 +pb_1c : 68.64 +pb_5c : 68.60 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.65 +pb_1c : 68.65 +pb_5c : 68.65 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.66 +pb_1c : 68.66 +pb_5c : 68.65 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.67 +pb_1c : 68.67 +pb_5c : 68.65 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.68 +pb_1c : 68.68 +pb_5c : 68.65 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.69 +pb_1c : 68.69 +pb_5c : 68.65 +pb_10c : 68.60 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.70 +pb_1c : 68.70 +pb_5c : 68.70 +pb_10c : 68.70 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.71 +pb_1c : 68.71 +pb_5c : 68.70 +pb_10c : 68.70 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.72 +pb_1c : 68.72 +pb_5c : 68.70 +pb_10c : 68.70 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.73 +pb_1c : 68.73 +pb_5c : 68.70 +pb_10c : 68.70 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.74 +pb_1c : 68.74 +pb_5c : 68.70 +pb_10c : 68.70 +pb_25c : 68.50 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.75 +pb_1c : 68.75 +pb_5c : 68.75 +pb_10c : 68.70 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.76 +pb_1c : 68.76 +pb_5c : 68.75 +pb_10c : 68.70 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.77 +pb_1c : 68.77 +pb_5c : 68.75 +pb_10c : 68.70 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.78 +pb_1c : 68.78 +pb_5c : 68.75 +pb_10c : 68.70 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.79 +pb_1c : 68.79 +pb_5c : 68.75 +pb_10c : 68.70 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.80 +pb_1c : 68.80 +pb_5c : 68.80 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.81 +pb_1c : 68.81 +pb_5c : 68.80 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.82 +pb_1c : 68.82 +pb_5c : 68.80 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.83 +pb_1c : 68.83 +pb_5c : 68.80 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.84 +pb_1c : 68.84 +pb_5c : 68.80 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.85 +pb_1c : 68.85 +pb_5c : 68.85 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.86 +pb_1c : 68.86 +pb_5c : 68.85 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.87 +pb_1c : 68.87 +pb_5c : 68.85 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.88 +pb_1c : 68.88 +pb_5c : 68.85 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.89 +pb_1c : 68.89 +pb_5c : 68.85 +pb_10c : 68.80 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.90 +pb_1c : 68.90 +pb_5c : 68.90 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.91 +pb_1c : 68.91 +pb_5c : 68.90 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.92 +pb_1c : 68.92 +pb_5c : 68.90 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.93 +pb_1c : 68.93 +pb_5c : 68.90 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.94 +pb_1c : 68.94 +pb_5c : 68.90 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.95 +pb_1c : 68.95 +pb_5c : 68.95 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.96 +pb_1c : 68.96 +pb_5c : 68.95 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.97 +pb_1c : 68.97 +pb_5c : 68.95 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.98 +pb_1c : 68.98 +pb_5c : 68.95 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +68.99 +pb_1c : 68.99 +pb_5c : 68.95 +pb_10c : 68.90 +pb_25c : 68.75 +pb_1d : 68.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.00 +pb_1c : 69.00 +pb_5c : 69.00 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.01 +pb_1c : 69.01 +pb_5c : 69.00 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.02 +pb_1c : 69.02 +pb_5c : 69.00 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.03 +pb_1c : 69.03 +pb_5c : 69.00 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.04 +pb_1c : 69.04 +pb_5c : 69.00 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.05 +pb_1c : 69.05 +pb_5c : 69.05 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.06 +pb_1c : 69.06 +pb_5c : 69.05 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.07 +pb_1c : 69.07 +pb_5c : 69.05 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.08 +pb_1c : 69.08 +pb_5c : 69.05 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.09 +pb_1c : 69.09 +pb_5c : 69.05 +pb_10c : 69.00 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.10 +pb_1c : 69.10 +pb_5c : 69.10 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.11 +pb_1c : 69.11 +pb_5c : 69.10 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.12 +pb_1c : 69.12 +pb_5c : 69.10 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.13 +pb_1c : 69.13 +pb_5c : 69.10 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.14 +pb_1c : 69.14 +pb_5c : 69.10 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.15 +pb_1c : 69.15 +pb_5c : 69.15 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.16 +pb_1c : 69.16 +pb_5c : 69.15 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.17 +pb_1c : 69.17 +pb_5c : 69.15 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.18 +pb_1c : 69.18 +pb_5c : 69.15 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.19 +pb_1c : 69.19 +pb_5c : 69.15 +pb_10c : 69.10 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.20 +pb_1c : 69.20 +pb_5c : 69.20 +pb_10c : 69.20 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.21 +pb_1c : 69.21 +pb_5c : 69.20 +pb_10c : 69.20 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.22 +pb_1c : 69.22 +pb_5c : 69.20 +pb_10c : 69.20 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.23 +pb_1c : 69.23 +pb_5c : 69.20 +pb_10c : 69.20 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.24 +pb_1c : 69.24 +pb_5c : 69.20 +pb_10c : 69.20 +pb_25c : 69.00 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.25 +pb_1c : 69.25 +pb_5c : 69.25 +pb_10c : 69.20 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.26 +pb_1c : 69.26 +pb_5c : 69.25 +pb_10c : 69.20 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.27 +pb_1c : 69.27 +pb_5c : 69.25 +pb_10c : 69.20 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.28 +pb_1c : 69.28 +pb_5c : 69.25 +pb_10c : 69.20 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.29 +pb_1c : 69.29 +pb_5c : 69.25 +pb_10c : 69.20 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.30 +pb_1c : 69.30 +pb_5c : 69.30 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.31 +pb_1c : 69.31 +pb_5c : 69.30 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.32 +pb_1c : 69.32 +pb_5c : 69.30 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.33 +pb_1c : 69.33 +pb_5c : 69.30 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.34 +pb_1c : 69.34 +pb_5c : 69.30 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.35 +pb_1c : 69.35 +pb_5c : 69.35 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.36 +pb_1c : 69.36 +pb_5c : 69.35 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.37 +pb_1c : 69.37 +pb_5c : 69.35 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.38 +pb_1c : 69.38 +pb_5c : 69.35 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.39 +pb_1c : 69.39 +pb_5c : 69.35 +pb_10c : 69.30 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.40 +pb_1c : 69.40 +pb_5c : 69.40 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.41 +pb_1c : 69.41 +pb_5c : 69.40 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.42 +pb_1c : 69.42 +pb_5c : 69.40 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.43 +pb_1c : 69.43 +pb_5c : 69.40 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.44 +pb_1c : 69.44 +pb_5c : 69.40 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.45 +pb_1c : 69.45 +pb_5c : 69.45 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.46 +pb_1c : 69.46 +pb_5c : 69.45 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.47 +pb_1c : 69.47 +pb_5c : 69.45 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.48 +pb_1c : 69.48 +pb_5c : 69.45 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.49 +pb_1c : 69.49 +pb_5c : 69.45 +pb_10c : 69.40 +pb_25c : 69.25 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.50 +pb_1c : 69.50 +pb_5c : 69.50 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.51 +pb_1c : 69.51 +pb_5c : 69.50 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.52 +pb_1c : 69.52 +pb_5c : 69.50 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.53 +pb_1c : 69.53 +pb_5c : 69.50 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.54 +pb_1c : 69.54 +pb_5c : 69.50 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.55 +pb_1c : 69.55 +pb_5c : 69.55 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.56 +pb_1c : 69.56 +pb_5c : 69.55 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.57 +pb_1c : 69.57 +pb_5c : 69.55 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.58 +pb_1c : 69.58 +pb_5c : 69.55 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.59 +pb_1c : 69.59 +pb_5c : 69.55 +pb_10c : 69.50 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.60 +pb_1c : 69.60 +pb_5c : 69.60 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.61 +pb_1c : 69.61 +pb_5c : 69.60 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.62 +pb_1c : 69.62 +pb_5c : 69.60 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.63 +pb_1c : 69.63 +pb_5c : 69.60 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.64 +pb_1c : 69.64 +pb_5c : 69.60 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.65 +pb_1c : 69.65 +pb_5c : 69.65 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.66 +pb_1c : 69.66 +pb_5c : 69.65 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.67 +pb_1c : 69.67 +pb_5c : 69.65 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.68 +pb_1c : 69.68 +pb_5c : 69.65 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.69 +pb_1c : 69.69 +pb_5c : 69.65 +pb_10c : 69.60 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.70 +pb_1c : 69.70 +pb_5c : 69.70 +pb_10c : 69.70 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.71 +pb_1c : 69.71 +pb_5c : 69.70 +pb_10c : 69.70 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.72 +pb_1c : 69.72 +pb_5c : 69.70 +pb_10c : 69.70 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.73 +pb_1c : 69.73 +pb_5c : 69.70 +pb_10c : 69.70 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.74 +pb_1c : 69.74 +pb_5c : 69.70 +pb_10c : 69.70 +pb_25c : 69.50 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.75 +pb_1c : 69.75 +pb_5c : 69.75 +pb_10c : 69.70 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.76 +pb_1c : 69.76 +pb_5c : 69.75 +pb_10c : 69.70 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.77 +pb_1c : 69.77 +pb_5c : 69.75 +pb_10c : 69.70 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.78 +pb_1c : 69.78 +pb_5c : 69.75 +pb_10c : 69.70 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.79 +pb_1c : 69.79 +pb_5c : 69.75 +pb_10c : 69.70 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.80 +pb_1c : 69.80 +pb_5c : 69.80 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.81 +pb_1c : 69.81 +pb_5c : 69.80 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.82 +pb_1c : 69.82 +pb_5c : 69.80 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.83 +pb_1c : 69.83 +pb_5c : 69.80 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.84 +pb_1c : 69.84 +pb_5c : 69.80 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.85 +pb_1c : 69.85 +pb_5c : 69.85 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.86 +pb_1c : 69.86 +pb_5c : 69.85 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.87 +pb_1c : 69.87 +pb_5c : 69.85 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.88 +pb_1c : 69.88 +pb_5c : 69.85 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.89 +pb_1c : 69.89 +pb_5c : 69.85 +pb_10c : 69.80 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.90 +pb_1c : 69.90 +pb_5c : 69.90 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.91 +pb_1c : 69.91 +pb_5c : 69.90 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.92 +pb_1c : 69.92 +pb_5c : 69.90 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.93 +pb_1c : 69.93 +pb_5c : 69.90 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.94 +pb_1c : 69.94 +pb_5c : 69.90 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.95 +pb_1c : 69.95 +pb_5c : 69.95 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.96 +pb_1c : 69.96 +pb_5c : 69.95 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.97 +pb_1c : 69.97 +pb_5c : 69.95 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.98 +pb_1c : 69.98 +pb_5c : 69.95 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +69.99 +pb_1c : 69.99 +pb_5c : 69.95 +pb_10c : 69.90 +pb_25c : 69.75 +pb_1d : 69.00 +pb_5d : 65.00 +pb_10d : 60.00 + +70.00 +pb_1c : 70.00 +pb_5c : 70.00 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.01 +pb_1c : 70.01 +pb_5c : 70.00 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.02 +pb_1c : 70.02 +pb_5c : 70.00 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.03 +pb_1c : 70.03 +pb_5c : 70.00 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.04 +pb_1c : 70.04 +pb_5c : 70.00 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.05 +pb_1c : 70.05 +pb_5c : 70.05 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.06 +pb_1c : 70.06 +pb_5c : 70.05 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.07 +pb_1c : 70.07 +pb_5c : 70.05 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.08 +pb_1c : 70.08 +pb_5c : 70.05 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.09 +pb_1c : 70.09 +pb_5c : 70.05 +pb_10c : 70.00 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.10 +pb_1c : 70.10 +pb_5c : 70.10 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.11 +pb_1c : 70.11 +pb_5c : 70.10 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.12 +pb_1c : 70.12 +pb_5c : 70.10 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.13 +pb_1c : 70.13 +pb_5c : 70.10 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.14 +pb_1c : 70.14 +pb_5c : 70.10 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.15 +pb_1c : 70.15 +pb_5c : 70.15 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.16 +pb_1c : 70.16 +pb_5c : 70.15 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.17 +pb_1c : 70.17 +pb_5c : 70.15 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.18 +pb_1c : 70.18 +pb_5c : 70.15 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.19 +pb_1c : 70.19 +pb_5c : 70.15 +pb_10c : 70.10 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.20 +pb_1c : 70.20 +pb_5c : 70.20 +pb_10c : 70.20 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.21 +pb_1c : 70.21 +pb_5c : 70.20 +pb_10c : 70.20 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.22 +pb_1c : 70.22 +pb_5c : 70.20 +pb_10c : 70.20 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.23 +pb_1c : 70.23 +pb_5c : 70.20 +pb_10c : 70.20 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.24 +pb_1c : 70.24 +pb_5c : 70.20 +pb_10c : 70.20 +pb_25c : 70.00 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.25 +pb_1c : 70.25 +pb_5c : 70.25 +pb_10c : 70.20 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.26 +pb_1c : 70.26 +pb_5c : 70.25 +pb_10c : 70.20 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.27 +pb_1c : 70.27 +pb_5c : 70.25 +pb_10c : 70.20 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.28 +pb_1c : 70.28 +pb_5c : 70.25 +pb_10c : 70.20 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.29 +pb_1c : 70.29 +pb_5c : 70.25 +pb_10c : 70.20 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.30 +pb_1c : 70.30 +pb_5c : 70.30 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.31 +pb_1c : 70.31 +pb_5c : 70.30 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.32 +pb_1c : 70.32 +pb_5c : 70.30 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.33 +pb_1c : 70.33 +pb_5c : 70.30 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.34 +pb_1c : 70.34 +pb_5c : 70.30 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.35 +pb_1c : 70.35 +pb_5c : 70.35 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.36 +pb_1c : 70.36 +pb_5c : 70.35 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.37 +pb_1c : 70.37 +pb_5c : 70.35 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.38 +pb_1c : 70.38 +pb_5c : 70.35 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.39 +pb_1c : 70.39 +pb_5c : 70.35 +pb_10c : 70.30 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.40 +pb_1c : 70.40 +pb_5c : 70.40 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.41 +pb_1c : 70.41 +pb_5c : 70.40 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.42 +pb_1c : 70.42 +pb_5c : 70.40 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.43 +pb_1c : 70.43 +pb_5c : 70.40 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.44 +pb_1c : 70.44 +pb_5c : 70.40 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.45 +pb_1c : 70.45 +pb_5c : 70.45 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.46 +pb_1c : 70.46 +pb_5c : 70.45 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.47 +pb_1c : 70.47 +pb_5c : 70.45 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.48 +pb_1c : 70.48 +pb_5c : 70.45 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.49 +pb_1c : 70.49 +pb_5c : 70.45 +pb_10c : 70.40 +pb_25c : 70.25 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.50 +pb_1c : 70.50 +pb_5c : 70.50 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.51 +pb_1c : 70.51 +pb_5c : 70.50 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.52 +pb_1c : 70.52 +pb_5c : 70.50 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.53 +pb_1c : 70.53 +pb_5c : 70.50 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.54 +pb_1c : 70.54 +pb_5c : 70.50 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.55 +pb_1c : 70.55 +pb_5c : 70.55 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.56 +pb_1c : 70.56 +pb_5c : 70.55 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.57 +pb_1c : 70.57 +pb_5c : 70.55 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.58 +pb_1c : 70.58 +pb_5c : 70.55 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.59 +pb_1c : 70.59 +pb_5c : 70.55 +pb_10c : 70.50 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.60 +pb_1c : 70.60 +pb_5c : 70.60 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.61 +pb_1c : 70.61 +pb_5c : 70.60 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.62 +pb_1c : 70.62 +pb_5c : 70.60 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.63 +pb_1c : 70.63 +pb_5c : 70.60 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.64 +pb_1c : 70.64 +pb_5c : 70.60 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.65 +pb_1c : 70.65 +pb_5c : 70.65 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.66 +pb_1c : 70.66 +pb_5c : 70.65 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.67 +pb_1c : 70.67 +pb_5c : 70.65 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.68 +pb_1c : 70.68 +pb_5c : 70.65 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.69 +pb_1c : 70.69 +pb_5c : 70.65 +pb_10c : 70.60 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.70 +pb_1c : 70.70 +pb_5c : 70.70 +pb_10c : 70.70 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.71 +pb_1c : 70.71 +pb_5c : 70.70 +pb_10c : 70.70 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.72 +pb_1c : 70.72 +pb_5c : 70.70 +pb_10c : 70.70 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.73 +pb_1c : 70.73 +pb_5c : 70.70 +pb_10c : 70.70 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.74 +pb_1c : 70.74 +pb_5c : 70.70 +pb_10c : 70.70 +pb_25c : 70.50 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.75 +pb_1c : 70.75 +pb_5c : 70.75 +pb_10c : 70.70 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.76 +pb_1c : 70.76 +pb_5c : 70.75 +pb_10c : 70.70 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.77 +pb_1c : 70.77 +pb_5c : 70.75 +pb_10c : 70.70 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.78 +pb_1c : 70.78 +pb_5c : 70.75 +pb_10c : 70.70 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.79 +pb_1c : 70.79 +pb_5c : 70.75 +pb_10c : 70.70 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.80 +pb_1c : 70.80 +pb_5c : 70.80 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.81 +pb_1c : 70.81 +pb_5c : 70.80 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.82 +pb_1c : 70.82 +pb_5c : 70.80 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.83 +pb_1c : 70.83 +pb_5c : 70.80 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.84 +pb_1c : 70.84 +pb_5c : 70.80 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.85 +pb_1c : 70.85 +pb_5c : 70.85 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.86 +pb_1c : 70.86 +pb_5c : 70.85 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.87 +pb_1c : 70.87 +pb_5c : 70.85 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.88 +pb_1c : 70.88 +pb_5c : 70.85 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.89 +pb_1c : 70.89 +pb_5c : 70.85 +pb_10c : 70.80 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.90 +pb_1c : 70.90 +pb_5c : 70.90 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.91 +pb_1c : 70.91 +pb_5c : 70.90 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.92 +pb_1c : 70.92 +pb_5c : 70.90 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.93 +pb_1c : 70.93 +pb_5c : 70.90 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.94 +pb_1c : 70.94 +pb_5c : 70.90 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.95 +pb_1c : 70.95 +pb_5c : 70.95 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.96 +pb_1c : 70.96 +pb_5c : 70.95 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.97 +pb_1c : 70.97 +pb_5c : 70.95 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.98 +pb_1c : 70.98 +pb_5c : 70.95 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +70.99 +pb_1c : 70.99 +pb_5c : 70.95 +pb_10c : 70.90 +pb_25c : 70.75 +pb_1d : 70.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.00 +pb_1c : 71.00 +pb_5c : 71.00 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.01 +pb_1c : 71.01 +pb_5c : 71.00 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.02 +pb_1c : 71.02 +pb_5c : 71.00 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.03 +pb_1c : 71.03 +pb_5c : 71.00 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.04 +pb_1c : 71.04 +pb_5c : 71.00 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.05 +pb_1c : 71.05 +pb_5c : 71.05 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.06 +pb_1c : 71.06 +pb_5c : 71.05 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.07 +pb_1c : 71.07 +pb_5c : 71.05 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.08 +pb_1c : 71.08 +pb_5c : 71.05 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.09 +pb_1c : 71.09 +pb_5c : 71.05 +pb_10c : 71.00 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.10 +pb_1c : 71.10 +pb_5c : 71.10 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.11 +pb_1c : 71.11 +pb_5c : 71.10 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.12 +pb_1c : 71.12 +pb_5c : 71.10 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.13 +pb_1c : 71.13 +pb_5c : 71.10 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.14 +pb_1c : 71.14 +pb_5c : 71.10 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.15 +pb_1c : 71.15 +pb_5c : 71.15 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.16 +pb_1c : 71.16 +pb_5c : 71.15 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.17 +pb_1c : 71.17 +pb_5c : 71.15 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.18 +pb_1c : 71.18 +pb_5c : 71.15 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.19 +pb_1c : 71.19 +pb_5c : 71.15 +pb_10c : 71.10 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.20 +pb_1c : 71.20 +pb_5c : 71.20 +pb_10c : 71.20 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.21 +pb_1c : 71.21 +pb_5c : 71.20 +pb_10c : 71.20 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.22 +pb_1c : 71.22 +pb_5c : 71.20 +pb_10c : 71.20 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.23 +pb_1c : 71.23 +pb_5c : 71.20 +pb_10c : 71.20 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.24 +pb_1c : 71.24 +pb_5c : 71.20 +pb_10c : 71.20 +pb_25c : 71.00 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.25 +pb_1c : 71.25 +pb_5c : 71.25 +pb_10c : 71.20 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.26 +pb_1c : 71.26 +pb_5c : 71.25 +pb_10c : 71.20 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.27 +pb_1c : 71.27 +pb_5c : 71.25 +pb_10c : 71.20 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.28 +pb_1c : 71.28 +pb_5c : 71.25 +pb_10c : 71.20 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.29 +pb_1c : 71.29 +pb_5c : 71.25 +pb_10c : 71.20 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.30 +pb_1c : 71.30 +pb_5c : 71.30 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.31 +pb_1c : 71.31 +pb_5c : 71.30 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.32 +pb_1c : 71.32 +pb_5c : 71.30 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.33 +pb_1c : 71.33 +pb_5c : 71.30 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.34 +pb_1c : 71.34 +pb_5c : 71.30 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.35 +pb_1c : 71.35 +pb_5c : 71.35 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.36 +pb_1c : 71.36 +pb_5c : 71.35 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.37 +pb_1c : 71.37 +pb_5c : 71.35 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.38 +pb_1c : 71.38 +pb_5c : 71.35 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.39 +pb_1c : 71.39 +pb_5c : 71.35 +pb_10c : 71.30 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.40 +pb_1c : 71.40 +pb_5c : 71.40 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.41 +pb_1c : 71.41 +pb_5c : 71.40 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.42 +pb_1c : 71.42 +pb_5c : 71.40 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.43 +pb_1c : 71.43 +pb_5c : 71.40 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.44 +pb_1c : 71.44 +pb_5c : 71.40 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.45 +pb_1c : 71.45 +pb_5c : 71.45 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.46 +pb_1c : 71.46 +pb_5c : 71.45 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.47 +pb_1c : 71.47 +pb_5c : 71.45 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.48 +pb_1c : 71.48 +pb_5c : 71.45 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.49 +pb_1c : 71.49 +pb_5c : 71.45 +pb_10c : 71.40 +pb_25c : 71.25 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.50 +pb_1c : 71.50 +pb_5c : 71.50 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.51 +pb_1c : 71.51 +pb_5c : 71.50 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.52 +pb_1c : 71.52 +pb_5c : 71.50 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.53 +pb_1c : 71.53 +pb_5c : 71.50 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.54 +pb_1c : 71.54 +pb_5c : 71.50 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.55 +pb_1c : 71.55 +pb_5c : 71.55 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.56 +pb_1c : 71.56 +pb_5c : 71.55 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.57 +pb_1c : 71.57 +pb_5c : 71.55 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.58 +pb_1c : 71.58 +pb_5c : 71.55 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.59 +pb_1c : 71.59 +pb_5c : 71.55 +pb_10c : 71.50 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.60 +pb_1c : 71.60 +pb_5c : 71.60 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.61 +pb_1c : 71.61 +pb_5c : 71.60 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.62 +pb_1c : 71.62 +pb_5c : 71.60 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.63 +pb_1c : 71.63 +pb_5c : 71.60 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.64 +pb_1c : 71.64 +pb_5c : 71.60 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.65 +pb_1c : 71.65 +pb_5c : 71.65 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.66 +pb_1c : 71.66 +pb_5c : 71.65 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.67 +pb_1c : 71.67 +pb_5c : 71.65 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.68 +pb_1c : 71.68 +pb_5c : 71.65 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.69 +pb_1c : 71.69 +pb_5c : 71.65 +pb_10c : 71.60 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.70 +pb_1c : 71.70 +pb_5c : 71.70 +pb_10c : 71.70 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.71 +pb_1c : 71.71 +pb_5c : 71.70 +pb_10c : 71.70 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.72 +pb_1c : 71.72 +pb_5c : 71.70 +pb_10c : 71.70 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.73 +pb_1c : 71.73 +pb_5c : 71.70 +pb_10c : 71.70 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.74 +pb_1c : 71.74 +pb_5c : 71.70 +pb_10c : 71.70 +pb_25c : 71.50 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.75 +pb_1c : 71.75 +pb_5c : 71.75 +pb_10c : 71.70 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.76 +pb_1c : 71.76 +pb_5c : 71.75 +pb_10c : 71.70 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.77 +pb_1c : 71.77 +pb_5c : 71.75 +pb_10c : 71.70 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.78 +pb_1c : 71.78 +pb_5c : 71.75 +pb_10c : 71.70 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.79 +pb_1c : 71.79 +pb_5c : 71.75 +pb_10c : 71.70 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.80 +pb_1c : 71.80 +pb_5c : 71.80 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.81 +pb_1c : 71.81 +pb_5c : 71.80 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.82 +pb_1c : 71.82 +pb_5c : 71.80 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.83 +pb_1c : 71.83 +pb_5c : 71.80 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.84 +pb_1c : 71.84 +pb_5c : 71.80 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.85 +pb_1c : 71.85 +pb_5c : 71.85 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.86 +pb_1c : 71.86 +pb_5c : 71.85 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.87 +pb_1c : 71.87 +pb_5c : 71.85 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.88 +pb_1c : 71.88 +pb_5c : 71.85 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.89 +pb_1c : 71.89 +pb_5c : 71.85 +pb_10c : 71.80 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.90 +pb_1c : 71.90 +pb_5c : 71.90 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.91 +pb_1c : 71.91 +pb_5c : 71.90 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.92 +pb_1c : 71.92 +pb_5c : 71.90 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.93 +pb_1c : 71.93 +pb_5c : 71.90 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.94 +pb_1c : 71.94 +pb_5c : 71.90 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.95 +pb_1c : 71.95 +pb_5c : 71.95 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.96 +pb_1c : 71.96 +pb_5c : 71.95 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.97 +pb_1c : 71.97 +pb_5c : 71.95 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.98 +pb_1c : 71.98 +pb_5c : 71.95 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +71.99 +pb_1c : 71.99 +pb_5c : 71.95 +pb_10c : 71.90 +pb_25c : 71.75 +pb_1d : 71.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.00 +pb_1c : 72.00 +pb_5c : 72.00 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.01 +pb_1c : 72.01 +pb_5c : 72.00 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.02 +pb_1c : 72.02 +pb_5c : 72.00 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.03 +pb_1c : 72.03 +pb_5c : 72.00 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.04 +pb_1c : 72.04 +pb_5c : 72.00 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.05 +pb_1c : 72.05 +pb_5c : 72.05 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.06 +pb_1c : 72.06 +pb_5c : 72.05 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.07 +pb_1c : 72.07 +pb_5c : 72.05 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.08 +pb_1c : 72.08 +pb_5c : 72.05 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.09 +pb_1c : 72.09 +pb_5c : 72.05 +pb_10c : 72.00 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.10 +pb_1c : 72.10 +pb_5c : 72.10 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.11 +pb_1c : 72.11 +pb_5c : 72.10 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.12 +pb_1c : 72.12 +pb_5c : 72.10 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.13 +pb_1c : 72.13 +pb_5c : 72.10 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.14 +pb_1c : 72.14 +pb_5c : 72.10 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.15 +pb_1c : 72.15 +pb_5c : 72.15 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.16 +pb_1c : 72.16 +pb_5c : 72.15 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.17 +pb_1c : 72.17 +pb_5c : 72.15 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.18 +pb_1c : 72.18 +pb_5c : 72.15 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.19 +pb_1c : 72.19 +pb_5c : 72.15 +pb_10c : 72.10 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.20 +pb_1c : 72.20 +pb_5c : 72.20 +pb_10c : 72.20 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.21 +pb_1c : 72.21 +pb_5c : 72.20 +pb_10c : 72.20 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.22 +pb_1c : 72.22 +pb_5c : 72.20 +pb_10c : 72.20 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.23 +pb_1c : 72.23 +pb_5c : 72.20 +pb_10c : 72.20 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.24 +pb_1c : 72.24 +pb_5c : 72.20 +pb_10c : 72.20 +pb_25c : 72.00 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.25 +pb_1c : 72.25 +pb_5c : 72.25 +pb_10c : 72.20 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.26 +pb_1c : 72.26 +pb_5c : 72.25 +pb_10c : 72.20 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.27 +pb_1c : 72.27 +pb_5c : 72.25 +pb_10c : 72.20 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.28 +pb_1c : 72.28 +pb_5c : 72.25 +pb_10c : 72.20 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.29 +pb_1c : 72.29 +pb_5c : 72.25 +pb_10c : 72.20 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.30 +pb_1c : 72.30 +pb_5c : 72.30 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.31 +pb_1c : 72.31 +pb_5c : 72.30 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.32 +pb_1c : 72.32 +pb_5c : 72.30 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.33 +pb_1c : 72.33 +pb_5c : 72.30 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.34 +pb_1c : 72.34 +pb_5c : 72.30 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.35 +pb_1c : 72.35 +pb_5c : 72.35 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.36 +pb_1c : 72.36 +pb_5c : 72.35 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.37 +pb_1c : 72.37 +pb_5c : 72.35 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.38 +pb_1c : 72.38 +pb_5c : 72.35 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.39 +pb_1c : 72.39 +pb_5c : 72.35 +pb_10c : 72.30 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.40 +pb_1c : 72.40 +pb_5c : 72.40 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.41 +pb_1c : 72.41 +pb_5c : 72.40 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.42 +pb_1c : 72.42 +pb_5c : 72.40 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.43 +pb_1c : 72.43 +pb_5c : 72.40 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.44 +pb_1c : 72.44 +pb_5c : 72.40 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.45 +pb_1c : 72.45 +pb_5c : 72.45 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.46 +pb_1c : 72.46 +pb_5c : 72.45 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.47 +pb_1c : 72.47 +pb_5c : 72.45 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.48 +pb_1c : 72.48 +pb_5c : 72.45 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.49 +pb_1c : 72.49 +pb_5c : 72.45 +pb_10c : 72.40 +pb_25c : 72.25 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.50 +pb_1c : 72.50 +pb_5c : 72.50 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.51 +pb_1c : 72.51 +pb_5c : 72.50 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.52 +pb_1c : 72.52 +pb_5c : 72.50 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.53 +pb_1c : 72.53 +pb_5c : 72.50 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.54 +pb_1c : 72.54 +pb_5c : 72.50 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.55 +pb_1c : 72.55 +pb_5c : 72.55 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.56 +pb_1c : 72.56 +pb_5c : 72.55 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.57 +pb_1c : 72.57 +pb_5c : 72.55 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.58 +pb_1c : 72.58 +pb_5c : 72.55 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.59 +pb_1c : 72.59 +pb_5c : 72.55 +pb_10c : 72.50 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.60 +pb_1c : 72.60 +pb_5c : 72.60 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.61 +pb_1c : 72.61 +pb_5c : 72.60 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.62 +pb_1c : 72.62 +pb_5c : 72.60 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.63 +pb_1c : 72.63 +pb_5c : 72.60 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.64 +pb_1c : 72.64 +pb_5c : 72.60 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.65 +pb_1c : 72.65 +pb_5c : 72.65 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.66 +pb_1c : 72.66 +pb_5c : 72.65 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.67 +pb_1c : 72.67 +pb_5c : 72.65 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.68 +pb_1c : 72.68 +pb_5c : 72.65 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.69 +pb_1c : 72.69 +pb_5c : 72.65 +pb_10c : 72.60 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.70 +pb_1c : 72.70 +pb_5c : 72.70 +pb_10c : 72.70 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.71 +pb_1c : 72.71 +pb_5c : 72.70 +pb_10c : 72.70 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.72 +pb_1c : 72.72 +pb_5c : 72.70 +pb_10c : 72.70 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.73 +pb_1c : 72.73 +pb_5c : 72.70 +pb_10c : 72.70 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.74 +pb_1c : 72.74 +pb_5c : 72.70 +pb_10c : 72.70 +pb_25c : 72.50 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.75 +pb_1c : 72.75 +pb_5c : 72.75 +pb_10c : 72.70 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.76 +pb_1c : 72.76 +pb_5c : 72.75 +pb_10c : 72.70 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.77 +pb_1c : 72.77 +pb_5c : 72.75 +pb_10c : 72.70 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.78 +pb_1c : 72.78 +pb_5c : 72.75 +pb_10c : 72.70 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.79 +pb_1c : 72.79 +pb_5c : 72.75 +pb_10c : 72.70 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.80 +pb_1c : 72.80 +pb_5c : 72.80 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.81 +pb_1c : 72.81 +pb_5c : 72.80 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.82 +pb_1c : 72.82 +pb_5c : 72.80 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.83 +pb_1c : 72.83 +pb_5c : 72.80 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.84 +pb_1c : 72.84 +pb_5c : 72.80 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.85 +pb_1c : 72.85 +pb_5c : 72.85 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.86 +pb_1c : 72.86 +pb_5c : 72.85 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.87 +pb_1c : 72.87 +pb_5c : 72.85 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.88 +pb_1c : 72.88 +pb_5c : 72.85 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.89 +pb_1c : 72.89 +pb_5c : 72.85 +pb_10c : 72.80 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.90 +pb_1c : 72.90 +pb_5c : 72.90 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.91 +pb_1c : 72.91 +pb_5c : 72.90 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.92 +pb_1c : 72.92 +pb_5c : 72.90 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.93 +pb_1c : 72.93 +pb_5c : 72.90 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.94 +pb_1c : 72.94 +pb_5c : 72.90 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.95 +pb_1c : 72.95 +pb_5c : 72.95 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.96 +pb_1c : 72.96 +pb_5c : 72.95 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.97 +pb_1c : 72.97 +pb_5c : 72.95 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.98 +pb_1c : 72.98 +pb_5c : 72.95 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +72.99 +pb_1c : 72.99 +pb_5c : 72.95 +pb_10c : 72.90 +pb_25c : 72.75 +pb_1d : 72.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.00 +pb_1c : 73.00 +pb_5c : 73.00 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.01 +pb_1c : 73.01 +pb_5c : 73.00 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.02 +pb_1c : 73.02 +pb_5c : 73.00 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.03 +pb_1c : 73.03 +pb_5c : 73.00 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.04 +pb_1c : 73.04 +pb_5c : 73.00 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.05 +pb_1c : 73.05 +pb_5c : 73.05 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.06 +pb_1c : 73.06 +pb_5c : 73.05 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.07 +pb_1c : 73.07 +pb_5c : 73.05 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.08 +pb_1c : 73.08 +pb_5c : 73.05 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.09 +pb_1c : 73.09 +pb_5c : 73.05 +pb_10c : 73.00 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.10 +pb_1c : 73.10 +pb_5c : 73.10 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.11 +pb_1c : 73.11 +pb_5c : 73.10 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.12 +pb_1c : 73.12 +pb_5c : 73.10 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.13 +pb_1c : 73.13 +pb_5c : 73.10 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.14 +pb_1c : 73.14 +pb_5c : 73.10 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.15 +pb_1c : 73.15 +pb_5c : 73.15 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.16 +pb_1c : 73.16 +pb_5c : 73.15 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.17 +pb_1c : 73.17 +pb_5c : 73.15 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.18 +pb_1c : 73.18 +pb_5c : 73.15 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.19 +pb_1c : 73.19 +pb_5c : 73.15 +pb_10c : 73.10 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.20 +pb_1c : 73.20 +pb_5c : 73.20 +pb_10c : 73.20 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.21 +pb_1c : 73.21 +pb_5c : 73.20 +pb_10c : 73.20 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.22 +pb_1c : 73.22 +pb_5c : 73.20 +pb_10c : 73.20 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.23 +pb_1c : 73.23 +pb_5c : 73.20 +pb_10c : 73.20 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.24 +pb_1c : 73.24 +pb_5c : 73.20 +pb_10c : 73.20 +pb_25c : 73.00 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.25 +pb_1c : 73.25 +pb_5c : 73.25 +pb_10c : 73.20 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.26 +pb_1c : 73.26 +pb_5c : 73.25 +pb_10c : 73.20 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.27 +pb_1c : 73.27 +pb_5c : 73.25 +pb_10c : 73.20 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.28 +pb_1c : 73.28 +pb_5c : 73.25 +pb_10c : 73.20 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.29 +pb_1c : 73.29 +pb_5c : 73.25 +pb_10c : 73.20 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.30 +pb_1c : 73.30 +pb_5c : 73.30 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.31 +pb_1c : 73.31 +pb_5c : 73.30 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.32 +pb_1c : 73.32 +pb_5c : 73.30 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.33 +pb_1c : 73.33 +pb_5c : 73.30 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.34 +pb_1c : 73.34 +pb_5c : 73.30 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.35 +pb_1c : 73.35 +pb_5c : 73.35 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.36 +pb_1c : 73.36 +pb_5c : 73.35 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.37 +pb_1c : 73.37 +pb_5c : 73.35 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.38 +pb_1c : 73.38 +pb_5c : 73.35 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.39 +pb_1c : 73.39 +pb_5c : 73.35 +pb_10c : 73.30 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.40 +pb_1c : 73.40 +pb_5c : 73.40 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.41 +pb_1c : 73.41 +pb_5c : 73.40 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.42 +pb_1c : 73.42 +pb_5c : 73.40 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.43 +pb_1c : 73.43 +pb_5c : 73.40 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.44 +pb_1c : 73.44 +pb_5c : 73.40 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.45 +pb_1c : 73.45 +pb_5c : 73.45 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.46 +pb_1c : 73.46 +pb_5c : 73.45 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.47 +pb_1c : 73.47 +pb_5c : 73.45 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.48 +pb_1c : 73.48 +pb_5c : 73.45 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.49 +pb_1c : 73.49 +pb_5c : 73.45 +pb_10c : 73.40 +pb_25c : 73.25 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.50 +pb_1c : 73.50 +pb_5c : 73.50 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.51 +pb_1c : 73.51 +pb_5c : 73.50 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.52 +pb_1c : 73.52 +pb_5c : 73.50 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.53 +pb_1c : 73.53 +pb_5c : 73.50 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.54 +pb_1c : 73.54 +pb_5c : 73.50 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.55 +pb_1c : 73.55 +pb_5c : 73.55 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.56 +pb_1c : 73.56 +pb_5c : 73.55 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.57 +pb_1c : 73.57 +pb_5c : 73.55 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.58 +pb_1c : 73.58 +pb_5c : 73.55 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.59 +pb_1c : 73.59 +pb_5c : 73.55 +pb_10c : 73.50 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.60 +pb_1c : 73.60 +pb_5c : 73.60 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.61 +pb_1c : 73.61 +pb_5c : 73.60 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.62 +pb_1c : 73.62 +pb_5c : 73.60 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.63 +pb_1c : 73.63 +pb_5c : 73.60 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.64 +pb_1c : 73.64 +pb_5c : 73.60 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.65 +pb_1c : 73.65 +pb_5c : 73.65 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.66 +pb_1c : 73.66 +pb_5c : 73.65 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.67 +pb_1c : 73.67 +pb_5c : 73.65 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.68 +pb_1c : 73.68 +pb_5c : 73.65 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.69 +pb_1c : 73.69 +pb_5c : 73.65 +pb_10c : 73.60 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.70 +pb_1c : 73.70 +pb_5c : 73.70 +pb_10c : 73.70 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.71 +pb_1c : 73.71 +pb_5c : 73.70 +pb_10c : 73.70 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.72 +pb_1c : 73.72 +pb_5c : 73.70 +pb_10c : 73.70 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.73 +pb_1c : 73.73 +pb_5c : 73.70 +pb_10c : 73.70 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.74 +pb_1c : 73.74 +pb_5c : 73.70 +pb_10c : 73.70 +pb_25c : 73.50 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.75 +pb_1c : 73.75 +pb_5c : 73.75 +pb_10c : 73.70 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.76 +pb_1c : 73.76 +pb_5c : 73.75 +pb_10c : 73.70 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.77 +pb_1c : 73.77 +pb_5c : 73.75 +pb_10c : 73.70 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.78 +pb_1c : 73.78 +pb_5c : 73.75 +pb_10c : 73.70 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.79 +pb_1c : 73.79 +pb_5c : 73.75 +pb_10c : 73.70 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.80 +pb_1c : 73.80 +pb_5c : 73.80 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.81 +pb_1c : 73.81 +pb_5c : 73.80 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.82 +pb_1c : 73.82 +pb_5c : 73.80 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.83 +pb_1c : 73.83 +pb_5c : 73.80 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.84 +pb_1c : 73.84 +pb_5c : 73.80 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.85 +pb_1c : 73.85 +pb_5c : 73.85 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.86 +pb_1c : 73.86 +pb_5c : 73.85 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.87 +pb_1c : 73.87 +pb_5c : 73.85 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.88 +pb_1c : 73.88 +pb_5c : 73.85 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.89 +pb_1c : 73.89 +pb_5c : 73.85 +pb_10c : 73.80 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.90 +pb_1c : 73.90 +pb_5c : 73.90 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.91 +pb_1c : 73.91 +pb_5c : 73.90 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.92 +pb_1c : 73.92 +pb_5c : 73.90 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.93 +pb_1c : 73.93 +pb_5c : 73.90 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.94 +pb_1c : 73.94 +pb_5c : 73.90 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.95 +pb_1c : 73.95 +pb_5c : 73.95 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.96 +pb_1c : 73.96 +pb_5c : 73.95 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.97 +pb_1c : 73.97 +pb_5c : 73.95 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.98 +pb_1c : 73.98 +pb_5c : 73.95 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +73.99 +pb_1c : 73.99 +pb_5c : 73.95 +pb_10c : 73.90 +pb_25c : 73.75 +pb_1d : 73.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.00 +pb_1c : 74.00 +pb_5c : 74.00 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.01 +pb_1c : 74.01 +pb_5c : 74.00 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.02 +pb_1c : 74.02 +pb_5c : 74.00 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.03 +pb_1c : 74.03 +pb_5c : 74.00 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.04 +pb_1c : 74.04 +pb_5c : 74.00 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.05 +pb_1c : 74.05 +pb_5c : 74.05 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.06 +pb_1c : 74.06 +pb_5c : 74.05 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.07 +pb_1c : 74.07 +pb_5c : 74.05 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.08 +pb_1c : 74.08 +pb_5c : 74.05 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.09 +pb_1c : 74.09 +pb_5c : 74.05 +pb_10c : 74.00 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.10 +pb_1c : 74.10 +pb_5c : 74.10 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.11 +pb_1c : 74.11 +pb_5c : 74.10 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.12 +pb_1c : 74.12 +pb_5c : 74.10 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.13 +pb_1c : 74.13 +pb_5c : 74.10 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.14 +pb_1c : 74.14 +pb_5c : 74.10 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.15 +pb_1c : 74.15 +pb_5c : 74.15 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.16 +pb_1c : 74.16 +pb_5c : 74.15 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.17 +pb_1c : 74.17 +pb_5c : 74.15 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.18 +pb_1c : 74.18 +pb_5c : 74.15 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.19 +pb_1c : 74.19 +pb_5c : 74.15 +pb_10c : 74.10 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.20 +pb_1c : 74.20 +pb_5c : 74.20 +pb_10c : 74.20 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.21 +pb_1c : 74.21 +pb_5c : 74.20 +pb_10c : 74.20 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.22 +pb_1c : 74.22 +pb_5c : 74.20 +pb_10c : 74.20 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.23 +pb_1c : 74.23 +pb_5c : 74.20 +pb_10c : 74.20 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.24 +pb_1c : 74.24 +pb_5c : 74.20 +pb_10c : 74.20 +pb_25c : 74.00 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.25 +pb_1c : 74.25 +pb_5c : 74.25 +pb_10c : 74.20 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.26 +pb_1c : 74.26 +pb_5c : 74.25 +pb_10c : 74.20 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.27 +pb_1c : 74.27 +pb_5c : 74.25 +pb_10c : 74.20 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.28 +pb_1c : 74.28 +pb_5c : 74.25 +pb_10c : 74.20 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.29 +pb_1c : 74.29 +pb_5c : 74.25 +pb_10c : 74.20 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.30 +pb_1c : 74.30 +pb_5c : 74.30 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.31 +pb_1c : 74.31 +pb_5c : 74.30 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.32 +pb_1c : 74.32 +pb_5c : 74.30 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.33 +pb_1c : 74.33 +pb_5c : 74.30 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.34 +pb_1c : 74.34 +pb_5c : 74.30 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.35 +pb_1c : 74.35 +pb_5c : 74.35 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.36 +pb_1c : 74.36 +pb_5c : 74.35 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.37 +pb_1c : 74.37 +pb_5c : 74.35 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.38 +pb_1c : 74.38 +pb_5c : 74.35 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.39 +pb_1c : 74.39 +pb_5c : 74.35 +pb_10c : 74.30 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.40 +pb_1c : 74.40 +pb_5c : 74.40 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.41 +pb_1c : 74.41 +pb_5c : 74.40 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.42 +pb_1c : 74.42 +pb_5c : 74.40 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.43 +pb_1c : 74.43 +pb_5c : 74.40 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.44 +pb_1c : 74.44 +pb_5c : 74.40 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.45 +pb_1c : 74.45 +pb_5c : 74.45 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.46 +pb_1c : 74.46 +pb_5c : 74.45 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.47 +pb_1c : 74.47 +pb_5c : 74.45 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.48 +pb_1c : 74.48 +pb_5c : 74.45 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.49 +pb_1c : 74.49 +pb_5c : 74.45 +pb_10c : 74.40 +pb_25c : 74.25 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.50 +pb_1c : 74.50 +pb_5c : 74.50 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.51 +pb_1c : 74.51 +pb_5c : 74.50 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.52 +pb_1c : 74.52 +pb_5c : 74.50 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.53 +pb_1c : 74.53 +pb_5c : 74.50 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.54 +pb_1c : 74.54 +pb_5c : 74.50 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.55 +pb_1c : 74.55 +pb_5c : 74.55 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.56 +pb_1c : 74.56 +pb_5c : 74.55 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.57 +pb_1c : 74.57 +pb_5c : 74.55 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.58 +pb_1c : 74.58 +pb_5c : 74.55 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.59 +pb_1c : 74.59 +pb_5c : 74.55 +pb_10c : 74.50 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.60 +pb_1c : 74.60 +pb_5c : 74.60 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.61 +pb_1c : 74.61 +pb_5c : 74.60 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.62 +pb_1c : 74.62 +pb_5c : 74.60 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.63 +pb_1c : 74.63 +pb_5c : 74.60 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.64 +pb_1c : 74.64 +pb_5c : 74.60 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.65 +pb_1c : 74.65 +pb_5c : 74.65 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.66 +pb_1c : 74.66 +pb_5c : 74.65 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.67 +pb_1c : 74.67 +pb_5c : 74.65 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.68 +pb_1c : 74.68 +pb_5c : 74.65 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.69 +pb_1c : 74.69 +pb_5c : 74.65 +pb_10c : 74.60 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.70 +pb_1c : 74.70 +pb_5c : 74.70 +pb_10c : 74.70 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.71 +pb_1c : 74.71 +pb_5c : 74.70 +pb_10c : 74.70 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.72 +pb_1c : 74.72 +pb_5c : 74.70 +pb_10c : 74.70 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.73 +pb_1c : 74.73 +pb_5c : 74.70 +pb_10c : 74.70 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.74 +pb_1c : 74.74 +pb_5c : 74.70 +pb_10c : 74.70 +pb_25c : 74.50 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.75 +pb_1c : 74.75 +pb_5c : 74.75 +pb_10c : 74.70 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.76 +pb_1c : 74.76 +pb_5c : 74.75 +pb_10c : 74.70 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.77 +pb_1c : 74.77 +pb_5c : 74.75 +pb_10c : 74.70 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.78 +pb_1c : 74.78 +pb_5c : 74.75 +pb_10c : 74.70 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.79 +pb_1c : 74.79 +pb_5c : 74.75 +pb_10c : 74.70 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.80 +pb_1c : 74.80 +pb_5c : 74.80 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.81 +pb_1c : 74.81 +pb_5c : 74.80 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.82 +pb_1c : 74.82 +pb_5c : 74.80 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.83 +pb_1c : 74.83 +pb_5c : 74.80 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.84 +pb_1c : 74.84 +pb_5c : 74.80 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.85 +pb_1c : 74.85 +pb_5c : 74.85 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.86 +pb_1c : 74.86 +pb_5c : 74.85 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.87 +pb_1c : 74.87 +pb_5c : 74.85 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.88 +pb_1c : 74.88 +pb_5c : 74.85 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.89 +pb_1c : 74.89 +pb_5c : 74.85 +pb_10c : 74.80 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.90 +pb_1c : 74.90 +pb_5c : 74.90 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.91 +pb_1c : 74.91 +pb_5c : 74.90 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.92 +pb_1c : 74.92 +pb_5c : 74.90 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.93 +pb_1c : 74.93 +pb_5c : 74.90 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.94 +pb_1c : 74.94 +pb_5c : 74.90 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.95 +pb_1c : 74.95 +pb_5c : 74.95 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.96 +pb_1c : 74.96 +pb_5c : 74.95 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.97 +pb_1c : 74.97 +pb_5c : 74.95 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.98 +pb_1c : 74.98 +pb_5c : 74.95 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +74.99 +pb_1c : 74.99 +pb_5c : 74.95 +pb_10c : 74.90 +pb_25c : 74.75 +pb_1d : 74.00 +pb_5d : 70.00 +pb_10d : 70.00 + +75.00 +pb_1c : 75.00 +pb_5c : 75.00 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.01 +pb_1c : 75.01 +pb_5c : 75.00 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.02 +pb_1c : 75.02 +pb_5c : 75.00 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.03 +pb_1c : 75.03 +pb_5c : 75.00 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.04 +pb_1c : 75.04 +pb_5c : 75.00 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.05 +pb_1c : 75.05 +pb_5c : 75.05 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.06 +pb_1c : 75.06 +pb_5c : 75.05 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.07 +pb_1c : 75.07 +pb_5c : 75.05 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.08 +pb_1c : 75.08 +pb_5c : 75.05 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.09 +pb_1c : 75.09 +pb_5c : 75.05 +pb_10c : 75.00 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.10 +pb_1c : 75.10 +pb_5c : 75.10 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.11 +pb_1c : 75.11 +pb_5c : 75.10 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.12 +pb_1c : 75.12 +pb_5c : 75.10 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.13 +pb_1c : 75.13 +pb_5c : 75.10 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.14 +pb_1c : 75.14 +pb_5c : 75.10 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.15 +pb_1c : 75.15 +pb_5c : 75.15 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.16 +pb_1c : 75.16 +pb_5c : 75.15 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.17 +pb_1c : 75.17 +pb_5c : 75.15 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.18 +pb_1c : 75.18 +pb_5c : 75.15 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.19 +pb_1c : 75.19 +pb_5c : 75.15 +pb_10c : 75.10 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.20 +pb_1c : 75.20 +pb_5c : 75.20 +pb_10c : 75.20 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.21 +pb_1c : 75.21 +pb_5c : 75.20 +pb_10c : 75.20 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.22 +pb_1c : 75.22 +pb_5c : 75.20 +pb_10c : 75.20 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.23 +pb_1c : 75.23 +pb_5c : 75.20 +pb_10c : 75.20 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.24 +pb_1c : 75.24 +pb_5c : 75.20 +pb_10c : 75.20 +pb_25c : 75.00 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.25 +pb_1c : 75.25 +pb_5c : 75.25 +pb_10c : 75.20 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.26 +pb_1c : 75.26 +pb_5c : 75.25 +pb_10c : 75.20 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.27 +pb_1c : 75.27 +pb_5c : 75.25 +pb_10c : 75.20 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.28 +pb_1c : 75.28 +pb_5c : 75.25 +pb_10c : 75.20 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.29 +pb_1c : 75.29 +pb_5c : 75.25 +pb_10c : 75.20 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.30 +pb_1c : 75.30 +pb_5c : 75.30 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.31 +pb_1c : 75.31 +pb_5c : 75.30 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.32 +pb_1c : 75.32 +pb_5c : 75.30 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.33 +pb_1c : 75.33 +pb_5c : 75.30 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.34 +pb_1c : 75.34 +pb_5c : 75.30 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.35 +pb_1c : 75.35 +pb_5c : 75.35 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.36 +pb_1c : 75.36 +pb_5c : 75.35 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.37 +pb_1c : 75.37 +pb_5c : 75.35 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.38 +pb_1c : 75.38 +pb_5c : 75.35 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.39 +pb_1c : 75.39 +pb_5c : 75.35 +pb_10c : 75.30 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.40 +pb_1c : 75.40 +pb_5c : 75.40 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.41 +pb_1c : 75.41 +pb_5c : 75.40 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.42 +pb_1c : 75.42 +pb_5c : 75.40 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.43 +pb_1c : 75.43 +pb_5c : 75.40 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.44 +pb_1c : 75.44 +pb_5c : 75.40 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.45 +pb_1c : 75.45 +pb_5c : 75.45 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.46 +pb_1c : 75.46 +pb_5c : 75.45 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.47 +pb_1c : 75.47 +pb_5c : 75.45 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.48 +pb_1c : 75.48 +pb_5c : 75.45 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.49 +pb_1c : 75.49 +pb_5c : 75.45 +pb_10c : 75.40 +pb_25c : 75.25 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.50 +pb_1c : 75.50 +pb_5c : 75.50 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.51 +pb_1c : 75.51 +pb_5c : 75.50 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.52 +pb_1c : 75.52 +pb_5c : 75.50 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.53 +pb_1c : 75.53 +pb_5c : 75.50 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.54 +pb_1c : 75.54 +pb_5c : 75.50 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.55 +pb_1c : 75.55 +pb_5c : 75.55 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.56 +pb_1c : 75.56 +pb_5c : 75.55 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.57 +pb_1c : 75.57 +pb_5c : 75.55 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.58 +pb_1c : 75.58 +pb_5c : 75.55 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.59 +pb_1c : 75.59 +pb_5c : 75.55 +pb_10c : 75.50 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.60 +pb_1c : 75.60 +pb_5c : 75.60 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.61 +pb_1c : 75.61 +pb_5c : 75.60 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.62 +pb_1c : 75.62 +pb_5c : 75.60 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.63 +pb_1c : 75.63 +pb_5c : 75.60 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.64 +pb_1c : 75.64 +pb_5c : 75.60 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.65 +pb_1c : 75.65 +pb_5c : 75.65 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.66 +pb_1c : 75.66 +pb_5c : 75.65 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.67 +pb_1c : 75.67 +pb_5c : 75.65 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.68 +pb_1c : 75.68 +pb_5c : 75.65 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.69 +pb_1c : 75.69 +pb_5c : 75.65 +pb_10c : 75.60 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.70 +pb_1c : 75.70 +pb_5c : 75.70 +pb_10c : 75.70 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.71 +pb_1c : 75.71 +pb_5c : 75.70 +pb_10c : 75.70 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.72 +pb_1c : 75.72 +pb_5c : 75.70 +pb_10c : 75.70 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.73 +pb_1c : 75.73 +pb_5c : 75.70 +pb_10c : 75.70 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.74 +pb_1c : 75.74 +pb_5c : 75.70 +pb_10c : 75.70 +pb_25c : 75.50 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.75 +pb_1c : 75.75 +pb_5c : 75.75 +pb_10c : 75.70 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.76 +pb_1c : 75.76 +pb_5c : 75.75 +pb_10c : 75.70 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.77 +pb_1c : 75.77 +pb_5c : 75.75 +pb_10c : 75.70 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.78 +pb_1c : 75.78 +pb_5c : 75.75 +pb_10c : 75.70 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.79 +pb_1c : 75.79 +pb_5c : 75.75 +pb_10c : 75.70 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.80 +pb_1c : 75.80 +pb_5c : 75.80 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.81 +pb_1c : 75.81 +pb_5c : 75.80 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.82 +pb_1c : 75.82 +pb_5c : 75.80 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.83 +pb_1c : 75.83 +pb_5c : 75.80 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.84 +pb_1c : 75.84 +pb_5c : 75.80 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.85 +pb_1c : 75.85 +pb_5c : 75.85 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.86 +pb_1c : 75.86 +pb_5c : 75.85 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.87 +pb_1c : 75.87 +pb_5c : 75.85 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.88 +pb_1c : 75.88 +pb_5c : 75.85 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.89 +pb_1c : 75.89 +pb_5c : 75.85 +pb_10c : 75.80 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.90 +pb_1c : 75.90 +pb_5c : 75.90 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.91 +pb_1c : 75.91 +pb_5c : 75.90 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.92 +pb_1c : 75.92 +pb_5c : 75.90 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.93 +pb_1c : 75.93 +pb_5c : 75.90 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.94 +pb_1c : 75.94 +pb_5c : 75.90 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.95 +pb_1c : 75.95 +pb_5c : 75.95 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.96 +pb_1c : 75.96 +pb_5c : 75.95 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.97 +pb_1c : 75.97 +pb_5c : 75.95 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.98 +pb_1c : 75.98 +pb_5c : 75.95 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +75.99 +pb_1c : 75.99 +pb_5c : 75.95 +pb_10c : 75.90 +pb_25c : 75.75 +pb_1d : 75.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.00 +pb_1c : 76.00 +pb_5c : 76.00 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.01 +pb_1c : 76.01 +pb_5c : 76.00 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.02 +pb_1c : 76.02 +pb_5c : 76.00 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.03 +pb_1c : 76.03 +pb_5c : 76.00 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.04 +pb_1c : 76.04 +pb_5c : 76.00 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.05 +pb_1c : 76.05 +pb_5c : 76.05 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.06 +pb_1c : 76.06 +pb_5c : 76.05 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.07 +pb_1c : 76.07 +pb_5c : 76.05 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.08 +pb_1c : 76.08 +pb_5c : 76.05 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.09 +pb_1c : 76.09 +pb_5c : 76.05 +pb_10c : 76.00 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.10 +pb_1c : 76.10 +pb_5c : 76.10 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.11 +pb_1c : 76.11 +pb_5c : 76.10 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.12 +pb_1c : 76.12 +pb_5c : 76.10 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.13 +pb_1c : 76.13 +pb_5c : 76.10 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.14 +pb_1c : 76.14 +pb_5c : 76.10 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.15 +pb_1c : 76.15 +pb_5c : 76.15 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.16 +pb_1c : 76.16 +pb_5c : 76.15 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.17 +pb_1c : 76.17 +pb_5c : 76.15 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.18 +pb_1c : 76.18 +pb_5c : 76.15 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.19 +pb_1c : 76.19 +pb_5c : 76.15 +pb_10c : 76.10 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.20 +pb_1c : 76.20 +pb_5c : 76.20 +pb_10c : 76.20 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.21 +pb_1c : 76.21 +pb_5c : 76.20 +pb_10c : 76.20 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.22 +pb_1c : 76.22 +pb_5c : 76.20 +pb_10c : 76.20 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.23 +pb_1c : 76.23 +pb_5c : 76.20 +pb_10c : 76.20 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.24 +pb_1c : 76.24 +pb_5c : 76.20 +pb_10c : 76.20 +pb_25c : 76.00 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.25 +pb_1c : 76.25 +pb_5c : 76.25 +pb_10c : 76.20 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.26 +pb_1c : 76.26 +pb_5c : 76.25 +pb_10c : 76.20 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.27 +pb_1c : 76.27 +pb_5c : 76.25 +pb_10c : 76.20 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.28 +pb_1c : 76.28 +pb_5c : 76.25 +pb_10c : 76.20 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.29 +pb_1c : 76.29 +pb_5c : 76.25 +pb_10c : 76.20 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.30 +pb_1c : 76.30 +pb_5c : 76.30 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.31 +pb_1c : 76.31 +pb_5c : 76.30 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.32 +pb_1c : 76.32 +pb_5c : 76.30 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.33 +pb_1c : 76.33 +pb_5c : 76.30 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.34 +pb_1c : 76.34 +pb_5c : 76.30 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.35 +pb_1c : 76.35 +pb_5c : 76.35 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.36 +pb_1c : 76.36 +pb_5c : 76.35 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.37 +pb_1c : 76.37 +pb_5c : 76.35 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.38 +pb_1c : 76.38 +pb_5c : 76.35 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.39 +pb_1c : 76.39 +pb_5c : 76.35 +pb_10c : 76.30 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.40 +pb_1c : 76.40 +pb_5c : 76.40 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.41 +pb_1c : 76.41 +pb_5c : 76.40 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.42 +pb_1c : 76.42 +pb_5c : 76.40 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.43 +pb_1c : 76.43 +pb_5c : 76.40 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.44 +pb_1c : 76.44 +pb_5c : 76.40 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.45 +pb_1c : 76.45 +pb_5c : 76.45 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.46 +pb_1c : 76.46 +pb_5c : 76.45 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.47 +pb_1c : 76.47 +pb_5c : 76.45 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.48 +pb_1c : 76.48 +pb_5c : 76.45 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.49 +pb_1c : 76.49 +pb_5c : 76.45 +pb_10c : 76.40 +pb_25c : 76.25 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.50 +pb_1c : 76.50 +pb_5c : 76.50 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.51 +pb_1c : 76.51 +pb_5c : 76.50 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.52 +pb_1c : 76.52 +pb_5c : 76.50 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.53 +pb_1c : 76.53 +pb_5c : 76.50 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.54 +pb_1c : 76.54 +pb_5c : 76.50 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.55 +pb_1c : 76.55 +pb_5c : 76.55 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.56 +pb_1c : 76.56 +pb_5c : 76.55 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.57 +pb_1c : 76.57 +pb_5c : 76.55 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.58 +pb_1c : 76.58 +pb_5c : 76.55 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.59 +pb_1c : 76.59 +pb_5c : 76.55 +pb_10c : 76.50 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.60 +pb_1c : 76.60 +pb_5c : 76.60 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.61 +pb_1c : 76.61 +pb_5c : 76.60 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.62 +pb_1c : 76.62 +pb_5c : 76.60 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.63 +pb_1c : 76.63 +pb_5c : 76.60 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.64 +pb_1c : 76.64 +pb_5c : 76.60 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.65 +pb_1c : 76.65 +pb_5c : 76.65 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.66 +pb_1c : 76.66 +pb_5c : 76.65 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.67 +pb_1c : 76.67 +pb_5c : 76.65 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.68 +pb_1c : 76.68 +pb_5c : 76.65 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.69 +pb_1c : 76.69 +pb_5c : 76.65 +pb_10c : 76.60 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.70 +pb_1c : 76.70 +pb_5c : 76.70 +pb_10c : 76.70 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.71 +pb_1c : 76.71 +pb_5c : 76.70 +pb_10c : 76.70 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.72 +pb_1c : 76.72 +pb_5c : 76.70 +pb_10c : 76.70 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.73 +pb_1c : 76.73 +pb_5c : 76.70 +pb_10c : 76.70 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.74 +pb_1c : 76.74 +pb_5c : 76.70 +pb_10c : 76.70 +pb_25c : 76.50 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.75 +pb_1c : 76.75 +pb_5c : 76.75 +pb_10c : 76.70 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.76 +pb_1c : 76.76 +pb_5c : 76.75 +pb_10c : 76.70 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.77 +pb_1c : 76.77 +pb_5c : 76.75 +pb_10c : 76.70 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.78 +pb_1c : 76.78 +pb_5c : 76.75 +pb_10c : 76.70 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.79 +pb_1c : 76.79 +pb_5c : 76.75 +pb_10c : 76.70 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.80 +pb_1c : 76.80 +pb_5c : 76.80 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.81 +pb_1c : 76.81 +pb_5c : 76.80 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.82 +pb_1c : 76.82 +pb_5c : 76.80 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.83 +pb_1c : 76.83 +pb_5c : 76.80 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.84 +pb_1c : 76.84 +pb_5c : 76.80 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.85 +pb_1c : 76.85 +pb_5c : 76.85 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.86 +pb_1c : 76.86 +pb_5c : 76.85 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.87 +pb_1c : 76.87 +pb_5c : 76.85 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.88 +pb_1c : 76.88 +pb_5c : 76.85 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.89 +pb_1c : 76.89 +pb_5c : 76.85 +pb_10c : 76.80 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.90 +pb_1c : 76.90 +pb_5c : 76.90 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.91 +pb_1c : 76.91 +pb_5c : 76.90 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.92 +pb_1c : 76.92 +pb_5c : 76.90 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.93 +pb_1c : 76.93 +pb_5c : 76.90 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.94 +pb_1c : 76.94 +pb_5c : 76.90 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.95 +pb_1c : 76.95 +pb_5c : 76.95 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.96 +pb_1c : 76.96 +pb_5c : 76.95 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.97 +pb_1c : 76.97 +pb_5c : 76.95 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.98 +pb_1c : 76.98 +pb_5c : 76.95 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +76.99 +pb_1c : 76.99 +pb_5c : 76.95 +pb_10c : 76.90 +pb_25c : 76.75 +pb_1d : 76.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.00 +pb_1c : 77.00 +pb_5c : 77.00 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.01 +pb_1c : 77.01 +pb_5c : 77.00 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.02 +pb_1c : 77.02 +pb_5c : 77.00 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.03 +pb_1c : 77.03 +pb_5c : 77.00 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.04 +pb_1c : 77.04 +pb_5c : 77.00 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.05 +pb_1c : 77.05 +pb_5c : 77.05 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.06 +pb_1c : 77.06 +pb_5c : 77.05 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.07 +pb_1c : 77.07 +pb_5c : 77.05 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.08 +pb_1c : 77.08 +pb_5c : 77.05 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.09 +pb_1c : 77.09 +pb_5c : 77.05 +pb_10c : 77.00 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.10 +pb_1c : 77.10 +pb_5c : 77.10 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.11 +pb_1c : 77.11 +pb_5c : 77.10 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.12 +pb_1c : 77.12 +pb_5c : 77.10 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.13 +pb_1c : 77.13 +pb_5c : 77.10 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.14 +pb_1c : 77.14 +pb_5c : 77.10 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.15 +pb_1c : 77.15 +pb_5c : 77.15 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.16 +pb_1c : 77.16 +pb_5c : 77.15 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.17 +pb_1c : 77.17 +pb_5c : 77.15 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.18 +pb_1c : 77.18 +pb_5c : 77.15 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.19 +pb_1c : 77.19 +pb_5c : 77.15 +pb_10c : 77.10 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.20 +pb_1c : 77.20 +pb_5c : 77.20 +pb_10c : 77.20 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.21 +pb_1c : 77.21 +pb_5c : 77.20 +pb_10c : 77.20 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.22 +pb_1c : 77.22 +pb_5c : 77.20 +pb_10c : 77.20 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.23 +pb_1c : 77.23 +pb_5c : 77.20 +pb_10c : 77.20 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.24 +pb_1c : 77.24 +pb_5c : 77.20 +pb_10c : 77.20 +pb_25c : 77.00 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.25 +pb_1c : 77.25 +pb_5c : 77.25 +pb_10c : 77.20 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.26 +pb_1c : 77.26 +pb_5c : 77.25 +pb_10c : 77.20 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.27 +pb_1c : 77.27 +pb_5c : 77.25 +pb_10c : 77.20 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.28 +pb_1c : 77.28 +pb_5c : 77.25 +pb_10c : 77.20 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.29 +pb_1c : 77.29 +pb_5c : 77.25 +pb_10c : 77.20 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.30 +pb_1c : 77.30 +pb_5c : 77.30 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.31 +pb_1c : 77.31 +pb_5c : 77.30 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.32 +pb_1c : 77.32 +pb_5c : 77.30 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.33 +pb_1c : 77.33 +pb_5c : 77.30 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.34 +pb_1c : 77.34 +pb_5c : 77.30 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.35 +pb_1c : 77.35 +pb_5c : 77.35 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.36 +pb_1c : 77.36 +pb_5c : 77.35 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.37 +pb_1c : 77.37 +pb_5c : 77.35 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.38 +pb_1c : 77.38 +pb_5c : 77.35 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.39 +pb_1c : 77.39 +pb_5c : 77.35 +pb_10c : 77.30 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.40 +pb_1c : 77.40 +pb_5c : 77.40 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.41 +pb_1c : 77.41 +pb_5c : 77.40 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.42 +pb_1c : 77.42 +pb_5c : 77.40 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.43 +pb_1c : 77.43 +pb_5c : 77.40 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.44 +pb_1c : 77.44 +pb_5c : 77.40 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.45 +pb_1c : 77.45 +pb_5c : 77.45 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.46 +pb_1c : 77.46 +pb_5c : 77.45 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.47 +pb_1c : 77.47 +pb_5c : 77.45 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.48 +pb_1c : 77.48 +pb_5c : 77.45 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.49 +pb_1c : 77.49 +pb_5c : 77.45 +pb_10c : 77.40 +pb_25c : 77.25 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.50 +pb_1c : 77.50 +pb_5c : 77.50 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.51 +pb_1c : 77.51 +pb_5c : 77.50 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.52 +pb_1c : 77.52 +pb_5c : 77.50 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.53 +pb_1c : 77.53 +pb_5c : 77.50 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.54 +pb_1c : 77.54 +pb_5c : 77.50 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.55 +pb_1c : 77.55 +pb_5c : 77.55 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.56 +pb_1c : 77.56 +pb_5c : 77.55 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.57 +pb_1c : 77.57 +pb_5c : 77.55 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.58 +pb_1c : 77.58 +pb_5c : 77.55 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.59 +pb_1c : 77.59 +pb_5c : 77.55 +pb_10c : 77.50 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.60 +pb_1c : 77.60 +pb_5c : 77.60 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.61 +pb_1c : 77.61 +pb_5c : 77.60 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.62 +pb_1c : 77.62 +pb_5c : 77.60 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.63 +pb_1c : 77.63 +pb_5c : 77.60 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.64 +pb_1c : 77.64 +pb_5c : 77.60 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.65 +pb_1c : 77.65 +pb_5c : 77.65 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.66 +pb_1c : 77.66 +pb_5c : 77.65 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.67 +pb_1c : 77.67 +pb_5c : 77.65 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.68 +pb_1c : 77.68 +pb_5c : 77.65 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.69 +pb_1c : 77.69 +pb_5c : 77.65 +pb_10c : 77.60 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.70 +pb_1c : 77.70 +pb_5c : 77.70 +pb_10c : 77.70 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.71 +pb_1c : 77.71 +pb_5c : 77.70 +pb_10c : 77.70 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.72 +pb_1c : 77.72 +pb_5c : 77.70 +pb_10c : 77.70 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.73 +pb_1c : 77.73 +pb_5c : 77.70 +pb_10c : 77.70 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.74 +pb_1c : 77.74 +pb_5c : 77.70 +pb_10c : 77.70 +pb_25c : 77.50 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.75 +pb_1c : 77.75 +pb_5c : 77.75 +pb_10c : 77.70 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.76 +pb_1c : 77.76 +pb_5c : 77.75 +pb_10c : 77.70 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.77 +pb_1c : 77.77 +pb_5c : 77.75 +pb_10c : 77.70 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.78 +pb_1c : 77.78 +pb_5c : 77.75 +pb_10c : 77.70 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.79 +pb_1c : 77.79 +pb_5c : 77.75 +pb_10c : 77.70 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.80 +pb_1c : 77.80 +pb_5c : 77.80 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.81 +pb_1c : 77.81 +pb_5c : 77.80 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.82 +pb_1c : 77.82 +pb_5c : 77.80 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.83 +pb_1c : 77.83 +pb_5c : 77.80 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.84 +pb_1c : 77.84 +pb_5c : 77.80 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.85 +pb_1c : 77.85 +pb_5c : 77.85 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.86 +pb_1c : 77.86 +pb_5c : 77.85 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.87 +pb_1c : 77.87 +pb_5c : 77.85 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.88 +pb_1c : 77.88 +pb_5c : 77.85 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.89 +pb_1c : 77.89 +pb_5c : 77.85 +pb_10c : 77.80 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.90 +pb_1c : 77.90 +pb_5c : 77.90 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.91 +pb_1c : 77.91 +pb_5c : 77.90 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.92 +pb_1c : 77.92 +pb_5c : 77.90 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.93 +pb_1c : 77.93 +pb_5c : 77.90 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.94 +pb_1c : 77.94 +pb_5c : 77.90 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.95 +pb_1c : 77.95 +pb_5c : 77.95 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.96 +pb_1c : 77.96 +pb_5c : 77.95 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.97 +pb_1c : 77.97 +pb_5c : 77.95 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.98 +pb_1c : 77.98 +pb_5c : 77.95 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +77.99 +pb_1c : 77.99 +pb_5c : 77.95 +pb_10c : 77.90 +pb_25c : 77.75 +pb_1d : 77.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.00 +pb_1c : 78.00 +pb_5c : 78.00 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.01 +pb_1c : 78.01 +pb_5c : 78.00 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.02 +pb_1c : 78.02 +pb_5c : 78.00 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.03 +pb_1c : 78.03 +pb_5c : 78.00 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.04 +pb_1c : 78.04 +pb_5c : 78.00 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.05 +pb_1c : 78.05 +pb_5c : 78.05 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.06 +pb_1c : 78.06 +pb_5c : 78.05 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.07 +pb_1c : 78.07 +pb_5c : 78.05 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.08 +pb_1c : 78.08 +pb_5c : 78.05 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.09 +pb_1c : 78.09 +pb_5c : 78.05 +pb_10c : 78.00 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.10 +pb_1c : 78.10 +pb_5c : 78.10 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.11 +pb_1c : 78.11 +pb_5c : 78.10 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.12 +pb_1c : 78.12 +pb_5c : 78.10 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.13 +pb_1c : 78.13 +pb_5c : 78.10 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.14 +pb_1c : 78.14 +pb_5c : 78.10 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.15 +pb_1c : 78.15 +pb_5c : 78.15 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.16 +pb_1c : 78.16 +pb_5c : 78.15 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.17 +pb_1c : 78.17 +pb_5c : 78.15 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.18 +pb_1c : 78.18 +pb_5c : 78.15 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.19 +pb_1c : 78.19 +pb_5c : 78.15 +pb_10c : 78.10 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.20 +pb_1c : 78.20 +pb_5c : 78.20 +pb_10c : 78.20 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.21 +pb_1c : 78.21 +pb_5c : 78.20 +pb_10c : 78.20 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.22 +pb_1c : 78.22 +pb_5c : 78.20 +pb_10c : 78.20 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.23 +pb_1c : 78.23 +pb_5c : 78.20 +pb_10c : 78.20 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.24 +pb_1c : 78.24 +pb_5c : 78.20 +pb_10c : 78.20 +pb_25c : 78.00 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.25 +pb_1c : 78.25 +pb_5c : 78.25 +pb_10c : 78.20 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.26 +pb_1c : 78.26 +pb_5c : 78.25 +pb_10c : 78.20 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.27 +pb_1c : 78.27 +pb_5c : 78.25 +pb_10c : 78.20 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.28 +pb_1c : 78.28 +pb_5c : 78.25 +pb_10c : 78.20 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.29 +pb_1c : 78.29 +pb_5c : 78.25 +pb_10c : 78.20 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.30 +pb_1c : 78.30 +pb_5c : 78.30 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.31 +pb_1c : 78.31 +pb_5c : 78.30 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.32 +pb_1c : 78.32 +pb_5c : 78.30 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.33 +pb_1c : 78.33 +pb_5c : 78.30 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.34 +pb_1c : 78.34 +pb_5c : 78.30 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.35 +pb_1c : 78.35 +pb_5c : 78.35 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.36 +pb_1c : 78.36 +pb_5c : 78.35 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.37 +pb_1c : 78.37 +pb_5c : 78.35 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.38 +pb_1c : 78.38 +pb_5c : 78.35 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.39 +pb_1c : 78.39 +pb_5c : 78.35 +pb_10c : 78.30 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.40 +pb_1c : 78.40 +pb_5c : 78.40 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.41 +pb_1c : 78.41 +pb_5c : 78.40 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.42 +pb_1c : 78.42 +pb_5c : 78.40 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.43 +pb_1c : 78.43 +pb_5c : 78.40 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.44 +pb_1c : 78.44 +pb_5c : 78.40 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.45 +pb_1c : 78.45 +pb_5c : 78.45 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.46 +pb_1c : 78.46 +pb_5c : 78.45 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.47 +pb_1c : 78.47 +pb_5c : 78.45 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.48 +pb_1c : 78.48 +pb_5c : 78.45 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.49 +pb_1c : 78.49 +pb_5c : 78.45 +pb_10c : 78.40 +pb_25c : 78.25 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.50 +pb_1c : 78.50 +pb_5c : 78.50 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.51 +pb_1c : 78.51 +pb_5c : 78.50 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.52 +pb_1c : 78.52 +pb_5c : 78.50 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.53 +pb_1c : 78.53 +pb_5c : 78.50 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.54 +pb_1c : 78.54 +pb_5c : 78.50 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.55 +pb_1c : 78.55 +pb_5c : 78.55 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.56 +pb_1c : 78.56 +pb_5c : 78.55 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.57 +pb_1c : 78.57 +pb_5c : 78.55 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.58 +pb_1c : 78.58 +pb_5c : 78.55 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.59 +pb_1c : 78.59 +pb_5c : 78.55 +pb_10c : 78.50 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.60 +pb_1c : 78.60 +pb_5c : 78.60 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.61 +pb_1c : 78.61 +pb_5c : 78.60 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.62 +pb_1c : 78.62 +pb_5c : 78.60 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.63 +pb_1c : 78.63 +pb_5c : 78.60 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.64 +pb_1c : 78.64 +pb_5c : 78.60 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.65 +pb_1c : 78.65 +pb_5c : 78.65 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.66 +pb_1c : 78.66 +pb_5c : 78.65 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.67 +pb_1c : 78.67 +pb_5c : 78.65 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.68 +pb_1c : 78.68 +pb_5c : 78.65 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.69 +pb_1c : 78.69 +pb_5c : 78.65 +pb_10c : 78.60 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.70 +pb_1c : 78.70 +pb_5c : 78.70 +pb_10c : 78.70 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.71 +pb_1c : 78.71 +pb_5c : 78.70 +pb_10c : 78.70 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.72 +pb_1c : 78.72 +pb_5c : 78.70 +pb_10c : 78.70 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.73 +pb_1c : 78.73 +pb_5c : 78.70 +pb_10c : 78.70 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.74 +pb_1c : 78.74 +pb_5c : 78.70 +pb_10c : 78.70 +pb_25c : 78.50 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.75 +pb_1c : 78.75 +pb_5c : 78.75 +pb_10c : 78.70 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.76 +pb_1c : 78.76 +pb_5c : 78.75 +pb_10c : 78.70 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.77 +pb_1c : 78.77 +pb_5c : 78.75 +pb_10c : 78.70 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.78 +pb_1c : 78.78 +pb_5c : 78.75 +pb_10c : 78.70 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.79 +pb_1c : 78.79 +pb_5c : 78.75 +pb_10c : 78.70 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.80 +pb_1c : 78.80 +pb_5c : 78.80 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.81 +pb_1c : 78.81 +pb_5c : 78.80 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.82 +pb_1c : 78.82 +pb_5c : 78.80 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.83 +pb_1c : 78.83 +pb_5c : 78.80 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.84 +pb_1c : 78.84 +pb_5c : 78.80 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.85 +pb_1c : 78.85 +pb_5c : 78.85 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.86 +pb_1c : 78.86 +pb_5c : 78.85 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.87 +pb_1c : 78.87 +pb_5c : 78.85 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.88 +pb_1c : 78.88 +pb_5c : 78.85 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.89 +pb_1c : 78.89 +pb_5c : 78.85 +pb_10c : 78.80 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.90 +pb_1c : 78.90 +pb_5c : 78.90 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.91 +pb_1c : 78.91 +pb_5c : 78.90 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.92 +pb_1c : 78.92 +pb_5c : 78.90 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.93 +pb_1c : 78.93 +pb_5c : 78.90 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.94 +pb_1c : 78.94 +pb_5c : 78.90 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.95 +pb_1c : 78.95 +pb_5c : 78.95 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.96 +pb_1c : 78.96 +pb_5c : 78.95 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.97 +pb_1c : 78.97 +pb_5c : 78.95 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.98 +pb_1c : 78.98 +pb_5c : 78.95 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +78.99 +pb_1c : 78.99 +pb_5c : 78.95 +pb_10c : 78.90 +pb_25c : 78.75 +pb_1d : 78.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.00 +pb_1c : 79.00 +pb_5c : 79.00 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.01 +pb_1c : 79.01 +pb_5c : 79.00 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.02 +pb_1c : 79.02 +pb_5c : 79.00 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.03 +pb_1c : 79.03 +pb_5c : 79.00 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.04 +pb_1c : 79.04 +pb_5c : 79.00 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.05 +pb_1c : 79.05 +pb_5c : 79.05 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.06 +pb_1c : 79.06 +pb_5c : 79.05 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.07 +pb_1c : 79.07 +pb_5c : 79.05 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.08 +pb_1c : 79.08 +pb_5c : 79.05 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.09 +pb_1c : 79.09 +pb_5c : 79.05 +pb_10c : 79.00 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.10 +pb_1c : 79.10 +pb_5c : 79.10 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.11 +pb_1c : 79.11 +pb_5c : 79.10 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.12 +pb_1c : 79.12 +pb_5c : 79.10 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.13 +pb_1c : 79.13 +pb_5c : 79.10 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.14 +pb_1c : 79.14 +pb_5c : 79.10 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.15 +pb_1c : 79.15 +pb_5c : 79.15 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.16 +pb_1c : 79.16 +pb_5c : 79.15 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.17 +pb_1c : 79.17 +pb_5c : 79.15 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.18 +pb_1c : 79.18 +pb_5c : 79.15 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.19 +pb_1c : 79.19 +pb_5c : 79.15 +pb_10c : 79.10 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.20 +pb_1c : 79.20 +pb_5c : 79.20 +pb_10c : 79.20 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.21 +pb_1c : 79.21 +pb_5c : 79.20 +pb_10c : 79.20 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.22 +pb_1c : 79.22 +pb_5c : 79.20 +pb_10c : 79.20 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.23 +pb_1c : 79.23 +pb_5c : 79.20 +pb_10c : 79.20 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.24 +pb_1c : 79.24 +pb_5c : 79.20 +pb_10c : 79.20 +pb_25c : 79.00 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.25 +pb_1c : 79.25 +pb_5c : 79.25 +pb_10c : 79.20 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.26 +pb_1c : 79.26 +pb_5c : 79.25 +pb_10c : 79.20 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.27 +pb_1c : 79.27 +pb_5c : 79.25 +pb_10c : 79.20 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.28 +pb_1c : 79.28 +pb_5c : 79.25 +pb_10c : 79.20 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.29 +pb_1c : 79.29 +pb_5c : 79.25 +pb_10c : 79.20 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.30 +pb_1c : 79.30 +pb_5c : 79.30 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.31 +pb_1c : 79.31 +pb_5c : 79.30 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.32 +pb_1c : 79.32 +pb_5c : 79.30 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.33 +pb_1c : 79.33 +pb_5c : 79.30 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.34 +pb_1c : 79.34 +pb_5c : 79.30 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.35 +pb_1c : 79.35 +pb_5c : 79.35 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.36 +pb_1c : 79.36 +pb_5c : 79.35 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.37 +pb_1c : 79.37 +pb_5c : 79.35 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.38 +pb_1c : 79.38 +pb_5c : 79.35 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.39 +pb_1c : 79.39 +pb_5c : 79.35 +pb_10c : 79.30 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.40 +pb_1c : 79.40 +pb_5c : 79.40 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.41 +pb_1c : 79.41 +pb_5c : 79.40 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.42 +pb_1c : 79.42 +pb_5c : 79.40 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.43 +pb_1c : 79.43 +pb_5c : 79.40 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.44 +pb_1c : 79.44 +pb_5c : 79.40 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.45 +pb_1c : 79.45 +pb_5c : 79.45 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.46 +pb_1c : 79.46 +pb_5c : 79.45 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.47 +pb_1c : 79.47 +pb_5c : 79.45 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.48 +pb_1c : 79.48 +pb_5c : 79.45 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.49 +pb_1c : 79.49 +pb_5c : 79.45 +pb_10c : 79.40 +pb_25c : 79.25 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.50 +pb_1c : 79.50 +pb_5c : 79.50 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.51 +pb_1c : 79.51 +pb_5c : 79.50 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.52 +pb_1c : 79.52 +pb_5c : 79.50 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.53 +pb_1c : 79.53 +pb_5c : 79.50 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.54 +pb_1c : 79.54 +pb_5c : 79.50 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.55 +pb_1c : 79.55 +pb_5c : 79.55 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.56 +pb_1c : 79.56 +pb_5c : 79.55 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.57 +pb_1c : 79.57 +pb_5c : 79.55 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.58 +pb_1c : 79.58 +pb_5c : 79.55 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.59 +pb_1c : 79.59 +pb_5c : 79.55 +pb_10c : 79.50 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.60 +pb_1c : 79.60 +pb_5c : 79.60 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.61 +pb_1c : 79.61 +pb_5c : 79.60 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.62 +pb_1c : 79.62 +pb_5c : 79.60 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.63 +pb_1c : 79.63 +pb_5c : 79.60 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.64 +pb_1c : 79.64 +pb_5c : 79.60 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.65 +pb_1c : 79.65 +pb_5c : 79.65 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.66 +pb_1c : 79.66 +pb_5c : 79.65 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.67 +pb_1c : 79.67 +pb_5c : 79.65 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.68 +pb_1c : 79.68 +pb_5c : 79.65 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.69 +pb_1c : 79.69 +pb_5c : 79.65 +pb_10c : 79.60 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.70 +pb_1c : 79.70 +pb_5c : 79.70 +pb_10c : 79.70 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.71 +pb_1c : 79.71 +pb_5c : 79.70 +pb_10c : 79.70 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.72 +pb_1c : 79.72 +pb_5c : 79.70 +pb_10c : 79.70 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.73 +pb_1c : 79.73 +pb_5c : 79.70 +pb_10c : 79.70 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.74 +pb_1c : 79.74 +pb_5c : 79.70 +pb_10c : 79.70 +pb_25c : 79.50 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.75 +pb_1c : 79.75 +pb_5c : 79.75 +pb_10c : 79.70 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.76 +pb_1c : 79.76 +pb_5c : 79.75 +pb_10c : 79.70 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.77 +pb_1c : 79.77 +pb_5c : 79.75 +pb_10c : 79.70 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.78 +pb_1c : 79.78 +pb_5c : 79.75 +pb_10c : 79.70 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.79 +pb_1c : 79.79 +pb_5c : 79.75 +pb_10c : 79.70 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.80 +pb_1c : 79.80 +pb_5c : 79.80 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.81 +pb_1c : 79.81 +pb_5c : 79.80 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.82 +pb_1c : 79.82 +pb_5c : 79.80 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.83 +pb_1c : 79.83 +pb_5c : 79.80 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.84 +pb_1c : 79.84 +pb_5c : 79.80 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.85 +pb_1c : 79.85 +pb_5c : 79.85 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.86 +pb_1c : 79.86 +pb_5c : 79.85 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.87 +pb_1c : 79.87 +pb_5c : 79.85 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.88 +pb_1c : 79.88 +pb_5c : 79.85 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.89 +pb_1c : 79.89 +pb_5c : 79.85 +pb_10c : 79.80 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.90 +pb_1c : 79.90 +pb_5c : 79.90 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.91 +pb_1c : 79.91 +pb_5c : 79.90 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.92 +pb_1c : 79.92 +pb_5c : 79.90 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.93 +pb_1c : 79.93 +pb_5c : 79.90 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.94 +pb_1c : 79.94 +pb_5c : 79.90 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.95 +pb_1c : 79.95 +pb_5c : 79.95 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.96 +pb_1c : 79.96 +pb_5c : 79.95 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.97 +pb_1c : 79.97 +pb_5c : 79.95 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.98 +pb_1c : 79.98 +pb_5c : 79.95 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +79.99 +pb_1c : 79.99 +pb_5c : 79.95 +pb_10c : 79.90 +pb_25c : 79.75 +pb_1d : 79.00 +pb_5d : 75.00 +pb_10d : 70.00 + +80.00 +pb_1c : 80.00 +pb_5c : 80.00 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.01 +pb_1c : 80.01 +pb_5c : 80.00 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.02 +pb_1c : 80.02 +pb_5c : 80.00 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.03 +pb_1c : 80.03 +pb_5c : 80.00 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.04 +pb_1c : 80.04 +pb_5c : 80.00 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.05 +pb_1c : 80.05 +pb_5c : 80.05 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.06 +pb_1c : 80.06 +pb_5c : 80.05 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.07 +pb_1c : 80.07 +pb_5c : 80.05 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.08 +pb_1c : 80.08 +pb_5c : 80.05 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.09 +pb_1c : 80.09 +pb_5c : 80.05 +pb_10c : 80.00 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.10 +pb_1c : 80.10 +pb_5c : 80.10 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.11 +pb_1c : 80.11 +pb_5c : 80.10 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.12 +pb_1c : 80.12 +pb_5c : 80.10 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.13 +pb_1c : 80.13 +pb_5c : 80.10 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.14 +pb_1c : 80.14 +pb_5c : 80.10 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.15 +pb_1c : 80.15 +pb_5c : 80.15 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.16 +pb_1c : 80.16 +pb_5c : 80.15 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.17 +pb_1c : 80.17 +pb_5c : 80.15 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.18 +pb_1c : 80.18 +pb_5c : 80.15 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.19 +pb_1c : 80.19 +pb_5c : 80.15 +pb_10c : 80.10 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.20 +pb_1c : 80.20 +pb_5c : 80.20 +pb_10c : 80.20 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.21 +pb_1c : 80.21 +pb_5c : 80.20 +pb_10c : 80.20 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.22 +pb_1c : 80.22 +pb_5c : 80.20 +pb_10c : 80.20 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.23 +pb_1c : 80.23 +pb_5c : 80.20 +pb_10c : 80.20 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.24 +pb_1c : 80.24 +pb_5c : 80.20 +pb_10c : 80.20 +pb_25c : 80.00 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.25 +pb_1c : 80.25 +pb_5c : 80.25 +pb_10c : 80.20 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.26 +pb_1c : 80.26 +pb_5c : 80.25 +pb_10c : 80.20 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.27 +pb_1c : 80.27 +pb_5c : 80.25 +pb_10c : 80.20 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.28 +pb_1c : 80.28 +pb_5c : 80.25 +pb_10c : 80.20 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.29 +pb_1c : 80.29 +pb_5c : 80.25 +pb_10c : 80.20 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.30 +pb_1c : 80.30 +pb_5c : 80.30 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.31 +pb_1c : 80.31 +pb_5c : 80.30 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.32 +pb_1c : 80.32 +pb_5c : 80.30 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.33 +pb_1c : 80.33 +pb_5c : 80.30 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.34 +pb_1c : 80.34 +pb_5c : 80.30 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.35 +pb_1c : 80.35 +pb_5c : 80.35 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.36 +pb_1c : 80.36 +pb_5c : 80.35 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.37 +pb_1c : 80.37 +pb_5c : 80.35 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.38 +pb_1c : 80.38 +pb_5c : 80.35 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.39 +pb_1c : 80.39 +pb_5c : 80.35 +pb_10c : 80.30 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.40 +pb_1c : 80.40 +pb_5c : 80.40 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.41 +pb_1c : 80.41 +pb_5c : 80.40 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.42 +pb_1c : 80.42 +pb_5c : 80.40 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.43 +pb_1c : 80.43 +pb_5c : 80.40 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.44 +pb_1c : 80.44 +pb_5c : 80.40 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.45 +pb_1c : 80.45 +pb_5c : 80.45 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.46 +pb_1c : 80.46 +pb_5c : 80.45 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.47 +pb_1c : 80.47 +pb_5c : 80.45 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.48 +pb_1c : 80.48 +pb_5c : 80.45 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.49 +pb_1c : 80.49 +pb_5c : 80.45 +pb_10c : 80.40 +pb_25c : 80.25 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.50 +pb_1c : 80.50 +pb_5c : 80.50 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.51 +pb_1c : 80.51 +pb_5c : 80.50 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.52 +pb_1c : 80.52 +pb_5c : 80.50 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.53 +pb_1c : 80.53 +pb_5c : 80.50 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.54 +pb_1c : 80.54 +pb_5c : 80.50 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.55 +pb_1c : 80.55 +pb_5c : 80.55 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.56 +pb_1c : 80.56 +pb_5c : 80.55 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.57 +pb_1c : 80.57 +pb_5c : 80.55 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.58 +pb_1c : 80.58 +pb_5c : 80.55 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.59 +pb_1c : 80.59 +pb_5c : 80.55 +pb_10c : 80.50 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.60 +pb_1c : 80.60 +pb_5c : 80.60 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.61 +pb_1c : 80.61 +pb_5c : 80.60 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.62 +pb_1c : 80.62 +pb_5c : 80.60 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.63 +pb_1c : 80.63 +pb_5c : 80.60 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.64 +pb_1c : 80.64 +pb_5c : 80.60 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.65 +pb_1c : 80.65 +pb_5c : 80.65 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.66 +pb_1c : 80.66 +pb_5c : 80.65 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.67 +pb_1c : 80.67 +pb_5c : 80.65 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.68 +pb_1c : 80.68 +pb_5c : 80.65 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.69 +pb_1c : 80.69 +pb_5c : 80.65 +pb_10c : 80.60 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.70 +pb_1c : 80.70 +pb_5c : 80.70 +pb_10c : 80.70 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.71 +pb_1c : 80.71 +pb_5c : 80.70 +pb_10c : 80.70 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.72 +pb_1c : 80.72 +pb_5c : 80.70 +pb_10c : 80.70 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.73 +pb_1c : 80.73 +pb_5c : 80.70 +pb_10c : 80.70 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.74 +pb_1c : 80.74 +pb_5c : 80.70 +pb_10c : 80.70 +pb_25c : 80.50 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.75 +pb_1c : 80.75 +pb_5c : 80.75 +pb_10c : 80.70 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.76 +pb_1c : 80.76 +pb_5c : 80.75 +pb_10c : 80.70 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.77 +pb_1c : 80.77 +pb_5c : 80.75 +pb_10c : 80.70 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.78 +pb_1c : 80.78 +pb_5c : 80.75 +pb_10c : 80.70 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.79 +pb_1c : 80.79 +pb_5c : 80.75 +pb_10c : 80.70 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.80 +pb_1c : 80.80 +pb_5c : 80.80 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.81 +pb_1c : 80.81 +pb_5c : 80.80 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.82 +pb_1c : 80.82 +pb_5c : 80.80 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.83 +pb_1c : 80.83 +pb_5c : 80.80 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.84 +pb_1c : 80.84 +pb_5c : 80.80 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.85 +pb_1c : 80.85 +pb_5c : 80.85 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.86 +pb_1c : 80.86 +pb_5c : 80.85 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.87 +pb_1c : 80.87 +pb_5c : 80.85 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.88 +pb_1c : 80.88 +pb_5c : 80.85 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.89 +pb_1c : 80.89 +pb_5c : 80.85 +pb_10c : 80.80 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.90 +pb_1c : 80.90 +pb_5c : 80.90 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.91 +pb_1c : 80.91 +pb_5c : 80.90 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.92 +pb_1c : 80.92 +pb_5c : 80.90 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.93 +pb_1c : 80.93 +pb_5c : 80.90 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.94 +pb_1c : 80.94 +pb_5c : 80.90 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.95 +pb_1c : 80.95 +pb_5c : 80.95 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.96 +pb_1c : 80.96 +pb_5c : 80.95 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.97 +pb_1c : 80.97 +pb_5c : 80.95 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.98 +pb_1c : 80.98 +pb_5c : 80.95 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +80.99 +pb_1c : 80.99 +pb_5c : 80.95 +pb_10c : 80.90 +pb_25c : 80.75 +pb_1d : 80.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.00 +pb_1c : 81.00 +pb_5c : 81.00 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.01 +pb_1c : 81.01 +pb_5c : 81.00 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.02 +pb_1c : 81.02 +pb_5c : 81.00 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.03 +pb_1c : 81.03 +pb_5c : 81.00 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.04 +pb_1c : 81.04 +pb_5c : 81.00 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.05 +pb_1c : 81.05 +pb_5c : 81.05 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.06 +pb_1c : 81.06 +pb_5c : 81.05 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.07 +pb_1c : 81.07 +pb_5c : 81.05 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.08 +pb_1c : 81.08 +pb_5c : 81.05 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.09 +pb_1c : 81.09 +pb_5c : 81.05 +pb_10c : 81.00 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.10 +pb_1c : 81.10 +pb_5c : 81.10 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.11 +pb_1c : 81.11 +pb_5c : 81.10 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.12 +pb_1c : 81.12 +pb_5c : 81.10 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.13 +pb_1c : 81.13 +pb_5c : 81.10 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.14 +pb_1c : 81.14 +pb_5c : 81.10 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.15 +pb_1c : 81.15 +pb_5c : 81.15 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.16 +pb_1c : 81.16 +pb_5c : 81.15 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.17 +pb_1c : 81.17 +pb_5c : 81.15 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.18 +pb_1c : 81.18 +pb_5c : 81.15 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.19 +pb_1c : 81.19 +pb_5c : 81.15 +pb_10c : 81.10 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.20 +pb_1c : 81.20 +pb_5c : 81.20 +pb_10c : 81.20 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.21 +pb_1c : 81.21 +pb_5c : 81.20 +pb_10c : 81.20 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.22 +pb_1c : 81.22 +pb_5c : 81.20 +pb_10c : 81.20 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.23 +pb_1c : 81.23 +pb_5c : 81.20 +pb_10c : 81.20 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.24 +pb_1c : 81.24 +pb_5c : 81.20 +pb_10c : 81.20 +pb_25c : 81.00 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.25 +pb_1c : 81.25 +pb_5c : 81.25 +pb_10c : 81.20 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.26 +pb_1c : 81.26 +pb_5c : 81.25 +pb_10c : 81.20 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.27 +pb_1c : 81.27 +pb_5c : 81.25 +pb_10c : 81.20 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.28 +pb_1c : 81.28 +pb_5c : 81.25 +pb_10c : 81.20 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.29 +pb_1c : 81.29 +pb_5c : 81.25 +pb_10c : 81.20 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.30 +pb_1c : 81.30 +pb_5c : 81.30 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.31 +pb_1c : 81.31 +pb_5c : 81.30 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.32 +pb_1c : 81.32 +pb_5c : 81.30 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.33 +pb_1c : 81.33 +pb_5c : 81.30 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.34 +pb_1c : 81.34 +pb_5c : 81.30 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.35 +pb_1c : 81.35 +pb_5c : 81.35 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.36 +pb_1c : 81.36 +pb_5c : 81.35 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.37 +pb_1c : 81.37 +pb_5c : 81.35 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.38 +pb_1c : 81.38 +pb_5c : 81.35 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.39 +pb_1c : 81.39 +pb_5c : 81.35 +pb_10c : 81.30 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.40 +pb_1c : 81.40 +pb_5c : 81.40 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.41 +pb_1c : 81.41 +pb_5c : 81.40 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.42 +pb_1c : 81.42 +pb_5c : 81.40 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.43 +pb_1c : 81.43 +pb_5c : 81.40 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.44 +pb_1c : 81.44 +pb_5c : 81.40 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.45 +pb_1c : 81.45 +pb_5c : 81.45 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.46 +pb_1c : 81.46 +pb_5c : 81.45 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.47 +pb_1c : 81.47 +pb_5c : 81.45 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.48 +pb_1c : 81.48 +pb_5c : 81.45 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.49 +pb_1c : 81.49 +pb_5c : 81.45 +pb_10c : 81.40 +pb_25c : 81.25 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.50 +pb_1c : 81.50 +pb_5c : 81.50 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.51 +pb_1c : 81.51 +pb_5c : 81.50 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.52 +pb_1c : 81.52 +pb_5c : 81.50 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.53 +pb_1c : 81.53 +pb_5c : 81.50 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.54 +pb_1c : 81.54 +pb_5c : 81.50 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.55 +pb_1c : 81.55 +pb_5c : 81.55 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.56 +pb_1c : 81.56 +pb_5c : 81.55 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.57 +pb_1c : 81.57 +pb_5c : 81.55 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.58 +pb_1c : 81.58 +pb_5c : 81.55 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.59 +pb_1c : 81.59 +pb_5c : 81.55 +pb_10c : 81.50 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.60 +pb_1c : 81.60 +pb_5c : 81.60 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.61 +pb_1c : 81.61 +pb_5c : 81.60 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.62 +pb_1c : 81.62 +pb_5c : 81.60 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.63 +pb_1c : 81.63 +pb_5c : 81.60 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.64 +pb_1c : 81.64 +pb_5c : 81.60 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.65 +pb_1c : 81.65 +pb_5c : 81.65 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.66 +pb_1c : 81.66 +pb_5c : 81.65 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.67 +pb_1c : 81.67 +pb_5c : 81.65 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.68 +pb_1c : 81.68 +pb_5c : 81.65 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.69 +pb_1c : 81.69 +pb_5c : 81.65 +pb_10c : 81.60 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.70 +pb_1c : 81.70 +pb_5c : 81.70 +pb_10c : 81.70 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.71 +pb_1c : 81.71 +pb_5c : 81.70 +pb_10c : 81.70 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.72 +pb_1c : 81.72 +pb_5c : 81.70 +pb_10c : 81.70 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.73 +pb_1c : 81.73 +pb_5c : 81.70 +pb_10c : 81.70 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.74 +pb_1c : 81.74 +pb_5c : 81.70 +pb_10c : 81.70 +pb_25c : 81.50 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.75 +pb_1c : 81.75 +pb_5c : 81.75 +pb_10c : 81.70 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.76 +pb_1c : 81.76 +pb_5c : 81.75 +pb_10c : 81.70 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.77 +pb_1c : 81.77 +pb_5c : 81.75 +pb_10c : 81.70 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.78 +pb_1c : 81.78 +pb_5c : 81.75 +pb_10c : 81.70 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.79 +pb_1c : 81.79 +pb_5c : 81.75 +pb_10c : 81.70 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.80 +pb_1c : 81.80 +pb_5c : 81.80 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.81 +pb_1c : 81.81 +pb_5c : 81.80 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.82 +pb_1c : 81.82 +pb_5c : 81.80 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.83 +pb_1c : 81.83 +pb_5c : 81.80 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.84 +pb_1c : 81.84 +pb_5c : 81.80 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.85 +pb_1c : 81.85 +pb_5c : 81.85 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.86 +pb_1c : 81.86 +pb_5c : 81.85 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.87 +pb_1c : 81.87 +pb_5c : 81.85 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.88 +pb_1c : 81.88 +pb_5c : 81.85 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.89 +pb_1c : 81.89 +pb_5c : 81.85 +pb_10c : 81.80 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.90 +pb_1c : 81.90 +pb_5c : 81.90 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.91 +pb_1c : 81.91 +pb_5c : 81.90 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.92 +pb_1c : 81.92 +pb_5c : 81.90 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.93 +pb_1c : 81.93 +pb_5c : 81.90 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.94 +pb_1c : 81.94 +pb_5c : 81.90 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.95 +pb_1c : 81.95 +pb_5c : 81.95 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.96 +pb_1c : 81.96 +pb_5c : 81.95 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.97 +pb_1c : 81.97 +pb_5c : 81.95 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.98 +pb_1c : 81.98 +pb_5c : 81.95 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +81.99 +pb_1c : 81.99 +pb_5c : 81.95 +pb_10c : 81.90 +pb_25c : 81.75 +pb_1d : 81.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.00 +pb_1c : 82.00 +pb_5c : 82.00 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.01 +pb_1c : 82.01 +pb_5c : 82.00 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.02 +pb_1c : 82.02 +pb_5c : 82.00 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.03 +pb_1c : 82.03 +pb_5c : 82.00 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.04 +pb_1c : 82.04 +pb_5c : 82.00 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.05 +pb_1c : 82.05 +pb_5c : 82.05 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.06 +pb_1c : 82.06 +pb_5c : 82.05 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.07 +pb_1c : 82.07 +pb_5c : 82.05 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.08 +pb_1c : 82.08 +pb_5c : 82.05 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.09 +pb_1c : 82.09 +pb_5c : 82.05 +pb_10c : 82.00 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.10 +pb_1c : 82.10 +pb_5c : 82.10 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.11 +pb_1c : 82.11 +pb_5c : 82.10 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.12 +pb_1c : 82.12 +pb_5c : 82.10 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.13 +pb_1c : 82.13 +pb_5c : 82.10 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.14 +pb_1c : 82.14 +pb_5c : 82.10 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.15 +pb_1c : 82.15 +pb_5c : 82.15 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.16 +pb_1c : 82.16 +pb_5c : 82.15 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.17 +pb_1c : 82.17 +pb_5c : 82.15 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.18 +pb_1c : 82.18 +pb_5c : 82.15 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.19 +pb_1c : 82.19 +pb_5c : 82.15 +pb_10c : 82.10 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.20 +pb_1c : 82.20 +pb_5c : 82.20 +pb_10c : 82.20 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.21 +pb_1c : 82.21 +pb_5c : 82.20 +pb_10c : 82.20 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.22 +pb_1c : 82.22 +pb_5c : 82.20 +pb_10c : 82.20 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.23 +pb_1c : 82.23 +pb_5c : 82.20 +pb_10c : 82.20 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.24 +pb_1c : 82.24 +pb_5c : 82.20 +pb_10c : 82.20 +pb_25c : 82.00 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.25 +pb_1c : 82.25 +pb_5c : 82.25 +pb_10c : 82.20 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.26 +pb_1c : 82.26 +pb_5c : 82.25 +pb_10c : 82.20 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.27 +pb_1c : 82.27 +pb_5c : 82.25 +pb_10c : 82.20 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.28 +pb_1c : 82.28 +pb_5c : 82.25 +pb_10c : 82.20 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.29 +pb_1c : 82.29 +pb_5c : 82.25 +pb_10c : 82.20 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.30 +pb_1c : 82.30 +pb_5c : 82.30 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.31 +pb_1c : 82.31 +pb_5c : 82.30 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.32 +pb_1c : 82.32 +pb_5c : 82.30 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.33 +pb_1c : 82.33 +pb_5c : 82.30 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.34 +pb_1c : 82.34 +pb_5c : 82.30 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.35 +pb_1c : 82.35 +pb_5c : 82.35 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.36 +pb_1c : 82.36 +pb_5c : 82.35 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.37 +pb_1c : 82.37 +pb_5c : 82.35 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.38 +pb_1c : 82.38 +pb_5c : 82.35 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.39 +pb_1c : 82.39 +pb_5c : 82.35 +pb_10c : 82.30 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.40 +pb_1c : 82.40 +pb_5c : 82.40 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.41 +pb_1c : 82.41 +pb_5c : 82.40 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.42 +pb_1c : 82.42 +pb_5c : 82.40 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.43 +pb_1c : 82.43 +pb_5c : 82.40 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.44 +pb_1c : 82.44 +pb_5c : 82.40 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.45 +pb_1c : 82.45 +pb_5c : 82.45 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.46 +pb_1c : 82.46 +pb_5c : 82.45 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.47 +pb_1c : 82.47 +pb_5c : 82.45 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.48 +pb_1c : 82.48 +pb_5c : 82.45 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.49 +pb_1c : 82.49 +pb_5c : 82.45 +pb_10c : 82.40 +pb_25c : 82.25 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.50 +pb_1c : 82.50 +pb_5c : 82.50 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.51 +pb_1c : 82.51 +pb_5c : 82.50 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.52 +pb_1c : 82.52 +pb_5c : 82.50 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.53 +pb_1c : 82.53 +pb_5c : 82.50 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.54 +pb_1c : 82.54 +pb_5c : 82.50 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.55 +pb_1c : 82.55 +pb_5c : 82.55 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.56 +pb_1c : 82.56 +pb_5c : 82.55 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.57 +pb_1c : 82.57 +pb_5c : 82.55 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.58 +pb_1c : 82.58 +pb_5c : 82.55 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.59 +pb_1c : 82.59 +pb_5c : 82.55 +pb_10c : 82.50 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.60 +pb_1c : 82.60 +pb_5c : 82.60 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.61 +pb_1c : 82.61 +pb_5c : 82.60 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.62 +pb_1c : 82.62 +pb_5c : 82.60 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.63 +pb_1c : 82.63 +pb_5c : 82.60 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.64 +pb_1c : 82.64 +pb_5c : 82.60 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.65 +pb_1c : 82.65 +pb_5c : 82.65 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.66 +pb_1c : 82.66 +pb_5c : 82.65 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.67 +pb_1c : 82.67 +pb_5c : 82.65 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.68 +pb_1c : 82.68 +pb_5c : 82.65 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.69 +pb_1c : 82.69 +pb_5c : 82.65 +pb_10c : 82.60 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.70 +pb_1c : 82.70 +pb_5c : 82.70 +pb_10c : 82.70 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.71 +pb_1c : 82.71 +pb_5c : 82.70 +pb_10c : 82.70 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.72 +pb_1c : 82.72 +pb_5c : 82.70 +pb_10c : 82.70 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.73 +pb_1c : 82.73 +pb_5c : 82.70 +pb_10c : 82.70 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.74 +pb_1c : 82.74 +pb_5c : 82.70 +pb_10c : 82.70 +pb_25c : 82.50 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.75 +pb_1c : 82.75 +pb_5c : 82.75 +pb_10c : 82.70 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.76 +pb_1c : 82.76 +pb_5c : 82.75 +pb_10c : 82.70 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.77 +pb_1c : 82.77 +pb_5c : 82.75 +pb_10c : 82.70 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.78 +pb_1c : 82.78 +pb_5c : 82.75 +pb_10c : 82.70 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.79 +pb_1c : 82.79 +pb_5c : 82.75 +pb_10c : 82.70 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.80 +pb_1c : 82.80 +pb_5c : 82.80 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.81 +pb_1c : 82.81 +pb_5c : 82.80 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.82 +pb_1c : 82.82 +pb_5c : 82.80 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.83 +pb_1c : 82.83 +pb_5c : 82.80 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.84 +pb_1c : 82.84 +pb_5c : 82.80 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.85 +pb_1c : 82.85 +pb_5c : 82.85 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.86 +pb_1c : 82.86 +pb_5c : 82.85 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.87 +pb_1c : 82.87 +pb_5c : 82.85 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.88 +pb_1c : 82.88 +pb_5c : 82.85 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.89 +pb_1c : 82.89 +pb_5c : 82.85 +pb_10c : 82.80 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.90 +pb_1c : 82.90 +pb_5c : 82.90 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.91 +pb_1c : 82.91 +pb_5c : 82.90 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.92 +pb_1c : 82.92 +pb_5c : 82.90 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.93 +pb_1c : 82.93 +pb_5c : 82.90 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.94 +pb_1c : 82.94 +pb_5c : 82.90 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.95 +pb_1c : 82.95 +pb_5c : 82.95 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.96 +pb_1c : 82.96 +pb_5c : 82.95 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.97 +pb_1c : 82.97 +pb_5c : 82.95 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.98 +pb_1c : 82.98 +pb_5c : 82.95 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +82.99 +pb_1c : 82.99 +pb_5c : 82.95 +pb_10c : 82.90 +pb_25c : 82.75 +pb_1d : 82.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.00 +pb_1c : 83.00 +pb_5c : 83.00 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.01 +pb_1c : 83.01 +pb_5c : 83.00 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.02 +pb_1c : 83.02 +pb_5c : 83.00 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.03 +pb_1c : 83.03 +pb_5c : 83.00 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.04 +pb_1c : 83.04 +pb_5c : 83.00 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.05 +pb_1c : 83.05 +pb_5c : 83.05 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.06 +pb_1c : 83.06 +pb_5c : 83.05 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.07 +pb_1c : 83.07 +pb_5c : 83.05 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.08 +pb_1c : 83.08 +pb_5c : 83.05 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.09 +pb_1c : 83.09 +pb_5c : 83.05 +pb_10c : 83.00 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.10 +pb_1c : 83.10 +pb_5c : 83.10 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.11 +pb_1c : 83.11 +pb_5c : 83.10 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.12 +pb_1c : 83.12 +pb_5c : 83.10 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.13 +pb_1c : 83.13 +pb_5c : 83.10 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.14 +pb_1c : 83.14 +pb_5c : 83.10 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.15 +pb_1c : 83.15 +pb_5c : 83.15 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.16 +pb_1c : 83.16 +pb_5c : 83.15 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.17 +pb_1c : 83.17 +pb_5c : 83.15 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.18 +pb_1c : 83.18 +pb_5c : 83.15 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.19 +pb_1c : 83.19 +pb_5c : 83.15 +pb_10c : 83.10 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.20 +pb_1c : 83.20 +pb_5c : 83.20 +pb_10c : 83.20 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.21 +pb_1c : 83.21 +pb_5c : 83.20 +pb_10c : 83.20 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.22 +pb_1c : 83.22 +pb_5c : 83.20 +pb_10c : 83.20 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.23 +pb_1c : 83.23 +pb_5c : 83.20 +pb_10c : 83.20 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.24 +pb_1c : 83.24 +pb_5c : 83.20 +pb_10c : 83.20 +pb_25c : 83.00 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.25 +pb_1c : 83.25 +pb_5c : 83.25 +pb_10c : 83.20 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.26 +pb_1c : 83.26 +pb_5c : 83.25 +pb_10c : 83.20 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.27 +pb_1c : 83.27 +pb_5c : 83.25 +pb_10c : 83.20 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.28 +pb_1c : 83.28 +pb_5c : 83.25 +pb_10c : 83.20 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.29 +pb_1c : 83.29 +pb_5c : 83.25 +pb_10c : 83.20 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.30 +pb_1c : 83.30 +pb_5c : 83.30 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.31 +pb_1c : 83.31 +pb_5c : 83.30 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.32 +pb_1c : 83.32 +pb_5c : 83.30 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.33 +pb_1c : 83.33 +pb_5c : 83.30 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.34 +pb_1c : 83.34 +pb_5c : 83.30 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.35 +pb_1c : 83.35 +pb_5c : 83.35 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.36 +pb_1c : 83.36 +pb_5c : 83.35 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.37 +pb_1c : 83.37 +pb_5c : 83.35 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.38 +pb_1c : 83.38 +pb_5c : 83.35 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.39 +pb_1c : 83.39 +pb_5c : 83.35 +pb_10c : 83.30 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.40 +pb_1c : 83.40 +pb_5c : 83.40 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.41 +pb_1c : 83.41 +pb_5c : 83.40 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.42 +pb_1c : 83.42 +pb_5c : 83.40 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.43 +pb_1c : 83.43 +pb_5c : 83.40 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.44 +pb_1c : 83.44 +pb_5c : 83.40 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.45 +pb_1c : 83.45 +pb_5c : 83.45 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.46 +pb_1c : 83.46 +pb_5c : 83.45 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.47 +pb_1c : 83.47 +pb_5c : 83.45 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.48 +pb_1c : 83.48 +pb_5c : 83.45 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.49 +pb_1c : 83.49 +pb_5c : 83.45 +pb_10c : 83.40 +pb_25c : 83.25 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.50 +pb_1c : 83.50 +pb_5c : 83.50 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.51 +pb_1c : 83.51 +pb_5c : 83.50 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.52 +pb_1c : 83.52 +pb_5c : 83.50 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.53 +pb_1c : 83.53 +pb_5c : 83.50 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.54 +pb_1c : 83.54 +pb_5c : 83.50 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.55 +pb_1c : 83.55 +pb_5c : 83.55 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.56 +pb_1c : 83.56 +pb_5c : 83.55 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.57 +pb_1c : 83.57 +pb_5c : 83.55 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.58 +pb_1c : 83.58 +pb_5c : 83.55 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.59 +pb_1c : 83.59 +pb_5c : 83.55 +pb_10c : 83.50 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.60 +pb_1c : 83.60 +pb_5c : 83.60 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.61 +pb_1c : 83.61 +pb_5c : 83.60 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.62 +pb_1c : 83.62 +pb_5c : 83.60 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.63 +pb_1c : 83.63 +pb_5c : 83.60 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.64 +pb_1c : 83.64 +pb_5c : 83.60 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.65 +pb_1c : 83.65 +pb_5c : 83.65 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.66 +pb_1c : 83.66 +pb_5c : 83.65 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.67 +pb_1c : 83.67 +pb_5c : 83.65 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.68 +pb_1c : 83.68 +pb_5c : 83.65 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.69 +pb_1c : 83.69 +pb_5c : 83.65 +pb_10c : 83.60 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.70 +pb_1c : 83.70 +pb_5c : 83.70 +pb_10c : 83.70 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.71 +pb_1c : 83.71 +pb_5c : 83.70 +pb_10c : 83.70 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.72 +pb_1c : 83.72 +pb_5c : 83.70 +pb_10c : 83.70 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.73 +pb_1c : 83.73 +pb_5c : 83.70 +pb_10c : 83.70 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.74 +pb_1c : 83.74 +pb_5c : 83.70 +pb_10c : 83.70 +pb_25c : 83.50 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.75 +pb_1c : 83.75 +pb_5c : 83.75 +pb_10c : 83.70 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.76 +pb_1c : 83.76 +pb_5c : 83.75 +pb_10c : 83.70 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.77 +pb_1c : 83.77 +pb_5c : 83.75 +pb_10c : 83.70 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.78 +pb_1c : 83.78 +pb_5c : 83.75 +pb_10c : 83.70 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.79 +pb_1c : 83.79 +pb_5c : 83.75 +pb_10c : 83.70 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.80 +pb_1c : 83.80 +pb_5c : 83.80 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.81 +pb_1c : 83.81 +pb_5c : 83.80 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.82 +pb_1c : 83.82 +pb_5c : 83.80 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.83 +pb_1c : 83.83 +pb_5c : 83.80 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.84 +pb_1c : 83.84 +pb_5c : 83.80 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.85 +pb_1c : 83.85 +pb_5c : 83.85 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.86 +pb_1c : 83.86 +pb_5c : 83.85 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.87 +pb_1c : 83.87 +pb_5c : 83.85 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.88 +pb_1c : 83.88 +pb_5c : 83.85 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.89 +pb_1c : 83.89 +pb_5c : 83.85 +pb_10c : 83.80 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.90 +pb_1c : 83.90 +pb_5c : 83.90 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.91 +pb_1c : 83.91 +pb_5c : 83.90 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.92 +pb_1c : 83.92 +pb_5c : 83.90 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.93 +pb_1c : 83.93 +pb_5c : 83.90 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.94 +pb_1c : 83.94 +pb_5c : 83.90 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.95 +pb_1c : 83.95 +pb_5c : 83.95 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.96 +pb_1c : 83.96 +pb_5c : 83.95 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.97 +pb_1c : 83.97 +pb_5c : 83.95 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.98 +pb_1c : 83.98 +pb_5c : 83.95 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +83.99 +pb_1c : 83.99 +pb_5c : 83.95 +pb_10c : 83.90 +pb_25c : 83.75 +pb_1d : 83.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.00 +pb_1c : 84.00 +pb_5c : 84.00 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.01 +pb_1c : 84.01 +pb_5c : 84.00 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.02 +pb_1c : 84.02 +pb_5c : 84.00 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.03 +pb_1c : 84.03 +pb_5c : 84.00 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.04 +pb_1c : 84.04 +pb_5c : 84.00 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.05 +pb_1c : 84.05 +pb_5c : 84.05 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.06 +pb_1c : 84.06 +pb_5c : 84.05 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.07 +pb_1c : 84.07 +pb_5c : 84.05 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.08 +pb_1c : 84.08 +pb_5c : 84.05 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.09 +pb_1c : 84.09 +pb_5c : 84.05 +pb_10c : 84.00 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.10 +pb_1c : 84.10 +pb_5c : 84.10 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.11 +pb_1c : 84.11 +pb_5c : 84.10 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.12 +pb_1c : 84.12 +pb_5c : 84.10 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.13 +pb_1c : 84.13 +pb_5c : 84.10 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.14 +pb_1c : 84.14 +pb_5c : 84.10 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.15 +pb_1c : 84.15 +pb_5c : 84.15 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.16 +pb_1c : 84.16 +pb_5c : 84.15 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.17 +pb_1c : 84.17 +pb_5c : 84.15 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.18 +pb_1c : 84.18 +pb_5c : 84.15 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.19 +pb_1c : 84.19 +pb_5c : 84.15 +pb_10c : 84.10 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.20 +pb_1c : 84.20 +pb_5c : 84.20 +pb_10c : 84.20 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.21 +pb_1c : 84.21 +pb_5c : 84.20 +pb_10c : 84.20 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.22 +pb_1c : 84.22 +pb_5c : 84.20 +pb_10c : 84.20 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.23 +pb_1c : 84.23 +pb_5c : 84.20 +pb_10c : 84.20 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.24 +pb_1c : 84.24 +pb_5c : 84.20 +pb_10c : 84.20 +pb_25c : 84.00 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.25 +pb_1c : 84.25 +pb_5c : 84.25 +pb_10c : 84.20 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.26 +pb_1c : 84.26 +pb_5c : 84.25 +pb_10c : 84.20 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.27 +pb_1c : 84.27 +pb_5c : 84.25 +pb_10c : 84.20 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.28 +pb_1c : 84.28 +pb_5c : 84.25 +pb_10c : 84.20 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.29 +pb_1c : 84.29 +pb_5c : 84.25 +pb_10c : 84.20 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.30 +pb_1c : 84.30 +pb_5c : 84.30 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.31 +pb_1c : 84.31 +pb_5c : 84.30 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.32 +pb_1c : 84.32 +pb_5c : 84.30 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.33 +pb_1c : 84.33 +pb_5c : 84.30 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.34 +pb_1c : 84.34 +pb_5c : 84.30 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.35 +pb_1c : 84.35 +pb_5c : 84.35 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.36 +pb_1c : 84.36 +pb_5c : 84.35 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.37 +pb_1c : 84.37 +pb_5c : 84.35 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.38 +pb_1c : 84.38 +pb_5c : 84.35 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.39 +pb_1c : 84.39 +pb_5c : 84.35 +pb_10c : 84.30 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.40 +pb_1c : 84.40 +pb_5c : 84.40 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.41 +pb_1c : 84.41 +pb_5c : 84.40 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.42 +pb_1c : 84.42 +pb_5c : 84.40 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.43 +pb_1c : 84.43 +pb_5c : 84.40 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.44 +pb_1c : 84.44 +pb_5c : 84.40 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.45 +pb_1c : 84.45 +pb_5c : 84.45 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.46 +pb_1c : 84.46 +pb_5c : 84.45 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.47 +pb_1c : 84.47 +pb_5c : 84.45 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.48 +pb_1c : 84.48 +pb_5c : 84.45 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.49 +pb_1c : 84.49 +pb_5c : 84.45 +pb_10c : 84.40 +pb_25c : 84.25 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.50 +pb_1c : 84.50 +pb_5c : 84.50 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.51 +pb_1c : 84.51 +pb_5c : 84.50 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.52 +pb_1c : 84.52 +pb_5c : 84.50 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.53 +pb_1c : 84.53 +pb_5c : 84.50 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.54 +pb_1c : 84.54 +pb_5c : 84.50 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.55 +pb_1c : 84.55 +pb_5c : 84.55 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.56 +pb_1c : 84.56 +pb_5c : 84.55 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.57 +pb_1c : 84.57 +pb_5c : 84.55 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.58 +pb_1c : 84.58 +pb_5c : 84.55 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.59 +pb_1c : 84.59 +pb_5c : 84.55 +pb_10c : 84.50 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.60 +pb_1c : 84.60 +pb_5c : 84.60 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.61 +pb_1c : 84.61 +pb_5c : 84.60 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.62 +pb_1c : 84.62 +pb_5c : 84.60 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.63 +pb_1c : 84.63 +pb_5c : 84.60 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.64 +pb_1c : 84.64 +pb_5c : 84.60 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.65 +pb_1c : 84.65 +pb_5c : 84.65 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.66 +pb_1c : 84.66 +pb_5c : 84.65 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.67 +pb_1c : 84.67 +pb_5c : 84.65 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.68 +pb_1c : 84.68 +pb_5c : 84.65 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.69 +pb_1c : 84.69 +pb_5c : 84.65 +pb_10c : 84.60 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.70 +pb_1c : 84.70 +pb_5c : 84.70 +pb_10c : 84.70 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.71 +pb_1c : 84.71 +pb_5c : 84.70 +pb_10c : 84.70 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.72 +pb_1c : 84.72 +pb_5c : 84.70 +pb_10c : 84.70 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.73 +pb_1c : 84.73 +pb_5c : 84.70 +pb_10c : 84.70 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.74 +pb_1c : 84.74 +pb_5c : 84.70 +pb_10c : 84.70 +pb_25c : 84.50 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.75 +pb_1c : 84.75 +pb_5c : 84.75 +pb_10c : 84.70 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.76 +pb_1c : 84.76 +pb_5c : 84.75 +pb_10c : 84.70 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.77 +pb_1c : 84.77 +pb_5c : 84.75 +pb_10c : 84.70 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.78 +pb_1c : 84.78 +pb_5c : 84.75 +pb_10c : 84.70 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.79 +pb_1c : 84.79 +pb_5c : 84.75 +pb_10c : 84.70 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.80 +pb_1c : 84.80 +pb_5c : 84.80 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.81 +pb_1c : 84.81 +pb_5c : 84.80 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.82 +pb_1c : 84.82 +pb_5c : 84.80 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.83 +pb_1c : 84.83 +pb_5c : 84.80 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.84 +pb_1c : 84.84 +pb_5c : 84.80 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.85 +pb_1c : 84.85 +pb_5c : 84.85 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.86 +pb_1c : 84.86 +pb_5c : 84.85 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.87 +pb_1c : 84.87 +pb_5c : 84.85 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.88 +pb_1c : 84.88 +pb_5c : 84.85 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.89 +pb_1c : 84.89 +pb_5c : 84.85 +pb_10c : 84.80 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.90 +pb_1c : 84.90 +pb_5c : 84.90 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.91 +pb_1c : 84.91 +pb_5c : 84.90 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.92 +pb_1c : 84.92 +pb_5c : 84.90 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.93 +pb_1c : 84.93 +pb_5c : 84.90 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.94 +pb_1c : 84.94 +pb_5c : 84.90 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.95 +pb_1c : 84.95 +pb_5c : 84.95 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.96 +pb_1c : 84.96 +pb_5c : 84.95 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.97 +pb_1c : 84.97 +pb_5c : 84.95 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.98 +pb_1c : 84.98 +pb_5c : 84.95 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +84.99 +pb_1c : 84.99 +pb_5c : 84.95 +pb_10c : 84.90 +pb_25c : 84.75 +pb_1d : 84.00 +pb_5d : 80.00 +pb_10d : 80.00 + +85.00 +pb_1c : 85.00 +pb_5c : 85.00 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.01 +pb_1c : 85.01 +pb_5c : 85.00 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.02 +pb_1c : 85.02 +pb_5c : 85.00 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.03 +pb_1c : 85.03 +pb_5c : 85.00 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.04 +pb_1c : 85.04 +pb_5c : 85.00 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.05 +pb_1c : 85.05 +pb_5c : 85.05 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.06 +pb_1c : 85.06 +pb_5c : 85.05 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.07 +pb_1c : 85.07 +pb_5c : 85.05 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.08 +pb_1c : 85.08 +pb_5c : 85.05 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.09 +pb_1c : 85.09 +pb_5c : 85.05 +pb_10c : 85.00 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.10 +pb_1c : 85.10 +pb_5c : 85.10 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.11 +pb_1c : 85.11 +pb_5c : 85.10 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.12 +pb_1c : 85.12 +pb_5c : 85.10 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.13 +pb_1c : 85.13 +pb_5c : 85.10 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.14 +pb_1c : 85.14 +pb_5c : 85.10 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.15 +pb_1c : 85.15 +pb_5c : 85.15 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.16 +pb_1c : 85.16 +pb_5c : 85.15 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.17 +pb_1c : 85.17 +pb_5c : 85.15 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.18 +pb_1c : 85.18 +pb_5c : 85.15 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.19 +pb_1c : 85.19 +pb_5c : 85.15 +pb_10c : 85.10 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.20 +pb_1c : 85.20 +pb_5c : 85.20 +pb_10c : 85.20 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.21 +pb_1c : 85.21 +pb_5c : 85.20 +pb_10c : 85.20 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.22 +pb_1c : 85.22 +pb_5c : 85.20 +pb_10c : 85.20 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.23 +pb_1c : 85.23 +pb_5c : 85.20 +pb_10c : 85.20 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.24 +pb_1c : 85.24 +pb_5c : 85.20 +pb_10c : 85.20 +pb_25c : 85.00 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.25 +pb_1c : 85.25 +pb_5c : 85.25 +pb_10c : 85.20 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.26 +pb_1c : 85.26 +pb_5c : 85.25 +pb_10c : 85.20 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.27 +pb_1c : 85.27 +pb_5c : 85.25 +pb_10c : 85.20 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.28 +pb_1c : 85.28 +pb_5c : 85.25 +pb_10c : 85.20 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.29 +pb_1c : 85.29 +pb_5c : 85.25 +pb_10c : 85.20 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.30 +pb_1c : 85.30 +pb_5c : 85.30 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.31 +pb_1c : 85.31 +pb_5c : 85.30 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.32 +pb_1c : 85.32 +pb_5c : 85.30 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.33 +pb_1c : 85.33 +pb_5c : 85.30 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.34 +pb_1c : 85.34 +pb_5c : 85.30 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.35 +pb_1c : 85.35 +pb_5c : 85.35 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.36 +pb_1c : 85.36 +pb_5c : 85.35 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.37 +pb_1c : 85.37 +pb_5c : 85.35 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.38 +pb_1c : 85.38 +pb_5c : 85.35 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.39 +pb_1c : 85.39 +pb_5c : 85.35 +pb_10c : 85.30 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.40 +pb_1c : 85.40 +pb_5c : 85.40 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.41 +pb_1c : 85.41 +pb_5c : 85.40 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.42 +pb_1c : 85.42 +pb_5c : 85.40 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.43 +pb_1c : 85.43 +pb_5c : 85.40 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.44 +pb_1c : 85.44 +pb_5c : 85.40 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.45 +pb_1c : 85.45 +pb_5c : 85.45 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.46 +pb_1c : 85.46 +pb_5c : 85.45 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.47 +pb_1c : 85.47 +pb_5c : 85.45 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.48 +pb_1c : 85.48 +pb_5c : 85.45 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.49 +pb_1c : 85.49 +pb_5c : 85.45 +pb_10c : 85.40 +pb_25c : 85.25 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.50 +pb_1c : 85.50 +pb_5c : 85.50 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.51 +pb_1c : 85.51 +pb_5c : 85.50 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.52 +pb_1c : 85.52 +pb_5c : 85.50 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.53 +pb_1c : 85.53 +pb_5c : 85.50 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.54 +pb_1c : 85.54 +pb_5c : 85.50 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.55 +pb_1c : 85.55 +pb_5c : 85.55 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.56 +pb_1c : 85.56 +pb_5c : 85.55 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.57 +pb_1c : 85.57 +pb_5c : 85.55 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.58 +pb_1c : 85.58 +pb_5c : 85.55 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.59 +pb_1c : 85.59 +pb_5c : 85.55 +pb_10c : 85.50 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.60 +pb_1c : 85.60 +pb_5c : 85.60 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.61 +pb_1c : 85.61 +pb_5c : 85.60 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.62 +pb_1c : 85.62 +pb_5c : 85.60 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.63 +pb_1c : 85.63 +pb_5c : 85.60 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.64 +pb_1c : 85.64 +pb_5c : 85.60 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.65 +pb_1c : 85.65 +pb_5c : 85.65 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.66 +pb_1c : 85.66 +pb_5c : 85.65 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.67 +pb_1c : 85.67 +pb_5c : 85.65 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.68 +pb_1c : 85.68 +pb_5c : 85.65 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.69 +pb_1c : 85.69 +pb_5c : 85.65 +pb_10c : 85.60 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.70 +pb_1c : 85.70 +pb_5c : 85.70 +pb_10c : 85.70 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.71 +pb_1c : 85.71 +pb_5c : 85.70 +pb_10c : 85.70 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.72 +pb_1c : 85.72 +pb_5c : 85.70 +pb_10c : 85.70 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.73 +pb_1c : 85.73 +pb_5c : 85.70 +pb_10c : 85.70 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.74 +pb_1c : 85.74 +pb_5c : 85.70 +pb_10c : 85.70 +pb_25c : 85.50 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.75 +pb_1c : 85.75 +pb_5c : 85.75 +pb_10c : 85.70 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.76 +pb_1c : 85.76 +pb_5c : 85.75 +pb_10c : 85.70 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.77 +pb_1c : 85.77 +pb_5c : 85.75 +pb_10c : 85.70 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.78 +pb_1c : 85.78 +pb_5c : 85.75 +pb_10c : 85.70 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.79 +pb_1c : 85.79 +pb_5c : 85.75 +pb_10c : 85.70 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.80 +pb_1c : 85.80 +pb_5c : 85.80 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.81 +pb_1c : 85.81 +pb_5c : 85.80 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.82 +pb_1c : 85.82 +pb_5c : 85.80 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.83 +pb_1c : 85.83 +pb_5c : 85.80 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.84 +pb_1c : 85.84 +pb_5c : 85.80 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.85 +pb_1c : 85.85 +pb_5c : 85.85 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.86 +pb_1c : 85.86 +pb_5c : 85.85 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.87 +pb_1c : 85.87 +pb_5c : 85.85 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.88 +pb_1c : 85.88 +pb_5c : 85.85 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.89 +pb_1c : 85.89 +pb_5c : 85.85 +pb_10c : 85.80 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.90 +pb_1c : 85.90 +pb_5c : 85.90 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.91 +pb_1c : 85.91 +pb_5c : 85.90 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.92 +pb_1c : 85.92 +pb_5c : 85.90 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.93 +pb_1c : 85.93 +pb_5c : 85.90 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.94 +pb_1c : 85.94 +pb_5c : 85.90 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.95 +pb_1c : 85.95 +pb_5c : 85.95 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.96 +pb_1c : 85.96 +pb_5c : 85.95 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.97 +pb_1c : 85.97 +pb_5c : 85.95 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.98 +pb_1c : 85.98 +pb_5c : 85.95 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +85.99 +pb_1c : 85.99 +pb_5c : 85.95 +pb_10c : 85.90 +pb_25c : 85.75 +pb_1d : 85.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.00 +pb_1c : 86.00 +pb_5c : 86.00 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.01 +pb_1c : 86.01 +pb_5c : 86.00 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.02 +pb_1c : 86.02 +pb_5c : 86.00 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.03 +pb_1c : 86.03 +pb_5c : 86.00 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.04 +pb_1c : 86.04 +pb_5c : 86.00 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.05 +pb_1c : 86.05 +pb_5c : 86.05 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.06 +pb_1c : 86.06 +pb_5c : 86.05 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.07 +pb_1c : 86.07 +pb_5c : 86.05 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.08 +pb_1c : 86.08 +pb_5c : 86.05 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.09 +pb_1c : 86.09 +pb_5c : 86.05 +pb_10c : 86.00 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.10 +pb_1c : 86.10 +pb_5c : 86.10 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.11 +pb_1c : 86.11 +pb_5c : 86.10 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.12 +pb_1c : 86.12 +pb_5c : 86.10 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.13 +pb_1c : 86.13 +pb_5c : 86.10 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.14 +pb_1c : 86.14 +pb_5c : 86.10 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.15 +pb_1c : 86.15 +pb_5c : 86.15 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.16 +pb_1c : 86.16 +pb_5c : 86.15 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.17 +pb_1c : 86.17 +pb_5c : 86.15 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.18 +pb_1c : 86.18 +pb_5c : 86.15 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.19 +pb_1c : 86.19 +pb_5c : 86.15 +pb_10c : 86.10 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.20 +pb_1c : 86.20 +pb_5c : 86.20 +pb_10c : 86.20 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.21 +pb_1c : 86.21 +pb_5c : 86.20 +pb_10c : 86.20 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.22 +pb_1c : 86.22 +pb_5c : 86.20 +pb_10c : 86.20 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.23 +pb_1c : 86.23 +pb_5c : 86.20 +pb_10c : 86.20 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.24 +pb_1c : 86.24 +pb_5c : 86.20 +pb_10c : 86.20 +pb_25c : 86.00 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.25 +pb_1c : 86.25 +pb_5c : 86.25 +pb_10c : 86.20 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.26 +pb_1c : 86.26 +pb_5c : 86.25 +pb_10c : 86.20 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.27 +pb_1c : 86.27 +pb_5c : 86.25 +pb_10c : 86.20 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.28 +pb_1c : 86.28 +pb_5c : 86.25 +pb_10c : 86.20 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.29 +pb_1c : 86.29 +pb_5c : 86.25 +pb_10c : 86.20 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.30 +pb_1c : 86.30 +pb_5c : 86.30 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.31 +pb_1c : 86.31 +pb_5c : 86.30 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.32 +pb_1c : 86.32 +pb_5c : 86.30 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.33 +pb_1c : 86.33 +pb_5c : 86.30 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.34 +pb_1c : 86.34 +pb_5c : 86.30 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.35 +pb_1c : 86.35 +pb_5c : 86.35 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.36 +pb_1c : 86.36 +pb_5c : 86.35 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.37 +pb_1c : 86.37 +pb_5c : 86.35 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.38 +pb_1c : 86.38 +pb_5c : 86.35 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.39 +pb_1c : 86.39 +pb_5c : 86.35 +pb_10c : 86.30 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.40 +pb_1c : 86.40 +pb_5c : 86.40 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.41 +pb_1c : 86.41 +pb_5c : 86.40 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.42 +pb_1c : 86.42 +pb_5c : 86.40 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.43 +pb_1c : 86.43 +pb_5c : 86.40 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.44 +pb_1c : 86.44 +pb_5c : 86.40 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.45 +pb_1c : 86.45 +pb_5c : 86.45 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.46 +pb_1c : 86.46 +pb_5c : 86.45 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.47 +pb_1c : 86.47 +pb_5c : 86.45 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.48 +pb_1c : 86.48 +pb_5c : 86.45 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.49 +pb_1c : 86.49 +pb_5c : 86.45 +pb_10c : 86.40 +pb_25c : 86.25 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.50 +pb_1c : 86.50 +pb_5c : 86.50 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.51 +pb_1c : 86.51 +pb_5c : 86.50 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.52 +pb_1c : 86.52 +pb_5c : 86.50 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.53 +pb_1c : 86.53 +pb_5c : 86.50 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.54 +pb_1c : 86.54 +pb_5c : 86.50 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.55 +pb_1c : 86.55 +pb_5c : 86.55 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.56 +pb_1c : 86.56 +pb_5c : 86.55 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.57 +pb_1c : 86.57 +pb_5c : 86.55 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.58 +pb_1c : 86.58 +pb_5c : 86.55 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.59 +pb_1c : 86.59 +pb_5c : 86.55 +pb_10c : 86.50 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.60 +pb_1c : 86.60 +pb_5c : 86.60 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.61 +pb_1c : 86.61 +pb_5c : 86.60 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.62 +pb_1c : 86.62 +pb_5c : 86.60 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.63 +pb_1c : 86.63 +pb_5c : 86.60 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.64 +pb_1c : 86.64 +pb_5c : 86.60 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.65 +pb_1c : 86.65 +pb_5c : 86.65 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.66 +pb_1c : 86.66 +pb_5c : 86.65 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.67 +pb_1c : 86.67 +pb_5c : 86.65 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.68 +pb_1c : 86.68 +pb_5c : 86.65 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.69 +pb_1c : 86.69 +pb_5c : 86.65 +pb_10c : 86.60 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.70 +pb_1c : 86.70 +pb_5c : 86.70 +pb_10c : 86.70 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.71 +pb_1c : 86.71 +pb_5c : 86.70 +pb_10c : 86.70 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.72 +pb_1c : 86.72 +pb_5c : 86.70 +pb_10c : 86.70 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.73 +pb_1c : 86.73 +pb_5c : 86.70 +pb_10c : 86.70 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.74 +pb_1c : 86.74 +pb_5c : 86.70 +pb_10c : 86.70 +pb_25c : 86.50 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.75 +pb_1c : 86.75 +pb_5c : 86.75 +pb_10c : 86.70 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.76 +pb_1c : 86.76 +pb_5c : 86.75 +pb_10c : 86.70 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.77 +pb_1c : 86.77 +pb_5c : 86.75 +pb_10c : 86.70 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.78 +pb_1c : 86.78 +pb_5c : 86.75 +pb_10c : 86.70 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.79 +pb_1c : 86.79 +pb_5c : 86.75 +pb_10c : 86.70 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.80 +pb_1c : 86.80 +pb_5c : 86.80 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.81 +pb_1c : 86.81 +pb_5c : 86.80 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.82 +pb_1c : 86.82 +pb_5c : 86.80 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.83 +pb_1c : 86.83 +pb_5c : 86.80 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.84 +pb_1c : 86.84 +pb_5c : 86.80 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.85 +pb_1c : 86.85 +pb_5c : 86.85 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.86 +pb_1c : 86.86 +pb_5c : 86.85 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.87 +pb_1c : 86.87 +pb_5c : 86.85 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.88 +pb_1c : 86.88 +pb_5c : 86.85 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.89 +pb_1c : 86.89 +pb_5c : 86.85 +pb_10c : 86.80 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.90 +pb_1c : 86.90 +pb_5c : 86.90 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.91 +pb_1c : 86.91 +pb_5c : 86.90 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.92 +pb_1c : 86.92 +pb_5c : 86.90 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.93 +pb_1c : 86.93 +pb_5c : 86.90 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.94 +pb_1c : 86.94 +pb_5c : 86.90 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.95 +pb_1c : 86.95 +pb_5c : 86.95 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.96 +pb_1c : 86.96 +pb_5c : 86.95 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.97 +pb_1c : 86.97 +pb_5c : 86.95 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.98 +pb_1c : 86.98 +pb_5c : 86.95 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +86.99 +pb_1c : 86.99 +pb_5c : 86.95 +pb_10c : 86.90 +pb_25c : 86.75 +pb_1d : 86.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.00 +pb_1c : 87.00 +pb_5c : 87.00 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.01 +pb_1c : 87.01 +pb_5c : 87.00 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.02 +pb_1c : 87.02 +pb_5c : 87.00 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.03 +pb_1c : 87.03 +pb_5c : 87.00 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.04 +pb_1c : 87.04 +pb_5c : 87.00 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.05 +pb_1c : 87.05 +pb_5c : 87.05 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.06 +pb_1c : 87.06 +pb_5c : 87.05 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.07 +pb_1c : 87.07 +pb_5c : 87.05 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.08 +pb_1c : 87.08 +pb_5c : 87.05 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.09 +pb_1c : 87.09 +pb_5c : 87.05 +pb_10c : 87.00 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.10 +pb_1c : 87.10 +pb_5c : 87.10 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.11 +pb_1c : 87.11 +pb_5c : 87.10 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.12 +pb_1c : 87.12 +pb_5c : 87.10 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.13 +pb_1c : 87.13 +pb_5c : 87.10 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.14 +pb_1c : 87.14 +pb_5c : 87.10 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.15 +pb_1c : 87.15 +pb_5c : 87.15 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.16 +pb_1c : 87.16 +pb_5c : 87.15 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.17 +pb_1c : 87.17 +pb_5c : 87.15 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.18 +pb_1c : 87.18 +pb_5c : 87.15 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.19 +pb_1c : 87.19 +pb_5c : 87.15 +pb_10c : 87.10 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.20 +pb_1c : 87.20 +pb_5c : 87.20 +pb_10c : 87.20 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.21 +pb_1c : 87.21 +pb_5c : 87.20 +pb_10c : 87.20 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.22 +pb_1c : 87.22 +pb_5c : 87.20 +pb_10c : 87.20 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.23 +pb_1c : 87.23 +pb_5c : 87.20 +pb_10c : 87.20 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.24 +pb_1c : 87.24 +pb_5c : 87.20 +pb_10c : 87.20 +pb_25c : 87.00 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.25 +pb_1c : 87.25 +pb_5c : 87.25 +pb_10c : 87.20 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.26 +pb_1c : 87.26 +pb_5c : 87.25 +pb_10c : 87.20 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.27 +pb_1c : 87.27 +pb_5c : 87.25 +pb_10c : 87.20 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.28 +pb_1c : 87.28 +pb_5c : 87.25 +pb_10c : 87.20 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.29 +pb_1c : 87.29 +pb_5c : 87.25 +pb_10c : 87.20 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.30 +pb_1c : 87.30 +pb_5c : 87.30 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.31 +pb_1c : 87.31 +pb_5c : 87.30 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.32 +pb_1c : 87.32 +pb_5c : 87.30 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.33 +pb_1c : 87.33 +pb_5c : 87.30 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.34 +pb_1c : 87.34 +pb_5c : 87.30 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.35 +pb_1c : 87.35 +pb_5c : 87.35 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.36 +pb_1c : 87.36 +pb_5c : 87.35 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.37 +pb_1c : 87.37 +pb_5c : 87.35 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.38 +pb_1c : 87.38 +pb_5c : 87.35 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.39 +pb_1c : 87.39 +pb_5c : 87.35 +pb_10c : 87.30 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.40 +pb_1c : 87.40 +pb_5c : 87.40 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.41 +pb_1c : 87.41 +pb_5c : 87.40 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.42 +pb_1c : 87.42 +pb_5c : 87.40 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.43 +pb_1c : 87.43 +pb_5c : 87.40 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.44 +pb_1c : 87.44 +pb_5c : 87.40 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.45 +pb_1c : 87.45 +pb_5c : 87.45 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.46 +pb_1c : 87.46 +pb_5c : 87.45 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.47 +pb_1c : 87.47 +pb_5c : 87.45 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.48 +pb_1c : 87.48 +pb_5c : 87.45 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.49 +pb_1c : 87.49 +pb_5c : 87.45 +pb_10c : 87.40 +pb_25c : 87.25 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.50 +pb_1c : 87.50 +pb_5c : 87.50 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.51 +pb_1c : 87.51 +pb_5c : 87.50 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.52 +pb_1c : 87.52 +pb_5c : 87.50 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.53 +pb_1c : 87.53 +pb_5c : 87.50 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.54 +pb_1c : 87.54 +pb_5c : 87.50 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.55 +pb_1c : 87.55 +pb_5c : 87.55 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.56 +pb_1c : 87.56 +pb_5c : 87.55 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.57 +pb_1c : 87.57 +pb_5c : 87.55 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.58 +pb_1c : 87.58 +pb_5c : 87.55 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.59 +pb_1c : 87.59 +pb_5c : 87.55 +pb_10c : 87.50 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.60 +pb_1c : 87.60 +pb_5c : 87.60 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.61 +pb_1c : 87.61 +pb_5c : 87.60 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.62 +pb_1c : 87.62 +pb_5c : 87.60 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.63 +pb_1c : 87.63 +pb_5c : 87.60 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.64 +pb_1c : 87.64 +pb_5c : 87.60 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.65 +pb_1c : 87.65 +pb_5c : 87.65 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.66 +pb_1c : 87.66 +pb_5c : 87.65 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.67 +pb_1c : 87.67 +pb_5c : 87.65 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.68 +pb_1c : 87.68 +pb_5c : 87.65 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.69 +pb_1c : 87.69 +pb_5c : 87.65 +pb_10c : 87.60 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.70 +pb_1c : 87.70 +pb_5c : 87.70 +pb_10c : 87.70 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.71 +pb_1c : 87.71 +pb_5c : 87.70 +pb_10c : 87.70 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.72 +pb_1c : 87.72 +pb_5c : 87.70 +pb_10c : 87.70 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.73 +pb_1c : 87.73 +pb_5c : 87.70 +pb_10c : 87.70 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.74 +pb_1c : 87.74 +pb_5c : 87.70 +pb_10c : 87.70 +pb_25c : 87.50 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.75 +pb_1c : 87.75 +pb_5c : 87.75 +pb_10c : 87.70 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.76 +pb_1c : 87.76 +pb_5c : 87.75 +pb_10c : 87.70 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.77 +pb_1c : 87.77 +pb_5c : 87.75 +pb_10c : 87.70 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.78 +pb_1c : 87.78 +pb_5c : 87.75 +pb_10c : 87.70 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.79 +pb_1c : 87.79 +pb_5c : 87.75 +pb_10c : 87.70 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.80 +pb_1c : 87.80 +pb_5c : 87.80 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.81 +pb_1c : 87.81 +pb_5c : 87.80 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.82 +pb_1c : 87.82 +pb_5c : 87.80 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.83 +pb_1c : 87.83 +pb_5c : 87.80 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.84 +pb_1c : 87.84 +pb_5c : 87.80 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.85 +pb_1c : 87.85 +pb_5c : 87.85 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.86 +pb_1c : 87.86 +pb_5c : 87.85 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.87 +pb_1c : 87.87 +pb_5c : 87.85 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.88 +pb_1c : 87.88 +pb_5c : 87.85 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.89 +pb_1c : 87.89 +pb_5c : 87.85 +pb_10c : 87.80 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.90 +pb_1c : 87.90 +pb_5c : 87.90 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.91 +pb_1c : 87.91 +pb_5c : 87.90 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.92 +pb_1c : 87.92 +pb_5c : 87.90 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.93 +pb_1c : 87.93 +pb_5c : 87.90 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.94 +pb_1c : 87.94 +pb_5c : 87.90 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.95 +pb_1c : 87.95 +pb_5c : 87.95 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.96 +pb_1c : 87.96 +pb_5c : 87.95 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.97 +pb_1c : 87.97 +pb_5c : 87.95 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.98 +pb_1c : 87.98 +pb_5c : 87.95 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +87.99 +pb_1c : 87.99 +pb_5c : 87.95 +pb_10c : 87.90 +pb_25c : 87.75 +pb_1d : 87.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.00 +pb_1c : 88.00 +pb_5c : 88.00 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.01 +pb_1c : 88.01 +pb_5c : 88.00 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.02 +pb_1c : 88.02 +pb_5c : 88.00 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.03 +pb_1c : 88.03 +pb_5c : 88.00 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.04 +pb_1c : 88.04 +pb_5c : 88.00 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.05 +pb_1c : 88.05 +pb_5c : 88.05 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.06 +pb_1c : 88.06 +pb_5c : 88.05 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.07 +pb_1c : 88.07 +pb_5c : 88.05 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.08 +pb_1c : 88.08 +pb_5c : 88.05 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.09 +pb_1c : 88.09 +pb_5c : 88.05 +pb_10c : 88.00 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.10 +pb_1c : 88.10 +pb_5c : 88.10 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.11 +pb_1c : 88.11 +pb_5c : 88.10 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.12 +pb_1c : 88.12 +pb_5c : 88.10 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.13 +pb_1c : 88.13 +pb_5c : 88.10 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.14 +pb_1c : 88.14 +pb_5c : 88.10 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.15 +pb_1c : 88.15 +pb_5c : 88.15 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.16 +pb_1c : 88.16 +pb_5c : 88.15 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.17 +pb_1c : 88.17 +pb_5c : 88.15 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.18 +pb_1c : 88.18 +pb_5c : 88.15 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.19 +pb_1c : 88.19 +pb_5c : 88.15 +pb_10c : 88.10 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.20 +pb_1c : 88.20 +pb_5c : 88.20 +pb_10c : 88.20 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.21 +pb_1c : 88.21 +pb_5c : 88.20 +pb_10c : 88.20 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.22 +pb_1c : 88.22 +pb_5c : 88.20 +pb_10c : 88.20 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.23 +pb_1c : 88.23 +pb_5c : 88.20 +pb_10c : 88.20 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.24 +pb_1c : 88.24 +pb_5c : 88.20 +pb_10c : 88.20 +pb_25c : 88.00 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.25 +pb_1c : 88.25 +pb_5c : 88.25 +pb_10c : 88.20 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.26 +pb_1c : 88.26 +pb_5c : 88.25 +pb_10c : 88.20 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.27 +pb_1c : 88.27 +pb_5c : 88.25 +pb_10c : 88.20 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.28 +pb_1c : 88.28 +pb_5c : 88.25 +pb_10c : 88.20 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.29 +pb_1c : 88.29 +pb_5c : 88.25 +pb_10c : 88.20 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.30 +pb_1c : 88.30 +pb_5c : 88.30 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.31 +pb_1c : 88.31 +pb_5c : 88.30 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.32 +pb_1c : 88.32 +pb_5c : 88.30 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.33 +pb_1c : 88.33 +pb_5c : 88.30 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.34 +pb_1c : 88.34 +pb_5c : 88.30 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.35 +pb_1c : 88.35 +pb_5c : 88.35 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.36 +pb_1c : 88.36 +pb_5c : 88.35 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.37 +pb_1c : 88.37 +pb_5c : 88.35 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.38 +pb_1c : 88.38 +pb_5c : 88.35 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.39 +pb_1c : 88.39 +pb_5c : 88.35 +pb_10c : 88.30 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.40 +pb_1c : 88.40 +pb_5c : 88.40 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.41 +pb_1c : 88.41 +pb_5c : 88.40 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.42 +pb_1c : 88.42 +pb_5c : 88.40 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.43 +pb_1c : 88.43 +pb_5c : 88.40 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.44 +pb_1c : 88.44 +pb_5c : 88.40 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.45 +pb_1c : 88.45 +pb_5c : 88.45 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.46 +pb_1c : 88.46 +pb_5c : 88.45 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.47 +pb_1c : 88.47 +pb_5c : 88.45 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.48 +pb_1c : 88.48 +pb_5c : 88.45 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.49 +pb_1c : 88.49 +pb_5c : 88.45 +pb_10c : 88.40 +pb_25c : 88.25 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.50 +pb_1c : 88.50 +pb_5c : 88.50 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.51 +pb_1c : 88.51 +pb_5c : 88.50 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.52 +pb_1c : 88.52 +pb_5c : 88.50 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.53 +pb_1c : 88.53 +pb_5c : 88.50 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.54 +pb_1c : 88.54 +pb_5c : 88.50 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.55 +pb_1c : 88.55 +pb_5c : 88.55 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.56 +pb_1c : 88.56 +pb_5c : 88.55 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.57 +pb_1c : 88.57 +pb_5c : 88.55 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.58 +pb_1c : 88.58 +pb_5c : 88.55 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.59 +pb_1c : 88.59 +pb_5c : 88.55 +pb_10c : 88.50 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.60 +pb_1c : 88.60 +pb_5c : 88.60 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.61 +pb_1c : 88.61 +pb_5c : 88.60 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.62 +pb_1c : 88.62 +pb_5c : 88.60 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.63 +pb_1c : 88.63 +pb_5c : 88.60 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.64 +pb_1c : 88.64 +pb_5c : 88.60 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.65 +pb_1c : 88.65 +pb_5c : 88.65 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.66 +pb_1c : 88.66 +pb_5c : 88.65 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.67 +pb_1c : 88.67 +pb_5c : 88.65 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.68 +pb_1c : 88.68 +pb_5c : 88.65 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.69 +pb_1c : 88.69 +pb_5c : 88.65 +pb_10c : 88.60 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.70 +pb_1c : 88.70 +pb_5c : 88.70 +pb_10c : 88.70 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.71 +pb_1c : 88.71 +pb_5c : 88.70 +pb_10c : 88.70 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.72 +pb_1c : 88.72 +pb_5c : 88.70 +pb_10c : 88.70 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.73 +pb_1c : 88.73 +pb_5c : 88.70 +pb_10c : 88.70 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.74 +pb_1c : 88.74 +pb_5c : 88.70 +pb_10c : 88.70 +pb_25c : 88.50 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.75 +pb_1c : 88.75 +pb_5c : 88.75 +pb_10c : 88.70 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.76 +pb_1c : 88.76 +pb_5c : 88.75 +pb_10c : 88.70 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.77 +pb_1c : 88.77 +pb_5c : 88.75 +pb_10c : 88.70 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.78 +pb_1c : 88.78 +pb_5c : 88.75 +pb_10c : 88.70 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.79 +pb_1c : 88.79 +pb_5c : 88.75 +pb_10c : 88.70 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.80 +pb_1c : 88.80 +pb_5c : 88.80 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.81 +pb_1c : 88.81 +pb_5c : 88.80 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.82 +pb_1c : 88.82 +pb_5c : 88.80 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.83 +pb_1c : 88.83 +pb_5c : 88.80 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.84 +pb_1c : 88.84 +pb_5c : 88.80 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.85 +pb_1c : 88.85 +pb_5c : 88.85 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.86 +pb_1c : 88.86 +pb_5c : 88.85 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.87 +pb_1c : 88.87 +pb_5c : 88.85 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.88 +pb_1c : 88.88 +pb_5c : 88.85 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.89 +pb_1c : 88.89 +pb_5c : 88.85 +pb_10c : 88.80 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.90 +pb_1c : 88.90 +pb_5c : 88.90 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.91 +pb_1c : 88.91 +pb_5c : 88.90 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.92 +pb_1c : 88.92 +pb_5c : 88.90 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.93 +pb_1c : 88.93 +pb_5c : 88.90 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.94 +pb_1c : 88.94 +pb_5c : 88.90 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.95 +pb_1c : 88.95 +pb_5c : 88.95 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.96 +pb_1c : 88.96 +pb_5c : 88.95 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.97 +pb_1c : 88.97 +pb_5c : 88.95 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.98 +pb_1c : 88.98 +pb_5c : 88.95 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +88.99 +pb_1c : 88.99 +pb_5c : 88.95 +pb_10c : 88.90 +pb_25c : 88.75 +pb_1d : 88.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.00 +pb_1c : 89.00 +pb_5c : 89.00 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.01 +pb_1c : 89.01 +pb_5c : 89.00 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.02 +pb_1c : 89.02 +pb_5c : 89.00 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.03 +pb_1c : 89.03 +pb_5c : 89.00 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.04 +pb_1c : 89.04 +pb_5c : 89.00 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.05 +pb_1c : 89.05 +pb_5c : 89.05 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.06 +pb_1c : 89.06 +pb_5c : 89.05 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.07 +pb_1c : 89.07 +pb_5c : 89.05 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.08 +pb_1c : 89.08 +pb_5c : 89.05 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.09 +pb_1c : 89.09 +pb_5c : 89.05 +pb_10c : 89.00 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.10 +pb_1c : 89.10 +pb_5c : 89.10 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.11 +pb_1c : 89.11 +pb_5c : 89.10 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.12 +pb_1c : 89.12 +pb_5c : 89.10 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.13 +pb_1c : 89.13 +pb_5c : 89.10 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.14 +pb_1c : 89.14 +pb_5c : 89.10 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.15 +pb_1c : 89.15 +pb_5c : 89.15 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.16 +pb_1c : 89.16 +pb_5c : 89.15 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.17 +pb_1c : 89.17 +pb_5c : 89.15 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.18 +pb_1c : 89.18 +pb_5c : 89.15 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.19 +pb_1c : 89.19 +pb_5c : 89.15 +pb_10c : 89.10 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.20 +pb_1c : 89.20 +pb_5c : 89.20 +pb_10c : 89.20 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.21 +pb_1c : 89.21 +pb_5c : 89.20 +pb_10c : 89.20 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.22 +pb_1c : 89.22 +pb_5c : 89.20 +pb_10c : 89.20 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.23 +pb_1c : 89.23 +pb_5c : 89.20 +pb_10c : 89.20 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.24 +pb_1c : 89.24 +pb_5c : 89.20 +pb_10c : 89.20 +pb_25c : 89.00 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.25 +pb_1c : 89.25 +pb_5c : 89.25 +pb_10c : 89.20 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.26 +pb_1c : 89.26 +pb_5c : 89.25 +pb_10c : 89.20 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.27 +pb_1c : 89.27 +pb_5c : 89.25 +pb_10c : 89.20 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.28 +pb_1c : 89.28 +pb_5c : 89.25 +pb_10c : 89.20 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.29 +pb_1c : 89.29 +pb_5c : 89.25 +pb_10c : 89.20 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.30 +pb_1c : 89.30 +pb_5c : 89.30 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.31 +pb_1c : 89.31 +pb_5c : 89.30 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.32 +pb_1c : 89.32 +pb_5c : 89.30 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.33 +pb_1c : 89.33 +pb_5c : 89.30 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.34 +pb_1c : 89.34 +pb_5c : 89.30 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.35 +pb_1c : 89.35 +pb_5c : 89.35 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.36 +pb_1c : 89.36 +pb_5c : 89.35 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.37 +pb_1c : 89.37 +pb_5c : 89.35 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.38 +pb_1c : 89.38 +pb_5c : 89.35 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.39 +pb_1c : 89.39 +pb_5c : 89.35 +pb_10c : 89.30 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.40 +pb_1c : 89.40 +pb_5c : 89.40 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.41 +pb_1c : 89.41 +pb_5c : 89.40 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.42 +pb_1c : 89.42 +pb_5c : 89.40 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.43 +pb_1c : 89.43 +pb_5c : 89.40 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.44 +pb_1c : 89.44 +pb_5c : 89.40 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.45 +pb_1c : 89.45 +pb_5c : 89.45 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.46 +pb_1c : 89.46 +pb_5c : 89.45 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.47 +pb_1c : 89.47 +pb_5c : 89.45 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.48 +pb_1c : 89.48 +pb_5c : 89.45 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.49 +pb_1c : 89.49 +pb_5c : 89.45 +pb_10c : 89.40 +pb_25c : 89.25 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.50 +pb_1c : 89.50 +pb_5c : 89.50 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.51 +pb_1c : 89.51 +pb_5c : 89.50 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.52 +pb_1c : 89.52 +pb_5c : 89.50 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.53 +pb_1c : 89.53 +pb_5c : 89.50 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.54 +pb_1c : 89.54 +pb_5c : 89.50 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.55 +pb_1c : 89.55 +pb_5c : 89.55 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.56 +pb_1c : 89.56 +pb_5c : 89.55 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.57 +pb_1c : 89.57 +pb_5c : 89.55 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.58 +pb_1c : 89.58 +pb_5c : 89.55 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.59 +pb_1c : 89.59 +pb_5c : 89.55 +pb_10c : 89.50 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.60 +pb_1c : 89.60 +pb_5c : 89.60 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.61 +pb_1c : 89.61 +pb_5c : 89.60 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.62 +pb_1c : 89.62 +pb_5c : 89.60 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.63 +pb_1c : 89.63 +pb_5c : 89.60 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.64 +pb_1c : 89.64 +pb_5c : 89.60 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.65 +pb_1c : 89.65 +pb_5c : 89.65 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.66 +pb_1c : 89.66 +pb_5c : 89.65 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.67 +pb_1c : 89.67 +pb_5c : 89.65 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.68 +pb_1c : 89.68 +pb_5c : 89.65 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.69 +pb_1c : 89.69 +pb_5c : 89.65 +pb_10c : 89.60 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.70 +pb_1c : 89.70 +pb_5c : 89.70 +pb_10c : 89.70 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.71 +pb_1c : 89.71 +pb_5c : 89.70 +pb_10c : 89.70 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.72 +pb_1c : 89.72 +pb_5c : 89.70 +pb_10c : 89.70 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.73 +pb_1c : 89.73 +pb_5c : 89.70 +pb_10c : 89.70 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.74 +pb_1c : 89.74 +pb_5c : 89.70 +pb_10c : 89.70 +pb_25c : 89.50 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.75 +pb_1c : 89.75 +pb_5c : 89.75 +pb_10c : 89.70 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.76 +pb_1c : 89.76 +pb_5c : 89.75 +pb_10c : 89.70 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.77 +pb_1c : 89.77 +pb_5c : 89.75 +pb_10c : 89.70 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.78 +pb_1c : 89.78 +pb_5c : 89.75 +pb_10c : 89.70 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.79 +pb_1c : 89.79 +pb_5c : 89.75 +pb_10c : 89.70 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.80 +pb_1c : 89.80 +pb_5c : 89.80 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.81 +pb_1c : 89.81 +pb_5c : 89.80 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.82 +pb_1c : 89.82 +pb_5c : 89.80 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.83 +pb_1c : 89.83 +pb_5c : 89.80 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.84 +pb_1c : 89.84 +pb_5c : 89.80 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.85 +pb_1c : 89.85 +pb_5c : 89.85 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.86 +pb_1c : 89.86 +pb_5c : 89.85 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.87 +pb_1c : 89.87 +pb_5c : 89.85 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.88 +pb_1c : 89.88 +pb_5c : 89.85 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.89 +pb_1c : 89.89 +pb_5c : 89.85 +pb_10c : 89.80 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.90 +pb_1c : 89.90 +pb_5c : 89.90 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.91 +pb_1c : 89.91 +pb_5c : 89.90 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.92 +pb_1c : 89.92 +pb_5c : 89.90 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.93 +pb_1c : 89.93 +pb_5c : 89.90 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.94 +pb_1c : 89.94 +pb_5c : 89.90 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.95 +pb_1c : 89.95 +pb_5c : 89.95 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.96 +pb_1c : 89.96 +pb_5c : 89.95 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.97 +pb_1c : 89.97 +pb_5c : 89.95 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.98 +pb_1c : 89.98 +pb_5c : 89.95 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +89.99 +pb_1c : 89.99 +pb_5c : 89.95 +pb_10c : 89.90 +pb_25c : 89.75 +pb_1d : 89.00 +pb_5d : 85.00 +pb_10d : 80.00 + +90.00 +pb_1c : 90.00 +pb_5c : 90.00 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.01 +pb_1c : 90.01 +pb_5c : 90.00 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.02 +pb_1c : 90.02 +pb_5c : 90.00 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.03 +pb_1c : 90.03 +pb_5c : 90.00 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.04 +pb_1c : 90.04 +pb_5c : 90.00 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.05 +pb_1c : 90.05 +pb_5c : 90.05 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.06 +pb_1c : 90.06 +pb_5c : 90.05 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.07 +pb_1c : 90.07 +pb_5c : 90.05 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.08 +pb_1c : 90.08 +pb_5c : 90.05 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.09 +pb_1c : 90.09 +pb_5c : 90.05 +pb_10c : 90.00 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.10 +pb_1c : 90.10 +pb_5c : 90.10 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.11 +pb_1c : 90.11 +pb_5c : 90.10 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.12 +pb_1c : 90.12 +pb_5c : 90.10 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.13 +pb_1c : 90.13 +pb_5c : 90.10 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.14 +pb_1c : 90.14 +pb_5c : 90.10 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.15 +pb_1c : 90.15 +pb_5c : 90.15 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.16 +pb_1c : 90.16 +pb_5c : 90.15 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.17 +pb_1c : 90.17 +pb_5c : 90.15 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.18 +pb_1c : 90.18 +pb_5c : 90.15 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.19 +pb_1c : 90.19 +pb_5c : 90.15 +pb_10c : 90.10 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.20 +pb_1c : 90.20 +pb_5c : 90.20 +pb_10c : 90.20 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.21 +pb_1c : 90.21 +pb_5c : 90.20 +pb_10c : 90.20 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.22 +pb_1c : 90.22 +pb_5c : 90.20 +pb_10c : 90.20 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.23 +pb_1c : 90.23 +pb_5c : 90.20 +pb_10c : 90.20 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.24 +pb_1c : 90.24 +pb_5c : 90.20 +pb_10c : 90.20 +pb_25c : 90.00 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.25 +pb_1c : 90.25 +pb_5c : 90.25 +pb_10c : 90.20 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.26 +pb_1c : 90.26 +pb_5c : 90.25 +pb_10c : 90.20 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.27 +pb_1c : 90.27 +pb_5c : 90.25 +pb_10c : 90.20 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.28 +pb_1c : 90.28 +pb_5c : 90.25 +pb_10c : 90.20 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.29 +pb_1c : 90.29 +pb_5c : 90.25 +pb_10c : 90.20 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.30 +pb_1c : 90.30 +pb_5c : 90.30 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.31 +pb_1c : 90.31 +pb_5c : 90.30 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.32 +pb_1c : 90.32 +pb_5c : 90.30 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.33 +pb_1c : 90.33 +pb_5c : 90.30 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.34 +pb_1c : 90.34 +pb_5c : 90.30 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.35 +pb_1c : 90.35 +pb_5c : 90.35 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.36 +pb_1c : 90.36 +pb_5c : 90.35 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.37 +pb_1c : 90.37 +pb_5c : 90.35 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.38 +pb_1c : 90.38 +pb_5c : 90.35 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.39 +pb_1c : 90.39 +pb_5c : 90.35 +pb_10c : 90.30 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.40 +pb_1c : 90.40 +pb_5c : 90.40 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.41 +pb_1c : 90.41 +pb_5c : 90.40 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.42 +pb_1c : 90.42 +pb_5c : 90.40 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.43 +pb_1c : 90.43 +pb_5c : 90.40 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.44 +pb_1c : 90.44 +pb_5c : 90.40 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.45 +pb_1c : 90.45 +pb_5c : 90.45 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.46 +pb_1c : 90.46 +pb_5c : 90.45 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.47 +pb_1c : 90.47 +pb_5c : 90.45 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.48 +pb_1c : 90.48 +pb_5c : 90.45 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.49 +pb_1c : 90.49 +pb_5c : 90.45 +pb_10c : 90.40 +pb_25c : 90.25 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.50 +pb_1c : 90.50 +pb_5c : 90.50 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.51 +pb_1c : 90.51 +pb_5c : 90.50 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.52 +pb_1c : 90.52 +pb_5c : 90.50 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.53 +pb_1c : 90.53 +pb_5c : 90.50 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.54 +pb_1c : 90.54 +pb_5c : 90.50 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.55 +pb_1c : 90.55 +pb_5c : 90.55 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.56 +pb_1c : 90.56 +pb_5c : 90.55 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.57 +pb_1c : 90.57 +pb_5c : 90.55 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.58 +pb_1c : 90.58 +pb_5c : 90.55 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.59 +pb_1c : 90.59 +pb_5c : 90.55 +pb_10c : 90.50 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.60 +pb_1c : 90.60 +pb_5c : 90.60 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.61 +pb_1c : 90.61 +pb_5c : 90.60 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.62 +pb_1c : 90.62 +pb_5c : 90.60 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.63 +pb_1c : 90.63 +pb_5c : 90.60 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.64 +pb_1c : 90.64 +pb_5c : 90.60 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.65 +pb_1c : 90.65 +pb_5c : 90.65 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.66 +pb_1c : 90.66 +pb_5c : 90.65 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.67 +pb_1c : 90.67 +pb_5c : 90.65 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.68 +pb_1c : 90.68 +pb_5c : 90.65 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.69 +pb_1c : 90.69 +pb_5c : 90.65 +pb_10c : 90.60 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.70 +pb_1c : 90.70 +pb_5c : 90.70 +pb_10c : 90.70 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.71 +pb_1c : 90.71 +pb_5c : 90.70 +pb_10c : 90.70 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.72 +pb_1c : 90.72 +pb_5c : 90.70 +pb_10c : 90.70 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.73 +pb_1c : 90.73 +pb_5c : 90.70 +pb_10c : 90.70 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.74 +pb_1c : 90.74 +pb_5c : 90.70 +pb_10c : 90.70 +pb_25c : 90.50 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.75 +pb_1c : 90.75 +pb_5c : 90.75 +pb_10c : 90.70 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.76 +pb_1c : 90.76 +pb_5c : 90.75 +pb_10c : 90.70 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.77 +pb_1c : 90.77 +pb_5c : 90.75 +pb_10c : 90.70 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.78 +pb_1c : 90.78 +pb_5c : 90.75 +pb_10c : 90.70 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.79 +pb_1c : 90.79 +pb_5c : 90.75 +pb_10c : 90.70 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.80 +pb_1c : 90.80 +pb_5c : 90.80 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.81 +pb_1c : 90.81 +pb_5c : 90.80 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.82 +pb_1c : 90.82 +pb_5c : 90.80 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.83 +pb_1c : 90.83 +pb_5c : 90.80 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.84 +pb_1c : 90.84 +pb_5c : 90.80 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.85 +pb_1c : 90.85 +pb_5c : 90.85 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.86 +pb_1c : 90.86 +pb_5c : 90.85 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.87 +pb_1c : 90.87 +pb_5c : 90.85 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.88 +pb_1c : 90.88 +pb_5c : 90.85 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.89 +pb_1c : 90.89 +pb_5c : 90.85 +pb_10c : 90.80 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.90 +pb_1c : 90.90 +pb_5c : 90.90 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.91 +pb_1c : 90.91 +pb_5c : 90.90 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.92 +pb_1c : 90.92 +pb_5c : 90.90 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.93 +pb_1c : 90.93 +pb_5c : 90.90 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.94 +pb_1c : 90.94 +pb_5c : 90.90 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.95 +pb_1c : 90.95 +pb_5c : 90.95 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.96 +pb_1c : 90.96 +pb_5c : 90.95 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.97 +pb_1c : 90.97 +pb_5c : 90.95 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.98 +pb_1c : 90.98 +pb_5c : 90.95 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +90.99 +pb_1c : 90.99 +pb_5c : 90.95 +pb_10c : 90.90 +pb_25c : 90.75 +pb_1d : 90.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.00 +pb_1c : 91.00 +pb_5c : 91.00 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.01 +pb_1c : 91.01 +pb_5c : 91.00 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.02 +pb_1c : 91.02 +pb_5c : 91.00 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.03 +pb_1c : 91.03 +pb_5c : 91.00 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.04 +pb_1c : 91.04 +pb_5c : 91.00 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.05 +pb_1c : 91.05 +pb_5c : 91.05 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.06 +pb_1c : 91.06 +pb_5c : 91.05 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.07 +pb_1c : 91.07 +pb_5c : 91.05 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.08 +pb_1c : 91.08 +pb_5c : 91.05 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.09 +pb_1c : 91.09 +pb_5c : 91.05 +pb_10c : 91.00 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.10 +pb_1c : 91.10 +pb_5c : 91.10 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.11 +pb_1c : 91.11 +pb_5c : 91.10 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.12 +pb_1c : 91.12 +pb_5c : 91.10 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.13 +pb_1c : 91.13 +pb_5c : 91.10 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.14 +pb_1c : 91.14 +pb_5c : 91.10 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.15 +pb_1c : 91.15 +pb_5c : 91.15 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.16 +pb_1c : 91.16 +pb_5c : 91.15 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.17 +pb_1c : 91.17 +pb_5c : 91.15 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.18 +pb_1c : 91.18 +pb_5c : 91.15 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.19 +pb_1c : 91.19 +pb_5c : 91.15 +pb_10c : 91.10 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.20 +pb_1c : 91.20 +pb_5c : 91.20 +pb_10c : 91.20 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.21 +pb_1c : 91.21 +pb_5c : 91.20 +pb_10c : 91.20 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.22 +pb_1c : 91.22 +pb_5c : 91.20 +pb_10c : 91.20 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.23 +pb_1c : 91.23 +pb_5c : 91.20 +pb_10c : 91.20 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.24 +pb_1c : 91.24 +pb_5c : 91.20 +pb_10c : 91.20 +pb_25c : 91.00 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.25 +pb_1c : 91.25 +pb_5c : 91.25 +pb_10c : 91.20 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.26 +pb_1c : 91.26 +pb_5c : 91.25 +pb_10c : 91.20 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.27 +pb_1c : 91.27 +pb_5c : 91.25 +pb_10c : 91.20 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.28 +pb_1c : 91.28 +pb_5c : 91.25 +pb_10c : 91.20 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.29 +pb_1c : 91.29 +pb_5c : 91.25 +pb_10c : 91.20 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.30 +pb_1c : 91.30 +pb_5c : 91.30 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.31 +pb_1c : 91.31 +pb_5c : 91.30 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.32 +pb_1c : 91.32 +pb_5c : 91.30 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.33 +pb_1c : 91.33 +pb_5c : 91.30 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.34 +pb_1c : 91.34 +pb_5c : 91.30 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.35 +pb_1c : 91.35 +pb_5c : 91.35 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.36 +pb_1c : 91.36 +pb_5c : 91.35 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.37 +pb_1c : 91.37 +pb_5c : 91.35 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.38 +pb_1c : 91.38 +pb_5c : 91.35 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.39 +pb_1c : 91.39 +pb_5c : 91.35 +pb_10c : 91.30 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.40 +pb_1c : 91.40 +pb_5c : 91.40 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.41 +pb_1c : 91.41 +pb_5c : 91.40 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.42 +pb_1c : 91.42 +pb_5c : 91.40 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.43 +pb_1c : 91.43 +pb_5c : 91.40 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.44 +pb_1c : 91.44 +pb_5c : 91.40 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.45 +pb_1c : 91.45 +pb_5c : 91.45 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.46 +pb_1c : 91.46 +pb_5c : 91.45 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.47 +pb_1c : 91.47 +pb_5c : 91.45 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.48 +pb_1c : 91.48 +pb_5c : 91.45 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.49 +pb_1c : 91.49 +pb_5c : 91.45 +pb_10c : 91.40 +pb_25c : 91.25 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.50 +pb_1c : 91.50 +pb_5c : 91.50 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.51 +pb_1c : 91.51 +pb_5c : 91.50 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.52 +pb_1c : 91.52 +pb_5c : 91.50 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.53 +pb_1c : 91.53 +pb_5c : 91.50 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.54 +pb_1c : 91.54 +pb_5c : 91.50 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.55 +pb_1c : 91.55 +pb_5c : 91.55 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.56 +pb_1c : 91.56 +pb_5c : 91.55 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.57 +pb_1c : 91.57 +pb_5c : 91.55 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.58 +pb_1c : 91.58 +pb_5c : 91.55 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.59 +pb_1c : 91.59 +pb_5c : 91.55 +pb_10c : 91.50 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.60 +pb_1c : 91.60 +pb_5c : 91.60 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.61 +pb_1c : 91.61 +pb_5c : 91.60 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.62 +pb_1c : 91.62 +pb_5c : 91.60 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.63 +pb_1c : 91.63 +pb_5c : 91.60 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.64 +pb_1c : 91.64 +pb_5c : 91.60 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.65 +pb_1c : 91.65 +pb_5c : 91.65 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.66 +pb_1c : 91.66 +pb_5c : 91.65 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.67 +pb_1c : 91.67 +pb_5c : 91.65 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.68 +pb_1c : 91.68 +pb_5c : 91.65 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.69 +pb_1c : 91.69 +pb_5c : 91.65 +pb_10c : 91.60 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.70 +pb_1c : 91.70 +pb_5c : 91.70 +pb_10c : 91.70 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.71 +pb_1c : 91.71 +pb_5c : 91.70 +pb_10c : 91.70 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.72 +pb_1c : 91.72 +pb_5c : 91.70 +pb_10c : 91.70 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.73 +pb_1c : 91.73 +pb_5c : 91.70 +pb_10c : 91.70 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.74 +pb_1c : 91.74 +pb_5c : 91.70 +pb_10c : 91.70 +pb_25c : 91.50 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.75 +pb_1c : 91.75 +pb_5c : 91.75 +pb_10c : 91.70 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.76 +pb_1c : 91.76 +pb_5c : 91.75 +pb_10c : 91.70 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.77 +pb_1c : 91.77 +pb_5c : 91.75 +pb_10c : 91.70 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.78 +pb_1c : 91.78 +pb_5c : 91.75 +pb_10c : 91.70 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.79 +pb_1c : 91.79 +pb_5c : 91.75 +pb_10c : 91.70 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.80 +pb_1c : 91.80 +pb_5c : 91.80 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.81 +pb_1c : 91.81 +pb_5c : 91.80 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.82 +pb_1c : 91.82 +pb_5c : 91.80 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.83 +pb_1c : 91.83 +pb_5c : 91.80 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.84 +pb_1c : 91.84 +pb_5c : 91.80 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.85 +pb_1c : 91.85 +pb_5c : 91.85 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.86 +pb_1c : 91.86 +pb_5c : 91.85 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.87 +pb_1c : 91.87 +pb_5c : 91.85 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.88 +pb_1c : 91.88 +pb_5c : 91.85 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.89 +pb_1c : 91.89 +pb_5c : 91.85 +pb_10c : 91.80 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.90 +pb_1c : 91.90 +pb_5c : 91.90 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.91 +pb_1c : 91.91 +pb_5c : 91.90 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.92 +pb_1c : 91.92 +pb_5c : 91.90 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.93 +pb_1c : 91.93 +pb_5c : 91.90 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.94 +pb_1c : 91.94 +pb_5c : 91.90 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.95 +pb_1c : 91.95 +pb_5c : 91.95 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.96 +pb_1c : 91.96 +pb_5c : 91.95 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.97 +pb_1c : 91.97 +pb_5c : 91.95 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.98 +pb_1c : 91.98 +pb_5c : 91.95 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +91.99 +pb_1c : 91.99 +pb_5c : 91.95 +pb_10c : 91.90 +pb_25c : 91.75 +pb_1d : 91.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.00 +pb_1c : 92.00 +pb_5c : 92.00 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.01 +pb_1c : 92.01 +pb_5c : 92.00 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.02 +pb_1c : 92.02 +pb_5c : 92.00 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.03 +pb_1c : 92.03 +pb_5c : 92.00 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.04 +pb_1c : 92.04 +pb_5c : 92.00 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.05 +pb_1c : 92.05 +pb_5c : 92.05 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.06 +pb_1c : 92.06 +pb_5c : 92.05 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.07 +pb_1c : 92.07 +pb_5c : 92.05 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.08 +pb_1c : 92.08 +pb_5c : 92.05 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.09 +pb_1c : 92.09 +pb_5c : 92.05 +pb_10c : 92.00 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.10 +pb_1c : 92.10 +pb_5c : 92.10 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.11 +pb_1c : 92.11 +pb_5c : 92.10 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.12 +pb_1c : 92.12 +pb_5c : 92.10 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.13 +pb_1c : 92.13 +pb_5c : 92.10 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.14 +pb_1c : 92.14 +pb_5c : 92.10 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.15 +pb_1c : 92.15 +pb_5c : 92.15 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.16 +pb_1c : 92.16 +pb_5c : 92.15 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.17 +pb_1c : 92.17 +pb_5c : 92.15 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.18 +pb_1c : 92.18 +pb_5c : 92.15 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.19 +pb_1c : 92.19 +pb_5c : 92.15 +pb_10c : 92.10 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.20 +pb_1c : 92.20 +pb_5c : 92.20 +pb_10c : 92.20 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.21 +pb_1c : 92.21 +pb_5c : 92.20 +pb_10c : 92.20 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.22 +pb_1c : 92.22 +pb_5c : 92.20 +pb_10c : 92.20 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.23 +pb_1c : 92.23 +pb_5c : 92.20 +pb_10c : 92.20 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.24 +pb_1c : 92.24 +pb_5c : 92.20 +pb_10c : 92.20 +pb_25c : 92.00 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.25 +pb_1c : 92.25 +pb_5c : 92.25 +pb_10c : 92.20 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.26 +pb_1c : 92.26 +pb_5c : 92.25 +pb_10c : 92.20 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.27 +pb_1c : 92.27 +pb_5c : 92.25 +pb_10c : 92.20 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.28 +pb_1c : 92.28 +pb_5c : 92.25 +pb_10c : 92.20 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.29 +pb_1c : 92.29 +pb_5c : 92.25 +pb_10c : 92.20 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.30 +pb_1c : 92.30 +pb_5c : 92.30 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.31 +pb_1c : 92.31 +pb_5c : 92.30 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.32 +pb_1c : 92.32 +pb_5c : 92.30 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.33 +pb_1c : 92.33 +pb_5c : 92.30 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.34 +pb_1c : 92.34 +pb_5c : 92.30 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.35 +pb_1c : 92.35 +pb_5c : 92.35 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.36 +pb_1c : 92.36 +pb_5c : 92.35 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.37 +pb_1c : 92.37 +pb_5c : 92.35 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.38 +pb_1c : 92.38 +pb_5c : 92.35 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.39 +pb_1c : 92.39 +pb_5c : 92.35 +pb_10c : 92.30 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.40 +pb_1c : 92.40 +pb_5c : 92.40 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.41 +pb_1c : 92.41 +pb_5c : 92.40 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.42 +pb_1c : 92.42 +pb_5c : 92.40 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.43 +pb_1c : 92.43 +pb_5c : 92.40 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.44 +pb_1c : 92.44 +pb_5c : 92.40 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.45 +pb_1c : 92.45 +pb_5c : 92.45 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.46 +pb_1c : 92.46 +pb_5c : 92.45 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.47 +pb_1c : 92.47 +pb_5c : 92.45 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.48 +pb_1c : 92.48 +pb_5c : 92.45 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.49 +pb_1c : 92.49 +pb_5c : 92.45 +pb_10c : 92.40 +pb_25c : 92.25 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.50 +pb_1c : 92.50 +pb_5c : 92.50 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.51 +pb_1c : 92.51 +pb_5c : 92.50 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.52 +pb_1c : 92.52 +pb_5c : 92.50 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.53 +pb_1c : 92.53 +pb_5c : 92.50 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.54 +pb_1c : 92.54 +pb_5c : 92.50 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.55 +pb_1c : 92.55 +pb_5c : 92.55 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.56 +pb_1c : 92.56 +pb_5c : 92.55 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.57 +pb_1c : 92.57 +pb_5c : 92.55 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.58 +pb_1c : 92.58 +pb_5c : 92.55 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.59 +pb_1c : 92.59 +pb_5c : 92.55 +pb_10c : 92.50 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.60 +pb_1c : 92.60 +pb_5c : 92.60 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.61 +pb_1c : 92.61 +pb_5c : 92.60 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.62 +pb_1c : 92.62 +pb_5c : 92.60 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.63 +pb_1c : 92.63 +pb_5c : 92.60 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.64 +pb_1c : 92.64 +pb_5c : 92.60 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.65 +pb_1c : 92.65 +pb_5c : 92.65 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.66 +pb_1c : 92.66 +pb_5c : 92.65 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.67 +pb_1c : 92.67 +pb_5c : 92.65 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.68 +pb_1c : 92.68 +pb_5c : 92.65 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.69 +pb_1c : 92.69 +pb_5c : 92.65 +pb_10c : 92.60 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.70 +pb_1c : 92.70 +pb_5c : 92.70 +pb_10c : 92.70 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.71 +pb_1c : 92.71 +pb_5c : 92.70 +pb_10c : 92.70 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.72 +pb_1c : 92.72 +pb_5c : 92.70 +pb_10c : 92.70 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.73 +pb_1c : 92.73 +pb_5c : 92.70 +pb_10c : 92.70 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.74 +pb_1c : 92.74 +pb_5c : 92.70 +pb_10c : 92.70 +pb_25c : 92.50 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.75 +pb_1c : 92.75 +pb_5c : 92.75 +pb_10c : 92.70 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.76 +pb_1c : 92.76 +pb_5c : 92.75 +pb_10c : 92.70 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.77 +pb_1c : 92.77 +pb_5c : 92.75 +pb_10c : 92.70 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.78 +pb_1c : 92.78 +pb_5c : 92.75 +pb_10c : 92.70 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.79 +pb_1c : 92.79 +pb_5c : 92.75 +pb_10c : 92.70 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.80 +pb_1c : 92.80 +pb_5c : 92.80 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.81 +pb_1c : 92.81 +pb_5c : 92.80 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.82 +pb_1c : 92.82 +pb_5c : 92.80 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.83 +pb_1c : 92.83 +pb_5c : 92.80 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.84 +pb_1c : 92.84 +pb_5c : 92.80 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.85 +pb_1c : 92.85 +pb_5c : 92.85 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.86 +pb_1c : 92.86 +pb_5c : 92.85 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.87 +pb_1c : 92.87 +pb_5c : 92.85 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.88 +pb_1c : 92.88 +pb_5c : 92.85 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.89 +pb_1c : 92.89 +pb_5c : 92.85 +pb_10c : 92.80 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.90 +pb_1c : 92.90 +pb_5c : 92.90 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.91 +pb_1c : 92.91 +pb_5c : 92.90 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.92 +pb_1c : 92.92 +pb_5c : 92.90 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.93 +pb_1c : 92.93 +pb_5c : 92.90 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.94 +pb_1c : 92.94 +pb_5c : 92.90 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.95 +pb_1c : 92.95 +pb_5c : 92.95 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.96 +pb_1c : 92.96 +pb_5c : 92.95 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.97 +pb_1c : 92.97 +pb_5c : 92.95 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.98 +pb_1c : 92.98 +pb_5c : 92.95 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +92.99 +pb_1c : 92.99 +pb_5c : 92.95 +pb_10c : 92.90 +pb_25c : 92.75 +pb_1d : 92.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.00 +pb_1c : 93.00 +pb_5c : 93.00 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.01 +pb_1c : 93.01 +pb_5c : 93.00 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.02 +pb_1c : 93.02 +pb_5c : 93.00 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.03 +pb_1c : 93.03 +pb_5c : 93.00 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.04 +pb_1c : 93.04 +pb_5c : 93.00 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.05 +pb_1c : 93.05 +pb_5c : 93.05 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.06 +pb_1c : 93.06 +pb_5c : 93.05 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.07 +pb_1c : 93.07 +pb_5c : 93.05 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.08 +pb_1c : 93.08 +pb_5c : 93.05 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.09 +pb_1c : 93.09 +pb_5c : 93.05 +pb_10c : 93.00 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.10 +pb_1c : 93.10 +pb_5c : 93.10 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.11 +pb_1c : 93.11 +pb_5c : 93.10 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.12 +pb_1c : 93.12 +pb_5c : 93.10 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.13 +pb_1c : 93.13 +pb_5c : 93.10 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.14 +pb_1c : 93.14 +pb_5c : 93.10 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.15 +pb_1c : 93.15 +pb_5c : 93.15 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.16 +pb_1c : 93.16 +pb_5c : 93.15 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.17 +pb_1c : 93.17 +pb_5c : 93.15 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.18 +pb_1c : 93.18 +pb_5c : 93.15 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.19 +pb_1c : 93.19 +pb_5c : 93.15 +pb_10c : 93.10 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.20 +pb_1c : 93.20 +pb_5c : 93.20 +pb_10c : 93.20 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.21 +pb_1c : 93.21 +pb_5c : 93.20 +pb_10c : 93.20 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.22 +pb_1c : 93.22 +pb_5c : 93.20 +pb_10c : 93.20 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.23 +pb_1c : 93.23 +pb_5c : 93.20 +pb_10c : 93.20 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.24 +pb_1c : 93.24 +pb_5c : 93.20 +pb_10c : 93.20 +pb_25c : 93.00 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.25 +pb_1c : 93.25 +pb_5c : 93.25 +pb_10c : 93.20 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.26 +pb_1c : 93.26 +pb_5c : 93.25 +pb_10c : 93.20 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.27 +pb_1c : 93.27 +pb_5c : 93.25 +pb_10c : 93.20 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.28 +pb_1c : 93.28 +pb_5c : 93.25 +pb_10c : 93.20 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.29 +pb_1c : 93.29 +pb_5c : 93.25 +pb_10c : 93.20 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.30 +pb_1c : 93.30 +pb_5c : 93.30 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.31 +pb_1c : 93.31 +pb_5c : 93.30 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.32 +pb_1c : 93.32 +pb_5c : 93.30 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.33 +pb_1c : 93.33 +pb_5c : 93.30 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.34 +pb_1c : 93.34 +pb_5c : 93.30 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.35 +pb_1c : 93.35 +pb_5c : 93.35 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.36 +pb_1c : 93.36 +pb_5c : 93.35 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.37 +pb_1c : 93.37 +pb_5c : 93.35 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.38 +pb_1c : 93.38 +pb_5c : 93.35 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.39 +pb_1c : 93.39 +pb_5c : 93.35 +pb_10c : 93.30 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.40 +pb_1c : 93.40 +pb_5c : 93.40 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.41 +pb_1c : 93.41 +pb_5c : 93.40 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.42 +pb_1c : 93.42 +pb_5c : 93.40 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.43 +pb_1c : 93.43 +pb_5c : 93.40 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.44 +pb_1c : 93.44 +pb_5c : 93.40 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.45 +pb_1c : 93.45 +pb_5c : 93.45 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.46 +pb_1c : 93.46 +pb_5c : 93.45 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.47 +pb_1c : 93.47 +pb_5c : 93.45 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.48 +pb_1c : 93.48 +pb_5c : 93.45 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.49 +pb_1c : 93.49 +pb_5c : 93.45 +pb_10c : 93.40 +pb_25c : 93.25 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.50 +pb_1c : 93.50 +pb_5c : 93.50 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.51 +pb_1c : 93.51 +pb_5c : 93.50 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.52 +pb_1c : 93.52 +pb_5c : 93.50 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.53 +pb_1c : 93.53 +pb_5c : 93.50 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.54 +pb_1c : 93.54 +pb_5c : 93.50 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.55 +pb_1c : 93.55 +pb_5c : 93.55 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.56 +pb_1c : 93.56 +pb_5c : 93.55 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.57 +pb_1c : 93.57 +pb_5c : 93.55 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.58 +pb_1c : 93.58 +pb_5c : 93.55 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.59 +pb_1c : 93.59 +pb_5c : 93.55 +pb_10c : 93.50 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.60 +pb_1c : 93.60 +pb_5c : 93.60 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.61 +pb_1c : 93.61 +pb_5c : 93.60 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.62 +pb_1c : 93.62 +pb_5c : 93.60 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.63 +pb_1c : 93.63 +pb_5c : 93.60 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.64 +pb_1c : 93.64 +pb_5c : 93.60 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.65 +pb_1c : 93.65 +pb_5c : 93.65 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.66 +pb_1c : 93.66 +pb_5c : 93.65 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.67 +pb_1c : 93.67 +pb_5c : 93.65 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.68 +pb_1c : 93.68 +pb_5c : 93.65 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.69 +pb_1c : 93.69 +pb_5c : 93.65 +pb_10c : 93.60 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.70 +pb_1c : 93.70 +pb_5c : 93.70 +pb_10c : 93.70 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.71 +pb_1c : 93.71 +pb_5c : 93.70 +pb_10c : 93.70 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.72 +pb_1c : 93.72 +pb_5c : 93.70 +pb_10c : 93.70 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.73 +pb_1c : 93.73 +pb_5c : 93.70 +pb_10c : 93.70 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.74 +pb_1c : 93.74 +pb_5c : 93.70 +pb_10c : 93.70 +pb_25c : 93.50 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.75 +pb_1c : 93.75 +pb_5c : 93.75 +pb_10c : 93.70 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.76 +pb_1c : 93.76 +pb_5c : 93.75 +pb_10c : 93.70 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.77 +pb_1c : 93.77 +pb_5c : 93.75 +pb_10c : 93.70 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.78 +pb_1c : 93.78 +pb_5c : 93.75 +pb_10c : 93.70 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.79 +pb_1c : 93.79 +pb_5c : 93.75 +pb_10c : 93.70 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.80 +pb_1c : 93.80 +pb_5c : 93.80 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.81 +pb_1c : 93.81 +pb_5c : 93.80 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.82 +pb_1c : 93.82 +pb_5c : 93.80 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.83 +pb_1c : 93.83 +pb_5c : 93.80 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.84 +pb_1c : 93.84 +pb_5c : 93.80 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.85 +pb_1c : 93.85 +pb_5c : 93.85 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.86 +pb_1c : 93.86 +pb_5c : 93.85 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.87 +pb_1c : 93.87 +pb_5c : 93.85 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.88 +pb_1c : 93.88 +pb_5c : 93.85 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.89 +pb_1c : 93.89 +pb_5c : 93.85 +pb_10c : 93.80 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.90 +pb_1c : 93.90 +pb_5c : 93.90 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.91 +pb_1c : 93.91 +pb_5c : 93.90 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.92 +pb_1c : 93.92 +pb_5c : 93.90 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.93 +pb_1c : 93.93 +pb_5c : 93.90 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.94 +pb_1c : 93.94 +pb_5c : 93.90 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.95 +pb_1c : 93.95 +pb_5c : 93.95 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.96 +pb_1c : 93.96 +pb_5c : 93.95 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.97 +pb_1c : 93.97 +pb_5c : 93.95 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.98 +pb_1c : 93.98 +pb_5c : 93.95 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +93.99 +pb_1c : 93.99 +pb_5c : 93.95 +pb_10c : 93.90 +pb_25c : 93.75 +pb_1d : 93.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.00 +pb_1c : 94.00 +pb_5c : 94.00 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.01 +pb_1c : 94.01 +pb_5c : 94.00 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.02 +pb_1c : 94.02 +pb_5c : 94.00 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.03 +pb_1c : 94.03 +pb_5c : 94.00 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.04 +pb_1c : 94.04 +pb_5c : 94.00 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.05 +pb_1c : 94.05 +pb_5c : 94.05 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.06 +pb_1c : 94.06 +pb_5c : 94.05 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.07 +pb_1c : 94.07 +pb_5c : 94.05 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.08 +pb_1c : 94.08 +pb_5c : 94.05 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.09 +pb_1c : 94.09 +pb_5c : 94.05 +pb_10c : 94.00 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.10 +pb_1c : 94.10 +pb_5c : 94.10 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.11 +pb_1c : 94.11 +pb_5c : 94.10 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.12 +pb_1c : 94.12 +pb_5c : 94.10 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.13 +pb_1c : 94.13 +pb_5c : 94.10 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.14 +pb_1c : 94.14 +pb_5c : 94.10 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.15 +pb_1c : 94.15 +pb_5c : 94.15 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.16 +pb_1c : 94.16 +pb_5c : 94.15 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.17 +pb_1c : 94.17 +pb_5c : 94.15 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.18 +pb_1c : 94.18 +pb_5c : 94.15 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.19 +pb_1c : 94.19 +pb_5c : 94.15 +pb_10c : 94.10 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.20 +pb_1c : 94.20 +pb_5c : 94.20 +pb_10c : 94.20 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.21 +pb_1c : 94.21 +pb_5c : 94.20 +pb_10c : 94.20 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.22 +pb_1c : 94.22 +pb_5c : 94.20 +pb_10c : 94.20 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.23 +pb_1c : 94.23 +pb_5c : 94.20 +pb_10c : 94.20 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.24 +pb_1c : 94.24 +pb_5c : 94.20 +pb_10c : 94.20 +pb_25c : 94.00 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.25 +pb_1c : 94.25 +pb_5c : 94.25 +pb_10c : 94.20 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.26 +pb_1c : 94.26 +pb_5c : 94.25 +pb_10c : 94.20 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.27 +pb_1c : 94.27 +pb_5c : 94.25 +pb_10c : 94.20 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.28 +pb_1c : 94.28 +pb_5c : 94.25 +pb_10c : 94.20 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.29 +pb_1c : 94.29 +pb_5c : 94.25 +pb_10c : 94.20 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.30 +pb_1c : 94.30 +pb_5c : 94.30 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.31 +pb_1c : 94.31 +pb_5c : 94.30 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.32 +pb_1c : 94.32 +pb_5c : 94.30 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.33 +pb_1c : 94.33 +pb_5c : 94.30 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.34 +pb_1c : 94.34 +pb_5c : 94.30 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.35 +pb_1c : 94.35 +pb_5c : 94.35 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.36 +pb_1c : 94.36 +pb_5c : 94.35 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.37 +pb_1c : 94.37 +pb_5c : 94.35 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.38 +pb_1c : 94.38 +pb_5c : 94.35 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.39 +pb_1c : 94.39 +pb_5c : 94.35 +pb_10c : 94.30 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.40 +pb_1c : 94.40 +pb_5c : 94.40 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.41 +pb_1c : 94.41 +pb_5c : 94.40 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.42 +pb_1c : 94.42 +pb_5c : 94.40 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.43 +pb_1c : 94.43 +pb_5c : 94.40 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.44 +pb_1c : 94.44 +pb_5c : 94.40 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.45 +pb_1c : 94.45 +pb_5c : 94.45 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.46 +pb_1c : 94.46 +pb_5c : 94.45 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.47 +pb_1c : 94.47 +pb_5c : 94.45 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.48 +pb_1c : 94.48 +pb_5c : 94.45 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.49 +pb_1c : 94.49 +pb_5c : 94.45 +pb_10c : 94.40 +pb_25c : 94.25 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.50 +pb_1c : 94.50 +pb_5c : 94.50 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.51 +pb_1c : 94.51 +pb_5c : 94.50 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.52 +pb_1c : 94.52 +pb_5c : 94.50 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.53 +pb_1c : 94.53 +pb_5c : 94.50 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.54 +pb_1c : 94.54 +pb_5c : 94.50 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.55 +pb_1c : 94.55 +pb_5c : 94.55 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.56 +pb_1c : 94.56 +pb_5c : 94.55 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.57 +pb_1c : 94.57 +pb_5c : 94.55 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.58 +pb_1c : 94.58 +pb_5c : 94.55 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.59 +pb_1c : 94.59 +pb_5c : 94.55 +pb_10c : 94.50 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.60 +pb_1c : 94.60 +pb_5c : 94.60 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.61 +pb_1c : 94.61 +pb_5c : 94.60 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.62 +pb_1c : 94.62 +pb_5c : 94.60 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.63 +pb_1c : 94.63 +pb_5c : 94.60 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.64 +pb_1c : 94.64 +pb_5c : 94.60 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.65 +pb_1c : 94.65 +pb_5c : 94.65 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.66 +pb_1c : 94.66 +pb_5c : 94.65 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.67 +pb_1c : 94.67 +pb_5c : 94.65 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.68 +pb_1c : 94.68 +pb_5c : 94.65 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.69 +pb_1c : 94.69 +pb_5c : 94.65 +pb_10c : 94.60 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.70 +pb_1c : 94.70 +pb_5c : 94.70 +pb_10c : 94.70 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.71 +pb_1c : 94.71 +pb_5c : 94.70 +pb_10c : 94.70 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.72 +pb_1c : 94.72 +pb_5c : 94.70 +pb_10c : 94.70 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.73 +pb_1c : 94.73 +pb_5c : 94.70 +pb_10c : 94.70 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.74 +pb_1c : 94.74 +pb_5c : 94.70 +pb_10c : 94.70 +pb_25c : 94.50 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.75 +pb_1c : 94.75 +pb_5c : 94.75 +pb_10c : 94.70 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.76 +pb_1c : 94.76 +pb_5c : 94.75 +pb_10c : 94.70 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.77 +pb_1c : 94.77 +pb_5c : 94.75 +pb_10c : 94.70 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.78 +pb_1c : 94.78 +pb_5c : 94.75 +pb_10c : 94.70 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.79 +pb_1c : 94.79 +pb_5c : 94.75 +pb_10c : 94.70 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.80 +pb_1c : 94.80 +pb_5c : 94.80 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.81 +pb_1c : 94.81 +pb_5c : 94.80 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.82 +pb_1c : 94.82 +pb_5c : 94.80 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.83 +pb_1c : 94.83 +pb_5c : 94.80 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.84 +pb_1c : 94.84 +pb_5c : 94.80 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.85 +pb_1c : 94.85 +pb_5c : 94.85 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.86 +pb_1c : 94.86 +pb_5c : 94.85 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.87 +pb_1c : 94.87 +pb_5c : 94.85 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.88 +pb_1c : 94.88 +pb_5c : 94.85 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.89 +pb_1c : 94.89 +pb_5c : 94.85 +pb_10c : 94.80 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.90 +pb_1c : 94.90 +pb_5c : 94.90 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.91 +pb_1c : 94.91 +pb_5c : 94.90 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.92 +pb_1c : 94.92 +pb_5c : 94.90 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.93 +pb_1c : 94.93 +pb_5c : 94.90 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.94 +pb_1c : 94.94 +pb_5c : 94.90 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.95 +pb_1c : 94.95 +pb_5c : 94.95 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.96 +pb_1c : 94.96 +pb_5c : 94.95 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.97 +pb_1c : 94.97 +pb_5c : 94.95 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.98 +pb_1c : 94.98 +pb_5c : 94.95 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +94.99 +pb_1c : 94.99 +pb_5c : 94.95 +pb_10c : 94.90 +pb_25c : 94.75 +pb_1d : 94.00 +pb_5d : 90.00 +pb_10d : 90.00 + +95.00 +pb_1c : 95.00 +pb_5c : 95.00 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.01 +pb_1c : 95.01 +pb_5c : 95.00 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.02 +pb_1c : 95.02 +pb_5c : 95.00 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.03 +pb_1c : 95.03 +pb_5c : 95.00 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.04 +pb_1c : 95.04 +pb_5c : 95.00 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.05 +pb_1c : 95.05 +pb_5c : 95.05 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.06 +pb_1c : 95.06 +pb_5c : 95.05 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.07 +pb_1c : 95.07 +pb_5c : 95.05 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.08 +pb_1c : 95.08 +pb_5c : 95.05 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.09 +pb_1c : 95.09 +pb_5c : 95.05 +pb_10c : 95.00 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.10 +pb_1c : 95.10 +pb_5c : 95.10 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.11 +pb_1c : 95.11 +pb_5c : 95.10 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.12 +pb_1c : 95.12 +pb_5c : 95.10 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.13 +pb_1c : 95.13 +pb_5c : 95.10 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.14 +pb_1c : 95.14 +pb_5c : 95.10 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.15 +pb_1c : 95.15 +pb_5c : 95.15 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.16 +pb_1c : 95.16 +pb_5c : 95.15 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.17 +pb_1c : 95.17 +pb_5c : 95.15 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.18 +pb_1c : 95.18 +pb_5c : 95.15 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.19 +pb_1c : 95.19 +pb_5c : 95.15 +pb_10c : 95.10 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.20 +pb_1c : 95.20 +pb_5c : 95.20 +pb_10c : 95.20 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.21 +pb_1c : 95.21 +pb_5c : 95.20 +pb_10c : 95.20 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.22 +pb_1c : 95.22 +pb_5c : 95.20 +pb_10c : 95.20 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.23 +pb_1c : 95.23 +pb_5c : 95.20 +pb_10c : 95.20 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.24 +pb_1c : 95.24 +pb_5c : 95.20 +pb_10c : 95.20 +pb_25c : 95.00 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.25 +pb_1c : 95.25 +pb_5c : 95.25 +pb_10c : 95.20 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.26 +pb_1c : 95.26 +pb_5c : 95.25 +pb_10c : 95.20 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.27 +pb_1c : 95.27 +pb_5c : 95.25 +pb_10c : 95.20 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.28 +pb_1c : 95.28 +pb_5c : 95.25 +pb_10c : 95.20 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.29 +pb_1c : 95.29 +pb_5c : 95.25 +pb_10c : 95.20 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.30 +pb_1c : 95.30 +pb_5c : 95.30 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.31 +pb_1c : 95.31 +pb_5c : 95.30 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.32 +pb_1c : 95.32 +pb_5c : 95.30 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.33 +pb_1c : 95.33 +pb_5c : 95.30 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.34 +pb_1c : 95.34 +pb_5c : 95.30 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.35 +pb_1c : 95.35 +pb_5c : 95.35 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.36 +pb_1c : 95.36 +pb_5c : 95.35 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.37 +pb_1c : 95.37 +pb_5c : 95.35 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.38 +pb_1c : 95.38 +pb_5c : 95.35 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.39 +pb_1c : 95.39 +pb_5c : 95.35 +pb_10c : 95.30 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.40 +pb_1c : 95.40 +pb_5c : 95.40 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.41 +pb_1c : 95.41 +pb_5c : 95.40 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.42 +pb_1c : 95.42 +pb_5c : 95.40 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.43 +pb_1c : 95.43 +pb_5c : 95.40 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.44 +pb_1c : 95.44 +pb_5c : 95.40 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.45 +pb_1c : 95.45 +pb_5c : 95.45 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.46 +pb_1c : 95.46 +pb_5c : 95.45 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.47 +pb_1c : 95.47 +pb_5c : 95.45 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.48 +pb_1c : 95.48 +pb_5c : 95.45 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.49 +pb_1c : 95.49 +pb_5c : 95.45 +pb_10c : 95.40 +pb_25c : 95.25 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.50 +pb_1c : 95.50 +pb_5c : 95.50 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.51 +pb_1c : 95.51 +pb_5c : 95.50 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.52 +pb_1c : 95.52 +pb_5c : 95.50 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.53 +pb_1c : 95.53 +pb_5c : 95.50 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.54 +pb_1c : 95.54 +pb_5c : 95.50 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.55 +pb_1c : 95.55 +pb_5c : 95.55 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.56 +pb_1c : 95.56 +pb_5c : 95.55 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.57 +pb_1c : 95.57 +pb_5c : 95.55 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.58 +pb_1c : 95.58 +pb_5c : 95.55 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.59 +pb_1c : 95.59 +pb_5c : 95.55 +pb_10c : 95.50 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.60 +pb_1c : 95.60 +pb_5c : 95.60 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.61 +pb_1c : 95.61 +pb_5c : 95.60 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.62 +pb_1c : 95.62 +pb_5c : 95.60 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.63 +pb_1c : 95.63 +pb_5c : 95.60 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.64 +pb_1c : 95.64 +pb_5c : 95.60 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.65 +pb_1c : 95.65 +pb_5c : 95.65 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.66 +pb_1c : 95.66 +pb_5c : 95.65 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.67 +pb_1c : 95.67 +pb_5c : 95.65 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.68 +pb_1c : 95.68 +pb_5c : 95.65 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.69 +pb_1c : 95.69 +pb_5c : 95.65 +pb_10c : 95.60 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.70 +pb_1c : 95.70 +pb_5c : 95.70 +pb_10c : 95.70 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.71 +pb_1c : 95.71 +pb_5c : 95.70 +pb_10c : 95.70 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.72 +pb_1c : 95.72 +pb_5c : 95.70 +pb_10c : 95.70 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.73 +pb_1c : 95.73 +pb_5c : 95.70 +pb_10c : 95.70 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.74 +pb_1c : 95.74 +pb_5c : 95.70 +pb_10c : 95.70 +pb_25c : 95.50 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.75 +pb_1c : 95.75 +pb_5c : 95.75 +pb_10c : 95.70 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.76 +pb_1c : 95.76 +pb_5c : 95.75 +pb_10c : 95.70 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.77 +pb_1c : 95.77 +pb_5c : 95.75 +pb_10c : 95.70 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.78 +pb_1c : 95.78 +pb_5c : 95.75 +pb_10c : 95.70 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.79 +pb_1c : 95.79 +pb_5c : 95.75 +pb_10c : 95.70 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.80 +pb_1c : 95.80 +pb_5c : 95.80 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.81 +pb_1c : 95.81 +pb_5c : 95.80 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.82 +pb_1c : 95.82 +pb_5c : 95.80 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.83 +pb_1c : 95.83 +pb_5c : 95.80 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.84 +pb_1c : 95.84 +pb_5c : 95.80 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.85 +pb_1c : 95.85 +pb_5c : 95.85 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.86 +pb_1c : 95.86 +pb_5c : 95.85 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.87 +pb_1c : 95.87 +pb_5c : 95.85 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.88 +pb_1c : 95.88 +pb_5c : 95.85 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.89 +pb_1c : 95.89 +pb_5c : 95.85 +pb_10c : 95.80 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.90 +pb_1c : 95.90 +pb_5c : 95.90 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.91 +pb_1c : 95.91 +pb_5c : 95.90 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.92 +pb_1c : 95.92 +pb_5c : 95.90 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.93 +pb_1c : 95.93 +pb_5c : 95.90 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.94 +pb_1c : 95.94 +pb_5c : 95.90 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.95 +pb_1c : 95.95 +pb_5c : 95.95 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.96 +pb_1c : 95.96 +pb_5c : 95.95 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.97 +pb_1c : 95.97 +pb_5c : 95.95 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.98 +pb_1c : 95.98 +pb_5c : 95.95 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +95.99 +pb_1c : 95.99 +pb_5c : 95.95 +pb_10c : 95.90 +pb_25c : 95.75 +pb_1d : 95.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.00 +pb_1c : 96.00 +pb_5c : 96.00 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.01 +pb_1c : 96.01 +pb_5c : 96.00 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.02 +pb_1c : 96.02 +pb_5c : 96.00 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.03 +pb_1c : 96.03 +pb_5c : 96.00 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.04 +pb_1c : 96.04 +pb_5c : 96.00 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.05 +pb_1c : 96.05 +pb_5c : 96.05 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.06 +pb_1c : 96.06 +pb_5c : 96.05 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.07 +pb_1c : 96.07 +pb_5c : 96.05 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.08 +pb_1c : 96.08 +pb_5c : 96.05 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.09 +pb_1c : 96.09 +pb_5c : 96.05 +pb_10c : 96.00 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.10 +pb_1c : 96.10 +pb_5c : 96.10 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.11 +pb_1c : 96.11 +pb_5c : 96.10 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.12 +pb_1c : 96.12 +pb_5c : 96.10 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.13 +pb_1c : 96.13 +pb_5c : 96.10 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.14 +pb_1c : 96.14 +pb_5c : 96.10 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.15 +pb_1c : 96.15 +pb_5c : 96.15 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.16 +pb_1c : 96.16 +pb_5c : 96.15 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.17 +pb_1c : 96.17 +pb_5c : 96.15 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.18 +pb_1c : 96.18 +pb_5c : 96.15 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.19 +pb_1c : 96.19 +pb_5c : 96.15 +pb_10c : 96.10 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.20 +pb_1c : 96.20 +pb_5c : 96.20 +pb_10c : 96.20 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.21 +pb_1c : 96.21 +pb_5c : 96.20 +pb_10c : 96.20 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.22 +pb_1c : 96.22 +pb_5c : 96.20 +pb_10c : 96.20 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.23 +pb_1c : 96.23 +pb_5c : 96.20 +pb_10c : 96.20 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.24 +pb_1c : 96.24 +pb_5c : 96.20 +pb_10c : 96.20 +pb_25c : 96.00 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.25 +pb_1c : 96.25 +pb_5c : 96.25 +pb_10c : 96.20 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.26 +pb_1c : 96.26 +pb_5c : 96.25 +pb_10c : 96.20 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.27 +pb_1c : 96.27 +pb_5c : 96.25 +pb_10c : 96.20 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.28 +pb_1c : 96.28 +pb_5c : 96.25 +pb_10c : 96.20 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.29 +pb_1c : 96.29 +pb_5c : 96.25 +pb_10c : 96.20 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.30 +pb_1c : 96.30 +pb_5c : 96.30 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.31 +pb_1c : 96.31 +pb_5c : 96.30 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.32 +pb_1c : 96.32 +pb_5c : 96.30 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.33 +pb_1c : 96.33 +pb_5c : 96.30 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.34 +pb_1c : 96.34 +pb_5c : 96.30 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.35 +pb_1c : 96.35 +pb_5c : 96.35 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.36 +pb_1c : 96.36 +pb_5c : 96.35 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.37 +pb_1c : 96.37 +pb_5c : 96.35 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.38 +pb_1c : 96.38 +pb_5c : 96.35 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.39 +pb_1c : 96.39 +pb_5c : 96.35 +pb_10c : 96.30 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.40 +pb_1c : 96.40 +pb_5c : 96.40 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.41 +pb_1c : 96.41 +pb_5c : 96.40 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.42 +pb_1c : 96.42 +pb_5c : 96.40 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.43 +pb_1c : 96.43 +pb_5c : 96.40 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.44 +pb_1c : 96.44 +pb_5c : 96.40 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.45 +pb_1c : 96.45 +pb_5c : 96.45 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.46 +pb_1c : 96.46 +pb_5c : 96.45 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.47 +pb_1c : 96.47 +pb_5c : 96.45 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.48 +pb_1c : 96.48 +pb_5c : 96.45 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.49 +pb_1c : 96.49 +pb_5c : 96.45 +pb_10c : 96.40 +pb_25c : 96.25 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.50 +pb_1c : 96.50 +pb_5c : 96.50 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.51 +pb_1c : 96.51 +pb_5c : 96.50 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.52 +pb_1c : 96.52 +pb_5c : 96.50 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.53 +pb_1c : 96.53 +pb_5c : 96.50 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.54 +pb_1c : 96.54 +pb_5c : 96.50 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.55 +pb_1c : 96.55 +pb_5c : 96.55 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.56 +pb_1c : 96.56 +pb_5c : 96.55 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.57 +pb_1c : 96.57 +pb_5c : 96.55 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.58 +pb_1c : 96.58 +pb_5c : 96.55 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.59 +pb_1c : 96.59 +pb_5c : 96.55 +pb_10c : 96.50 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.60 +pb_1c : 96.60 +pb_5c : 96.60 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.61 +pb_1c : 96.61 +pb_5c : 96.60 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.62 +pb_1c : 96.62 +pb_5c : 96.60 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.63 +pb_1c : 96.63 +pb_5c : 96.60 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.64 +pb_1c : 96.64 +pb_5c : 96.60 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.65 +pb_1c : 96.65 +pb_5c : 96.65 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.66 +pb_1c : 96.66 +pb_5c : 96.65 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.67 +pb_1c : 96.67 +pb_5c : 96.65 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.68 +pb_1c : 96.68 +pb_5c : 96.65 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.69 +pb_1c : 96.69 +pb_5c : 96.65 +pb_10c : 96.60 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.70 +pb_1c : 96.70 +pb_5c : 96.70 +pb_10c : 96.70 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.71 +pb_1c : 96.71 +pb_5c : 96.70 +pb_10c : 96.70 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.72 +pb_1c : 96.72 +pb_5c : 96.70 +pb_10c : 96.70 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.73 +pb_1c : 96.73 +pb_5c : 96.70 +pb_10c : 96.70 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.74 +pb_1c : 96.74 +pb_5c : 96.70 +pb_10c : 96.70 +pb_25c : 96.50 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.75 +pb_1c : 96.75 +pb_5c : 96.75 +pb_10c : 96.70 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.76 +pb_1c : 96.76 +pb_5c : 96.75 +pb_10c : 96.70 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.77 +pb_1c : 96.77 +pb_5c : 96.75 +pb_10c : 96.70 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.78 +pb_1c : 96.78 +pb_5c : 96.75 +pb_10c : 96.70 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.79 +pb_1c : 96.79 +pb_5c : 96.75 +pb_10c : 96.70 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.80 +pb_1c : 96.80 +pb_5c : 96.80 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.81 +pb_1c : 96.81 +pb_5c : 96.80 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.82 +pb_1c : 96.82 +pb_5c : 96.80 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.83 +pb_1c : 96.83 +pb_5c : 96.80 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.84 +pb_1c : 96.84 +pb_5c : 96.80 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.85 +pb_1c : 96.85 +pb_5c : 96.85 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.86 +pb_1c : 96.86 +pb_5c : 96.85 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.87 +pb_1c : 96.87 +pb_5c : 96.85 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.88 +pb_1c : 96.88 +pb_5c : 96.85 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.89 +pb_1c : 96.89 +pb_5c : 96.85 +pb_10c : 96.80 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.90 +pb_1c : 96.90 +pb_5c : 96.90 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.91 +pb_1c : 96.91 +pb_5c : 96.90 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.92 +pb_1c : 96.92 +pb_5c : 96.90 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.93 +pb_1c : 96.93 +pb_5c : 96.90 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.94 +pb_1c : 96.94 +pb_5c : 96.90 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.95 +pb_1c : 96.95 +pb_5c : 96.95 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.96 +pb_1c : 96.96 +pb_5c : 96.95 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.97 +pb_1c : 96.97 +pb_5c : 96.95 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.98 +pb_1c : 96.98 +pb_5c : 96.95 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +96.99 +pb_1c : 96.99 +pb_5c : 96.95 +pb_10c : 96.90 +pb_25c : 96.75 +pb_1d : 96.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.00 +pb_1c : 97.00 +pb_5c : 97.00 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.01 +pb_1c : 97.01 +pb_5c : 97.00 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.02 +pb_1c : 97.02 +pb_5c : 97.00 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.03 +pb_1c : 97.03 +pb_5c : 97.00 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.04 +pb_1c : 97.04 +pb_5c : 97.00 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.05 +pb_1c : 97.05 +pb_5c : 97.05 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.06 +pb_1c : 97.06 +pb_5c : 97.05 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.07 +pb_1c : 97.07 +pb_5c : 97.05 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.08 +pb_1c : 97.08 +pb_5c : 97.05 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.09 +pb_1c : 97.09 +pb_5c : 97.05 +pb_10c : 97.00 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.10 +pb_1c : 97.10 +pb_5c : 97.10 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.11 +pb_1c : 97.11 +pb_5c : 97.10 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.12 +pb_1c : 97.12 +pb_5c : 97.10 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.13 +pb_1c : 97.13 +pb_5c : 97.10 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.14 +pb_1c : 97.14 +pb_5c : 97.10 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.15 +pb_1c : 97.15 +pb_5c : 97.15 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.16 +pb_1c : 97.16 +pb_5c : 97.15 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.17 +pb_1c : 97.17 +pb_5c : 97.15 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.18 +pb_1c : 97.18 +pb_5c : 97.15 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.19 +pb_1c : 97.19 +pb_5c : 97.15 +pb_10c : 97.10 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.20 +pb_1c : 97.20 +pb_5c : 97.20 +pb_10c : 97.20 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.21 +pb_1c : 97.21 +pb_5c : 97.20 +pb_10c : 97.20 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.22 +pb_1c : 97.22 +pb_5c : 97.20 +pb_10c : 97.20 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.23 +pb_1c : 97.23 +pb_5c : 97.20 +pb_10c : 97.20 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.24 +pb_1c : 97.24 +pb_5c : 97.20 +pb_10c : 97.20 +pb_25c : 97.00 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.25 +pb_1c : 97.25 +pb_5c : 97.25 +pb_10c : 97.20 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.26 +pb_1c : 97.26 +pb_5c : 97.25 +pb_10c : 97.20 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.27 +pb_1c : 97.27 +pb_5c : 97.25 +pb_10c : 97.20 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.28 +pb_1c : 97.28 +pb_5c : 97.25 +pb_10c : 97.20 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.29 +pb_1c : 97.29 +pb_5c : 97.25 +pb_10c : 97.20 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.30 +pb_1c : 97.30 +pb_5c : 97.30 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.31 +pb_1c : 97.31 +pb_5c : 97.30 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.32 +pb_1c : 97.32 +pb_5c : 97.30 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.33 +pb_1c : 97.33 +pb_5c : 97.30 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.34 +pb_1c : 97.34 +pb_5c : 97.30 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.35 +pb_1c : 97.35 +pb_5c : 97.35 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.36 +pb_1c : 97.36 +pb_5c : 97.35 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.37 +pb_1c : 97.37 +pb_5c : 97.35 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.38 +pb_1c : 97.38 +pb_5c : 97.35 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.39 +pb_1c : 97.39 +pb_5c : 97.35 +pb_10c : 97.30 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.40 +pb_1c : 97.40 +pb_5c : 97.40 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.41 +pb_1c : 97.41 +pb_5c : 97.40 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.42 +pb_1c : 97.42 +pb_5c : 97.40 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.43 +pb_1c : 97.43 +pb_5c : 97.40 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.44 +pb_1c : 97.44 +pb_5c : 97.40 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.45 +pb_1c : 97.45 +pb_5c : 97.45 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.46 +pb_1c : 97.46 +pb_5c : 97.45 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.47 +pb_1c : 97.47 +pb_5c : 97.45 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.48 +pb_1c : 97.48 +pb_5c : 97.45 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.49 +pb_1c : 97.49 +pb_5c : 97.45 +pb_10c : 97.40 +pb_25c : 97.25 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.50 +pb_1c : 97.50 +pb_5c : 97.50 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.51 +pb_1c : 97.51 +pb_5c : 97.50 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.52 +pb_1c : 97.52 +pb_5c : 97.50 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.53 +pb_1c : 97.53 +pb_5c : 97.50 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.54 +pb_1c : 97.54 +pb_5c : 97.50 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.55 +pb_1c : 97.55 +pb_5c : 97.55 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.56 +pb_1c : 97.56 +pb_5c : 97.55 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.57 +pb_1c : 97.57 +pb_5c : 97.55 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.58 +pb_1c : 97.58 +pb_5c : 97.55 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.59 +pb_1c : 97.59 +pb_5c : 97.55 +pb_10c : 97.50 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.60 +pb_1c : 97.60 +pb_5c : 97.60 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.61 +pb_1c : 97.61 +pb_5c : 97.60 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.62 +pb_1c : 97.62 +pb_5c : 97.60 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.63 +pb_1c : 97.63 +pb_5c : 97.60 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.64 +pb_1c : 97.64 +pb_5c : 97.60 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.65 +pb_1c : 97.65 +pb_5c : 97.65 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.66 +pb_1c : 97.66 +pb_5c : 97.65 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.67 +pb_1c : 97.67 +pb_5c : 97.65 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.68 +pb_1c : 97.68 +pb_5c : 97.65 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.69 +pb_1c : 97.69 +pb_5c : 97.65 +pb_10c : 97.60 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.70 +pb_1c : 97.70 +pb_5c : 97.70 +pb_10c : 97.70 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.71 +pb_1c : 97.71 +pb_5c : 97.70 +pb_10c : 97.70 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.72 +pb_1c : 97.72 +pb_5c : 97.70 +pb_10c : 97.70 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.73 +pb_1c : 97.73 +pb_5c : 97.70 +pb_10c : 97.70 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.74 +pb_1c : 97.74 +pb_5c : 97.70 +pb_10c : 97.70 +pb_25c : 97.50 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.75 +pb_1c : 97.75 +pb_5c : 97.75 +pb_10c : 97.70 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.76 +pb_1c : 97.76 +pb_5c : 97.75 +pb_10c : 97.70 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.77 +pb_1c : 97.77 +pb_5c : 97.75 +pb_10c : 97.70 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.78 +pb_1c : 97.78 +pb_5c : 97.75 +pb_10c : 97.70 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.79 +pb_1c : 97.79 +pb_5c : 97.75 +pb_10c : 97.70 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.80 +pb_1c : 97.80 +pb_5c : 97.80 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.81 +pb_1c : 97.81 +pb_5c : 97.80 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.82 +pb_1c : 97.82 +pb_5c : 97.80 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.83 +pb_1c : 97.83 +pb_5c : 97.80 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.84 +pb_1c : 97.84 +pb_5c : 97.80 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.85 +pb_1c : 97.85 +pb_5c : 97.85 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.86 +pb_1c : 97.86 +pb_5c : 97.85 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.87 +pb_1c : 97.87 +pb_5c : 97.85 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.88 +pb_1c : 97.88 +pb_5c : 97.85 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.89 +pb_1c : 97.89 +pb_5c : 97.85 +pb_10c : 97.80 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.90 +pb_1c : 97.90 +pb_5c : 97.90 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.91 +pb_1c : 97.91 +pb_5c : 97.90 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.92 +pb_1c : 97.92 +pb_5c : 97.90 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.93 +pb_1c : 97.93 +pb_5c : 97.90 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.94 +pb_1c : 97.94 +pb_5c : 97.90 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.95 +pb_1c : 97.95 +pb_5c : 97.95 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.96 +pb_1c : 97.96 +pb_5c : 97.95 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.97 +pb_1c : 97.97 +pb_5c : 97.95 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.98 +pb_1c : 97.98 +pb_5c : 97.95 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +97.99 +pb_1c : 97.99 +pb_5c : 97.95 +pb_10c : 97.90 +pb_25c : 97.75 +pb_1d : 97.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.00 +pb_1c : 98.00 +pb_5c : 98.00 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.01 +pb_1c : 98.01 +pb_5c : 98.00 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.02 +pb_1c : 98.02 +pb_5c : 98.00 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.03 +pb_1c : 98.03 +pb_5c : 98.00 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.04 +pb_1c : 98.04 +pb_5c : 98.00 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.05 +pb_1c : 98.05 +pb_5c : 98.05 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.06 +pb_1c : 98.06 +pb_5c : 98.05 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.07 +pb_1c : 98.07 +pb_5c : 98.05 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.08 +pb_1c : 98.08 +pb_5c : 98.05 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.09 +pb_1c : 98.09 +pb_5c : 98.05 +pb_10c : 98.00 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.10 +pb_1c : 98.10 +pb_5c : 98.10 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.11 +pb_1c : 98.11 +pb_5c : 98.10 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.12 +pb_1c : 98.12 +pb_5c : 98.10 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.13 +pb_1c : 98.13 +pb_5c : 98.10 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.14 +pb_1c : 98.14 +pb_5c : 98.10 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.15 +pb_1c : 98.15 +pb_5c : 98.15 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.16 +pb_1c : 98.16 +pb_5c : 98.15 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.17 +pb_1c : 98.17 +pb_5c : 98.15 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.18 +pb_1c : 98.18 +pb_5c : 98.15 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.19 +pb_1c : 98.19 +pb_5c : 98.15 +pb_10c : 98.10 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.20 +pb_1c : 98.20 +pb_5c : 98.20 +pb_10c : 98.20 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.21 +pb_1c : 98.21 +pb_5c : 98.20 +pb_10c : 98.20 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.22 +pb_1c : 98.22 +pb_5c : 98.20 +pb_10c : 98.20 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.23 +pb_1c : 98.23 +pb_5c : 98.20 +pb_10c : 98.20 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.24 +pb_1c : 98.24 +pb_5c : 98.20 +pb_10c : 98.20 +pb_25c : 98.00 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.25 +pb_1c : 98.25 +pb_5c : 98.25 +pb_10c : 98.20 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.26 +pb_1c : 98.26 +pb_5c : 98.25 +pb_10c : 98.20 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.27 +pb_1c : 98.27 +pb_5c : 98.25 +pb_10c : 98.20 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.28 +pb_1c : 98.28 +pb_5c : 98.25 +pb_10c : 98.20 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.29 +pb_1c : 98.29 +pb_5c : 98.25 +pb_10c : 98.20 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.30 +pb_1c : 98.30 +pb_5c : 98.30 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.31 +pb_1c : 98.31 +pb_5c : 98.30 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.32 +pb_1c : 98.32 +pb_5c : 98.30 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.33 +pb_1c : 98.33 +pb_5c : 98.30 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.34 +pb_1c : 98.34 +pb_5c : 98.30 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.35 +pb_1c : 98.35 +pb_5c : 98.35 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.36 +pb_1c : 98.36 +pb_5c : 98.35 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.37 +pb_1c : 98.37 +pb_5c : 98.35 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.38 +pb_1c : 98.38 +pb_5c : 98.35 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.39 +pb_1c : 98.39 +pb_5c : 98.35 +pb_10c : 98.30 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.40 +pb_1c : 98.40 +pb_5c : 98.40 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.41 +pb_1c : 98.41 +pb_5c : 98.40 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.42 +pb_1c : 98.42 +pb_5c : 98.40 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.43 +pb_1c : 98.43 +pb_5c : 98.40 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.44 +pb_1c : 98.44 +pb_5c : 98.40 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.45 +pb_1c : 98.45 +pb_5c : 98.45 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.46 +pb_1c : 98.46 +pb_5c : 98.45 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.47 +pb_1c : 98.47 +pb_5c : 98.45 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.48 +pb_1c : 98.48 +pb_5c : 98.45 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.49 +pb_1c : 98.49 +pb_5c : 98.45 +pb_10c : 98.40 +pb_25c : 98.25 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.50 +pb_1c : 98.50 +pb_5c : 98.50 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.51 +pb_1c : 98.51 +pb_5c : 98.50 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.52 +pb_1c : 98.52 +pb_5c : 98.50 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.53 +pb_1c : 98.53 +pb_5c : 98.50 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.54 +pb_1c : 98.54 +pb_5c : 98.50 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.55 +pb_1c : 98.55 +pb_5c : 98.55 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.56 +pb_1c : 98.56 +pb_5c : 98.55 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.57 +pb_1c : 98.57 +pb_5c : 98.55 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.58 +pb_1c : 98.58 +pb_5c : 98.55 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.59 +pb_1c : 98.59 +pb_5c : 98.55 +pb_10c : 98.50 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.60 +pb_1c : 98.60 +pb_5c : 98.60 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.61 +pb_1c : 98.61 +pb_5c : 98.60 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.62 +pb_1c : 98.62 +pb_5c : 98.60 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.63 +pb_1c : 98.63 +pb_5c : 98.60 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.64 +pb_1c : 98.64 +pb_5c : 98.60 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.65 +pb_1c : 98.65 +pb_5c : 98.65 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.66 +pb_1c : 98.66 +pb_5c : 98.65 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.67 +pb_1c : 98.67 +pb_5c : 98.65 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.68 +pb_1c : 98.68 +pb_5c : 98.65 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.69 +pb_1c : 98.69 +pb_5c : 98.65 +pb_10c : 98.60 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.70 +pb_1c : 98.70 +pb_5c : 98.70 +pb_10c : 98.70 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.71 +pb_1c : 98.71 +pb_5c : 98.70 +pb_10c : 98.70 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.72 +pb_1c : 98.72 +pb_5c : 98.70 +pb_10c : 98.70 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.73 +pb_1c : 98.73 +pb_5c : 98.70 +pb_10c : 98.70 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.74 +pb_1c : 98.74 +pb_5c : 98.70 +pb_10c : 98.70 +pb_25c : 98.50 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.75 +pb_1c : 98.75 +pb_5c : 98.75 +pb_10c : 98.70 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.76 +pb_1c : 98.76 +pb_5c : 98.75 +pb_10c : 98.70 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.77 +pb_1c : 98.77 +pb_5c : 98.75 +pb_10c : 98.70 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.78 +pb_1c : 98.78 +pb_5c : 98.75 +pb_10c : 98.70 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.79 +pb_1c : 98.79 +pb_5c : 98.75 +pb_10c : 98.70 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.80 +pb_1c : 98.80 +pb_5c : 98.80 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.81 +pb_1c : 98.81 +pb_5c : 98.80 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.82 +pb_1c : 98.82 +pb_5c : 98.80 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.83 +pb_1c : 98.83 +pb_5c : 98.80 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.84 +pb_1c : 98.84 +pb_5c : 98.80 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.85 +pb_1c : 98.85 +pb_5c : 98.85 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.86 +pb_1c : 98.86 +pb_5c : 98.85 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.87 +pb_1c : 98.87 +pb_5c : 98.85 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.88 +pb_1c : 98.88 +pb_5c : 98.85 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.89 +pb_1c : 98.89 +pb_5c : 98.85 +pb_10c : 98.80 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.90 +pb_1c : 98.90 +pb_5c : 98.90 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.91 +pb_1c : 98.91 +pb_5c : 98.90 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.92 +pb_1c : 98.92 +pb_5c : 98.90 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.93 +pb_1c : 98.93 +pb_5c : 98.90 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.94 +pb_1c : 98.94 +pb_5c : 98.90 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.95 +pb_1c : 98.95 +pb_5c : 98.95 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.96 +pb_1c : 98.96 +pb_5c : 98.95 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.97 +pb_1c : 98.97 +pb_5c : 98.95 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.98 +pb_1c : 98.98 +pb_5c : 98.95 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +98.99 +pb_1c : 98.99 +pb_5c : 98.95 +pb_10c : 98.90 +pb_25c : 98.75 +pb_1d : 98.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.00 +pb_1c : 99.00 +pb_5c : 99.00 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.01 +pb_1c : 99.01 +pb_5c : 99.00 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.02 +pb_1c : 99.02 +pb_5c : 99.00 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.03 +pb_1c : 99.03 +pb_5c : 99.00 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.04 +pb_1c : 99.04 +pb_5c : 99.00 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.05 +pb_1c : 99.05 +pb_5c : 99.05 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.06 +pb_1c : 99.06 +pb_5c : 99.05 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.07 +pb_1c : 99.07 +pb_5c : 99.05 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.08 +pb_1c : 99.08 +pb_5c : 99.05 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.09 +pb_1c : 99.09 +pb_5c : 99.05 +pb_10c : 99.00 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.10 +pb_1c : 99.10 +pb_5c : 99.10 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.11 +pb_1c : 99.11 +pb_5c : 99.10 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.12 +pb_1c : 99.12 +pb_5c : 99.10 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.13 +pb_1c : 99.13 +pb_5c : 99.10 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.14 +pb_1c : 99.14 +pb_5c : 99.10 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.15 +pb_1c : 99.15 +pb_5c : 99.15 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.16 +pb_1c : 99.16 +pb_5c : 99.15 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.17 +pb_1c : 99.17 +pb_5c : 99.15 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.18 +pb_1c : 99.18 +pb_5c : 99.15 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.19 +pb_1c : 99.19 +pb_5c : 99.15 +pb_10c : 99.10 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.20 +pb_1c : 99.20 +pb_5c : 99.20 +pb_10c : 99.20 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.21 +pb_1c : 99.21 +pb_5c : 99.20 +pb_10c : 99.20 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.22 +pb_1c : 99.22 +pb_5c : 99.20 +pb_10c : 99.20 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.23 +pb_1c : 99.23 +pb_5c : 99.20 +pb_10c : 99.20 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.24 +pb_1c : 99.24 +pb_5c : 99.20 +pb_10c : 99.20 +pb_25c : 99.00 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.25 +pb_1c : 99.25 +pb_5c : 99.25 +pb_10c : 99.20 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.26 +pb_1c : 99.26 +pb_5c : 99.25 +pb_10c : 99.20 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.27 +pb_1c : 99.27 +pb_5c : 99.25 +pb_10c : 99.20 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.28 +pb_1c : 99.28 +pb_5c : 99.25 +pb_10c : 99.20 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.29 +pb_1c : 99.29 +pb_5c : 99.25 +pb_10c : 99.20 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.30 +pb_1c : 99.30 +pb_5c : 99.30 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.31 +pb_1c : 99.31 +pb_5c : 99.30 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.32 +pb_1c : 99.32 +pb_5c : 99.30 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.33 +pb_1c : 99.33 +pb_5c : 99.30 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.34 +pb_1c : 99.34 +pb_5c : 99.30 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.35 +pb_1c : 99.35 +pb_5c : 99.35 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.36 +pb_1c : 99.36 +pb_5c : 99.35 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.37 +pb_1c : 99.37 +pb_5c : 99.35 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.38 +pb_1c : 99.38 +pb_5c : 99.35 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.39 +pb_1c : 99.39 +pb_5c : 99.35 +pb_10c : 99.30 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.40 +pb_1c : 99.40 +pb_5c : 99.40 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.41 +pb_1c : 99.41 +pb_5c : 99.40 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.42 +pb_1c : 99.42 +pb_5c : 99.40 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.43 +pb_1c : 99.43 +pb_5c : 99.40 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.44 +pb_1c : 99.44 +pb_5c : 99.40 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.45 +pb_1c : 99.45 +pb_5c : 99.45 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.46 +pb_1c : 99.46 +pb_5c : 99.45 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.47 +pb_1c : 99.47 +pb_5c : 99.45 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.48 +pb_1c : 99.48 +pb_5c : 99.45 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.49 +pb_1c : 99.49 +pb_5c : 99.45 +pb_10c : 99.40 +pb_25c : 99.25 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.50 +pb_1c : 99.50 +pb_5c : 99.50 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.51 +pb_1c : 99.51 +pb_5c : 99.50 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.52 +pb_1c : 99.52 +pb_5c : 99.50 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.53 +pb_1c : 99.53 +pb_5c : 99.50 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.54 +pb_1c : 99.54 +pb_5c : 99.50 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.55 +pb_1c : 99.55 +pb_5c : 99.55 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.56 +pb_1c : 99.56 +pb_5c : 99.55 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.57 +pb_1c : 99.57 +pb_5c : 99.55 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.58 +pb_1c : 99.58 +pb_5c : 99.55 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.59 +pb_1c : 99.59 +pb_5c : 99.55 +pb_10c : 99.50 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.60 +pb_1c : 99.60 +pb_5c : 99.60 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.61 +pb_1c : 99.61 +pb_5c : 99.60 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.62 +pb_1c : 99.62 +pb_5c : 99.60 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.63 +pb_1c : 99.63 +pb_5c : 99.60 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.64 +pb_1c : 99.64 +pb_5c : 99.60 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.65 +pb_1c : 99.65 +pb_5c : 99.65 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.66 +pb_1c : 99.66 +pb_5c : 99.65 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.67 +pb_1c : 99.67 +pb_5c : 99.65 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.68 +pb_1c : 99.68 +pb_5c : 99.65 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.69 +pb_1c : 99.69 +pb_5c : 99.65 +pb_10c : 99.60 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.70 +pb_1c : 99.70 +pb_5c : 99.70 +pb_10c : 99.70 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.71 +pb_1c : 99.71 +pb_5c : 99.70 +pb_10c : 99.70 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.72 +pb_1c : 99.72 +pb_5c : 99.70 +pb_10c : 99.70 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.73 +pb_1c : 99.73 +pb_5c : 99.70 +pb_10c : 99.70 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.74 +pb_1c : 99.74 +pb_5c : 99.70 +pb_10c : 99.70 +pb_25c : 99.50 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.75 +pb_1c : 99.75 +pb_5c : 99.75 +pb_10c : 99.70 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.76 +pb_1c : 99.76 +pb_5c : 99.75 +pb_10c : 99.70 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.77 +pb_1c : 99.77 +pb_5c : 99.75 +pb_10c : 99.70 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.78 +pb_1c : 99.78 +pb_5c : 99.75 +pb_10c : 99.70 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.79 +pb_1c : 99.79 +pb_5c : 99.75 +pb_10c : 99.70 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.80 +pb_1c : 99.80 +pb_5c : 99.80 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.81 +pb_1c : 99.81 +pb_5c : 99.80 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.82 +pb_1c : 99.82 +pb_5c : 99.80 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.83 +pb_1c : 99.83 +pb_5c : 99.80 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.84 +pb_1c : 99.84 +pb_5c : 99.80 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.85 +pb_1c : 99.85 +pb_5c : 99.85 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.86 +pb_1c : 99.86 +pb_5c : 99.85 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.87 +pb_1c : 99.87 +pb_5c : 99.85 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.88 +pb_1c : 99.88 +pb_5c : 99.85 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.89 +pb_1c : 99.89 +pb_5c : 99.85 +pb_10c : 99.80 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.90 +pb_1c : 99.90 +pb_5c : 99.90 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.91 +pb_1c : 99.91 +pb_5c : 99.90 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.92 +pb_1c : 99.92 +pb_5c : 99.90 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.93 +pb_1c : 99.93 +pb_5c : 99.90 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.94 +pb_1c : 99.94 +pb_5c : 99.90 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.95 +pb_1c : 99.95 +pb_5c : 99.95 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.96 +pb_1c : 99.96 +pb_5c : 99.95 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.97 +pb_1c : 99.97 +pb_5c : 99.95 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.98 +pb_1c : 99.98 +pb_5c : 99.95 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + +99.99 +pb_1c : 99.99 +pb_5c : 99.95 +pb_10c : 99.90 +pb_25c : 99.75 +pb_1d : 99.00 +pb_5d : 95.00 +pb_10d : 90.00 + diff --git a/sdk/PrebidMobileTests/Resources/pbs_request.json b/sdk/PrebidMobileTests/Resources/pbs_request.json new file mode 100644 index 000000000..03720dbba --- /dev/null +++ b/sdk/PrebidMobileTests/Resources/pbs_request.json @@ -0,0 +1,36 @@ +{ + "device":{ + "make":"Apple", + "ua":"Mozilla\/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit\/602.1.50 (KHTML, like Gecko) Mobile\/14A345", + "devtime":1495477815, + "connectiontype":1, + "model":"x86_64", + "ifa":"27FB28C2-6821-49C1-9959-D315A1090A6E", + "lmt":0 + }, + "user":{ + "gender":0, + "language":"en" + }, + "prebid_version":"0.21.0-pre", + "app":{ + "bundle":"AppNexus.PrebidMobileDemo" + }, + "ad_units":[ + { + "sizes":[ + { + "w":300, + "h":250 + } + ], + "config_id":"0b33e7ae-cf61-4003-8404-0711eea6e673", + "code":"HomeScreen" + } + ], + "cache_markup":1, + "sort_bids":1, + "max_key_length":20, + "tid":"F3740584-220F-49F7-805C-A4845F22F400", + "account_id":"aecd6ef7-b992-4e99-9bb8-65e2d984e1dd" +} diff --git a/sdk/PrebidMobileTests/Resources/pbs_response.json b/sdk/PrebidMobileTests/Resources/pbs_response.json new file mode 100644 index 000000000..b26c1f271 --- /dev/null +++ b/sdk/PrebidMobileTests/Resources/pbs_response.json @@ -0,0 +1,37 @@ +{ + "tid":"F3740584-220F-49F7-805C-A4845F22F400", + "status":"OK", + "bidder_status":[ + { + "bidder":"appnexus", + "response_time_ms":27, + "num_bids":1 + }, + { + "bidder":"indexExchange", + "ad_unit":"HomeScreen", + "error":"Index doesn't support apps" + }, + { + "bidder":"pubmatic", + "response_time_ms":33, + "no_bid":true + }, + { + "bidder":"rubicon", + "response_time_ms":113 + } + ], + "bids":[ + { + "bid_id":"18e07dee61047f", + "code":"HomeScreen", + "creative_id":"29681110", + "bidder":"appnexus", + "price":0.5, + "width":300, + "height":250, + "cache_id":"2071cf11-085e-4c3c-9eb7-505341634676" + } + ] +} diff --git a/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.h b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.h new file mode 100644 index 000000000..06fc48367 --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.h @@ -0,0 +1,23 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +extern NSString *const kANHTTPStubURLProtocolRequestDidLoadNotification; +extern NSString *const kANHTTPStubURLProtocolRequest; + +@interface ANHTTPStubURLProtocol : NSURLProtocol + +@end diff --git a/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.m b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.m new file mode 100644 index 000000000..d22046e8e --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubURLProtocol.m @@ -0,0 +1,100 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANHTTPStubURLProtocol.h" +#import "ANHTTPStubbingManager.h" + +static NSString *const kANTestHTTPStubURLProtocolExceptionKey = @"ANTestHTTPStubURLProtocolException"; +NSString *const kANHTTPStubURLProtocolRequestDidLoadNotification = @"ANHTTPStubURLProtocolRequestDidLoad"; +NSString *const kANHTTPStubURLProtocolRequest = @"ANHTTPStubURLProtocolRequest"; + +@implementation ANHTTPStubURLProtocol + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request { + BOOL broadcastRequests = [ANHTTPStubbingManager sharedStubbingManager].broadcastRequests; + if (broadcastRequests && request) { + [[NSNotificationCenter defaultCenter] postNotificationName:kANHTTPStubURLProtocolRequestDidLoadNotification + object:nil + userInfo:@{kANHTTPStubURLProtocolRequest: request}]; + } + BOOL isHttpOrHttps = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"]; + if (!isHttpOrHttps) { + return NO; + } + BOOL ignoreUnstubbedRequests = [ANHTTPStubbingManager sharedStubbingManager].ignoreUnstubbedRequests; + if (ignoreUnstubbedRequests) { + ANURLConnectionStub *stub = [[ANHTTPStubbingManager sharedStubbingManager] stubForURLString:request.URL.absoluteString]; + return (stub != nil); + } else { + return YES; + } +} + ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { + return request; +} + ++ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b { + return NO; +} + +- (void)startLoading { + id client = self.client; + ANURLConnectionStub *stub = [self stubForRequest]; + if (stub) { + NSURLResponse *response = [self buildResponseForRequestUsingStub:stub]; + [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + NSData *responseData = [self buildDataForRequestUsingStub:stub]; + [client URLProtocol:self didLoadData:responseData]; + [client URLProtocolDidFinishLoading:self]; + NSLog(@"Successfully loaded request from stub: %@", [self request]); + } else { + NSLog(@"Could not load request successfully: %@", [self request]); + NSLog(@"This can happen if the request was not stubbed, or if the stubs were removed before this request was completed (due to asynchronous request loading)."); + [client URLProtocol:self + didFailWithError:[NSError errorWithDomain:kANTestHTTPStubURLProtocolExceptionKey + code:1 + userInfo:nil]]; + } +} + +- (void)stopLoading { + // Do nothing, but method is required. +} + +#pragma mark - Stubbing + +- (ANURLConnectionStub *)stubForRequest { + return [[ANHTTPStubbingManager sharedStubbingManager] stubForURLString:self.request.URL.absoluteString]; +} + +- (NSURLResponse *)buildResponseForRequestUsingStub:(ANURLConnectionStub *)stub { + NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] + statusCode:stub.responseCode + HTTPVersion:@"HTTP/1.1" + headerFields:@{}]; + return httpResponse; +} + +- (NSData *)buildDataForRequestUsingStub:(ANURLConnectionStub *)stub { + if ([stub.responseBody isKindOfClass:[NSString class]]) { + return [stub.responseBody dataUsingEncoding:NSUTF8StringEncoding]; + } else if ([stub.responseBody isKindOfClass:[NSData class]]) { + return stub.responseBody; + } + return nil; +} + +@end diff --git a/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.h b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.h new file mode 100644 index 000000000..3f59e8d14 --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.h @@ -0,0 +1,49 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANHTTPStubURLProtocol.h" +#import "ANURLConnectionStub.h" + +@interface ANHTTPStubbingManager : NSObject + ++ (ANHTTPStubbingManager *)sharedStubbingManager; + +- (void)enable; +- (void)disable; + +- (void)addStub:(ANURLConnectionStub *)stub; +- (void)addStubs:(NSArray *)stubs; +- (void)removeAllStubs; + +- (ANURLConnectionStub *)stubForURLString:(NSString *)URLString; + +/** + If set to YES, then unstubbed requests will be ignored by this class and handled by the system. + If set to NO (default), then unstubbed requests will result in didFailToLoad errors. + + Default is NO. + */ +@property (nonatomic) BOOL ignoreUnstubbedRequests; + +/** + If set to YES, then all requests which trigger canInitWithRequest: will be broadcast + as kANHTTPStubURLProtocolRequestDidLoadNotification notifications. The request will be in the user info, + as the value of the kANHTTPStubURLProtocolRequest key. + + Default is NO. + */ +@property (nonatomic) BOOL broadcastRequests; + +@end diff --git a/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.m b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.m new file mode 100644 index 000000000..9b39bde7b --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANHTTPStubbingManager.m @@ -0,0 +1,82 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANHTTPStubbingManager.h" +#import "ANHTTPStubURLProtocol.h" + +@interface ANHTTPStubbingManager () +@property (nonatomic) NSMutableArray *stubs; +@end + +@implementation ANHTTPStubbingManager + ++ (ANHTTPStubbingManager *)sharedStubbingManager { + static dispatch_once_t sharedStubbingManagerToken; + static ANHTTPStubbingManager *manager; + dispatch_once(&sharedStubbingManagerToken, ^{ + manager = [[ANHTTPStubbingManager alloc] init]; + }); + return manager; +} + +- (void)enable { + [NSURLProtocol registerClass:[ANHTTPStubURLProtocol class]]; +} + +- (void)disable { + [NSURLProtocol unregisterClass:[ANHTTPStubURLProtocol class]]; +} + +- (void)addStub:(ANURLConnectionStub *)stub { + [self.stubs addObject:stub]; +} + +- (void)addStubs:(NSArray *)stubs { + [self.stubs addObjectsFromArray:stubs]; +} + +- (void)removeAllStubs { + [self.stubs removeAllObjects]; +} + +- (NSMutableArray *)stubs { + @synchronized(self) { + if (!_stubs) + _stubs = [[NSMutableArray alloc] init]; + return _stubs; + } +} + +- (ANURLConnectionStub *)stubForURLString:(NSString *)URLString { + NSString *requestURLString = URLString; + NSArray *stubArray = self.stubs; + __block ANURLConnectionStub *stubMatch = nil; + [stubArray enumerateObjectsUsingBlock:^(ANURLConnectionStub *stub, NSUInteger idx, BOOL *stop) { + NSString *stubRequestURLString = stub.requestURLRegexPatternString; + NSError *error; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:stubRequestURLString + options:NSRegularExpressionDotMatchesLineSeparators + error:&error]; + if ([regex numberOfMatchesInString:requestURLString + options:0 + range:NSMakeRange(0, [requestURLString length])]) { + stubMatch = stub; + *stop = YES; + } + }]; + return stubMatch; +} + +@end diff --git a/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.h b/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.h new file mode 100644 index 000000000..087464ed1 --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.h @@ -0,0 +1,41 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface ANURLConnectionStub : NSObject + +@property (nonatomic, readwrite, strong) NSString *requestURLRegexPatternString; +@property (nonatomic, readwrite, assign) NSInteger responseCode; +@property (nonatomic, readwrite, strong) id responseBody; //can be nsstring or nsdata + ++ (ANURLConnectionStub *)stubForPreBidMobileBannerWithAdSize:(CGSize)adSize + uuid:(NSString *)uuid; ++ (ANURLConnectionStub *)stubForPreBidMobileInterstitialWithUUID:(NSString *)uuid; ++ (ANURLConnectionStub *)stubForPreBidMobileNoBid; + ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type; ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type + withRequestURLRegexPatternString:(NSString *)pattern; ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type + withRequestURLRegexPatternString:(NSString *)pattern + inBundle:(NSBundle *)bundle; + ++ (ANURLConnectionStub *)stubForMraidFile; + +@end diff --git a/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.m b/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.m new file mode 100644 index 000000000..87f61e68c --- /dev/null +++ b/sdk/PrebidMobileTests/Stubbing/ANURLConnectionStub.m @@ -0,0 +1,169 @@ +/* Copyright 2014 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "ANURLConnectionStub.h" + +@implementation ANURLConnectionStub + +- (id)copyWithZone:(NSZone *)zone { + ANURLConnectionStub *newStub = [[ANURLConnectionStub alloc] init]; + newStub.requestURLRegexPatternString = self.requestURLRegexPatternString; + newStub.responseCode = self.responseCode; + newStub.responseBody = self.responseBody; + return newStub; +} + +- (BOOL)isEqual:(ANURLConnectionStub *)object { + BOOL sameRequestURLString = [self.requestURLRegexPatternString isEqualToString:object.requestURLRegexPatternString]; + BOOL sameResponseCode = self.responseCode = object.responseCode; + BOOL sameResponseBody = [self.responseBody isEqualToString:object.responseBody]; + return sameRequestURLString && sameResponseBody && sameResponseCode; +} + +- (NSUInteger)hash { + NSMutableString *description = [[NSMutableString alloc] init]; + [description appendString:self.requestURLRegexPatternString]; + [description appendString:[NSString stringWithFormat:@"%ld", (long)self.responseCode]]; + [description appendString:self.responseBody]; + return [description hash]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"NSURLConnectionStub: \n\ + Request URL Pattern: %@,\n\ + Response Code: %ld,\n\ + Response Body: %@", + self.requestURLRegexPatternString, (long)self.responseCode, self.responseBody]; +} + +#pragma mark - Pre-Initialized Stubbers + ++ (ANURLConnectionStub *)stubForPreBidMobileBannerWithAdSize:(CGSize)adSize + uuid:(NSString *)uuid { + ANURLConnectionStub *stub = [[ANURLConnectionStub alloc] init]; + stub.requestURLRegexPatternString = [NSString stringWithFormat:@"https://mobile.adnxs.com/ut/v1"]; + stub.responseCode = 200; + stub.responseBody = [NSJSONSerialization dataWithJSONObject:[[self class] responseForStandardBannerWithAdSize:adSize uuid:uuid] + options:0 + error:nil]; + return stub; +} + ++ (ANURLConnectionStub *)stubForPreBidMobileInterstitialWithUUID:(NSString *)uuid { + ANURLConnectionStub *stub = [[ANURLConnectionStub alloc] init]; + stub.requestURLRegexPatternString = [NSString stringWithFormat:@"https://mobile.adnxs.com/ut/v1"]; + stub.responseCode = 200; + stub.responseBody = [NSJSONSerialization dataWithJSONObject:[[self class] responseForStandardInterstitialWithUUID:uuid] + options:0 + error:nil]; + return stub; +} + ++ (ANURLConnectionStub *)stubForPreBidMobileNoBid { + ANURLConnectionStub *stub = [[ANURLConnectionStub alloc] init]; + stub.requestURLRegexPatternString = [NSString stringWithFormat:@"https://mobile.adnxs.com/ut/v1"]; + stub.responseCode = 200; + stub.responseBody = [NSJSONSerialization dataWithJSONObject:[[self class] responseForNoBid] + options:0 + error:nil]; + return stub; +} + ++ (ANURLConnectionStub *)stubForMraidFile { + ANURLConnectionStub *stub = [[ANURLConnectionStub alloc] init]; + stub.requestURLRegexPatternString = [@"http://mediation.adnxs.com/" stringByAppendingString:@"mraid.js"]; + stub.responseBody = @""; + stub.responseCode = 200; + return stub; +} + ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type { + return [ANURLConnectionStub stubForResource:resource + ofType:type + withRequestURLRegexPatternString:resource + inBundle:[NSBundle mainBundle]]; +} + ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type + withRequestURLRegexPatternString:(NSString *)pattern { + return [ANURLConnectionStub stubForResource:resource + ofType:type + withRequestURLRegexPatternString:pattern + inBundle:[NSBundle mainBundle]]; +} + ++ (ANURLConnectionStub *)stubForResource:(NSString *)resource + ofType:(NSString *)type + withRequestURLRegexPatternString:(NSString *)pattern + inBundle:(NSBundle *)bundle { + ANURLConnectionStub *stub = [[ANURLConnectionStub alloc] init]; + stub.responseCode = 200; + stub.requestURLRegexPatternString = pattern; + stub.responseBody = [NSData dataWithContentsOfFile:[bundle pathForResource:resource + ofType:type]]; + return stub; +} + ++ (NSDictionary *)responseForNoBid { + NSMutableDictionary *response = [[NSMutableDictionary alloc] init]; + response[@"status"] = @"ok"; + NSMutableDictionary *adElement = [[NSMutableDictionary alloc] init]; + adElement[@"nobid"] = @"1"; + response[@"tags"] = @[[adElement copy]]; + return [response copy]; +} + ++ (NSDictionary *)responseForStandardInterstitialWithUUID:(NSString *)uuid { + NSMutableDictionary *response = [[NSMutableDictionary alloc] init]; + response[@"status"] = @"ok"; + NSDictionary *adElement = [[self class] adElementForAdType:@"banner" + adSize:CGSizeMake(320.0, 480.0) + uuid:uuid]; + response[@"tags"] = @[adElement]; + return [response copy]; +} + ++ (NSDictionary *)responseForStandardBannerWithAdSize:(CGSize)adSize + uuid:(NSString *)uuid { + NSMutableDictionary *response = [[NSMutableDictionary alloc] init]; + response[@"status"] = @"ok"; + NSDictionary *adElement = [[self class] adElementForAdType:@"banner" + adSize:adSize + uuid:uuid]; + response[@"tags"] = @[adElement]; + return [response copy]; +} + ++ (NSDictionary *)adElementForAdType:(NSString *)type + adSize:(CGSize)adSize + uuid:(NSString *)uuid { + NSMutableDictionary *widthHeightForBanner = [[NSMutableDictionary alloc] init]; + widthHeightForBanner[@"width"] = [@(adSize.width) description]; + widthHeightForBanner[@"height"] = [@(adSize.height) description]; + + NSMutableDictionary *adElement = [[NSMutableDictionary alloc] init]; + adElement[@"banner"] = widthHeightForBanner; + adElement[@"cpm"] = @"1.15"; + + NSMutableDictionary *adElementWrapper = [[NSMutableDictionary alloc] init]; + adElementWrapper[@"ad"] = adElement; + adElementWrapper[@"uuid"] = uuid; + adElementWrapper[@"ut_url"] = @"http://appenxus.com"; + return [adElementWrapper copy]; +} + +@end diff --git a/sdk/PrebidServerAdapter/PBServerAdapter.h b/sdk/PrebidServerAdapter/PBServerAdapter.h new file mode 100644 index 000000000..72b90ebb1 --- /dev/null +++ b/sdk/PrebidServerAdapter/PBServerAdapter.h @@ -0,0 +1,27 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import +#import "PBAdUnit.h" +#import "PBBidResponseDelegate.h" + +@interface PBServerAdapter : NSObject + +- (nonnull instancetype)initWithAccountId:(nonnull NSString *)accountId; + +- (void)requestBidsWithAdUnits:(nullable NSArray *)adUnits + withDelegate:(nonnull id)delegate; + +@end diff --git a/sdk/PrebidServerAdapter/PBServerAdapter.m b/sdk/PrebidServerAdapter/PBServerAdapter.m new file mode 100644 index 000000000..a8b18efa2 --- /dev/null +++ b/sdk/PrebidServerAdapter/PBServerAdapter.m @@ -0,0 +1,308 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBBidResponse.h" +#import "PBBidResponseDelegate.h" +#import "PBLogging.h" +#import "PBServerAdapter.h" +#import "PBServerFetcher.h" +#import "PBServerGlobal.h" +#import "PBServerLocation.h" +#import "PBServerReachability.h" +#import "PBTargetingParams.h" +#import +#import +#import +#import +#import + +static NSString *const kAPNAdServerResponseKeyNoBid = @"nobid"; +static NSString *const kAPNAdServerResponseKeyUUID = @"uuid"; +static NSString *const kPrebidMobileVersion = @"0.0.1"; + +@interface PBServerAdapter () + +@property (nonatomic, strong) NSString *accountId; + +@end + +@implementation PBServerAdapter + +- (nonnull instancetype)initWithAccountId:(nonnull NSString *)accountId { + if (self = [super init]) { + _accountId = accountId; + } + return self; +} + +- (void)requestBidsWithAdUnits:(nullable NSArray *)adUnits + withDelegate:(nonnull id)delegate { + NSURLRequest *request = [self buildRequestForAdUnits:adUnits]; + [[PBServerFetcher sharedInstance] makeBidRequest:request withCompletionHandler:^(NSDictionary *adUnitToBidsMap, NSError *error) { + if (error) { + [delegate didCompleteWithError:error]; + return; + } + for (NSString *adUnitId in [adUnitToBidsMap allKeys]) { + NSArray *bidsArray = (NSArray *)[adUnitToBidsMap objectForKey:adUnitId]; + NSMutableArray *bidResponsesArray = [[NSMutableArray alloc] init]; + for (NSDictionary *bid in bidsArray) { + PBBidResponse *bidResponse = [PBBidResponse bidResponseWithAdUnitId:adUnitId adServerTargeting:bid[@"ad_server_targeting"]]; + PBLogDebug(@"Bid Successful with rounded bid targeting keys are %@ for adUnit id is %@", bidResponse.customKeywords, adUnitId); + [bidResponsesArray addObject:bidResponse]; + } + [delegate didReceiveSuccessResponse:bidResponsesArray]; + } + }]; +} + +- (NSURLRequest *)buildRequestForAdUnits:(NSArray *)adUnits { + NSURL *url = [NSURL URLWithString:@"https://prebid.adnxs.com/pbs/v1/auction"]; + NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:1000]; + [mutableRequest setHTTPMethod:@"POST"]; + NSError *error; + NSData *postData = [NSJSONSerialization dataWithJSONObject:[self requestBodyForAdUnits:adUnits] + options:kNilOptions + error:&error]; + if (!error) { + [mutableRequest setHTTPBody:postData]; + return [mutableRequest copy]; + } else { + return nil; + } +} + +- (NSDictionary *)requestBodyForAdUnits:(NSArray *)adUnits { + NSMutableDictionary *requestDict = [[NSMutableDictionary alloc] init]; + + requestDict[@"cache_markup"] = @(1); + requestDict[@"sort_bids"] = @(1); + // need this so DFP targeting keys aren't too long + requestDict[@"max_key_length"] = @(20); + requestDict[@"account_id"] = self.accountId; + requestDict[@"tid"] = [[NSUUID UUID] UUIDString]; + requestDict[@"prebid_version"] = @"0.21.0-pre"; + + requestDict[@"sdk"] = @{@"source": @"prebid-mobile", + @"version": kPrebidMobileVersion, + @"platform": @"iOS"}; + + NSDictionary *user = [self user]; + if (user) { + requestDict[@"user"] = user; + } + NSDictionary *device = [self device]; + if (device) { + requestDict[@"device"] = device; + } + NSDictionary *appID = [self app]; + if (appID != nil) { + requestDict[@"app"] = appID; + } + NSArray *keywords = [self keywords]; + if (keywords) { + requestDict[@"keywords"] = keywords; + } + + NSMutableArray *adUnitConfigs = [[NSMutableArray alloc] init]; + for (PBAdUnit *adUnit in adUnits) { + NSMutableDictionary *adUnitConfig = [[NSMutableDictionary alloc] init]; + adUnitConfig[@"code"] = adUnit.identifier; + + NSMutableArray *sizeArray = [[NSMutableArray alloc] initWithCapacity:adUnit.adSizes.count]; + for (id size in adUnit.adSizes) { + CGSize arSize = [size CGSizeValue]; + NSDictionary *sizeDict = [NSDictionary dictionaryWithObjectsAndKeys:@(arSize.width), @"w", @(arSize.height), @"h", nil]; + [sizeArray addObject:sizeDict]; + } + adUnitConfig[@"sizes"] = sizeArray; + + adUnitConfig[@"config_id"] = adUnit.configId; + [adUnitConfigs addObject:adUnitConfig]; + } + requestDict[@"ad_units"] = adUnitConfigs; + + return [requestDict copy]; +} + +- (NSDictionary *)user { + NSMutableDictionary *userDict = [[NSMutableDictionary alloc] init]; + + NSInteger ageValue = [[PBTargetingParams sharedInstance] age]; + if (ageValue > 0) { + userDict[@"age"] = @(ageValue); + } + + PBTargetingParamsGender genderValue = [[PBTargetingParams sharedInstance] gender]; + NSUInteger gender; + switch (genderValue) { + case PBTargetingParamsGenderMale: + gender = 1; + break; + case PBTargetingParamsGenderFemale: + gender = 2; + break; + default: + gender = 0; + break; + } + userDict[@"gender"] = @(gender); + + NSString *language = [NSLocale preferredLanguages][0]; + if (language.length) { + userDict[@"language"] = language; + } + + return [userDict copy]; +} + +- (NSArray *)keywords { + NSDictionary *customKeywords = [[PBTargetingParams sharedInstance] customKeywords]; + if (customKeywords.count < 1) { + return nil; + } + + NSMutableArray *kvSegmentsArray = [[NSMutableArray alloc] init]; + + [customKeywords enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + NSString *stringKey = PBSConvertToNSString(key); + NSArray *arrayValue = PBSConvertToNSArray(value); + if (stringKey.length > 0 && arrayValue.count > 0) { + [kvSegmentsArray addObject:@{ @"key": stringKey, + @"value": arrayValue }]; + } + }]; + return [kvSegmentsArray copy]; +} + +- (NSDictionary *)device { + NSMutableDictionary *deviceDict = [[NSMutableDictionary alloc] init]; + + NSString *userAgent = PBSUserAgent(); + if (userAgent) { + deviceDict[@"ua"] = userAgent; + } + + NSDictionary *geo = [self geo]; + if (geo) { + deviceDict[@"geo"] = geo; + } + + deviceDict[@"make"] = @"Apple"; + + NSString *deviceModel = PBSDeviceModel(); + if (deviceModel) { + deviceDict[@"model"] = deviceModel; + } + + CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init]; + CTCarrier *carrier = [netinfo subscriberCellularProvider]; + + if (carrier.carrierName.length > 0) { + deviceDict[@"carrier"] = carrier.carrierName; + } + + PBServerReachability *reachability = [PBServerReachability reachabilityForInternetConnection]; + PBSNetworkStatus status = [reachability currentReachabilityStatus]; + NSUInteger connectionType = 0; + switch (status) { + case PBSNetworkStatusReachableViaWiFi: + connectionType = 1; + break; + case PBSNetworkStatusReachableViaWWAN: + connectionType = 2; + break; + default: + connectionType = 0; + break; + } + deviceDict[@"connectiontype"] = @(connectionType); + + if (carrier.mobileCountryCode.length > 0 && carrier.mobileNetworkCode.length > 0) { + deviceDict[@"mccmnc"] = [[carrier.mobileCountryCode stringByAppendingString:@"-"] stringByAppendingString:carrier.mobileNetworkCode]; + } + + // Limit ad tracking + deviceDict[@"lmt"] = @(!PBSAdvertisingTrackingEnabled()); + + NSString *deviceId = PBSUDID(); + if (deviceId) { + deviceDict[@"ifa"] = deviceId; + } + + NSInteger timeInMiliseconds = (NSInteger)[[NSDate date] timeIntervalSince1970]; + deviceDict[@"devtime"] = @(timeInMiliseconds); + + return [deviceDict copy]; +} + +- (NSDictionary *)geo { + CLLocation *clLocation = [[PBTargetingParams sharedInstance] location]; + PBServerLocation *location = [PBServerLocation getLocationWithLatitude:clLocation.coordinate.latitude longitude:clLocation.coordinate.longitude timestamp:clLocation.timestamp horizontalAccuracy:clLocation.horizontalAccuracy]; + if (location) { + NSMutableDictionary *geoDict = [[NSMutableDictionary alloc] init]; + CGFloat latitude = location.latitude; + CGFloat longitude = location.longitude; + + if (location.precision >= 0) { + NSNumberFormatter *nf = [[self class] precisionNumberFormatter]; + nf.maximumFractionDigits = location.precision; + nf.minimumFractionDigits = location.precision; + geoDict[@"lat"] = [nf numberFromString:[NSString stringWithFormat:@"%f", location.latitude]]; + geoDict[@"lon"] = [nf numberFromString:[NSString stringWithFormat:@"%f", location.longitude]]; + } else { + geoDict[@"lat"] = @(latitude); + geoDict[@"lon"] = @(longitude); + } + + NSDate *locationTimestamp = location.timestamp; + NSTimeInterval ageInSeconds = -1.0 * [locationTimestamp timeIntervalSinceNow]; + NSInteger ageInMilliseconds = (NSInteger)(ageInSeconds * 1000); + + geoDict[@"lastfix"] = @(ageInMilliseconds); + geoDict[@"accuracy"] = @((NSInteger)location.horizontalAccuracy); + + return [geoDict copy]; + } else { + return nil; + } +} + +- (NSDictionary *)app { + if ([[PBTargetingParams sharedInstance] itunesID] != nil) { + NSString *itunesid = [[PBTargetingParams sharedInstance] itunesID]; + return @{ @"appid": itunesid }; + } else { + NSString *appId = [[NSBundle mainBundle] bundleIdentifier]; + if (appId == nil) { + appId = @""; + } + return @{ @"bundle": appId }; + } +} + ++ (NSNumberFormatter *)precisionNumberFormatter { + static dispatch_once_t precisionNumberFormatterToken; + static NSNumberFormatter *precisionNumberFormatter; + dispatch_once(&precisionNumberFormatterToken, ^{ + precisionNumberFormatter = [[NSNumberFormatter alloc] init]; + precisionNumberFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"]; + }); + return precisionNumberFormatter; +} + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.h b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.h new file mode 100644 index 000000000..8e9fd33a1 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.h @@ -0,0 +1,24 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface PBServerFetcher : NSObject + ++ (instancetype)sharedInstance; + +- (void)makeBidRequest:(NSURLRequest *)request withCompletionHandler:(void (^)(NSDictionary *, NSError *))completionHandler; + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.m b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.m new file mode 100644 index 000000000..026a4af51 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerFetcher.m @@ -0,0 +1,123 @@ + +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBLogging.h" +#import "PBServerFetcher.h" + +@interface PBServerFetcher () + +@property (nonatomic, strong) NSString *requestTID; + +@end + +@implementation PBServerFetcher + ++ (instancetype)sharedInstance { + static dispatch_once_t _dispatchHandle = 0; + static PBServerFetcher *_sharedInstance = nil; + + dispatch_once(&_dispatchHandle, ^{ + if (_sharedInstance == nil) + _sharedInstance = [[PBServerFetcher alloc] init]; + + }); + return _sharedInstance; +} + +- (void)makeBidRequest:(NSURLRequest *)request withCompletionHandler:(void (^)(NSDictionary *, NSError *))completionHandler { + PBLogDebug(@"Bid request to appnexus: %@ params: %@", request.URL.absoluteString, [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding]); + NSDictionary *params = [NSJSONSerialization JSONObjectWithData:[request HTTPBody] + options:kNilOptions + error:nil]; + self.requestTID = params[@"tid"]; + + [NSURLConnection sendAsynchronousRequest:request + queue:[[NSOperationQueue alloc] init] + completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { + if (response != nil && data.length > 0) { + PBLogDebug(@"Bid response from appnexus: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + NSDictionary *adUnitToBids = [self processData:data]; + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(adUnitToBids, nil); + }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(nil, error); + }); + } + }]; +} + +- (NSDictionary *)processData:(NSData *)data { + NSError *error; + id object = [NSJSONSerialization JSONObjectWithData:data + options:kNilOptions + error:&error]; + if (error) { + PBLogError(@"Error parsing ad server response"); + return [[NSMutableDictionary alloc] init]; + } + if (!object) { + return [[NSMutableDictionary alloc] init]; + } + if ([object isKindOfClass:[NSDictionary class]]) { + NSDictionary *response = (NSDictionary *)object; + if ([[response objectForKey:@"status"] isKindOfClass:[NSString class]]) { + NSString *status = (NSString *)[response objectForKey:@"status"]; + if ([status isEqualToString:@"OK"]) { + // check to make sure the request tid matches the response tid + if ([(NSString *)[response objectForKey:@"tid"] isEqualToString:self.requestTID]) { + return [self mapBidsToAdUnits:response]; + } else { + PBLogError(@"Response tid did not match request tid %@", response); + } + } + else { + PBLogError(@"Received bad status response from the ad server %@", response); + } + } + } else { + PBLogError(@"Unexpected response structure received from ad server %@", object); + } + return [[NSMutableDictionary alloc] init]; +} + +- (NSDictionary *)mapBidsToAdUnits:(NSDictionary *)responseDict { + NSDictionary *response = (NSDictionary *)responseDict; + + NSMutableDictionary *adUnitToBidsMap = [[NSMutableDictionary alloc] init]; + if ([[response objectForKey:@"bids"] isKindOfClass:[NSArray class]]) { + NSArray *bids = (NSArray *)[response objectForKey:@"bids"]; + [bids enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if ([obj isKindOfClass:[NSDictionary class]]) { + NSDictionary *bid = (NSDictionary *)obj; + NSMutableArray *bidsArray = [adUnitToBidsMap objectForKey:bid[@"code"]]; + if (bidsArray) { + [bidsArray addObject:bid]; + [adUnitToBidsMap setObject:bidsArray forKey:bid[@"code"]]; + } else { + NSMutableArray *newBidsArray = [[NSMutableArray alloc] initWithArray:@[bid]]; + [adUnitToBidsMap setObject:newBidsArray forKey:bid[@"code"]]; + } + } + }]; + return adUnitToBidsMap; + } + + return [[NSMutableDictionary alloc] init]; +} + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.h b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.h new file mode 100644 index 000000000..d09f9c3f6 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.h @@ -0,0 +1,30 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +#pragma mark Global Methods +NSString *PBSUserAgent(void); +NSString *PBSDeviceModel(void); + +BOOL PBSAdvertisingTrackingEnabled(void); + +NSString *PBSUDID(void); +NSString *PBSConvertToNSString(id value); +NSArray *PBSConvertToNSArray(id value); + +@interface PBServerGlobal : NSObject + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.m b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.m new file mode 100644 index 000000000..da3d82ecb --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerGlobal.m @@ -0,0 +1,84 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBServerGlobal.h" +#import +#import +#import + +static NSString *const kIFASentinelValue = @"00000000-0000-0000-0000-000000000000"; + +NSString *PBSUserAgent() { + static NSString *userAgent = nil; + if (userAgent == nil) { + UIWebView *webview = [[UIWebView alloc] init]; + userAgent = [[webview stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"] copy]; + webview.delegate = nil; + [webview stopLoading]; + } + return userAgent; +} + +NSString *PBSDeviceModel() { + struct utsname systemInfo; + uname(&systemInfo); + + return @(systemInfo.machine); +} + + +NSString *PBSUDID() { + static NSString *udidComponent = @""; + if ([udidComponent isEqualToString:@""]) { + NSString *advertisingIdentifier = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString]; + if (advertisingIdentifier && ![advertisingIdentifier isEqualToString:kIFASentinelValue]) { + udidComponent = advertisingIdentifier; + } + } + return udidComponent; +} + +BOOL PBSAdvertisingTrackingEnabled() { + // If a user does turn this off, use the unique identifier *only* for the + // following: + // - Frequency capping + // - Conversion events + // - Estimating number of unique users + // - Security and fraud detection + // - Debugging + return [ASIdentifierManager sharedManager].isAdvertisingTrackingEnabled; +} + +NSArray *PBSConvertToNSArray(id value) { + if ([value isKindOfClass:[NSArray class]]) + return value; + if ([value respondsToSelector:@selector(stringValue)]) { + return [value array]; + } + return nil; +} + +NSString *PBSConvertToNSString(id value) { + if ([value isKindOfClass:[NSString class]]) + return value; + if ([value respondsToSelector:@selector(stringValue)]) { + return [value stringValue]; + } + return nil; +} + +@implementation PBServerGlobal + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.h b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.h new file mode 100644 index 000000000..2cd7473ed --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.h @@ -0,0 +1,83 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface PBServerLocation : NSObject + +/** + The latitude of the user's location. This must be a valid + latitude, i.e., between -90.0 and 90.0. + */ +@property (nonatomic, readwrite, assign) CGFloat latitude; + +/** + The longitude of the user's location. This must be a valid + longitude, i.e., between -180.0 and 180.0. + */ +@property (nonatomic, readwrite, assign) CGFloat longitude; + +/** + The time when the user was in this location. If nil, defaults to + the current time. + */ +@property (nonatomic, readwrite, strong) NSDate *timestamp; + +/** + Determines the size of one side of the ``rectangle'' inside which + the user is located. If 0, defaults to 100 meters. If negative, + the location will be invalidated. + */ +@property (nonatomic, readwrite, assign) CGFloat horizontalAccuracy; + +/** + The precision of the location. Returns -1 if the location has unlimited + precision. + */ +@property (nonatomic, readonly, assign) NSInteger precision; + +/** + Returns an PBServerLocation instance generated from a user's location. It is + expected that the latitude, longitude, timestamp, and horizontal accuracy + parameters will be passed from a CLLocation instance. + + Returns nil if invalid location data is passed in (see + the property definitions above for what constitutes invalid data). + */ ++ (PBServerLocation *)getLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + timestamp:(NSDate *)timestamp + horizontalAccuracy:(CGFloat)horizontalAccuracy; + +/** + Returns an PBServerLocation instance with latitude and longitude values rounded to the + number of decimal places specified in precision. It is expected that the latitude, + longitude, timestamp, and horizontal accuracy parameters will be passed directly + from a CLLocation instance. + + Returns nil if invalid location data is passed in (see the property definitions + above for what constitutes invalid data). In addition, if the precision is: + + ** Equal to -1, no rounding will occur. + + ** Greater than 6, the latitude & longitude values will be rounded to 6 decimal places. + */ ++ (PBServerLocation *)getLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + timestamp:(NSDate *)timestamp + horizontalAccuracy:(CGFloat)horizontalAccuracy + precision:(NSInteger)precision; + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.m b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.m new file mode 100644 index 000000000..588c476c7 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerLocation.m @@ -0,0 +1,84 @@ +/* Copyright 2017 APPNEXUS INC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "PBServerLocation.h" + +static NSInteger const kPBSLocationMaxLocationPrecision = 6; +static NSInteger const kPBSLocationDefaultHorizontalAccuracy = 100; + +@interface PBServerLocation () + +@property (nonatomic, readwrite, assign) NSInteger precision; + +@end + +@implementation PBServerLocation + ++ (PBServerLocation *)getLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + timestamp:(NSDate *)timestamp + horizontalAccuracy:(CGFloat)horizontalAccuracy { + return [PBServerLocation getLocationWithLatitude:latitude + longitude:longitude + timestamp:timestamp + horizontalAccuracy:horizontalAccuracy + precision:-1]; +} + ++ (PBServerLocation *)getLocationWithLatitude:(CGFloat)latitude + longitude:(CGFloat)longitude + timestamp:(NSDate *)timestamp + horizontalAccuracy:(CGFloat)horizontalAccuracy + precision:(NSInteger)precision { + BOOL invalidLatitude = latitude < -90 || latitude > 90; + BOOL invalidLongitude = longitude < -180 || longitude > 180; + BOOL invalidHorizontalAccuracy = horizontalAccuracy < 0; + if (invalidLatitude || invalidLongitude || invalidHorizontalAccuracy) { + return nil; + } + + BOOL invalidPrecision = precision < -1; + if (invalidPrecision) { + //Log + } + + if (horizontalAccuracy == 0) + horizontalAccuracy = kPBSLocationDefaultHorizontalAccuracy; + + if (timestamp == nil) + timestamp = [NSDate date]; + + PBServerLocation *location = [[PBServerLocation alloc] init]; + if (precision <= -1) { + location.latitude = latitude; + location.longitude = longitude; + location.precision = -1; + } else { + NSInteger effectivePrecision = precision; + if (precision > kPBSLocationMaxLocationPrecision) { + effectivePrecision = kPBSLocationMaxLocationPrecision; + } + + CGFloat precisionFloat = powf(10, effectivePrecision); + location.latitude = roundf(latitude * precisionFloat) / precisionFloat; + location.longitude = roundf(longitude * precisionFloat) / precisionFloat; + location.precision = effectivePrecision; + } + location.timestamp = timestamp; + location.horizontalAccuracy = horizontalAccuracy; + return location; +} + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.h b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.h new file mode 100644 index 000000000..a2caf1045 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.h @@ -0,0 +1,97 @@ +/* + File: Reachability.h + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity + APIs. + Version: 3.5 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + + */ +#import +#import +#import + +typedef enum : NSInteger { + PBSNetworkStatusNotReachable = 0, + PBSNetworkStatusReachableViaWiFi, + PBSNetworkStatusReachableViaWWAN +} PBSNetworkStatus; + +extern NSString *kPBSReachabilityChangedNotification; + +@interface PBServerReachability : NSObject + +/*! + * Use to check the reachability of a given host name. + */ ++ (instancetype)reachabilityWithHostName:(NSString *)hostName; + +/*! + * Use to check the reachability of a given IP address. + */ ++ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress; + +/*! + * Checks whether the default route is available. Should be used by applications + * that do not connect to a particular host. + */ ++ (instancetype)reachabilityForInternetConnection; + +/*! + * Checks whether a local WiFi connection is available. + */ ++ (instancetype)reachabilityForLocalWiFi; + +/*! + * Start listening for reachability notifications on the current run loop. + */ +- (BOOL)startNotifier; +- (void)stopNotifier; + +- (PBSNetworkStatus)currentReachabilityStatus; + +/*! + * WWAN may be available, but not active until a connection has been + * established. WiFi may require a connection for VPN on Demand. + */ +- (BOOL)connectionRequired; + +@end diff --git a/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.m b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.m new file mode 100644 index 000000000..2aa84c344 --- /dev/null +++ b/sdk/PrebidServerAdapter/PrebidServerModule/PBServerReachability.m @@ -0,0 +1,272 @@ +/* + File: Reachability.m + Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity + APIs. + Version: 3.5 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple + Inc. ("Apple") in consideration of your agreement to the following + terms, and your use, installation, modification or redistribution of + this Apple software constitutes acceptance of these terms. If you do + not agree with these terms, please do not use, install, modify or + redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may + be used to endorse or promote products derived from the Apple Software + without specific prior written permission from Apple. Except as + expressly stated in this notice, no other rights or licenses, express or + implied, are granted by Apple herein, including but not limited to any + patent rights that may be infringed by your derivative works or by other + works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2014 Apple Inc. All Rights Reserved. + + */ + +#import +#import +#import +#import + +#import + +#import "PBServerReachability.h" + +NSString *kPBSReachabilityChangedNotification = @"kPBSNetworkReachabilityChangedNotification"; + +#pragma mark - Supporting functions + +#define kShouldPrintReachabilityFlags 0 + +static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, + const char *comment) { +#if kShouldPrintReachabilityFlags + + NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n", + (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-', + (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-', + + (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-', + (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-', + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-', + (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-', + (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-', comment); +#endif +} + +static void ReachabilityCallback(SCNetworkReachabilityRef target, + SCNetworkReachabilityFlags flags, void *info) { +#pragma unused(target, flags) + NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); + NSCAssert([(__bridge NSObject *)info isKindOfClass:[PBServerReachability class]], + @"info was wrong class in ReachabilityCallback"); + + PBServerReachability *noteObject = (__bridge PBServerReachability *)info; + // Post a notification to notify the client that the network reachability + // changed. + [[NSNotificationCenter defaultCenter] postNotificationName:kPBSReachabilityChangedNotification + object:noteObject]; +} + +#pragma mark - Reachability implementation + +@implementation PBServerReachability { + BOOL _alwaysReturnLocalWiFiStatus; // default is NO + SCNetworkReachabilityRef _reachabilityRef; +} + ++ (instancetype)reachabilityWithHostName:(NSString *)hostName { + PBServerReachability *returnValue = NULL; + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]); + if (reachability != NULL) { + returnValue = [[self alloc] init]; + if (returnValue != NULL) { + returnValue->_reachabilityRef = reachability; + returnValue->_alwaysReturnLocalWiFiStatus = NO; + } + } + return returnValue; +} + ++ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress { + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress); + + PBServerReachability *returnValue = NULL; + + if (reachability != NULL) { + returnValue = [[self alloc] init]; + if (returnValue != NULL) { + returnValue->_reachabilityRef = reachability; + returnValue->_alwaysReturnLocalWiFiStatus = NO; + } + } + return returnValue; +} + ++ (instancetype)reachabilityForInternetConnection { + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + return [self reachabilityWithAddress:&zeroAddress]; +} + ++ (instancetype)reachabilityForLocalWiFi { + struct sockaddr_in localWifiAddress; + bzero(&localWifiAddress, sizeof(localWifiAddress)); + localWifiAddress.sin_len = sizeof(localWifiAddress); + localWifiAddress.sin_family = AF_INET; + + // IN_LINKLOCALNETNUM is defined in as 169.254.0.0. + localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM); + + PBServerReachability *returnValue = [self reachabilityWithAddress:&localWifiAddress]; + if (returnValue != NULL) { + returnValue->_alwaysReturnLocalWiFiStatus = YES; + } + + return returnValue; +} + +#pragma mark - Start and stop notifier + +- (BOOL)startNotifier { + BOOL returnValue = NO; + SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, + NULL, NULL}; + + if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)) { + if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { + returnValue = YES; + } + } + + return returnValue; +} + +- (void)stopNotifier { + if (_reachabilityRef != NULL) { + SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + } +} + +- (void)dealloc { + [self stopNotifier]; + if (_reachabilityRef != NULL) { + CFRelease(_reachabilityRef); + } +} + +#pragma mark - Network Flag Handling + +- (PBSNetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags { + PrintReachabilityFlags(flags, "localWiFiStatusForFlags"); + PBSNetworkStatus returnValue = PBSNetworkStatusNotReachable; + + if ((flags & kSCNetworkReachabilityFlagsReachable) && + (flags & kSCNetworkReachabilityFlagsIsDirect)) { + returnValue = PBSNetworkStatusReachableViaWiFi; + } + + return returnValue; +} + +- (PBSNetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags { + PrintReachabilityFlags(flags, "networkStatusForFlags"); + if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) { + // The target host is not reachable. + return PBSNetworkStatusNotReachable; + } + + PBSNetworkStatus returnValue = PBSNetworkStatusNotReachable; + + if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) { + /* + If the target host is reachable and no connection is required then we'll assume + (for now) that you're on Wi-Fi... + */ + returnValue = PBSNetworkStatusReachableViaWiFi; + } + + if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0) || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) { + /* + ... and the connection is on-demand (or on-traffic) if the calling + application is using the CFSocketStream or higher APIs... + */ + + if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) { + /* + ... and no [user] intervention is needed... + */ + returnValue = PBSNetworkStatusReachableViaWiFi; + } + } + + if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) { + /* + ... but WWAN connections are OK if the calling application is using the + CFNetwork APIs. + */ + returnValue = PBSNetworkStatusReachableViaWWAN; + } + + return returnValue; +} + +- (BOOL)connectionRequired { + NSAssert(_reachabilityRef != NULL, + @"connectionRequired called with NULL reachabilityRef"); + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) { + return (flags & kSCNetworkReachabilityFlagsConnectionRequired); + } + + return NO; +} + +- (PBSNetworkStatus)currentReachabilityStatus { + NSAssert(_reachabilityRef != NULL, + @"currentNetworkStatus called with NULL SCNetworkReachabilityRef"); + PBSNetworkStatus returnValue = PBSNetworkStatusNotReachable; + SCNetworkReachabilityFlags flags; + + if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)) { + if (_alwaysReturnLocalWiFiStatus) { + returnValue = [self localWiFiStatusForFlags:flags]; + } else { + returnValue = [self networkStatusForFlags:flags]; + } + } + + return returnValue; +} + +@end