bioelectea 0.1.0__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bioelectea/__init__.py +1 -1
- bioelectea/__main__.py +1 -1
- bioelectea/cli.py +1 -1
- bioelectea/modules/__init__.py +0 -0
- bioelectea/modules/lca_engine.py +38 -0
- bioelectea/modules/tea_core.py +73 -0
- {bioelectea-0.1.0.dist-info → bioelectea-0.1.3.dist-info}/METADATA +1 -1
- bioelectea-0.1.3.dist-info/RECORD +10 -0
- bioelectea-0.1.0.dist-info/RECORD +0 -7
- {bioelectea-0.1.0.dist-info → bioelectea-0.1.3.dist-info}/WHEEL +0 -0
- {bioelectea-0.1.0.dist-info → bioelectea-0.1.3.dist-info}/entry_points.txt +0 -0
bioelectea/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
__all__ = ["__version__"]
|
2
|
-
__version__ = "0.1.0"
|
2
|
+
__version__ = "0.1.0"
|
bioelectea/__main__.py
CHANGED
bioelectea/cli.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
def main():
|
2
|
-
print("bioelectea: hello, world! CLI stub is alive.")
|
2
|
+
print("bioelectea: hello, world! CLI stub is alive.")
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
"""LCA engine scaffold for BioElecTEA."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
from dataclasses import dataclass
|
5
|
+
from typing import List, Tuple
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass
|
9
|
+
class LCAItem:
|
10
|
+
name: str
|
11
|
+
amount: float # e.g., kg, kWh
|
12
|
+
gwp_factor: float # kg CO2e per unit
|
13
|
+
ce_factor: float # placeholder score per unit
|
14
|
+
|
15
|
+
|
16
|
+
@dataclass
|
17
|
+
class LCAResult:
|
18
|
+
total_gwp: float
|
19
|
+
total_ce: float
|
20
|
+
breakdown: List[Tuple[str, float, float]] # (name, gwp, ce)
|
21
|
+
|
22
|
+
|
23
|
+
class LCAEngine:
|
24
|
+
def __init__(self, items: List[LCAItem]) -> None:
|
25
|
+
self.items = items
|
26
|
+
|
27
|
+
def evaluate(self) -> LCAResult:
|
28
|
+
breakdown: List[Tuple[str, float, float]] = []
|
29
|
+
gwp_sum = 0.0
|
30
|
+
ce_sum = 0.0
|
31
|
+
for it in self.items:
|
32
|
+
gwp = it.amount * it.gwp_factor
|
33
|
+
ce = it.amount * it.ce_factor
|
34
|
+
breakdown.append((it.name, gwp, ce))
|
35
|
+
gwp_sum += gwp
|
36
|
+
ce_sum += ce
|
37
|
+
breakdown.sort(key=lambda x: x[1], reverse=True)
|
38
|
+
return LCAResult(total_gwp=gwp_sum, total_ce=ce_sum, breakdown=breakdown)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
"""TEA core calculations for BioElecTEA."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
from dataclasses import dataclass
|
5
|
+
from typing import List, Optional
|
6
|
+
|
7
|
+
|
8
|
+
@dataclass
|
9
|
+
class TEAInput:
|
10
|
+
years: int
|
11
|
+
discount_rate: float # e.g., 0.08
|
12
|
+
capex: float # upfront
|
13
|
+
opex_yearly: float # constant v0
|
14
|
+
revenue_yearly: float # constant v0
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class TEAResult:
|
19
|
+
npv: float
|
20
|
+
irr: Optional[float]
|
21
|
+
payback_year: Optional[int]
|
22
|
+
cashflows: List[float]
|
23
|
+
|
24
|
+
|
25
|
+
class TEACore:
|
26
|
+
def __init__(self, params: TEAInput) -> None:
|
27
|
+
self.p = params
|
28
|
+
|
29
|
+
def build_cashflows(self) -> List[float]:
|
30
|
+
cf: List[float] = [-self.p.capex]
|
31
|
+
for _ in range(self.p.years):
|
32
|
+
cf.append(self.p.revenue_yearly - self.p.opex_yearly)
|
33
|
+
return cf
|
34
|
+
|
35
|
+
@staticmethod
|
36
|
+
def npv(rate: float, cashflows: List[float]) -> float:
|
37
|
+
return sum(cf / ((1 + rate) ** t) for t, cf in enumerate(cashflows))
|
38
|
+
|
39
|
+
@staticmethod
|
40
|
+
def irr(
|
41
|
+
cashflows: List[float],
|
42
|
+
guess: float = 0.1,
|
43
|
+
tol: float = 1e-6,
|
44
|
+
max_iter: int = 100,
|
45
|
+
) -> Optional[float]:
|
46
|
+
# Simple Newton-Raphson (demo). For production consider numpy_financial.
|
47
|
+
rate = guess
|
48
|
+
for _ in range(max_iter):
|
49
|
+
f = sum(cf / ((1 + rate) ** t) for t, cf in enumerate(cashflows))
|
50
|
+
df = sum(-t * cf / ((1 + rate) ** (t + 1)) for t, cf in enumerate(cashflows) if t > 0)
|
51
|
+
if abs(df) < 1e-12:
|
52
|
+
return None
|
53
|
+
new_rate = rate - f / df
|
54
|
+
if abs(new_rate - rate) < tol:
|
55
|
+
return new_rate
|
56
|
+
rate = new_rate
|
57
|
+
return None
|
58
|
+
|
59
|
+
@staticmethod
|
60
|
+
def payback(cashflows: List[float]) -> Optional[int]:
|
61
|
+
acc = 0.0
|
62
|
+
for t, cf in enumerate(cashflows):
|
63
|
+
acc += cf
|
64
|
+
if acc >= 0:
|
65
|
+
return t
|
66
|
+
return None
|
67
|
+
|
68
|
+
def run(self) -> TEAResult:
|
69
|
+
cfs = self.build_cashflows()
|
70
|
+
npv_val = self.npv(self.p.discount_rate, cfs)
|
71
|
+
irr_val = self.irr(cfs)
|
72
|
+
pby = self.payback(cfs)
|
73
|
+
return TEAResult(npv=npv_val, irr=irr_val, payback_year=pby, cashflows=cfs)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
bioelectea/__init__.py,sha256=tXbRXsO0NE_UV1kIHiZTTQQH0fj0U2KoxxNusu_gzrM,48
|
2
|
+
bioelectea/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
|
3
|
+
bioelectea/cli.py,sha256=H7-9VRqa4tUKlB0hnVWYbuvgdw3SKUgpyaQ15oDaT3g,70
|
4
|
+
bioelectea/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
bioelectea/modules/lca_engine.py,sha256=XmLAMLmSiUxCzJy8xHnWYM5ANEHELHr4dOWyLOFHjI4,1041
|
6
|
+
bioelectea/modules/tea_core.py,sha256=wDYQCb0qqnM_Ng6tX4N_QFzHiB8sEagDalVMkAqnRYc,2133
|
7
|
+
bioelectea-0.1.3.dist-info/METADATA,sha256=18vxrU0CZOB6oDIjDoDKm3Fq1VKkSd3YE650TJz0mlU,618
|
8
|
+
bioelectea-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
+
bioelectea-0.1.3.dist-info/entry_points.txt,sha256=HK1ogjSOhfUb_H8kBIXvkaZ2XyPJHakSHd5tKuqxTEc,51
|
10
|
+
bioelectea-0.1.3.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
bioelectea/__init__.py,sha256=sca3B8hAtmHVH9qxtqZusd9a0Kzov3VtgHnvq8_ZJY8,49
|
2
|
-
bioelectea/__main__.py,sha256=HrbCy8Q6qXHtsbU7_WIsmGfH9P4jRqYv8vsXdQdiozw,62
|
3
|
-
bioelectea/cli.py,sha256=DvdPH4SnlIRYKI4IQmR1W9fHE77VdAr30gUKp6POjWU,71
|
4
|
-
bioelectea-0.1.0.dist-info/METADATA,sha256=wQ4IXUD2uTEuoZflp6naBWiO2HN0xfdZVMg25ZmUIMg,618
|
5
|
-
bioelectea-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
6
|
-
bioelectea-0.1.0.dist-info/entry_points.txt,sha256=HK1ogjSOhfUb_H8kBIXvkaZ2XyPJHakSHd5tKuqxTEc,51
|
7
|
-
bioelectea-0.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|