class MatrixTabularStatistic(BaseMatrixStatistic): """Table with the count and percent of answered and unanswered questions, diveded per choice. It should be used for matrix questions. """ security = ClassSecurityInfo() _constructors = (lambda *args, **kw: manage_addStatistic(MatrixTabularStatistic, *args, **kw), ) meta_type = "Naaya Survey - Matrix Tabular Statistic" meta_label = "Matrix Tabular Statistic" meta_sortorder = 300 meta_description = """Table with the count and percent of answered and unanswered questions, diveded per choice. It should be used for matrix questions.""" icon_filename = 'statistics/www/matrix_tabular_statistic.gif' security.declarePublic('render') def render(self, answers): """Render statistics as HTML code""" total, unanswered, per_row_and_choice = self.calculate(self.question, answers) return self.page(question=self.question, total=total, unanswered=unanswered, per_row_and_choice=per_row_and_choice) page = PageTemplateFile("zpt/matrix_tabular_statistics.zpt", globals()) security.declarePrivate('add_to_excel') def add_to_excel(self, state): """ adds content to the excel file based on the specific statistic type """ import xlwt answers = state['answers'] ws = state['ws'] current_row = state['current_row'] translator = self.getSite().getPortalTranslations() total, unanswered, per_row_and_choice = self.calculate(self.question, answers) #define Excel styles header_style = xlwt.easyxf('font: bold on; align: vert centre') normal_style = xlwt.easyxf('align: vert centre') #write cell elements similarly to the zpt-->html output ws.write(current_row, 1, self.question.title, header_style) current_row += 1 current_col = 2 for choice in self.question.choices: ws.write(current_row, current_col, choice, header_style) current_col += 1 ws.write(current_row, current_col, translator('Not answered'), header_style) current_row += 1 for row in self.question.rows: r = self.question.rows.index(row) ws.write(current_row, 1, row, header_style) current_col = 2 for statistics in per_row_and_choice[r]: ws.write(current_row, current_col, '%u (%.2f%%)' % (statistics[0], round(statistics[1], 2)), normal_style) current_col += 1 ws.write(current_row, current_col, '%u (%.2f%%)' % (unanswered[r][0], round(unanswered[r][1], 2)), normal_style) current_row += 1 state['current_row'] = current_row
class TextAnswerListing(BaseStatistic): """Table with the count and percent of answered and unanswered questions. """ security = ClassSecurityInfo() _constructors = (lambda *args, **kw: manage_addStatistic(TextAnswerListing, *args, **kw), ) meta_type = "Naaya Survey - Text Answer Listing" meta_label = "Text Answer Listing" meta_description = """Listing with answers posted in 'Paragraph text' and 'Single line text'""" meta_sortorder = 100 icon_filename = 'statistics/www/simple_tabular_statistic.gif' def __init__(self, id, question, lang=None, **kwargs): if not (isinstance(question, StringWidget) or isinstance(question, TextAreaWidget)): raise TypeError('Unsupported question type') BaseStatistic.__init__(self, id, question, lang=lang, **kwargs) def calculate(self, answers): """ """ return self.utSortObjsListByAttr(answers, 'modification_time') security.declarePublic('render') def render(self, answers): """Render statistics as HTML code""" return self.page(data=self.calculate(answers), question=self.question) page = PageTemplateFile("zpt/text_answer_listing.zpt", globals()) security.declarePrivate('add_to_excel') def add_to_excel(self, state): """ adds content to the excel file based on the specific statistic type """ import xlwt answers = state['answers'] ws = state['ws'] current_row = state['current_row'] translator = self.getSite().getPortalTranslations() data=self.calculate(answers) question=self.question #define Excel styles header_style = xlwt.easyxf('font: bold on; align: vert centre') normal_style = xlwt.easyxf('align: vert centre') hyper_style = xlwt.easyxf('align: vert centre; font: underline single, color-index blue') #write cell elements similarly to the zpt-->html output ws.write(current_row, 1, self.question.title, header_style) current_row += 1 ws.write(current_row, 1, translator('User'), header_style) ws.write(current_row, 2, translator('Date'), header_style) ws.write(current_row, 3, translator('Answer'), header_style) current_row += 1 for answer in data: if self.checkPermissionPublishObjects(): answer_url = answer.absolute_url() respondent = answer.get_respondent_name() ws.write(current_row, 1, xlwt.Formula('HYPERLINK' + '("%s"; "%s")' % (answer_url, respondent)), hyper_style) ws.write(current_row, 2, self.utShowDateTime(answer.modification_time), normal_style) response = answer.get(question.id, '', lang=self.gl_get_selected_language()) # try to get any response if multilingual if not response: all_responses = answer.get(question.id, '') if isinstance(all_responses, dict): all_responses = filter(None, all_responses.values()) if len(all_responses) > 0: response = all_responses[0] ws.write(current_row, 3, self.utLinkifyURLs(response) or 'No response.', normal_style) current_row += 1 state['current_row'] = current_row + 1
class SimpleTabularStatistic(BaseStatistic): """Table with the count and percent of answered and unanswered questions. """ security = ClassSecurityInfo() _constructors = (lambda *args, **kw: manage_addStatistic(SimpleTabularStatistic, *args, **kw), ) meta_type = "Naaya Survey - Simple Tabular Statistic" meta_label = "Simple Tabular Statistic" meta_description = """Table with the count and percent of answered and unanswered questions.""" meta_sortorder = 100 icon_filename = 'statistics/www/simple_tabular_statistic.gif' def __init__(self, id, question, lang=None, **kwargs): if isinstance(question, LabelWidget): raise TypeError('Unsupported question type') BaseStatistic.__init__(self, id, question, lang=lang, **kwargs) def calculate(self, question, answers): """ -> (total, answered, unanswered)""" w_id = question.getWidgetId() total = answered_count = 0 for answer in answers: val = answer.get(w_id) if val: answered_count += 1 total += 1 unanswered_count = total - answered_count if total: answered_percent = 100.0 * answered_count / total unanswered_percent = 100.0 * unanswered_count / total else: answered_percent = unanswered_percent = 0 return (total, (answered_count, answered_percent), (unanswered_count, unanswered_percent)) security.declarePublic('render') def render(self, answers): """Render statistics as HTML code""" total, answered, unanswered = self.calculate(self.question, answers) return self.page(question=self.question, total=total, answered=answered, unanswered=unanswered) page = PageTemplateFile("zpt/simple_tabular_statistics.zpt", globals()) security.declarePrivate('add_to_excel') def add_to_excel(self, state): """ adds content to the excel file based on the specific statistic type """ answers = state['answers'] ws = state['ws'] current_row = state['current_row'] translator = self.getSite().getPortalTranslations() total, answered, unanswered = self.calculate(self.question, answers) #define Excel styles header_style = xlwt.easyxf('font: bold on; align: vert centre') normal_style = xlwt.easyxf('align: vert centre') #write cell elements similarly to the zpt-->html output ws.write(current_row, 1, self.question.title, header_style) current_row += 1 ws.write(current_row, 2, translator('Count'), header_style) ws.write(current_row, 3, translator('Percent'), header_style) current_row += 1 ws.write(current_row, 1, translator('Answered'), header_style) ws.write(current_row, 2, answered[0], normal_style) ws.write(current_row, 3, '%.2f%%' % (round(answered[1], 2), ), normal_style) current_row += 1 ws.write(current_row, 1, translator('Not answered'), header_style) ws.write(current_row, 2, unanswered[0], normal_style) ws.write(current_row, 3, '%.2f%%' % (round(unanswered[1], 2), ), normal_style) current_row += 1 ws.write(current_row, 1, translator('Total'), header_style) ws.write(current_row, 2, total, normal_style) ws.write(current_row, 3, '100%%', normal_style) current_row += 1 state['current_row'] = current_row
class ComboboxMatrixTabularStatistic(BaseStatistic): """Table with the count and percent of answered and unanswered questions, diveded per row and choice. It should be used for combobox matrix questions. """ security = ClassSecurityInfo() _constructors = (lambda *args, **kw: manage_addStatistic( ComboboxMatrixTabularStatistic, *args, **kw), ) meta_type = "Naaya Survey - Combobox Matrix Tabular Statistic" meta_label = "Combobox Matrix Tabular Statistic" meta_sortorder = 320 meta_description = """Table with the count and percent of answered and unanswered questions, diveded per row and choice. It should be used for combobox matrix questions.""" icon_filename = 'statistics/www/matrix_tabular_statistic.gif' def __init__(self, id, question, lang=None, **kwargs): if not isinstance(question, ComboboxMatrixWidget): raise TypeError('Unsupported question type') BaseStatistic.__init__(self, id, question, lang=lang, **kwargs) def calculate(self, question, answers): """ -> (total, answered, unanswered, per_choice)""" w_id = question.getWidgetId() total = answered_count = 0 per_row_and_choice_count = [[[0 for v in question.values] for c in question.choices] for r in question.rows] unanswered_count = [[0 for c in question.choices] for r in question.rows] for answer in answers: total += 1 answer = answer.get(w_id) if answer is None: for r in range(len(question.rows)): for c in range(len(question.choices)): unanswered_count[r][c] += 1 continue for r, per_row_choices in enumerate(answer): for c, value in enumerate(per_row_choices): if value: per_row_and_choice_count[r][c][value] += 1 else: unanswered_count[r][c] += 1 if total: unanswered_stats = [[(x, 100.0 * x / total) for x in row] for row in unanswered_count] per_row_and_choice_stats = [[[(i, 100.0 * i / total) for i in per_value_count] for per_value_count in per_choice_count] for per_choice_count in per_row_and_choice_count] else: unanswered_stats = [[(0, 0.0) for x in row] for row in unanswered_count] per_row_and_choice_stats = [[[(0, 0.0) for i in per_value_count] for per_value_count in per_choice_count] for per_choice_count in per_row_and_choice_count] return (total, unanswered_stats, per_row_and_choice_stats) security.declarePublic('render') def render(self, answers): """Render statistics as HTML code""" total, unanswered, per_row_and_choice = self.calculate(self.question, answers) return self.page(question=self.question, total=total, unanswered=unanswered, per_row_and_choice=per_row_and_choice) page = PageTemplateFile("zpt/combobox_matrix_tabular_statistics.zpt", globals()) security.declarePrivate('add_to_excel') def add_to_excel(self, state): """ adds content to the excel file based on the specific statistic type """ import xlwt answers = state['answers'] ws = state['ws'] current_row = state['current_row'] translator = self.getSite().getPortalTranslations() total, unanswered, per_row_and_choice = self.calculate(self.question, answers) #define Excel styles header_style = xlwt.easyxf('font: bold on; align: vert centre') normal_style = xlwt.easyxf('align: vert centre') italic_style = xlwt.easyxf('align: vert centre; font: italic on') #write cell elements similarly to the zpt-->html output ws.write(current_row, 1, self.question.title, header_style) current_row += 1 ws.write(current_row, 1, translator('row'), italic_style) ws.write(current_row, 2, translator('value'), italic_style) current_col = 3 for choice in self.question.choices: ws.write(current_row, current_col, choice, header_style) current_col += 1 current_row += 1 for row in self.question.rows: r = self.question.rows.index(row) current_col = 1 ws.write_merge(current_row, current_row+len(self.question.values), 1, 1, row, header_style) for value in self.question.values: v = self.question.values.index(value) current_col = 2 ws.write(current_row, current_col, value, header_style) current_col += 1 for statistic in per_row_and_choice[r]: ws.write(current_row, current_col, '%u (%.2f%%)' % (statistic[v][0], round(statistic[v][1], 2)), normal_style) current_col += 1 current_row += 1 current_col = 2 ws.write(current_row, current_col, translator('Not answered'), header_style) current_col += 1 for statistic in unanswered[r]: ws.write(current_row, current_col, '%u (%.2f%%)' % (statistic[0], round(statistic[1], 2)), normal_style) current_col += 1 current_row += 1 state['current_row'] = current_row + 1
class MatrixCssBarChartStatistic(BaseMatrixStatistic): """Table with the count and percent of answered and unanswered questions, diveded per choice. It should be used for matrix questions. """ security = ClassSecurityInfo() _constructors = (lambda *args, **kw: manage_addStatistic( MatrixCssBarChartStatistic, *args, **kw), ) meta_type = "Naaya Survey - Matrix CSS Bar Chart Statistic" meta_label = "Matrix CSS Bar Chart Statistic" meta_sortorder = 311 meta_description = """Table with the count and percent of answered and unanswered questions, diveded per choice. It should be used for matrix questions.""" icon_filename = "statistics/www/matrix_css_barchart_statistic.gif" security.declarePublic('getColors') def getPallete(self, numcolors): """Get a pallete of numcolors colors. The colors are a list of hexadecimal codes, e.g. '#f0b0d0'. """ h, s, v = 0.01, 0.55, 0.95 step = float(1 - h) / numcolors colors = [] for i in range(numcolors): r, g, b = colorsys.hsv_to_rgb(h, s, v) color = "%02x%02x%02x" % tuple([int(x * 255) for x in h, s, v]) colors.append(color) h += step return colors security.declarePublic('render') def render(self, answers): """Render statistics as HTML code""" total, unanswered, per_row_and_choice = self.calculate( self.question, answers) return self.page( question=self.question, total=total, unanswered=unanswered, per_row_and_choice=per_row_and_choice, colors=self.getPallete(len(self.question.choices) + 1)) page = PageTemplateFile("zpt/matrix_css_barchart_statistics.zpt", globals()) security.declarePrivate('add_to_excel') def add_to_excel(self, state): """ adds content to the excel file based on the specific statistic type """ import xlwt temp_folder = state['temp_folder'] answers = state['answers'] ws = state['ws'] current_row = state['current_row'] translator = self.getSite().getPortalTranslations() file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'www', 'barchart.png') total, unanswered, per_row_and_choice = self.calculate( self.question, answers) colors = self.getPallete(len(self.question.choices) + 1) #define Excel styles header_style = xlwt.easyxf('font: bold on; align: vert centre') normal_style = xlwt.easyxf('align: vert centre') #write cell elements similarly to the zpt-->html output ws.write(current_row, 1, self.question.title, header_style) current_row += 1 for row in self.question.rows: r = self.question.rows.index(row) ws.write_merge(current_row, current_row + len(self.question.choices), 1, 1, row, header_style) for choice in self.question.choices: c = self.question.choices.index(choice) ws.write(current_row, 2, choice, header_style) width = int(per_row_and_choice[r][c][1]) * 2 height = 12 if width * height: path = self.set_bitmap_props(file_path, width, height, temp_folder) ws.insert_bitmap(path, current_row, 3, 0, 3) current_row += 1 ws.write(current_row, 2, translator('Not answered'), header_style) width = int(unanswered[r][1]) * 2 if width * height: path = self.set_bitmap_props(file_path, width, height, temp_folder) ws.insert_bitmap(path, current_row, 3, 0, 3) current_row += 2 state['current_row'] = current_row