Mercurial Hosting > luan
changeset 291:a35d1177bbf0
implement Ab_testing.web_page()
git-svn-id: https://luan-java.googlecode.com/svn/trunk@292 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Tue, 09 Dec 2014 23:24:07 +0000 |
parents | 9a0cc6d9b27b |
children | e8a2153f6ce1 |
files | core/src/luan/LuanFunction.java dist/jars/luan-core-trunk.jar dist/jars/luan-logging-trunk.jar dist/jars/luan-lucene-trunk.jar dist/jars/luan-mail-trunk.jar dist/jars/luan-web-trunk.jar lucene/src/luan/modules/lucene/Ab_testing.luan lucene/src/luan/modules/lucene/LuceneSearcher.java |
diffstat | 8 files changed, 130 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
diff -r 9a0cc6d9b27b -r a35d1177bbf0 core/src/luan/LuanFunction.java --- a/core/src/luan/LuanFunction.java Tue Dec 09 04:39:18 2014 +0000 +++ b/core/src/luan/LuanFunction.java Tue Dec 09 23:24:07 2014 +0000 @@ -12,7 +12,7 @@ } @Override public String repr() { - return "<function>"; + return "<" + toString() + ">"; } }
diff -r 9a0cc6d9b27b -r a35d1177bbf0 dist/jars/luan-core-trunk.jar Binary file dist/jars/luan-core-trunk.jar has changed
diff -r 9a0cc6d9b27b -r a35d1177bbf0 dist/jars/luan-logging-trunk.jar Binary file dist/jars/luan-logging-trunk.jar has changed
diff -r 9a0cc6d9b27b -r a35d1177bbf0 dist/jars/luan-lucene-trunk.jar Binary file dist/jars/luan-lucene-trunk.jar has changed
diff -r 9a0cc6d9b27b -r a35d1177bbf0 dist/jars/luan-mail-trunk.jar Binary file dist/jars/luan-mail-trunk.jar has changed
diff -r 9a0cc6d9b27b -r a35d1177bbf0 dist/jars/luan-web-trunk.jar Binary file dist/jars/luan-web-trunk.jar has changed
diff -r 9a0cc6d9b27b -r a35d1177bbf0 lucene/src/luan/modules/lucene/Ab_testing.luan --- a/lucene/src/luan/modules/lucene/Ab_testing.luan Tue Dec 09 04:39:18 2014 +0000 +++ b/lucene/src/luan/modules/lucene/Ab_testing.luan Tue Dec 09 23:24:07 2014 +0000 @@ -1,5 +1,7 @@ import "luan:Math" import "luan:Table" +import "luan:Io" +import "luan:web/Http" function of(index) @@ -12,6 +14,13 @@ function ab_testing.test(test) test.name or error "name not defined" test.values or error "values not defined" + + -- list of event names + test.events or error "events not defined" + + -- map of event name to aggregator factory + test.aggregator_factories or error "aggregator_factories not defined" + -- test.date_field is optional local field = "ab_test_" .. test.name @@ -19,22 +28,21 @@ index.fields[field] = field .. " index" test.field = field - -- pass in map of name to aggregator factory - -- returns map of name to (map of value to result) and "start_date" - function test.results(aggregator_factories) + -- returns map of event name to (map of value to result) and "start_date" + function test.results() return index.Searcher( function(searcher) local results = {} - for name in pairs(aggregator_factories) do + for name in pairs(test.aggregator_factories) do results[name] = {} end local date_field = test.date_field local start_date = nil for _, value in ipairs(test.values) do local aggregators = {} - for name, factory in pairs(aggregator_factories) do + for name, factory in pairs(test.aggregator_factories) do aggregators[name] = factory() end - local query = { [field] = value } + local query = index.Query.term{ [field] = value } searcher.search(query, function(doc) for _, aggregator in pairs(aggregators) do aggregator.aggregate(doc) @@ -55,6 +63,36 @@ end ) end + function test.fancy_results() + local events = test.events + local results = test.results() + local fancy = {} + fancy.start_date = results.start_date + local event = events[1] + fancy[event] = {} + for value, count in pairs(results[event]) do + fancy[event][value] = {} + fancy[event][value].count = count + fancy[event][value].pct_of_total = 100 + fancy[event][value].pct_of_prev = 100 + end + local all = results[event] + local prev = all + for i in range(2,#events) do + event = events[i] + fancy[event] = {} + for value, count in pairs(results[event]) do + fancy[event][value] = {} + fancy[event][value].count = count + fancy[event][value].pct_of_total = percent(count,all[value]) + fancy[event][value].pct_of_prev = percent(count,prev[value]) + end + prev = results[event] + end + return fancy + end + + ab_testing.test_map[test.name] = test ab_testing.test_list[#ab_testing.test_list + 1] = test @@ -88,6 +126,19 @@ end end + function ab_testing.web_page(test_names) + return { service = function() + local results = {} + for _, name in ipairs(test_names) do + local test = ab_testing.test_map[name] + test or error("test not found: "..name) + results[name] = test.fancy_results() + end + Io.stdout = Http.response.text_writer() + html(test_names,ab_testing.test_map,results) + end } + end + return ab_testing end @@ -108,7 +159,7 @@ end end -count_all = count( function() return true end ) +count_all = count( function(doc) return true end ) -- fn(doc) should return number to add to result, return 0 for nothing function sum(fn) @@ -124,7 +175,7 @@ -local function percent(x,total) +function percent(x,total) if total==0 then return 0 else @@ -132,29 +183,68 @@ end end -function fancy(results,names) - local fancy = {} - fancy.start_date = results.start_date - local name = names[1] - fancy[name] = {} - for value, count in pairs(result[name]) do - fancy[name][value] = {} - fancy[name][value].count = count - fancy[name][value].pct_of_total = 100 - fancy[name][value].pct_of_prev = 100 + +function html(test_names,tests,results) %> +<html> +<body> +<h2>A/B Tests</h2> +<% + for _, test_name in ipairs(test_names) do + local test = tests[test_name] + local result = results[test_name] + local n = #test.values + %> + <h3><%=test_name%></h3> + <table> + <tr> + <th>Event</th> + <th class="top" colspan="<%=n%>">Count</th> + <th class="top" colspan="<%=n%>">% of total</th> + <th class="top" colspan="<%=n%>">% of prev</th> + </tr> + <tr> + <th></th> + <% + for _ in range(1,3) do + for _, value in ipairs(test.values) do + %> + <th class="top"><%=value%></th> + <% + end + end + %> + </tr> + <% + for _, event in ipairs(test.events) do + local event_values = result[event] + %> + <tr> + <td><%=event%></td> + <% + for _, value in ipairs(test.values) do + %> + <td><%=event_values[value].count%></th> + <% + end + for _, value in ipairs(test.values) do + %> + <td><%=event_values[value].pct_of_total%></th> + <% + end + for _, value in ipairs(test.values) do + %> + <td><%=event_values[value].pct_of_prev%></th> + <% + end + %> + </tr> + <% + end + %> + </table> + <% end - local all = result[name] - local prev = all - for i in range(2,#names) do - name = names[i] - fancy[name] = {} - for value, count in pairs(result[name]) do - fancy[name][value] = {} - fancy[name][value].count = count - fancy[name][value].pct_of_total = percent(count,all[value]) - fancy[name][value].pct_of_prev = percent(count,prev[value]) - end - prev = result[name] - end - return fancy -end +%> +</body> +</html> +<% end
diff -r 9a0cc6d9b27b -r a35d1177bbf0 lucene/src/luan/modules/lucene/LuceneSearcher.java --- a/lucene/src/luan/modules/lucene/LuceneSearcher.java Tue Dec 09 04:39:18 2014 +0000 +++ b/lucene/src/luan/modules/lucene/LuceneSearcher.java Tue Dec 09 23:24:07 2014 +0000 @@ -65,8 +65,12 @@ }; private static abstract class MyCollector extends Collector { + int docBase; + @Override public void setScorer(Scorer scorer) {} - @Override public void setNextReader(AtomicReaderContext context) {} + @Override public void setNextReader(AtomicReaderContext context) { + this.docBase = context.docBase; + } @Override public boolean acceptsDocsOutOfOrder() { return true; } @@ -78,7 +82,7 @@ Collector col = new MyCollector() { @Override public void collect(int doc) { try { - LuanTable docTbl = doc(luan,doc); + LuanTable docTbl = doc(luan,docBase+doc); luan.call(fn,new Object[]{docTbl}); } catch(LuanException e) { throw new LuanRuntimeException(e);