Add 'Clear All' button, table for results, custom text component
This commit is contained in:
parent
49d649a3b3
commit
db3fb7ec0f
|
@ -1,7 +1,7 @@
|
||||||
export const UPDATEVALUE = 'UPDATEVALUE';
|
export const UPDATEVALUE = 'UPDATEVALUE';
|
||||||
export const UPDATEMULT = 'UPDATEMULT';
|
export const UPDATEMULT = 'UPDATEMULT';
|
||||||
|
export const CLEARALL = 'CLEARALL';
|
||||||
export const MENUOPEN = 'MENUOPEN';
|
export const MENUOPEN = 'MENUOPEN';
|
||||||
export const MENUCLOSE = 'MENUCLOSE';
|
export const MENUCLOSE = 'MENUCLOSE';
|
||||||
export const MAIN = 'MAIN';
|
export const MAIN = 'MAIN';
|
||||||
export const HELP = 'HELP';
|
export const HELP = 'HELP';
|
||||||
export const SETREF = 'SETREF';
|
|
||||||
|
|
|
@ -17,3 +17,9 @@ export function updatemult(form, index, mult) {
|
||||||
mult,
|
mult,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearall() {
|
||||||
|
return {
|
||||||
|
type: types.CLEARALL,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +1,30 @@
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {ScrollView, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
|
import {Alert, ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native';
|
||||||
|
|
||||||
import Resistor from './resistor';
|
import Resistor from './resistor';
|
||||||
import Section from './section';
|
import Section from './section';
|
||||||
|
import ClearAll from './clearall';
|
||||||
|
import MyText from './mytext'
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
function getUnit(n) {
|
||||||
button: {
|
if (n >= 1000000) {
|
||||||
width: 100,
|
return {unit: ' MΩ', mult: 1000000};
|
||||||
height: 30,
|
} else if (n >= 1000) {
|
||||||
padding: 10,
|
return {unit: ' kΩ', mult: 1000};
|
||||||
backgroundColor: 'lightgray',
|
} else if (n >= 1) {
|
||||||
alignItems: 'center',
|
return {unit: ' Ω', mult: 1};
|
||||||
justifyContent: 'center',
|
} else {
|
||||||
margin: 3
|
return {unit: ' mΩ', mult: 0.001};
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
table: {
|
||||||
|
borderBottomColor: 'lightgrey',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
padding: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default class Calc extends Component {
|
export default class Calc extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -24,42 +34,165 @@ export default class Calc extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {state} = this.props;
|
const {state} = this.props;
|
||||||
|
|
||||||
const allValid = state.have.every((x) => x.valid);
|
const targetValid = state.target.valid;
|
||||||
const nonEmpty = state.have.some((x) => x.value);
|
const targetNonEmpty = state.target.value ? true : false;
|
||||||
|
|
||||||
|
const haveAllValid = state.have.every((x) => x.valid);
|
||||||
|
const haveNonEmpty = state.have.some((x) => x.value);
|
||||||
|
|
||||||
|
const precision = () => {
|
||||||
|
if (targetValid && targetNonEmpty) {
|
||||||
|
const pieces = state.target.value.split('.');
|
||||||
|
if (pieces[1]) {
|
||||||
|
if (pieces[1].length > 20) {
|
||||||
|
return 20; // Max toFixed() allows
|
||||||
|
}
|
||||||
|
if (pieces[1].length > 2) {
|
||||||
|
return pieces[1].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
const targetRes = state.target.value * state.target.mult;
|
||||||
|
|
||||||
const reciprocalSum = state.have
|
const reciprocalSum = state.have
|
||||||
.filter((x) => x.value)
|
.filter((x) => x.value)
|
||||||
.reduce((a,b) => a + 1.0/(b.value * b.mult), 0.0);
|
.reduce((a,b) => a + 1.0 / (b.value * b.mult), 0.0);
|
||||||
|
|
||||||
|
const sum = 1.0 / reciprocalSum;
|
||||||
|
|
||||||
|
const percentError = Math.abs((sum - targetRes) / targetRes * 100);
|
||||||
|
|
||||||
|
const nextRes = 1.0 / (1.0 / targetRes - reciprocalSum);
|
||||||
|
|
||||||
|
const printSum = () => {
|
||||||
|
if (haveAllValid && haveNonEmpty) {
|
||||||
|
const {unit, mult} = getUnit(sum);
|
||||||
|
const val = sum / mult;
|
||||||
|
return val.toFixed(precision()) + unit;
|
||||||
|
} else {
|
||||||
|
return '---';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const printPercentError = () => {
|
||||||
|
if (targetValid && targetNonEmpty && haveAllValid && haveNonEmpty) {
|
||||||
|
// Check if the 'overall resistor value' matches the target
|
||||||
|
const {unit, mult} = getUnit(targetRes);
|
||||||
|
console.log((targetRes / mult).toFixed(precision()) + unit);
|
||||||
|
if (printSum() === (targetRes / mult).toFixed(precision()) + unit) {
|
||||||
|
return (0.0).toFixed(precision());
|
||||||
|
}
|
||||||
|
return percentError.toFixed(precision());
|
||||||
|
} else {
|
||||||
|
return '---';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const printNextRes= () => {
|
||||||
|
if (targetValid && targetNonEmpty && haveAllValid && haveNonEmpty) {
|
||||||
|
// Check if we are done because error is 0 or value's exact
|
||||||
|
if (nextRes == Infinity || printPercentError() == 0.0) {
|
||||||
|
return 'Done.';
|
||||||
|
} else if (nextRes < 0) {
|
||||||
|
return 'N/A.';
|
||||||
|
}
|
||||||
|
const {unit, mult} = getUnit(nextRes);
|
||||||
|
const val = nextRes / mult;
|
||||||
|
return val.toFixed(precision()) + unit;
|
||||||
|
} else {
|
||||||
|
return '---';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const printInfo = () => {
|
||||||
|
if (!haveAllValid) {
|
||||||
|
return 'A parallel resistor is not valid.';
|
||||||
|
} else if (!targetNonEmpty) {
|
||||||
|
return 'No target resistor.';
|
||||||
|
} else if (!targetValid) {
|
||||||
|
return 'Target resistor not valid.';
|
||||||
|
} else if (!haveNonEmpty) {
|
||||||
|
return 'No resistors in parallel.';
|
||||||
|
} else if (printNextRes() === 'N/A.') {
|
||||||
|
return (
|
||||||
|
<MyText>
|
||||||
|
No solution exists. <MyText
|
||||||
|
style={{color: '#3b6f73'}}
|
||||||
|
onPress={() => {
|
||||||
|
Alert.alert(
|
||||||
|
'No Solution Exists',
|
||||||
|
'This app recommends resistors to be added in parallel. It\'s impossible to increase resistance (to make it closer to the target) by adding another resistor in parallel.\n\nPlease remove the lowest value resistor if you wish to keep solving.',
|
||||||
|
[{text: 'OK'}]
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Why?
|
||||||
|
</MyText>
|
||||||
|
</MyText>
|
||||||
|
);
|
||||||
|
} else if (printNextRes() === 'Done.') {
|
||||||
|
return 'Target achieved.';
|
||||||
|
} else {
|
||||||
|
return 'Add the next resistor.';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={{padding: 20}}>
|
<View style={{padding: 20}}>
|
||||||
<Section>
|
<Section>
|
||||||
<Text>
|
<MyText>
|
||||||
Enter the exact resistance target:
|
Enter the exact resistance target:
|
||||||
</Text>
|
</MyText>
|
||||||
|
</Section>
|
||||||
|
<Section>
|
||||||
<Resistor form="target" />
|
<Resistor form="target" />
|
||||||
</Section>
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
<Text>
|
<View style={{flexDirection: 'row'}}>
|
||||||
Overall parallel resistor value:
|
<View>
|
||||||
{allValid && nonEmpty ? ' ' + 1/reciprocalSum : ' ???'}
|
<MyText style={styles.table}>
|
||||||
</Text>
|
Overall parallel resistor value:
|
||||||
<Text>
|
</MyText>
|
||||||
Error between this and the target: {0}%
|
<MyText style={styles.table}>
|
||||||
</Text>
|
Error between this and target:
|
||||||
<Text>
|
</MyText>
|
||||||
Next recommended resistor value: {0}
|
<MyText style={styles.table}>
|
||||||
</Text>
|
Next resistor value needed:
|
||||||
|
</MyText>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<MyText style={styles.table} selectable={true}>
|
||||||
|
{printSum()}
|
||||||
|
</MyText>
|
||||||
|
<MyText style={styles.table} selectable={true}>
|
||||||
|
{printPercentError()} %
|
||||||
|
</MyText>
|
||||||
|
<MyText style={styles.table} selectable={true}>
|
||||||
|
{printNextRes()}
|
||||||
|
</MyText>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<MyText style={{padding: styles.table.padding}}>
|
||||||
|
{printInfo()}
|
||||||
|
</MyText>
|
||||||
</Section>
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
<Text>
|
<MyText>
|
||||||
Enter the resistors you have in parallel:
|
Enter the resistors you have in parallel:
|
||||||
</Text>
|
</MyText>
|
||||||
|
</Section>
|
||||||
|
<Section>
|
||||||
{state.have.map((x,n) =>
|
{state.have.map((x,n) =>
|
||||||
<Resistor form="have" index={n} key={n} />
|
<Resistor form="have" index={n} key={n} />
|
||||||
)}
|
)}
|
||||||
</Section>
|
</Section>
|
||||||
|
<View style={{alignItems: 'center'}}>
|
||||||
|
<ClearAll />
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
|
57
src/components/clearall.js
Normal file
57
src/components/clearall.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {bindActionCreators} from 'redux';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import * as calcActions from '../actions/calcActions';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
clearbutton: {
|
||||||
|
height: 30,
|
||||||
|
width: 100,
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: 'lightgray',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
margin: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClearAll extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {actions} = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
Alert.alert(
|
||||||
|
'Clear all resistors?',
|
||||||
|
'',
|
||||||
|
[
|
||||||
|
{text: 'CANCEL'},
|
||||||
|
{text: 'OK', onPress: actions.clearall},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
style={styles.clearbutton} activeOpacity={1}
|
||||||
|
>
|
||||||
|
<Text>Clear all</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(null, (dispatch) => ({
|
||||||
|
actions: bindActionCreators(calcActions, dispatch)
|
||||||
|
}))(ClearAll);
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {StyleSheet, View, Text, TouchableOpacity} from 'react-native';
|
import {StyleSheet, View, Text, TouchableOpacity} from 'react-native';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
});
|
|
||||||
|
|
||||||
export default class Help extends Component {
|
export default class Help extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
//const { counter } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
||||||
<Text>This is a sample counter app.</Text>
|
<Text>This is a sample counter app.</Text>
|
||||||
|
|
25
src/components/mytext.js
Normal file
25
src/components/mytext.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {StyleSheet, Text} from 'react-native';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
mytext: {
|
||||||
|
color: 'black',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class MyText extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Text {...this.props} style={[styles.mytext, this.props.style]}>
|
||||||
|
{this.props.children}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,10 @@ class Resistor extends Component {
|
||||||
updatemult('1');
|
updatemult('1');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(this);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', margin: 3}}>
|
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', margin: 3}}>
|
||||||
<TextInput
|
<TextInput
|
||||||
value={data.value}
|
value={data.value || ''}
|
||||||
onChangeText={(x) => updatevalue(x)}
|
onChangeText={(x) => updatevalue(x)}
|
||||||
style={Object.assign({}, styles.resistorinput, {
|
style={Object.assign({}, styles.resistorinput, {
|
||||||
borderColor: data.valid ? 'grey' : 'red',
|
borderColor: data.valid ? 'grey' : 'red',
|
||||||
|
@ -79,9 +77,8 @@ class Resistor extends Component {
|
||||||
<Picker.Item label=" mΩ" value="0.001" />
|
<Picker.Item label=" mΩ" value="0.001" />
|
||||||
</Picker>
|
</Picker>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
console.log(this);
|
data.value ? Alert.alert(
|
||||||
Alert.alert(
|
|
||||||
'Clear resistor value?',
|
'Clear resistor value?',
|
||||||
data.value +
|
data.value +
|
||||||
// I created this kludge for fun (so don't hate on me):
|
// I created this kludge for fun (so don't hate on me):
|
||||||
|
@ -93,7 +90,7 @@ class Resistor extends Component {
|
||||||
{text: 'CANCEL'},
|
{text: 'CANCEL'},
|
||||||
{text: 'OK', onPress: clear},
|
{text: 'OK', onPress: clear},
|
||||||
]
|
]
|
||||||
)
|
) : null ;
|
||||||
}}
|
}}
|
||||||
style={styles.clearbutton} activeOpacity={1}
|
style={styles.clearbutton} activeOpacity={1}
|
||||||
>
|
>
|
||||||
|
@ -119,8 +116,6 @@ function mapStateToProps(state, ownProps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps,
|
export default connect(mapStateToProps, (dispatch) => ({
|
||||||
(dispatch) => ({
|
actions: bindActionCreators(calcActions, dispatch)
|
||||||
actions: bindActionCreators(calcActions, dispatch)
|
}))(Resistor);
|
||||||
})
|
|
||||||
)(Resistor);
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ class CalcApp extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {state} = this.props;
|
const {state} = this.props;
|
||||||
console.log(this);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Calc state={state}/>
|
<Calc state={state}/>
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {bindActionCreators} from 'redux';
|
|
||||||
import Help from '../components/help';
|
import Help from '../components/help';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
class HelpApp extends Component {
|
export default class HelpApp extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { state, actions } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<Help {...actions} />
|
<Help />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(state => ({
|
|
||||||
}), (dispatch) => ({
|
|
||||||
}))(HelpApp);
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Nav extends Component {
|
||||||
const { state, actions } = this.props;
|
const { state, actions } = this.props;
|
||||||
|
|
||||||
const drawerStyles = {
|
const drawerStyles = {
|
||||||
drawer: { shadowColor: '#000000', shadowOpacity: 0.8, shadowRadius: 3},
|
drawer: {shadowColor: '#000000', shadowOpacity: 0.8, shadowRadius: 3},
|
||||||
main: {paddingLeft: 3},
|
main: {paddingLeft: 3},
|
||||||
}
|
}
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -34,8 +34,8 @@ class Nav extends Component {
|
||||||
type="overlay"
|
type="overlay"
|
||||||
content={<MenuApp />}
|
content={<MenuApp />}
|
||||||
tapToClose={true}
|
tapToClose={true}
|
||||||
openDrawerOffset={0.3}
|
openDrawerOffset={(viewport) => viewport.width - 250}
|
||||||
captureGestures={false}
|
captureGestures={true}
|
||||||
panCloseMask={0.3}
|
panCloseMask={0.3}
|
||||||
closedDrawerOffset={-3}
|
closedDrawerOffset={-3}
|
||||||
styles={drawerStyles}
|
styles={drawerStyles}
|
||||||
|
|
|
@ -91,6 +91,8 @@ export default function calc(state = initialState, action = {}) {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case types.CLEARALL:
|
||||||
|
return initialState;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user