node-red-contrib-power-saver 3.2.3 → 3.4.0
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.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/docs/.vuepress/clientAppEnhance.js +5 -0
- package/docs/.vuepress/components/BestSaveVerificator.vue +306 -0
- package/docs/.vuepress/components/DonateButtons.vue +87 -0
- package/docs/.vuepress/config.js +36 -7
- package/docs/.vuepress/dist/404.html +5 -5
- package/docs/.vuepress/dist/assets/css/563.styles.99f4a8aa.css +1 -0
- package/docs/.vuepress/dist/assets/css/835.styles.c5afb22b.css +1 -0
- package/docs/.vuepress/dist/assets/css/{styles.e835bef6.css → styles.031dcf27.css} +2 -1
- package/docs/.vuepress/dist/assets/img/best-save-config.79a2f39a.png +0 -0
- package/docs/.vuepress/dist/assets/img/copy-payload-best-save.b9192985.png +0 -0
- package/docs/.vuepress/dist/assets/img/heat-capacitor-temperatureVsPrice.6e74905b.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-strategy-heat-capacitor-cascade-control.2e75ed9e.png +0 -0
- package/docs/.vuepress/dist/assets/img/node-ps-strategy-heat-capacitor-simple-flow-example.29d9bf59.png +0 -0
- package/docs/.vuepress/dist/assets/img/oven-setpoint-calculation.5bda0eec.png +0 -0
- package/docs/.vuepress/dist/assets/img/overshoot-time.b3b5d70e.png +0 -0
- package/docs/.vuepress/dist/assets/js/262.cf2c57d2.js +1 -0
- package/docs/.vuepress/dist/assets/js/{293.5e967839.js → 293.08ea5200.js} +0 -0
- package/docs/.vuepress/dist/assets/js/331.15ee3c51.js +1 -0
- package/docs/.vuepress/dist/assets/js/{491.c183eba3.js → 491.17a98f38.js} +0 -0
- package/docs/.vuepress/dist/assets/js/619.8ba1b1f6.js +2 -0
- package/docs/.vuepress/dist/assets/js/{812.79dad458.js.LICENSE.txt → 619.8ba1b1f6.js.LICENSE.txt} +0 -0
- package/docs/.vuepress/dist/assets/js/811.6a3392d5.js +1 -0
- package/docs/.vuepress/dist/assets/js/app.e881e9b6.js +1 -0
- package/docs/.vuepress/dist/assets/js/runtime~app.8bebaa00.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-0607240a.661e1808.js → v-0607240a.a57c2199.js} +0 -0
- package/docs/.vuepress/dist/assets/js/{v-08683c60.a6b9cf5b.js → v-08683c60.ccafdcab.js} +0 -0
- package/docs/.vuepress/dist/assets/js/v-0aca7ba6.4f3573a3.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.76407435.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-1ad821fa.6e2194d0.js → v-1ad821fa.5978386f.js} +0 -0
- package/docs/.vuepress/dist/assets/js/v-1b3a0ab8.def099e9.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-1e2b191e.98cc227b.js → v-1e2b191e.88dc5555.js} +0 -0
- package/docs/.vuepress/dist/assets/js/v-29504124.4aca27d5.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-30acb564.f2fcd69f.js → v-30acb564.529a3c16.js} +0 -0
- package/docs/.vuepress/dist/assets/js/v-4637f9e4.5cc542f6.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-4c28314d.48fc6e75.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-510ed0d4.b58000bf.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-5954bcb2.182daf70.js → v-5954bcb2.937005d0.js} +0 -0
- package/docs/.vuepress/dist/assets/js/{v-5db8da3a.f2de6cb9.js → v-5db8da3a.3de3588d.js} +1 -1
- package/docs/.vuepress/dist/assets/js/{v-61f728ca.6fdbbb92.js → v-61f728ca.21d432fe.js} +1 -1
- package/docs/.vuepress/dist/assets/js/v-677dfaed.1ad4c776.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-7446a652.74b21d0b.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-7c87f26e.5e3553b0.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-84304104.f66996c5.js +1 -0
- package/docs/.vuepress/dist/assets/js/{v-8daa1a0e.dde202c9.js → v-8daa1a0e.c06c5c76.js} +1 -1
- package/docs/.vuepress/dist/assets/js/{v-b4a42144.9e5f9728.js → v-b4a42144.733e4e7c.js} +0 -0
- package/docs/.vuepress/dist/assets/js/v-e8c55052.9664f731.js +1 -0
- package/docs/.vuepress/dist/assets/js/v-fffb8e28.525be02a.js +1 -0
- package/docs/.vuepress/dist/changelog/index.html +5 -5
- package/docs/.vuepress/dist/contribute/index.html +5 -5
- package/docs/.vuepress/dist/examples/example-cascade-temperature-control.html +286 -0
- package/docs/.vuepress/dist/examples/example-heat-capacitor.html +229 -0
- package/docs/.vuepress/dist/examples/example-next-schedule-entity.html +6 -6
- package/docs/.vuepress/dist/examples/example-nordpool-current-state.html +6 -7
- package/docs/.vuepress/dist/examples/example-nordpool-events-state.html +6 -6
- package/docs/.vuepress/dist/examples/example-tibber-mqtt.html +6 -7
- package/docs/.vuepress/dist/examples/index.html +5 -5
- package/docs/.vuepress/dist/faq/best-save-viewer.html +15 -0
- package/docs/.vuepress/dist/faq/index.html +5 -5
- package/docs/.vuepress/dist/guide/index.html +6 -6
- package/docs/.vuepress/dist/index.html +5 -5
- package/docs/.vuepress/dist/nodes/index.html +5 -5
- package/docs/.vuepress/dist/nodes/old-power-saver-doc.html +7 -7
- package/docs/.vuepress/dist/nodes/power-saver.html +5 -5
- package/docs/.vuepress/dist/nodes/ps-elvia-add-tariff.html +5 -5
- package/docs/.vuepress/dist/nodes/ps-general-add-tariff.html +5 -5
- package/docs/.vuepress/dist/nodes/ps-receive-price.html +8 -8
- package/docs/.vuepress/dist/nodes/ps-strategy-best-save.html +27 -8
- package/docs/.vuepress/dist/nodes/ps-strategy-heat-capacitor.html +242 -0
- package/docs/.vuepress/dist/nodes/ps-strategy-lowest-price.html +22 -7
- package/docs/.vuepress/dist/nodes/strategy-input.html +5 -5
- package/docs/README.md +4 -1
- package/docs/changelog/README.md +22 -0
- package/docs/contribute/README.md +11 -3
- package/docs/examples/README.md +8 -2
- package/docs/examples/example-cascade-temperature-control.md +345 -0
- package/docs/examples/example-heat-capacitor.md +271 -0
- package/docs/examples/example-nordpool-current-state.md +0 -1
- package/docs/examples/example-tibber-mqtt.md +0 -1
- package/docs/faq/README.md +28 -1
- package/docs/faq/best-save-viewer.md +61 -0
- package/docs/images/best-save-config.png +0 -0
- package/docs/images/copy-payload-best-save.png +0 -0
- package/docs/images/heat-capacitor-temperatureVsPrice.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor-cascade-control.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor-simple-flow-example.png +0 -0
- package/docs/images/node-ps-strategy-heat-capacitor.png +0 -0
- package/docs/images/oven-setpoint-calculation.png +0 -0
- package/docs/images/overshoot-time.png +0 -0
- package/docs/images/temperature-manipulation-config.png +0 -0
- package/docs/nodes/README.md +7 -1
- package/docs/nodes/ps-strategy-best-save.md +95 -8
- package/docs/nodes/ps-strategy-heat-capacitor.md +346 -0
- package/docs/nodes/ps-strategy-lowest-price.md +57 -0
- package/package.json +8 -3
- package/src/handle-input.js +32 -10
- package/src/strategy-best-save.html +0 -21
- package/src/strategy-best-save.js +8 -11
- package/src/strategy-heat-capacitor-functions.js +246 -0
- package/src/strategy-heat-capacitor.html +85 -0
- package/src/strategy-heat-capacitor.js +125 -0
- package/test/commands-input.test.js +47 -0
- package/test/data/best-save-result.json +1 -2
- package/test/data/converted-prices.json +1 -1
- package/test/data/current-undefined-prices.json +197 -0
- package/test/data/current-undefined-result.json +208 -0
- package/test/data/lowest-price-result-missing-end.json +2 -1
- package/test/data/multiple-trades.json +53 -0
- package/test/data/reconfigResult.js +56 -294
- package/test/data/reconfigResult_old2.js +75 -0
- package/test/data/tibber-decreasing-24h.json +101 -0
- package/test/data/tibber-decreasing2-24h.json +101 -0
- package/test/data/tibber-result-end-0-24h.json +1 -0
- package/test/data/tibber-result-end-0.json +1 -0
- package/test/send-config-input.test.js +3 -37
- package/test/strategy-best-save-test-utils.js +2 -1
- package/test/strategy-best-save.test.js +14 -8
- package/test/strategy-heat-capacitor-node.test.js +183 -0
- package/test/strategy-heat-capacitor.test.js +105 -0
- package/test/test-utils.js +1 -7
- package/test/utils.test.js +0 -33
- package/docs/.vuepress/dist/assets/img/best-save-config.93fa3c21.png +0 -0
- package/docs/.vuepress/dist/assets/js/812.79dad458.js +0 -2
- package/docs/.vuepress/dist/assets/js/app.49ad6d54.js +0 -1
- package/docs/.vuepress/dist/assets/js/runtime~app.547d0f4e.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0aca7ba6.b42fad7f.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-0b5e3c8c.3b37457f.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-4637f9e4.b320f5e8.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-510ed0d4.3c7e0056.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-677dfaed.0013f083.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7446a652.d05e2648.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-7c87f26e.1127dcf5.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-e8c55052.8384b053.js +0 -1
- package/docs/.vuepress/dist/assets/js/v-fffb8e28.3406fd88.js +0 -1
- package/test/data/adjustedResult.js +0 -302
- package/test/data/adjustedResult_old.js +0 -154
package/CHANGELOG.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[The changelog has moved here](
|
|
1
|
+
[The changelog has moved here](http://power-saver.smoky.no/changelog/)
|
package/README.md
CHANGED
|
@@ -4,4 +4,4 @@ A Node-RED node to save money when power prices are changing by the hour.
|
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
## Please read more in the [documentation](
|
|
7
|
+
## Please read more in the [documentation](http://power-saver.smoky.no/).
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<textarea rows="5" cols="80" name="rawData" placeHolder="Paste data here" v-model="dataString"></textarea>
|
|
3
|
+
<p>{{ message }}</p>
|
|
4
|
+
<div class="config" v-if="message === '' && payload.version">
|
|
5
|
+
<h3>Config:</h3>
|
|
6
|
+
<p>Max in sequence: {{ payload.config.maxHoursToSaveInSequence }}</p>
|
|
7
|
+
<p>Min on after max: {{ payload.config.minHoursOnAfterMaxSequenceSaved }}</p>
|
|
8
|
+
<p>Minimum saving: {{ payload.config.minSaving }}</p>
|
|
9
|
+
<p>Send when rescheduling: {{ payload.config.sendCurrentValueWhenRescheduling ? "Yes" : "No" }}</p>
|
|
10
|
+
<p>If no schedule, output: {{ payload.config.outputIfNoSchedule ? "On" : "Off" }}</p>
|
|
11
|
+
<h3>Meta data:</h3>
|
|
12
|
+
<p>Node version: {{ payload.version }}</p>
|
|
13
|
+
<p>Data timestamp: {{ payload.time }}</p>
|
|
14
|
+
<p>Price source: {{ payload.source }}</p>
|
|
15
|
+
<p>Current output: {{ payload.current ? "On" : "Off" }}</p>
|
|
16
|
+
<hr />
|
|
17
|
+
<h3>Days:</h3>
|
|
18
|
+
<table>
|
|
19
|
+
<tr>
|
|
20
|
+
<th>Date</th>
|
|
21
|
+
<th v-tooltip="'Number of hours for the day'">Hours</th>
|
|
22
|
+
<th v-tooltip="'Number of hours that are on'">Count on</th>
|
|
23
|
+
<th v-tooltip="'Number of hours that are off'">Count off</th>
|
|
24
|
+
<th v-tooltip="'Average price for the day'">Avg price</th>
|
|
25
|
+
<th v-tooltip="'Number of hours that are turned off (saved)'">Count saved</th>
|
|
26
|
+
<th v-tooltip="'Sum saved per kWh for the hours that are saved'">Sum saved</th>
|
|
27
|
+
<th v-tooltip="'Sum saved / count saved'">Avg saved 1</th>
|
|
28
|
+
<th v-tooltip="'Sum saved / Hours (whole day)'">Avg saved 2</th>
|
|
29
|
+
</tr>
|
|
30
|
+
<tr v-for="day in dayData" :key="day.date">
|
|
31
|
+
<td>{{ day.date }}</td>
|
|
32
|
+
<td>{{ day.countHours }}</td>
|
|
33
|
+
<td>{{ day.countOn }}</td>
|
|
34
|
+
<td>{{ day.countOff }}</td>
|
|
35
|
+
<td>{{ day.avgPrice }}</td>
|
|
36
|
+
<td>{{ day.countSaved }}</td>
|
|
37
|
+
<td>{{ day.sumSaved }}</td>
|
|
38
|
+
<td>{{ day.avgSaved1 }}</td>
|
|
39
|
+
<td>{{ day.avgSaved2 }}</td>
|
|
40
|
+
</tr>
|
|
41
|
+
</table>
|
|
42
|
+
|
|
43
|
+
<h3>Hours:</h3>
|
|
44
|
+
|
|
45
|
+
<div>
|
|
46
|
+
<input type="checkbox" id="showNegative" v-model="showNegative" />
|
|
47
|
+
<label for="showNegative">Show negative</label>
|
|
48
|
+
|
|
49
|
+
<label style="margin-left: 40px">Show saving per sequence as:</label>
|
|
50
|
+
<input type="radio" id="sum" value="sum" v-model="show" />
|
|
51
|
+
<label for="sum">Sum</label>
|
|
52
|
+
<input type="radio" id="avg" value="avg" v-model="show" />
|
|
53
|
+
<label for="avg">Average</label>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<table>
|
|
57
|
+
<tr>
|
|
58
|
+
<th colspan="5">Input data</th>
|
|
59
|
+
<th class="sepcol"></th>
|
|
60
|
+
<th :colspan="differenceColumns.length">Saving if turned off x hours</th>
|
|
61
|
+
<th class="sepcol"></th>
|
|
62
|
+
<th :colspan="differenceColumns.length">Saving for sequence of x hours</th>
|
|
63
|
+
</tr>
|
|
64
|
+
<tr>
|
|
65
|
+
<th>Date</th>
|
|
66
|
+
<th>Hour</th>
|
|
67
|
+
<th>Price</th>
|
|
68
|
+
<th>On/Off</th>
|
|
69
|
+
<th>Saving</th>
|
|
70
|
+
<th class="sepcol"></th>
|
|
71
|
+
<th v-for="h in differenceColumns" :key="h">
|
|
72
|
+
{{ h }}
|
|
73
|
+
</th>
|
|
74
|
+
<th class="sepcol"></th>
|
|
75
|
+
<th v-for="h in differenceColumns" :key="h">
|
|
76
|
+
{{ h }}
|
|
77
|
+
</th>
|
|
78
|
+
</tr>
|
|
79
|
+
<tr v-for="(hour, i) in payload.hours" :key="hour.start">
|
|
80
|
+
<td>{{ DateTime.fromISO(hour.start).day }}</td>
|
|
81
|
+
<td>{{ DateTime.fromISO(hour.start).toLocaleString(DateTime.TIME_SIMPLE) }}</td>
|
|
82
|
+
<td :class="priceClasses(i)">{{ hour.price }}</td>
|
|
83
|
+
<td>{{ hour.onOff ? "On" : "Off" }}</td>
|
|
84
|
+
<td>{{ hour.saving ?? "" }}</td>
|
|
85
|
+
<td class="sepcol"></td>
|
|
86
|
+
<td v-for="(h, j) in differenceColumns" :key="h" @click="showSavingSource(i, j)" :class="savingClasses(i, j)">
|
|
87
|
+
{{ showNegative || differencePerHour[i][j] > 0 ? differencePerHour[i][j] : "" }}
|
|
88
|
+
</td>
|
|
89
|
+
<td class="sepcol"></td>
|
|
90
|
+
<td
|
|
91
|
+
v-for="(h, j) in differenceColumns"
|
|
92
|
+
:key="h"
|
|
93
|
+
@click="showSequenceSource(i, j)"
|
|
94
|
+
:class="sequenceClasses(i, j)"
|
|
95
|
+
>
|
|
96
|
+
{{
|
|
97
|
+
showNegative || totalPerSequence[i][j] > 0
|
|
98
|
+
? "" + (showSum ? totalPerSequence[i][j] : averagePerSequence[i][j])
|
|
99
|
+
: ""
|
|
100
|
+
}}
|
|
101
|
+
</td>
|
|
102
|
+
</tr>
|
|
103
|
+
</table>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
|
|
107
|
+
<script setup>
|
|
108
|
+
import { computed, onMounted, reactive, ref, watch } from "vue";
|
|
109
|
+
|
|
110
|
+
const { roundPrice } = require("../../../src/utils");
|
|
111
|
+
const { DateTime } = require("luxon");
|
|
112
|
+
|
|
113
|
+
const message = ref("");
|
|
114
|
+
const showNegative = ref(false);
|
|
115
|
+
|
|
116
|
+
const show = ref("avg");
|
|
117
|
+
const showSum = computed(() => show.value === "sum");
|
|
118
|
+
|
|
119
|
+
console.log("This is the setup script");
|
|
120
|
+
|
|
121
|
+
const dataString = ref("");
|
|
122
|
+
watch(dataString, (value) => {
|
|
123
|
+
convert(value);
|
|
124
|
+
calculatePotentialSavings();
|
|
125
|
+
highlightSequence.length = 0;
|
|
126
|
+
clickedSequence.row = null;
|
|
127
|
+
clickedSequence.col = null;
|
|
128
|
+
clickedSaving.row = null;
|
|
129
|
+
clickedSaving.col = null;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const payload = reactive({});
|
|
133
|
+
function convert(value) {
|
|
134
|
+
try {
|
|
135
|
+
const obj = JSON.parse(value);
|
|
136
|
+
const pl = obj.payload ?? obj;
|
|
137
|
+
Object.keys(pl).forEach((key) => (payload[key] = pl[key]));
|
|
138
|
+
message.value = "";
|
|
139
|
+
} catch (e) {
|
|
140
|
+
message.value = "No legal JSON data";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const differencePerHour = reactive([]);
|
|
145
|
+
const differenceColumns = reactive([]);
|
|
146
|
+
const totalPerSequence = reactive([]);
|
|
147
|
+
const averagePerSequence = reactive([]);
|
|
148
|
+
|
|
149
|
+
function calculatePotentialSavings() {
|
|
150
|
+
const hours = payload.hours;
|
|
151
|
+
|
|
152
|
+
// Savings per hour
|
|
153
|
+
for (let i = 0; i < payload.config.maxHoursToSaveInSequence; i++) {
|
|
154
|
+
differenceColumns[i] = i + 1;
|
|
155
|
+
}
|
|
156
|
+
for (let i = 0; i < hours.length; i++) {
|
|
157
|
+
const row = reactive([]);
|
|
158
|
+
for (let j = 0; j < differenceColumns.length; j++) {
|
|
159
|
+
row[j] = i + j + 1 < hours.length ? roundPrice(hours[i].price - hours[i + j + 1].price) : null;
|
|
160
|
+
}
|
|
161
|
+
differencePerHour[i] = row;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Savings per sequence
|
|
165
|
+
for (let i = 0; i < hours.length; i++) {
|
|
166
|
+
const tot = reactive([]);
|
|
167
|
+
const avg = reactive([]);
|
|
168
|
+
for (let j = 0; j < differenceColumns.length; j++) {
|
|
169
|
+
tot[j] = 0;
|
|
170
|
+
for (let k = 0; k <= j; k++) {
|
|
171
|
+
const res = tot[j] + (i + k < hours.length ? differencePerHour[i + k][j - k] : 0);
|
|
172
|
+
tot[j] = roundPrice(res);
|
|
173
|
+
avg[j] = roundPrice(res / (j + 1));
|
|
174
|
+
}
|
|
175
|
+
totalPerSequence[i] = tot;
|
|
176
|
+
averagePerSequence[i] = avg;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Daily data
|
|
182
|
+
const dayData = computed(() => {
|
|
183
|
+
const hours = payload.hours;
|
|
184
|
+
const dates = [...new Set(hours.map((h) => DateTime.fromISO(h.start).toISODate()))];
|
|
185
|
+
const days = dates.map((d) => {
|
|
186
|
+
return { date: d };
|
|
187
|
+
});
|
|
188
|
+
days.forEach((d) => {
|
|
189
|
+
const dayHours = hours.filter((h) => DateTime.fromISO(h.start).toISODate() === d.date);
|
|
190
|
+
d.countHours = dayHours.length;
|
|
191
|
+
d.countOn = dayHours.filter((h) => h.onOff).length;
|
|
192
|
+
d.countOff = dayHours.filter((h) => !h.onOff).length;
|
|
193
|
+
d.countSaved = dayHours.filter((h) => h.saving !== null).length;
|
|
194
|
+
d.avgPrice = roundPrice(
|
|
195
|
+
dayHours.reduce((prev, h) => {
|
|
196
|
+
return prev + h.price;
|
|
197
|
+
}, 0.0) / d.countHours
|
|
198
|
+
);
|
|
199
|
+
d.sumSaved =
|
|
200
|
+
d.countSaved > 0
|
|
201
|
+
? roundPrice(
|
|
202
|
+
dayHours.reduce((prev, h) => {
|
|
203
|
+
return prev + h.saving ?? 0;
|
|
204
|
+
}, 0)
|
|
205
|
+
)
|
|
206
|
+
: null;
|
|
207
|
+
d.avgSaved1 = d.countSaved > 0 ? roundPrice(d.sumSaved / d.countSaved) : null;
|
|
208
|
+
d.avgSaved2 = d.countSaved > 0 ? roundPrice(d.sumSaved / d.countHours) : null;
|
|
209
|
+
});
|
|
210
|
+
return days;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Event handlers
|
|
214
|
+
|
|
215
|
+
// Show source for sequence sums
|
|
216
|
+
const highlightSequence = reactive([]);
|
|
217
|
+
const clickedSequence = reactive({ row: null, col: null });
|
|
218
|
+
function showSequenceSource(row, col) {
|
|
219
|
+
const sameCell = row === clickedSequence.row && col === clickedSequence.col;
|
|
220
|
+
highlightSequence.length = 0;
|
|
221
|
+
clickedSequence.row = sameCell ? null : row;
|
|
222
|
+
clickedSequence.col = sameCell ? null : col;
|
|
223
|
+
for (let c = 0; c <= col && !sameCell; c++) {
|
|
224
|
+
highlightSequence.push({ row: row + c, col: col - c });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Show source for saving
|
|
229
|
+
const clickedSaving = reactive({ row: null, col: null });
|
|
230
|
+
function showSavingSource(row, col) {
|
|
231
|
+
const sameCell = row === clickedSaving.row && col === clickedSaving.col;
|
|
232
|
+
clickedSaving.row = sameCell ? null : row;
|
|
233
|
+
clickedSaving.col = sameCell ? null : col;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Styling functions
|
|
237
|
+
|
|
238
|
+
function priceClasses(i) {
|
|
239
|
+
let hl =
|
|
240
|
+
clickedSaving.row === null ? false : clickedSaving.row === i || clickedSaving.row + clickedSaving.col === i - 1;
|
|
241
|
+
let res = hl ? "highlightSaving " : " ";
|
|
242
|
+
return res;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function savingClasses(i, j) {
|
|
246
|
+
const seq = highlightSequence.some((cell) => cell.row === i && cell.col === j);
|
|
247
|
+
const sav = i === clickedSaving.row && j === clickedSaving.col;
|
|
248
|
+
const res = "selectable ";
|
|
249
|
+
if (seq & sav) {
|
|
250
|
+
return res + "highlightBoth";
|
|
251
|
+
}
|
|
252
|
+
if (seq) {
|
|
253
|
+
return res + "highlightSequence";
|
|
254
|
+
}
|
|
255
|
+
if (sav) {
|
|
256
|
+
return res + "highlightSaving";
|
|
257
|
+
}
|
|
258
|
+
return res;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function sequenceClasses(i, j) {
|
|
262
|
+
let res = clickedSequence.row === i && clickedSequence.col === j ? "highlightSequence " : " ";
|
|
263
|
+
if (averagePerSequence[i][j] < payload.config.minSaving) {
|
|
264
|
+
res = res + "belowMin ";
|
|
265
|
+
}
|
|
266
|
+
return res + "selectable";
|
|
267
|
+
}
|
|
268
|
+
</script>
|
|
269
|
+
|
|
270
|
+
<style scoped>
|
|
271
|
+
.config > p {
|
|
272
|
+
margin: 0;
|
|
273
|
+
padding: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
td,
|
|
277
|
+
th {
|
|
278
|
+
margin: 2px 4px;
|
|
279
|
+
padding: 2px 4px;
|
|
280
|
+
font-size: small;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.highlightSequence {
|
|
284
|
+
background-color: lightskyblue;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.highlightSaving {
|
|
288
|
+
background-color: yellow;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.highlightBoth {
|
|
292
|
+
background-color: lightgreen;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.belowMin {
|
|
296
|
+
color: red;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.selectable {
|
|
300
|
+
cursor: pointer;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.sepcol {
|
|
304
|
+
background-color: darkgray;
|
|
305
|
+
}
|
|
306
|
+
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="box">
|
|
3
|
+
<div class="left">
|
|
4
|
+
<form action="https://www.paypal.com/donate" method="post" target="_blank">
|
|
5
|
+
<input type="hidden" name="business" value="5K5SRZU27TAC8" />
|
|
6
|
+
<input type="hidden" name="no_recurring" value="0" />
|
|
7
|
+
<input type="hidden" name="item_name" value="One of my hobbies is creating software for smart homes" />
|
|
8
|
+
<input type="hidden" name="currency_code" value="NOK" />
|
|
9
|
+
<input
|
|
10
|
+
type="image"
|
|
11
|
+
src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif"
|
|
12
|
+
border="0"
|
|
13
|
+
name="submit"
|
|
14
|
+
title="PayPal - The safer, easier way to pay online!"
|
|
15
|
+
alt="Donate with PayPal button"
|
|
16
|
+
/>
|
|
17
|
+
<img alt="" border="0" src="https://www.paypal.com/en_NO/i/scr/pixel.gif" width="1" height="1" />
|
|
18
|
+
</form>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="right">
|
|
21
|
+
<a
|
|
22
|
+
class="patreonButton"
|
|
23
|
+
href="https://www.patreon.com/bePatron?u=65948417"
|
|
24
|
+
data-patreon-widget-type="become-patron-button"
|
|
25
|
+
target="_blank"
|
|
26
|
+
>Become a Patron!
|
|
27
|
+
</a>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div><br /></div>
|
|
31
|
+
</template>
|
|
32
|
+
<script setup></script>
|
|
33
|
+
|
|
34
|
+
<style scoped>
|
|
35
|
+
.box {
|
|
36
|
+
display: flex;
|
|
37
|
+
justify-content: space-evenly;
|
|
38
|
+
}
|
|
39
|
+
left {
|
|
40
|
+
flex: 1 1 auto;
|
|
41
|
+
}
|
|
42
|
+
right {
|
|
43
|
+
flex: 1 1 auto;
|
|
44
|
+
}
|
|
45
|
+
.buttonDiv {
|
|
46
|
+
text-size-adjust: 100%;
|
|
47
|
+
color: rgb(36, 30, 18);
|
|
48
|
+
font-family: aktiv-grotesk, sans-serif;
|
|
49
|
+
font-size: 16px;
|
|
50
|
+
-webkit-font-smoothing: antialiased;
|
|
51
|
+
text-rendering: optimizelegibility;
|
|
52
|
+
-webkit-box-direction: normal;
|
|
53
|
+
width: 11rem;
|
|
54
|
+
}
|
|
55
|
+
.patreonButton {
|
|
56
|
+
text-size-adjust: 100%;
|
|
57
|
+
font-family: aktiv-grotesk, sans-serif;
|
|
58
|
+
-webkit-font-smoothing: antialiased;
|
|
59
|
+
text-rendering: optimizelegibility;
|
|
60
|
+
-webkit-box-direction: normal;
|
|
61
|
+
-webkit-box-align: center;
|
|
62
|
+
align-items: center;
|
|
63
|
+
backface-visibility: hidden;
|
|
64
|
+
background-color: rgb(255, 66, 77);
|
|
65
|
+
border-radius: 9999px;
|
|
66
|
+
border: 1px solid rgb(255, 66, 77);
|
|
67
|
+
box-sizing: border-box;
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
font-weight: 500;
|
|
70
|
+
height: unset;
|
|
71
|
+
-webkit-box-pack: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
padding: 0.46875rem 1rem;
|
|
74
|
+
position: relative;
|
|
75
|
+
pointer-events: unset;
|
|
76
|
+
text-align: center;
|
|
77
|
+
text-transform: none;
|
|
78
|
+
transition: all 300ms cubic-bezier(0.19, 1, 0.22, 1) 0s;
|
|
79
|
+
user-select: none;
|
|
80
|
+
white-space: unset;
|
|
81
|
+
width: 100%;
|
|
82
|
+
color: rgb(255, 255, 255) !important;
|
|
83
|
+
font-size: 0.875rem !important;
|
|
84
|
+
text-decoration: none;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
}
|
|
87
|
+
</style>
|
package/docs/.vuepress/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
const { path } = require("@vuepress/utils");
|
|
1
2
|
module.exports = {
|
|
2
3
|
lang: "en-US",
|
|
3
4
|
title: "Power Saver",
|
|
4
5
|
description: "A Node-RED note to save money on hourly changing power prices",
|
|
5
|
-
base: "/
|
|
6
|
-
publicPath: "/node-red-contrib-power-saver/",
|
|
6
|
+
base: "/",
|
|
7
7
|
themeConfig: {
|
|
8
8
|
contributors: false,
|
|
9
9
|
navbar: [
|
|
@@ -19,6 +19,10 @@ module.exports = {
|
|
|
19
19
|
text: "Examples",
|
|
20
20
|
link: "/examples/",
|
|
21
21
|
},
|
|
22
|
+
{
|
|
23
|
+
text: "FAQ",
|
|
24
|
+
link: "/faq/",
|
|
25
|
+
},
|
|
22
26
|
{
|
|
23
27
|
text: "Contribute",
|
|
24
28
|
link: "/contribute/",
|
|
@@ -41,7 +45,11 @@ module.exports = {
|
|
|
41
45
|
{ text: "Power Saver", link: "/nodes/power-saver.md" },
|
|
42
46
|
{
|
|
43
47
|
text: "Strategy nodes",
|
|
44
|
-
children: [
|
|
48
|
+
children: [
|
|
49
|
+
"/nodes/ps-strategy-best-save.md",
|
|
50
|
+
"/nodes/ps-strategy-lowest-price.md",
|
|
51
|
+
{ text: "ps-strategy-heat-capacitor", link: "/nodes/ps-strategy-heat-capacitor.md" },
|
|
52
|
+
],
|
|
45
53
|
},
|
|
46
54
|
{ text: "Utility nodes", children: ["/nodes/ps-receive-price.md"] },
|
|
47
55
|
{
|
|
@@ -62,15 +70,36 @@ module.exports = {
|
|
|
62
70
|
"/examples/example-nordpool-current-state.md",
|
|
63
71
|
"/examples/example-nordpool-events-state.md",
|
|
64
72
|
"/examples/example-tibber-mqtt.md",
|
|
73
|
+
"/examples/example-heat-capacitor.md",
|
|
74
|
+
"/examples/example-cascade-temperature-control.md",
|
|
65
75
|
],
|
|
66
76
|
},
|
|
67
77
|
],
|
|
68
|
-
"/
|
|
69
|
-
"/
|
|
78
|
+
"/faq/": [{ text: "FAQ", children: ["/faq/README.md"] }],
|
|
79
|
+
"/contribute/": [{ text: "Contribute", children: ["/contribute/README.md"] }],
|
|
80
|
+
"/changelog/": [{ text: "Changelog", children: ["/changelog/README.md"] }],
|
|
70
81
|
},
|
|
71
82
|
},
|
|
72
83
|
head: [
|
|
73
|
-
|
|
74
|
-
[
|
|
84
|
+
["link", { rel: "shortcut icon", type: "image/x-icon", href: "euro.png" }],
|
|
85
|
+
[
|
|
86
|
+
"script",
|
|
87
|
+
{
|
|
88
|
+
async: true,
|
|
89
|
+
src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9857859182772006",
|
|
90
|
+
crossorigin: "anonymous",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
],
|
|
94
|
+
plugins: [
|
|
95
|
+
[
|
|
96
|
+
"@vuepress/register-components",
|
|
97
|
+
{
|
|
98
|
+
components: {
|
|
99
|
+
BestSaveVerificator: path.resolve(__dirname, "./components/BestSaveVerificator.vue"),
|
|
100
|
+
DonateButtons: path.resolve(__dirname, "./components/DonateButtons.vue"),
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
75
104
|
],
|
|
76
105
|
};
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
6
|
<meta name="generator" content="VuePress 2.0.0-beta.27">
|
|
7
|
-
<link rel="icon" href="
|
|
8
|
-
<link rel="preload" href="/
|
|
9
|
-
<link rel="stylesheet" href="/
|
|
7
|
+
<link rel="shortcut icon" type="image/x-icon" href="euro.png"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9857859182772006" crossorigin="anonymous"></script><title>Power Saver</title><meta name="description" content="A Node-RED note to save money on hourly changing power prices">
|
|
8
|
+
<link rel="preload" href="/assets/js/runtime~app.8bebaa00.js" as="script"><link rel="preload" href="/assets/css/styles.031dcf27.css" as="style"><link rel="preload" href="/assets/js/619.8ba1b1f6.js" as="script"><link rel="preload" href="/assets/js/app.e881e9b6.js" as="script">
|
|
9
|
+
<link rel="stylesheet" href="/assets/css/styles.031dcf27.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
|
-
<div id="app"><!--[--><div class="theme-container"><div class="theme-default-content"><h1>404</h1><blockquote>
|
|
13
|
-
<script src="/
|
|
12
|
+
<div id="app"><!--[--><div class="theme-container"><div class="theme-default-content"><h1>404</h1><blockquote>Looks like we've got some broken links.</blockquote><a href="/" class="">Take me home</a></div></div><!----><!--]--></div>
|
|
13
|
+
<script src="/assets/js/runtime~app.8bebaa00.js" defer></script><script src="/assets/js/619.8ba1b1f6.js" defer></script><script src="/assets/js/app.e881e9b6.js" defer></script>
|
|
14
14
|
</body>
|
|
15
15
|
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.config>p[data-v-78951500]{margin:0;padding:0}td[data-v-78951500],th[data-v-78951500]{margin:2px 4px;padding:2px 4px;font-size:small}.highlightSequence[data-v-78951500]{background-color:#87cefa}.highlightSaving[data-v-78951500]{background-color:#ff0}.highlightBoth[data-v-78951500]{background-color:#90ee90}.belowMin[data-v-78951500]{color:red}.selectable[data-v-78951500]{cursor:pointer}.sepcol[data-v-78951500]{background-color:#a9a9a9}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.box[data-v-66d8d572]{display:flex;justify-content:space-evenly}left[data-v-66d8d572],right[data-v-66d8d572]{flex:1 1 auto}.buttonDiv[data-v-66d8d572],.patreonButton[data-v-66d8d572]{-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;font-family:aktiv-grotesk,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility}.buttonDiv[data-v-66d8d572]{color:#241e12;font-size:16px;width:11rem}.patreonButton[data-v-66d8d572]{align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:#ff424d;border-radius:9999px;border:1px solid #ff424d;box-sizing:border-box;display:inline-flex;font-weight:500;height:unset;justify-content:center;padding:.46875rem 1rem;position:relative;pointer-events:unset;text-align:center;text-transform:none;transition:all 300ms cubic-bezier(.19,1,.22,1) 0s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:unset;width:100%;color:#fff!important;font-size:.875rem!important;text-decoration:none;cursor:pointer}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
:root{--c-brand:#3eaf7c;--c-brand-light:#4abf8a;--c-bg:#ffffff;--c-bg-light:#f3f4f5;--c-bg-lighter:#eeeeee;--c-bg-navbar:var(--c-bg);--c-bg-sidebar:var(--c-bg);--c-bg-arrow:#cccccc;--c-text:#2c3e50;--c-text-accent:var(--c-brand);--c-text-light:#3a5169;--c-text-lighter:#4e6e8e;--c-text-lightest:#6a8bad;--c-text-quote:#999999;--c-border:#eaecef;--c-border-dark:#dfe2e5;--c-tip:#42b983;--c-tip-bg:var(--c-bg-light);--c-tip-title:var(--c-text);--c-tip-text:var(--c-text);--c-tip-text-accent:var(--c-text-accent);--c-warning:#e7c000;--c-warning-bg:#fffae3;--c-warning-title:#ad9000;--c-warning-text:#746000;--c-warning-text-accent:var(--c-text);--c-danger:#cc0000;--c-danger-bg:#ffe0e0;--c-danger-title:#990000;--c-danger-text:#660000;--c-danger-text-accent:var(--c-text);--c-details-bg:#eeeeee;--c-badge-tip:var(--c-tip);--c-badge-warning:var(--c-warning);--c-badge-danger:var(--c-danger);--t-color:0.3s ease;--t-transform:0.3s ease;--code-bg-color:#282c34;--code-hl-bg-color:rgba(0, 0, 0, 0.66);--code-ln-color:#9e9e9e;--code-ln-wrapper-width:3.5rem;--font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code:Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height:3.6rem;--navbar-padding-v:0.7rem;--navbar-padding-h:1.5rem;--sidebar-width:20rem;--sidebar-width-mobile:calc(var(--sidebar-width) * 0.82);--content-width:740px;--homepage-width:960px}.back-to-top{--back-to-top-color:var(--c-brand);--back-to-top-color-hover:var(--c-brand-light)}.DocSearch{--docsearch-primary-color:var(--c-brand);--docsearch-text-color:var(--c-text);--docsearch-highlight-color:var(--c-brand);--docsearch-muted-color:var(--c-text-quote);--docsearch-container-background:rgba(9, 10, 17, 0.8);--docsearch-modal-background:var(--c-bg-light);--docsearch-searchbox-background:var(--c-bg-lighter);--docsearch-searchbox-focus-background:var(--c-bg);--docsearch-searchbox-shadow:inset 0 0 0 2px var(--c-brand);--docsearch-hit-color:var(--c-text-light);--docsearch-hit-active-color:var(--c-bg);--docsearch-hit-background:var(--c-bg);--docsearch-hit-shadow:0 1px 3px 0 var(--c-border-dark);--docsearch-footer-background:var(--c-bg)}.medium-zoom-overlay{--medium-zoom-bg-color:var(--c-bg)}#nprogress{--nprogress-color:var(--c-brand)}.pwa-popup{--pwa-popup-text-color:var(--c-text);--pwa-popup-bg-color:var(--c-bg);--pwa-popup-border-color:var(--c-brand);--pwa-popup-shadow:0 4px 16px var(--c-brand);--pwa-popup-btn-text-color:var(--c-bg);--pwa-popup-btn-bg-color:var(--c-brand);--pwa-popup-btn-hover-bg-color:var(--c-brand-light)}.search-box{--search-bg-color:var(--c-bg);--search-accent-color:var(--c-brand);--search-text-color:var(--c-text);--search-border-color:var(--c-border);--search-item-text-color:var(--c-text-lighter);--search-item-focus-bg-color:var(--c-bg-light)}html.dark{--c-brand:#3aa675;--c-brand-light:#349469;--c-bg:#22272e;--c-bg-light:#2b313a;--c-bg-lighter:#262c34;--c-text:#adbac7;--c-text-light:#96a7b7;--c-text-lighter:#8b9eb0;--c-text-lightest:#8094a8;--c-border:#3e4c5a;--c-border-dark:#34404c;--c-tip:#318a62;--c-warning:#ceab00;--c-warning-bg:#7e755b;--c-warning-title:#ceac03;--c-warning-text:#362e00;--c-danger:#940000;--c-danger-bg:#806161;--c-danger-title:#610000;--c-danger-text:#3a0000;--c-details-bg:#323843;--code-hl-bg-color:#363b46;color-scheme:dark}html.dark .DocSearch{--docsearch-logo-color:var(--c-text);--docsearch-modal-shadow:inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;--docsearch-key-shadow:inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, 0.3);--docsearch-key-gradient:linear-gradient(-225deg, #444950, #1c1e21);--docsearch-footer-shadow:inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2)}body,html{padding:0;margin:0;background-color:var(--c-bg);transition:background-color var(--t-color)}body{font-family:var(--font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:var(--c-text)}a,p a code{color:var(--c-text-accent)}a{font-weight:500;overflow-wrap:break-word}p a code{font-weight:400}code,kbd{font-family:var(--font-family-code)}kbd{background:var(--c-bg-lighter);border:solid .15rem var(--c-border-dark);border-bottom:solid .25rem var(--c-border-dark);border-radius:.15rem;padding:0 .15em}code{color:var(--c-text-lighter);padding:.25rem .5rem;font-size:.85em;background-color:var(--c-bg-light);border-radius:3px;overflow-wrap:break-word;transition:background-color var(--t-color),color var(--t-color)}blockquote{color:var(--c-text-quote);border-left:.2rem solid var(--c-border-dark);margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p,code{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color)}h3{font-size:1.35rem}h4{font-size:1.15rem}h5{font-size:1.05rem}blockquote,h6{font-size:1rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a,a.header-anchor:hover{text-decoration:none}a.header-anchor:focus-visible{opacity:1}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid var(--c-border)}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid var(--c-border-dark)}tr:nth-child(2n){background-color:var(--c-bg-light)}td,th{border:1px solid var(--c-border-dark);padding:.6em 1em}.arrow,.badge{display:inline-block}.arrow{width:0;height:0}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.up{border-bottom:6px solid var(--c-bg-arrow)}.arrow.down{border-top:6px solid var(--c-bg-arrow)}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.right{border-left:6px solid var(--c-bg-arrow)}.arrow.left{border-right:6px solid var(--c-bg-arrow)}.badge{font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:var(--c-bg);vertical-align:top;transition:color var(--t-color),background-color var(--t-color)}.badge.tip{background-color:var(--c-badge-tip)}.badge.warning{background-color:var(--c-badge-warning)}.badge.danger{background-color:var(--c-badge-danger)}.badge+.badge{margin-left:5px}code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:var(--font-family-code);font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#ec5975}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;border-radius:6px;overflow:auto}.theme-default-content pre code,.theme-default-content pre[class*=language-] code{color:#fff;padding:0;background-color:transparent;border-radius:0;overflow-wrap:unset;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.theme-default-content .line-number{font-family:var(--font-family-code)}div[class*=language-]{position:relative;background-color:var(--code-bg-color);border-radius:6px}div[class*=language-]::before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:var(--code-ln-color)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:0 0!important;position:relative;z-index:1}div[class*=language-] .highlight-lines{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlight-line{background-color:var(--code-hl-bg-color)}div[class*=language-]:not(.line-numbers-mode) .line-numbers{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line::before{content:" ";position:absolute;z-index:2;left:0;top:0;display:block;width:var(--code-ln-wrapper-width);height:100%}div[class*=language-].line-numbers-mode pre{margin-left:var(--code-ln-wrapper-width);padding-left:1rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers{position:absolute;top:0;width:var(--code-ln-wrapper-width);text-align:center;color:var(--code-ln-color);padding-top:1.25rem;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers .line-number,div[class*=language-].line-numbers-mode .line-numbers br{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers .line-number{position:relative;z-index:3;font-size:.85em}div[class*=language-].line-numbers-mode::after{content:"";position:absolute;top:0;left:0;width:var(--code-ln-wrapper-width);height:100%;border-radius:6px 0 0 6px;border-right:1px solid var(--code-hl-bg-color)}div[class*=language-].ext-c:before{content:"c"}div[class*=language-].ext-cpp:before{content:"cpp"}div[class*=language-].ext-cs:before{content:"cs"}div[class*=language-].ext-css:before{content:"css"}div[class*=language-].ext-dart:before{content:"dart"}div[class*=language-].ext-docker:before{content:"docker"}div[class*=language-].ext-fs:before{content:"fs"}div[class*=language-].ext-go:before{content:"go"}div[class*=language-].ext-html:before{content:"html"}div[class*=language-].ext-java:before{content:"java"}div[class*=language-].ext-js:before{content:"js"}div[class*=language-].ext-json:before{content:"json"}div[class*=language-].ext-kt:before{content:"kt"}div[class*=language-].ext-less:before{content:"less"}div[class*=language-].ext-makefile:before{content:"makefile"}div[class*=language-].ext-md:before{content:"md"}div[class*=language-].ext-php:before{content:"php"}div[class*=language-].ext-py:before{content:"py"}div[class*=language-].ext-rb:before{content:"rb"}div[class*=language-].ext-rs:before{content:"rs"}div[class*=language-].ext-sass:before{content:"sass"}div[class*=language-].ext-scss:before{content:"scss"}div[class*=language-].ext-sh:before{content:"sh"}div[class*=language-].ext-styl:before{content:"styl"}div[class*=language-].ext-ts:before{content:"ts"}div[class*=language-].ext-toml:before{content:"toml"}div[class*=language-].ext-vue:before{content:"vue"}div[class*=language-].ext-yml:before{content:"yml"}@media (max-width:419px){.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.code-group__nav{margin-top:.85rem;margin-bottom:calc(-1.7rem - 6px);padding-bottom:calc(1.7rem - 6px);padding-left:10px;padding-top:10px;border-top-left-radius:6px;border-top-right-radius:6px;background-color:var(--code-bg-color)}.code-group__ul{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.code-group__nav-tab{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:rgba(255,255,255,.9);font-weight:600}.code-group__nav-tab:focus{outline:0}.code-group__nav-tab:focus-visible{outline:1px solid rgba(255,255,255,.9)}.code-group__nav-tab-active{border-bottom:var(--c-brand) 1px solid}@media (max-width:419px){.code-group__nav{margin-left:-1.5rem;margin-right:-1.5rem;border-radius:0}}.code-group-item,.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subtitle>a.router-link-active::after{display:none}.code-group-item__active{display:block}.code-group-item>pre{background-color:orange}.custom-container{transition:color var(--t-color),border-color var(--t-color),background-color var(--t-color)}.custom-container .custom-container-title{font-weight:600;margin-bottom:-.4rem}.custom-container.danger,.custom-container.tip,.custom-container.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-container.tip{border-color:var(--c-tip);background-color:var(--c-tip-bg);color:var(--c-tip-text)}.custom-container.tip .custom-container-title{color:var(--c-tip-title)}.custom-container.tip a{color:var(--c-tip-text-accent)}.custom-container.warning{border-color:var(--c-warning);background-color:var(--c-warning-bg);color:var(--c-warning-text)}.custom-container.warning .custom-container-title{color:var(--c-warning-title)}.custom-container.warning a{color:var(--c-warning-text-accent)}.custom-container.danger{border-color:var(--c-danger);background-color:var(--c-danger-bg);color:var(--c-danger-text)}.custom-container.danger .custom-container-title{color:var(--c-danger-title)}.custom-container.danger a{color:var(--c-danger-text-accent)}.custom-container.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:var(--c-details-bg)}.custom-container.details h4{margin-top:0}.custom-container.details figure:last-child,.custom-container.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-container.details summary{outline:0;cursor:pointer}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title,.dropdown-wrapper .mobile-dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:0 0;border:0;font-weight:500;color:var(--c-text)}.dropdown-wrapper .mobile-dropdown-title{display:none;font-weight:600;font-size:inherit}.dropdown-wrapper .dropdown-title:hover,.dropdown-wrapper .mobile-dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow,.dropdown-wrapper .mobile-dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .mobile-dropdown-title:hover{color:var(--c-text-accent)}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subtitle{margin:.45rem 0 0;border-top:1px solid var(--c-border);padding:1rem 0 .45rem;font-size:.9rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subtitle>span{padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subtitle>a{font-weight:inherit}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover,.navbar-links a.router-link-active,.navbar-links a:hover{color:var(--c-text-accent)}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after{content:"";width:0;height:0;border-left:5px solid var(--c-text-accent);border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child .dropdown-subtitle{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title,.dropdown-wrapper.open .mobile-dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{display:none}.dropdown-wrapper .mobile-dropdown-title{display:block}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subtitle{border-top:0;margin-top:0;padding-top:0;padding-bottom:0;font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item>a{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:720px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:var(--c-bg-navbar);padding:.6rem 0;border:1px solid var(--c-border);border-bottom-color:var(--c-border-dark);text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.dropdown-enter-from,.dropdown-leave-to{height:0!important}.home{padding:var(--navbar-height) 2rem 0;max-width:var(--homepage-width);margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .actions,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .actions{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:var(--c-text-lightest)}.home .hero .action-button{display:inline-block;font-size:1.2rem;padding:.8rem 1.6rem;border-width:2px;border-style:solid;border-radius:4px;transition:background-color var(--t-color);box-sizing:border-box}.home .hero .action-button.primary{color:var(--c-bg);background-color:var(--c-brand);border-color:var(--c-brand)}.home .hero .action-button.primary:hover{background-color:var(--c-brand-light)}.home .hero .action-button.secondary{color:var(--c-brand);background-color:var(--c-bg);border-color:var(--c-brand)}.home .hero .action-button.secondary:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.home .features{border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:var(--c-text-light)}.home .feature p,.home .footer{color:var(--c-text-lighter)}.home .footer{padding:2.5rem;border-top:1px solid var(--c-border);text-align:center;transition:border-color var(--t-color)}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .actions,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.theme-default-content:not(.custom){max-width:var(--content-width);margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.page{padding-top:var(--navbar-height);padding-left:var(--sidebar-width)}.navbar,.sidebar{position:fixed;left:0;box-sizing:border-box}.navbar{z-index:20;top:0;right:0;height:var(--navbar-height);border-bottom:1px solid var(--c-border);background-color:var(--c-bg-navbar);transition:background-color var(--t-color),border-color var(--t-color)}.sidebar{font-size:16px;width:var(--sidebar-width);z-index:10;margin:0;top:var(--navbar-height);bottom:0;border-right:1px solid var(--c-border);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--c-brand) var(--c-border);background-color:var(--c-bg-sidebar);transition:transform var(--t-transform),background-color var(--t-color),border-color var(--t-color)}.sidebar::-webkit-scrollbar{width:7px}.sidebar::-webkit-scrollbar-track{background-color:var(--c-border)}.sidebar::-webkit-scrollbar-thumb{background-color:var(--c-brand)}.sidebar-mask{position:fixed;z-index:9;top:0;left:0;width:100vw;height:100vh;display:none}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1){transform:rotate(45deg) translate3d(5.5px,5.5px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(2){transform:scale3d(0,1,1)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform:rotate(-45deg) translate3d(6px,-6px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1),.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform-origin:center}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .page{padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:calc(.5rem - var(--navbar-height));padding-top:calc(1rem + var(--navbar-height));margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-container,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-container,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-container,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-container,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-container,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-container,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}.theme-default-content:not(.custom){padding-top:0}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}@media (max-width:959px){.sidebar{font-size:15px;width:var(--sidebar-width-mobile)}.page{padding-left:var(--sidebar-width-mobile)}}@media (max-width:719px){.sidebar{top:0;padding-top:var(--navbar-height);transform:translateX(-100%)}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}}.navbar{--navbar-line-height:calc( var(--navbar-height) - 2 * var(--navbar-padding-v) );padding:var(--navbar-padding-v) var(--navbar-padding-h);line-height:var(--navbar-line-height)}.navbar .logo{height:var(--navbar-line-height);margin-right:var(--navbar-padding-v);vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:var(--c-text);position:relative}.navbar .navbar-links-wrapper{display:flex;position:absolute;box-sizing:border-box;top:var(--navbar-padding-v);right:var(--navbar-padding-h);height:var(--navbar-line-height);padding-left:var(--navbar-padding-h);white-space:nowrap;font-size:.9rem}.navbar .navbar-links-wrapper .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.navbar-links,.navbar-links a{display:inline-block}.navbar-links a{line-height:1.4rem;color:inherit}.navbar-links .navbar-links-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:var(--navbar-line-height)}.navbar-links .navbar-links-item:first-child{margin-left:0}@media (max-width:719px){.navbar-links .navbar-links-item{margin-left:0}}@media (min-width:719px){.navbar-links a.router-link-active,.navbar-links a:hover{color:var(--c-text)}.navbar-links-item>a:not(.external).router-link-active,.navbar-links-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid var(--c-text-accent)}}.toggle-sidebar-button{position:absolute;top:.6rem;left:1rem;display:none;padding:.6rem;cursor:pointer}.toggle-sidebar-button .icon{display:flex;flex-direction:column;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;cursor:inherit}.toggle-sidebar-button .icon span{display:inline-block;width:100%;height:2px;border-radius:2px;background-color:var(--c-text);transition:transform var(--t-transform)}.toggle-sidebar-button .icon span:nth-child(2){margin:6px 0}@media screen and (max-width:719px){.toggle-sidebar-button{display:block}}.toggle-dark-button{display:flex;margin:auto;margin-left:1rem;border:0;background:0 0;color:var(--c-text);opacity:.8;cursor:pointer}.toggle-dark-button:hover{opacity:1}.toggle-dark-button .icon{width:1.25rem;height:1.25rem}.page-meta,.page-nav{max-width:var(--content-width);margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-meta,.page-nav{padding:2rem}}@media (max-width:419px){.page-meta,.page-nav{padding:1.5rem}}.page{padding-bottom:2rem;display:block}.page-meta{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-meta .meta-item{cursor:default;margin-top:.8rem}.page-meta .meta-item .meta-item-label{font-weight:500;color:var(--c-text-lighter)}.page-meta .meta-item .meta-item-info{font-weight:400;color:var(--c-text-quote)}.page-meta .edit-link{display:inline-block;margin-right:.25rem}.page-meta .last-updated{float:right}@media (max-width:719px){.page-meta .last-updated{font-size:.8em;float:none}.page-meta .contributors{font-size:.8em}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding-top:1rem;overflow:auto}.page-nav .next{float:right}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .navbar-links{display:none;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color);padding:.5rem 0 .75rem}.sidebar .navbar-links a{font-weight:600}.sidebar .navbar-links .navbar-links-item{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar .sidebar-links{padding:1.5rem 0}.sidebar .sidebar-links>li:not(:first-child),.sidebar-links>.sidebar-item:not(.sidebar-heading):not(:first-child){margin-top:.75rem}.sidebar .sidebar-links .sidebar-sub-items{padding-left:1rem;font-size:.95em}@media (max-width:719px){.sidebar .navbar-links{display:block}.sidebar .navbar-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after{top:calc(1rem - 2px)}.sidebar .sidebar-links{padding:1rem 0}}.sidebar-heading{color:var(--c-text);transition:color .15s ease;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-item:not(.sidebar-heading){font-size:1em;font-weight:400;display:inline-block;color:var(--c-text);border-left:.25rem solid transparent;margin:0;padding:.35rem 1rem .35rem 2rem;line-height:1.4;width:100%;box-sizing:border-box}.sidebar-sub-items .sidebar-item:not(.sidebar-heading){padding:.25rem 1rem .25rem 1.75rem}.sidebar-item{cursor:default}a.sidebar-item{cursor:pointer}a.sidebar-item.active,a.sidebar-item:hover{color:var(--c-text-accent)}a.sidebar-item.active{font-weight:600;border-left-color:var(--c-text-accent)}a.sidebar-item.sidebar-heading.active{font-weight:700;border-left-color:transparent}.sidebar-sub-items a.sidebar-item.active{font-weight:500;border-left-color:transparent}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.table-of-contents .badge{vertical-align:middle}.fade-slide-y-enter-active{transition:all .3s ease}.fade-slide-y-leave-active{transition:all .3s cubic-bezier(1,.5,.8,1)}.fade-slide-y-enter-from,.fade-slide-y-leave-to{transform:translateY(10px);opacity:0}
|
|
3
3
|
:root{--medium-zoom-z-index:100;--medium-zoom-bg-color:#ffffff;--medium-zoom-opacity:1}
|
|
4
4
|
.medium-zoom-overlay{background-color:var(--medium-zoom-bg-color)!important;z-index:var(--medium-zoom-z-index)}.medium-zoom-overlay~img{z-index:calc(var(--medium-zoom-z-index) + 1)}.medium-zoom--opened .medium-zoom-overlay{opacity:var(--medium-zoom-opacity)}
|
|
5
|
+
.resize-observer[data-v-b329ee4c]{border:0;background-color:transparent;opacity:0}.resize-observer[data-v-b329ee4c],.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper__popper{z-index:10000;top:0;left:0}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__inner{position:relative;box-sizing:border-box;overflow-y:auto}.v-popper__inner>div{position:relative;z-index:1}.v-popper__arrow-container{position:absolute;width:10px;height:10px}.v-popper__popper--arrow-overflow .v-popper__arrow-container{display:none}.v-popper__arrow-inner,.v-popper__arrow-outer{border-style:solid;position:absolute;top:0;left:0;width:0;height:0}.v-popper__arrow-inner{visibility:hidden;border-width:7px}.v-popper__arrow-outer{border-width:6px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{left:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{left:-1px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{border-bottom-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{border-top-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{top:-4px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{top:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{top:-1px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{border-left-width:0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{left:-4px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{left:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-10px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer{border-right-width:0;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner{left:-2px}.v-popper{width:-webkit-max-content;width:-moz-max-content;width:max-content}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;border-radius:6px;border:1px solid #ddd;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow-inner{visibility:visible;border-color:#fff}.v-popper--theme-dropdown .v-popper__arrow-outer{border-color:#ddd}.v-popper--theme-tooltip .v-popper__inner{background:rgba(0,0,0,.8);color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow-outer{border-color:#000c}
|
|
5
6
|
:root{--back-to-top-z-index:5;--back-to-top-color:#3eaf7c;--back-to-top-color-hover:#71cda3}
|
|
6
|
-
.back-to-top{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;height:1.2rem;background-color:var(--back-to-top-color);-webkit-mask:url(/
|
|
7
|
+
.back-to-top{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;height:1.2rem;background-color:var(--back-to-top-color);-webkit-mask:url(/assets/img/back-to-top.8b37f773.svg) no-repeat;mask:url(/assets/img/back-to-top.8b37f773.svg) no-repeat;z-index:var(--back-to-top-z-index)}.back-to-top:hover{background-color:var(--back-to-top-color-hover)}@media (max-width:959px){.back-to-top{display:none}}.back-to-top-enter-active,.back-to-top-leave-active{transition:opacity .3s}.back-to-top-enter-from,.back-to-top-leave-to{opacity:0}
|
|
7
8
|
:root{--nprogress-color:#29d;--nprogress-z-index:1031}
|
|
8
9
|
#nprogress{pointer-events:none}#nprogress .bar{background:var(--nprogress-color);position:fixed;z-index:var(--nprogress-z-index);top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px var(--nprogress-color),0 0 5px var(--nprogress-color);opacity:1;transform:rotate(3deg) translate(0,-4px)}
|
|
Binary file
|
|
Binary file
|
package/docs/.vuepress/dist/assets/img/node-ps-strategy-heat-capacitor-cascade-control.2e75ed9e.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|