Commit 0b86270f authored by Jan Pöppel's avatar Jan Pöppel
Browse files

Merge branch 'tomerge' into 'master'

Tomerge

See merge request scs/webviz!1
parents e5202ab0 8d3162e8
import React, { Component } from 'react';
class CheckboxList extends Component {
constructor (props, context) {
super(props, context);
let checkState = {};
for (var i=0; i<props.boxes.length; i++) {
checkState[props.boxes[i]] = false;
}
this.state = {
checkState: checkState
}
this.updateCheckState = this.updateCheckState.bind(this);
}
updateCheckState(e) {
let checkName = e.target.id.slice(0,-5);
let newCheckState = Object.assign({}, this.state.checkState);
newCheckState[checkName] = !newCheckState[checkName];
this.setState({
checkState: newCheckState
})
this.props.callback(checkName, newCheckState[checkName]);
}
render() {
let checkNames = this.props.boxes;
let checkBoxes = checkNames.map(el => {
return (
<div>
{el}
<input id={el + "Check"} type="checkbox" defaultChecked={this.state.checkState[el]} checked={this.state.checkState[el]} onChange={this.updateCheckState} />
</div>
)
})
return(
<div className={"flex"}>
{checkBoxes}
</div>
)
}
}
export default CheckboxList;
\ No newline at end of file
......@@ -30,17 +30,19 @@ class Condition extends Component {
}
return (
<li><span>
<span name="conditionName">{name}</span>
<span align="right">
<li>
{/* <span> */}
<div className="conList-item">
<span>{name}: </span>
{/* </span> */}
{/* <span align="right"> */}
<select id={"visSelect_"+name} onChange={this.optionChanged}>
{options}
</select>
</span>
<span>
<input id={"btn"+name} type="button" value="Visualize" onClick={() => this.props.onSelect(name, this.option)} />
</span>
</span>
<input id={"btn"+name+"aggr"} type="button" value="Aggregate" onClick={() => this.props.onSelect(name)} />
{/* </span> */}
</div>
</li>
)
......
import React, { PureComponent } from 'react';
import { randomFill } from 'crypto';
class CanvasGridworld extends PureComponent {
constructor (props, context) {
super(props, context)
super(props, context);
this.onMouseMove = this.onMouseMove.bind(this);
}
componentDidMount() {
......@@ -14,6 +17,15 @@ class CanvasGridworld extends PureComponent {
this.updateCanvas();
}
onMouseMove(e) {
// console.log("mouse at : ", e)//e.screenX, e.screenY)
let canvas = this.refs[this.props.bgname];
let r = canvas.getBoundingClientRect();
var mouseX = e.clientX - r.left;
var mouseY = e.clientY - r.top;
// console.log("mouse at: ", mouseX, mouseY)
}
renderMap() {
let map = this.props.map.map;
let canvas = this.refs[this.props.bgname];
......@@ -183,8 +195,8 @@ class CanvasGridworld extends PureComponent {
context.beginPath();
traj.forEach(function(pos, i, traj) {
let centerX = pos[1]*tileSize + tileSize/2; // +offX;
let centerY = pos[0]*tileSize + tileSize/2; // +offY;
let centerX = pos[1]*tileSize + tileSize/2;
let centerY = pos[0]*tileSize + tileSize/2;
if (i == 0) {
context.moveTo(centerX, centerY);
} else {
......@@ -195,14 +207,87 @@ class CanvasGridworld extends PureComponent {
context.stroke();
}
getColor(i, maxColors) {
var hue = i*(360 / maxColors);
var sat = 60 + Math.random() * 10;
var light = 50 + Math.random() * 10;
return `hsl(${hue}, ${sat}%, ${light}%)`
}
renderPredictions() {
}
renderAggregates() {
const canvas = this.refs[this.props.bgname];
let tileSize = this.tileSize;
let aggregates = this.props.aggregates;
var context = canvas.getContext("2d");
// context.lineWidth=2;
var posThick = {};
var visited = {};
for (var i=0; i< aggregates.length; i++) {
visited= {};
var trajObj = aggregates[i];
var name = Object.keys(trajObj)[0];
var traj = trajObj[name];
traj.forEach(function(pos, j) {
var posString = JSON.stringify(pos);
if (!visited[posString]){
if (posThick[posString]) {
posThick[posString] += 1
} else {
posThick[posString] = 1
}
}
visited[posString] = true;
})
}
for (var i=0; i< aggregates.length; i++) {
var trajObj = aggregates[i];
var name = Object.keys(trajObj)[0];
var traj = trajObj[name];
context.strokeStyle = this.getColor(i, aggregates.length); //"red";
var lastPos;
traj.forEach(function(pos, j) {
context.lineWidth = posThick[JSON.stringify(pos)]/2;
context.beginPath();
let centerX = pos[1]*tileSize + tileSize/2;
let centerY = pos[0]*tileSize + tileSize/2;
if (j > 0) {
context.moveTo(lastPos[0], lastPos[1]);
context.lineTo(centerX,centerY);
}
lastPos = [centerX, centerY];
context.stroke();
})
}
}
updateCanvas() {
var renderAggregates = this.props.aggregates && this.props.aggregates.length > 0;
if (this.props.map) {
this.renderMap();
if (this.props.showPath) {
this.renderPath()
if (this.props.showPath && !renderAggregates) {
this.renderPath();
}
if (this.props.pos && !renderAggregates) {
this.renderAgent();
}
if (renderAggregates) {
this.renderAggregates();
}
this.renderAgent();
};
}
......@@ -210,7 +295,7 @@ class CanvasGridworld extends PureComponent {
let { bgname, fgname, width, height } = this.props;
return (
<div>
<canvas ref={bgname} width={width} height={height} />
<canvas ref={bgname} width={width} height={height} onMouseMove={this.onMouseMove}/>
{/* <canvas className={"agentcanvas canvas"} ref={fgname} width={width} height={height} /> */}
</div>
)
......
import React, { PureComponent } from 'react';
export default class ListSelection extends PureComponent {
render () {
var { name, options1, onChange1, selected1, options2, onChange2, selected2 } = this.props;
var optionList = [];
for (var i=0; i< options1.length; i++) {
optionList.push(
<option key={i} value={options1[i]} selected={options1[i]===selected1}>
{options1[i]}
</option>
)
}
if (options2) {
var option2List = [];
options2 = options2.sort((a, b) => a.localeCompare(b, 'en', { numeric: true }))
for (var i=0; i< options2.length; i++) {
option2List.push(
<option key={i} value={options2[i]} selected={options2[i]===selected2}>
{options2[i]}
</option>
)
}
}
return (
<div className="conList-item">
{name}:
<select id={name+"Sel1"} onChange={onChange1} >
{optionList}
</select>
{options2 ? <select id={name+"Sel2"} onChange={onChange2}>
{option2List}
</select> : ""
}
</div>
)
}
}
\ No newline at end of file
......@@ -161,7 +161,7 @@ function mapStateToPropsBars(state, ownProps) {
export class BarPlot extends PureComponent {
render() {
let {width, height, bars} = this.props;
let {width, height, bars, yDomain} = this.props;
return(
<FlexibleWidthXYPlot
......@@ -170,7 +170,7 @@ export class BarPlot extends PureComponent {
dontCheckIfEmpty={true}
margin={{"left": 60, "right": 100}}
xType={"ordinal"}
yDomain={[0,1]}
yDomain={yDomain ? yDomain : null}
>
{bars}
<Borders style={{
......
......@@ -55,13 +55,25 @@ function mapDispatchToProps(dispatch) {
class CustomSlider extends PureComponent {
handleChangeSlider = value => {
if (value === this.props.max) {
if (value > this.props.max) { //TODO Check if this still works with plots, we usually want it to be infinity to render everything coming in when we move it to the far right!
this.props.onSliderChange(Infinity);
} else {
this.props.onSliderChange(value);
}
};
// TODO Make it a proper function registered in constructor to prevent
// recreating this function on every render
onWheel = e => {
let newVal = this.props.value;
if (e.deltaY < 0) {
newVal = newVal < this.props.max ? newVal + 1 : this.props.max;
} else {
newVal = newVal > this.props.min ? newVal - 1 : this.props.min;
}
this.handleChangeSlider(newVal);
e.preventDefault();
}
render () {
const {min, max, value} = this.props;
......@@ -74,7 +86,7 @@ class CustomSlider extends PureComponent {
console.log("max val: ", max);
return (
<div className='slider custom-labels'>
<div className='slider custom-labels' onWheel={this.onWheel}>
<Slider
min={min}
max={max}
......@@ -83,6 +95,7 @@ class CustomSlider extends PureComponent {
l={value}
onChange={this.handleChangeSlider}
/>
{/* <input type="range" min={min} max={max} value={value} onChange={this.handleChangeSlider} /> */}
<div className='value'>{value}</div>
......
......@@ -4,6 +4,7 @@ import io from "socket.io-client";
import ExperimentView from "./experimentView";
import StudyReview from "./studyView";
// import CanvasGridworldOld from "./gridworldOld";
import Element from "./element.js";
import CustomSlider from "./slider.js";
......@@ -22,6 +23,8 @@ import {FlexibleWidthXYPlot, XAxis, YAxis, Borders,
LineSeries, LineSeriesCanvas,
VerticalBarSeries, VerticalBarSeriesCanvas,
CustomSVGSeries, DiscreteColorLegend, VerticalGridLines} from "react-vis"; // ./3rdParty/
import ListSelection from './listSelection';
import ActionPrediction from './actionPrediction';
export default class Webblocks extends Component {
......@@ -37,10 +40,18 @@ export default class Webblocks extends Component {
tw: false,
tg: false,
na: false,
switching: false},
switching: false,
actionPred: false},
aggregates: [],
showComplete: false,
participants: {},
selectedParticipant: null,
runResults: {},
studyResults: null,
studyMaps: null,
studyTrajs: null,
layout: [
{"w": 18,"h": 8,"x": 0,"y": 0,"i": "sel"},
{"w": 18,"h": 9,"x": 0,"y": 0,"i": "sel"},
{"w": 6,"h": 18,"x": 0,"y": 4,"i": "gridGroundTruth"},
{"w": 6,"h": 18,"x": 6,"y": 4,"i": "gridAgentsBelief"},
{"w": 12,"h": 5,"x": 0,"y": 14,"i": "slider"},
......@@ -50,7 +61,10 @@ export default class Webblocks extends Component {
{"w": 6,"h": 2,"x": 12,"y": 15,"i": "Options"},
{"w": 5,"h": 7,"x": 0,"y": 16,"i": "Desire Beliefs"},
{"w": 9,"h": 7,"x": 5,"y": 16,"i": "Goal Beliefs"},
{"w": 3,"h": 7,"x": 14,"y": 16,"i": "World Beliefs"}
{"w": 2,"h": 7,"x": 12,"y": 24,"i": "World Beliefs"},
{"w": 4,"h": 3,"x": 14,"y": 24,"i": "Participant Selection"},
{"w": 4,"h": 3,"x": 14,"y": 24,"i": "Action Prediction"},
{"w": 12,"h": 28,"x": 0,"y": 20,"i": "studyReview"}
]
}
......@@ -69,18 +83,45 @@ export default class Webblocks extends Component {
this.onWheel = this.onWheel.bind(this);
this.onParticipantSelection = this.onParticipantSelection.bind(this);
this.onCondSelection = this.onCondSelection.bind(this);
this.onChangeCompletePath = this.onChangeCompletePath.bind(this);
}
onChangeCompletePath(e) {
this.setState({
showComplete: !this.state.showComplete,
stepNr: !this.state.showComplete ? Infinity : this.state.stepNr
})
}
onParticipantSelection(e) {
console.log("participant selection: ", e);
this.setState({
selectedParticipant: e.target.value
});
}
onCondSelection(e) {
console.log("conditionSelection: ", e);
this.conditionName = e.target.value;
this.socket.emit("message", this.conditionSrc, JSON.stringify({"selection": {"condition": e.target.value, "participant": this.state.selectedParticipant, "methods": this.state.requests}}));
}
componentDidMount() {
this.socket = io.connect("http://localhost:5000", {transport:["websocket"]});
this.socket.on("connect", function() {
console.log("Connected");
});
this.socket.emit("add_connection", "zmq:5057");
this.socket.emit("add_connection", "zmq:5057"); //For modelInduction communication
this.socket.emit("add_connection", "zmq:5058"); //For goalInferenceStudy
this.socket.emit("message", "zmq:5057", JSON.stringify({"conditionRequest":""}));
this.socket.emit("message", "zmq:5058", JSON.stringify({"get_results":true}));
this.socket.on("update_data", this.update_data);
}
......@@ -88,10 +129,12 @@ export default class Webblocks extends Component {
update_data(data) {
console.log("received data: ", data);
var newState = {...this.state};
if (data.conditions) {
this.setState({
conditions: data.conditions
})
newState.conditions = data.conditions;
// this.setState({
// conditions: data.conditions
// })
this.conditionSrc = data.connection;
}
if (data.runData) {
......@@ -101,13 +144,17 @@ export default class Webblocks extends Component {
newRunResults[key] = data.runData.methodResults[key];
}
this.setState({
newState = {...newState,
// this.setState({
map: {"map": data.runData.map, "targets": data.runData.targets, "goalPos": data.runData.goalPos},
agentPositions: data.runData.agentPositions,
stepNr: 0,
stepNr: this.state.showComplete ? Infinity : 0,
runResults: newRunResults,
visibleList: [],
})
aggregates: [],
selectedParticipant: data.runData.participant
}//)
this.selectedConditionRun = data.runNr;
}
if (data.position_update) {
......@@ -117,17 +164,44 @@ export default class Webblocks extends Component {
let newPositions = this.state.agentPositions.slice();
newPositions[idx] = newPos;
this.setState({
// this.setState({
newState = {...newState,
agentPositions: newPositions,
stepNr: idx
})
}//)
}
if (data.visibles) {
this.setState({
// this.setState({
newState = {...newState,
visibleList: data.visibles
})
}//)
}
if (data.trajectories) {
// this.setState({
newState = {...newState,
aggregates: data.trajectories
}//)
}
if (data.participants) {
console.log("got participant info")
// this.setState({
newState = {...newState,
participants: data.participants
}//)
}
if (data.studyResults) {
newState = {...newState,
studyResults: data.studyResults,
studyMaps: data.mapDetails,
studyTrajs: data.trajs
}
}
this.setState(newState);
}
onSliderChange(value) {
......@@ -143,12 +217,17 @@ export default class Webblocks extends Component {
}
onConditionSelect(condition, runNr) {
this.conditionName = condition;
this.selectedConditionRun = runNr;
this.socket.emit("message", this.conditionSrc, JSON.stringify({"selection": {"condition": condition, "runNr": runNr, "methods": this.state.requests}}));
var playBtn = document.getElementById("togglePlay");
if (playBtn) {
playBtn.innerText = "Replay";
if (runNr) {
this.conditionName = condition;
this.selectedConditionRun = runNr;
this.socket.emit("message", this.conditionSrc, JSON.stringify({"selection": {"condition": condition, "runNr": runNr, "methods": this.state.requests}}));
var playBtn = document.getElementById("togglePlay");
if (playBtn) {
playBtn.innerText = "Replay";
}
} else {
this.conditionName = condition;
this.socket.emit("message", this.conditionSrc, JSON.stringify({"aggregate": {"condition": condition}}));
}
for (var key in this.state.requests) {
......@@ -260,10 +339,6 @@ export default class Webblocks extends Component {
render() {
let {stepNr, map, agentPositions, requests, runResults} = this.state; //, samples, ratingsSamples, ratingsM1, ratingsM2, ratingsM3, ratingsM4} = this.state;
// if (ratings) {
// var ratingObjects =
// })
// }
const colors = {"twg": "blue",
"tw": "orange",
......@@ -291,36 +366,36 @@ export default class Webblocks extends Component {
}
let bars = [];
let goal_bars = [];
let world_bars = [];
var actionPredictions = {};
for (var key in requests) {
if (requests[key] && runResults[key]) {
if (requests[key] && runResults[key] && runResults[key].priorList) {
if (stepNr === Infinity) {
stepNr = runResults[key].priorList.length-1;
}
var bardata = []
for (var desire in runResults[key].priorList[stepNr].desire) {
bardata.push({"x": desire, "y": runResults[key].priorList[stepNr].desire[desire]})
}
bars.push(<VerticalBarSeries key={key} data={bardata} color={colors[key]} />)
}
}
let goal_bars = [];
for (var key in requests) {
if (requests[key] && runResults[key]) {
var bardata = []
bardata = [];
for (var gb in runResults[key].priorList[stepNr].goal) {
bardata.push({"x": gb, "y": runResults[key].priorList[stepNr].goal[gb]})
}
goal_bars.push(<VerticalBarSeries key={key} data={bardata} color={colors[key]} />)
}
}
let world_bars = [];
for (var key in requests) {
if (requests[key] && runResults[key]) {
var bardata = []
bardata = []
for (var wb in runResults[key].priorList[stepNr].world) {
bardata.push({"x": wb, "y": runResults[key].priorList[stepNr].world[wb]})
}
world_bars.push(<VerticalBarSeries key={key} data={bardata} color={colors[key]} />)
}