def get_available_pageviews(targets, start, end, datestr=False, ignore=None): pageviews_by_sr_name = {} all_campaigns = set() targets, is_single = tup(targets, ret_is_single=True) target_srs = chain.from_iterable( target.subreddits_slow for target in targets) all_sr_names = set() srs = set(target_srs) # get all campaigns in target_srs and pull in campaigns from other # subreddits that are targeted while srs: all_sr_names |= {sr.name for sr in srs} new_pageviews_by_sr_name = get_predicted_pageviews(srs) pageviews_by_sr_name.update(new_pageviews_by_sr_name) new_campaigns_by_date = get_campaigns_by_date(srs, start, end, ignore) new_campaigns = set(chain.from_iterable( new_campaigns_by_date.itervalues())) all_campaigns.update(new_campaigns) new_sr_names = set(chain.from_iterable( campaign.target.subreddit_names for campaign in new_campaigns )) new_sr_names -= all_sr_names srs = set(Subreddit._by_name(new_sr_names).values()) # determine booked impressions by target for each day dates = set(get_date_range(start, end)) booked_by_target_by_date = {date: defaultdict(int) for date in dates} for campaign in all_campaigns: camp_dates = set(get_date_range(campaign.start_date, campaign.end_date)) sr_names = tuple(sorted(campaign.target.subreddit_names)) daily_impressions = campaign.impressions / campaign.ndays for date in camp_dates.intersection(dates): booked_by_target_by_date[date][sr_names] += daily_impressions datekey = lambda dt: dt.strftime('%m/%d/%Y') if datestr else dt ret = {} for target in targets: name = make_target_name(target) ret[name] = {} for date in dates: booked_by_target = booked_by_target_by_date[date] pageviews = get_maximized_pageviews( target.subreddit_names, booked_by_target, pageviews_by_sr_name) ret[name][datekey(date)] = max(0, pageviews) if is_single: name = make_target_name(targets[0]) return ret[name] else: return ret
def get_available_pageviews(targets, start, end, location=None, datestr=False, ignore=None): """ Return the available pageviews by date for the targets and location. Available pageviews depends on all equal and higher level locations: A location is: subreddit > country > metro e.g. if a campaign is targeting /r/funny in USA/Boston we need to check that there's enough inventory in: * /r/funny (all campaigns targeting /r/funny regardless of location) * /r/funny + USA (all campaigns targeting /r/funny and USA with or without metro level targeting) * /r/funny + USA + Boston (all campaigns targeting /r/funny and USA and Boston) The available inventory is the smallest of these values. """ # assemble levels of location targeting, None means untargeted locations = [None] if location: locations.append(location) if location.metro: locations.append(Location(country=location.country)) # get all the campaigns directly and indirectly involved in our target targets, is_single = tup(targets, ret_is_single=True) target_srs = list( chain.from_iterable(target.subreddits_slow for target in targets)) all_campaigns = find_campaigns(target_srs, start, end, ignore) # get predicted pageviews for each subreddit and location all_sr_names = set(sr.name for sr in target_srs) all_sr_names |= set( chain.from_iterable(campaign.target.subreddit_names for campaign in all_campaigns)) all_srs = Subreddit._by_name(all_sr_names).values() pageviews_dict = { location: get_predicted_pageviews(all_srs, location) for location in locations } # determine booked impressions by target and location for each day dates = set(get_date_range(start, end)) booked_dict = {} for date in dates: booked_dict[date] = {} for location in locations: booked_dict[date][location] = defaultdict(int) for campaign in all_campaigns: camp_dates = set(get_date_range(campaign.start_date, campaign.end_date)) sr_names = tuple(sorted(campaign.target.subreddit_names)) daily_impressions = campaign.impressions / campaign.ndays for location in locations: if location and not location.contains(campaign.location): # campaign's location is less specific than location continue for date in camp_dates.intersection(dates): booked_dict[date][location][sr_names] += daily_impressions # calculate inventory for each target and location on each date datekey = lambda dt: dt.strftime('%m/%d/%Y') if datestr else dt ret = {} for target in targets: name = make_target_name(target) subreddit_names = target.subreddit_names ret[name] = {} for date in dates: pageviews_by_location = {} for location in locations: # calculate available impressions for each location booked_by_target = booked_dict[date][location] pageviews_by_sr_name = pageviews_dict[location] pageviews_by_location[location] = get_maximized_pageviews( subreddit_names, booked_by_target, pageviews_by_sr_name) # available pageviews is the minimum from all locations min_pageviews = min(pageviews_by_location.values()) ret[name][datekey(date)] = max(0, min_pageviews) if is_single: name = make_target_name(targets[0]) return ret[name] else: return ret
def get_available_pageviews(targets, start, end, location=None, datestr=False, ignore=None): """ Return the available pageviews by date for the targets and location. Available pageviews depends on all equal and higher level locations: A location is: subreddit > country > metro e.g. if a campaign is targeting /r/funny in USA/Boston we need to check that there's enough inventory in: * /r/funny (all campaigns targeting /r/funny regardless of location) * /r/funny + USA (all campaigns targeting /r/funny and USA with or without metro level targeting) * /r/funny + USA + Boston (all campaigns targeting /r/funny and USA and Boston) The available inventory is the smallest of these values. """ # assemble levels of location targeting, None means untargeted locations = [None] if location: locations.append(location) if location.metro: locations.append(Location(country=location.country)) # get all the campaigns directly and indirectly involved in our target targets, is_single = tup(targets, ret_is_single=True) target_srs = list(chain.from_iterable( target.subreddits_slow for target in targets)) all_campaigns = find_campaigns(target_srs, start, end, ignore) # get predicted pageviews for each subreddit and location all_sr_names = set(sr.name for sr in target_srs) all_sr_names |= set(chain.from_iterable( campaign.target.subreddit_names for campaign in all_campaigns )) all_srs = Subreddit._by_name(all_sr_names).values() pageviews_dict = {location: get_predicted_pageviews(all_srs, location) for location in locations} # determine booked impressions by target and location for each day dates = set(get_date_range(start, end)) booked_dict = {} for date in dates: booked_dict[date] = {} for location in locations: booked_dict[date][location] = defaultdict(int) for campaign in all_campaigns: camp_dates = set(get_date_range(campaign.start_date, campaign.end_date)) sr_names = tuple(sorted(campaign.target.subreddit_names)) daily_impressions = campaign.impressions / campaign.ndays for location in locations: if location and not location.contains(campaign.location): # campaign's location is less specific than location continue for date in camp_dates.intersection(dates): booked_dict[date][location][sr_names] += daily_impressions # calculate inventory for each target and location on each date datekey = lambda dt: dt.strftime('%m/%d/%Y') if datestr else dt ret = {} for target in targets: name = make_target_name(target) subreddit_names = target.subreddit_names ret[name] = {} for date in dates: pageviews_by_location = {} for location in locations: # calculate available impressions for each location booked_by_target = booked_dict[date][location] pageviews_by_sr_name = pageviews_dict[location] pageviews_by_location[location] = get_maximized_pageviews( subreddit_names, booked_by_target, pageviews_by_sr_name) # available pageviews is the minimum from all locations min_pageviews = min(pageviews_by_location.values()) ret[name][datekey(date)] = max(0, min_pageviews) if is_single: name = make_target_name(targets[0]) return ret[name] else: return ret