eco-calculator-core 1.1.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/README.md +32 -0
- package/dist/index.d.mts +74 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +91 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# eco-calculator-core
|
|
2
|
+
|
|
3
|
+
**TypeScript библиотека для точного расчёта углеродного следа.**
|
|
4
|
+
|
|
5
|
+
Используется в проекте [EcoTrackr](https://github.com/yourusername/ecotrackr).
|
|
6
|
+
|
|
7
|
+
## Использование
|
|
8
|
+
|
|
9
|
+
import { CarbonCalculator, EmissionEntry } from 'eco-calculator-core';
|
|
10
|
+
|
|
11
|
+
const entries: EmissionEntry[] = [
|
|
12
|
+
{ category: 'transport', activity: 'car', value: 150, unit: 'km' },
|
|
13
|
+
{ category: 'food', activity: 'beef', value: 2, unit: 'kg' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const total = CarbonCalculator.calculateTotal(entries);
|
|
17
|
+
const breakdown = CarbonCalculator.getCategoryBreakdown(entries);
|
|
18
|
+
const suggestions = CarbonCalculator.getSuggestions(total);
|
|
19
|
+
|
|
20
|
+
console.log(`Total CO₂e: ${total} кг`);
|
|
21
|
+
|
|
22
|
+
Основные методыCarbonCalculator.calculate() — расчёт одной записи
|
|
23
|
+
CarbonCalculator.calculateTotal() — общий расчёт
|
|
24
|
+
CarbonCalculator.getCategoryBreakdown() — разбивка по категориям
|
|
25
|
+
CarbonCalculator.getSuggestions() — персональные рекомендации
|
|
26
|
+
CarbonCalculator.getMonthlySummary() — полная сводка
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Установка
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install eco-calculator-core
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface EmissionEntry {
|
|
2
|
+
category: string;
|
|
3
|
+
activity: string;
|
|
4
|
+
value: number;
|
|
5
|
+
unit: string;
|
|
6
|
+
date?: string;
|
|
7
|
+
}
|
|
8
|
+
interface CalculationResult {
|
|
9
|
+
co2e: number;
|
|
10
|
+
category: string;
|
|
11
|
+
activity: string;
|
|
12
|
+
value: number;
|
|
13
|
+
unit: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare const EMISSION_FACTORS: {
|
|
17
|
+
readonly transport: {
|
|
18
|
+
readonly car: 0.192;
|
|
19
|
+
readonly electric_car: 0.045;
|
|
20
|
+
readonly plane: 0.24;
|
|
21
|
+
readonly train: 0.041;
|
|
22
|
+
readonly bus: 0.089;
|
|
23
|
+
readonly metro: 0.035;
|
|
24
|
+
readonly bike: 0;
|
|
25
|
+
readonly walk: 0;
|
|
26
|
+
};
|
|
27
|
+
readonly energy: {
|
|
28
|
+
readonly electricity: 0.475;
|
|
29
|
+
readonly gas: 0.202;
|
|
30
|
+
readonly heating_oil: 0.35;
|
|
31
|
+
readonly coal: 0.95;
|
|
32
|
+
};
|
|
33
|
+
readonly food: {
|
|
34
|
+
readonly beef: 99.5;
|
|
35
|
+
readonly lamb: 39.2;
|
|
36
|
+
readonly pork: 12.5;
|
|
37
|
+
readonly chicken: 14;
|
|
38
|
+
readonly fish: 13.5;
|
|
39
|
+
readonly eggs: 4.8;
|
|
40
|
+
readonly cheese: 23.8;
|
|
41
|
+
readonly milk: 3.2;
|
|
42
|
+
readonly vegetables: 2.5;
|
|
43
|
+
readonly fruits: 1.8;
|
|
44
|
+
readonly rice: 4;
|
|
45
|
+
readonly plant_based: 2.5;
|
|
46
|
+
};
|
|
47
|
+
readonly shopping: {
|
|
48
|
+
readonly clothes: 15;
|
|
49
|
+
readonly electronics: 120;
|
|
50
|
+
readonly plastic: 3.5;
|
|
51
|
+
readonly furniture: 8.5;
|
|
52
|
+
};
|
|
53
|
+
readonly waste: {
|
|
54
|
+
readonly general: 0.5;
|
|
55
|
+
readonly plastic: 2.8;
|
|
56
|
+
readonly paper: 1.1;
|
|
57
|
+
readonly food_waste: 2.5;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
type Category = keyof typeof EMISSION_FACTORS;
|
|
61
|
+
type Activity<C extends Category> = keyof typeof EMISSION_FACTORS[C];
|
|
62
|
+
|
|
63
|
+
declare class CarbonCalculator {
|
|
64
|
+
static calculate(entry: EmissionEntry): CalculationResult;
|
|
65
|
+
static calculateTotal(entries: EmissionEntry[]): number;
|
|
66
|
+
static getCategoryBreakdown(entries: EmissionEntry[]): {
|
|
67
|
+
category: string;
|
|
68
|
+
co2e: number;
|
|
69
|
+
percentage: number;
|
|
70
|
+
}[];
|
|
71
|
+
static getSuggestions(totalCO2: number): string[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type Activity, type CalculationResult, CarbonCalculator, type Category, EMISSION_FACTORS, type EmissionEntry };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface EmissionEntry {
|
|
2
|
+
category: string;
|
|
3
|
+
activity: string;
|
|
4
|
+
value: number;
|
|
5
|
+
unit: string;
|
|
6
|
+
date?: string;
|
|
7
|
+
}
|
|
8
|
+
interface CalculationResult {
|
|
9
|
+
co2e: number;
|
|
10
|
+
category: string;
|
|
11
|
+
activity: string;
|
|
12
|
+
value: number;
|
|
13
|
+
unit: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare const EMISSION_FACTORS: {
|
|
17
|
+
readonly transport: {
|
|
18
|
+
readonly car: 0.192;
|
|
19
|
+
readonly electric_car: 0.045;
|
|
20
|
+
readonly plane: 0.24;
|
|
21
|
+
readonly train: 0.041;
|
|
22
|
+
readonly bus: 0.089;
|
|
23
|
+
readonly metro: 0.035;
|
|
24
|
+
readonly bike: 0;
|
|
25
|
+
readonly walk: 0;
|
|
26
|
+
};
|
|
27
|
+
readonly energy: {
|
|
28
|
+
readonly electricity: 0.475;
|
|
29
|
+
readonly gas: 0.202;
|
|
30
|
+
readonly heating_oil: 0.35;
|
|
31
|
+
readonly coal: 0.95;
|
|
32
|
+
};
|
|
33
|
+
readonly food: {
|
|
34
|
+
readonly beef: 99.5;
|
|
35
|
+
readonly lamb: 39.2;
|
|
36
|
+
readonly pork: 12.5;
|
|
37
|
+
readonly chicken: 14;
|
|
38
|
+
readonly fish: 13.5;
|
|
39
|
+
readonly eggs: 4.8;
|
|
40
|
+
readonly cheese: 23.8;
|
|
41
|
+
readonly milk: 3.2;
|
|
42
|
+
readonly vegetables: 2.5;
|
|
43
|
+
readonly fruits: 1.8;
|
|
44
|
+
readonly rice: 4;
|
|
45
|
+
readonly plant_based: 2.5;
|
|
46
|
+
};
|
|
47
|
+
readonly shopping: {
|
|
48
|
+
readonly clothes: 15;
|
|
49
|
+
readonly electronics: 120;
|
|
50
|
+
readonly plastic: 3.5;
|
|
51
|
+
readonly furniture: 8.5;
|
|
52
|
+
};
|
|
53
|
+
readonly waste: {
|
|
54
|
+
readonly general: 0.5;
|
|
55
|
+
readonly plastic: 2.8;
|
|
56
|
+
readonly paper: 1.1;
|
|
57
|
+
readonly food_waste: 2.5;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
type Category = keyof typeof EMISSION_FACTORS;
|
|
61
|
+
type Activity<C extends Category> = keyof typeof EMISSION_FACTORS[C];
|
|
62
|
+
|
|
63
|
+
declare class CarbonCalculator {
|
|
64
|
+
static calculate(entry: EmissionEntry): CalculationResult;
|
|
65
|
+
static calculateTotal(entries: EmissionEntry[]): number;
|
|
66
|
+
static getCategoryBreakdown(entries: EmissionEntry[]): {
|
|
67
|
+
category: string;
|
|
68
|
+
co2e: number;
|
|
69
|
+
percentage: number;
|
|
70
|
+
}[];
|
|
71
|
+
static getSuggestions(totalCO2: number): string[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { type Activity, type CalculationResult, CarbonCalculator, type Category, EMISSION_FACTORS, type EmissionEntry };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
CarbonCalculator: () => CarbonCalculator,
|
|
24
|
+
EMISSION_FACTORS: () => EMISSION_FACTORS
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/factors.ts
|
|
29
|
+
var EMISSION_FACTORS = {
|
|
30
|
+
transport: {
|
|
31
|
+
car: 0.192,
|
|
32
|
+
electric_car: 0.045,
|
|
33
|
+
plane: 0.24,
|
|
34
|
+
train: 0.041,
|
|
35
|
+
bus: 0.089,
|
|
36
|
+
metro: 0.035,
|
|
37
|
+
bike: 0,
|
|
38
|
+
walk: 0
|
|
39
|
+
},
|
|
40
|
+
energy: {
|
|
41
|
+
electricity: 0.475,
|
|
42
|
+
gas: 0.202,
|
|
43
|
+
heating_oil: 0.35,
|
|
44
|
+
coal: 0.95
|
|
45
|
+
},
|
|
46
|
+
food: {
|
|
47
|
+
beef: 99.5,
|
|
48
|
+
lamb: 39.2,
|
|
49
|
+
pork: 12.5,
|
|
50
|
+
chicken: 14,
|
|
51
|
+
fish: 13.5,
|
|
52
|
+
eggs: 4.8,
|
|
53
|
+
cheese: 23.8,
|
|
54
|
+
milk: 3.2,
|
|
55
|
+
vegetables: 2.5,
|
|
56
|
+
fruits: 1.8,
|
|
57
|
+
rice: 4,
|
|
58
|
+
plant_based: 2.5
|
|
59
|
+
},
|
|
60
|
+
shopping: {
|
|
61
|
+
clothes: 15,
|
|
62
|
+
electronics: 120,
|
|
63
|
+
plastic: 3.5,
|
|
64
|
+
furniture: 8.5
|
|
65
|
+
},
|
|
66
|
+
waste: {
|
|
67
|
+
general: 0.5,
|
|
68
|
+
plastic: 2.8,
|
|
69
|
+
paper: 1.1,
|
|
70
|
+
food_waste: 2.5
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/calculator.ts
|
|
75
|
+
var CarbonCalculator = class {
|
|
76
|
+
static calculate(entry) {
|
|
77
|
+
const categoryFactors = EMISSION_FACTORS[entry.category];
|
|
78
|
+
const factor = categoryFactors?.[entry.activity] ?? 0;
|
|
79
|
+
const co2e = Number((entry.value * factor).toFixed(2));
|
|
80
|
+
return {
|
|
81
|
+
co2e,
|
|
82
|
+
category: entry.category,
|
|
83
|
+
activity: entry.activity,
|
|
84
|
+
value: entry.value,
|
|
85
|
+
unit: entry.unit
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
static calculateTotal(entries) {
|
|
89
|
+
return entries.reduce((sum, entry) => sum + this.calculate(entry).co2e, 0);
|
|
90
|
+
}
|
|
91
|
+
static getCategoryBreakdown(entries) {
|
|
92
|
+
const total = this.calculateTotal(entries);
|
|
93
|
+
const breakdown = entries.reduce((acc, entry) => {
|
|
94
|
+
const result = this.calculate(entry);
|
|
95
|
+
acc[entry.category] = (acc[entry.category] ?? 0) + result.co2e;
|
|
96
|
+
return acc;
|
|
97
|
+
}, {});
|
|
98
|
+
return Object.entries(breakdown).map(([category, co2e]) => ({
|
|
99
|
+
category,
|
|
100
|
+
co2e: Number(co2e.toFixed(2)),
|
|
101
|
+
percentage: total > 0 ? Number((co2e / total * 100).toFixed(1)) : 0
|
|
102
|
+
})).sort((a, b) => b.co2e - a.co2e);
|
|
103
|
+
}
|
|
104
|
+
static getSuggestions(totalCO2) {
|
|
105
|
+
if (totalCO2 > 1e3) {
|
|
106
|
+
return ["\u0421\u043E\u043A\u0440\u0430\u0442\u0438\u0442\u0435 \u0430\u0432\u0438\u0430\u043F\u0435\u0440\u0435\u043B\u0451\u0442\u044B", "\u0420\u0430\u0441\u0441\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043C\u043E\u0431\u0438\u043B\u044C", "\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u0435 \u043A\u0440\u0430\u0441\u043D\u043E\u0435 \u043C\u044F\u0441\u043E"];
|
|
107
|
+
}
|
|
108
|
+
if (totalCO2 > 600) {
|
|
109
|
+
return ["\u0411\u043E\u043B\u044C\u0448\u0435 \u043E\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0430", "\u042D\u043A\u043E\u043D\u043E\u043C\u044C\u0442\u0435 \u044D\u043D\u0435\u0440\u0433\u0438\u044E", "\u0420\u0430\u0441\u0442\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0434\u043D\u0438"];
|
|
110
|
+
}
|
|
111
|
+
return ["\u041E\u0442\u043B\u0438\u0447\u043D\u044B\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442! \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0439\u0442\u0435!"];
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
115
|
+
0 && (module.exports = {
|
|
116
|
+
CarbonCalculator,
|
|
117
|
+
EMISSION_FACTORS
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/factors.ts","../src/calculator.ts"],"sourcesContent":["// src/index.ts\nexport * from './types';\nexport * from './factors';\nexport { CarbonCalculator } from './calculator';","// src/factors.ts\nexport const EMISSION_FACTORS = {\n transport: {\n car: 0.192,\n electric_car: 0.045,\n plane: 0.24,\n train: 0.041,\n bus: 0.089,\n metro: 0.035,\n bike: 0,\n walk: 0,\n },\n energy: {\n electricity: 0.475,\n gas: 0.202,\n heating_oil: 0.35,\n coal: 0.95,\n },\n food: {\n beef: 99.5,\n lamb: 39.2,\n pork: 12.5,\n chicken: 14.0,\n fish: 13.5,\n eggs: 4.8,\n cheese: 23.8,\n milk: 3.2,\n vegetables: 2.5,\n fruits: 1.8,\n rice: 4.0,\n plant_based: 2.5,\n },\n shopping: {\n clothes: 15,\n electronics: 120,\n plastic: 3.5,\n furniture: 8.5,\n },\n waste: {\n general: 0.5,\n plastic: 2.8,\n paper: 1.1,\n food_waste: 2.5,\n },\n} as const;\n\nexport type Category = keyof typeof EMISSION_FACTORS;\nexport type Activity<C extends Category> = keyof typeof EMISSION_FACTORS[C];","// src/calculator.ts\nimport { EMISSION_FACTORS } from './factors';\nimport type { EmissionEntry, CalculationResult } from './types';\n\nexport class CarbonCalculator {\n static calculate(entry: EmissionEntry): CalculationResult {\n const categoryFactors = EMISSION_FACTORS[entry.category as keyof typeof EMISSION_FACTORS];\n const factor = categoryFactors?.[entry.activity as keyof typeof categoryFactors] ?? 0;\n\n const co2e = Number((entry.value * factor).toFixed(2));\n\n return {\n co2e,\n category: entry.category,\n activity: entry.activity,\n value: entry.value,\n unit: entry.unit,\n };\n }\n\n static calculateTotal(entries: EmissionEntry[]): number {\n return entries.reduce((sum, entry) => sum + this.calculate(entry).co2e, 0);\n }\n\n static getCategoryBreakdown(entries: EmissionEntry[]) {\n const total = this.calculateTotal(entries);\n\n const breakdown = entries.reduce((acc, entry) => {\n const result = this.calculate(entry);\n acc[entry.category] = (acc[entry.category] ?? 0) + result.co2e;\n return acc;\n }, {} as Record<string, number>);\n\n return Object.entries(breakdown)\n .map(([category, co2e]) => ({\n category,\n co2e: Number(co2e.toFixed(2)),\n percentage: total > 0 ? Number(((co2e / total) * 100).toFixed(1)) : 0,\n }))\n .sort((a, b) => b.co2e - a.co2e);\n }\n\n static getSuggestions(totalCO2: number): string[] {\n if (totalCO2 > 1000) {\n return [\"Сократите авиаперелёты\", \"Рассмотрите электромобиль\", \"Уменьшите красное мясо\"];\n }\n if (totalCO2 > 600) {\n return [\"Больше общественного транспорта\", \"Экономьте энергию\", \"Растительные дни\"];\n }\n return [\"Отличный результат! Продолжайте!\"];\n }\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,IAAM,mBAAmB;AAAA,EAC5B,WAAW;AAAA,IACP,KAAK;AAAA,IACL,cAAc;AAAA,IACd,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACJ,aAAa;AAAA,IACb,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,aAAa;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACH,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,EAChB;AACJ;;;ACxCO,IAAM,mBAAN,MAAuB;AAAA,EAC1B,OAAO,UAAU,OAAyC;AACtD,UAAM,kBAAkB,iBAAiB,MAAM,QAAyC;AACxF,UAAM,SAAS,kBAAkB,MAAM,QAAwC,KAAK;AAEpF,UAAM,OAAO,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC;AAErD,WAAO;AAAA,MACH;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,MAAM,MAAM;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,OAAO,eAAe,SAAkC;AACpD,WAAO,QAAQ,OAAO,CAAC,KAAK,UAAU,MAAM,KAAK,UAAU,KAAK,EAAE,MAAM,CAAC;AAAA,EAC7E;AAAA,EAEA,OAAO,qBAAqB,SAA0B;AAClD,UAAM,QAAQ,KAAK,eAAe,OAAO;AAEzC,UAAM,YAAY,QAAQ,OAAO,CAAC,KAAK,UAAU;AAC7C,YAAM,SAAS,KAAK,UAAU,KAAK;AACnC,UAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,KAAK,KAAK,OAAO;AAC1D,aAAO;AAAA,IACX,GAAG,CAAC,CAA2B;AAE/B,WAAO,OAAO,QAAQ,SAAS,EAC1B,IAAI,CAAC,CAAC,UAAU,IAAI,OAAO;AAAA,MACxB;AAAA,MACA,MAAM,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,MAC5B,YAAY,QAAQ,IAAI,QAAS,OAAO,QAAS,KAAK,QAAQ,CAAC,CAAC,IAAI;AAAA,IACxE,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAAA,EACvC;AAAA,EAEA,OAAO,eAAe,UAA4B;AAC9C,QAAI,WAAW,KAAM;AACjB,aAAO,CAAC,mIAA0B,qJAA6B,4HAAwB;AAAA,IAC3F;AACA,QAAI,WAAW,KAAK;AAChB,aAAO,CAAC,oLAAmC,qGAAqB,6FAAkB;AAAA,IACtF;AACA,WAAO,CAAC,8KAAkC;AAAA,EAC9C;AACJ;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// src/factors.ts
|
|
2
|
+
var EMISSION_FACTORS = {
|
|
3
|
+
transport: {
|
|
4
|
+
car: 0.192,
|
|
5
|
+
electric_car: 0.045,
|
|
6
|
+
plane: 0.24,
|
|
7
|
+
train: 0.041,
|
|
8
|
+
bus: 0.089,
|
|
9
|
+
metro: 0.035,
|
|
10
|
+
bike: 0,
|
|
11
|
+
walk: 0
|
|
12
|
+
},
|
|
13
|
+
energy: {
|
|
14
|
+
electricity: 0.475,
|
|
15
|
+
gas: 0.202,
|
|
16
|
+
heating_oil: 0.35,
|
|
17
|
+
coal: 0.95
|
|
18
|
+
},
|
|
19
|
+
food: {
|
|
20
|
+
beef: 99.5,
|
|
21
|
+
lamb: 39.2,
|
|
22
|
+
pork: 12.5,
|
|
23
|
+
chicken: 14,
|
|
24
|
+
fish: 13.5,
|
|
25
|
+
eggs: 4.8,
|
|
26
|
+
cheese: 23.8,
|
|
27
|
+
milk: 3.2,
|
|
28
|
+
vegetables: 2.5,
|
|
29
|
+
fruits: 1.8,
|
|
30
|
+
rice: 4,
|
|
31
|
+
plant_based: 2.5
|
|
32
|
+
},
|
|
33
|
+
shopping: {
|
|
34
|
+
clothes: 15,
|
|
35
|
+
electronics: 120,
|
|
36
|
+
plastic: 3.5,
|
|
37
|
+
furniture: 8.5
|
|
38
|
+
},
|
|
39
|
+
waste: {
|
|
40
|
+
general: 0.5,
|
|
41
|
+
plastic: 2.8,
|
|
42
|
+
paper: 1.1,
|
|
43
|
+
food_waste: 2.5
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/calculator.ts
|
|
48
|
+
var CarbonCalculator = class {
|
|
49
|
+
static calculate(entry) {
|
|
50
|
+
const categoryFactors = EMISSION_FACTORS[entry.category];
|
|
51
|
+
const factor = categoryFactors?.[entry.activity] ?? 0;
|
|
52
|
+
const co2e = Number((entry.value * factor).toFixed(2));
|
|
53
|
+
return {
|
|
54
|
+
co2e,
|
|
55
|
+
category: entry.category,
|
|
56
|
+
activity: entry.activity,
|
|
57
|
+
value: entry.value,
|
|
58
|
+
unit: entry.unit
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
static calculateTotal(entries) {
|
|
62
|
+
return entries.reduce((sum, entry) => sum + this.calculate(entry).co2e, 0);
|
|
63
|
+
}
|
|
64
|
+
static getCategoryBreakdown(entries) {
|
|
65
|
+
const total = this.calculateTotal(entries);
|
|
66
|
+
const breakdown = entries.reduce((acc, entry) => {
|
|
67
|
+
const result = this.calculate(entry);
|
|
68
|
+
acc[entry.category] = (acc[entry.category] ?? 0) + result.co2e;
|
|
69
|
+
return acc;
|
|
70
|
+
}, {});
|
|
71
|
+
return Object.entries(breakdown).map(([category, co2e]) => ({
|
|
72
|
+
category,
|
|
73
|
+
co2e: Number(co2e.toFixed(2)),
|
|
74
|
+
percentage: total > 0 ? Number((co2e / total * 100).toFixed(1)) : 0
|
|
75
|
+
})).sort((a, b) => b.co2e - a.co2e);
|
|
76
|
+
}
|
|
77
|
+
static getSuggestions(totalCO2) {
|
|
78
|
+
if (totalCO2 > 1e3) {
|
|
79
|
+
return ["\u0421\u043E\u043A\u0440\u0430\u0442\u0438\u0442\u0435 \u0430\u0432\u0438\u0430\u043F\u0435\u0440\u0435\u043B\u0451\u0442\u044B", "\u0420\u0430\u0441\u0441\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043C\u043E\u0431\u0438\u043B\u044C", "\u0423\u043C\u0435\u043D\u044C\u0448\u0438\u0442\u0435 \u043A\u0440\u0430\u0441\u043D\u043E\u0435 \u043C\u044F\u0441\u043E"];
|
|
80
|
+
}
|
|
81
|
+
if (totalCO2 > 600) {
|
|
82
|
+
return ["\u0411\u043E\u043B\u044C\u0448\u0435 \u043E\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0440\u0430\u043D\u0441\u043F\u043E\u0440\u0442\u0430", "\u042D\u043A\u043E\u043D\u043E\u043C\u044C\u0442\u0435 \u044D\u043D\u0435\u0440\u0433\u0438\u044E", "\u0420\u0430\u0441\u0442\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0434\u043D\u0438"];
|
|
83
|
+
}
|
|
84
|
+
return ["\u041E\u0442\u043B\u0438\u0447\u043D\u044B\u0439 \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442! \u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0439\u0442\u0435!"];
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
export {
|
|
88
|
+
CarbonCalculator,
|
|
89
|
+
EMISSION_FACTORS
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/factors.ts","../src/calculator.ts"],"sourcesContent":["// src/factors.ts\nexport const EMISSION_FACTORS = {\n transport: {\n car: 0.192,\n electric_car: 0.045,\n plane: 0.24,\n train: 0.041,\n bus: 0.089,\n metro: 0.035,\n bike: 0,\n walk: 0,\n },\n energy: {\n electricity: 0.475,\n gas: 0.202,\n heating_oil: 0.35,\n coal: 0.95,\n },\n food: {\n beef: 99.5,\n lamb: 39.2,\n pork: 12.5,\n chicken: 14.0,\n fish: 13.5,\n eggs: 4.8,\n cheese: 23.8,\n milk: 3.2,\n vegetables: 2.5,\n fruits: 1.8,\n rice: 4.0,\n plant_based: 2.5,\n },\n shopping: {\n clothes: 15,\n electronics: 120,\n plastic: 3.5,\n furniture: 8.5,\n },\n waste: {\n general: 0.5,\n plastic: 2.8,\n paper: 1.1,\n food_waste: 2.5,\n },\n} as const;\n\nexport type Category = keyof typeof EMISSION_FACTORS;\nexport type Activity<C extends Category> = keyof typeof EMISSION_FACTORS[C];","// src/calculator.ts\nimport { EMISSION_FACTORS } from './factors';\nimport type { EmissionEntry, CalculationResult } from './types';\n\nexport class CarbonCalculator {\n static calculate(entry: EmissionEntry): CalculationResult {\n const categoryFactors = EMISSION_FACTORS[entry.category as keyof typeof EMISSION_FACTORS];\n const factor = categoryFactors?.[entry.activity as keyof typeof categoryFactors] ?? 0;\n\n const co2e = Number((entry.value * factor).toFixed(2));\n\n return {\n co2e,\n category: entry.category,\n activity: entry.activity,\n value: entry.value,\n unit: entry.unit,\n };\n }\n\n static calculateTotal(entries: EmissionEntry[]): number {\n return entries.reduce((sum, entry) => sum + this.calculate(entry).co2e, 0);\n }\n\n static getCategoryBreakdown(entries: EmissionEntry[]) {\n const total = this.calculateTotal(entries);\n\n const breakdown = entries.reduce((acc, entry) => {\n const result = this.calculate(entry);\n acc[entry.category] = (acc[entry.category] ?? 0) + result.co2e;\n return acc;\n }, {} as Record<string, number>);\n\n return Object.entries(breakdown)\n .map(([category, co2e]) => ({\n category,\n co2e: Number(co2e.toFixed(2)),\n percentage: total > 0 ? Number(((co2e / total) * 100).toFixed(1)) : 0,\n }))\n .sort((a, b) => b.co2e - a.co2e);\n }\n\n static getSuggestions(totalCO2: number): string[] {\n if (totalCO2 > 1000) {\n return [\"Сократите авиаперелёты\", \"Рассмотрите электромобиль\", \"Уменьшите красное мясо\"];\n }\n if (totalCO2 > 600) {\n return [\"Больше общественного транспорта\", \"Экономьте энергию\", \"Растительные дни\"];\n }\n return [\"Отличный результат! Продолжайте!\"];\n }\n}"],"mappings":";AACO,IAAM,mBAAmB;AAAA,EAC5B,WAAW;AAAA,IACP,KAAK;AAAA,IACL,cAAc;AAAA,IACd,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACJ,aAAa;AAAA,IACb,KAAK;AAAA,IACL,aAAa;AAAA,IACb,MAAM;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,aAAa;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACN,SAAS;AAAA,IACT,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACf;AAAA,EACA,OAAO;AAAA,IACH,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,EAChB;AACJ;;;ACxCO,IAAM,mBAAN,MAAuB;AAAA,EAC1B,OAAO,UAAU,OAAyC;AACtD,UAAM,kBAAkB,iBAAiB,MAAM,QAAyC;AACxF,UAAM,SAAS,kBAAkB,MAAM,QAAwC,KAAK;AAEpF,UAAM,OAAO,QAAQ,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC;AAErD,WAAO;AAAA,MACH;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,MAAM,MAAM;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,OAAO,eAAe,SAAkC;AACpD,WAAO,QAAQ,OAAO,CAAC,KAAK,UAAU,MAAM,KAAK,UAAU,KAAK,EAAE,MAAM,CAAC;AAAA,EAC7E;AAAA,EAEA,OAAO,qBAAqB,SAA0B;AAClD,UAAM,QAAQ,KAAK,eAAe,OAAO;AAEzC,UAAM,YAAY,QAAQ,OAAO,CAAC,KAAK,UAAU;AAC7C,YAAM,SAAS,KAAK,UAAU,KAAK;AACnC,UAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,KAAK,KAAK,OAAO;AAC1D,aAAO;AAAA,IACX,GAAG,CAAC,CAA2B;AAE/B,WAAO,OAAO,QAAQ,SAAS,EAC1B,IAAI,CAAC,CAAC,UAAU,IAAI,OAAO;AAAA,MACxB;AAAA,MACA,MAAM,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,MAC5B,YAAY,QAAQ,IAAI,QAAS,OAAO,QAAS,KAAK,QAAQ,CAAC,CAAC,IAAI;AAAA,IACxE,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAAA,EACvC;AAAA,EAEA,OAAO,eAAe,UAA4B;AAC9C,QAAI,WAAW,KAAM;AACjB,aAAO,CAAC,mIAA0B,qJAA6B,4HAAwB;AAAA,IAC3F;AACA,QAAI,WAAW,KAAK;AAChB,aAAO,CAAC,oLAAmC,qGAAqB,6FAAkB;AAAA,IACtF;AACA,WAAO,CAAC,8KAAkC;AAAA,EAC9C;AACJ;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eco-calculator-core",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Lightweight and accurate TypeScript library for carbon footprint calculations. Used in EcoTrackr project.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"dev": "tsup --watch",
|
|
14
|
+
"test": "vitest",
|
|
15
|
+
"test:ci": "vitest run",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"carbon",
|
|
20
|
+
"co2",
|
|
21
|
+
"footprint",
|
|
22
|
+
"calculator",
|
|
23
|
+
"ecology",
|
|
24
|
+
"sustainability",
|
|
25
|
+
"climate",
|
|
26
|
+
"typescript"
|
|
27
|
+
],
|
|
28
|
+
"author": "Your Name",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/yourusername/eco-calculator-core"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/yourusername/eco-calculator-core#readme",
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"tsup": "^8.3.0",
|
|
37
|
+
"typescript": "^5.7.2",
|
|
38
|
+
"vitest": "^2.1.1"
|
|
39
|
+
}
|
|
40
|
+
}
|