Skip to content
Browse files

Added specificity, limit & priorty to system.

* Results returned are sorted by
** Most matching
** Author priority (0=lowest)
** creation date (newest wins)
* Config file may specify max number of announcements to return
  • Loading branch information...
1 parent de359af commit 2aee3388901829c6806fbf6df158faede37dfd3f @jrconlin committed Nov 5, 2012
View
1 Makefile
@@ -19,4 +19,3 @@ test:
run:
$(PS) campaign-local.ini
-
View
8 README.rst
@@ -1,8 +1,8 @@
-CampainManager
+Campaign Manager
=============
-Campaign Manager is a server that provides small HTML elements to be used
-by the firefox browser as part of marketing and outreach.
+Campaign Manager is a server that provides JSON fragments to be displayed by
+the Firefox browser as part of product marketing and outreach.
Installing
----
@@ -13,6 +13,8 @@ Please make sure the following packages are installed on the system:
gcc
virtualenv
sqlite
+mysql
+zmq
Once those packages are successfully installed:
View
2 campaign.ini
@@ -20,6 +20,8 @@ db.db = /tmp/campaigns.sqlite
#db.db = campaign
# Number of seconds to cache a query
#db.query_window = 1
+# Limit the number of annoucements to return
+#db.limit = None
#dbg.traceback = False
#dbg.break_unknown_exception = False
View
1 campaign/storage/__init__.py
@@ -78,6 +78,7 @@ def normalize_announce(self, data):
'end_time': data.get('end_time'),
'author': data.get('author'),
'created': data.get('created', now),
+ 'specific': data.get('specific'),
}
if snip.get('id') is None:
snip['id'] = self._gen_key(snip)
View
13 campaign/storage/sql.py
@@ -15,6 +15,8 @@ class Campaign(Base):
__tablename__ = 'campaigns'
id = Column('id', String(25), primary_key=True)
+ priority = Column('priority', Integer, index=True)
+ specific = Column('specific', Integer, index=True)
channel = Column('channel', String(24), index=True, nullable=True)
version = Column('version', Float, index=True, nullable=True)
product = Column('product', String(50), index=True, nullable=True)
@@ -101,6 +103,12 @@ def resolve(self, token):
def put_announce(self, data):
if data.get('note') is None:
raise StorageException('Incomplete record. Skipping.')
+ specificity = 0
+ for col in ['lang', 'loc', 'platform',
+ 'channel', 'version', 'idle_time']:
+ if col in data:
+ specificity += 1
+ data['specific'] = specificity
snip = self.normalize_announce(data)
campaign = Campaign(**snip)
self.session.add(campaign)
@@ -147,10 +155,13 @@ def get_announce(self, data):
data['idle_time'] = 0
sql += "and coalesce(idle_time, 0) <= :idle_time "
params['idle_time'] = data.get('idle_time')
- sql += " order by id"
+ sql += " order by priority desc, specific desc, created desc"
if (settings.get('dbg.show_query', False)):
print sql
print params
+ if (settings.get('db.limit')):
+ sql += " limit :limit";
+ params['limit'] = settings.get('db.limit')
items = self.engine.execute(text(sql), **dict(params))
result = []
for item in items:
View
5 campaign/templates/main.mako
@@ -27,6 +27,7 @@
<input type="hidden" name="author" value="${author}" />
<fieldset class="times">
<legend>When to show?</legend>
+<label for="priority">Priority(0=lowest):</label><input type="number" name="priority" value="0" />
<label for="start_time">Start time:</label><input type="datetime-local" name="start_time" value="" />
<label for="end_time">End time:</label><input type="datetime-local" name="end_time" value="" />
<label for="idle_time">Idle time(days):</label><input type="number" name="idle_time" value="0" />
@@ -63,12 +64,14 @@
<div class="head row">
<div class="delete">Delete?</div>
<div class="id">ID</div>
+<div class="priority">Priority</div>
<div class="created">Created</div>
<div class="start_time">Start Time</div>
<div class="end_time">End Time</div>
<div class="idle_time">Idle Time</div>
<div class="lang">Language</div>
<div class="locale">Locale</div>
+<div class="product">Product</div>
<div class="platform">Platform</div>
<div class="channel">Channel</div>
<div class="version">Version</div>
@@ -107,12 +110,14 @@
<div class="record row">
<div class="delete"><input type="checkbox" value="${note.id}"></div>
<div class="id"><a href="/redirect/${vers}/${dnote['id']}">${dnote['id']}</a></div>
+ <div class="priority">${dnote['priority']}</div>
<div class="created">${strftime(time_format, localtime(dnote['created']))}</div>
<div class="start_time">${dnote['start_time']}</div>
<div class="end_time">${dnote['end_time']}</div>
<div class="idle_time">${dnote['idle_time']} days</div>
<div class="lang">${dnote['lang']}</div>
<div class="locale">${dnote['locale']}</div>
+<div class="product">${dnote['product']}</div>
<div class="platform">${dnote['platform']}</div>
<div class="channel">${dnote['channel']}</div>
<div class="version">${dnote['version']}</div>
View
6 campaign/templates/style.css
@@ -2,10 +2,10 @@
body {font-family:Arial;}
header {padding-bottom:1em;width:100%;border:1px solid #EEE;}
header button {text-align:right;}
-#new_item label {display:inline-block;min-width:7em;text-align:right;}
+#new_item label {display:inline-block;min-width:5em;text-align:right;}
#new_item label:before {content:"\A";white-space:pre; }
+#new_item .note label {display:block;text-align:left;}
#existing .row {display:table-row;}
#existing .head {font-weight: bold; }
#existing .row div {display:table-cell;padding:2px;}
-
-
+input[type=number] {width:2em;}
View
6 campaign/tests/test_storage.py
@@ -46,8 +46,8 @@ def test_search(self):
to exercise the search algo using a lot of records. """
# really wish that update allowed chaining.
updates = [{'lang': None, 'locale': None, 'title': 'Everyone'},
- {'platform': 'a', 'channel': 'a', 'title': 'p: a;c: a'},
- {'platform': 'b', 'channel': 'a', 'title': 'p: b;c: a'},
+ {'platform': 'a', 'channel': 'a', 'title': 'p:a;c:a'},
+ {'platform': 'b', 'channel': 'a', 'title': 'p:b;c:a'},
{'platform': 'a', 'start_time': self.now + 1,
'end_time': self.now + 3, 'title': 'notyet'},
{'platform': 'a', 'end_time': self.now - 5, 'title': 'tooold'},
@@ -69,6 +69,8 @@ def test_search(self):
# only Everyone and p: a;c: a should be returned.
print "P&C check:"
self.assertEqual(len(announce), 2)
+ # Make sure the most specific entry is returned first.
+ self.assertEqual(announce[0].get('title'), 'p:a;c:a')
data = {'platform': 'a', 'channel': 'a', 'idle_time': 15}
announce = self.storage.get_announce(data)

0 comments on commit 2aee338

Please sign in to comment.
Something went wrong with that request. Please try again.