Changeset 199

Show
Ignore:
Timestamp:
08/23/08 16:27:40 (10 months ago)
Author:
rgrp
Message:

[shakespeare/stats][m]: substantial improvements to stats in both core and WUI.

  • Add word stats support in both core and in WUI
  • Improve tests to catch bug with existing text stats
  • Other WUI improvements e.g. to deal with non-existent texts, and provide an index page
  • TODO: word index page
Location:
trunk/shakespeare
Files:
7 modified
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/shakespeare/controllers/stats.py

    r193 r199  
    1111    def index(self): 
    1212        return render('stats/index') 
    13      
     13 
     14    def text_index(self): 
     15        # only get those texts with stats 
     16        c.texts = model.Material.query.all() 
     17        import shakespeare.controllers.text 
     18        ctrl = shakespeare.controllers.text.TextController() 
     19        return ctrl.index() 
     20 
    1421    def text(self, id): 
    1522        text_name = id 
    1623        text = model.Material.byName(text_name) 
     24        # no id or no text by that id 
     25        if not text: 
     26            return self.text_index() 
    1727        stats = shakespeare.stats.Stats() 
    1828        c.text = text 
     
    2333        return render('stats/text') 
    2434 
     35    def word_index(self): 
     36        return '' 
     37     
     38    def word(self, id): 
     39        if id is None: 
     40            return self.word_index() 
     41        word = id 
     42        c.word = word 
     43        stats = shakespeare.stats.Stats() 
     44        c.stats = stats.word_stats(word) 
     45        # will not have that many texts so do not need to limit c.stats 
     46        data = [ (s.text.title, s.freq) for s in c.stats ] 
     47        c.img_url = self.vertical_bar_chart(data) 
     48        return render('stats/word') 
     49 
    2550    # TODO: factor this out to its module (?) 
    2651    def vertical_bar_chart(self, data, width=500): 
     52        if not data: 
     53            return '' 
    2754        # tranpose 
    2855        tdata = zip(*data) 
  • trunk/shakespeare/stats.py

    r192 r199  
    6060 
    6161    def text_stats(self, text): 
    62         '''Return word statistics for text, most popular word first.''' 
    63         stats = model.Statistic.query.order_by(model.Statistic.freq.desc()).all() 
     62        '''Statistics for text, most popular word first.''' 
     63        stats = model.Statistic.query.filter_by(text=text).order_by( 
     64                model.Statistic.freq.desc() 
     65                ).all() 
    6466        return stats 
    6567 
     68    def word_stats(self, word): 
     69        '''Statistics for word (i.e. which texts use it) in order or 
     70        usage.''' 
     71        stats = model.Statistic.query.filter_by(word=word).order_by( 
     72                model.Statistic.freq.desc() 
     73                ).all() 
     74        return stats 
     75 
  • trunk/shakespeare/templates/stats/index.html

    r187 r199  
    55 
    66  <div py:match="content"> 
    7     <p>This section provides statistical information about word occurences in 
    8     the various textual materials available on the site. If you know the name 
    9     of a text you can get information by visiting ./text_name/ 
     7    <p>This section provides statistical information about the various textual 
     8    materials available on the site. 
    109    </p> 
     10    <p> 
     11      Currently information is provided organized by: 
     12    </p> 
     13    <ul> 
     14      <li> 
     15        <a href="${h.url_for(controller='stats', action='text', 
     16          id=None)}">Text</a> 
     17      </li> 
     18      <li> 
     19        <a href="${h.url_for(controller='stats', action='word', 
     20          id=None)}">Word</a> 
     21      </li> 
     22    </ul> 
    1123  </div> 
    1224 
  • trunk/shakespeare/templates/stats/text.html

    r193 r199  
    99      alt="Word Statistics Bar Chart" /> 
    1010 
    11     <table border="1" style="margin-left: 550px;"> 
     11    <p py:if="not c.stats"> 
     12      Sorry, no statistics are available for ${c.text.title} (name: ${c.text.name}) 
     13    </p> 
     14    <table style="margin-left: 550px;"> 
    1215    <thead> 
    1316      <tr> 
  • trunk/shakespeare/templates/stats/word.html

    r193 r199  
    22  xmlns:xi="http://www.w3.org/2001/XInclude"> 
    33   
    4   <py:def function="page_title">Stats for ${c.text.title}</py:def> 
     4  <py:def function="page_title">Stats for '${c.word}'</py:def> 
    55 
    66  <div py:match="content"> 
     
    99      alt="Word Statistics Bar Chart" /> 
    1010 
    11     <table border="1" style="margin-left: 550px;"> 
     11    <p py:if="not c.stats"> 
     12      Sorry, no statistics are available for ${c.text.title} (name: ${c.text.name}) 
     13    </p> 
     14    <table style="margin-left: 550px;"> 
    1215    <thead> 
    1316      <tr> 
    1417        <th>Index</th> 
    1518        <th> 
    16           Word   
     19          Text 
    1720        </th> 
    1821        <th> 
     
    2730        </td> 
    2831        <td> 
    29           ${stat.word} 
     32          ${stat.text.title} 
    3033        </td> 
    3134        <td> 
  • trunk/shakespeare/tests/__init__.py

    r187 r199  
    1818from routes import url_for 
    1919 
    20 __all__ = ['url_for', 'TestController', 'make_fixture' ] 
     20__all__ = ['url_for', 'TestController', 'make_fixture', 'make_fixture2' ] 
    2121 
    2222here_dir = os.path.dirname(os.path.abspath(__file__)) 
     
    6666    return sonnet18 
    6767 
     68def make_fixture2(): 
     69    import shakespeare.model as model 
     70    sonnet18_name = 'test_sonnet18_2' 
     71    sonnet18 = model.Material.byName(sonnet18_name) 
     72    if not sonnet18: 
     73        sonnet18 = model.Material(name=sonnet18_name, 
     74                title='Sonnet 18 Duplicate', 
     75                ) 
     76        model.Session.flush() 
     77    sonnet18.content = sonnet18_text 
     78    return sonnet18 
    6879 
    6980class TestController(object): 
  • trunk/shakespeare/tests/functional/test_stats.py

    r187 r199  
    88 
    99    text = make_fixture() 
     10    text2 = make_fixture2() 
    1011 
    1112    def setUp(self): 
     
    2122        res = self.app.get(url) 
    2223        assert 'Stats' in res 
     24 
     25    def test_text_stats_index(self): 
     26        url = url_for(controller='stats', action='text', id=None) 
     27        res = self.app.get(url) 
     28        assert self.text.name in res 
     29        assert self.text2.name in res 
    2330     
    24     def test_stats(self): 
    25         text = make_fixture() 
     31    def test_text_stats(self): 
    2632        url = url_for(controller='stats', action='text', id=self.text.name) 
    2733        res = self.app.get(url) 
    2834        assert 'summer' in res 
    2935 
     36    # TODO: stats for a text with no associated items  
     37    def test_text_no_stats(self): 
     38        url = url_for(controller='stats', action='text', id=self.text2.name) 
     39        res = self.app.get(url) 
     40        assert 'Sorry, no statistics' in res 
     41 
     42    def test_word_stats(self): 
     43        shakespeare.tests.test_stats.stats_fixture(self.text2) 
     44        word = 'summer' 
     45        url = url_for(controller='stats', action='word', id=word) 
     46        res = self.app.get(url) 
     47        assert 'summer' in res 
     48        assert self.text.title in res 
     49        assert self.text2.title in res 
     50        assert '3' in res 
     51 
  • trunk/shakespeare/tests/test_stats.py

    r187 r199  
    1818        self.stats = shakespeare.stats.Stats() 
    1919        self.text = make_fixture() 
     20        self.text2 = make_fixture2() 
    2021        model.Session.begin() 
    2122 
     
    4445 
    4546    def test_text_stats(self): 
     47        # create stats for at least 2 texts to make sure we only pick up one 
    4648        stats_fixture(self.text) 
     49        stats_fixture(self.text2) 
    4750 
    4851        stats = self.stats.text_stats(self.text) 
     
    5457        assert stats[2].word == 'summer' 
    5558        assert stats[2].freq == 3 
     59     
     60    def test_word_stats(self): 
     61        stats_fixture(self.text) 
     62        stats_fixture(self.text2) 
     63        stats = self.stats.word_stats('summer') 
     64        assert len(stats) == 2 
     65        assert stats[0].text.name == self.text.name 
     66        assert stats[0].freq == 3 
     67        # same text so should be the same! 
     68        assert stats[0].freq == stats[1].freq 
    5669 
    5770 
    58