Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ python scripts/verify_installation.py

### 🖥️ **Running the Desktop Application**
```sh
python src/osbridgelcca/desktop/app.py
python src_web/osbridgelcca/desktop/app.py
```

### 🌐 **Running the Web Application**
#### **Start the Backend Server**
```sh
python src/osbridgelcca/backend/manage.py runserver
python src_web/osbridgelcca/backend/manage.py runserver
```
#### **Start the Frontend**
```sh
cd src/osbridgelcca/web
cd src_web/osbridgelcca/web
npm install
npm start
```
Expand Down
9 changes: 8 additions & 1 deletion install.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
@echo off
echo Creating and activating Conda environment...
call conda activate osbridgelcca || conda create -n osbridgelcca python=3.9 -y && conda activate osbridgelcca

REM Try activating the environment
call conda activate osbridgelcca 2>nul
if errorlevel 1 (
echo Environment not found. Creating it now...
call conda create -n osbridgelcca python=3.9 -y
call conda activate osbridgelcca
)

echo Installing dependencies from pyproject.toml...
pip install .
Expand Down
1 change: 1 addition & 0 deletions scripts/verify_installation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import importlib
import sys
sys.stdout.reconfigure(encoding='utf-8')

# List of required packages
REQUIRED_PACKAGES = [
Expand Down
Empty file added src/__init__.py
Empty file.
Empty file.
21 changes: 21 additions & 0 deletions src/osbridgelcca/backend/config.py
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
# Placeholder for app configuration

import os
from pathlib import Path

# Base directory of the project
BASE_DIR = Path(__file__).resolve().parent.parent.parent

# Database configuration
DATABASE_URL = os.getenv('DATABASE_URL', f'sqlite:///{BASE_DIR}/data/lcca.db')

# Create data directory if it doesn't exist
DATA_DIR = BASE_DIR / 'data'
DATA_DIR.mkdir(exist_ok=True)

# Database configuration options
DB_CONFIG = {
'pool_size': 5,
'max_overflow': 10,
'pool_timeout': 30,
'pool_recycle': 1800
}
28 changes: 28 additions & 0 deletions src/osbridgelcca/backend/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import QueuePool
from .models import Base
from .config import DATABASE_URL, DB_CONFIG

# Create engine with connection pooling
engine = create_engine(
DATABASE_URL,
poolclass=QueuePool,
**DB_CONFIG
)

# Create session factory
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
"""Get database session"""
db = SessionLocal()
try:
yield db
finally:
db.close()

def init_database():
"""Initialize database tables"""
Base.metadata.create_all(bind=engine)
4 changes: 3 additions & 1 deletion src/osbridgelcca/backend/main.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Placeholder for Flask API entry point
from osbridgelcca.backend.database import init_database

init_database()
92 changes: 92 additions & 0 deletions src/osbridgelcca/backend/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from sqlalchemy import create_engine, Column, Integer, Float, String, ForeignKey, DateTime, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from datetime import datetime, UTC

Base = declarative_base()

class MaterialRate(Base):
"""Regional schedule of rates for materials"""
__tablename__ = 'material_rates'

id = Column(Integer, primary_key=True)
material_name = Column(String(100), nullable=False)
region = Column(String(50), nullable=False)
unit = Column(String(20), nullable=False)
rate = Column(Float, nullable=False)
currency = Column(String, nullable=False)
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class ScrapValue(Base):
"""Scrap values and recyclability percentages"""
__tablename__ = 'scrap_values'

id = Column(Integer, primary_key=True)
material_name = Column(String(100), nullable=False)
scrap_value = Column(Float, nullable=False)
recyclability_percentage = Column(Float, nullable=False)
currency = Column(String, nullable=False)
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class EnvironmentalImpact(Base):
"""Environmental impact data from EPDs"""
__tablename__ = 'environmental_impacts'

id = Column(Integer, primary_key=True)
material_name = Column(String(100), nullable=False)
epd_id = Column(String(50), nullable=False)
global_warming_potential = Column(Float, nullable=False) # kg CO2 eq
water_consumption = Column(Float) # m³
energy_consumption = Column(Float) # MJ
waste_generation = Column(Float) # kg
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class SocialCostOfCarbon(Base):
"""Country-specific social cost of carbon"""
__tablename__ = 'social_cost_of_carbon'

id = Column(Integer, primary_key=True)
country = Column(String(50), nullable=False)
year = Column(Integer, nullable=False)
cost_per_ton = Column(Float, nullable=False) # USD per ton CO2
currency = Column(String, nullable=False)
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class TransportEmissionFactor(Base):
"""Road transport carbon emission factors"""
__tablename__ = 'transport_emission_factors'

id = Column(Integer, primary_key=True)
vehicle_type = Column(String(50), nullable=False)
emission_factor = Column(Float, nullable=False) # kg CO2 per km
load_factor = Column(Float) # Average load factor
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class VehicleOperationCost(Base):
"""Vehicle operation costs"""
__tablename__ = 'vehicle_operation_costs'

id = Column(Integer, primary_key=True)
vehicle_type = Column(String(50), nullable=False)
fuel_cost_per_km = Column(Float, nullable=False)
maintenance_cost_per_km = Column(Float, nullable=False)
insurance_cost_per_year = Column(Float, nullable=False)
currency = Column(String(3), nullable=False)
last_updated = Column(DateTime, default=lambda: datetime.now(UTC))

class UserAnalysis(Base):
"""User analyses storage"""
__tablename__ = 'user_analyses'

id = Column(Integer, primary_key=True)
user_id = Column(String(50), nullable=False)
analysis_name = Column(String(100), nullable=False)
analysis_data = Column(JSON, nullable=False)
created_at = Column(DateTime, default=lambda: datetime.now(UTC))
updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))

def init_db(db_url):
"""Initialize the database"""
engine = create_engine(db_url)
Base.metadata.create_all(engine)
return engine
Empty file.
76 changes: 67 additions & 9 deletions src/osbridgelcca/core/bridge_lcc.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,84 @@
import pandas as pd
from input_data import Input
from cost_components import CostComponent
from src.osbridgelcca.core.cost_components import InitialConstructionCost, InitialCarbonEmissionCost, TimeCost, \
RoadUserCost


class BridgeLCC:
"""Main class for handling Life Cycle Cost Analysis of bridges."""
def __init__(self, project_name, inputs):

def __init__(self, project_name: str, inputs: Input):
self.project_name = project_name
self.inputs = inputs # Dictionary of user inputs
self.outputs = {}
self.inputs = inputs # Expecting an instance of Input class
self.outputs = {} # Initialize output storage

def calculate_lcc(self):
"""Calculate the total life cycle cost based on input parameters."""
try:
material_cost = sum(self.inputs["bill_of_quantity"].values())
maintenance_cost = self.inputs["maintenance_cost"]
operation_cost = self.inputs["vehicle_operating_cost"]
discount_rate = self.inputs["discount_rate"]
material_cost = self.inputs.material_data.quantity * self.inputs.material_data.unit_rate
maintenance_cost = self.inputs.maintenance_data.periodic_maintenance_rate
operation_cost = self.inputs.traffic_data.annual_traffic_increase * 5000 # Example formula
discount_rate = self.inputs.finance_data.discount_rate / 100 # Convert percentage to decimal

# Simple NPV calculation
total_cost = (material_cost + maintenance_cost + operation_cost) / (1 + discount_rate)
self.outputs["total_lcc"] = total_cost
return total_cost
except KeyError as e:
except AttributeError as e:
raise ValueError(f"Missing input parameter: {e}")

def get_outputs(self):
"""Return computed outputs."""
return self.outputs

def tabulate_cost_components(self):
"""Create a Pandas DataFrame for cost components."""
data = {
"Sl. No.": list(range(1, 12)) + ["Total"],
"Cost Component": [
"Initial costs", "Initial carbon emissions costs", "Time costs",
"Road user costs due to re-routing", "Carbon emission cost due to re-routing",
"Periodic maintenance costs", "Periodic maintenance carbon emissions costs",
"Annual routine inspection costs", "Repair and rehabilitation costs",
"Demolition and disposal costs", "Recycling costs", "Total life cycle cost"
],
"Cost Amount": [InitialConstructionCost.amount,
InitialCarbonEmissionCost.amount,
TimeCost.amount,
RoadUserCost.amount,
82.62, 19.36, 1.5, 17.68, 13.8, 0, 0.84, -2.67, 212.81],
"Life Cycle Stage": [
"Initial", "Initial", "Initial", "Initial", "Initial",
"Use", "Use", "Use", "Use",
"End", "End", "Total"
],
"Cost Type": [
"Economic", "Environmental", "Social", "Social", "Environmental",
"Economic", "Environmental", "Economic", "Economic",
"Economic", "Economic", "Total"
]
}

df = pd.DataFrame(data)
return df

# Example Usage
if __name__ == "__main__":
from input_data import MaterialData, FinanceData, TrafficData, MaintenanceData, RepairData, DemolitionData, RecycleData, CarbonEmissionData

material = MaterialData("Steel", "Reinforcement bars", 5000, "kg", 60, "Govt Schedule", 32, 2.5, "EPD Source", 5, 90)
finance = FinanceData(5.0, 7.5, 1.2)
carbon = CarbonEmissionData("SSP2", "RCP6", 1200)
traffic = TrafficData(15, 4000, "Plain", "Urban", 10, {"Car": 50, "Truck": 30, "Bus": 20})
maintenance = MaintenanceData(0.55, 1.0, 10, 5, 1)
repair = RepairData("Component-wise repair details")
demolition = DemolitionData(10)
recycle = RecycleData(80, 10000, 5000)

project_input = Input(material, finance, carbon, traffic, maintenance, repair, demolition, recycle)
bridge = BridgeLCC("Bridge A", project_input)

print("Total LCC:", bridge.calculate_lcc())
print("\nCost Components Table:")
print(bridge.tabulate_cost_components())
Loading