Delete Promote_Graph.

This commit is contained in:
Brian Simpson
2013-10-18 08:01:57 -04:00
parent 0a652a9513
commit 0dce9b97a7
6 changed files with 0 additions and 480 deletions

View File

@@ -208,7 +208,6 @@ def make_map():
controller='promote', action='pay')
mc('/promoted/refund/:link/:campaign', controller='promote',
action='refund')
mc('/promoted/admin/graph', controller='promote', action='admingraph')
mc('/promoted/:action', controller='promote',
requirements=dict(action="edit_promo|new_promo|roadblock"))

View File

@@ -22,7 +22,6 @@
from datetime import datetime, timedelta
from babel.numbers import format_number
import itertools
import json
import urllib
@@ -40,7 +39,6 @@ from r2.lib.menus import NamedButton, NavButton, NavMenu
from r2.lib.pages import (
LinkInfoPage,
PaymentForm,
Promote_Graph,
PromotePage,
PromoteLinkForm,
PromoteLinkNew,
@@ -107,27 +105,6 @@ from r2.models import (
)
def _check_dates(dates):
params = ('startdate', 'enddate')
error_types = (errors.BAD_DATE,
errors.DATE_TOO_EARLY,
errors.DATE_TOO_LATE,
errors.BAD_DATE_RANGE,
errors.DATE_RANGE_TOO_LARGE)
for error_case in itertools.product(error_types, params):
if error_case in c.errors:
bad_dates = dates
start, end = None, None
break
else:
bad_dates = None
start, end = dates
if not start or not end:
start = promote.promo_datetime_now(offset=-7).date()
end = promote.promo_datetime_now(offset=6).date()
return start, end, bad_dates
def campaign_has_oversold_error(form, campaign):
if campaign.priority.inventory_override:
return
@@ -323,21 +300,6 @@ class PromoteController(ListingController):
datestr=True)
return {'inventory': available_by_datestr}
@validate(VSponsor(),
dates=VDateRange(["startdate", "enddate"],
max_range=timedelta(days=28),
required=False))
@validate(VSponsorAdmin(),
dates=VDateRange(["startdate", "enddate"],
max_range=timedelta(days=28),
required=False))
def GET_admingraph(self, dates):
start, end, bad_dates = _check_dates(dates)
content = Promote_Graph(start, end, bad_dates=bad_dates)
if c.render_style == 'csv':
return content.as_csv()
return PromotePage("admingraph", content=content).render()
# ## POST controllers below
@validatedForm(VSponsorAdmin(),
link=VLink("link_id"),

View File

@@ -167,7 +167,6 @@ menu = MenuHandler(hot = _('hot'),
all_promos = _('all'),
future_promos = _('unseen'),
roadblock = _('roadblock'),
admin_graph = _('admin analytics'),
live_promos = _('live'),
unpaid_promos = _('unpaid'),
pending_promos = _('pending'),

View File

@@ -3427,8 +3427,6 @@ class PromotePage(Reddit):
buttons.append(NamedButton('my_current_promos', dest = ''))
if c.user_is_sponsor:
buttons.append(NamedButton('admin_graph',
dest='/admin/graph'))
buttons.append(NavButton('report', 'report'))
buttons.append(NavButton('underdelivered', 'underdelivered'))
buttons.append(NavButton('house ads', 'house'))
@@ -3788,196 +3786,6 @@ class Promotion_Summary(Templated):
% ndays, p.render('email'))
def force_datetime(d):
return datetime.datetime.combine(d, datetime.time())
class Promote_Graph(Templated):
@classmethod
@memoize('get_market', time = 60)
def get_market(cls, user_id, start_date, end_date):
market = {}
promo_counter = {}
def callback(link, bid_day, starti, endi, campaign):
for i in xrange(starti, endi):
if user_id is None or link.author_id == user_id:
if (not promote.is_unpaid(link) and
not promote.is_rejected(link) and
campaign.trans_id != NO_TRANSACTION):
market[i] = market.get(i, 0) + bid_day
promo_counter[i] = promo_counter.get(i, 0) + 1
cls.promo_iter(start_date, end_date, callback)
return market, promo_counter
@classmethod
def promo_iter(cls, start_date, end_date, callback):
size = (end_date - start_date).days
current_promos = cls.get_current_promos(start_date, end_date)
campaign_ids = [camp_id for link, camp_id, s, e in current_promos]
campaigns = PromoCampaign._byID(campaign_ids, data=True)
for link, campaign_id, s, e in current_promos:
if campaign_id in campaigns:
campaign = campaigns[campaign_id]
sdate = campaign.start_date.date()
edate = campaign.end_date.date()
starti = max((sdate - start_date).days, 0)
endi = min((edate - start_date).days, size)
bid_day = campaign.bid / max((edate - sdate).days, 1)
callback(link, bid_day, starti, endi, campaign)
@classmethod
def get_current_promos(cls, start_date, end_date):
# grab promoted links
# returns a list of (thing_id, campaign_idx, start, end)
promos = PromotionWeights.get_schedule(start_date, end_date)
# sort based on the start date
promos.sort(key = lambda x: x[2])
# wrap the links
links = wrap_links([p[0] for p in promos])
# remove rejected/unpaid promos
links = dict((l._fullname, l) for l in links.things
if promote.is_accepted(l) or promote.is_unapproved(l))
# filter promos accordingly
promos = [(links[thing_name], campaign_id, s, e)
for thing_name, campaign_id, s, e in promos
if links.has_key(thing_name)]
return promos
def __init__(self, start_date, end_date, bad_dates=None):
self.now = promote.promo_datetime_now()
start_date = to_date(start_date)
end_date = to_date(end_date)
end_before = end_date + datetime.timedelta(days=1)
size = (end_before - start_date).days
self.dates = [start_date + datetime.timedelta(i) for i in xrange(size)]
# these will be cached queries
market, promo_counter = self.get_market(None, start_date, end_before)
my_market = market
# determine the range of each link
promote_blocks = []
def block_maker(link, bid_day, starti, endi, campaign):
if (not promote.is_rejected(link)
and not promote.is_unpaid(link)):
promote_blocks.append((link, starti, endi, campaign))
self.promo_iter(start_date, end_before, block_maker)
# now sort the promoted_blocks into the most contiguous chuncks we can
sorted_blocks = []
while promote_blocks:
cur = promote_blocks.pop(0)
while True:
sorted_blocks.append(cur)
# get the future items (sort will be preserved)
future = filter(lambda x: x[2] >= cur[3], promote_blocks)
if future:
# resort by date and give precidence to longest promo:
cur = min(future, key = lambda x: (x[2], x[2]-x[3]))
promote_blocks.remove(cur)
else:
break
pool =PromotionWeights.bid_history(promote.promo_datetime_now(offset=-30),
promote.promo_datetime_now(offset=2))
# graphs of impressions and clicks
self.promo_traffic = promote.traffic_totals()
impressions = [(d, i) for (d, (i, k)) in self.promo_traffic]
pool = dict((d, b+r) for (d, b, r) in pool)
if impressions:
CPM = [(force_datetime(d), (pool.get(d, 0) * 1000. / i) if i else 0)
for (d, (i, k)) in self.promo_traffic if d in pool]
mean_CPM = sum(x[1] for x in CPM) * 1. / max(len(CPM), 1)
CPC = [(force_datetime(d), (100 * pool.get(d, 0) / k) if k else 0)
for (d, (i, k)) in self.promo_traffic if d in pool]
mean_CPC = sum(x[1] for x in CPC) * 1. / max(len(CPC), 1)
cpm_title = _("cost per 1k impressions ($%(avg).2f average)") % dict(avg=mean_CPM)
cpc_title = _("cost per click ($%(avg).2f average)") % dict(avg=mean_CPC/100.)
data = traffic.zip_timeseries(((d, (min(v, mean_CPM * 2),)) for d, v in CPM),
((d, (min(v, mean_CPC * 2),)) for d, v in CPC))
from r2.lib.pages.trafficpages import COLORS # not top level because of * imports :(
self.performance_table = TimeSeriesChart("promote-graph-table",
_("historical performance"),
"day",
[dict(color=COLORS.DOWNVOTE_BLUE,
title=cpm_title,
shortname=_("CPM")),
dict(color=COLORS.DOWNVOTE_BLUE,
title=cpc_title,
shortname=_("CPC"))],
data)
else:
self.performance_table = None
self.promo_traffic = dict(self.promo_traffic)
predicted = inventory.get_predicted_by_date(None, start_date,
end_before)
self.impression_inventory = predicted
# TODO: Real data
self.scheduled_impressions = dict.fromkeys(predicted, 0)
self.cpc = {}
self.cpm = {}
self.delivered = {}
self.clicked = {}
self.my_market = {}
self.promo_counter = {}
today = self.now.date()
for i in xrange(size):
day = start_date + datetime.timedelta(i)
cpc = cpm = delivered = clicks = "---"
if day in self.promo_traffic:
delivered, clicks = self.promo_traffic[day]
if i in market and day < today:
cpm = "$%.2f" % promote.cost_per_mille(market[i], delivered)
cpc = "$%.2f" % promote.cost_per_click(market[i], clicks)
delivered = format_number(delivered, c.locale)
clicks = format_number(clicks, c.locale)
if day == today:
delivered = "(%s)" % delivered
clicks = "(%s)" % clicks
self.cpc[day] = cpc
self.cpm[day] = cpm
self.delivered[day] = delivered
self.clicked[day] = clicks
if i in my_market:
self.my_market[day] = "$%.2f" % my_market[i]
else:
self.my_market[day] = "---"
self.promo_counter[day] = promo_counter.get(i, "---")
Templated.__init__(self, today=today, promote_blocks=sorted_blocks,
start_date=start_date, end_date=end_date,
bad_dates=bad_dates)
def to_iter(self, localize = True):
locale = c.locale
def num(x):
if localize:
return format_number(x, locale)
return str(x)
for link, uimp, nimp, ucli, ncli in self.recent:
yield (link._date.strftime("%Y-%m-%d"),
num(uimp), num(nimp), num(ucli), num(ncli),
num(link._ups - link._downs),
"$%.2f" % link.promote_bid,
_force_unicode(link.title))
class PromoteReport(Templated):
def __init__(self, links, link_text, owner_name, bad_links, start, end):
self.links = links

View File

@@ -5248,70 +5248,6 @@ button.new-campaign:disabled { color: gray; }
dt { margin-left: 10px; font-weight: bold; }
dd { margin-left: 20px; }
.calendar-lead {
margin: 15px;
}
table.calendar {
white-space: nowrap;
width: 90%;
margin-top: 20px;
position: relative;
padding-top: 120px;
padding-bottom: 100px;
empty-cells: show;
table-layout: fixed;
}
.calendar .today {
background-color: yellow;
}
.calendar thead tr {
border-bottom: 2px solid gray;
}
.calendar thead th, .calendar thead td {
font-weight: bold;
text-align: center;
text-transform: uppercase;
}
.calendar td, .calendar th[scope="col"] {
border-left: 1px dashed gray;
}
.calendar .blob {
margin: 0;
padding: 0px;
z-index: 10;
cursor: pointer;
}
.calendar .blob.link:hover {
border: 1px solid red;
box-shadow: 2px 2px 2px #000;
-moz-box-shadow: 2px 2px 2px #000;
z-index: 100;
}
.calendar .blob .bid {
text-align: right;
font-weight: bold;
padding: 5px 5px 0px 5px;
}
.calendar .blob.link {
margin: -1px -2px 0px -2px;
border: 1px solid black;
}
.calendar .blob.link .title{
font-size: small;
padding: 0 5px 5px 5px;
display: block;
}
.borderless td {
border: none;
}

View File

@@ -1,184 +0,0 @@
## The contents of this file are subject to the Common Public Attribution
## License Version 1.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://code.reddit.com/LICENSE. The License is based on the Mozilla Public
## License Version 1.1, but Sections 14 and 15 have been added to cover use of
## software over a computer network and provide for limited attribution for the
## Original Developer. In addition, Exhibit A has been modified to be
## consistent with Exhibit B.
##
## Software distributed under the License is distributed on an "AS IS" basis,
## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
## the specific language governing rights and limitations under the License.
##
## The Original Code is reddit.
##
## The Original Developer is the Initial Developer. The Initial Developer of
## the Original Code is reddit Inc.
##
## All portions of the code written by reddit are Copyright (c) 2006-2013
## reddit Inc. All Rights Reserved.
###############################################################################
<%!
from r2.lib import js
from r2.lib.template_helpers import static
%>
<%namespace file="reddittraffic.html" import="load_timeseries_js"/>
<%namespace name="pr" file="promotelinkform.html" />
${load_timeseries_js()}
${unsafe(js.use('sponsored'))}
<h1>${_("Sponsored link calendar")}</h1>
<div class="calendar-lead">
<h2>${_("Viewing calendar for dates:")}</h2>
%if thing.bad_dates and all(thing.bad_dates):
<div class="error">
${_("Sorry, I couldn't make sense of the date range: %(start)s - %(end)s") %\
dict(start=thing.bad_dates[0].strftime('%m/%d/%Y'),
end=thing.bad_dates[1].strftime('%m/%d/%Y'))}
</div>
%endif
<form action="/promoted/admin/graph" method="get">
<%pr:datepicker name="startdate" value="${thing.start_date.strftime('%m/%d/%Y')}"
minDateSrc="date-min" initfuncname="init_startdate"
min_date_offset="86400000">
function(elem) { check_enddate(elem, $("#enddate")); return elem; }
</%pr:datepicker>
&nbsp;&ndash;&nbsp;
<%pr:datepicker name="enddate" value="${thing.end_date.strftime('%m/%d/%Y')}"
minDateSrc="startdate" initfuncname="init_enddate"
min_date_offset="86400000">
function(elem) { return elem; }
</%pr:datepicker>
<input type="submit" value="${_("go")}"></input>
</form>
</div>
<table class="calendar">
<thead>
<tr>
<th scope="row">${_("Date")}</th>
%for date in thing.dates:
<th scope="col" class="${"today" if date == thing.today else ""}">
<time>${date}</time>
</th>
%endfor
</tr>
<tr>
## TRANSLATORS: Noun
<th scope="row">${_("Count")}</th>
%for date in thing.dates:
<td class="${"today" if date == thing.today else ""}">
${thing.promo_counter[date]}
</td>
%endfor
</tr>
%if thing.scheduled_impressions:
<tr>
## TRANSLATORS: Advertising term; "ad impressions scheduled for delivery"
<th scope="row">${_("Scheduled")}<br/>
${_("Inventory")}</th>
%for date in thing.dates:
<td class="${"today" if date == thing.today else ""}">
${thing.scheduled_impressions.get(date, "---")}<br/>
${thing.impression_inventory.get(date, "---")}
</td>
%endfor
</tr>
%endif
<tr>
<th scope="row">
## TRANSLATORS: Advertising term; "ad impressions delivered / shown"
${_("Impressions")}<br/>
## TRANSLATORS: Advertising term: "cost per mille"
${_("CPM")}
</th>
%for date in thing.dates:
<td class="${"today" if date == thing.today else ""}">
${thing.delivered[date]}<br/>
${thing.cpm[date]}
</td>
%endfor
</tr>
<tr>
<th scope="row">
${_("Clicks")}<br/>
## TRANSLATORS: Advertising term: "cost per click"
${_("CPC")}
</th>
%for date in thing.dates:
<td class="${"today" if date == thing.today else ""}">
${thing.clicked[date]}<br/>
${thing.cpc[date]}
</td>
%endfor
</tr>
<tr>
<th scope="row">
%if c.user_is_sponsor:
## TRANSLATORS: Advertising term: Total value of scheduled ads
${_("Total Commit")}
%else:
## TRANSLATORS: Advertising term: Amount spent on scheduled ads
${_("Your Commit")}
%endif
</th>
%for date in thing.dates:
<td class="${"today" if date == thing.today else ""}">
${thing.my_market[date]}
</td>
%endfor
</tr>
</thead>
<tbody>
%for link, start, end, campaign in thing.promote_blocks:
<tr>
<th class="placeholder"></th>
%for i in xrange(start):
<td class="placeholder
${"today" if thing.dates[i] == thing.today else ""}"></td>
%endfor
<td colspan="${end - start}">
<div class="blob promotedlink ${link.rowstyle} rounded"
title="${link.title}">
<div class="bid">
${campaign.sr_name + ':' if campaign.sr_name else ''}
$${int(campaign.bid)}
</div>
<a class="title" href="/promoted/edit_promo/${link._id36}"
title="${link.title}">
${link.author.name}
</a>
</div>
</td>
%for i in xrange(end, len(thing.dates)):
<td class="placeholder
${"today" if thing.dates[i] == thing.today else ""}"></td>
%endfor
</tr>
%endfor
</tbody>
</table>
<div class="clear"></div>
<h1>${_("historical site performance")}</h1>
<div id="charts"></div>
${thing.performance_table}
<script type="text/javascript">
$(function() {
init_startdate();
init_enddate();
});
r.timeseries.init();
</script>
</div>