Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #20

Merged
merged 6 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"chartjs-plugin-annotation": "^0.5.7",
"file-saver": "^2.0.2",
"lodash": "^4.17.15",
"lodash.clonedeep": "^4.5.0",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
Expand Down
42 changes: 21 additions & 21 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,27 +237,27 @@ class App extends React.Component<{},{}> {
}
render () {
return (
<div className="App">
<NavbarCustom links={this.links} ref={this.navRef}/>
<h1 style={{textAlign: 'center'}}>World of Warships Ballistics Calculator</h1>
<hr/>
<ShellFormsContainer ref={this.SFCref} settings={this.settings}/>
<hr/>
<TargetFormsContainer ref={this.TFCref}/>
<hr/>
<SettingsBar settings={this.settings} ref={this.Settingsref} updateColors={this.updateColors}/>
<hr/>
<Row>
<Col/>
<Col sm="9">
<Button style={{width: "100%", paddingTop: "0.6rem", paddingBottom: "0.6rem"}}
variant="secondary" onClick={this.generate}>Make Graphs!</Button>
</Col>
<Col/>
</Row>
<hr/>
<ChartGroup ref={this.graphsRef} settings={this.settings} links={this.links} onUpdate={this.onUpdate}/>
</div>
<div className="App">
<NavbarCustom links={this.links} ref={this.navRef}/>
<h1 style={{textAlign: 'center'}}>World of Warships Ballistics Calculator</h1>
<hr/>
<ShellFormsContainer ref={this.SFCref} settings={this.settings}/>
<hr/>
<TargetFormsContainer ref={this.TFCref}/>
<hr/>
<SettingsBar settings={this.settings} ref={this.Settingsref} updateColors={this.updateColors}/>
<hr/>
<Row>
<Col/>
<Col sm="9">
<Button style={{width: "100%", paddingTop: "0.6rem", paddingBottom: "0.6rem"}}
variant="secondary" onClick={this.generate}>Make Graphs!</Button>
</Col>
<Col/>
</Row>
<hr/>
<ChartGroup ref={this.graphsRef} settings={this.settings} links={this.links} onUpdate={this.onUpdate}/>
</div>
);
}
componentDidMount(){
Expand Down
136 changes: 70 additions & 66 deletions src/components/Charts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,28 @@ export class SingleChart extends React.Component<singleChartProps, singleChartSt
}
render(){
return(
<>
<Button style={{width: "100%", paddingTop: "0.6rem", paddingBottom: "0.6rem", height: "3rem"}}
onClick={this.toggleCollapse} ref={this.scrollRef} variant="dark"
aria-controls="collapseChart"
aria-expanded={this.state.open}
className={this.state.open === true ? 'active' : ''}
>{this.titles[Number(!this.state.open)] + this.props.title}</Button>
<Collapse in={this.state.open}>
<div id="collapseChart">
<Scatter data={this.props.config.data} options={this.props.config.options}
width={this.props.dimensions.width} height={this.props.dimensions.height}
ref={this.chartRef} datasetKeyProvider={this.datasetKeyProvider}/>
<Row style={{margin: 0}}>
<Col sm="4" style={{padding: 0}}/>
<Col sm="2" style={{padding: 0}}><DownloadButton ref={this.DownloadRef[0]} updateData={this.updateDownloadGraph}
label="Download Graph"/></Col>
<Col sm="2" style={{padding: 0}}><DownloadButton ref={this.DownloadRef[1]} updateData={this.updateDownloadJSON}
label="Download Data"/></Col>
<Col sm="4" style={{padding: 0}}/>
</Row>
</div>
</Collapse>
</>
<>
<Button style={{width: "100%", paddingTop: "0.6rem", paddingBottom: "0.6rem", height: "3rem"}}
onClick={this.toggleCollapse} ref={this.scrollRef} variant="dark"
aria-controls="collapseChart" aria-expanded={this.state.open}
className={this.state.open === true ? 'active' : ''}
>{this.titles[Number(!this.state.open)] + this.props.title}</Button>
<Collapse in={this.state.open}>
<div id="collapseChart">
<Scatter data={this.props.config.data} options={this.props.config.options}
width={this.props.dimensions.width} height={this.props.dimensions.height}
ref={this.chartRef} datasetKeyProvider={this.datasetKeyProvider}/>
<Row style={{margin: 0}}>
<Col sm="4" style={{padding: 0}}/>
<Col sm="2" style={{padding: 0}}><DownloadButton ref={this.DownloadRef[0]} updateData={this.updateDownloadGraph}
label="Download Graph"/></Col>
<Col sm="2" style={{padding: 0}}><DownloadButton ref={this.DownloadRef[1]} updateData={this.updateDownloadJSON}
label="Download Data"/></Col>
<Col sm="4" style={{padding: 0}}/>
</Row>
</div>
</Collapse>
</>
);
}
componentDidUpdate(){
Expand Down Expand Up @@ -459,52 +458,57 @@ export class ChartGroup extends React.Component<chartGroupProps>{
render(){
const addChart = (target : T.chartT) => {
return this.chartConfigs[target].map((value, i) => {
return (<SingleChart config={value[singleChartIndex.config]} dimensions={this.dimensions}
ref={value[singleChartIndex.ref]} key={i} title={value[singleChartIndex.name]}/>);
return (<SingleChart
ref={value[singleChartIndex.ref]} key={i}
config={value[singleChartIndex.config]}
dimensions={this.dimensions}
title={value[singleChartIndex.name]}/>);
});
}
return(
<>
<GeneralTooltip title="Impact Charts" content={
<>
<table id="tooltip-table">
<tr><td>Effective Penetration*</td><td>Belt Impact Angle</td></tr>
<tr><td>Effective Deck Penetration*</td><td>Deck Impact Angle</td></tr>
<tr><td>Impact Velocity</td><td>Time to Target**</td></tr>
</table>
* Adjusts for fall angle and normalization <br/> - does not adjust for armor inclination <br/>
** Scaled by x(1/3.1) ≈ game / real world <br/>
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Impact Charts</h3>
</GeneralTooltip>
{addChart('impact')}
<GeneralTooltip title="Angle Charts" content={
<>
Shows at what target angles and ranges shells will: <br/>
- Start Ricocheting - Always Ricochet <br/>
- No Longer Perforate Armor <br/>
- Start to Fuse on Armor <br/>
Note: Adjusts for angle of fall and armor inclination
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Angle Charts</h3>
</GeneralTooltip>
{addChart('angle')}
<GeneralTooltip title="Post-Penetration Charts" content={
<>
Show how far shells would travel into a ship after penetrating armor. <br/>
Along with whether and when shells would fuse at the given target angle. <br/>
Note: <br/>
- Shows x axis of distance travelled (distance travelled that is parallel to the ship's beam) <br/>
***This is not total distance travelled by the shell. ***<br/>
- Adjusts for angle of fall and armor inclination
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Post-Penetration Charts</h3>
</GeneralTooltip>
{addChart('post')}
</>
<>
<GeneralTooltip title="Impact Charts" content={
<>
<table id="tooltip-table">
<tbody>
<tr><td>Effective Penetration*</td><td>Belt Impact Angle</td></tr>
<tr><td>Effective Deck Penetration*</td><td>Deck Impact Angle</td></tr>
<tr><td>Impact Velocity</td><td>Time to Target**</td></tr>
</tbody>
</table>
* Adjusts for fall angle and normalization <br/> - does not adjust for armor inclination <br/>
** Scaled by x(1/3.1) ≈ game / real world <br/>
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Impact Charts</h3>
</GeneralTooltip>
{addChart('impact')}
<GeneralTooltip title="Angle Charts" content={
<>
Shows at what target angles and ranges shells will: <br/>
- Start Ricocheting - Always Ricochet <br/>
- No Longer Perforate Armor <br/>
- Start to Fuse on Armor <br/>
Note: Adjusts for angle of fall and armor inclination
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Angle Charts</h3>
</GeneralTooltip>
{addChart('angle')}
<GeneralTooltip title="Post-Penetration Charts" content={
<>
Show how far shells would travel into a ship after penetrating armor. <br/>
Along with whether and when shells would fuse at the given target angle. <br/>
Note: <br/>
- Shows x axis of distance travelled (distance travelled that is parallel to the ship's beam) <br/>
***This is not total distance travelled by the shell. ***<br/>
- Adjusts for angle of fall and armor inclination
</>
}>
<h3 style={{textAlign: "center", display:"inline-block"}}>Post-Penetration Charts</h3>
</GeneralTooltip>
{addChart('post')}
</>
);
}
componentDidMount(){
Expand Down
70 changes: 38 additions & 32 deletions src/components/DefaultForms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class DefaultForm extends React.Component
return (
<Form.Group className="form-inline" style={{marginBottom: ".25rem"}}>
<Form.Label column sm="3">{this.props.label}</Form.Label>
<Form.Control as="select" placeholder="" defaultValue={this.props.defaultValue}
<Form.Control as="select" placeholder="" defaultValue={this.props.defaultValue} aria-label={this.props.label}
onChange={this.handleChange} ref={this.form} style={{width: "70%"}}>
{this.state.options.map((value,i) => {return (<option aria-label={value} key={i}>{value}</option>);})}
</Form.Control>
Expand Down Expand Up @@ -67,7 +67,6 @@ const fetchJsonData = async (target) => {
}
return response.json();
})
.then((data) => {return data;})
.catch((error) => {
console.error('There has been a problem with your fetch operation:', error);
}
Expand All @@ -82,15 +81,16 @@ class DefaultShips extends React.Component
<{sendDefault: Function, reset: Function, index: number, keyProp: number, defaultData: T.defaultDataT}> {
defaultForms : defaultFormType = Object.seal({
version: ['Version' , React.createRef<DefaultForm>(), 0],
nation: ['Nation' , React.createRef<DefaultForm>(), 0],
shipType: ['Type' , React.createRef<DefaultForm>(), 0],
ship: ['Ship' , React.createRef<DefaultForm>(), 0],
artillery: ['Artillery' , React.createRef<DefaultForm>(), 0],
shellType: ['Shell Type', React.createRef<DefaultForm>(), 0],
nation: ['Nation' , React.createRef<DefaultForm>(), 1],
shipType: ['Type' , React.createRef<DefaultForm>(), 2],
ship: ['Ship' , React.createRef<DefaultForm>(), 3],
artillery: ['Artillery' , React.createRef<DefaultForm>(), 4],
shellType: ['Shell Type', React.createRef<DefaultForm>(), 5],
})
changeForm = (value, id) => {
//this.defaultForms[id][singleFormIndex.value] = value;
this.props.defaultData[id][T.singleDefaultDataIndex.value] = value;
const defaultData = this.props.defaultData;
defaultData[id][T.singleDefaultDataIndex.value] = value;
const queryIndex = this.defaultForms[id][singleFormIndex.queryIndex];
const queries = {
0: this.queryNation, 1: this.queryType, 2: this.queryShip,
Expand All @@ -114,60 +114,66 @@ class DefaultShips extends React.Component
});
}
queryNation = () => {
fetchJson(dataURL + this.props.defaultData.version[T.singleDefaultDataIndex.value] + "/nations.json",
const defaultData = this.props.defaultData;
fetchJson(dataURL + defaultData.version[T.singleDefaultDataIndex.value] + "/nations.json",
(data) => {this.updateForm('nation', data);}
);
}
queryType = () => {
fetchJson(dataURL + this.props.defaultData.version[T.singleDefaultDataIndex.value] + "/" +
this.props.defaultData.nation[T.singleDefaultDataIndex.value] + "/shiptypes.json",
const defaultData = this.props.defaultData;
fetchJson(dataURL + defaultData.version[T.singleDefaultDataIndex.value] + "/" +
defaultData.nation[T.singleDefaultDataIndex.value] + "/shiptypes.json",
(data) => {this.updateForm('shipType', data);}
);
}
queryShip = async () => {
const defaultData = this.props.defaultData;
const data = await fetchJsonData(
dataURL + this.props.defaultData.version[T.singleDefaultDataIndex.value] + "/" +
this.props.defaultData.nation[T.singleDefaultDataIndex.value] +
"/" + this.props.defaultData.nation[T.singleDefaultDataIndex.value] + "_" +
this.props.defaultData.shipType[T.singleDefaultDataIndex.value] + ".json");
this.props.defaultData.queriedData = data;
dataURL + defaultData.version[T.singleDefaultDataIndex.value] + "/" +
defaultData.nation[T.singleDefaultDataIndex.value] +
"/" + defaultData.nation[T.singleDefaultDataIndex.value] + "_" +
defaultData.shipType[T.singleDefaultDataIndex.value] + ".json");
defaultData.queriedData = data;
let sorted = Object.keys(data);
sorted.sort((a, b) => {return data[a]['Tier'] - data[b]['Tier']});
this.updateForm('ship', sorted);
}
queryArtillery = () => {
const shipName : string = this.props.defaultData.ship[T.singleDefaultDataIndex.value];
const shipInfo = this.props.defaultData.queriedData[shipName];
const defaultData = this.props.defaultData;
const shipName : string = defaultData.ship[T.singleDefaultDataIndex.value];
const shipInfo = defaultData.queriedData[shipName];
let options: string[] = [];
Object.keys(shipInfo!).forEach((key : string) : void => {
if(key.includes('Artillery')){options.push(key);}
});
this.updateForm('artillery', options);
}
queryShellType = () => {
const input = this.props.defaultData.queriedData[this.props.defaultData.ship[T.singleDefaultDataIndex.value]]
const defaultData = this.props.defaultData;
const input = defaultData.queriedData[this.props.defaultData.ship[T.singleDefaultDataIndex.value]]
[this.props.defaultData.artillery[T.singleDefaultDataIndex.value]];
this.updateForm('shellType', Object.keys(input));
}
sendData = () => {
const defaultData = this.props.defaultData;
this.props.sendDefault(
this.props.defaultData.queriedData[this.props.defaultData.ship[T.singleDefaultDataIndex.value]]
[this.props.defaultData.artillery[T.singleDefaultDataIndex.value]]
[this.props.defaultData.shellType[T.singleDefaultDataIndex.value]],
this.props.defaultData.ship[T.singleDefaultDataIndex.value]
defaultData.queriedData[defaultData.ship[T.singleDefaultDataIndex.value]]
[defaultData.artillery[T.singleDefaultDataIndex.value]]
[defaultData.shellType[T.singleDefaultDataIndex.value]],
defaultData.ship[T.singleDefaultDataIndex.value]
);
}
render(){
const defaultData = this.props.defaultData;
return(
<Container style={{paddingLeft: 0, paddingRight: 0}}>
{Object.entries(this.defaultForms).map( ([k, v], i) => {
v[singleFormIndex.queryIndex] = i;
return (<DefaultForm label={v[singleFormIndex.name]} key={i} controlId={k}
handleValueChange={this.changeForm} ref={v[singleFormIndex.ref]} keyProp={this.props.keyProp}
defaultValue={this.props.defaultData[k][T.singleDefaultDataIndex.value]}
defaultOptions={this.props.defaultData[k][T.singleDefaultDataIndex.options]}> </DefaultForm>);
})}
</Container>
<Container style={{paddingLeft: 0, paddingRight: 0}}>
{Object.entries(this.defaultForms).map( ([name, v], i) => {
return (<DefaultForm label={v[singleFormIndex.name]} key={i} controlId={name}
handleValueChange={this.changeForm} ref={v[singleFormIndex.ref]} keyProp={this.props.keyProp}
defaultValue={defaultData[name][T.singleDefaultDataIndex.value]}
defaultOptions={defaultData[name][T.singleDefaultDataIndex.options]}> </DefaultForm>);
})}
</Container>
);
}
//componentDidUpdate(){}
Expand Down
9 changes: 4 additions & 5 deletions src/components/DownloadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ export class DownloadButton extends React.Component<{updateData: Function, label
}
private click = () => {this.props.updateData()}
render(){
const state = this.state, props = this.props;
return (
<a download={this.state.download} href={this.state.href}>
<Button variant="outline-secondary" onClick={this.click} style={this.props.style}>
{this.props.label}
</Button>
</a>
<a download={state.download} href={state.href}>
<Button variant="outline-secondary" onClick={this.click} style={props.style}>{props.label}</Button>
</a>
);
}
}
Expand Down
Loading