Give the simulation a progressive feeling
This commit is contained in:
parent
e95a33ba1f
commit
0696188191
21
src/App.tsx
21
src/App.tsx
|
|
@ -44,6 +44,7 @@ import { throttle } from "lodash";
|
||||||
import "./app.css";
|
import "./app.css";
|
||||||
|
|
||||||
const headerOffset = 10;
|
const headerOffset = 10;
|
||||||
|
const simulationDuration = 4000;
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
|
|
@ -341,20 +342,18 @@ export default function App() {
|
||||||
value: Math.round(d0 * theta).toLocaleString() + " DAI"
|
value: Math.round(d0 * theta).toLocaleString() + " DAI"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `${
|
label: resultParameterDescriptions.exitTributes.name,
|
||||||
resultParameterDescriptions.exitTributes.name
|
|
||||||
} (${withdrawCount} txs)`,
|
|
||||||
description: resultParameterDescriptions.exitTributes.text,
|
description: resultParameterDescriptions.exitTributes.text,
|
||||||
value:
|
value:
|
||||||
(+getLast(withdrawFeeTimeseries).toPrecision(3)).toLocaleString() +
|
(+getLast(withdrawFeeTimeseries).toPrecision(3)).toLocaleString() +
|
||||||
" DAI"
|
` DAI (${withdrawCount} txs)`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `${
|
label: resultParameterDescriptions.slippage.name,
|
||||||
resultParameterDescriptions.slippage.name
|
|
||||||
} (avg tx size ${Math.round(avgTxSize).toLocaleString()} DAI)`,
|
|
||||||
description: resultParameterDescriptions.slippage.text,
|
description: resultParameterDescriptions.slippage.text,
|
||||||
value: +(100 * avgSlippage).toFixed(3) + "%"
|
value:
|
||||||
|
+(100 * avgSlippage).toFixed(3) +
|
||||||
|
` % (avg tx size ${Math.round(avgTxSize).toLocaleString()} DAI)`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -521,6 +520,7 @@ export default function App() {
|
||||||
priceTimeseries={priceTimeseries}
|
priceTimeseries={priceTimeseries}
|
||||||
floorpriceTimeseries={floorpriceTimeseries}
|
floorpriceTimeseries={floorpriceTimeseries}
|
||||||
totalFundsRaisedTimeseries={totalFundsRaisedTimeseries}
|
totalFundsRaisedTimeseries={totalFundsRaisedTimeseries}
|
||||||
|
simulationDuration={simulationDuration}
|
||||||
p0={p0}
|
p0={p0}
|
||||||
p1={p1}
|
p1={p1}
|
||||||
/>
|
/>
|
||||||
|
|
@ -566,7 +566,10 @@ export default function App() {
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className={classes.box}>
|
<Box className={classes.box}>
|
||||||
<ResultParams resultFields={resultFields} />
|
<ResultParams
|
||||||
|
resultFields={resultFields}
|
||||||
|
simulationDuration={simulationDuration}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import React from "react";
|
||||||
|
import "./dotsLoader.css";
|
||||||
|
|
||||||
|
export default function DotsLoader() {
|
||||||
|
return (
|
||||||
|
<div className="spinner">
|
||||||
|
<div className="bounce1" />
|
||||||
|
<div className="bounce2" />
|
||||||
|
<div className="bounce3" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
AreaChart,
|
AreaChart,
|
||||||
Area,
|
Area,
|
||||||
|
|
@ -34,12 +34,14 @@ function PriceSimulationChart({
|
||||||
priceTimeseries,
|
priceTimeseries,
|
||||||
totalFundsRaisedTimeseries,
|
totalFundsRaisedTimeseries,
|
||||||
floorpriceTimeseries,
|
floorpriceTimeseries,
|
||||||
|
simulationDuration,
|
||||||
p0,
|
p0,
|
||||||
p1
|
p1
|
||||||
}: {
|
}: {
|
||||||
priceTimeseries: number[];
|
priceTimeseries: number[];
|
||||||
totalFundsRaisedTimeseries: number[];
|
totalFundsRaisedTimeseries: number[];
|
||||||
floorpriceTimeseries: number[];
|
floorpriceTimeseries: number[];
|
||||||
|
simulationDuration: number;
|
||||||
p0: number;
|
p0: number;
|
||||||
p1: number;
|
p1: number;
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -59,6 +61,21 @@ function PriceSimulationChart({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When resizing the window the chart animation looks very bad
|
||||||
|
* Keep the animation active only during the initial animation time,
|
||||||
|
* but afterwards, deactivate to prevent the re-size ugly effect
|
||||||
|
*/
|
||||||
|
const [isAnimationActive, setIsAnimationActive] = useState(true);
|
||||||
|
useEffect(() => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
setIsAnimationActive(false);
|
||||||
|
}, simulationDuration + 100);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Chart components
|
// Chart components
|
||||||
|
|
||||||
const theme: any = useTheme();
|
const theme: any = useTheme();
|
||||||
|
|
@ -171,7 +188,8 @@ function PriceSimulationChart({
|
||||||
<Tooltip content={<CustomTooltip />} />
|
<Tooltip content={<CustomTooltip />} />
|
||||||
|
|
||||||
<Area
|
<Area
|
||||||
isAnimationActive={false}
|
isAnimationActive={isAnimationActive}
|
||||||
|
animationDuration={simulationDuration}
|
||||||
yAxisId="left"
|
yAxisId="left"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey={keyVerticalLeft}
|
dataKey={keyVerticalLeft}
|
||||||
|
|
@ -181,7 +199,8 @@ function PriceSimulationChart({
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
isAnimationActive={false}
|
isAnimationActive={isAnimationActive}
|
||||||
|
animationDuration={simulationDuration}
|
||||||
yAxisId="left"
|
yAxisId="left"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey={keyVerticalLeft2}
|
dataKey={keyVerticalLeft2}
|
||||||
|
|
@ -208,7 +227,8 @@ function PriceSimulationChart({
|
||||||
|
|
||||||
{/* Capital collected from withdraw fees - AREA */}
|
{/* Capital collected from withdraw fees - AREA */}
|
||||||
<Area
|
<Area
|
||||||
isAnimationActive={false}
|
isAnimationActive={isAnimationActive}
|
||||||
|
animationDuration={simulationDuration}
|
||||||
yAxisId="right"
|
yAxisId="right"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey={keyVerticalRight}
|
dataKey={keyVerticalRight}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import Grid from "@material-ui/core/Grid";
|
import Grid from "@material-ui/core/Grid";
|
||||||
import TextWithPopover from "./TextWithPopover";
|
import TextWithPopover from "./TextWithPopover";
|
||||||
|
import DotsLoader from "./DotsLoader";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
|
|
@ -42,14 +43,31 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function ResultParams({
|
export default function ResultParams({
|
||||||
resultFields
|
resultFields,
|
||||||
|
simulationDuration
|
||||||
}: {
|
}: {
|
||||||
resultFields: {
|
resultFields: {
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
value: number | string;
|
value: number | string;
|
||||||
}[];
|
}[];
|
||||||
|
simulationDuration: number;
|
||||||
}) {
|
}) {
|
||||||
|
/**
|
||||||
|
* When resizing the window the chart animation looks very bad
|
||||||
|
* Keep the animation active only during the initial animation time,
|
||||||
|
* but afterwards, deactivate to prevent the re-size ugly effect
|
||||||
|
*/
|
||||||
|
const [isAnimationActive, setIsAnimationActive] = useState(true);
|
||||||
|
useEffect(() => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
setIsAnimationActive(false);
|
||||||
|
}, simulationDuration);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -61,7 +79,11 @@ export default function ResultParams({
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={4} className={classes.centerContainer}>
|
<Grid item xs={4} className={classes.centerContainer}>
|
||||||
<Typography gutterBottom>{value}</Typography>
|
{isAnimationActive ? (
|
||||||
|
<DotsLoader />
|
||||||
|
) : (
|
||||||
|
<Typography gutterBottom>{value}</Typography>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { getLinspaceTicks } from "./utils";
|
||||||
import { getInitialParams, getPriceR } from "./math";
|
import { getInitialParams, getPriceR } from "./math";
|
||||||
import { useTheme } from "@material-ui/styles";
|
import { useTheme } from "@material-ui/styles";
|
||||||
|
|
||||||
|
const isAnimationActive = false;
|
||||||
const keyHorizontal = "x";
|
const keyHorizontal = "x";
|
||||||
const keyVertical = "Supply (tokens) / Reserve (DAI)";
|
const keyVertical = "Supply (tokens) / Reserve (DAI)";
|
||||||
|
|
||||||
|
|
@ -181,7 +182,7 @@ function SupplyVsDemandChart({
|
||||||
/>
|
/>
|
||||||
<Tooltip content={<CustomTooltip />} />
|
<Tooltip content={<CustomTooltip />} />
|
||||||
<Area
|
<Area
|
||||||
isAnimationActive={false}
|
isAnimationActive={isAnimationActive}
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey={keyVertical}
|
dataKey={keyVertical}
|
||||||
stroke={theme.palette.primary.main}
|
stroke={theme.palette.primary.main}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*Huge thanks to @tobiasahlin at http://tobiasahlin.com/spinkit/ */
|
||||||
|
.spinner {
|
||||||
|
opacity: 0.5;
|
||||||
|
width: 70px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner > div {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
margin-right: 4px;
|
||||||
|
background-color: #9aa3ad;
|
||||||
|
border-radius: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
|
||||||
|
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .bounce1 {
|
||||||
|
-webkit-animation-delay: -0.32s;
|
||||||
|
animation-delay: -0.32s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner .bounce2 {
|
||||||
|
-webkit-animation-delay: -0.16s;
|
||||||
|
animation-delay: -0.16s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes sk-bouncedelay {
|
||||||
|
0%,
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes sk-bouncedelay {
|
||||||
|
0%,
|
||||||
|
80%,
|
||||||
|
100% {
|
||||||
|
-webkit-transform: scale(0);
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
40% {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue