1
0

smd-code-calculator.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. const {
  2. formatMagnitudeNumber,
  3. getOption,
  4. normalizeIndex,
  5. selectBestUnit
  6. } = require('./calculator-helpers')
  7. const KIND_OPTIONS = [
  8. { key: 'resistor', label: '电阻' },
  9. { key: 'capacitor', label: '电容' }
  10. ]
  11. const RESISTOR_FORMAT_OPTIONS = [
  12. { key: '3digit', label: '3位' },
  13. { key: '4digit', label: '4位' },
  14. { key: 'eia96', label: 'EIA-96' }
  15. ]
  16. const CAPACITOR_FORMAT_OPTIONS = [
  17. { key: '3digit', label: '3位' },
  18. { key: '4digit', label: '4位' },
  19. { key: 'eia198', label: 'EIA-198' }
  20. ]
  21. const RESISTOR_UNITS = [
  22. { label: 'mΩ', factor: 1e-3 },
  23. { label: 'Ω', factor: 1 },
  24. { label: 'kΩ', factor: 1e3 },
  25. { label: 'MΩ', factor: 1e6 },
  26. { label: 'GΩ', factor: 1e9 }
  27. ]
  28. const CAPACITOR_UNITS = [
  29. { label: 'pF', factor: 1e-12 },
  30. { label: 'nF', factor: 1e-9 },
  31. { label: 'μF', factor: 1e-6 },
  32. { label: 'mF', factor: 1e-3 },
  33. { label: 'F', factor: 1 }
  34. ]
  35. const EIA_96_VALUES = [
  36. 100, 102, 105, 107, 110, 113, 115, 118, 121, 124, 127, 130,
  37. 133, 137, 140, 143, 147, 150, 154, 158, 162, 165, 169, 174,
  38. 178, 182, 187, 191, 196, 200, 205, 210, 215, 221, 226, 232,
  39. 237, 243, 249, 255, 261, 267, 274, 280, 287, 294, 301, 309,
  40. 316, 324, 332, 340, 348, 357, 365, 374, 383, 392, 402, 412,
  41. 422, 432, 442, 453, 464, 475, 487, 499, 511, 523, 536, 549,
  42. 562, 576, 590, 604, 619, 634, 649, 665, 681, 698, 715, 732,
  43. 750, 768, 787, 806, 825, 845, 866, 887, 909, 931, 953, 976
  44. ]
  45. const EIA_96_MULTIPLIERS = {
  46. A: 1,
  47. B: 10,
  48. C: 100,
  49. D: 1000,
  50. E: 10000,
  51. F: 100000,
  52. H: 10,
  53. R: 0.01,
  54. S: 0.1,
  55. X: 0.1,
  56. Y: 0.01,
  57. Z: 0.001
  58. }
  59. const EIA_198_VALUES = {
  60. A: 1.0,
  61. B: 1.1,
  62. C: 1.2,
  63. D: 1.3,
  64. E: 1.5,
  65. F: 1.6,
  66. G: 1.8,
  67. H: 2.0,
  68. J: 2.2,
  69. K: 2.4,
  70. a: 2.5,
  71. L: 2.7,
  72. M: 3.0,
  73. N: 3.3,
  74. b: 3.5,
  75. P: 3.6,
  76. Q: 3.9,
  77. d: 4.0,
  78. R: 4.3,
  79. e: 4.5,
  80. S: 4.7,
  81. f: 5.0,
  82. T: 5.1,
  83. U: 5.6,
  84. m: 6.0,
  85. V: 6.2,
  86. W: 6.8,
  87. n: 7.0,
  88. X: 7.5,
  89. t: 8.0,
  90. Y: 8.2,
  91. y: 9.0,
  92. Z: 9.1
  93. }
  94. const EIA_198_MULTIPLIERS = {
  95. 0: 1,
  96. 1: 10,
  97. 2: 100,
  98. 3: 1000,
  99. 4: 10000,
  100. 5: 100000,
  101. 6: 1000000,
  102. 7: 10000000,
  103. 8: 0.01,
  104. 9: 0.1
  105. }
  106. function formatNumber(value) {
  107. return formatMagnitudeNumber(value, { fallbackText: '' })
  108. }
  109. function formatValue(baseValue, units, fallbackIndex = 0) {
  110. const unit = selectBestUnit(units, baseValue, fallbackIndex).unit
  111. return `${formatNumber(baseValue / unit.factor)} ${unit.label}`
  112. }
  113. function sanitizeCode(text) {
  114. return String(text === undefined || text === null ? '' : text).trim().replace(/\s+/g, '')
  115. }
  116. function parseDecimalCode(code, unitName) {
  117. if (!/^[0-9]*[Rr][0-9]+$/.test(code)) return null
  118. const normalized = code.replace(/[Rr]/, '.')
  119. const value = Number(normalized)
  120. if (!Number.isFinite(value)) throw new Error('编码格式无效')
  121. return {
  122. formula: `${code} = ${formatNumber(value)} ${unitName}`,
  123. value
  124. }
  125. }
  126. function parseDigitCode(code, significantDigits, unitName) {
  127. const decimalParsed = parseDecimalCode(code, unitName)
  128. if (decimalParsed) return decimalParsed
  129. if (!new RegExp(`^\\d{${significantDigits + 1}}$`).test(code)) {
  130. throw new Error(`请输入${significantDigits + 1}位数字编码`)
  131. }
  132. if (/^0+$/.test(code)) {
  133. return {
  134. formula: `${code} = 0 ${unitName}`,
  135. value: 0
  136. }
  137. }
  138. const significant = Number(code.slice(0, significantDigits))
  139. const multiplier = Number(code.slice(significantDigits))
  140. const value = significant * Math.pow(10, multiplier)
  141. return {
  142. formula: `${significant} × 10^${multiplier} ${unitName}`,
  143. value
  144. }
  145. }
  146. function parseEia96(code) {
  147. const normalized = code.toUpperCase()
  148. const match = normalized.match(/^(\d{2})([A-Z])$/)
  149. if (!match) throw new Error('请输入2位数字加1位字母')
  150. const valueIndex = Number(match[1])
  151. const multiplier = EIA_96_MULTIPLIERS[match[2]]
  152. if (valueIndex < 1 || valueIndex > 96 || multiplier === undefined) {
  153. throw new Error('EIA-96编码无效')
  154. }
  155. const baseValue = EIA_96_VALUES[valueIndex - 1]
  156. return {
  157. formula: `${match[1]}=${baseValue},${match[2]}=×${formatNumber(multiplier)}`,
  158. value: baseValue * multiplier
  159. }
  160. }
  161. function parseEia198(code) {
  162. const match = code.match(/^([A-Za-z])(\d)$/) || code.match(/^(\d)([A-Za-z])$/)
  163. if (!match) throw new Error('请输入1位字母加1位数字')
  164. const letter = Number.isNaN(Number(match[1])) ? match[1] : match[2]
  165. const digit = Number.isNaN(Number(match[1])) ? match[2] : match[1]
  166. const baseValue = EIA_198_VALUES[letter]
  167. const multiplier = EIA_198_MULTIPLIERS[digit]
  168. if (baseValue === undefined || multiplier === undefined) {
  169. throw new Error('EIA-198编码无效')
  170. }
  171. return {
  172. formula: `${letter}=${formatNumber(baseValue)},${digit}=×${formatNumber(multiplier)}pF`,
  173. value: baseValue * multiplier * 1e-12
  174. }
  175. }
  176. function calculate(kindKey, formatKey, codeText) {
  177. const code = sanitizeCode(codeText)
  178. if (!code) {
  179. return {
  180. formulaText: '',
  181. resultText: '--',
  182. errorText: ''
  183. }
  184. }
  185. try {
  186. if (kindKey === 'capacitor') {
  187. const parsed = formatKey === 'eia198'
  188. ? parseEia198(code)
  189. : parseDigitCode(code, formatKey === '4digit' ? 3 : 2, 'pF')
  190. const value = formatKey === 'eia198' ? parsed.value : parsed.value * 1e-12
  191. return {
  192. formulaText: parsed.formula,
  193. resultText: formatValue(value, CAPACITOR_UNITS),
  194. errorText: ''
  195. }
  196. }
  197. const parsed = formatKey === 'eia96'
  198. ? parseEia96(code)
  199. : parseDigitCode(code, formatKey === '4digit' ? 3 : 2, 'Ω')
  200. return {
  201. formulaText: parsed.formula,
  202. resultText: formatValue(parsed.value, RESISTOR_UNITS, 1),
  203. errorText: ''
  204. }
  205. } catch (error) {
  206. return {
  207. formulaText: '',
  208. resultText: '--',
  209. errorText: error.message || '编码格式无效'
  210. }
  211. }
  212. }
  213. function buildState(source = {}) {
  214. const kindIndex = normalizeIndex(source.smdKindIndex, KIND_OPTIONS, 0)
  215. const kind = getOption(KIND_OPTIONS, kindIndex)
  216. const formatOptions = kind.key === 'capacitor' ? CAPACITOR_FORMAT_OPTIONS : RESISTOR_FORMAT_OPTIONS
  217. const currentFormatKey = source.smdFormatKey || (source.smdFormatOptions && source.smdFormatOptions[source.smdFormatIndex || 0] && source.smdFormatOptions[source.smdFormatIndex || 0].key)
  218. let formatIndex = formatOptions.findIndex((item) => item.key === currentFormatKey)
  219. if (formatIndex < 0) formatIndex = normalizeIndex(source.smdFormatIndex, formatOptions, 0)
  220. const format = getOption(formatOptions, formatIndex)
  221. const codeText = sanitizeCode(source.smdCodeText)
  222. const result = calculate(kind.key, format.key, codeText)
  223. return {
  224. smdCodeText: codeText,
  225. smdErrorText: result.errorText,
  226. smdFormatIndex: formatIndex,
  227. smdFormatKey: format.key,
  228. smdFormatOptions: formatOptions,
  229. smdFormatText: format.label,
  230. smdFormulaText: result.formulaText,
  231. smdKindIndex: kindIndex,
  232. smdKindKey: kind.key,
  233. smdKindOptions: KIND_OPTIONS,
  234. smdKindText: kind.label,
  235. smdResultText: result.resultText
  236. }
  237. }
  238. function createInitialState() {
  239. return buildState({
  240. smdCodeText: '',
  241. smdFormatIndex: 0,
  242. smdKindIndex: 0
  243. })
  244. }
  245. function updateState(state, changedData = {}) {
  246. return buildState({
  247. ...state,
  248. ...changedData
  249. })
  250. }
  251. module.exports = {
  252. CAPACITOR_FORMAT_OPTIONS,
  253. KIND_OPTIONS,
  254. RESISTOR_FORMAT_OPTIONS,
  255. createInitialState,
  256. updateState
  257. }