public
Description: Screenplay writing program
Homepage: http://www.oskusoft.com
Clone URL: git://github.com/oskusalerma/blyte.git
oskusalerma (author)
Mon Sep 08 06:23:11 -0700 2008
commit  21ce2faf8dca2eb52ea51480ae1bf6cae0d51a38
tree    5e1066594e119362fef504601088ba95f04a6ace
parent  dfcbe4bd651227bc8dc9b1142f3fc5b74da7cede
blyte / characterreport.py
100644 180 lines (130 sloc) 5.329 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import gutil
import misc
import pdf
import pml
import screenplay
import util
 
from wxPython.wx import *
 
def genCharacterReport(mainFrame, sp):
    report = CharacterReport(sp)
 
    if not report.cinfo:
        wxMessageBox("No characters speaking found.",
                     "Error", wxOK, mainFrame)
 
        return
 
    charNames = []
    for s in util.listify(report.cinfo, "name"):
        charNames.append(misc.CheckBoxItem(s))
    
    dlg = misc.CheckBoxDlg(mainFrame, "Report type", report.inf,
        "Information to include:", False, charNames,
        "Characters to include:", True)
 
    ok = False
    if dlg.ShowModal() == wxID_OK:
        ok = True
 
        for i in range(len(report.cinfo)):
            report.cinfo[i].include = charNames[i].selected
 
    dlg.Destroy()
 
    if not ok:
        return
    
    data = report.generate()
 
    gutil.showTempPDF(data, sp.cfgGl, mainFrame)
    
class CharacterReport:
    def __init__(self, sp):
 
        self.sp = sp
        
        ls = sp.lines
 
        # key = character name, value = CharInfo
        chars = {}
 
        name = None
        scene = "(NO SCENE NAME)"
        
        # how many lines processed for current speech
        curSpeechLines = 0
        
        for i in xrange(len(ls)):
            line = ls[i]
 
            if (line.lt == screenplay.SCENE) and\
                   (line.lb == screenplay.LB_LAST):
                scene = util.upper(line.text)
                
            elif (line.lt == screenplay.CHARACTER) and\
                   (line.lb == screenplay.LB_LAST):
                name = util.upper(line.text)
                curSpeechLines = 0
                
            elif line.lt in (screenplay.DIALOGUE, screenplay.PAREN) and name:
                ci = chars.get(name)
                if not ci:
                    ci = CharInfo(name, sp)
                    chars[name] = ci
 
                if scene:
                    ci.scenes[scene] = ci.scenes.get(scene, 0) + 1
 
                if curSpeechLines == 0:
                    ci.speechCnt += 1
 
                curSpeechLines += 1
 
                # PAREN lines don't count as spoken words
                if line.lt == screenplay.DIALOGUE:
                    ci.lineCnt += 1
 
                    words = util.splitToWords(line.text)
 
                    ci.wordCnt += len(words)
                    ci.wordCharCnt += reduce(lambda x, y: x + len(y), words,
                                             0)
                
                ci.pages.addPage(sp.line2page(i))
 
            else:
                name = None
                curSpeechLines = 0
 
        # list of CharInfo objects
        self.cinfo = []
        for v in chars.values():
            self.cinfo.append(v)
 
        self.cinfo.sort(cmpLines)
 
        self.totalSpeechCnt = self.sum("speechCnt")
        self.totalLineCnt = self.sum("lineCnt")
        self.totalWordCnt = self.sum("wordCnt")
        self.totalWordCharCnt = self.sum("wordCharCnt")
 
        # information types and what to include
        self.INF_BASIC, self.INF_PAGES, self.INF_LOCATIONS = range(3)
        self.inf = []
        for s in ["Basic information", "Page list", "Location list"]:
            self.inf.append(misc.CheckBoxItem(s))
 
    # calculate total sum of self.cinfo.{name} and return it.
    def sum(self, name):
        return reduce(lambda tot, ci: tot + getattr(ci, name), self.cinfo, 0)
        
    def generate(self):
        tf = pml.TextFormatter(self.sp.cfg.paperWidth,
                               self.sp.cfg.paperHeight, 20.0, 12)
 
        for ci in self.cinfo:
            if not ci.include:
                continue
            
            tf.addText(ci.name, fs = 14,
                       style = pml.BOLD | pml.UNDERLINED)
 
            if self.inf[self.INF_BASIC].selected:
                tf.addText("Speeches: %d, Lines: %d (%.2f%%),"
                    " per speech: %.2f" % (ci.speechCnt, ci.lineCnt,
                    util.pctf(ci.lineCnt, self.totalLineCnt),
                    util.safeDiv(ci.lineCnt, ci.speechCnt)))
 
                tf.addText("Words: %d, per speech: %.2f,"
                    " characters per: %.2f" % (ci.wordCnt,
                    util.safeDiv(ci.wordCnt, ci.speechCnt),
                    util.safeDiv(ci.wordCharCnt, ci.wordCnt)))
                
            if self.inf[self.INF_PAGES].selected:
                tf.addWrappedText("Pages: %d, list: %s" % (len(ci.pages),
                    ci.pages), " ")
 
            if self.inf[self.INF_LOCATIONS].selected:
                tf.addSpace(2.5)
 
                for it in util.sortDict(ci.scenes):
                    tf.addText("%3d %s" % (it[1], it[0]),
                               x = tf.margin * 2.0, fs = 10)
            
            tf.addSpace(5.0)
            
        return pdf.generate(tf.doc)
 
# information about one character
class CharInfo:
    def __init__(self, name, sp):
        self.name = name
 
        self.speechCnt = 0
        self.lineCnt = 0
        self.wordCnt = 0
        self.wordCharCnt = 0
        self.scenes = {}
        self.include = True
        self.pages = screenplay.PageList(sp.getPageNumbers())
 
def cmpLines(c1, c2):
    ret = cmp(c2.lineCnt, c1.lineCnt)
 
    if ret != 0:
        return ret
    else:
        return cmp(c1.name, c2.name)