working on presentation and content

This commit is contained in:
Khalim Conn-Kowlessar 2024-02-21 17:30:56 +00:00
parent c0b1acef98
commit 35a75bc4e5
6 changed files with 85 additions and 31 deletions

View file

@ -470,7 +470,7 @@ class Property:
to_update[k] = None
return to_update
def get_full_property_data(self):
def get_full_property_data(self, current_valuation=None):
"""
This method extracts the data which is pushed to the database, containing core information, from the EPC
about a property
@ -492,6 +492,7 @@ class Property:
"tenure": self.data["tenure"],
"current_epc_rating": self.data["current-energy-rating"],
"current_sap_points": self.data["current-energy-efficiency"],
"current_valuation": current_valuation
}
property_data = self._clean_upload_data(property_data)

View file

@ -86,6 +86,7 @@ class PropertyModel(Base):
tenure = Column(Text)
current_epc_rating = Column(Enum(Epc))
current_sap_points = Column(Float)
current_valuation = Column(Float)
class FeatureRating(enum.Enum):

View file

@ -53,6 +53,9 @@ class Plan(Base):
property_id = Column(BigInteger, ForeignKey(PropertyModel.id), nullable=False)
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
is_default = Column(Boolean, nullable=False)
valuation_increase_lower_bound = Column(Float)
valuation_increase_upper_bound = Column(Float)
valuation_increase_average = Column(Float)
class PlanRecommendations(Base):

View file

@ -291,27 +291,43 @@ async def trigger_plan(body: PlanTriggerRequest):
batch_properties = input_properties[i:i + BATCH_SIZE]
for p in batch_properties:
recommendations_to_upload = recommendations.get(p.id, [])
default_recommendations = [r for r in recommendations_to_upload if r["default"]]
total_sap_points = sum([r["sap_points"] for r in default_recommendations])
new_sap_points = float(p.data["current-energy-efficiency"]) + total_sap_points
new_epc = sap_to_epc(new_sap_points)
valuations = PropertyValuation.estimate(property_instance=p, target_epc=new_epc)
# Your existing operations
property_details_epc = p.get_property_details_epc(
portfolio_id=body.portfolio_id, rating_lookup=rating_lookup
portfolio_id=body.portfolio_id, rating_lookup=rating_lookup,
)
create_property_details_epc(session, property_details_epc)
update_or_create_property_spatial_details(session, p.uprn, p.spatial)
property_data = p.get_full_property_data()
property_data = p.get_full_property_data(current_valuation=valuations["current_value"])
update_property_data(
session, property_id=p.id, portfolio_id=body.portfolio_id, property_data=property_data
)
recommendations_to_upload = recommendations.get(p.id, [])
if not recommendations_to_upload:
continue
new_plan_id = create_plan(session, {
"portfolio_id": body.portfolio_id,
"property_id": p.id,
"is_default": True
"is_default": True,
"valuation_increase_lower_bound": (
valuations["lower_bound_increased_value"] - valuations["current_value"]
),
"valuation_increase_upper_bound": (
valuations["upper_bound_increased_value"] - valuations["current_value"]
),
"valuation_increase_average": (
valuations["average_increased_value"] - valuations["current_value"]
),
})
uploaded_recommendation_ids = upload_recommendations(session, recommendations_to_upload, p.id)
@ -320,14 +336,6 @@ async def trigger_plan(body: PlanTriggerRequest):
session, plan_id=new_plan_id, recommendation_ids=uploaded_recommendation_ids
)
# Get defaults
default_recommendations = [r for r in recommendations_to_upload if r["default"]]
total_sap_points = sum([r["sap_points"] for r in default_recommendations])
new_sap_points = float(p.data["current-energy-efficiency"]) + total_sap_points
new_epc = sap_to_epc(new_sap_points)
valuations = PropertyValuation.estimate(property_instance=p, target_epc=new_epc)
property_valuation_increases.append(
valuations["average_increased_value"] - valuations["current_value"]
)

View file

@ -1,4 +1,5 @@
import os
from pptx.enum.text import PP_ALIGN
from pptx import Presentation
from pptx.util import Inches, Pt
import matplotlib.pyplot as plt
@ -148,26 +149,64 @@ def save_figure_as_image(figure, filename='temp_plot.png'):
plt.close(figure) # Close the figure to prevent it from displaying in notebooks or Python environments
def add_commentary_with_bullets(slide, commentary, top_inches, left_inches=Inches(1), width_inches=Inches(8),
height_inches=Inches(2)):
"""
Adds commentary with bullet points to a slide.
:param slide: The slide object to add the commentary to.
:param commentary: The commentary text, with sections separated by newlines for bullet points.
:param top_inches: The top position of the commentary text box.
:param left_inches: The left position of the commentary text box.
:param width_inches: The width of the commentary text box.
:param height_inches: The height of the commentary text box.
"""
txBox = slide.shapes.add_textbox(left_inches, top_inches, width_inches, height_inches)
tf = txBox.text_frame
# Configure text frame
tf.word_wrap = True
tf.auto_size = True
tf.paragraphs[0].alignment = PP_ALIGN.LEFT
# Split the commentary into sections for bullet points
sections = commentary.split("\n")
for i, section in enumerate(sections):
if i > 0:
p = tf.add_paragraph() # Add a new paragraph for each section after the first
else:
p = tf.paragraphs[0] # Use the first paragraph for the first section
p.text = section
p.space_after = Pt(14) # Adjust space after each bullet point as needed
p.font.size = Pt(14) # Adjust font size as needed
p.level = 0 # Bullet level, can be adjusted for nested bullets
p.space_before = Pt(0)
def add_slide_with_image(prs, title, img_path=None, commentary=None):
"""
Adds a slide with an image and optional commentary.
Adds a slide with an image (if provided) and optional commentary. If no image is provided,
places the commentary text in the middle of the slide.
"""
slide_layout = prs.slide_layouts[5] # Title and Content layout
slide = prs.slides.add_slide(slide_layout)
title_placeholder = slide.shapes.title
title_placeholder.text = title
# Add the image
# Determine the position of the commentary text box based on whether an image is included
if img_path:
# Add the image
slide.shapes.add_picture(img_path, Inches(1), Inches(1.5), Inches(8), Inches(4.5))
# Position for commentary when image is present
commentary_top = Inches(6)
else:
# Position for commentary when image is not present (centered vertically)
commentary_top = Inches(3)
# Add commentary if provided
if commentary:
txBox = slide.shapes.add_textbox(Inches(1), Inches(6), Inches(8), Inches(1))
tf = txBox.text_frame
p = tf.add_paragraph()
p.text = commentary
p.font.size = Pt(14) # Adjust font size as needed
add_commentary_with_bullets(slide, commentary, commentary_top)
def create_powerpoint(data, save_location):

View file

@ -104,16 +104,18 @@ def app():
)
# Valuation: upper and lower bounds - TODO!
min_valuation, max_valuation, average_valuation = 0, 0, 0
min_valuation, max_valuation, average_valuation = (0, 0, 0)
recommendations_df.keys()
slide_1_commentary = (
f"Floor areas range from {min_area} to {max_area} square meters, with an average of {average_area} square "
f"meters. "
f"meters. \n"
f"Annual energy consumption ranges from {min_energy_consumption} to {max_energy_consumption} kWh, with an "
f"average of {average_consumption} kWh. "
f"CO2 emissions range from {min_co2} to {max_co2} tonnes, with an average of {average_co2} tonnes. "
f"average of {average_consumption} kWh. \n"
f"CO2 emissions range from {min_co2} to {max_co2} tonnes, with an average of {average_co2} tonnes. \n"
f"Valuations range from £{min_valuation} to £{max_valuation} £, with an average of £"
f"{average_valuation}."
f"{average_valuation}.\n"
)
############
@ -154,13 +156,13 @@ def app():
)
slide_2_commentary = (
f"{n_units_to_target} expected to achieve EPC {EPC_TARGET} "
f"Measures include: {measures}"
f"{n_units_to_target} units expected to achieve EPC {EPC_TARGET} \n"
f"Measures include: {measures}\n"
f"Valuation increase per property: £{min_valuation_impact}-{max_valuation_impact}, average: £"
f"{average_valuation_impact}"
f"Bill savings per property: £{min_bill_savings}-{max_bill_savings}, average: £{average_bill_savings}"
f"Total CO2 reduction: {min_co2_reduction}-{max_co2_reduction} tonnes, average: {average_co2_reduction}"
f"tonnes, total for the {n_units_to_target} properties: {total_co2_reduction} tonnes"
f"{average_valuation_impact}\n"
f"Bill savings per property: £{min_bill_savings}-{max_bill_savings}, average: £{average_bill_savings}\n"
f"Total CO2 reduction: {min_co2_reduction}-{max_co2_reduction} tonnes, average: {average_co2_reduction}\n"
f"tonnes, total for the {n_units_to_target} properties: {total_co2_reduction} tonnes\n"
)
############