Commit e62d5ba7 authored by Bruno López Trigo's avatar Bruno López Trigo

Engadido framework material a interface

parent 30c1515f
......@@ -276,7 +276,7 @@ public class ClassifierManagerImpl implements ClassifierManager {
configFile = new File(this.BASE + dataset + "/" + dataset + "-" + lang + ".json");
break;
}
treeFile = new File(location);
if (!treeFile.exists()) {
......@@ -293,16 +293,15 @@ public class ClassifierManagerImpl implements ClassifierManager {
break;
}
}
treeFile = new File(location);
if (!treeFile.exists()) {
throw new NotFoundEx("Tree not found");
}
DatasetConfig config = this.mapper.readConfigJSON(configFile);
Node root = this.mapper.readTreeJSON(treeFile);
this.treeBuilder = new TreeBuilder();
......@@ -315,42 +314,54 @@ public class ClassifierManagerImpl implements ClassifierManager {
@Override
public Classification classify(String token, String dataset, String algorithm, String lang, Instance instance) throws NotFoundEx, FormatEx, IOException {
File configFile = null;
DatasetConfig config = null;
Node root;
Node root = null;
if (token.isEmpty()) {
switch (lang) {
case "en":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + ".json"));
break;
case "es":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + "-es.json"));
break;
case "gl":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + "-gl.json"));
break;
}
switch (lang) {
case "en":
configFile = new File(this.BASE + dataset + "/" + dataset + ".json");
break;
case "es":
configFile = new File(this.BASE + dataset + "/" + dataset + "-es.json");
break;
case "gl":
configFile = new File(this.BASE + dataset + "/" + dataset + "-gl.json");
break;
}
if (configFile.exists()) {
config = this.mapper.readConfigJSON(configFile);
root = this.mapper.readTreeJSON(new File(this.BASE + dataset + "/" + algorithm + "/tree.json"));
} else {
switch (lang) {
case "en":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + ".json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + ".json");
break;
case "es":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-es.json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-es.json");
break;
case "gl":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-gl.json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-gl.json");
break;
}
if(!configFile.exists()){
throw new NotFoundEx("Classifier not found");
}
config = this.mapper.readConfigJSON(configFile);
root = this.mapper.readTreeJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + algorithm + "/tree.json"));
}
for (Map.Entry<String, Object> entry : instance.getValues().entrySet()) {
for (Map.Entry<String, Object> entry
: instance.getValues()
.entrySet()) {
if (config.getAttributeById(entry.getKey()) == null) {
throw new FormatEx("Wrong instance format");
}
}
this.treeInterpreter = new TreeInterpreter(root);
......@@ -361,37 +372,48 @@ public class ClassifierManagerImpl implements ClassifierManager {
@Override
public ArrayList<Classification> classify(String token, String dataset, String algorithm, String lang, Instance instance, double percentage) throws NotFoundEx, FormatEx, IOException {
DatasetConfig config = null;
Node root;
File configFile = null;
Node root = null;
if (token.isEmpty()) {
switch (lang) {
case "en":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + ".json"));
break;
case "es":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + "-es.json"));
break;
case "gl":
config = this.mapper.readConfigJSON(new File(this.BASE + dataset + "/" + dataset + "-gl.json"));
break;
}
switch (lang) {
case "en":
configFile = new File(this.BASE + dataset + "/" + dataset + ".json");
break;
case "es":
configFile = new File(this.BASE + dataset + "/" + dataset + "-es.json");
break;
case "gl":
configFile = new File(this.BASE + dataset + "/" + dataset + "-gl.json");
break;
}
if (configFile.exists()) {
config = this.mapper.readConfigJSON(configFile);
root = this.mapper.readTreeJSON(new File(this.BASE + dataset + "/" + algorithm + "/tree.json"));
} else {
switch (lang) {
case "en":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + ".json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + ".json");
break;
case "es":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-es.json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-es.json");
break;
case "gl":
config = this.mapper.readConfigJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-gl.json"));
configFile = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + dataset + "-gl.json");
break;
}
if(!configFile.exists()){
throw new NotFoundEx("Classifier not found");
}
config = this.mapper.readConfigJSON(configFile);
root = this.mapper.readTreeJSON(new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + algorithm + "/tree.json"));
}
for (Map.Entry<String, Object> entry : instance.getValues().entrySet()) {
for (Map.Entry<String, Object> entry
: instance.getValues()
.entrySet()) {
if (config.getAttributeById(entry.getKey()) == null) {
throw new FormatEx("Wrong instance format");
}
......@@ -408,14 +430,14 @@ public class ClassifierManagerImpl implements ClassifierManager {
File input;
input = new File(this.BASE + dataset + "/" + algorithm + "/" + dataset + ".arff." + algorithm + ".log.txt");
if(!input.exists()){
input = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + algorithm + "/" + dataset + ".arff." + algorithm + ".log.txt");
if (!input.exists()) {
input = new File(this.BASE + "tmp/" + token + "/" + dataset + "/" + algorithm + "/" + dataset + ".arff." + algorithm + ".log.txt");
}
if(!input.exists()){
if (!input.exists()) {
throw new NotFoundEx("Matrix not found");
}
this.matrixBuilder = new MatrixBuilder(input);
return this.matrixBuilder.readMatrix();
......
#Generated by Maven
#Wed Oct 17 18:50:43 CEST 2018
#Fri Oct 19 18:43:34 CEST 2018
version=1.0
groupId=brunolopez
artifactId=expliclas-api
This diff is collapsed.
......@@ -4,6 +4,8 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^3.2.2",
"@material-ui/icons": "^3.0.1",
"react": "^16.3.2",
"react-d3-tree": "^1.11.0",
"react-dom": "^16.3.2",
......
......@@ -2,13 +2,13 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"/>
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png">
<link href="https://fonts.googleapis.com/css?family=Mali|Roboto" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<title>ExpliClas</title>
</head>
......
......@@ -16,12 +16,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import Routes from './components/global/Routes';
import LanguageSelector from './components/global/LanguageSelector';
import {withRouter} from 'react-router-dom';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import {LABELS} from './language';
export default class App extends Component {
const theme = createMuiTheme({
typography: {
useNextVariants: true,
},
});
class App extends Component {
constructor(){
super();
this.state={
......@@ -31,24 +38,33 @@ export default class App extends Component {
}
};
this.handleLanguage = this.handleLanguage.bind(this);
this.goToClassifiers = this.goToClassifiers.bind(this);
}
handleLanguage(event){
const value = event.target.value;
handleLanguage(id){
this.setState(prevState => ({
language: {
...prevState.language,
id: value
id
}
}))
}
goToClassifiers(dataset){
this.setState({
dataset
});
this.props.history.push("classifiers");
}
render(){
return(
<Fragment>
<LanguageSelector language={this.state.language} handleChange={this.handleLanguage}></LanguageSelector>
<Routes language={this.state.language}></Routes>
</Fragment>
<MuiThemeProvider theme={theme}>
<Routes language={this.state.language} handleLanguageChange={this.handleLanguage} handleDataset={this.goToClassifiers} dataset={this.state.dataset}></Routes>
</MuiThemeProvider>
);
}
}
\ No newline at end of file
}
export default withRouter(App);
\ No newline at end of file
......@@ -15,6 +15,7 @@ export default class CenteredTree extends Component {
},
collapsible: true
};
//this.updateTree = this.updateTree.bind(this);
}
componentDidMount() {
......@@ -28,9 +29,13 @@ export default class CenteredTree extends Component {
}
componentWillReceiveProps(){
this.forceUpdate();
}
render(){
return(
<div className="treeContainer" ref={tc => (this.treeContainer = tc)}>
<div id="treeContainer" className="treeContainer" ref={tc => (this.treeContainer = tc)}>
{this.state.translate && this.props.treeData ?
<Tree
ref="tree"
......
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import Typography from '@material-ui/core/Typography';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Divider from '@material-ui/core/Divider';
import { Input } from '@material-ui/core';
const styles = theme => ({
root: {
width: '100%',
marginTop: 20
},
heading: {
fontSize: theme.typography.pxToRem(15),
flexBasis: '33.33%',
flexShrink: 0,
},
list: {
backgroundColor: theme.palette.background.paper
},
secondaryHeading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
});
class ControlledExpansionPanels extends React.Component {
constructor(props){
super(props);
this.state = {
expanded: null,
};
this.handleChangeAtt = this.handleChangeAtt.bind(this);
}
componentDidMount() {
let instance = {
values: {
}
}
if(this.props.attributes){
this.props.attributes.map(att => {
return instance.values[att.id] = 0
})
}
this.setState({instance})
}
handleChange = panel => (event, expanded) => {
this.setState({
expanded: expanded ? panel : false
});
};
handleChangeAtt(event){
var instance = this.state.instance;
instance.values[event.target.id] = event.target.value;
this.setState(
{instance}
);
this.props.classify(instance);
}
render() {
const { classes } = this.props;
const { expanded } = this.state;
return (
<div className={classes.root}>
{this.props.attributes ?
this.props.attributes.map(att => {
return(
<ExpansionPanel key={att.name} expanded={expanded === att.name} onChange={this.handleChange(att.name)}>
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
<Typography className={classes.heading}>{att.name}</Typography>
{this.state.instance ?
<Input
id={att.id}
placeholder={att.name}
value={this.state.instance.values[att.id]}
onChange={this.handleChangeAtt}
className={classes.input}
inputProps={{
'aria-label': 'Description',
}}/> : ''}
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<Typography>
...
</Typography>
</ExpansionPanelDetails>
</ExpansionPanel>);
})
: ''}
{this.props.attributes ?
<List component="nav">
<ListItem>
<ListItemText primary="Margin error" />
<Input
id='margin'
placeholder='margin error percentage'
className={classes.input}
inputProps={{
'aria-label': 'Description',
}}/>
</ListItem>
<Divider />
</List>
: ''}
{this.props.consequents ?
<List component="nav">
{this.props.consequents.map(conseq => {
return(
<Fragment key={conseq.name}>
<ListItem button>
<ListItemText primary={conseq.name} />
</ListItem>
<Divider />
</Fragment>
)
})}
</List> : ''}
</div>
)
}
}
ControlledExpansionPanels.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ControlledExpansionPanels);
import React, { Component } from 'react';
import '../css/ClassifierPanel.css';
export default class LeftPanel extends Component {
constructor(props){
super(props);
this.state = {};
}
render(){
return(
<div className='left-panel'>
<div className='panel-title'>
{this.props.config.dataset}
</div>
<div className='attributes-title'>
{this.props.language.labels[this.props.language.id].attributes}
</div>
<div className='attributes-panel'>
{this.props.config.attributes.map(att => {
return <div key={att.name} className='item bottom-green'>{att.name}</div>
})}
</div>
<div className='consequents-title'>
{this.props.language.labels[this.props.language.id].consequents}
</div>
<div className='consequents-panel'>
{this.props.config.consequents.map(conseq => {
return <div key={conseq.name} className='item bottom-red'>{conseq.name}</div>
})}
</div>
</div>
);
}
}
\ No newline at end of file
import React, {Component} from 'react';
import React, {Component, Fragment} from 'react';
import '../css/Matrix.css';
export default class Matrix extends Component {
constructor(props){
super(props);
}
render(){
return(
<div className="matrixContainer">
{this.props.consequents ?
<div className="row">
<div className="column"></div>
{this.props.consequents.map(conseq => {
return <div key={conseq.name} className="column">{conseq.name}</div>
return <div key={conseq.name} className="column conseq-column">{conseq.name}</div>
})}
</div> : ''}
{this.props.matrix ?
this.props.matrix.data.map(function(row, index){
var sum = this.props.sum[index];
var rowIndex = index;
var consequents = this.props.consequents;
return (
<div key={index} className="row">
{row.map(function(column, index){
var color = - (column/sum * 255) + 255;
var background = 'rgb(' + color + ',' + color + ',' + color + ')';
var font = color < 100 ? 'white' : 'black';
return <div key={index} className="column" style={{backgroundColor: background, color: font}}>{column}</div>
}, sum)}
if(index === 0){
return(
<Fragment key={index}>
<div className="column conseq-column">{consequents[rowIndex].name}</div>
<div className="column" style={{backgroundColor: background, color: font}}>{column}</div>
</Fragment>
)
}
else{
return <div key={index} className="column" style={{backgroundColor: background, color: font}}>{column}</div>
}
}, sum, rowIndex, consequents)}
</div>)
}, this)
: ''}
......
import React, { Component } from 'react';
import '../css/ClassifierPanel.css';
import '../css/Matrix.css';
import CenteredTree from './CenteredTree';
import Matrix from './Matrix';
export default class RightPanel extends Component {
constructor(props){
super(props);
this.state = {
option: 'tree'
};
this.handleOptionChange = this.handleOptionChange.bind(this);
}
handleOptionChange(event){
this.setState({
option: event.target.id
})
}
render(){
return(
<div className='right-panel'>
<div className='right-panel-bar'>
<div onClick={this.handleOptionChange} id='tree' className={this.state.option === 'tree' ? 'button-bar selected': 'button-bar'}>
Tree
</div>
<div onClick={this.handleOptionChange} id='matrix' className={this.state.option === 'matrix' ? 'button-bar selected': 'button-bar'}>
Matrix
</div>
</div>
{this.props.treeData && this.state.option === 'tree' ?
<CenteredTree treeData={this.props.treeData}></CenteredTree>:''
}
{this.props.matrix && this.state.option === 'matrix' ?
<Matrix matrix={this.props.matrix} sum={this.props.sum} consequents={this.props.consequents}></Matrix>:''
}
</div>
);
}
}
\ No newline at end of file
.treeContainer{
height: 90%;
border-style: solid;
border-width: 1px;
width: 100%;
height: 100%;
}
.nodeNameBase{
......
.matrixContainer{
margin: auto;
margin-top: 30px;
width: 90%;
margin-top: 10px;