#!/usr/bin/python
# coding: utf-8
 
#--------------------------------------------------------------------
# Fichero:  informe.py
# Objetivo: Hacer un informe con los resultados de la encuesta
# Autor:    Pedro Reina <[email protected]>
# Fecha:    D.11.12.2016
# Licencia: CC0 1.0 Universal
#           https://creativecommons.org/publicdomain/zero/1.0/
#--------------------------------------------------------------------
 
#------------------------------------------------
# Variables del programa
#------------------------------------------------
 
# El archivo con la base de datos
Origen = 'encuesta.db'
 
# El PDF para imprimir
Destino = 'informe.pdf'
 
# Consultas a la base de datos
ConsultaPregunta = 'SELECT * FROM pregunta'
ConsultaPlazo = 'SELECT * FROM plazo ORDER BY limite'
 
# Primera linea del documento
Titulo = 'Encuesta sobre el profesor Pedro Reina'
 
# Los márgenes de la página, en centímetros
MargenIzquierdo = 2
MargenSuperior = 2
 
# La distancia entre líneas de texto, en centímetros
Interlineado = 0.75
 
#------------------------------------------------
# Módulos necesarios
#------------------------------------------------
 
# Another Python SQLite Wrapper
import apsw
 
# Matemáticas
import math
 
# Creación de PDF con ReportLab
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.lib.pagesizes import A4
from reportlab.graphics.shapes import Drawing, colors
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.platypus import *
from reportlab.lib.styles import getSampleStyleSheet
 
#------------------------------------------------
# Funciones
#------------------------------------------------
 
#------------------------------------------------
# El programa
#------------------------------------------------
 
# Informamos al usuario
print 'Origen: ' + Origen
print 'Destino: ' + Destino
print 'Preparando...'
 
# Abrimos conexión a la base de datos
Conexion = apsw.Connection (Origen)
 
# Creamos un cursor para dialogar con la conexión
Cursor = Conexion.cursor()
 
# Conversión de medidas: todas las hemos pedido en cm
# pero se usan en puntos tipográficos
MargenIzquierdo *= cm
MargenSuperior *= cm
Interlineado *= cm
 
# Preparamos el PDF
Pdf = canvas.Canvas (Destino, pagesize=A4)
Pdf.setAuthor ('Pedro Reina')
Pdf.setTitle ('Informe de encuesta')
 
# Guardamos las dimensiones de la página
Anchura, Altura = A4
 
# Preparamos el estilo de los párrafos con el texto de la pregunta
ListaEstilos = getSampleStyleSheet()
Estilo = ListaEstilos['BodyText']
Estilo.fontSize = 12
 
# Consultamos los límites del plazo de la consulta
Registro = 1
for Fila in Cursor.execute (ConsultaPlazo):
    if Registro == 1:
        Inicio = Fila[0]
        Registro = 2
    else:
        Final = Fila[0]
 
# Preparamos el título
Titulo += ' de ' + Inicio + ' a ' + Final
 
# Leemos los registros
Registro = 1
for Fila in Cursor.execute (ConsultaPregunta):
 
    # Tomamos los campos del registro
    Texto = Fila[0]
    R1 = Fila[1]
    R2 = Fila[2]
    R3 = Fila[3]
    R4 = Fila[4]
    R5 = Fila[5]
 
    # Corrección de tags
    Texto = Texto.replace ('<B>', '<b>')
    Texto = Texto.replace ('</B>', '</b>')
 
    # Numeramos las preguntas
    Texto = str(Registro) + '. ' + Texto
 
    # Cálculos estadísticos
    Maximo = max(R1, R2, R3, R4, R5)
    NumRespuestas = R1 + R2 + R3 + R4 + R5
    Media = float(R1 + 2*R2 + 3*R3 + 4*R4 + 5*R5) / NumRespuestas
    DesvTipica = (math.sqrt(float(R1 + 4*R2 + 9*R3 + 16*R4 + 25*R5) /
                  NumRespuestas - Media*Media))
    Media = round(Media, 1)
    DesvTipica = round(DesvTipica, 1)
 
    # Descripción de la estadística
    Estadistica = ('Respuestas: ' + str (NumRespuestas) + '. ' +
                  'Media: ' + str (Media) + '. ' +
                  u'Desviación típica: ' + str (DesvTipica))
 
    # Vamos a imprimir dos preguntas por página
    # Esta variable indica la posición inicial de dibujo de la
    #   pregunta en la página
    if Registro % 2:
        Base = 0
    else:
        Base = - Altura / 2
 
    # Posición inicial de las líneas escritas
    Linea = Base + Altura - MargenSuperior
 
    # Escribimos los textos
    Pdf.setFont('Helvetica', 14)
    Pdf.drawString(MargenIzquierdo, Linea, Titulo)
    Pdf.setFont('Helvetica', 12)
    Linea -= Interlineado
    Parrafo = Paragraph(Texto, Estilo)
    AnchuraParrafo, AlturaParrafo = (
        Parrafo.wrapOn (Pdf, Anchura - 2 * MargenIzquierdo, Altura))
    Linea -= AlturaParrafo
    Parrafo.drawOn(Pdf, MargenIzquierdo, Linea)
    Linea -= Interlineado
    Pdf.drawString(MargenIzquierdo, Linea, Estadistica)
 
    # El diagrama de barras
    Dibujo = Drawing (400, 200)
    Datos = [ (R1, R2, R3, R4, R5) ]
    Diagrama = VerticalBarChart()
    Diagrama.x = 50
    Diagrama.y = 50
    Diagrama.height = 140
    Diagrama.width = 300
    Diagrama.data = Datos
    Diagrama.bars[0].fillColor = colors.gray
    Diagrama.barLabelFormat = '%d'
    Diagrama.barLabels.dy = 8
    Diagrama.valueAxis.valueMin = 0
    Diagrama.valueAxis.valueMax = max(Maximo, 1)
    Diagrama.valueAxis.valueStep = max(Maximo/4, 1)
    Diagrama.categoryAxis.labels.dy = -2
    Diagrama.categoryAxis.categoryNames = ['1','2','3','4','5']
    Dibujo.add (Diagrama)
    Dibujo.drawOn (Pdf, 100, Base+520-AlturaParrafo)
 
    # Fin de página
    if Registro % 2 == 0:
        Pdf.showPage()
    Registro += 1
 
# Escribimos el PDF
Pdf.save()
 
# Cerramos la conexión
Conexion.close (True)
 
# Informamos al usuario
print 'Terminado.'