recovery-lab-math 1.0.0__tar.gz
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.
- recovery_lab_math-1.0.0/PKG-INFO +87 -0
- recovery_lab_math-1.0.0/README.md +66 -0
- recovery_lab_math-1.0.0/pyproject.toml +34 -0
- recovery_lab_math-1.0.0/recovery_lab_math.egg-info/PKG-INFO +87 -0
- recovery_lab_math-1.0.0/recovery_lab_math.egg-info/SOURCES.txt +8 -0
- recovery_lab_math-1.0.0/recovery_lab_math.egg-info/dependency_links.txt +1 -0
- recovery_lab_math-1.0.0/recovery_lab_math.egg-info/entry_points.txt +2 -0
- recovery_lab_math-1.0.0/recovery_lab_math.egg-info/top_level.txt +1 -0
- recovery_lab_math-1.0.0/recoveryspend.py +149 -0
- recovery_lab_math-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: recovery-lab-math
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Home recovery purchase vs gym drop-in, in the terminal: true heater draw, per-session supplies, amortized hardware, and the break-even frequency
|
|
5
|
+
Author: James Verlander
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://hackedself.com/
|
|
8
|
+
Project-URL: Source Code, https://github.com/scrapertweeter3-prog/recovery-lab-math
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/scrapertweeter3-prog/recovery-lab-math/issues
|
|
10
|
+
Keywords: sauna,cold-plunge,recovery,biohacking,cost-per-session,break-even,longevity,cli
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Recoveryspend - Home recovery lab cost-per-session + break-even
|
|
23
|
+
|
|
24
|
+
A terminal calculator that answers one question: does the home unit beat
|
|
25
|
+
the gym-studio drop-in, and when? Costs any home recovery purchase (sauna,
|
|
26
|
+
cold plunge, red-light panel, massage gun, per-session amenity) against a
|
|
27
|
+
drop-in price, using the exact method from the HackedSelf article: true
|
|
28
|
+
energy draw from nameplate watts and your electric rate, filter/service
|
|
29
|
+
supplies per session, amortized purchase over a realistic session count,
|
|
30
|
+
and the weekly-frequency level where the home setup breaks even in years.
|
|
31
|
+
|
|
32
|
+
Python 3.8+, standard library only. No install, no network, nothing leaves
|
|
33
|
+
your machine.
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
## The method
|
|
38
|
+
|
|
39
|
+
- **Energy per session** = heater draw (W) / 1000 x hours x $/kWh
|
|
40
|
+
(preheat counted at half draw)
|
|
41
|
+
- **Supplies per session** = annual filter/treatment cost / sessions per year
|
|
42
|
+
- **Amortized hardware** = purchase price / sessions before it's paid off,
|
|
43
|
+
shown separately so you can watch it fall toward zero
|
|
44
|
+
- **Break even** = solve price / sessions-per-week for the frequency where
|
|
45
|
+
the home marginal cost equals the drop-in price, in weeks and years
|
|
46
|
+
|
|
47
|
+
The gym comparison uses the drop-in price only. If you already pay for a
|
|
48
|
+
membership that includes the amenity, the drop-in is $0 and the home unit
|
|
49
|
+
never wins - recoveryspend tells you that plainly.
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
$ python3 recoveryspend.py --price 4500 --watts 6000 --kwh 0.17 \
|
|
55
|
+
--sessions-year 150 --dropin 35 --name "2-person infrared sauna"
|
|
56
|
+
== 2-person infrared sauna vs drop-in
|
|
57
|
+
Energy per session 5.78 (4.5 kW effective, 0.75 h, $0.170/kWh)
|
|
58
|
+
Supplies per session 0.50 ($75/yr filters, 150 sessions/yr)
|
|
59
|
+
Marginal cost/session 6.28
|
|
60
|
+
Drop-in price 35.00
|
|
61
|
+
Break even 2.6 sessions/wk (0.7 yr)
|
|
62
|
+
|
|
63
|
+
$ python3 recoveryspend.py --json ...
|
|
64
|
+
{"verdict": "home wins", "marginal": 6.28, "dropin": 35.0, ...}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Also check
|
|
68
|
+
|
|
69
|
+
- `--preheat 1.0` full-draw preheat hour instead of the half-draw default
|
|
70
|
+
- `--life-sessions 500` amortization window (default 500 sessions)
|
|
71
|
+
- `--supplies-year 0` no filter/treatment line
|
|
72
|
+
- Exit code 1 when the home unit loses at the current frequency, so the
|
|
73
|
+
check can gate a purchase decision in a script
|
|
74
|
+
|
|
75
|
+
## Honest limits
|
|
76
|
+
|
|
77
|
+
Energy math is nameplate math: real duty cycles, ambient temperature and
|
|
78
|
+
insulation move the true number, so treat the figure as the optimistic
|
|
79
|
+
floor and the break-even as the optimistic edge. Sessions-per-year is a
|
|
80
|
+
behavioral guess only you can make; the break-even output is exactly the
|
|
81
|
+
place that guess gets honest. No study effect sizes are cited anywhere in
|
|
82
|
+
this repo, because there are none here - this tool is dollars, not dose.
|
|
83
|
+
|
|
84
|
+
## Related
|
|
85
|
+
|
|
86
|
+
The full protocol and the worked example behind this method:
|
|
87
|
+
https://hackedself.com/recovery/home-recovery-lab-cost-per-session/
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Recoveryspend - Home recovery lab cost-per-session + break-even
|
|
2
|
+
|
|
3
|
+
A terminal calculator that answers one question: does the home unit beat
|
|
4
|
+
the gym-studio drop-in, and when? Costs any home recovery purchase (sauna,
|
|
5
|
+
cold plunge, red-light panel, massage gun, per-session amenity) against a
|
|
6
|
+
drop-in price, using the exact method from the HackedSelf article: true
|
|
7
|
+
energy draw from nameplate watts and your electric rate, filter/service
|
|
8
|
+
supplies per session, amortized purchase over a realistic session count,
|
|
9
|
+
and the weekly-frequency level where the home setup breaks even in years.
|
|
10
|
+
|
|
11
|
+
Python 3.8+, standard library only. No install, no network, nothing leaves
|
|
12
|
+
your machine.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## The method
|
|
17
|
+
|
|
18
|
+
- **Energy per session** = heater draw (W) / 1000 x hours x $/kWh
|
|
19
|
+
(preheat counted at half draw)
|
|
20
|
+
- **Supplies per session** = annual filter/treatment cost / sessions per year
|
|
21
|
+
- **Amortized hardware** = purchase price / sessions before it's paid off,
|
|
22
|
+
shown separately so you can watch it fall toward zero
|
|
23
|
+
- **Break even** = solve price / sessions-per-week for the frequency where
|
|
24
|
+
the home marginal cost equals the drop-in price, in weeks and years
|
|
25
|
+
|
|
26
|
+
The gym comparison uses the drop-in price only. If you already pay for a
|
|
27
|
+
membership that includes the amenity, the drop-in is $0 and the home unit
|
|
28
|
+
never wins - recoveryspend tells you that plainly.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
$ python3 recoveryspend.py --price 4500 --watts 6000 --kwh 0.17 \
|
|
34
|
+
--sessions-year 150 --dropin 35 --name "2-person infrared sauna"
|
|
35
|
+
== 2-person infrared sauna vs drop-in
|
|
36
|
+
Energy per session 5.78 (4.5 kW effective, 0.75 h, $0.170/kWh)
|
|
37
|
+
Supplies per session 0.50 ($75/yr filters, 150 sessions/yr)
|
|
38
|
+
Marginal cost/session 6.28
|
|
39
|
+
Drop-in price 35.00
|
|
40
|
+
Break even 2.6 sessions/wk (0.7 yr)
|
|
41
|
+
|
|
42
|
+
$ python3 recoveryspend.py --json ...
|
|
43
|
+
{"verdict": "home wins", "marginal": 6.28, "dropin": 35.0, ...}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Also check
|
|
47
|
+
|
|
48
|
+
- `--preheat 1.0` full-draw preheat hour instead of the half-draw default
|
|
49
|
+
- `--life-sessions 500` amortization window (default 500 sessions)
|
|
50
|
+
- `--supplies-year 0` no filter/treatment line
|
|
51
|
+
- Exit code 1 when the home unit loses at the current frequency, so the
|
|
52
|
+
check can gate a purchase decision in a script
|
|
53
|
+
|
|
54
|
+
## Honest limits
|
|
55
|
+
|
|
56
|
+
Energy math is nameplate math: real duty cycles, ambient temperature and
|
|
57
|
+
insulation move the true number, so treat the figure as the optimistic
|
|
58
|
+
floor and the break-even as the optimistic edge. Sessions-per-year is a
|
|
59
|
+
behavioral guess only you can make; the break-even output is exactly the
|
|
60
|
+
place that guess gets honest. No study effect sizes are cited anywhere in
|
|
61
|
+
this repo, because there are none here - this tool is dollars, not dose.
|
|
62
|
+
|
|
63
|
+
## Related
|
|
64
|
+
|
|
65
|
+
The full protocol and the worked example behind this method:
|
|
66
|
+
https://hackedself.com/recovery/home-recovery-lab-cost-per-session/
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "recovery-lab-math"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Home recovery purchase vs gym drop-in, in the terminal: true heater draw, per-session supplies, amortized hardware, and the break-even frequency"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "James Verlander"}]
|
|
13
|
+
keywords = ["sauna", "cold-plunge", "recovery", "biohacking", "cost-per-session", "break-even", "longevity", "cli"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Scientific/Engineering",
|
|
22
|
+
"Topic :: Utilities",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://hackedself.com/"
|
|
27
|
+
"Source Code" = "https://github.com/scrapertweeter3-prog/recovery-lab-math"
|
|
28
|
+
"Bug Tracker" = "https://github.com/scrapertweeter3-prog/recovery-lab-math/issues"
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
recoveryspend = "recoveryspend:main"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools]
|
|
34
|
+
py-modules = ["recoveryspend"]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: recovery-lab-math
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Home recovery purchase vs gym drop-in, in the terminal: true heater draw, per-session supplies, amortized hardware, and the break-even frequency
|
|
5
|
+
Author: James Verlander
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://hackedself.com/
|
|
8
|
+
Project-URL: Source Code, https://github.com/scrapertweeter3-prog/recovery-lab-math
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/scrapertweeter3-prog/recovery-lab-math/issues
|
|
10
|
+
Keywords: sauna,cold-plunge,recovery,biohacking,cost-per-session,break-even,longevity,cli
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Recoveryspend - Home recovery lab cost-per-session + break-even
|
|
23
|
+
|
|
24
|
+
A terminal calculator that answers one question: does the home unit beat
|
|
25
|
+
the gym-studio drop-in, and when? Costs any home recovery purchase (sauna,
|
|
26
|
+
cold plunge, red-light panel, massage gun, per-session amenity) against a
|
|
27
|
+
drop-in price, using the exact method from the HackedSelf article: true
|
|
28
|
+
energy draw from nameplate watts and your electric rate, filter/service
|
|
29
|
+
supplies per session, amortized purchase over a realistic session count,
|
|
30
|
+
and the weekly-frequency level where the home setup breaks even in years.
|
|
31
|
+
|
|
32
|
+
Python 3.8+, standard library only. No install, no network, nothing leaves
|
|
33
|
+
your machine.
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
## The method
|
|
38
|
+
|
|
39
|
+
- **Energy per session** = heater draw (W) / 1000 x hours x $/kWh
|
|
40
|
+
(preheat counted at half draw)
|
|
41
|
+
- **Supplies per session** = annual filter/treatment cost / sessions per year
|
|
42
|
+
- **Amortized hardware** = purchase price / sessions before it's paid off,
|
|
43
|
+
shown separately so you can watch it fall toward zero
|
|
44
|
+
- **Break even** = solve price / sessions-per-week for the frequency where
|
|
45
|
+
the home marginal cost equals the drop-in price, in weeks and years
|
|
46
|
+
|
|
47
|
+
The gym comparison uses the drop-in price only. If you already pay for a
|
|
48
|
+
membership that includes the amenity, the drop-in is $0 and the home unit
|
|
49
|
+
never wins - recoveryspend tells you that plainly.
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
$ python3 recoveryspend.py --price 4500 --watts 6000 --kwh 0.17 \
|
|
55
|
+
--sessions-year 150 --dropin 35 --name "2-person infrared sauna"
|
|
56
|
+
== 2-person infrared sauna vs drop-in
|
|
57
|
+
Energy per session 5.78 (4.5 kW effective, 0.75 h, $0.170/kWh)
|
|
58
|
+
Supplies per session 0.50 ($75/yr filters, 150 sessions/yr)
|
|
59
|
+
Marginal cost/session 6.28
|
|
60
|
+
Drop-in price 35.00
|
|
61
|
+
Break even 2.6 sessions/wk (0.7 yr)
|
|
62
|
+
|
|
63
|
+
$ python3 recoveryspend.py --json ...
|
|
64
|
+
{"verdict": "home wins", "marginal": 6.28, "dropin": 35.0, ...}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Also check
|
|
68
|
+
|
|
69
|
+
- `--preheat 1.0` full-draw preheat hour instead of the half-draw default
|
|
70
|
+
- `--life-sessions 500` amortization window (default 500 sessions)
|
|
71
|
+
- `--supplies-year 0` no filter/treatment line
|
|
72
|
+
- Exit code 1 when the home unit loses at the current frequency, so the
|
|
73
|
+
check can gate a purchase decision in a script
|
|
74
|
+
|
|
75
|
+
## Honest limits
|
|
76
|
+
|
|
77
|
+
Energy math is nameplate math: real duty cycles, ambient temperature and
|
|
78
|
+
insulation move the true number, so treat the figure as the optimistic
|
|
79
|
+
floor and the break-even as the optimistic edge. Sessions-per-year is a
|
|
80
|
+
behavioral guess only you can make; the break-even output is exactly the
|
|
81
|
+
place that guess gets honest. No study effect sizes are cited anywhere in
|
|
82
|
+
this repo, because there are none here - this tool is dollars, not dose.
|
|
83
|
+
|
|
84
|
+
## Related
|
|
85
|
+
|
|
86
|
+
The full protocol and the worked example behind this method:
|
|
87
|
+
https://hackedself.com/recovery/home-recovery-lab-cost-per-session/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recoveryspend
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""recoveryspend: home recovery purchase vs drop-in price, per session.
|
|
3
|
+
|
|
4
|
+
Costs a home sauna / cold plunge / red-light panel against a studio drop-in
|
|
5
|
+
using nameplate energy math, per-session supplies, and amortized hardware,
|
|
6
|
+
then reports payoff time at your weekly frequency.
|
|
7
|
+
|
|
8
|
+
Stdlib only. Python 3.8+. No network.
|
|
9
|
+
"""
|
|
10
|
+
import argparse
|
|
11
|
+
import json
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
AMORT_SESSIONS_DEFAULT = 500 # sessions before hardware is considered paid off
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def money(x):
|
|
18
|
+
return round(x + 1e-9, 2)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def cost_model(price, watts, hours, preheat_frac, kwh, supplies_year,
|
|
22
|
+
sessions_year, life_sessions):
|
|
23
|
+
kw = watts / 1000.0
|
|
24
|
+
energy = money(kw * (hours + preheat_frac) * kwh)
|
|
25
|
+
supplies = money(supplies_year / sessions_year)
|
|
26
|
+
marginal = money(energy + supplies)
|
|
27
|
+
amortized = money(price / max(life_sessions, 1))
|
|
28
|
+
allin = money(marginal + amortized)
|
|
29
|
+
return {
|
|
30
|
+
"kw": round(kw, 2),
|
|
31
|
+
"hours_incl_preheat": round(hours + preheat_frac, 2),
|
|
32
|
+
"kwh_rate": kwh,
|
|
33
|
+
"energy_per_session": energy,
|
|
34
|
+
"supplies_per_session": supplies,
|
|
35
|
+
"marginal_per_session": marginal,
|
|
36
|
+
"amortized_per_session": amortized,
|
|
37
|
+
"allin_per_session": allin,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def payoff(price, marginal, dropin, freq, life_sessions):
|
|
42
|
+
"""Weeks/years to pay off the purchase at `freq` sessions per week.
|
|
43
|
+
|
|
44
|
+
Returns (weeks, years, note). weeks is None when it never pays off.
|
|
45
|
+
"""
|
|
46
|
+
gap = dropin - marginal
|
|
47
|
+
if dropin <= 0:
|
|
48
|
+
return None, None, "gym is free (membership includes it): home never wins"
|
|
49
|
+
if gap <= 0:
|
|
50
|
+
return None, None, "energy+supplies already exceed the drop-in price"
|
|
51
|
+
weeks = price / (gap * freq)
|
|
52
|
+
return round(weeks, 1), round(weeks / 52.0, 1), None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def verdict_for(m, dropin, freq, life_sessions):
|
|
56
|
+
"""Honest verdict: does the purchase pay off inside the amortization
|
|
57
|
+
window? That happens iff dropin >= marginal + amortized (the all-in)."""
|
|
58
|
+
if dropin <= 0:
|
|
59
|
+
return "keep the membership: the amenity is already free", 0
|
|
60
|
+
if m["marginal_per_session"] >= dropin:
|
|
61
|
+
return "home loses: running cost alone exceeds the drop-in", 1
|
|
62
|
+
if m["allin_per_session"] <= dropin:
|
|
63
|
+
return "home wins", 0
|
|
64
|
+
return ("never amortizes in %d sessions: ownership play only"
|
|
65
|
+
% life_sessions), 0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def main(argv=None):
|
|
69
|
+
p = argparse.ArgumentParser(
|
|
70
|
+
description="Home recovery purchase vs drop-in: cost per session "
|
|
71
|
+
"and payoff time.")
|
|
72
|
+
p.add_argument("--price", type=float, required=True,
|
|
73
|
+
help="purchase price of the home unit ($)")
|
|
74
|
+
p.add_argument("--watts", type=float, required=True,
|
|
75
|
+
help="nameplate heater draw (W)")
|
|
76
|
+
p.add_argument("--hours", type=float, default=0.75,
|
|
77
|
+
help="session length in hours (default 0.75)")
|
|
78
|
+
p.add_argument("--preheat", type=float, default=0.5,
|
|
79
|
+
help="preheat draw in full-draw hours (default 0.5)")
|
|
80
|
+
p.add_argument("--kwh", type=float, required=True,
|
|
81
|
+
help="your electric rate ($/kWh)")
|
|
82
|
+
p.add_argument("--supplies-year", type=float, default=0.0,
|
|
83
|
+
help="annual filter/treatment cost ($)")
|
|
84
|
+
p.add_argument("--sessions-year", type=int, default=100,
|
|
85
|
+
help="expected sessions per year (supplies divisor)")
|
|
86
|
+
p.add_argument("--life-sessions", type=int,
|
|
87
|
+
default=AMORT_SESSIONS_DEFAULT,
|
|
88
|
+
help="sessions over which to amortize the purchase")
|
|
89
|
+
p.add_argument("--dropin", type=float, required=True,
|
|
90
|
+
help="studio/gym drop-in price per session ($)")
|
|
91
|
+
p.add_argument("--freq", type=float, default=1.0,
|
|
92
|
+
help="planned sessions per week for the payoff clock "
|
|
93
|
+
"(default 1.0)")
|
|
94
|
+
p.add_argument("--name", default="home unit", help="label for output")
|
|
95
|
+
p.add_argument("--json", action="store_true", help="JSON output")
|
|
96
|
+
args = p.parse_args(argv)
|
|
97
|
+
|
|
98
|
+
if args.sessions_year <= 0:
|
|
99
|
+
p.error("--sessions-year must be positive")
|
|
100
|
+
if args.life_sessions <= 0:
|
|
101
|
+
p.error("--life-sessions must be positive")
|
|
102
|
+
if args.freq <= 0:
|
|
103
|
+
p.error("--freq must be positive")
|
|
104
|
+
|
|
105
|
+
m = cost_model(args.price, args.watts, args.hours, args.preheat,
|
|
106
|
+
args.kwh, args.supplies_year, args.sessions_year,
|
|
107
|
+
args.life_sessions)
|
|
108
|
+
weeks, years, note = payoff(args.price, m["marginal_per_session"],
|
|
109
|
+
args.dropin, args.freq, args.life_sessions)
|
|
110
|
+
verdict, rc = verdict_for(m, args.dropin, args.freq, args.life_sessions)
|
|
111
|
+
|
|
112
|
+
out = {
|
|
113
|
+
"name": args.name,
|
|
114
|
+
"dropin": args.dropin,
|
|
115
|
+
"freq_per_week": args.freq,
|
|
116
|
+
**m,
|
|
117
|
+
"payoff_weeks_at_freq": weeks,
|
|
118
|
+
"payoff_years_at_freq": years,
|
|
119
|
+
"note": note,
|
|
120
|
+
"verdict": verdict,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if args.json:
|
|
124
|
+
print(json.dumps(out, indent=2))
|
|
125
|
+
return rc
|
|
126
|
+
|
|
127
|
+
print("== %s vs drop-in" % args.name)
|
|
128
|
+
print("Energy per session %6.2f (%.2f kW, %.2f h incl. preheat, "
|
|
129
|
+
"$%.3f/kWh)" % (m["energy_per_session"], m["kw"],
|
|
130
|
+
m["hours_incl_preheat"], args.kwh))
|
|
131
|
+
print("Supplies per session %6.2f ($%.0f/yr, %d sessions/yr)"
|
|
132
|
+
% (m["supplies_per_session"], args.supplies_year,
|
|
133
|
+
args.sessions_year))
|
|
134
|
+
print("Marginal cost/session %6.2f" % m["marginal_per_session"])
|
|
135
|
+
print("Amortized/session %6.2f (over %d sessions)"
|
|
136
|
+
% (m["amortized_per_session"], args.life_sessions))
|
|
137
|
+
print("All-in/session %6.2f" % m["allin_per_session"])
|
|
138
|
+
print("Drop-in price %6.2f" % args.dropin)
|
|
139
|
+
if note:
|
|
140
|
+
print("Payoff %s" % note)
|
|
141
|
+
else:
|
|
142
|
+
print("Payoff at %.1f/wk %6.1f wk (%.1f yr)"
|
|
143
|
+
% (args.freq, weeks, years))
|
|
144
|
+
print("Verdict: %s" % verdict)
|
|
145
|
+
return rc
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
sys.exit(main())
|