Commit 519323e2 authored by Bruno López Trigo's avatar Bruno López Trigo

Código do servizo web ExpliClas con todos os pasos básicos requeridos

parent 9fabdfec
......@@ -2,15 +2,6 @@
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/resources/log.xml</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/iosystem/Problem.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/languagerealiser/LanguageRealiser.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/languagerealiser/ClauseGenerator.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/iosystem/XMLParser.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/iosystem/IOImpl.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/src/rulesystem/RuleBuilder.java</file>
<file>file:/home/brilemau/Documents/repos/ExpliClas-TFG/codigo/WekaParser-v2/resources/beer.xml</file>
</group>
<group/>
</open-files>
</project-private>
<h1>AutoExplainable Classifier</h1><h2>Global information</h2><p>There are 8 types of beer: Blanche, Lager, Pilsner, IPA, Stout, Barleywine, Porter and Belgian Strong Ale.</p><p>There may be some confusion among samples related to some types of beer. But among all of them the pair [IPA; Barleywine] is the most confused.</p><h2>Main Solution</h2><p>Beer is type Pilsner because its strength is standard, its color is straw and its bitterness is high.</p><h2></h2>
\ No newline at end of file
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
{
"name": "expliclas",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-router-dom": "^4.2.2",
"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, 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.ico">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Yeseva+One" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Ovo|Yeseva+One" rel="stylesheet">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
import React, { Component } from 'react';
import {BrowserRouter as Router, Route, Redirect} from 'react-router-dom';
import Home from './components/Home';
import Datasets from './components/Datasets';
import Progress from './components/Progress';
import BuildLog from './components/BuildLog';
import Classifier from './components/Classifier';
import Logs from './components/Logs';
import Explanation from './components/Explanation';
class App extends Component {
constructor(props) {
super(props);
this.state = {
ownlog: false,
step: localStorage.getItem('step'),
problem: localStorage.getItem('problem'),
algorithm: localStorage.getItem('algorithm')
}
this.setLogState = this.setLogState.bind(this);
this.setOwnLog = this.setOwnLog.bind(this);
this.setStep = this.setStep.bind(this);
this.setProblemAlgorithm = this.setProblemAlgorithm.bind(this);
this.setProblem = this.setProblem.bind(this);
this.setAlgorithm = this.setAlgorithm.bind(this);
this.clearState = this.clearState.bind(this);
}
setLogState(e) {
fetch('http://localhost:8080/expliclas/token')
.then((response) => {
return response.headers.get("Authorization");
})
.then((token) => {
localStorage.setItem('token', token);
localStorage.setItem('step', 'datasets');
this.setState({
step: 'datasets'
})
})
.catch((error) => {
console.log(error);
});
}
setOwnLog(newlog){
localStorage.setItem('ownlog', newlog);
this.setState({
ownlog: newlog
});
}
setStep(newstep){
localStorage.setItem('step', newstep);
this.setState({
step: newstep
});
}
setProblem(newproblem){
localStorage.setItem('problem', newproblem);
this.setState({
problem: newproblem
})
}
setAlgorithm(newalgorithm){
localStorage.setItem('algorithm', newalgorithm);
this.setState({
algorithm: newalgorithm
});
}
setProblemAlgorithm(newproblem, newalgorithm){
localStorage.setItem('problem', newproblem);
localStorage.setItem('algorithm', newalgorithm);
this.setState({
problem: newproblem,
algorithm: newalgorithm
});
}
clearState(){
localStorage.removeItem('step');
localStorage.removeItem('problem');
localStorage.removeItem('algorithm');
this.setState({
ownlog: false,
step: localStorage.getItem('step'),
problem: localStorage.getItem('problem'),
algorithm: localStorage.getItem('algorithm')
})
}
render() {
if(localStorage.getItem('token')!=null){
var breadcrumb = <Progress ownlog={this.state.ownlog} step={this.state.step} />;
}
var routeHome = <Route path="/" exact strict render = {() => (
localStorage.getItem('token') ? (
<Redirect to="/datasets" />
) : (
<Home setLogState = {this.setLogState} />
)
)} />
var routeDatasets = <Route path="/datasets" exact strict render = {() => (
localStorage.getItem('token') ? (
<Datasets clearState={this.clearState} setOwnLog={this.setOwnLog} setStep={this.setStep} setProblem={this.setProblem} />
) : (
<Redirect to="/" />
)
)} />
var routeBuild = <Route path="/buildlog" exact strict render = {() => (
localStorage.getItem('token') && localStorage.getItem('step') !== "logs"
&& localStorage.getItem('step') !== "classifier" && localStorage.getItem('step') !== "explanation" ? (
<BuildLog setStep={this.setStep} setProblem={this.setProblemAlgorithm} />
) : (
<Redirect to={localStorage.getItem('step')} />
)
)} />
var routeLogs = <Route path="/logs" exact strict render = {() => (
localStorage.getItem('token') && localStorage.getItem('step') !== "buildlog"
&& localStorage.getItem('problem') ? (
<Logs setStep={this.setStep} setAlgorithm={this.setAlgorithm} problem={this.state.problem} />
) : (
<Redirect to={localStorage.getItem('step')} />
)
)} />
var routeClassifier = <Route path="/classifier" exact strict render = {() => (
localStorage.getItem('token') && localStorage.getItem('step') !== "datasets"
&& localStorage.getItem('problem') && localStorage.getItem('algorithm') ? (
<Classifier setStep={this.setStep} problem={this.state.problem} algorithm={this.state.algorithm} />
) : (
<Redirect to={localStorage.getItem('step')} />
)
)} />
var routeExplanation = <Route path="/explanation" exact strict render = {() => (
localStorage.getItem('token') && localStorage.getItem('step') !== "datasets"
&& localStorage.getItem('step') !== "logs" && localStorage.getItem('step') !== "buildlog" ? (
<Explanation setStep={this.setStep} problem={this.state.problem} algorithm={this.state.algorithm} />
) : (
<Redirect to={localStorage.getItem('step')} />
)
)} />
return (
<Router>
<div className="App">
{breadcrumb}
{routeHome}
{routeDatasets}
{routeBuild}
{routeLogs}
{routeClassifier}
{routeExplanation}
</div>
</Router>
);
}
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
import React, { Component } from 'react';
import './css/AddCard.css'
import { withRouter } from "react-router-dom";
class AddCard extends Component {
constructor(){
super();
this.addCard = this.addCard.bind(this);
}
addCard(uploadedFile){
this.props.setOwnLog(true);
this.props.history.push({
pathname: '/buildlog'
});
}
render(){
return(
<div className="col-sm text-center">
<div className="card tarjeta center-block addCard">
<div className="card-body">
<h4 className="card-title">add</h4>
<label className="upload">
<i className="btn fa fa-plus-circle fa-3x"></i>
<input style={{display: 'none'}} onClick={this.addCard}></input>
</label>
</div>
</div>
</div>
);
}
}
export default withRouter(AddCard);
\ No newline at end of file
import React, { Component } from 'react';
import { withRouter } from "react-router-dom";
import FormJ48 from './FormJ48';
import FormRT from './FormRT';
import './css/BuildLog.css';
class BuildLog extends Component {
constructor(props){
super(props);
this.state = {
active: false,
algorithm: ''
};
this.activeDropdown = this.activeDropdown.bind(this);
this.selectValue = this.selectValue.bind(this);
this.props.setStep('buildlog');
console.log(props);
}
componentWillReceiveProps(nextProps) {
this.setState({ file: nextProps.file });
}
activeDropdown(event){
if(!this.state.active){
event.target.parentElement.parentElement.style.height = '200px';
}
else{
event.target.parentElement.parentElement.style.height = '100px';
}
this.setState({
active: !this.state.active
})
}
selectValue(event){
var parent = event.target.parentElement.parentElement.parentElement.children[0];
parent.parentElement.parentElement.style.height = '100px';
this.setState({
active: !this.state.active,
algorithm: event.target.innerHTML
});
document.getElementById('label').innerHTML = event.target.innerHTML;
}
render(){
var classes = this.state.active ? 'dropdown active': 'dropdown';
var form;
if(this.state.algorithm === "J48"){
form = <FormJ48 setProblem={this.props.setProblem} />
}
else if(this.state.algorithm === "RandomTree"){
form = <FormRT setProblem={this.props.setProblem} />
}
return(
<div className="container-fluid gap">
<div className="form-group selector">
<div className={classes}>
<span id="label" className="selLabel" onClick={this.activeDropdown}>Algorithm</span>
<input type="hidden" name="cd-dropdown"></input>
<ul className="dropdown-list">
<li data-value='1' onClick={this.selectValue}>
<span>J48</span>
</li>
<li data-value='2' onClick={this.selectValue}>
<span>RandomTree</span>
</li>
</ul>
</div>
</div>
{form}
</div>
);
}
}
export default withRouter(BuildLog);
\ No newline at end of file
import React, { Component } from 'react';
import { withRouter } from "react-router-dom";
import './css/Classifier.css';
class Classifier extends Component {
constructor(props){
super(props);
this.props.setStep("classifier");
this.state = {
problem: this.props.problem,
algorithm: this.props.algorithm,
log: '',
global: '',
showAtts: false,
showClasses: false,
}
this.getProblemInfo();
this.getLog();
this.getGlobalExpl();
this.attsClick = this.attsClick.bind(this);
this.classesClick = this.classesClick.bind(this);
this.selectLog = this.selectLog.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
problem: nextProps.problem,
algorithm: nextProps.algorithm
});
}
getProblemInfo(){
var url = "http://localhost:8080/expliclas/global/" + this.state.problem;
fetch(url, {
headers: new Headers({
'Authorization': localStorage.getItem('token')
})
})
.then((response) => {
return response.json();
})
.then((data) => {
this.setState({
problemInfo: data
});
});
}
getLog(){
var url = "http://localhost:8080/expliclas/log/" +
this.state.problem + "/" + this.state.algorithm +
"/" + this.state.problem + ".arff." + this.state.algorithm + ".log.txt";
fetch(url, {
headers: new Headers({
'Authorization': localStorage.getItem('token')
})
})
.then((response) => {
return response.json();
})
.then((data) => {
this.setState({
log: data
});
});
}
getGlobalExpl(){
var url = "http://localhost:8080/expliclas/global/" + this.state.problem +
"/" + this.state.algorithm;
fetch(url, {
headers: new Headers({
'Authorization': localStorage.getItem('token')
})
})
.then((response) => {
return response.json();
})
.then((data) => {
this.setState({
global: data
});
});
}
attsClick(){
this.setState({
showAtts: !this.state.showAtts
});
}
classesClick(){
this.setState({
showClasses: !this.state.showClasses
});
}
selectLog(){
this.props.history.push({
pathname: '/explanation'
});
}
render(){
if(this.state.problemInfo!=null && this.state.problemInfo.attribute!=null){
var listAttributes = this.state.problemInfo.attribute.map(function(item) {
return (
<li>
<p>{item.valuetxt}</p>
</li>
);
});
}
var atts = {
display: 'none'
}
var arrowAtts = this.state.showAtts ? "fa fa-chevron-up" : "fa fa-chevron-down";
var arrowClasses = this.state.showClasses ? "fa fa-chevron-up" : "fa fa-chevron-down";
var classes = {
display: 'none'
}
if(this.state.showAtts){
atts = {
display: 'block'
}
}
if(this.state.showClasses){
classes = {
display: 'block'
}
}
if(this.state.problemInfo!=null && this.state.problemInfo.consequent!=null){
var listConsequents = this.state.problemInfo.consequent.map(function(item) {
return (
<li>
<p>{item.text}</p>
</li>
);
});
}
if(this.state.global!=null && this.state.global.explanationClauses!=null){
var phrases = this.state.global.explanationClauses.map(function(item) {
return (
<p>{item}</p>
);
});
}
return(
<div className="container-fluid gap">
<div className="row">
<div className="col-lg-6 col-sm-12 col-12">
<div className="card logcard1">
<h5 className="card-title titlecard"><i className="fa fa-file-text-o"></i> | {this.state.problem + " log"}</h5>
<div className="card-body">
<div className="text-group">
<textarea className="form-control" value={this.state.log.data}>
</textarea>
</div>
</div>
</div>
</div>
<div className="col-lg-6 col-sm-12 col-12">
<div className="card logcard2">
<h5 className="card-title titlecard"><i className="fa fa-font"></i> | {this.state.problem + " explanation"}</h5>
<div className="card-body">
<div className="row col-list">
<div className="col-12 col-sm-12 col-md-6 t1">
<div className="col-head text-center" onClick={this.attsClick}>
<h2>Attributes <i className={arrowAtts}></i></h2>
</div>
<ul className="list-unstyled" style={atts}>
{listAttributes}
</ul>
</div>
<div className="col-12 col-sm-12 col-md-6 t2">
<div className="col-head text-center" onClick={this.classesClick}>
<h2>Classes <i className={arrowClasses}></i></h2>
</div>
<ul className="list-unstyled" style={classes}>
{listConsequents}
</ul>
</div>
</div>
<div className="row col-list">
<div className="col-12 t3">
<div className="col-head text-center">
<h2>Global explanation</h2>
</div>
<div className="explanation">
{phrases}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="row separator">
<div className="col-12 text-center">
<button type="button" className="btn btn-default btn-plain" onClick={this.selectLog}>Next</button>
</div>
</div>
</div>
);
}
}
export default withRouter(Classifier);
\ No newline at end of file
import React, { Component } from 'react';
import './css/DatasetCard.css'
import { withRouter } from "react-router-dom";
class DatasetCard extends Component {
constructor(props){
super(props);
this.state = {
name: this.props.name,
type: this.props.type
}
this.selectProblem = this.selectProblem.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
name: nextProps.name,
type: nextProps.type
});
}
selectProblem(event){
this.props.setOwnLog(false);
this.props.setProblem(this.state.name);
this.props.history.push({
pathname: '/logs'
});
}
render(){
return(
<div className="col-sm text-center" key={this.state.name}>
<div className="card tarjeta center-block">
<div id={this.state.type} className="card-body">