oltc-selector 1.1.0 → 1.2.1

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/bin/oltc.js +97 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  填工况,给出 2025 目录里**最低满足**的型号。网页和 `oltc` CLI 共用同一份 `selectOltc` 引擎。
4
4
 
5
- **CLI(无报价):** `npm i -g oltc-selector`,命令是 `oltc`。Agent 技能包:`skills/oltc-selector/`(站点 `/agents/` 可下载 zip)。
5
+ **CLI(无报价):** `npm i -g oltc-selector`,命令是 `oltc`。Agent 技能包:`skills/huaming-oltc-selector/`(站点 `/agents/` 可下载 zip)。
6
6
  **网页:** [oltc-selector.vercel.app](https://oltc-selector.vercel.app/) · [GitHub Pages](https://erict16.github.io/oltc-selector/)
7
7
 
8
8
  私人辅助,不是厂家官网。型号是起点,出 OS 前要工程确认。
package/bin/oltc.js CHANGED
@@ -1543,11 +1543,12 @@ function selectOltc(input) {
1543
1543
  const reasonsZh = [];
1544
1544
  const warningsEn = [];
1545
1545
  const warningsZh = [];
1546
+ const dutyA = input.throughCurrentA >= 100 ? String(Math.round(input.throughCurrentA)) : String(Math.round(input.throughCurrentA * 10) / 10);
1546
1547
  reasonsEn.push(
1547
- `Minimum-adequate path: ${s.nameEn}, Ium ${current} A \u2265 ${input.throughCurrentA} A, Um ${att.um} kV.`
1548
+ `Minimum-adequate path: ${s.nameEn}, Ium ${current} A \u2265 ${dutyA} A, Um ${att.um} kV.`
1548
1549
  );
1549
1550
  reasonsZh.push(
1550
- `\u6700\u4F4E\u6EE1\u8DB3\u8DEF\u5F84\uFF1A${s.nameZh}\uFF0CIum ${current} A \u2265 \u9700\u6C42 ${input.throughCurrentA} A\uFF0CUm ${att.um} kV\u3002`
1551
+ `\u6700\u4F4E\u6EE1\u8DB3\u8DEF\u5F84\uFF1A${s.nameZh}\uFF0CIum ${current} A \u2265 \u9700\u6C42 ${dutyA} A\uFF0CUm ${att.um} kV\u3002`
1551
1552
  );
1552
1553
  if (s.structure === "compound" && !octc) {
1553
1554
  reasonsEn.push(
@@ -1757,7 +1758,8 @@ function parseCliArgs(argv) {
1757
1758
  phases: "III",
1758
1759
  json: false,
1759
1760
  help: false,
1760
- pm: 8
1761
+ pm: 8,
1762
+ given: /* @__PURE__ */ new Set()
1761
1763
  };
1762
1764
  const take = (i, flag) => {
1763
1765
  const v = argv[i + 1];
@@ -1777,62 +1779,73 @@ function parseCliArgs(argv) {
1777
1779
  continue;
1778
1780
  }
1779
1781
  if (a === "--octc") {
1782
+ out.given.add("octc");
1780
1783
  out.octc = true;
1781
1784
  continue;
1782
1785
  }
1783
1786
  if (a === "--oil") {
1787
+ out.given.add("medium");
1784
1788
  out.oil = true;
1785
1789
  out.vacuum = false;
1786
1790
  continue;
1787
1791
  }
1788
1792
  if (a === "--vacuum") {
1793
+ out.given.add("medium");
1789
1794
  out.vacuum = true;
1790
1795
  out.oil = false;
1791
1796
  continue;
1792
1797
  }
1793
1798
  if (a === "--iu" || a === "--imax") {
1799
+ out.given.add("iu");
1794
1800
  const [v, n] = take(i, a);
1795
1801
  out.iu = num(v, a);
1796
1802
  i = n;
1797
1803
  continue;
1798
1804
  }
1799
1805
  if (a === "--mva") {
1806
+ out.given.add("mva");
1800
1807
  const [v, n] = take(i, a);
1801
1808
  out.mva = num(v, a);
1802
1809
  i = n;
1803
1810
  continue;
1804
1811
  }
1805
1812
  if (a === "--kv") {
1813
+ out.given.add("kv");
1806
1814
  const [v, n] = take(i, a);
1807
1815
  out.kv = num(v, a);
1808
1816
  i = n;
1809
1817
  continue;
1810
1818
  }
1811
1819
  if (a === "--um") {
1820
+ out.given.add("um");
1812
1821
  const [v, n] = take(i, a);
1813
1822
  out.um = num(v, a);
1814
1823
  i = n;
1815
1824
  continue;
1816
1825
  }
1817
1826
  if (a === "--ust") {
1827
+ out.given.add("ust");
1818
1828
  const [v, n] = take(i, a);
1819
1829
  out.ust = num(v, a);
1820
1830
  i = n;
1821
1831
  continue;
1822
1832
  }
1823
1833
  if (a === "--step-pct") {
1834
+ out.given.add("stepPct");
1824
1835
  const [v, n] = take(i, a);
1825
1836
  out.stepPct = num(v, a);
1826
1837
  i = n;
1827
1838
  continue;
1828
1839
  }
1829
1840
  if (a === "--k") {
1841
+ out.given.add("k");
1830
1842
  const [v, n] = take(i, a);
1831
1843
  out.k = num(v, a);
1832
1844
  i = n;
1833
1845
  continue;
1834
1846
  }
1835
1847
  if (a === "--conn" || a === "--connection") {
1848
+ out.given.add("conn");
1836
1849
  const [v, n] = take(i, a);
1837
1850
  const c = v.toUpperCase();
1838
1851
  if (c !== "Y" && c !== "D") throw new CliError(`--conn must be Y or D`);
@@ -1841,6 +1854,7 @@ function parseCliArgs(argv) {
1841
1854
  continue;
1842
1855
  }
1843
1856
  if (a === "--reg") {
1857
+ out.given.add("reg");
1844
1858
  const [v, n] = take(i, a);
1845
1859
  const r = v.toUpperCase();
1846
1860
  if (r === "W" || r === "REVERSING") out.reg = "reversing";
@@ -1852,18 +1866,21 @@ function parseCliArgs(argv) {
1852
1866
  continue;
1853
1867
  }
1854
1868
  if (a === "--pm") {
1869
+ out.given.add("pm");
1855
1870
  const [v, n] = take(i, a);
1856
1871
  out.pm = num(v, a);
1857
1872
  i = n;
1858
1873
  continue;
1859
1874
  }
1860
1875
  if (a === "--positions" || a === "--pos") {
1876
+ out.given.add("positions");
1861
1877
  const [v, n] = take(i, a);
1862
1878
  out.positions = num(v, a);
1863
1879
  i = n;
1864
1880
  continue;
1865
1881
  }
1866
1882
  if (a === "--structure") {
1883
+ out.given.add("structure");
1867
1884
  const [v, n] = take(i, a);
1868
1885
  const s = v.toLowerCase();
1869
1886
  const map = {
@@ -1887,6 +1904,7 @@ function parseCliArgs(argv) {
1887
1904
  continue;
1888
1905
  }
1889
1906
  if (a === "--series") {
1907
+ out.given.add("series");
1890
1908
  const [v, n] = take(i, a);
1891
1909
  const r = v.toUpperCase();
1892
1910
  const ok = ["II", "IV", "V", "VI", "VII", "VIII", "AUTO"];
@@ -1898,6 +1916,7 @@ function parseCliArgs(argv) {
1898
1916
  continue;
1899
1917
  }
1900
1918
  if (a === "--mount") {
1919
+ out.given.add("mount");
1901
1920
  const [v, n] = take(i, a);
1902
1921
  const m = v.toLowerCase().replace("_", "-");
1903
1922
  if (m === "in-tank" || m === "intank") out.mount = "in_tank";
@@ -1908,12 +1927,14 @@ function parseCliArgs(argv) {
1908
1927
  continue;
1909
1928
  }
1910
1929
  if (a === "--contact") {
1930
+ out.given.add("contact");
1911
1931
  const [v, n] = take(i, a);
1912
1932
  out.contact = v;
1913
1933
  i = n;
1914
1934
  continue;
1915
1935
  }
1916
1936
  if (a === "--phases") {
1937
+ out.given.add("phases");
1917
1938
  const [v, n] = take(i, a);
1918
1939
  const p = v.toUpperCase();
1919
1940
  if (p !== "I" && p !== "II" && p !== "III") {
@@ -1924,6 +1945,7 @@ function parseCliArgs(argv) {
1924
1945
  continue;
1925
1946
  }
1926
1947
  if (a === "--duty") {
1948
+ out.given.add("octc");
1927
1949
  const [v, n] = take(i, a);
1928
1950
  const d = v.toLowerCase();
1929
1951
  if (d === "octc" || d === "off" || d === "detc") out.octc = true;
@@ -1950,7 +1972,7 @@ Flags:
1950
1972
  --um kV Equipment Um (OLTC). With --mva/--kv, derived if omitted.
1951
1973
  --ust V Step voltage. With --mva/--kv/--step-pct, derived if omitted.
1952
1974
  --step-pct % Step as percent (1.25 means 1.25%). Capacity path only.
1953
- --k n Safety factor on capacity path only (default 1.2).
1975
+ --k n Safety factor on capacity path only (default 1.0, same as the web app).
1954
1976
  --conn Y|D Switch connection (star / delta). Default Y.
1955
1977
  --reg W|G|0 Reversing / coarse-fine / linear. Default W.
1956
1978
  --pm N \xB1 steps. Default 8.
@@ -1986,7 +2008,7 @@ function cliToSelectInput(args) {
1986
2008
  const pct = args.stepPct != null && args.stepPct > 0 ? args.stepPct / 100 : 0.0125;
1987
2009
  const minus = args.pm != null && args.pm > 0 ? args.pm : 8;
1988
2010
  const iMax = maxThroughCurrent(rated, minus, pct);
1989
- const k = args.k != null && args.k > 0 ? args.k : 1.2;
2011
+ const k = args.k != null && args.k > 0 ? args.k : 1;
1990
2012
  iu = iMax * k;
1991
2013
  if (um == null || !(um > 0)) {
1992
2014
  um = oltcUmFromRatedKv(args.kv, args.conn);
@@ -2021,7 +2043,7 @@ function cliToSelectInput(args) {
2021
2043
  input.octcSeries = args.series ?? "auto";
2022
2044
  if (args.contact) input.octcContact = args.contact;
2023
2045
  if (args.positions != null) input.positions = args.positions;
2024
- else if (args.pm != null && args.pm > 0) {
2046
+ else if (args.given.has("pm") && args.pm != null && args.pm > 0) {
2025
2047
  input.positions = Math.round(2 * args.pm + 1);
2026
2048
  }
2027
2049
  } else if (args.reg === "linear") {
@@ -2035,7 +2057,65 @@ function cliToSelectInput(args) {
2035
2057
  }
2036
2058
  return input;
2037
2059
  }
2038
- function formatCliText(input) {
2060
+ var MOUNT_ZH = {
2061
+ in_tank: "\u7BB1\u5185",
2062
+ on_tank: "\u7BB1\u9876",
2063
+ dry_type: "\u5E72\u5F0F",
2064
+ // CLI 不会接收这两种,列上只为 Record 完整性
2065
+ external_compartment: "\u5916\u7F6E\u9694\u5BA4",
2066
+ reactor: "\u7535\u6297\u5668"
2067
+ };
2068
+ function assumptionsFromArgs(args) {
2069
+ const mark = (key) => args.given.has(key) ? "" : "\uFF08\u9ED8\u8BA4\uFF09";
2070
+ const items = [
2071
+ `conn=${args.conn} ${args.conn === "Y" ? "\u661F\u70B9" : "\u7EBF\u7AEF"}${mark("conn")}`
2072
+ ];
2073
+ if (args.mva != null) {
2074
+ items.push(args.given.has("k") ? `k=${args.k}` : "k=1.0\uFF08\u9ED8\u8BA4\uFF09");
2075
+ items.push(
2076
+ args.given.has("stepPct") ? `step=${args.stepPct}%` : "step=1.25%\uFF08\u9ED8\u8BA4\uFF09"
2077
+ );
2078
+ }
2079
+ const phases = `\u76F8\u6570=${args.phases}${mark("phases")}`;
2080
+ if (args.octc) {
2081
+ if (args.positions != null) {
2082
+ items.push(`${args.positions} \u6863`);
2083
+ } else if (args.given.has("pm") && args.pm != null && args.pm > 0) {
2084
+ items.push(`${Math.round(2 * args.pm + 1)} \u6863\uFF08\u7531 \xB1${args.pm} \u63A8\uFF09`);
2085
+ } else if (!args.given.has("contact")) {
2086
+ items.push("\u6863\u6570\u672A\u6307\u5B9A");
2087
+ }
2088
+ const s = args.series ?? "auto";
2089
+ items.push(
2090
+ s === "auto" ? `\u63A5\u7EBF=\u81EA\u52A8\uFF08${args.conn === "Y" ? "IV" : "II"}\uFF09${mark("series")}` : `\u63A5\u7EBF=${s}${mark("series")}`
2091
+ );
2092
+ items.push(`${MOUNT_ZH[args.mount]}${mark("mount")}`);
2093
+ items.push(phases);
2094
+ return items;
2095
+ }
2096
+ items.push(
2097
+ `reg=${args.reg === "reversing" ? "W \u6B63\u53CD\u8C03" : args.reg === "coarse_fine" ? "G \u7C97\u7EC6\u8C03" : "0 \u7EBF\u6027\u8C03"}${mark("reg")}`
2098
+ );
2099
+ if (args.reg === "linear") {
2100
+ items.push(
2101
+ args.positions != null ? `${args.positions} \u6863${mark("positions")}` : "\u6863\u6570\u672A\u6307\u5B9A"
2102
+ );
2103
+ } else {
2104
+ items.push(`\xB1${args.pm ?? 8} \u6863${mark("pm")}`);
2105
+ }
2106
+ items.push(`${args.oil || !args.vacuum ? "\u6CB9\u6D78" : "\u771F\u7A7A"}${mark("medium")}`);
2107
+ items.push(`${MOUNT_ZH[args.mount]}${mark("mount")}`);
2108
+ items.push(phases);
2109
+ return items;
2110
+ }
2111
+ function assumptionsLine(args) {
2112
+ const items = assumptionsFromArgs(args);
2113
+ if (items.every((i) => !i.includes("\uFF08\u9ED8\u8BA4\uFF09") && !i.includes("\u672A\u6307\u5B9A"))) {
2114
+ return null;
2115
+ }
2116
+ return `\u5047\u5B9A\uFF1A${items.join(" \xB7 ")}`;
2117
+ }
2118
+ function formatCliText(input, args) {
2039
2119
  const out = selectOltc(input);
2040
2120
  if (!out.ok || !out.results.length) {
2041
2121
  const err = [...out.errorsZh, ...out.errorsEn].join("\n") || "No type found.";
@@ -2055,9 +2135,16 @@ function formatCliText(input) {
2055
2135
  lines.push("\u5176\u4ED6");
2056
2136
  for (const a of alts) lines.push(a.model);
2057
2137
  }
2138
+ if (args) {
2139
+ const assumed = assumptionsLine(args);
2140
+ if (assumed) {
2141
+ lines.push("");
2142
+ lines.push(assumed);
2143
+ }
2144
+ }
2058
2145
  return lines.join("\n") + "\n";
2059
2146
  }
2060
- function formatCliJson(input) {
2147
+ function formatCliJson(input, args) {
2061
2148
  const out = selectOltc(input);
2062
2149
  const primary = out.results[0] ?? null;
2063
2150
  const alts = pickOtherOptions(out.results, 3).map((r) => r.model);
@@ -2066,6 +2153,7 @@ function formatCliJson(input) {
2066
2153
  model: primary?.model ?? null,
2067
2154
  why: primary?.reasonsZh[0] ?? primary?.reasonsEn[0] ?? null,
2068
2155
  alts,
2156
+ assumptions: args ? assumptionsFromArgs(args) : [],
2069
2157
  errors: out.errorsZh.length ? out.errorsZh : out.errorsEn
2070
2158
  };
2071
2159
  return JSON.stringify(payload, null, 2) + "\n";
@@ -2081,7 +2169,7 @@ function runCli(argv, io = {
2081
2169
  return 0;
2082
2170
  }
2083
2171
  const input = cliToSelectInput(args);
2084
- io.stdout(args.json ? formatCliJson(input) : formatCliText(input));
2172
+ io.stdout(args.json ? formatCliJson(input, args) : formatCliText(input, args));
2085
2173
  return 0;
2086
2174
  } catch (err) {
2087
2175
  const msg = err instanceof Error ? err.message : String(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oltc-selector",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Huaming OLTC/OCTC type selection CLI. No prices. Same engine as the web app.",
5
5
  "bin": {
6
6
  "oltc": "bin/oltc.js"