import React from 'react';
import MGrid from '@material-ui/core/Grid';
import { Theme, withStyles, StyleRules } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import Button from '@material-ui/core/Button';
import Slider from '@material-ui/lab/Slider';
import FormGroup from '@material-ui/core/FormGroup';
import Grid, {getNodeColor} from './Grid';
import { Line } from 'react-chartjs-2';
import Color from 'color';
const styles = (theme: Theme): StyleRules => ({
inputLabel: {
fontSize: 16,
paddingRight: 0,
textAlign: 'right',
width: '30%'
},
inputValue: {
textAlign: 'left'
},
buttonSpacer: {
marginBottom: theme.spacing.unit * 4,
},
bottomButtons: {
marginTop: 10,
textAlign: 'center',
},
slider: {
padding: '22px 0px',
},
errorHint: {
fontSize: 16,
paddingLeft: 16,
lineHeight: '32px',
color: theme.palette.secondary.main
},
grid: {
textAlign: 'center'
}
});
interface SnowProps {
classes: {
inputLabel: string,
inputValue: string,
buttonSpacer: string,
bottomButtons: string,
slider: string,
errorHint: string,
grid: string
}
}
function getRandomInt(max: number) {
return Math.floor(Math.random() * Math.floor(max));
}
function getRandomSubarray(arr: number[], size: number) {
let shuffled = arr.slice(0), i = arr.length, min = i - size, temp, index;
while (i-- > min) {
index = Math.floor((i + 1) * Math.random());
temp = shuffled[index];
shuffled[index] = shuffled[i];
shuffled[i] = temp;
}
return shuffled.slice(min);
}
const watchedD = [15, 10, 5, 1];
class Snow extends React.Component<SnowProps> {
static genMatrix(n: number) {
let d = [];
for (let i = 0; i < n; i++)
{
let r = [];
for (let j = 0; j < n; j++)
r.push({d: [0, 0], col: getRandomInt(2)});
d.push(r);
}
return d;
}
state = {
colorMatrix: Snow.genMatrix(20),
n: '20',
k: '10',
alpha: '8',
nodesPerTick: '20',
maxInactiveTicks: '200',
loaded: true,
ticking: false,
simulationSpeed: 100,
dialogOpen: false,
dialogMsg: {title: '', message: ''},
nError: false,
kError: false,
alphaError: false,
nodesPerTickError: false,
maxInactiveTicksError: false,
dcnts: [watchedD.map(() => [] as number[]),
watchedD.map(() => [] as number[])] as number[][][],
ticks: [] as number[],
N: 400
};
config = {
iter: 0,
n: 20,
k: 10,
alpha: 8,
nodesPerTick: 10,
maxInactiveTicks: 200,
inactiveTicks: 0
};
getNodeState(n: number, u: number) {
let r = Math.floor(u / n);
let c = u % n;
return this.state.colorMatrix[r][c];
}
setNodeState(n: number, u: number, s: {d: number[], col: number}) {
let r = Math.floor(u / n);
let c = u % n;
let m = [...this.state.colorMatrix];
m[r][c] = s;
this.setState({colorMatrix: m});
}
tick(n: number, m: number) {
let N = n * n;
let active = false;
let nodes = [];
for (let j = 0; j < N; j++) nodes.push(j);
getRandomSubarray(nodes, m).forEach(v => {
let u = getRandomInt(N);
let peers = [];
for (let j = 0; j < N; j++)
if (j != u) peers.push(j);
let sample = getRandomSubarray(peers, this.config.k);
let cnt = [0, 0];
sample.forEach((v) => {
let ss = this.getNodeState(n, v);
cnt[ss.col]++;
});
let s = this.getNodeState(n, u);
for (let c = 0; c < 2; c++)
{
if (cnt[c] > this.config.alpha)
{
s.d[c]++;
if (s.d[c] > s.d[s.col])
{
if (s.col != c) active = true;
s.col = c;
this.setNodeState(n, u, s);
}
}
}
});
if (this.config.iter % 10 == 0)
{
let dcnts = [];
for (let c = 0; c < 2; c++)
{
dcnts.push(watchedD.map((d, i) => {
let dcnt = 0;
for (let i = 0; i < n; i++)
for (let j = 0; j < n; j++)
{
const s = this.state.colorMatrix[i][j];
if (s.d[c] >= d)
dcnt++;
}
if (c == 0) dcnt = -dcnt;
return [...this.state.dcnts[c][i], dcnt].splice(-50);
}));
}
this.setState({
dcnts: dcnts,
ticks: [...this.state.ticks, this.config.iter].splice(-50)
});
}
return active;
}
pauseTick() {
this.setState({ticking: false});
}
startTick() {
const n = Number(this.state.n);
const N = n * n;
const k = Number(this.state.k);
const alpha = Number(this.state.alpha);
const nodesPerTick = Number(this.state.nodesPerTick);
const maxInactiveTicks = Number(this.state.maxInactiveTicks);
if (!Number.isInteger(n) || n < 2 || n > 40)
{
this.setState({ nError: true });
return;
}
if (!Number.isInteger(k) || k < 1 || k > N)
{
this.setState({ kError: true });
return;
}
if (!Number.isInteger(alpha) || !(k / 2 < alpha && alpha <= k))
{
this.setState({ alphaError: true });
return;
}
if (!Number.isInteger(nodesPerTick) || nodesPerTick < 1 || nodesPerTick > N)
{
this.setState({ nodesPerTickError: true });
return;
}
if (!Number.isInteger(maxInactiveTicks) || maxInactiveTicks < 1 || maxInactiveTicks > 1e6)
{
this.setState({ maxInactiveTicksError: true });
return;
}
if (!this.state.loaded)
{
this.config.iter = 0;
this.config.n = n;
this.setState({