Skip to content

Commit 463020e

Browse files
committed
refactor and more comments
1 parent 143515f commit 463020e

File tree

8 files changed

+126
-98
lines changed

8 files changed

+126
-98
lines changed

src/calulateSolutionMassesByEC.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { getECbyRho } from "./getECbyRho";
2+
import { getDencityByRho } from "./getDencityByRho";
3+
import { getRhoByEC } from "./getRhoByEC";
4+
import { bruteForceMonotonic } from "./bruteForceMonotonic";
5+
import { getRhoByDencitySaltAndWaterGrams } from "./getRhoByDencitySaltAndWaterGrams";
6+
7+
export class SolutionCalculationResult {
8+
public rho: number;
9+
public targetEC: number;
10+
public realEC: number;
11+
public ECError: number;
12+
public ECAccuracy: number;
13+
public saltGrams: number;
14+
public waterGrams: number;
15+
public minEC: number;
16+
public maxEC: number;
17+
public score: number;
18+
public volume: number;
19+
}
20+
21+
export function calulateSolutionMassesByEC(EC: number, minWaterGrams: number, maxWatergrams: number, waterStep: number, saltStep: number): SolutionCalculationResult {
22+
let rho = getRhoByEC(EC);
23+
let dencity = getDencityByRho(rho);
24+
let bestCandidate: SolutionCalculationResult = {
25+
rho: 0,
26+
targetEC: EC,
27+
realEC: 0,
28+
ECError: Number.POSITIVE_INFINITY,
29+
ECAccuracy: Number.POSITIVE_INFINITY,
30+
saltGrams: 0,
31+
waterGrams: 0,
32+
minEC: 0,
33+
maxEC: 0,
34+
score: Number.POSITIVE_INFINITY,
35+
volume: 0
36+
};
37+
for (let waterGrams = minWaterGrams; waterGrams <= maxWatergrams; waterGrams += waterStep) {
38+
waterGrams = Math.round(waterGrams / waterStep) * waterStep;
39+
let saltGrams = bruteForceMonotonic((saltGrams: number) => {
40+
let realRho = getRhoByDencitySaltAndWaterGrams(dencity, saltGrams, waterGrams);
41+
return realRho;
42+
}, rho, saltStep, 1000, 0.000001);
43+
let saltGramsRounded = Math.round(saltGrams / saltStep) * saltStep;
44+
let saltFrom = saltGramsRounded - 2 * saltStep;
45+
let saltTo = saltGramsRounded + 2 * saltStep;
46+
for (let saltGrams = saltFrom; saltGrams <= saltTo; saltGrams += saltStep) {
47+
let realEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, saltGrams, waterGrams));
48+
let minSalt = saltGrams - saltStep / 2;
49+
let maxSalt = saltGrams + saltStep / 2;
50+
let minWater = waterGrams - waterStep / 2;
51+
let maxWater = waterGrams + waterStep / 2;
52+
let minEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, minSalt, maxWater));
53+
let maxEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, maxSalt, minWater));
54+
let ECError = Math.abs(EC - realEC);
55+
let ECAccuracy = maxEC - minEC;
56+
let score = ECError + ECAccuracy / 2;
57+
if (ECAccuracy < 0) {
58+
debugger;
59+
}
60+
if (score < bestCandidate.score) {
61+
bestCandidate = {
62+
rho,
63+
targetEC: EC,
64+
realEC,
65+
ECError,
66+
ECAccuracy,
67+
saltGrams,
68+
waterGrams,
69+
minEC,
70+
maxEC,
71+
score,
72+
volume: ((saltGrams + waterGrams) / dencity) * 1000
73+
};
74+
}
75+
}
76+
// console.log('waterGrams:', waterGrams, 'saltGrams:', saltGrams, 'rhoError:', rhoError);
77+
}
78+
return bestCandidate;
79+
}

src/getDencityByRho.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ let rhoToDencity: Array<[number, number]> = [
2020
[311.2, 1197]
2121
]
2222

23-
// плотность расствора, грамм на литр
23+
/**
24+
*
25+
* @param rho
26+
* @returns грамм раствора на литр раствора
27+
*/
2428
export function getDencityByRho(rho: number): number {
2529
let less: [number, number];
2630
let more: [number, number];

src/getECbyRho.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
2-
/*
3-
rho is grams of salt per 1 liter of solution! Not per 1 liter of water!
1+
/**
2+
*
3+
* @param rho грам соли на литр раствора
4+
* @returns EC, мСм/см, миллисименс на сантиметр
45
*/
56
export function getECbyRho(rho: number): number {
67
let EW = 58.44;

src/getRhoByDencitySaltAndWaterGrams.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
*
3+
* @param dencity грамм раствора на литр раствора
4+
* @param saltGrams грамм соли
5+
* @param waterGrams грамм воды
6+
* @returns Rho, грам соли на литр раствора
7+
*/
18
export function getRhoByDencitySaltAndWaterGrams(dencity: number, saltGrams: number, waterGrams: number): number {
29
let solutionGrams = saltGrams + waterGrams;
310
let solutionMl = solutionGrams / dencity * 1000;

src/getRhoByEC.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { getECbyRho } from "./getECbyRho";
22
import { bruteForceMonotonic } from "./bruteForceMonotonic";
33

4+
/**
5+
*
6+
* @param targetEC мСм/см, миллисименс на сантиметр
7+
* @returns Rho, грам соли на литр раствора
8+
*/
49
export function getRhoByEC(targetEC: number): number {
510
let rho = bruteForceMonotonic(getECbyRho, targetEC, 0, 350, 0.000001);
611
return rho;

src/index.ts

Lines changed: 4 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import fs from "fs";
2-
import { getECbyRho } from "./getECbyRho";
3-
import { getDencityByRho } from "./getDencityByRho";
42
import { Cfg } from "./Cfg";
5-
import { getRhoByEC } from "./getRhoByEC";
6-
import { bruteForceMonotonic, setEnsureMonotonicSteps } from "./bruteForceMonotonic";
7-
import { getRhoByDencitySaltAndWaterGrams } from "./getRhoByDencitySaltAndWaterGrams";
3+
import { setEnsureMonotonicSteps } from "./bruteForceMonotonic";
84
import { MarkdownExporter } from "./MarkdownExporter";
5+
import { SolutionCalculationResult, calulateSolutionMassesByEC } from "./calulateSolutionMassesByEC";
6+
97
let cfg: Cfg;
108
let saltSymbolsAfterPoint: number;
119
let waterSymbolsAfterPoint: number;
@@ -28,19 +26,17 @@ async function main() {
2826
fs.writeFileSync('tmp/NaClSolutions.html', html);
2927
let pdf = await MarkdownExporter.export(markdown, false);
3028
fs.writeFileSync('NaClSolutions.pdf', pdf);
31-
3229
}
3330

3431
function getTable(ECs: Array<number>, minWaterGrams: number, maxWatergrams: number, printingAccuracyShift: number = 0) {
35-
3632
let str = '';
3733
let columns = ['EC', 'H2O(г)', 'NaCl(г)', 'Рассчетный EC', 'Диапазон EC', 'Диапазон EC%', '$\\rho$(г/л)', 'Отклонение EC', 'Объём раствора(мл)'];
3834
str += '| ' + columns.join(' | ') + '|\n';
3935
let dashes = columns.map(() => '---');
4036
str += '| ' + dashes.join(' | ') + '|\n';
4137
for (let EC of ECs) {
4238
let targetNumDigits = getSymbolsAfterPoint(EC);
43-
let res = calulateSolutionMassesByEC(EC, minWaterGrams, maxWatergrams, cfg.waterScalesDivisionValue, cfg.saltScalesDivisionValue);
39+
let res: SolutionCalculationResult = calulateSolutionMassesByEC(EC, minWaterGrams, maxWatergrams, cfg.waterScalesDivisionValue, cfg.saltScalesDivisionValue);
4440
let ecAccuracyPercentage = (res.ECAccuracy / EC * 100).toFixed(printingAccuracyShift + 2) + '%';
4541
str += '| ' + [
4642
EC,
@@ -57,82 +53,6 @@ function getTable(ECs: Array<number>, minWaterGrams: number, maxWatergrams: numb
5753
return str;
5854
}
5955

60-
class SolutionCalculationResult {
61-
public rho: number;
62-
public targetEC: number;
63-
public realEC: number;
64-
public ECError: number;
65-
public ECAccuracy: number;
66-
public saltGrams: number;
67-
public waterGrams: number;
68-
public minEC: number;
69-
public maxEC: number;
70-
public score: number;
71-
public volume: number;
72-
}
73-
74-
function calulateSolutionMassesByEC(EC: number, minWaterGrams: number, maxWatergrams: number, waterStep: number, saltStep: number): SolutionCalculationResult {
75-
let rho = getRhoByEC(EC);
76-
let dencity = getDencityByRho(rho);
77-
let bestCandidate: SolutionCalculationResult = {
78-
rho: 0,
79-
targetEC: EC,
80-
realEC: 0,
81-
ECError: Number.POSITIVE_INFINITY,
82-
ECAccuracy: Number.POSITIVE_INFINITY,
83-
saltGrams: 0,
84-
waterGrams: 0,
85-
minEC: 0,
86-
maxEC: 0,
87-
score: Number.POSITIVE_INFINITY,
88-
volume: 0
89-
}
90-
for (let waterGrams = minWaterGrams; waterGrams <= maxWatergrams; waterGrams += waterStep) {
91-
waterGrams = Math.round(waterGrams / waterStep) * waterStep;
92-
let saltGrams = bruteForceMonotonic((saltGrams: number) => {
93-
let realRho = getRhoByDencitySaltAndWaterGrams(dencity, saltGrams, waterGrams);
94-
return realRho;
95-
}, rho, saltStep, 1000, 1e-6);
96-
let saltGramsRounded = Math.round(saltGrams / saltStep) * saltStep;
97-
let saltFrom = saltGramsRounded - 2 * saltStep;
98-
let saltTo = saltGramsRounded + 2 * saltStep;
99-
for (let saltGrams = saltFrom; saltGrams <= saltTo; saltGrams += saltStep) {
100-
let realEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, saltGrams, waterGrams));
101-
let minSalt = saltGrams - saltStep / 2;
102-
let maxSalt = saltGrams + saltStep / 2;
103-
let minWater = waterGrams - waterStep / 2;
104-
let maxWater = waterGrams + waterStep / 2
105-
let minEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, minSalt, maxWater));
106-
let maxEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, maxSalt, minWater));
107-
let ECError = Math.abs(EC - realEC);
108-
let ECAccuracy = maxEC - minEC;
109-
let score = ECError + ECAccuracy / 2;
110-
if (ECAccuracy < 0) {
111-
debugger;
112-
}
113-
if (score < bestCandidate.score) {
114-
bestCandidate = {
115-
rho,
116-
targetEC: EC,
117-
realEC,
118-
ECError,
119-
ECAccuracy,
120-
saltGrams,
121-
waterGrams,
122-
minEC,
123-
maxEC,
124-
score,
125-
volume: ((saltGrams+waterGrams)/dencity)*1000
126-
}
127-
}
128-
}
129-
// console.log('waterGrams:', waterGrams, 'saltGrams:', saltGrams, 'rhoError:', rhoError);
130-
131-
}
132-
return bestCandidate;
133-
}
134-
135-
13656
function formatDate(date: Date) {
13757
var d = new Date(date),
13858
month = '' + (d.getMonth() + 1),
@@ -164,7 +84,6 @@ function getArray(from: number, to: number) {
16484
return res;
16585
}
16686

167-
16887
main();
16988

17089

src/pureWaterDencity.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
// 20°C
2-
// ГСССД 2-77
3-
// https://files.stroyinf.ru/Data2/1/4293783/4293783232.htm
1+
/**
2+
* грамм на литр
3+
* 20°C
4+
* ГСССД 2-77
5+
* https://files.stroyinf.ru/Data2/1/4293783/4293783232.htm
6+
*/
47
export const pureWaterDencity = 998.204;

tests/tests.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { getDencityByRho } from "../src/getDencityByRho";
22
import { getECbyRho } from "../src/getECbyRho";
33
import { getRhoByEC } from "../src/getRhoByEC";
44
import { getRhoByDencitySaltAndWaterGrams } from "../src/getRhoByDencitySaltAndWaterGrams";
5+
import { bruteForceMonotonic } from "../src/bruteForceMonotonic";
6+
import { pureWaterDencity } from "../src/pureWaterDencity";
57

68
test("getDencityForRho", () => {
79
expect(getDencityByRho(0.4904),).toBeCloseTo(998.5356178, 6);
@@ -21,11 +23,19 @@ test("getECForSolution", () => {
2123
expect(getRhoByEC(111.8)).toBeCloseTo(51.80772436, 6);
2224
});
2325

24-
test("Accuracy", ()=> {
25-
let rho = getRhoByEC(1.413);
26+
test("PharmacySolution", () => {
27+
let originalSaltGrams = 9;
28+
let liters = 1;
29+
let rho = originalSaltGrams; // 0.9% 1 мл препарата содержит: натрия хлорид - 9 мг.
2630
let dencity = getDencityByRho(rho);
27-
let lowEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, 0.495, 713.5));
28-
let highEC = getECbyRho(getRhoByDencitySaltAndWaterGrams(dencity, 0.505, 712.5));
29-
console.log(lowEC, highEC);
30-
31+
let solutionMass = dencity * liters;
32+
let waterGrams = solutionMass - originalSaltGrams;
33+
let saltGrams = bruteForceMonotonic((saltGrams: number) => {
34+
let realRho = getRhoByDencitySaltAndWaterGrams(dencity, saltGrams, waterGrams);
35+
return realRho;
36+
}, rho, 0.0001, 1000, 1e-7);
37+
let EC = getECbyRho(rho);
38+
expect(saltGrams).toBeCloseTo(rho, 6);
39+
expect(EC).toBeCloseTo(16.3500511, 6);
3140
});
41+

0 commit comments

Comments
 (0)