Initial contribution
This commit is contained in:
parent
048d2b475f
commit
8fa6637b3a
6 changed files with 85 additions and 11 deletions
|
@ -7,6 +7,7 @@
|
||||||
"@testing-library/react": "^12.1.2",
|
"@testing-library/react": "^12.1.2",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
"react-csv-reader": "^3.4.0",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
"web-vitals": "^2.1.2"
|
"web-vitals": "^2.1.2"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.App {
|
.App {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
font-size: xx-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-logo {
|
.App-logo {
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: calc(10px + 2vmin);
|
font-size: calc(8px + 1vmin);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/App.js
35
src/App.js
|
@ -1,22 +1,37 @@
|
||||||
import logo from './logo.svg';
|
import logo from './logo.svg';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
import Table from './Table.js';
|
||||||
|
import CSVReader from 'react-csv-reader'
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { transactionPrices, calculateTotal , filterMultiples } from './filter.js';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
let [dataSet, setDataSet] = useState([]);
|
||||||
|
let [tableSet, setTableSet] = useState([]);
|
||||||
|
let [tableHeaders, setTableHeaders] = useState([]);
|
||||||
|
let [pricesSet, setPricesSet] = useState([]);
|
||||||
|
let [total, setTotal] = useState(0);
|
||||||
|
|
||||||
|
function importCSV(data) {
|
||||||
|
setDataSet(data);
|
||||||
|
setTableHeaders(data.shift());
|
||||||
|
setTableSet(data);
|
||||||
|
setTotal(calculateTotal(data));
|
||||||
|
setPricesSet(Object.entries(filterMultiples(transactionPrices(data))));
|
||||||
|
//setPricesSet(Object.entries(transactionPrices(data)));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<header className="App-header">
|
<header className="App-header">
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
|
||||||
<p>
|
<p>
|
||||||
Edit <code>src/App.js</code> and save to reload.
|
Import a .csv file using the button below
|
||||||
</p>
|
</p>
|
||||||
<a
|
<CSVReader onFileLoaded={importCSV}/>
|
||||||
className="App-link"
|
<h3>Total : {total} eur</h3>
|
||||||
href="https://reactjs.org"
|
<h4>Volume of transactions at different prices (Verified transactions only)</h4>
|
||||||
target="_blank"
|
<Table headers={['Price','Volume']} rows={pricesSet}/>
|
||||||
rel="noopener noreferrer"
|
<Table headers={tableHeaders} rows={tableSet}/>
|
||||||
>
|
|
||||||
Learn React
|
|
||||||
</a>
|
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
15
src/Table.js
Normal file
15
src/Table.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
function Entry({strings}) {
|
||||||
|
return <tr>{strings.map((string, index) => <td key={string + index}>{string}</td>)}</tr>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Headers({strings}) {
|
||||||
|
return <thead><tr>{strings.map((string) => <th key={string}>{string}</th>)}</tr></thead>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Table({headers, rows=[]}) {
|
||||||
|
return <table><Headers strings={headers}/><tbody>{rows.map((row, index) => <Entry key={index} strings={row} />)}</tbody></table>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Table;
|
41
src/filter.js
Normal file
41
src/filter.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
export function transactionPrices(data, filterOK=true) {
|
||||||
|
let transactionPrices = {};
|
||||||
|
data.forEach((transaction) => {
|
||||||
|
const price = Number(transaction[3].replace(',','.'));
|
||||||
|
if (!filterOK || transaction[7] === "OK")
|
||||||
|
transactionPrices[price] = transactionPrices[price] ? transactionPrices[price] + 1 : 1;
|
||||||
|
});
|
||||||
|
return transactionPrices;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateTotal(data, filterOK=true) {
|
||||||
|
let total = 0;
|
||||||
|
data.forEach((transaction) => {
|
||||||
|
const price = Number(transaction[3].replace(',','.'));
|
||||||
|
if (!filterOK || transaction[7] === "OK")
|
||||||
|
total += price;
|
||||||
|
});
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function filterMultiples(prices, multiples=[3.5]) {
|
||||||
|
let sales = {};
|
||||||
|
Object.entries(prices).forEach((pair) => {
|
||||||
|
const price = Number(pair[0]);
|
||||||
|
const amount = pair[1];
|
||||||
|
let dealt = false; // Ugly loop exit
|
||||||
|
//console.log(price,amount);
|
||||||
|
for (let i in multiples) {
|
||||||
|
let multiple = multiples[i];
|
||||||
|
if (price % multiple === 0) {
|
||||||
|
const quantity = price/multiple*amount;
|
||||||
|
sales[multiple] = sales[multiple] ? sales[multiple] + quantity : quantity;
|
||||||
|
dealt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dealt) sales[price] = sales[price] ? sales[price] + 1 : 1 ;
|
||||||
|
});
|
||||||
|
console.log(multiples);
|
||||||
|
return sales;
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
body {
|
body {
|
||||||
|
font-size: xx-small;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
|
Loading…
Reference in a new issue