import React, { Component } from 'react'
import { EVENTS } from '../../constants/swimmingConstants/swimmingConstants';
import * as SwimFormulas from '../../constants/graphFunctions/graphFunctions';
import Container from 'react-bootstrap/Container';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import ReactTable from '../../components/reactTable/reactTable';
import FastestMeets from '../../components/analytics/fastestMeets/fastestMeets';
import FastestCity from '../../components/analytics/fastestCity/fastestCity';
import PeakMonth from '../../components/analytics/peakMonth/peakMonth';
import PropTypes from 'prop-types';
/**
* Club Dashboard converts the data fetched from the route 'club', to a usable format to be used by the components (FastestMeets,FastestCity,PeakMonths).
* @component
*/
class ClubDashboard extends Component {
render() {
let swimmerData = [];
let allSwimmerData = [];
let allSwimmerDataSubComponents = [];
let event = '';
let allData;
// * Checks if the data passed is null OR if data passed in form [Years[Events[Swimmers]]].length == 0 aka. No swimmers for event
try {
if (this.props.swimmerData === null || this.props.swimmerData[0][0][0].length === 0) {
return (
<div name="InvalidYearNoData"> </div>
)
} else {
allData = this.props.swimmerData;
event = this.props.event;
// * If a specific event is selected, it will get the Sheet with the data for that specific event.
if (event !== 'All') {
allData[0].forEach(workbook => {
// * In every Workbook (Age / Year) it holds Sheets with the Events, will select the sheet that contains the events data
let index = EVENTS.indexOf(event)
let Sheet = workbook[index];
// * For the selected event collect all the swimmer data
Sheet.forEach(swimmer => {
swimmer.__EMPTY_8 = SwimFormulas.standardizeTimes(swimmer.__EMPTY_7);
swimmerData.push(swimmer);
})
})
// * Pass it the keys that will be used as the header for the table in React Table
let meetCityKeys = [
'__EMPTY_11',
'__EMPTY_14',
];
// * Converts all the events data into the labels and data for the piechart of meet city
let meetCity = [...SwimFormulas.mostOccurrences(SwimFormulas.meetCity(swimmerData))].sort((a, b) => b[1] - a[1]);
// * Converts it into array that holds objects with properties that can be used by the ReactTable Component
let meetCityArr = [];
meetCity.forEach((city) => meetCityArr.push(Object({ '__EMPTY_11': city[0], '__EMPTY_14': city[1] })));
// * Pass it the keys that will be used as the header for the table in React Table
let meetKeys = [
'__EMPTY_9',
'__EMPTY_12',
'__EMPTY_14',
'__EMPTY_16',
'__EMPTY_17'
];
// * Converts all events data into label for Meet data. (Meet Name and occurence of best time)
// * Converts the Meet Data Map into useable 'key' and 'value' arrays for graphing
let meets = [...SwimFormulas.mostOccurrences(SwimFormulas.meetName(swimmerData))].sort((a, b) => b[1] - a[1]);
let timeMap = new Map();
meets.forEach(el => timeMap.set(el[0]));
// * Going to be used for the groupings to sort by multiple properties.
for (let el of timeMap) {
// * Builds a Key for the map that consists of an array of Objects where all the meetNames are the same
el[1] = swimmerData.filter(item => item.__EMPTY_12 === el[0])
timeMap.set(el[0], el[1]);
}
for (let el of timeMap) {
let length = el[1].length
let times = el[1].map(el => el.__EMPTY_8);
let average = times.reduce((a, b) => a + b) / length;
let stddev = times.map(t => Math.pow((t - average), 2));
stddev = Math.sqrt(stddev.reduce((a, b) => a + b) / length);
timeMap.set(el[0], { groupMembers: el[1], average: average, stddev: stddev, length: length })
}
timeMap = [...timeMap].sort((a, b) => (a[1].average > b[1].average) && (a[1].stddev > b[1].stddev));
let meetArr = [];
timeMap.forEach((city, index) => meetArr.push(Object(
{
'__EMPTY_9': index + 1,
'__EMPTY_12': city[0],
'__EMPTY_14': city[1].length,
'__EMPTY_16': new Date(city[1].average).toISOString().substr(14, 8),
'__EMPTY_17': new Date(city[1].stddev).toISOString().substr(14, 8),
})
))
return (
<div>
<Container fluid className="mt-1">
<Row>
{/* Displays The Distribution of months with best time, aka. Peak Months */}
<Col className="text-center colBorder"> <PeakMonth swimmerData={swimmerData} allSwimmerData={allSwimmerData} allSwimmerDataSubComponents={allSwimmerDataSubComponents} event={this.props.event} />
</Col>
</Row>
<Row className="mt-2">
<Col className="colBorder" md={6} sm={12}>
<FastestCity swimmerData={swimmerData} />
<ReactTable tableData={meetCityArr} allowedKeys={meetCityKeys} />
</Col>
<Col className="colBorder" md={6} sm={12}>
<FastestMeets swimmerData={swimmerData} swimEvent={this.props.swimEvent} />
<ReactTable tableData={meetArr} allowedKeys={meetKeys} />
</Col>
</Row>
</Container>
</div>
)
}
// * Need to process data from Workbook -> Worksheets -> Event -> Swimmers
try {
// * For getting Data of the subcomponents that will add up to all events
allData.forEach(Workbook => {
let Sheet = Workbook[0];
Sheet.forEach(sheet => {
allSwimmerDataSubComponents.push(sheet)
})
})
// * For getting the Data of all sheets containing all events (Workbook holds each fetch file)
// * Each fetch file contains 18 Sheets (aka arrays of events) in each, it contains 50 swimmers (Objects) (Max)
allData.forEach(Workbook => {
Workbook.forEach(Sheet => {
Sheet.forEach(Event => {
Event.forEach(Swimmer => {
Swimmer.__EMPTY_8 = SwimFormulas.standardizeTimes(Swimmer.__EMPTY_7);
allSwimmerData.push(Swimmer);
})
})
})
})
} catch {
console.log('Error: Unable to convert workbook data into sheets');
}
// * Pass it the keys that will be used as the header for the table in React Table
let meetCityKeys = [
'__EMPTY_11',
'__EMPTY_14',
];
// * Converts all the events data into the labels and data for the piechart of meet city
let meetCity = Array.from(SwimFormulas.mostOccurrences(SwimFormulas.meetCity(allSwimmerData))).sort((a, b) => b[1] - a[1]);
let meetCityKey = meetCity.map(city => city[0]);
let meetCityNum = meetCity.map(number => number[1]);
// * Converts it into array that holds objects with properties that can be used by the ReactTable Component
let meetCityArr = [];
meetCity.forEach((city, index) => meetCityArr.push(Object({ '__EMPTY_11': meetCityKey[index], '__EMPTY_14': meetCityNum[index] })));
// * Pass it the keys that will be used as the header for the table in React Table
let meetKeys = [
'__EMPTY_12',
'__EMPTY_14',
];
// * Converts all events data into label for Meet data. (Meet Name and occurence of best time)
// * Converts the Meet Data Map into useable 'key' and 'value' arrays for graphing
let meets = Array.from(SwimFormulas.mostOccurrences(SwimFormulas.meetName(allSwimmerData))).sort((a, b) => b[1] - a[1]);
let meetName = meets.map(name => name[0]);
let meetNumber = meets.map(number => number[1]);
let meetArr = [];
meets.forEach((city, index) => meetArr.push(Object({ '__EMPTY_12': meetName[index], '__EMPTY_14': meetNumber[index] })))
return (
<div>
<Container fluid className="mt-1">
<Row>
{/* Displays The Distribution of months with best time, aka. Peak Months */}
<Col className="text-center colBorder"> <PeakMonth swimmerData={swimmerData} allSwimmerData={allSwimmerData} allSwimmerDataSubComponents={allSwimmerDataSubComponents} event={this.props.event} />
</Col>
</Row>
<Row className="mt-2">
<Col className="colBorder" sm={6}>
<FastestCity swimmerData={allSwimmerData} />
<ReactTable tableData={meetCityArr} allowedKeys={meetCityKeys} />
</Col>
<Col className="colBorder" sm={6}>
<FastestMeets swimmerData={allSwimmerData} swimEvent={this.props.swimEvent} />
<ReactTable tableData={meetArr} allowedKeys={meetKeys} />
</Col>
</Row>
</Container>
</div>
)
}
}
catch (e) {
console.log(e);
return (
<div></div>
)
}
}
}
ClubDashboard.propTypes = {
/**
* Standardized JSON File structure Converted from Clubs Component. It is an Array[Workbooks[Events[Swimmers[]]]]
*/
swimmerData: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.object)))),
/**
* The name of the event
*/
event: PropTypes.string.isRequired,
/**
* The name of the swimEvent
*/
swimEvent: PropTypes.string.isRequired,
}
export default ClubDashboard;
Source