| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- const {
- formatMagnitudeNumber,
- formatScaledValue,
- getOption,
- normalizeIndex,
- parsePositiveNumber,
- selectBestUnit
- } = require('./calculator-helpers')
- const TWO_PI = 2 * Math.PI
- const NETWORK_OPTIONS = [
- { key: 'rc', label: 'RC' },
- { key: 'rl', label: 'RL' }
- ]
- const RESPONSE_OPTIONS = [
- { key: 'lowpass', label: '低通' },
- { key: 'highpass', label: '高通' }
- ]
- const RESISTANCE_UNIT_OPTIONS = [
- { label: 'mΩ', factor: 1e-3 },
- { label: 'Ω', factor: 1 },
- { label: 'kΩ', factor: 1e3 },
- { label: 'MΩ', factor: 1e6 },
- { label: 'GΩ', factor: 1e9 }
- ]
- const CAPACITANCE_UNIT_OPTIONS = [
- { label: 'pF', factor: 1e-12 },
- { label: 'nF', factor: 1e-9 },
- { label: 'μF', factor: 1e-6 },
- { label: 'mF', factor: 1e-3 },
- { label: 'F', factor: 1 }
- ]
- const INDUCTANCE_UNIT_OPTIONS = [
- { label: 'pH', factor: 1e-12 },
- { label: 'nH', factor: 1e-9 },
- { label: 'μH', factor: 1e-6 },
- { label: 'mH', factor: 1e-3 },
- { label: 'H', factor: 1 },
- { label: 'kH', factor: 1e3 }
- ]
- const FREQUENCY_UNIT_OPTIONS = [
- { label: 'Hz', factor: 1 },
- { label: 'kHz', factor: 1e3 },
- { label: 'MHz', factor: 1e6 },
- { label: 'GHz', factor: 1e9 },
- { label: 'THz', factor: 1e12 }
- ]
- function getReactiveUnitOptions(networkKey) {
- return networkKey === 'rl' ? INDUCTANCE_UNIT_OPTIONS : CAPACITANCE_UNIT_OPTIONS
- }
- function getDiagramComponents(networkKey, responseKey) {
- if (networkKey === 'rc' && responseKey === 'highpass') {
- return { series: 'c', seriesLabel: 'C', shunt: 'r', shuntLabel: 'R' }
- }
- if (networkKey === 'rl' && responseKey === 'lowpass') {
- return { series: 'l', seriesLabel: 'L', shunt: 'r', shuntLabel: 'R' }
- }
- if (networkKey === 'rl' && responseKey === 'highpass') {
- return { series: 'r', seriesLabel: 'R', shunt: 'l', shuntLabel: 'L' }
- }
- return { series: 'r', seriesLabel: 'R', shunt: 'c', shuntLabel: 'C' }
- }
- function calculateMissingValue(networkKey, values) {
- const hasResistance = Number.isFinite(values.resistance)
- const hasReactive = Number.isFinite(values.reactive)
- const hasFrequency = Number.isFinite(values.frequency)
- const validCount = [hasResistance, hasReactive, hasFrequency].filter(Boolean).length
- if (validCount < 2) {
- return {
- computedKey: '',
- errorText: ''
- }
- }
- if (validCount > 2) {
- return {
- computedKey: '',
- errorText: '保留两项,清空一项用于计算'
- }
- }
- if (networkKey === 'rl') {
- if (!hasResistance) {
- return {
- computedKey: 'resistance',
- value: TWO_PI * values.frequency * values.reactive
- }
- }
- if (!hasReactive) {
- return {
- computedKey: 'reactive',
- value: values.resistance / (TWO_PI * values.frequency)
- }
- }
- return {
- computedKey: 'frequency',
- value: values.resistance / (TWO_PI * values.reactive)
- }
- }
- if (!hasResistance) {
- return {
- computedKey: 'resistance',
- value: 1 / (TWO_PI * values.frequency * values.reactive)
- }
- }
- if (!hasReactive) {
- return {
- computedKey: 'reactive',
- value: 1 / (TWO_PI * values.frequency * values.resistance)
- }
- }
- return {
- computedKey: 'frequency',
- value: 1 / (TWO_PI * values.resistance * values.reactive)
- }
- }
- function buildState(source = {}) {
- const networkIndex = normalizeIndex(source.filterNetworkIndex, NETWORK_OPTIONS, 0)
- const responseIndex = normalizeIndex(source.filterResponseIndex, RESPONSE_OPTIONS, 0)
- const network = getOption(NETWORK_OPTIONS, networkIndex)
- const response = getOption(RESPONSE_OPTIONS, responseIndex)
- const reactiveUnitOptions = getReactiveUnitOptions(network.key)
- const resistanceUnitIndex = normalizeIndex(source.filterResistanceUnitIndex, RESISTANCE_UNIT_OPTIONS, 1)
- const capacitanceUnitIndex = normalizeIndex(source.filterCapacitanceUnitIndex, CAPACITANCE_UNIT_OPTIONS, 1)
- const inductanceUnitIndex = normalizeIndex(source.filterInductanceUnitIndex, INDUCTANCE_UNIT_OPTIONS, 3)
- const frequencyUnitIndex = normalizeIndex(source.filterFrequencyUnitIndex, FREQUENCY_UNIT_OPTIONS, 0)
- const reactiveUnitIndex = network.key === 'rl' ? inductanceUnitIndex : capacitanceUnitIndex
- const resistanceUnit = getOption(RESISTANCE_UNIT_OPTIONS, resistanceUnitIndex)
- const reactiveUnit = getOption(reactiveUnitOptions, reactiveUnitIndex)
- const frequencyUnit = getOption(FREQUENCY_UNIT_OPTIONS, frequencyUnitIndex)
- const resistanceText = String(source.filterResistanceValue || '')
- const reactiveText = String(source.filterReactiveValue || '')
- const frequencyText = String(source.filterFrequencyValue || '')
- const resistanceNumber = parsePositiveNumber(resistanceText)
- const reactiveNumber = parsePositiveNumber(reactiveText)
- const frequencyNumber = parsePositiveNumber(frequencyText)
- const invalidInput = [resistanceNumber, reactiveNumber, frequencyNumber].some((value) => Number.isNaN(value))
- const values = {
- frequency: Number.isFinite(frequencyNumber) ? frequencyNumber * frequencyUnit.factor : null,
- reactive: Number.isFinite(reactiveNumber) ? reactiveNumber * reactiveUnit.factor : null,
- resistance: Number.isFinite(resistanceNumber) ? resistanceNumber * resistanceUnit.factor : null
- }
- const calculated = invalidInput
- ? { computedKey: '', errorText: '输入值需大于 0' }
- : calculateMissingValue(network.key, values)
- const computedValue = Number.isFinite(calculated.value) ? calculated.value : null
- const diagram = getDiagramComponents(network.key, response.key)
- let resistanceDisplayUnit = resistanceUnit
- let resistanceDisplayUnitIndex = resistanceUnitIndex
- let reactiveDisplayUnit = reactiveUnit
- let reactiveDisplayUnitIndex = reactiveUnitIndex
- let frequencyDisplayUnit = frequencyUnit
- let frequencyDisplayUnitIndex = frequencyUnitIndex
- let resistanceDisplayValue = Number.isFinite(resistanceNumber)
- ? formatMagnitudeNumber(resistanceNumber, { fallbackText: '' })
- : resistanceText
- let reactiveDisplayValue = Number.isFinite(reactiveNumber)
- ? formatMagnitudeNumber(reactiveNumber, { fallbackText: '' })
- : reactiveText
- let frequencyDisplayValue = Number.isFinite(frequencyNumber)
- ? formatMagnitudeNumber(frequencyNumber, { fallbackText: '' })
- : frequencyText
- if (computedValue !== null && calculated.computedKey === 'resistance') {
- const selected = selectBestUnit(RESISTANCE_UNIT_OPTIONS, computedValue, resistanceUnitIndex)
- resistanceDisplayUnit = selected.unit
- resistanceDisplayUnitIndex = selected.index
- resistanceDisplayValue = formatScaledValue(computedValue, resistanceDisplayUnit, { fallbackText: '' })
- } else if (computedValue !== null && calculated.computedKey === 'reactive') {
- const selected = selectBestUnit(reactiveUnitOptions, computedValue, reactiveUnitIndex)
- reactiveDisplayUnit = selected.unit
- reactiveDisplayUnitIndex = selected.index
- reactiveDisplayValue = formatScaledValue(computedValue, reactiveDisplayUnit, { fallbackText: '' })
- } else if (computedValue !== null && calculated.computedKey === 'frequency') {
- const selected = selectBestUnit(FREQUENCY_UNIT_OPTIONS, computedValue, frequencyUnitIndex)
- frequencyDisplayUnit = selected.unit
- frequencyDisplayUnitIndex = selected.index
- frequencyDisplayValue = formatScaledValue(computedValue, frequencyDisplayUnit, { fallbackText: '' })
- }
- return {
- filterCapacitanceUnitIndex: network.key === 'rc' ? reactiveDisplayUnitIndex : capacitanceUnitIndex,
- filterComputedKey: calculated.computedKey || '',
- filterErrorText: calculated.errorText || '',
- filterFrequencyDisplayValue: frequencyDisplayValue,
- filterFrequencyUnitIndex: frequencyDisplayUnitIndex,
- filterFrequencyUnitOptions: FREQUENCY_UNIT_OPTIONS,
- filterFrequencyUnitText: frequencyDisplayUnit.label,
- filterFrequencyValue: frequencyText,
- filterFormulaText: network.key === 'rl' ? 'fc = R / (2πL)' : 'fc = 1 / (2πRC)',
- filterInductanceUnitIndex: network.key === 'rl' ? reactiveDisplayUnitIndex : inductanceUnitIndex,
- filterNetworkIndex: networkIndex,
- filterNetworkKey: network.key,
- filterNetworkOptions: NETWORK_OPTIONS,
- filterNetworkText: network.label,
- filterReactiveDisplayValue: reactiveDisplayValue,
- filterReactiveName: network.key === 'rl' ? '电感' : '电容',
- filterReactiveSymbol: network.key === 'rl' ? 'L' : 'C',
- filterReactiveUnitIndex: reactiveDisplayUnitIndex,
- filterReactiveUnitOptions: reactiveUnitOptions,
- filterReactiveUnitText: reactiveDisplayUnit.label,
- filterReactiveValue: reactiveText,
- filterResistanceDisplayValue: resistanceDisplayValue,
- filterResistanceUnitIndex: resistanceDisplayUnitIndex,
- filterResistanceUnitOptions: RESISTANCE_UNIT_OPTIONS,
- filterResistanceUnitText: resistanceDisplayUnit.label,
- filterResistanceValue: resistanceText,
- filterResponseIndex: responseIndex,
- filterResponseKey: response.key,
- filterResponseOptions: RESPONSE_OPTIONS,
- filterResponseText: response.label,
- filterSeriesComponentKey: diagram.series,
- filterSeriesComponentLabel: diagram.seriesLabel,
- filterShuntComponentKey: diagram.shunt,
- filterShuntComponentLabel: diagram.shuntLabel
- }
- }
- function createInitialState() {
- return buildState({
- filterCapacitanceUnitIndex: 1,
- filterFrequencyUnitIndex: 0,
- filterInductanceUnitIndex: 3,
- filterNetworkIndex: 0,
- filterReactiveValue: '',
- filterResistanceUnitIndex: 1,
- filterResistanceValue: '',
- filterResponseIndex: 0
- })
- }
- function updateState(state, changedData = {}) {
- return buildState({
- ...state,
- ...changedData
- })
- }
- function normalizeValue(state, fieldKey, fieldValue) {
- const source = buildState(state)
- const config = {
- frequency: {
- options: FREQUENCY_UNIT_OPTIONS,
- unitIndex: source.filterFrequencyUnitIndex,
- unitIndexKey: 'filterFrequencyUnitIndex',
- valueKey: 'filterFrequencyValue'
- },
- reactive: {
- options: source.filterReactiveUnitOptions,
- unitIndex: source.filterReactiveUnitIndex,
- unitIndexKey: source.filterNetworkKey === 'rl'
- ? 'filterInductanceUnitIndex'
- : 'filterCapacitanceUnitIndex',
- valueKey: 'filterReactiveValue'
- },
- resistance: {
- options: RESISTANCE_UNIT_OPTIONS,
- unitIndex: source.filterResistanceUnitIndex,
- unitIndexKey: 'filterResistanceUnitIndex',
- valueKey: 'filterResistanceValue'
- }
- }[fieldKey]
- if (!config) return source
- const text = fieldValue === undefined ? source[config.valueKey] : fieldValue
- const numberValue = parsePositiveNumber(text)
- if (!Number.isFinite(numberValue)) {
- return updateState(source, {
- [config.valueKey]: text
- })
- }
- const currentUnit = getOption(config.options, config.unitIndex)
- const baseValue = numberValue * currentUnit.factor
- const selected = selectBestUnit(config.options, baseValue, config.unitIndex)
- return updateState(source, {
- [config.unitIndexKey]: selected.index,
- [config.valueKey]: formatScaledValue(baseValue, selected.unit, { fallbackText: '' })
- })
- }
- module.exports = {
- CAPACITANCE_UNIT_OPTIONS,
- FREQUENCY_UNIT_OPTIONS,
- INDUCTANCE_UNIT_OPTIONS,
- NETWORK_OPTIONS,
- RESISTANCE_UNIT_OPTIONS,
- RESPONSE_OPTIONS,
- createInitialState,
- normalizeValue,
- updateState
- }
|