from django.db import models from django.conf import settings import io from django.core import serializers from django.templatetags.static import static from PIL import Image, ImageDraw, ImageFont import matplotlib.pyplot as plt import numpy as np # Create your models here. class Response(models.Model): # user data first_name = models.CharField("First Name", max_length=50) last_name = models.CharField("Last Name", max_length=50) email = models.EmailField("Email", max_length=254) # scores decision = models.PositiveIntegerField("Decision Making") decision_it = models.PositiveIntegerField("Decision Making - IT") decision_legal = models.PositiveIntegerField("Decision Making - Legal/Procurement") resources = models.PositiveIntegerField("Resources") impact = models.PositiveIntegerField("Impact") velocity = models.PositiveIntegerField("Velocity") expectations = models.PositiveIntegerField("Expectations") # self.overall overall = models.PositiveIntegerField("Overall Score") results = models.ImageField("Results Image", blank=True, null=True) results_pdf = models.ImageField("Results PDF", blank=True, null=True) class Meta: verbose_name = "Response" verbose_name_plural = "Responses" def __str__(self): return f'{self.first_name} {self.last_name}\'s Response' def save(self, *args, **kwargs): self.results = f'{self.id}.png' self.results_pdf = f'{self.id}.pdf' super().save(*args, **kwargs) fig, ax = plt.subplots(figsize=(8, 8)) height = list(serializers.serialize("python", [self])[0]['fields'].values())[3:-2] print(f'height {height}') bars = tuple([field.verbose_name for field in self._meta.get_fields()][4:-2]) y_pos = np.arange(len(bars)) for i, v in enumerate(height): if v > 10: ax.text(int(v) - 11, i + 0.05, f'{v}%', color='white', fontweight='bold', fontsize=14) else: ax.text(int(v) + 2, i + 0.05, f'{v}%', color='black', fontweight='bold', fontsize=14) col = [] for val in height: if val < 50: col.append('#FF0000') elif val <= 75: col.append('#FFC000') else: col.append('#70AD47') ax.barh(y_pos, height, align='center', color=col) ax.set_xlim([0,100]) ax.set_yticks(y_pos) ax.set_yticklabels(bars) ax.invert_yaxis() # labels read top-to-bottom ax.set_title('Breakdown by Section:') buf = io.BytesIO() plt.savefig(buf, format='png', bbox_inches='tight', transparent=False) buf.seek(0) im = Image.open(buf) width, height = im.size y_offset = 200 new_height = height + y_offset result = Image.new(im.mode, (width, new_height), color=(255,255,255)) result.paste(im, (0, y_offset)) width, height = result.size font_path = f"{str(settings.PROJECT_PATH)}{static('font/OpenSans-Regular.ttf')}" font = ImageFont.truetype(font_path, size=25); top_header = 'OVERALL PROGRESS:' draw = ImageDraw.Draw(result) draw.text( ((width-draw.textsize(top_header, font=font)[0])/2, draw.textsize(top_header)[1]), # Coordinates top_header, # Text (0, 0, 0), # Color font=font ) font = ImageFont.truetype(font_path, size=160); draw.text( (((width-draw.textsize(f'{self.overall}%', font=font)[0])/2), draw.textsize(top_header)[1]), # Coordinates f'{self.overall}%', # Text (255, 0, 0) if self.overall < 50 else (255, 192, 0) if self.overall <= 75 else (112, 173, 71), # Color font=font ) result.save(f'{settings.BASE_DIR}/media/{self.id}.png') rgba = Image.open(f'{settings.BASE_DIR}/media/{self.id}.png') rgb = Image.new('RGB', rgba.size, (255, 255, 255)) rgb.paste(rgba, mask=rgba.split()[3]) rgb.save(f'{settings.BASE_DIR}/media/{self.id}.pdf', 'PDF', resoultion=100.0)