1
0
mirror of https://github.com/gsi-upm/soil synced 2025-08-24 12:02:20 +00:00

Squashed 'soil/web/' content from commit 4dcd0fc

git-subtree-dir: soil/web
git-subtree-split: 4dcd0fcb3d
This commit is contained in:
J. Fernando Sánchez
2018-12-07 20:30:24 +01:00
commit 8fec544772
24 changed files with 3386 additions and 0 deletions

431
templates/css/main.css Normal file
View File

@@ -0,0 +1,431 @@
html, body {
height: 100%;
}
.carousel {
height: calc(100% - 150px);
}
.carousel-inner {
height: calc(100% - 50px) !important;
}
.carousel-inner .item,
.carousel-inner .item .container-fluid {
height: 100%;
}
.navbar {
box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, .2)
}
.nav.navbar-right {
margin-right: 10px !important;
}
.nav.navbar-right a {
outline: none !important;
}
.dropdown-menu > li > a:hover {
background-color: #d4d3d3;
cursor: pointer;
}
.wrapper-heading {
display: flex;
flex-direction: row;
padding: 0 !important;
}
.soil_logo {
padding: 0 !important;
border-left: none !important;
border-right: none !important;
display: flex;
justify-content: flex-end;
background-color: rgb(88, 88, 88);
}
.soil_logo > img {
max-height: 100%;
}
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #999;
stroke-opacity: .6;
}
svg#graph, #configuration {
background-color: white;
margin-top: 15px;
border-style: double;
border-color: rgba(0, 0, 0, 0.35);
border-radius: 5px;
padding: 0px;
}
#timeline {
padding: 0;
margin-top: 20px;
}
#configuration {
margin-top: 15px;
padding: 15px;
border-left: none !important;
overflow: auto;
display: flex;
flex-direction: column;
align-items: inherit;
justify-content: space-evenly;
}
button {
outline: none !important;
}
.btn-toolbar.controls {
position: absolute;
right: 0;
}
.controls > .btn {
margin-left: 10px !important;
}
button.pressed {
background-color: rgb(167, 242, 168);
-webkit-animation: background 1s cubic-bezier(1,0,0,1) infinite;
animation: background 1s cubic-bezier(1,0,0,1) infinite;
cursor: default !important;
}
@-webkit-keyframes background {
50% { background-color: #dddddd; }
100% { background-color: rgb(167, 242, 168); }
}
@keyframes background {
50% { background-color: #dddddd; }
100% { background-color: rgb(167, 242, 168); }
}
#slider3 {
background: repeating-linear-gradient( 90deg, white 27px, white 30px, #fff 32px, #aaa 33px );
background-color: white;
}
hr {
margin-top: 15px !important;
margin-bottom: 15px !important;
width: 100%;
}
#update .config-item {
margin-top: 15px !important;
}
/** LOADER **/
#load {
position: absolute;
font-weight: bold;
}
#load.loader {
border: 5px solid #f3f3f3;
border-radius: 50%;
border-top: 5px solid #3498db;
border-bottom: 5px solid #3498db;
width: 30px;
height: 30px;
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
position: absolute;
}
#load:before {
content: 'No file'
}
#load.loader:before {
content: '' !important;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/** ALERT **/
.alert-danger {
position: absolute;
margin-top: 20px;
margin-left: 5px;
}
/** FILE BROWSER **/
.custom-file {
position: relative;
display: inline-block;
width: 100%;
height: 35px;
margin-bottom: 0;
cursor: pointer;
}
.custom-file-input {
min-width: 14rem;
max-width: 100%;
height: 35px;
margin: 0;
filter: alpha(opacity=0);
opacity: 0;
}
.custom-file-control {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 5;
height: 35px;
padding: .5rem 1rem;
overflow: hidden;
line-height: 1.5;
color: #464a4c;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #fff;
border: 1px solid rgba(0,0,0,.15);
border-radius: .25rem;
}
.custom-file-control::before {
content: "Browse";
position: absolute;
top: -1px;
right: -1px;
bottom: -1px;
z-index: 6;
display: block;
height: 35px;
padding: .5rem 1rem;
line-height: 1.5;
color: #464a4c;
background-color: #eceeef;
border: 1px solid rgba(0,0,0,.15);
border-radius: 0 .25rem .25rem 0;
}
.custom-file-control::after {
content: attr(data-content);
}
/** TABLES **/
#percentTable {
height: 150px !important;
width: 100% !important;
}
#percentTable tr {
padding: 5px 2px;
}
#percentTable .no-data-table {
font-size: 10px;
justify-content: center;
align-items: center;
display: flex;
flex: 1;
height: 100%;
font-weight: 100;
}
hr {
margin-top: 15px !important;
margin-bottom: 15px !important;
}
#info-graph {
width: 70% !important;
}
.logo {
margin-top: -40px;
position: absolute;
right: 15px;
}
/** SLIDER **/
.speed-slider,
.link-distance-slider {
padding: 0 10px !important;
margin-top: 5px !important;
width: 100% !important;
}
.slider {
width: 100% !important;
}
.slider .slider-selection {
background-image: linear-gradient(to bottom,
rgba(36, 110, 162, 0.5) 0%,
rgba(3, 169, 224, 0.5) 100%) !important;
}
.slider-disabled .slider-selection {
opacity: 0.5;
}
.slider.slider-disabled .slider-track {
cursor: default !important;
}
table#speed,
table#link-distance {
width: 100%;
}
table#speed .min,
table#speed .max,
table#link-distance .min,
table#link-distance .max {
font-weight: normal !important;
}
/* Console */
#update, .console, .soil_logo {
padding: 10px 15px;
height: 135px;
border: 1px solid #585858;
}
#update {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.container-fluid.fixed {
padding-top: 15px;
}
.console {
background-color: rgb(88,88,88);
font-family: "Ubuntu Mono";
font-size: 14px;
font-weight: 500;
color: white;
line-height: 14px;
overflow: auto;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
width: 100%;
}
.console::-webkit-scrollbar {
width: 6px;
background-color: #F5F5F5;
}
.console::-webkit-scrollbar-thumb {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #555;
}
/** FORMS **/
.checkbox {
margin-left: 10px !important;
}
#wrapper-settings {
padding: 15px !important;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
#wrapper-settings.none {
font-weight: bold;
display: flex;
flex: 1;
justify-content: center;
align-items: center;
}
#wrapper-settings.none:before {
content: 'No configuration provided';
}
#wrapper-settings .btn-group button:focus {
background: initial;
border-color: #ccc;
}
#wrapper-settings .btn-group button {
font-size: xx-small;
padding: 3px 6px;
}
.item.settings .container-fluid {
padding-top: 10px !important;
}
#wrapper-settings::-webkit-scrollbar {
width: 6px;
background-color: #F5F5F5;
}
#wrapper-settings::-webkit-scrollbar-thumb {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #ccc;
}
/** CHARTS **/
#charts {
height: 100%;
padding-left: 0 !important;
padding-top: 15px !important;
padding-bottom: 15px !important;
}
.chart {
height: 50%;
}
.chart.no-data:before {
content: 'No data';
position: absolute;
font-size: 10px;
padding-bottom: 35px;
}
.chart.no-data {
font-weight: bold;
display: flex;
flex: 1;
justify-content: center;
align-items: center;
}
/** MODAL **/
.modal-footer,
.modal-header {
border: none !important;
}

View File

@@ -0,0 +1,72 @@
#slider3 {
margin: 0 0 10px 0;
}
.d3-slider {
position: relative;
font-family: Verdana,Arial,sans-serif;
font-size: 1.1em;
border: 1px solid #aaaaaa;
z-index: 2;
}
.d3-slider-horizontal {
height: 40px;
}
.d3-slider-range {
background:#2980b9;
left:0px;
right:0px;
height: 0.8em;
position: absolute;
}
.d3-slider-handle {
position: absolute;
width: .8em;
height: 48px;
border: 1px solid #d3d3d3;
border-radius: 4px;
background: #eee;
background: linear-gradient(to bottom, #eee 0%, #ddd 100%);
z-index: 3;
}
.d3-slider-handle:hover {
border: 1px solid #999999;
}
.d3-slider-horizontal .d3-slider-handle {
top: -.3em;
margin-left: -.4em;
}
.d3-slider-axis {
position: relative;
z-index: 1;
}
.d3-slider-axis-bottom {
top: 38px;
}
.d3-slider-axis-right {
left: .8em;
}
.d3-slider-axis path {
stroke-width: 0;
fill: none;
}
.d3-slider-axis line {
fill: none;
stroke: #aaa;
shape-rendering: crispEdges;
stroke-dasharray: 2;
}
.d3-slider-axis text {
font-size: 11px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 MiB

140
templates/img/logo_gsi.svg Normal file
View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="360"
height="330"
id="svg3752"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="logo_gsi_nuevo.svg"
inkscape:export-filename="/home/cif/GoogleDrive/docs/gsi/corporativo/logos-fondos/logos/logo_gsi_nuevo_740_671.png"
inkscape:export-xdpi="185.6273"
inkscape:export-ydpi="185.6273">
<defs
id="defs3754">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3760" />
<inkscape:perspective
id="perspective3730"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<filter
inkscape:collect="always"
id="filter3757"
x="-0.4412556"
width="1.8825113"
y="-0.4412556"
height="1.8825113"
color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.91928251"
id="feGaussianBlur3759" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="187.12284"
inkscape:cy="78.411806"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata3757">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-722.36218)">
<g
style="display:inline"
id="g3761"
transform="matrix(2.2932314,0,0,2.2932314,-744.72199,6804.6985)">
<g
transform="translate(-161.76758,3.3349672)"
id="g2940">
<g
id="g2922">
<g
transform="translate(-79.72168,-3162.9998)"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#00a9e0;fill-opacity:1;stroke:none;font-family:Calibri;-inkscape-font-specification:Calibri Bold"
id="flowRoot4140">
<path
d="m 688.88086,587.87773 c -6e-5,3.71096 -0.70806,6.98244 -2.12402,9.81446 -1.36724,2.83204 -3.32037,5.2002 -5.85938,7.10449 -2.53911,1.9043 -5.54203,3.32031 -9.00879,4.24805 -3.46683,0.97656 -7.22659,1.46484 -11.2793,1.46484 -2.44143,0 -4.78517,-0.19531 -7.03125,-0.58594 -2.19728,-0.34179 -4.17482,-0.78125 -5.93261,-1.31836 -1.75783,-0.58593 -3.22267,-1.17187 -4.39453,-1.75781 -1.17189,-0.58593 -2.02638,-1.12304 -2.56348,-1.61133 -0.53712,-0.5371 -0.95215,-1.34277 -1.24512,-2.41699 -0.29297,-1.12304 -0.43946,-2.75878 -0.43945,-4.90723 -10e-6,-1.416 0.0488,-2.53904 0.14648,-3.36914 0.0977,-0.87889 0.24414,-1.56248 0.43946,-2.05078 0.1953,-0.53709 0.43944,-0.87889 0.73242,-1.02539 0.29296,-0.19529 0.65917,-0.29295 1.09863,-0.29297 0.5371,2e-5 1.31835,0.3174 2.34375,0.95215 1.07421,0.58595 2.39257,1.24513 3.95508,1.97754 1.56248,0.73244 3.36912,1.41603 5.41992,2.05078 2.09959,0.63478 4.46775,0.95216 7.10449,0.95215 1.66013,10e-6 3.12497,-0.17089 4.39454,-0.5127 1.31832,-0.34178 2.44137,-0.83006 3.36914,-1.46484 0.97652,-0.63475 1.70894,-1.44041 2.19726,-2.41699 0.48825,-0.97655 0.73239,-2.09959 0.73242,-3.36914 -3e-5,-1.46482 -0.4639,-2.70994 -1.3916,-3.73535 -0.87894,-1.0742 -2.07523,-2.00193 -3.58887,-2.78321 -1.46487,-0.78122 -3.14944,-1.51364 -5.05371,-2.19726 -1.85549,-0.68357 -3.7842,-1.4404 -5.78613,-2.27051 -1.95314,-0.83005 -3.88185,-1.78219 -5.78613,-2.85645 -1.85548,-1.07418 -3.54005,-2.39254 -5.05371,-3.95507 -1.46486,-1.56246 -2.66114,-3.44235 -3.58887,-5.63965 -0.87891,-2.19722 -1.31837,-4.83394 -1.31836,-7.91016 -10e-6,-3.12494 0.61035,-5.98139 1.83106,-8.56933 1.22069,-2.63666 2.9785,-4.88275 5.27343,-6.73829 2.29491,-1.8554 5.07811,-3.29582 8.34961,-4.32128 3.32029,-1.02532 7.03122,-1.53802 11.13281,-1.53809 2.05075,7e-5 4.02829,0.14656 5.93262,0.43945 1.95309,0.29304 3.7109,0.65925 5.27344,1.09864 1.56245,0.43952 2.88081,0.9278 3.95508,1.46484 1.07417,0.48835 1.831,0.9278 2.27051,1.31836 0.48823,0.34186 0.83002,0.70807 1.02539,1.09863 0.19526,0.34186 0.34174,0.78132 0.43945,1.31836 0.0976,0.48835 0.17085,1.12311 0.21973,1.9043 0.0976,0.73248 0.14643,1.66022 0.14648,2.7832 -5e-5,1.31842 -0.0489,2.39264 -0.14648,3.22266 -0.0489,0.83013 -0.17095,1.48931 -0.36622,1.97754 -0.14653,0.48833 -0.36626,0.83013 -0.65918,1.02539 -0.29301,0.14654 -0.63481,0.21978 -1.02539,0.21972 -0.4395,6e-5 -1.12309,-0.24408 -2.05078,-0.73242 -0.92778,-0.53705 -2.09965,-1.09858 -3.51562,-1.68457 -1.36723,-0.58588 -2.97856,-1.12299 -4.83399,-1.61133 -1.80667,-0.53705 -3.88187,-0.8056 -6.22558,-0.80566 -1.66019,6e-5 -3.10062,0.17096 -4.32129,0.51269 -1.22073,0.34186 -2.22171,0.83014 -3.00293,1.46485 -0.78128,0.63482 -1.36721,1.39166 -1.75781,2.27051 -0.39065,0.83013 -0.58596,1.73345 -0.58594,2.70996 -2e-5,1.51372 0.46384,2.78325 1.3916,3.80859 0.92771,1.02544 2.14841,1.92876 3.66211,2.70996 1.51364,0.7813 3.22262,1.51372 5.12695,2.19727 1.95309,0.68363 3.90622,1.44047 5.85938,2.27051 2.00191,0.78129 3.95503,1.70902 5.85937,2.7832 1.95308,1.07425 3.68648,2.39261 5.2002,3.95508 1.51362,1.56253 2.73432,3.44241 3.66211,5.63964 0.92768,2.14847 1.39154,4.71194 1.3916,7.69043"
style="font-size:150px;fill:#00a9e0;font-family:Calibri;-inkscape-font-specification:Calibri Bold"
id="path3806" />
<path
d="m 721.10742,606.33477 c -3e-5,0.48828 -0.14651,0.92773 -0.43945,1.31836 -0.293,0.34179 -0.80569,0.63476 -1.53809,0.8789 -0.68362,0.24414 -1.61135,0.41504 -2.7832,0.5127 -1.1719,0.14648 -2.66115,0.21972 -4.46777,0.21972 -1.80666,0 -3.29592,-0.0732 -4.46778,-0.21972 -1.17189,-0.0977 -2.12403,-0.26856 -2.85644,-0.5127 -0.68361,-0.24414 -1.17189,-0.53711 -1.46485,-0.8789 -0.29297,-0.39063 -0.43946,-0.83008 -0.43945,-1.31836 l 0,-65.18555 c -10e-6,-0.48821 0.14648,-0.90325 0.43945,-1.24512 0.29296,-0.39055 0.78124,-0.70794 1.46485,-0.95215 0.73241,-0.2929 1.68455,-0.51262 2.85644,-0.65918 1.17186,-0.14641 2.66112,-0.21965 4.46778,-0.21972 1.80662,7e-5 3.29587,0.0733 4.46777,0.21972 1.17185,0.14656 2.09958,0.36628 2.7832,0.65918 0.7324,0.24421 1.24509,0.5616 1.53809,0.95215 0.29294,0.34187 0.43942,0.75691 0.43945,1.24512 l 0,65.18555 m 1.3916,-87.45118 c -3e-5,3.71103 -0.75686,6.2745 -2.2705,7.69043 -1.5137,1.4161 -4.32132,2.12411 -8.42286,2.12403 -4.1504,8e-5 -6.95802,-0.68352 -8.42285,-2.05078 -1.41602,-1.36711 -2.12403,-3.83293 -2.12402,-7.39747 -10e-6,-3.71084 0.73241,-6.27431 2.19726,-7.69042 1.51367,-1.46475 4.34569,-2.19717 8.4961,-2.19727 4.10154,1e-4 6.88474,0.70811 8.34961,2.12402 1.46481,1.36729 2.19723,3.8331 2.19726,7.39746"
style="font-size:150px;fill:#00a9e0;font-family:Calibri;-inkscape-font-specification:Calibri Bold"
id="path3808" />
</g>
<g
transform="matrix(1,0,0,1.1503876,-79.72168,-3243.7762)"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#00a9e0;fill-opacity:1;stroke:none;font-family:Calibri;-inkscape-font-specification:Calibri Bold"
id="flowRoot2914">
<path
d="m 633.80273,545.54375 c -6e-5,2.34381 -0.26862,4.07721 -0.80566,5.2002 -0.53718,1.1231 -1.19635,1.68462 -1.97754,1.68457 l -7.69043,0 c 1.07416,1.17193 1.831,2.5147 2.27051,4.02832 0.48822,1.46489 0.73236,3.00297 0.73242,4.61425 -6e-5,3.80864 -0.63482,7.20219 -1.9043,10.18067 -1.26958,2.92972 -3.10064,5.41995 -5.49316,7.4707 -2.3438,2.00198 -5.20024,3.54007 -8.56934,4.61426 -3.32035,1.02541 -7.03128,1.53811 -11.13281,1.53808 -2.09964,3e-5 -4.10159,-0.24411 -6.00586,-0.73242 -1.90432,-0.53708 -3.36916,-1.14743 -4.39453,-1.83105 -0.58596,0.63479 -1.12307,1.39162 -1.61133,2.27051 -0.43947,0.87893 -0.6592,1.85549 -0.65918,2.92968 -2e-5,1.41604 0.61033,2.58791 1.83106,3.51563 1.26951,0.87892 3.02732,1.3672 5.27344,1.46484 l 15.89355,0.58594 c 3.71089,0.1465 7.00679,0.68361 9.8877,1.61133 2.92963,0.87892 5.37103,2.14845 7.32421,3.80859 2.00189,1.61134 3.51556,3.56446 4.54102,5.85938 1.07415,2.29492 1.61126,4.90722 1.61133,7.83691 -7e-5,3.22265 -0.70808,6.24999 -2.12403,9.08203 -1.41607,2.88085 -3.5401,5.37108 -6.37207,7.47071 -2.83208,2.09958 -6.39653,3.75974 -10.69336,4.98046 -4.24809,1.22068 -9.22855,1.83103 -14.9414,1.83106 -5.56644,-3e-5 -10.32717,-0.43948 -14.28223,-1.31836 -3.90626,-0.87893 -7.12892,-2.09963 -9.66797,-3.66211 -2.49024,-1.56252 -4.32129,-3.4424 -5.49316,-5.63965 -1.12305,-2.14845 -1.68457,-4.51661 -1.68457,-7.10449 0,-1.61134 0.19531,-3.14942 0.58594,-4.61426 0.43945,-1.46485 1.0498,-2.88086 1.83105,-4.24805 0.83007,-1.31835 1.83105,-2.58788 3.00293,-3.80859 1.17187,-1.2207 2.51464,-2.39257 4.02832,-3.51562 -2.09962,-1.12304 -3.73536,-2.63671 -4.90723,-4.54102 -1.12305,-1.95311 -1.68457,-4.07713 -1.68457,-6.37207 0,-2.88084 0.65918,-5.49314 1.97754,-7.83691 1.31835,-2.39255 3.02734,-4.54099 5.12696,-6.44532 -1.709,-1.70895 -3.07618,-3.75973 -4.10157,-6.15234 -1.02539,-2.39254 -1.53809,-5.37105 -1.53808,-8.93555 -10e-6,-3.80854 0.65917,-7.20209 1.97754,-10.18066 1.36718,-3.02728 3.24706,-5.56634 5.63965,-7.61719 2.39256,-2.09954 5.249,-3.68645 8.56933,-4.76074 3.32029,-1.12298 6.98239,-1.6845 10.98633,-1.68457 2.05075,7e-5 4.00387,0.12214 5.85937,0.36621 1.90426,0.24421 3.66207,0.58601 5.27344,1.02539 l 20.72754,0 c 0.83001,7e-5 1.48919,0.53718 1.97754,1.61133 0.53704,1.07428 0.8056,2.88092 0.80566,5.41992 m -23.65722,15.4541 c -5e-5,-3.51557 -0.97661,-6.24994 -2.92969,-8.20312 -1.95316,-1.95307 -4.71195,-2.92963 -8.27637,-2.92969 -1.80667,6e-5 -3.39358,0.31744 -4.76074,0.95215 -1.36721,0.58599 -2.51467,1.41607 -3.44238,2.49023 -0.87893,1.02545 -1.53811,2.24615 -1.97754,3.66211 -0.43948,1.36724 -0.6592,2.80767 -0.65918,4.32129 -2e-5,3.32036 0.97654,5.95707 2.92969,7.91016 1.95309,1.90433 4.66305,2.85648 8.12988,2.85644 1.85543,4e-5 3.46676,-0.29293 4.83398,-0.8789 1.36715,-0.5859 2.4902,-1.39157 3.36914,-2.417 0.9277,-1.02535 1.61129,-2.19722 2.05079,-3.51562 0.48823,-1.36714 0.73237,-2.78316 0.73242,-4.24805 m 4.32129,52.14844 c -5e-5,-2.19727 -0.87896,-3.88184 -2.63672,-5.05371 -1.75786,-1.17187 -4.17485,-1.80664 -7.25098,-1.9043 l -13.11035,-0.36621 c -1.26956,0.92774 -2.29495,1.83106 -3.07617,2.70996 -0.73245,0.83008 -1.3428,1.63574 -1.83106,2.41699 -0.43947,0.78125 -0.73244,1.53809 -0.8789,2.27051 -0.14651,0.73242 -0.21975,1.48925 -0.21973,2.27051 -2e-5,2.4414 1.22068,4.29686 3.66211,5.56641 2.49021,1.26951 5.98142,1.90428 10.47363,1.90429 2.78317,-10e-6 5.12692,-0.29298 7.03125,-0.8789 1.90426,-0.53713 3.44234,-1.26955 4.61426,-2.19727 1.17183,-0.92774 2.00191,-1.97755 2.49023,-3.14941 0.48824,-1.12306 0.73238,-2.31935 0.73243,-3.58887"
style="font-size:150px;fill:#00a9e0;font-family:Calibri;-inkscape-font-specification:Calibri Bold"
id="path3811" />
</g>
</g>
</g>
<g
transform="translate(-154.76465,-3152.2336)"
style="font-size:42px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#00629b;fill-opacity:0.98431373;stroke:none;font-family:Calibri;-inkscape-font-specification:AlArabiya Bold"
id="flowRoot3727">
<path
d="m 574.2041,625.37123 c -2e-5,1.62697 -0.23928,3.08302 -0.71777,4.36817 -0.47854,1.28516 -1.18264,2.37207 -2.11231,3.26074 -0.9297,0.88867 -2.07814,1.56543 -3.44531,2.03027 -1.3672,0.46485 -2.93947,0.69727 -4.7168,0.69727 -1.66798,0 -3.16505,-0.20508 -4.49121,-0.61523 -1.32618,-0.42383 -2.44727,-1.05957 -3.36328,-1.90723 -0.91602,-0.84765 -1.62012,-1.90039 -2.1123,-3.1582 -0.47852,-1.27148 -0.71778,-2.75488 -0.71778,-4.4502 l 0,-16.13965 c 0,-0.13669 0.041,-0.25974 0.12305,-0.36914 0.082,-0.10935 0.22558,-0.19821 0.43066,-0.2666 0.21875,-0.0683 0.49902,-0.12302 0.84082,-0.16406 0.3418,-0.041 0.7793,-0.0615 1.3125,-0.0615 0.51953,3e-5 0.95019,0.0205 1.292,0.0615 0.34179,0.041 0.61522,0.0957 0.82031,0.16406 0.20507,0.0684 0.34862,0.15725 0.43066,0.2666 0.0957,0.1094 0.14355,0.23245 0.14356,0.36914 l 0,15.66797 c -10e-6,1.05274 0.12987,1.96876 0.38965,2.74805 0.25975,0.76563 0.62889,1.40137 1.10742,1.90722 0.49218,0.50587 1.07323,0.88868 1.74316,1.14844 0.68358,0.2461 1.44237,0.36915 2.27637,0.36914 0.84764,10e-6 1.60643,-0.12988 2.27637,-0.38965 0.6699,-0.25976 1.23728,-0.63573 1.70215,-1.12793 0.46482,-0.50585 0.82029,-1.12108 1.0664,-1.8457 0.25975,-0.73827 0.38963,-1.57226 0.38965,-2.50195 l 0,-15.97559 c -2e-5,-0.13669 0.041,-0.25974 0.12305,-0.36914 0.082,-0.10935 0.22556,-0.19821 0.43066,-0.2666 0.20506,-0.0683 0.4785,-0.12302 0.82031,-0.16406 0.35545,-0.041 0.79295,-0.0615 1.3125,-0.0615 0.51951,3e-5 0.94334,0.0205 1.27149,0.0615 0.34177,0.041 0.61521,0.0957 0.82031,0.16406 0.20505,0.0684 0.34861,0.15725 0.43066,0.2666 0.082,0.1094 0.12303,0.23245 0.12305,0.36914 l 0,15.91406"
id="path3814" />
<path
d="m 598.11621,616.77846 c -2e-5,1.49025 -0.23244,2.80959 -0.69726,3.95801 -0.46487,1.14845 -1.14163,2.11915 -2.03028,2.91211 -0.88869,0.77931 -1.98244,1.37403 -3.28125,1.78418 -1.28517,0.41016 -2.80274,0.61524 -4.55273,0.61523 l -2.21485,0 0,8.46973 c 0,0.13672 -0.0479,0.25976 -0.14355,0.36914 -0.082,0.10937 -0.22559,0.19824 -0.43067,0.2666 -0.20508,0.0684 -0.47852,0.12305 -0.82031,0.16406 -0.3418,0.041 -0.7793,0.0615 -1.3125,0.0615 -0.51953,0 -0.95703,-0.0205 -1.3125,-0.0615 -0.3418,-0.041 -0.61524,-0.0957 -0.82031,-0.16406 -0.20508,-0.0684 -0.34864,-0.15723 -0.43066,-0.2666 -0.082,-0.10938 -0.12305,-0.23242 -0.12305,-0.36914 l 0,-23.8711 c 0,-0.64255 0.16406,-1.12106 0.49219,-1.43554 0.34179,-0.3281 0.78613,-0.49216 1.333,-0.49219 l 6.25489,0 c 0.62889,3e-5 1.22362,0.0274 1.78418,0.082 0.5742,0.041 1.2578,0.14358 2.05078,0.30762 0.79295,0.15042 1.59276,0.43752 2.39941,0.86133 0.8203,0.42385 1.51756,0.96389 2.0918,1.62011 0.5742,0.64261 1.0117,1.40139 1.3125,2.27637 0.30076,0.86135 0.45115,1.83205 0.45117,2.91211 m -5.63965,0.38965 c -10e-6,-0.92967 -0.16408,-1.69529 -0.49219,-2.29688 -0.32813,-0.60154 -0.73145,-1.04587 -1.20996,-1.333 -0.47852,-0.28709 -0.98438,-0.46483 -1.51757,-0.53321 -0.51955,-0.082 -1.05959,-0.12302 -1.62012,-0.12304 l -2.29688,0 0,9.00293 2.41993,0 c 0.86131,1e-5 1.57908,-0.1162 2.15332,-0.34864 0.58787,-0.2324 1.06639,-0.55369 1.43554,-0.96386 0.36913,-0.42382 0.6494,-0.92284 0.84082,-1.49707 0.19139,-0.58788 0.2871,-1.22362 0.28711,-1.90723"
id="path3816" />
<path
d="m 633.2666,634.51772 c -3e-5,0.13672 -0.0411,0.25976 -0.12305,0.36914 -0.0684,0.10937 -0.20511,0.19824 -0.41015,0.2666 -0.19144,0.0684 -0.45121,0.12305 -0.7793,0.16406 -0.32816,0.041 -0.74515,0.0615 -1.25098,0.0615 -0.49221,0 -0.90237,-0.0205 -1.23046,-0.0615 -0.32816,-0.041 -0.58792,-0.0957 -0.7793,-0.16406 -0.19144,-0.0684 -0.32815,-0.15723 -0.41016,-0.2666 -0.0821,-0.10938 -0.12307,-0.23242 -0.12304,-0.36914 l 0,-21.59473 -0.041,0 -7.69043,21.57422 c -0.0547,0.17774 -0.14357,0.32813 -0.2666,0.45117 -0.12307,0.10938 -0.29397,0.19825 -0.5127,0.2666 -0.20509,0.0684 -0.4717,0.10938 -0.7998,0.12305 -0.32814,0.0273 -0.72463,0.041 -1.18945,0.041 -0.46487,0 -0.86135,-0.0205 -1.18946,-0.0615 -0.32814,-0.0273 -0.60158,-0.0752 -0.82031,-0.14355 -0.20509,-0.082 -0.36916,-0.17774 -0.49219,-0.28711 -0.12306,-0.10938 -0.20509,-0.23926 -0.24609,-0.38965 l -7.42383,-21.57422 -0.041,0 0,21.59473 c -1e-5,0.13672 -0.041,0.25976 -0.12305,0.36914 -0.0684,0.10937 -0.20509,0.19824 -0.41016,0.2666 -0.20508,0.0684 -0.47168,0.12305 -0.7998,0.16406 -0.31446,0.041 -0.72462,0.0615 -1.23047,0.0615 -0.49219,0 -0.90235,-0.0205 -1.23047,-0.0615 -0.32813,-0.041 -0.59473,-0.0957 -0.7998,-0.16406 -0.19141,-0.0684 -0.32813,-0.15723 -0.41016,-0.2666 -0.0684,-0.10938 -0.10254,-0.23242 -0.10254,-0.36914 l 0,-23.64551 c 0,-0.69724 0.18457,-1.23044 0.55371,-1.59961 0.36914,-0.36911 0.86133,-0.55368 1.47656,-0.55371 l 3.52735,0 c 0.62889,3e-5 1.16893,0.0547 1.62011,0.16406 0.45117,0.0957 0.84081,0.26663 1.16895,0.5127 0.32811,0.23245 0.60155,0.5469 0.82031,0.94336 0.21874,0.38283 0.41015,0.86135 0.57422,1.43554 l 5.74219,15.81153 0.082,0 5.94727,-15.77051 c 0.17771,-0.57419 0.36911,-1.05955 0.57421,-1.45605 0.21873,-0.39646 0.46482,-0.71775 0.73829,-0.96387 0.28708,-0.24607 0.62204,-0.41697 1.00488,-0.5127 0.38278,-0.10935 0.82712,-0.16403 1.33301,-0.16406 l 3.62988,0 c 0.36911,3e-5 0.68356,0.0479 0.94336,0.14356 0.2734,0.0957 0.49215,0.23928 0.65625,0.43066 0.1777,0.17776 0.30758,0.40335 0.38965,0.67676 0.0957,0.25979 0.14352,0.56057 0.14355,0.90234 l 0,23.64551"
id="path3818" />
</g>
<path
transform="matrix(1.6,0,0,1.6,-233,-3460.4252)"
style="fill:#ffffff;fill-opacity:0.98431373;filter:url(#filter3757)"
d="m 445,510.49219 c 0,1.38071 -1.11929,2.5 -2.5,2.5 -1.38071,0 -2.5,-1.11929 -2.5,-2.5 0,-1.38071 1.11929,-2.5 2.5,-2.5 1.38071,0 2.5,1.11929 2.5,2.5 z"
id="path3735" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

BIN
templates/img/logo_soil.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg"><path d="M1472 992v480q0 26-19 45t-45 19h-384v-384h-256v384h-384q-26 0-45-19t-19-45v-480q0-1 .5-3t.5-3l575-474 575 474q1 2 1 6zm223-69l-62 74q-8 9-21 11h-3q-13 0-21-7l-692-577-692 577q-12 8-24 7-13-2-21-11l-62-74q-8-10-7-23.5t11-21.5l719-599q32-26 76-26t76 26l244 204v-195q0-14 9-23t23-9h192q14 0 23 9t9 23v408l219 182q10 8 11 21.5t-7 23.5z"/></svg>

After

Width:  |  Height:  |  Size: 462 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="512px" id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M448,448c0,0,0-26.4-2.2-40.2c-1.8-10.9-16.9-25.3-81.1-48.9c-63.2-23.2-59.3-11.9-59.3-54.6c0-27.7,14.1-11.6,23.1-64.2 c3.5-20.7,6.3-6.9,13.9-40.1c4-17.4-2.7-18.7-1.9-27c0.8-8.3,1.6-15.7,3.1-32.7C345.4,119.3,325.9,64,256,64 c-69.9,0-89.4,55.3-87.5,76.4c1.5,16.9,2.3,24.4,3.1,32.7c0.8,8.3-5.9,9.6-1.9,27c7.6,33.1,10.4,19.3,13.9,40.1 c9,52.6,23.1,36.5,23.1,64.2c0,42.8,3.9,31.5-59.3,54.6c-64.2,23.5-79.4,38-81.1,48.9C64,421.6,64,448,64,448h192H448z"/></svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN' 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'><svg enable-background="new 0 0 91.8 92.6" id="Layer_1" version="1.0" viewBox="0 0 91.8 92.6" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M46.3,3.6c-23.5,0-42.5,19-42.5,42.5s19,42.5,42.5,42.5c23.5,0,42.5-19,42.5-42.5S69.8,3.6,46.3,3.6z M72.8,52.9H53v19.8c0,2-1.6,3.6-3.6,3.6h-6.2c-2,0-3.6-1.6-3.6-3.6V52.9H19.8c-2,0-3.6-1.6-3.6-3.6v-6.2c0-2,1.6-3.6,3.6-3.6h19.8 V19.7c0-2,1.6-3.6,3.6-3.6h6.2c2,0,3.6,1.6,3.6,3.6v19.8h19.8c2,0,3.6,1.6,3.6,3.6v6.2C76.4,51.2,74.8,52.9,72.8,52.9z" fill="#1E1E1E"/></svg>

After

Width:  |  Height:  |  Size: 697 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><svg height="16px" version="1.1" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" xmlns:xlink="http://www.w3.org/1999/xlink"><title/><defs/><g fill="none" fill-rule="evenodd" id="Icons with numbers" stroke="none" stroke-width="1"><g fill="#000000" id="Group" transform="translate(-192.000000, -192.000000)"><path d="M201,205.917042 C203.512502,205.49553 205.495527,203.512505 205.917042,201 L203,201 L203,199 L205.917042,199 C205.495527,196.487495 203.512502,194.50447 201,194.082958 L201,197 L199,197 L199,194.082958 C196.487498,194.50447 194.504473,196.487495 194.082958,199 L197,199 L197,201 L194.082958,201 C194.504473,203.512505 196.487498,205.49553 199,205.917042 L199,203 L201,203 Z M200,208 C195.581722,208 192,204.418278 192,200 C192,195.581722 195.581722,192 200,192 C204.418278,192 208,195.581722 208,200 C208,204.418278 204.418278,208 200,208 Z M200,208" id="Oval 163"/></g></g></svg>

After

Width:  |  Height:  |  Size: 992 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 64 64" height="64px" id="Layer_1" version="1.1" viewBox="0 0 64 64" width="64px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><g><path d="M52.419,15.975c0,0,1.013,1.019,1.727,0.002l1.363-1.953c0.476-0.687-0.139-1.162-0.202-1.209 l-8.265-5.775H47.04c-0.509-0.354-0.847-0.139-1.024,0.06l-0.148,0.213l-1.259,1.802c-0.006,0.007-0.71,1.119,0.416,1.707v0.001 c1.61,0.792,4.563,2.462,7.392,5.158L52.419,15.975z" fill="#241F20"/></g><g><path d="M38.512,0.071H25.488c-1.011,0-1.839,0.812-1.839,1.839v1.518c0,1.026,0.828,1.854,1.839,1.854h0.644 v1.072c0.001,1.541,0.974,1.669,1.462,1.636c0.083-0.012,0.169-0.025,0.26-0.037c0.001,0,0.013-0.003,0.013-0.003L27.866,7.95 c1.734-0.237,4.605-0.464,7.898-0.045l0.002-0.003c0,0,2.109,0.391,2.103-1.549V5.281h0.644c1.012,0,1.839-0.827,1.839-1.854V1.91 C40.351,0.884,39.523,0.071,38.512,0.071z" fill="#241F20"/></g><path d="M32,10.301c-14.808,0-26.812,12.005-26.812,26.815c0,14.807,12.004,26.812,26.812,26.812 c14.809,0,26.812-12.006,26.812-26.812C58.812,22.306,46.809,10.301,32,10.301z M33.717,37.108 c-1.575,0.002-1.709-1.094-1.717-1.41V17.155c0.046-0.645,0.381-1.86,2.248-1.546c0.037,0.005,0.072,0.009,0.111,0.014 c0.12,0.02,0.233,0.036,0.32,0.043c5.44,0.764,17.373,4.302,18.864,20.343c-0.042,0.446-0.295,1.096-1.412,1.103 C42.529,37.085,36.454,37.097,33.717,37.108z" fill="#241F20"/></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

378
templates/index.html Normal file
View File

@@ -0,0 +1,378 @@
<!DOCTYPE html>
<head>
<!-- FAVICON -->
<link rel="shortcut icon" href="http://gsi.dit.upm.es/templates/purity_iii/favicon.ico" type="image/x-icon">
<link rel="icon" href="http://gsi.dit.upm.es/templates/purity_iii/favicon.ico" type="image/x-icon">
<!-- JQUERY -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- BOOTSTRAP 3.3.7 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- BOOTSTRAP SLIDER -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.9.0/css/bootstrap-slider.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.9.0/bootstrap-slider.js"></script>
<!-- D3.js // DATA-DRIVEN DOCUMENTS -->
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
<script type="text/javascript" src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<!-- C3.js // D3-based reusable chart library -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.min.js"></script>
<!-- JAVASCRIPTS -->
<script type="text/javascript" src="js/visualization.js"></script>
<script type="text/javascript" src="js/timeline.js"></script>
<script type="text/javascript" src="js/socket.js"></script>
<script type="text/javascript" src="js/template.js"></script>
<!-- STYLESHEETS -->
<link rel="stylesheet" type="text/css" href="css/main.css">
<link rel="stylesheet" type="text/css" href="css/timeline.css">
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Ubuntu+Mono" />
<title>{{ name }}</title>
<script type="text/javascript">//<![CDATA[
var width = window.innerWidth * 0.75,
height = window.innerHeight * 3 / 5,
speed = 1000,
play,
slider;
var width_chart = (window.innerWidth - 30) / 2 - 15,
height_chart = (window.innerHeight - 230) / 2,
chart_nodes,
chart_attrs;
window.onload = function() {
"use strict";
// Create svg, timeline and settings
self.GraphVisualization.create('graph', height, width);
$('<div>').attr('id', 'load').appendTo('#graph_container').css('left', width / 2 - 25).css('top', height / 2);
$('#configuration').css("height", height);
d3.select('#slider3').attr("width", width).call(
d3.slider().axis(true).min(0).max(100)
);
// Load a file
$('#update #file').change(function() {
var file = $('#file')[0].files[0];
$('.console').append('<br/>');
self.GraphVisualization.reset();
$('#load').show();
$('.custom-file-control').attr("data-content",
file['name'] || "Choose file..."
);
if ( file['type'] !== "application/x-yaml" ) {
console.error('File format not supported. Sorry for the inconvenience.');
_socket.error('File format not supported. Sorry for the inconvenience.');
return;
} else {
$('.alert.alert-danger').hide();
}
var fileReader = new FileReader();
if (fileReader && file) {
fileReader.readAsText(file);
fileReader.onload = function () {
var content = fileReader.result;
$('#load').show().addClass('loader');
_socket.send(content, 'config_file');
};
}
});
// Select 'attributes'
$('.config-item #properties').change(function() {
self.GraphVisualization.update_graph($(this).val(), slider.value(), function() {
update_statistics_table();
});
});
// Run simulation
$('#simulation_modal .btn-success').click(function() {
if ( !jQuery.isEmptyObject(run_simulation()) ) {
self.GraphVisualization.reset();
$('#load').show().addClass('loader');
_socket.send(run_simulation(), 'run_simulation');
$('.console').append('<br/>');
}
$('#simulation_modal').modal('hide')
});
chart_nodes = create_chart(width_chart, height_chart, 'Time', 'Number of nodes', '#chart_nodes');
chart_attrs = create_chart(width_chart, height_chart, 'Time', 'Attributes', '#chart_attrs');
// Fill modal window
$('#simulation_modal').on('show.bs.modal', function(e) {
var variables = run_simulation()
var x = 0,
row;
for (var i in variables) {
if ( x % 2 === 0 ) row = $('<tr>').appendTo('#simulation_modal table tbody');
$('<td>').text(i).appendTo(row);
$('<td>').text(variables[i]).appendTo(row);
x++;
}
});
$('#simulation_modal').on('hide.bs.modal', function(e) {
$('#simulation_modal table tbody').empty();
});
}
///]]
</script>
</head>
<body>
<div class="container-fluid fixed">
<div class="col-sm-9 wrapper-heading">
<!-- CONSOLE -->
<div class="console">
Please, upload a YAML file that defines all the parameters of a simulation. <br/>
If you don't know how to write the file, please visit this page:<br/>
http://soilsim.readthedocs.io/en/latest/quickstart.html<br/>
</div>
<!-- //CONSOLE -->
<!-- SOIL Logo -->
<div class="soil_logo" >
<img src="img/logo_soil.png" />
</div>
<!-- //SOIL Logo -->
</div>
<div id="update" class="col-sm-3">
<!-- Load File -->
<form enctype="multipart/form-data">
<label class="custom-file">
<input type="file" id="file" name="file" class="custom-file-input">
<span class="custom-file-control" data-content="Choose file..."></span>
</label>
</form>
<!-- //Load File -->
<!-- Atributos -->
<div class="config-item">
Attributes:
<select id="properties" class="form-control form-control-sm">
<optgroup id="properties-dynamic" label="Dynamics"></optgroup>
<optgroup id="properties-static" label="Statics"></optgroup>
</select>
</div>
<!-- //Atributos -->
</div>
</div>
<nav class="navbar navbar-default navbar-fixed-bottom">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">{{ name }}</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li data-target="#myCarousel" data-slide-to="0" class="active" id="home_menu"><a href='#'>Home</a></li>
<li data-target="#myCarousel" data-slide-to="1" id="settings_menu"><a href="#">Settings &amp; Charts</a></li>
<li class="dropdown" id="trials">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Trials <span class="caret"></span></a>
<ul class="dropdown-menu"></ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#" id="run_simulation" role="button">Run simulation</a></li>
<li><a href="#" id="download_simulation" role="button" data-toggle="modal" data-target="#download_modal">Download</a></li>
</ul>
</div>
<script type="text/javascript">
$('.nav li[data-target="#myCarousel"]').click(function() {
$('.nav li').removeClass('active');
$(this).addClass('active');
});
</script>
</div>
</nav>
<div id="myCarousel" class="carousel slide">
<!-- Wrapper for slides -->
<div class="carousel-inner">
<!-- Wrapper Graph Container -->
<div class="item active">
<div class="container-fluid">
<div id="graph_container">
<svg id="graph" class="col-sm-9" xmlns="http://www.w3.org/2000/svg"></svg>
</div>
<div id="configuration" class="col-sm-3">
<!-- Graph Info -->
<div class="config-item" style="margin-top: 0 !important;">
<table id="info-graph">
<tbody>
<tr id="nodes"><th>Nodes:</th></tr>
<tr id="links"><th>Links:</th></tr>
</tbody>
</table>
<div class="logo pull-right">
<img src="img/logo_gsi.svg" style="height: 40px;">
</div>
</div>
<hr />
<!-- //Graph Info -->
<!-- PROPIEDADES -->
<div class="config-item">
<table id="percentTable">
<tbody><tr><th class="no-data-table">No data</th></tr></tbody>
</table>
</div>
<hr />
<!-- //PROPIEDADES -->
<!-- SPEED -->
<div class="config-item">
<table id="speed"><tbody><tr>
<th class="text-left min">min</th>
<th class="text-center">Speed</th>
<th class="text-right max">max</th>
</tr></tbody></table>
<div class="speed-slider">
<input id="speed-slider" type="text" data-slider-min="1" data-slider-max="1000" data-slider-step="0.01" data-slider-value="1000" data-slider-tooltip="hide" data-slider-reversed="true" data-slider-enabled="false" data-slider-scale="logarithmic"/>
</div>
</div>
<hr />
<script type="text/javascript">
$('#speed-slider').slider();
</script>
<!-- //SPEED -->
<!-- LINK DISTANCE -->
<div class="config-item">
<table id="link-distance"><tbody><tr>
<th class="text-left min">min</th>
<th class="text-center">Link Distance</th>
<th class="text-right max">max</th>
</tr></tbody></table>
<div class="link-distance-slider">
<input id="link-distance-slider" type="text" data-slider-min="30" data-slider-max="1000" data-slider-step="0.01" data-slider-value="30" data-slider-tooltip="hide" data-slider-reversed="false" data-slider-enabled="false" data-slider-scale="logarithmic"/>
</div>
</div>
<script type="text/javascript">
$('#link-distance-slider').slider();
</script>
<!-- //LINK DISTANCE -->
</div>
<!-- TIMELINE -->
<div id="timeline" class="col-sm-12">
<div id="slider3" class="pull-left col-sm-9"></div>
<div class="btn-toolbar controls">
<button type="button" id="button_play" class="btn btn-lg">
<span class="glyphicon glyphicon-play" aria-hidden="true"></span>
</button>
<button type="button" id="button_pause" class="btn btn-lg">
<span class="glyphicon glyphicon-pause" aria-hidden="true"></span>
</button>
<button type="button" id="button_zoomFit" class="btn btn-lg">
<span class="glyphicon glyphicon-fullscreen" aria-hidden="true"></span>
</button>
</div>
</div>
<!-- //TIMELINE -->
<!-- ERROR ALERT -->
<div class="alert alert-danger alert-dismissable fade in" style="display: none;">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<strong>Error! </strong><span id="error-message"></span>
</div>
<!-- //ERROR ALERT -->
</div>
</div>
<!-- //Wrapper Graph Container -->
<!-- Wrapper Settings -->
<div class="item" id="settings">
<div class="container-fluid">
<div class="col-sm-6" id="charts">
<div id="chart_nodes" class="chart no-data"></div>
<div id="chart_attrs" class="chart no-data"></div>
</div>
<div class="col-sm-6 none" id="wrapper-settings"></div>
</div>
</div>
</div>
<!-- //Wrapper for slides -->
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="simulation_modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">New simulation</h4>
</div>
<div class="modal-body text-justify">
<p>You are going to run a new simulation, all charts and trials are going to be lost. A new ones will be available after the simulation.</p>
<p>Check your new environment variables for this simulation.</p>
<table class="table">
<thead><tr><th>Variable</th><th>Value</th><th>Variable</th><th>Value</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success">Run</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" tabindex="-1" role="dialog" id="download_modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Download Simulation Results</h4>
</div>
<div class="modal-body text-justify">
<p>You can download the results of the selected trial in GEXF or JSON Graph format for your personal purposes.</p>
<ul >
<li><b>GEXF</b> <i>(Graph Exchange XML Format)</i> is a language for describing complex network structures, their associated data and dynamics. It can be used to visualize the simulation with Gephi.</li>
<li><b>JSON Graph</b> generate and parse JSON serializable data for NetworkX graphs. It is a convention for modeling graph information as a JSON object that can be parsed by any JSON parser.</li>
</ul>
<p>For downloading the results of the other trials simulated, please first select them in menu.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" disabled="disabled" id="download_gexf">GEXF</button>
<button type="button" class="btn btn-success" disabled="disabled" id="download_json">JSON Graph</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</body>
</html>

460
templates/js/socket.js Executable file
View File

@@ -0,0 +1,460 @@
// Open the websocket connection
var ws = new WebSocket((window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + '/ws');
// Open conection with Socket
ws.onopen = function() {
console.log('Connection opened!');
};
// Receive data from server
ws.onmessage = function(message) {
//console.log('Message received!');
var msg = JSON.parse(message.data);
switch(msg['type']) {
case 'trials':
reset_trials();
set_trials(msg['data']);
// $('#load').removeClass('loader');
break;
case 'get_trial':
console.log(msg['data']);
self.GraphVisualization.import(convertJSON(msg['data']), function() {
reset_configuration();
set_configuration();
// $('#home_menu').click(function() {
// setTimeout(function() {
// reset_timeline();
// set_timeline(msg['data']);
// }, 1000);
// });
reset_timeline();
set_timeline(msg['data']);
$('#load').hide();
});
$('#charts .chart').removeClass('no-data');
set_chart_nodes(msg['data'], chart_nodes)
set_chart_attrs(msg['data'], chart_attrs, $('.config-item #properties').val())
$('.config-item #properties').change(function() {
chart_attrs.destroy();
chart_attrs = create_chart(width_chart, height_chart, 'Time', 'Attributes', '#chart_attrs');
set_chart_attrs(msg['data'], chart_attrs, $('.config-item #properties').val())
});
break;
case 'settings':
$('#wrapper-settings').empty().removeClass('none');
initGUI(msg['data']);
break;
case 'error':
console.error(msg['error']);
_socket.error(msg['error']);
$('#load').removeClass('loader');
break;
case 'log':
$('.console').append('$ ' + msg['logger'] + ': ' + msg['logging'] + '<br/>');
$('.console').animate({ scrollTop: $('.console')[0].scrollHeight }, 'fast');
break;
case 'visualization_params':
console.log(msg['data']);
self.GraphVisualization.set_params(msg['data']['shape_property'], msg['data']['shapes'], msg['data']['colors']);
if ( msg['data']['background_image'] ) {
// $('svg#graph').css('background-image', 'linear-gradient(to bottom, rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%), url(img/background/' + msg['data']['background_image'])
// .css('background-size', '130%').css('background-position', '5% 30%').css('background-repeat', 'no-repeat');
$('<style>').text('svg line.link { stroke: white !important; stroke-width: 1.5px !important; }').appendTo($('html > head'));
$('<style>').text('svg circle.node { stroke-width: 2.5px !important; }').appendTo($('html > head'));
self.GraphVisualization.set_background('img/background/' + msg['data']['background_image'], msg['data']['background_opacity'], msg['data']['background_filter_color']);
}
break;
case 'download_gexf':
var xml_declaration = '<?xml version="1.0" encoding="utf-8"?>';
download(msg['filename'] + '.gexf', 'xml', xml_declaration + msg['data']);
break;
case 'download_json':
download(msg['filename'] + '.json', 'json', JSON.stringify(msg['data'], null, 4));
break;
default:
console.warn('Unexpected message!')
}
}
var _socket = {
send: function(message, type) {
var json = {}
json['type'] = type
json['data'] = message
ws.send(JSON.stringify(json))
},
error: function(message) {
$('#error-message').text(message);
$('.alert.alert-danger').show();
},
current_trial: undefined
};
var set_trials = function(trials) {
for ( i in trials ) {
var list_item = $('<li>').appendTo('.dropdown#trials .dropdown-menu');
$('<a>').val(i).text(trials[i]).appendTo(list_item);
}
// Select 'trials'
$('.dropdown#trials li a').click(function() {
var a = $('.dropdown-toggle .caret');
$('.dropdown-toggle').text($(this).text() + ' ').append(a);
_socket.send($(this).val(), 'get_trial');
_socket.current_trial = $(this).val();
});
// Request first trial as default
_socket.send(0, 'get_trial')
_socket.current_trial = 0
};
var reset_trials = function() {
// 'Trials' selector
$('.dropdown-menu').empty();
var a = $('.dropdown-toggle .caret');
$('.dropdown-toggle').text('Trials ').append(a);
}
var convertJSON = function(json) {
// For NetworkX Geometric Graphs get positions
json.nodes.forEach(function(node) {
var scx = d3.scale.linear().domain([0, 1]).range([0, width]);
var scy = d3.scale.linear().domain([0, 1]).range([width, 0]);
if ( node.pos ) {
node.scx = scx(node.pos[0]);
node.scy = scy(node.pos[1]);
}
delete node.pos;
});
json.links.forEach(function(link) {
link.source = json.nodes[link.source]
link.target = json.nodes[link.target]
});
// Fix spells for nodes
json.nodes.forEach(function(node) {
for (i in node.spells) {
if (node.spells[i][0] > node.spells[i][1]) {
aux = node.spells[i][0];
node.spells[i][0] = node.spells[i][1];
node.spells[i][1] = aux;
}
}
});
return json;
}
var update_statistics_table = function() {
$('#percentTable tbody').empty()
var statisticsSorted = Object.keys(self.GraphVisualization.statistics).sort(function(a,b) {
return self.GraphVisualization.statistics[b] - self.GraphVisualization.statistics[a];
});
for ( var i in statisticsSorted ) {
if ( i <= 5 ) {
// Draw table
var appendTo = '#percentTable > tbody tr:nth-child(' + Number(parseInt(i) + 1) + ')';
var propertyName = (statisticsSorted[i].includes('class')) ?
statisticsSorted[i].split('.').pop().split('\'')[0] : statisticsSorted[i];
$('<tr>').addClass('col-sm-12').appendTo('#percentTable > tbody');
$('<td>').css('background-color', self.GraphVisualization.color($('.config-item #properties').val(), statisticsSorted[i])).addClass('col-sm-1').appendTo(appendTo);
$('<td>').addClass('text-left col-sm-4').text(self.GraphVisualization.statistics[statisticsSorted[i]] + ' %').appendTo(appendTo);
$('<td>').addClass('text-right col-sm-6 property-name').text(propertyName).appendTo(appendTo);
}
}
}
var set_configuration = function() {
// Number of nodes and links info table
$('<tr>').appendTo('#info-graph > tbody');
$('<th>').text('Nodes:').appendTo('#info-graph > tbody tr:nth-child(1)');
$('<th>').text(self.GraphVisualization.nodes).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(1)');
$('<tr>').appendTo('#info-graph > tbody');
$('<th>').text('Links:').appendTo('#info-graph > tbody tr:nth-child(2)');
$('<th>').text(self.GraphVisualization.links).addClass('text-right').appendTo('#info-graph > tbody tr:nth-child(2)');
// Options of 'Select'
for ( var i in self.GraphVisualization.model['dynamic'] ) {
$('<option>').val(self.GraphVisualization.model['dynamic'][i].title)
.text(self.GraphVisualization.model['dynamic'][i].title).appendTo('#properties-dynamic');
}
for ( var i in self.GraphVisualization.model['static'] ) {
$('<option>').val(self.GraphVisualization.model['static'][i].title)
.text(self.GraphVisualization.model['static'][i].title).appendTo('#properties-static');
}
// Hide optgroups if they are empty
if ( $('#properties-dynamic').children().length === 0 ) $('#properties-dynamic').hide();
if ( $('#properties-static').children().length === 0 ) $('#properties-static').hide();
update_statistics_table();
// Enable 'Link Distance' slider
$('#link-distance-slider').slider('enable').on('change', function(value) {
self.GraphVisualization.set_link_distance(value.value.newValue);
});
// Enable 'Run configuration' button
$('#run_simulation').attr('data-toggle', 'modal').attr('data-target', '#simulation_modal');
// Enable 'Download' buttons
$('#download_modal .btn-success').prop('disabled', false);
$('#download_gexf').on('click', function() {
_socket.send(_socket.current_trial, 'download_gexf')
});
$('#download_json').on('click', function() {
_socket.send(_socket.current_trial, 'download_json')
});
}
var reset_configuration = function() {
// Information table about the graph
$('#info-graph > tbody').empty();
// 'Select' for properties
$('#properties-dynamic').empty().show();
$('#properties-static').empty().show();
// 'Link Distance' slider
$('#link-distance-slider').slider('disable').slider('setValue', 30);
// 'Download' buttons
$('#download_gexf').off();
$('#download_json').off();
}
var set_timeline = function(graph) {
// 'Timeline' slider
var [min, max] = get_limits(graph);
var stepUnix = (max - min) / 200;
var minUnix = (min !== Math.min()) ? min : 0;
var maxUnix = (max !== Math.max()) ? max : minUnix + 20;
slider = d3.slider();
d3.select('#slider3').attr('width', width).call(
slider.axis(true).min(minUnix).max(maxUnix).step(stepUnix).value(maxUnix)
.on('slide', function(evt, value) {
self.GraphVisualization.update_graph($('.config-item #properties').val(), value, function() {
update_statistics_table();
});
})
);
// Draw graph for the first time
self.GraphVisualization.update_graph($('.config-item #properties').val(), maxUnix, function() {
update_statistics_table();
setTimeout(function() {
self.GraphVisualization.fit();
if ( $('svg #root > image').length !== 0 ) {
$('svg #root > image').attr('height', d3.select('#root').node().getBBox().height * 1.2);
var dx = d3.select('#graph-wrapper').node().getBBox().width - d3.select('svg #root > image').node().getBBox().width;
var dy = d3.select('#graph-wrapper').node().getBBox().height - d3.select('svg #root > image').node().getBBox().height;
$('svg #root > image').attr('transform', 'translate(' + (dx / 2) + ',' + (dy / 2) + ')');
$('svg #root > rect').attr('transform', 'translate(' + (dx / 2) + ',' + (dy / 2) + ')')
.attr('width', d3.select('svg #root > image').node().getBBox().width)
.attr('height', d3.select('svg #root > image').node().getBBox().height);
}
}, 1000);
});
// 'Speed' slider
$('#speed-slider').slider('enable').on('change', function(value) {
speed = value.value.newValue;
});
// Button 'Play'
$('button#button_play').on('click', function() {
$('button#button_play').addClass('pressed').prop("disabled", true);
$('#speed-slider').slider('disable');
slider.step( 1 / speed );
if (slider.value() >= maxUnix) {
slider.value(minUnix);
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
update_statistics_table();
});
setTimeout(player, 1000);
} else {
player();
}
var i = slider.value();
function player() {
clearInterval(play);
play = setInterval(function() {
self.GraphVisualization.update_graph($('.config-item #properties').val(), slider.value(), function() {
update_statistics_table();
});
if (slider.value() + slider.step() >= maxUnix) {
slider.value(maxUnix);
slider.step(stepUnix);
clearInterval(play);
$('button#button_play').removeClass('pressed').prop("disabled", false);
$('#speed-slider').slider('enable');
} else {
slider.value(i);
i += slider.step();
}
}, 5);
}
});
// Button 'Pause'
$('button#button_pause').on('click', function() {
clearInterval(play);
slider.step(stepUnix);
$('button#button_play').removeClass('pressed').prop("disabled", false);
$('#speed-slider').slider('enable');
});
// Button 'Zoom to Fit'
$('button#button_zoomFit').click(function() { self.GraphVisualization.fit(); });
}
var reset_timeline = function() {
// 'Timeline' slider
$('#slider3').html('');
// 'Speed' slider
$('#speed-slider').slider('disable').slider('setValue', 1000);
// Buttons
clearInterval(play);
$('button#button_play').off().removeClass('pressed').prop("disabled", false);
$('button#button_pause').off();
$('button#button_zoomFit').off();
}
var get_limits = function(graph) {
var max = Math.max();
var min = Math.min()
graph.links.forEach(function(link) {
if (link.end > max) max = link.end
if (link.start > max) max = link.start
if (link.end < min) min = link.end
if (link.start < min) min = link.start
});
graph.nodes.forEach(function(node) {
for (property in node) {
if ( Array.isArray(node[property]) ) {
for (i in node[property]) {
for (j in node[property][i]) {
if (node[property][i][j] > max) max = node[property][i][j];
if (node[property][i][j] < min) min = node[property][i][j];
}
}
}
}
})
return [min, max];
}
var set_chart_nodes = function(graph, chart) {
var [min, max] = get_limits(graph);
var data = ['nodes']
for (var i = min; i <= max; i++) {
data.push(this.GraphVisualization.get_nodes(i));
}
chart.load({
unload: true,
columns: [data]
});
}
var set_chart_attrs = function(graph, chart, property) {
var [min, max] = get_limits(graph);
var data_tmp = {}
for (var i = min; i <= max; i++) {
this.GraphVisualization.get_attributes(property, i, function(object) {
for (var value in object) {
if (!data_tmp[value]) {
var time = 0
for (var done in data_tmp)
time = (data_tmp[done].length > time) ? data_tmp[done].length - 1 : time
data_tmp[value] = Array(time).fill(0);
}
data_tmp[value].push(object[value]);
}
});
}
var data = $.map(data_tmp, function(value, index) {
value.splice(0,0,index);
return [value];
});
chart.load({
unload: true,
columns: data
});
chart.axis.labels({y: property});
}
var create_chart = function(width, height, label_x, label_y, bind_to) {
return c3.generate({
size: {
width: width,
height: height
},
data: {
columns: [],
type: 'area-spline'
},
axis: {
x: { label: label_x },
y: { label: label_y }
},
point: { show: false },
bindto: bind_to
});
}
var run_simulation = function() {
var environment_variables = {}
$('#wrapper-settings input').each(function() {
switch(this.type) {
case 'text':
environment_variables[this.id] = Number(this.value);
break;
case 'checkbox':
environment_variables[this.id] = ($(this).is(':checked')) ? true : false;
break;
case 'number':
environment_variables[this.id] = Number(this.value);
break;
default:
console.warn(this.id + ' not defined when running simulation!');
break;
}
});
return environment_variables;
}
var download = function(filename, filetype, content) {
var file = document.createElement('a');
file.setAttribute('href', 'data:text/' + filetype + ';charset=utf-8,' + encodeURIComponent(content));
file.setAttribute('download', filename);
file.click();
delete file;
}

99
templates/js/template.js Normal file
View File

@@ -0,0 +1,99 @@
// Add model parameters that can be edited prior to a model run
var initGUI = function(model_params) {
var addBooleanInput = function(name, value) {
var checked = (value) ? 'checked' : 'value';
var wrapper = $('<div>').attr('class', 'col-sm-6').height('110px');
var input_group = $('<div>').attr('class', 'input-group').appendTo(wrapper);
var label = $('<label>').attr('for', name).attr('class', 'checkbox').appendTo(input_group);
var input = $('<input>') .attr('class', 'form-check-input').attr('id', name).attr('type', 'checkbox').attr(checked, checked).appendTo(label);
input.after(name);
$('#wrapper-settings').append(wrapper);
};
var addSliderInput = function(name, value) {
var wrapper = $('<div>').attr('class', 'col-sm-6').height('110px');
var label = $('<div>').width('100%').text(name).css('text-align', 'center').css('font-weight', 'bolder').appendTo(wrapper);
var input = $('<input>').attr('id', name).attr('type', 'text').attr('data-slider-min', '0.001').attr('data-slider-max', '1').attr('data-slider-step', '0.001').attr('data-slider-value', value).attr('data-slider-tooltip', 'hide').css('padding', '0 10px').appendTo(wrapper);
var span = $('<div>').attr('id', name + '_value').text('Current value: ').width('100%').css('padding-top', '10px').appendTo(wrapper);
var current_value = $('<span>').attr('id', name + '_number').text(value).appendTo(span);
var button_group = $('<div>').attr('class', 'btn-group').attr('role', 'group').css('position', 'absolute').css('right', '15px').appendTo(span);
var button_down = $('<button>').attr('type', 'button').attr('class', 'btn btn-default btn-default-down').appendTo(button_group);
var button_up = $('<button>').attr('type', 'button').attr('class', 'btn btn-default btn-default-down').appendTo(button_group);
$('<span>').attr('class', 'glyphicon glyphicon-chevron-down').attr('aria-hidden', 'true').appendTo(button_down);
$('<span>').attr('class', 'glyphicon glyphicon-chevron-up').attr('aria-hidden', 'true').appendTo(button_up);
$('#wrapper-settings').append(wrapper);
input.slider().on('change', function(slideEvt) {
current_value.text(slideEvt.value.newValue);
});
var timeout, interval;
button_down.on('mousedown', function() {
input.slider('setValue', input.slider('getValue') - 0.001);
current_value.text(input.slider('getValue'));
timeout = setTimeout(function() {
interval = setInterval(function() {
input.slider('setValue', input.slider('getValue') - 0.001);
current_value.text(input.slider('getValue'));
}, 30);
}, 500);
});
button_down.on('mouseup', function() {
clearTimeout(timeout);
clearInterval(interval);
});
button_up.on('mousedown', function() {
input.slider('setValue', input.slider('getValue') + 0.001);
current_value.text(input.slider('getValue'));
timeout = setTimeout(function() {
interval = setInterval(function() {
input.slider('setValue', input.slider('getValue') + 0.001);
current_value.text(input.slider('getValue'));
}, 30);
}, 500);
});
button_up.on('mouseup', function() {
clearTimeout(timeout);
clearInterval(interval);
});
};
var addNumberInput = function(name, value) {
var wrapper = $('<div>').attr('class', 'col-sm-6').height('110px');
var label = $('<div>').width('100%').text(name).css('text-align', 'center').css('font-weight', 'bolder').appendTo(wrapper);
var input = $('<input>').attr('id', name).attr('type', 'number').attr('class', 'form-control').attr('value', value).attr('min', 0).css('margin-top', '18px').appendTo(wrapper);
$('#wrapper-settings').append(wrapper);
}
var addTextBox = function(param, obj) {
var well = $('<div class="well">' + obj.value + '</div>')[0];
sidebar.append(well);
};
for (var option in model_params) {
var type = typeof(model_params[option]);
var param_str = String(option);
switch (model_params[option]['type']) {
case 'boolean':
addBooleanInput(model_params[option]['label'], model_params[option]['value']);
break;
case 'number':
addSliderInput(model_params[option]['label'], model_params[option]['value']);
break;
case 'great_number':
addNumberInput(model_params[option]['label'], model_params[option]['value']);
break;
default:
console.warn(model_params[option]['label'] + ' not defined!');
break;
}
}
};

429
templates/js/timeline.js Normal file
View File

@@ -0,0 +1,429 @@
/*
D3.js Slider
Inspired by jQuery UI Slider
Copyright (c) 2013, Bjorn Sandvik - http://blog.thematicmapping.org
BSD license: http://opensource.org/licenses/BSD-3-Clause
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['d3'], factory);
} else if (typeof exports === 'object') {
if (process.browser) {
// Browserify. Import css too using cssify.
require('./d3.slider.css');
}
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('d3'));
} else {
// Browser globals (root is window)
root.d3.slider = factory(root.d3);
}
}(this, function (d3) {
return function module() {
"use strict";
// Public variables width default settings
var min = 0,
max = 100,
step = 0.01,
animate = true,
orientation = "horizontal",
axis = false,
margin = 50,
value,
active = 1,
snap = false,
scale;
// Private variables
var axisScale,
dispatch = d3.dispatch("slide", "slideend"),
formatPercent = d3.format(".2%"),
tickPadding = 5,
tickFormat = d3.format(".0"),
handle1,
handle2 = null,
divRange,
sliderLength;
function slider(selection) {
selection.each(function() {
// Create scale if not defined by user
if (!scale) {
scale = d3.scale.linear().domain([min, max]);
}
// Start value
value = value || scale.domain()[0];
// DIV container
var div = d3.select(this).classed("d3-slider d3-slider-" + orientation, true);
var drag = d3.behavior.drag();
drag.on('dragend', function () {
dispatch.slideend(d3.event, value);
})
// Slider handle
//if range slider, create two
// var divRange;
if (toType(value) == "array" && value.length == 2) {
handle1 = div.append("a")
.classed("d3-slider-handle", true)
.attr("xlink:href", "#")
.attr('id', "handle-one")
.on("click", stopPropagation)
.call(drag);
handle2 = div.append("a")
.classed("d3-slider-handle", true)
.attr('id', "handle-two")
.attr("xlink:href", "#")
.on("click", stopPropagation)
.call(drag);
} else {
handle1 = div.append("a")
.classed("d3-slider-handle", true)
.attr("xlink:href", "#")
.attr('id', "handle-one")
.on("click", stopPropagation)
.call(drag);
}
// Horizontal slider
if (orientation === "horizontal") {
div.on("click", onClickHorizontal);
if (toType(value) == "array" && value.length == 2) {
divRange = d3.select(this).append('div').classed("d3-slider-range", true);
handle1.style("left", formatPercent(scale(value[ 0 ])));
divRange.style("left", formatPercent(scale(value[ 0 ])));
drag.on("drag", onDragHorizontal);
var width = 100 - parseFloat(formatPercent(scale(value[ 1 ])));
handle2.style("left", formatPercent(scale(value[ 1 ])));
divRange.style("right", width+"%");
drag.on("drag", onDragHorizontal);
} else {
handle1.style("left", formatPercent(scale(value)));
drag.on("drag", onDragHorizontal);
}
sliderLength = parseInt(div.style("width"), 10);
} else { // Vertical
div.on("click", onClickVertical);
drag.on("drag", onDragVertical);
if (toType(value) == "array" && value.length == 2) {
divRange = d3.select(this).append('div').classed("d3-slider-range-vertical", true);
handle1.style("bottom", formatPercent(scale(value[ 0 ])));
divRange.style("bottom", formatPercent(scale(value[ 0 ])));
drag.on("drag", onDragVertical);
var top = 100 - parseFloat(formatPercent(scale(value[ 1 ])));
handle2.style("bottom", formatPercent(scale(value[ 1 ])));
divRange.style("top", top+"%");
drag.on("drag", onDragVertical);
} else {
handle1.style("bottom", formatPercent(scale(value)));
drag.on("drag", onDragVertical);
}
sliderLength = parseInt(div.style("height"), 10);
}
if (axis) {
createAxis(div);
}
function createAxis(dom) {
// Create axis if not defined by user
if (typeof axis === "boolean") {
axis = d3.svg.axis()
.ticks(Math.round(sliderLength) / 100)
.tickFormat(tickFormat)
.tickPadding(tickPadding)
.orient((orientation === "horizontal") ? "bottom" : "right");
}
// Copy slider scale to move from percentages to pixels
axisScale = scale.ticks ? scale.copy().range([0, sliderLength]) : scale.copy().rangePoints([0, sliderLength], 0.5);
axis.scale(axisScale);
// Create SVG axis container
var svg = dom.append("svg")
.classed("d3-slider-axis d3-slider-axis-" + axis.orient(), true)
.on("click", stopPropagation);
var g = svg.append("g");
// Horizontal axis
if (orientation === "horizontal") {
svg.style("margin-left", -margin - 16 + "px");
svg.attr({
width: sliderLength + margin * 2,
height: margin + 30
});
if (axis.orient() === "top") {
svg.style("top", -margin + "px");
g.attr("transform", "translate(" + margin + "," + margin + ")");
} else { // bottom
g.attr("transform", "translate(" + margin + ",0)");
}
} else { // Vertical
svg.style("top", -margin + "px");
svg.attr({
width: margin,
height: sliderLength + margin * 2
});
if (axis.orient() === "left") {
svg.style("left", -margin + "px");
g.attr("transform", "translate(" + margin + "," + margin + ")");
} else { // right
g.attr("transform", "translate(" + 0 + "," + margin + ")");
}
}
g.call(axis);
}
function onClickHorizontal() {
if (toType(value) != "array") {
var pos = Math.max(0, Math.min(sliderLength, d3.event.offsetX || d3.event.layerX));
moveHandle(scale.invert ?
stepValue(scale.invert(pos / sliderLength))
: nearestTick(pos / sliderLength));
}
}
function onClickVertical() {
if (toType(value) != "array") {
var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.offsetY || d3.event.layerY));
moveHandle(scale.invert ?
stepValue(scale.invert(pos / sliderLength))
: nearestTick(pos / sliderLength));
}
}
function onDragHorizontal() {
if ( d3.event.sourceEvent.target.id === "handle-one") {
active = 1;
} else if ( d3.event.sourceEvent.target.id == "handle-two" ) {
active = 2;
}
var pos = Math.max(0, Math.min(sliderLength, d3.event.x));
moveHandle(scale.invert ?
stepValue(scale.invert(pos / sliderLength))
: nearestTick(pos / sliderLength));
}
function onDragVertical() {
if ( d3.event.sourceEvent.target.id === "handle-one") {
active = 1;
} else if ( d3.event.sourceEvent.target.id == "handle-two" ) {
active = 2;
}
var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.y))
moveHandle(scale.invert ?
stepValue(scale.invert(pos / sliderLength))
: nearestTick(pos / sliderLength));
}
function stopPropagation() {
d3.event.stopPropagation();
}
});
}
// Move slider handle on click/drag
function moveHandle(newValue) {
var currentValue = toType(value) == "array" && value.length == 2 ? value[active - 1]: value,
oldPos = formatPercent(scale(stepValue(currentValue))),
newPos = formatPercent(scale(stepValue(newValue))),
position = (orientation === "horizontal") ? "left" : "bottom";
if (oldPos !== newPos) {
if (toType(value) == "array" && value.length == 2) {
value[ active - 1 ] = newValue;
if (d3.event) {
dispatch.slide(d3.event, value );
};
} else {
if (d3.event) {
dispatch.slide(d3.event.sourceEvent || d3.event, value = newValue);
};
}
if ( value[ 0 ] >= value[ 1 ] ) return;
if ( active === 1 ) {
if (toType(value) == "array" && value.length == 2) {
(position === "left") ? divRange.style("left", newPos) : divRange.style("bottom", newPos);
}
if (animate) {
handle1.transition()
.styleTween(position, function() { return d3.interpolate(oldPos, newPos); })
.duration((typeof animate === "number") ? animate : 250);
} else {
handle1.style(position, newPos);
}
} else {
var width = 100 - parseFloat(newPos);
var top = 100 - parseFloat(newPos);
(position === "left") ? divRange.style("right", width + "%") : divRange.style("top", top + "%");
if (animate) {
handle2.transition()
.styleTween(position, function() { return d3.interpolate(oldPos, newPos); })
.duration((typeof animate === "number") ? animate : 250);
} else {
handle2.style(position, newPos);
}
}
}
}
// Calculate nearest step value
function stepValue(val) {
if (val === scale.domain()[0] || val === scale.domain()[1]) {
return val;
}
var alignValue = val;
if (snap) {
alignValue = nearestTick(scale(val));
} else{
var valModStep = (val - scale.domain()[0]) % step;
alignValue = val - valModStep;
if (Math.abs(valModStep) * 2 >= step) {
alignValue += (valModStep > 0) ? step : -step;
}
};
return alignValue;
}
// Find the nearest tick
function nearestTick(pos) {
var ticks = scale.ticks ? scale.ticks() : scale.domain();
var dist = ticks.map(function(d) {return pos - scale(d);});
var i = -1,
index = 0,
r = scale.ticks ? scale.range()[1] : scale.rangeExtent()[1];
do {
i++;
if (Math.abs(dist[i]) < r) {
r = Math.abs(dist[i]);
index = i;
};
} while (dist[i] > 0 && i < dist.length - 1);
return ticks[index];
};
// Return the type of an object
function toType(v) {
return ({}).toString.call(v).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};
// Getter/setter functions
slider.min = function(_) {
if (!arguments.length) return min;
min = _;
return slider;
};
slider.max = function(_) {
if (!arguments.length) return max;
max = _;
return slider;
};
slider.step = function(_) {
if (!arguments.length) return step;
step = _;
return slider;
};
slider.animate = function(_) {
if (!arguments.length) return animate;
animate = _;
return slider;
};
slider.orientation = function(_) {
if (!arguments.length) return orientation;
orientation = _;
return slider;
};
slider.axis = function(_) {
if (!arguments.length) return axis;
axis = _;
return slider;
};
slider.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return slider;
};
slider.value = function(_) {
if (!arguments.length) return value;
if (value) {
moveHandle(stepValue(_));
};
value = _;
return slider;
};
slider.snap = function(_) {
if (!arguments.length) return snap;
snap = _;
return slider;
};
slider.scale = function(_) {
if (!arguments.length) return scale;
scale = _;
return slider;
};
d3.rebind(slider, dispatch, "on");
return slider;
}
}));

View File

@@ -0,0 +1,686 @@
;(function(undefined) {
"use strict";
/**
* Graph Visualization
* ===================
*
* Author: Tasio Méndez (tasiomendez)
* URL: https://github.com/tasiomendez/
* Version: 0.1
*/
// Private constants
var focus_opacity = 0.1,
radius = 8,
shape_size = 16,
required_node = ['id', 'index', 'label', 'px', 'py', 'spells', 'weight', 'x', 'y', 'pos', 'scx', 'scy'];
// Private variables
var width,
height,
graph, // JSON data for the graph
model, // Definition of the attributes of the nodes
linkedByIndex, // Nodes linked by index
name, // Name of the graph (id for svg item)
svg, // Svg item
force, // Set up the force layout
color, // Color for nodes
zoom, // Zoom
groot, // Append sections to svg to have nodes and edges separately
graph_wrapper,
glinks,
gnodes,
background_image,
background_opacity,
background_filter_color,
data_node, // Actual node data for the graph
data_link, // Actual link data for the graph
link, // Line svgs
node, // Circles for the nodes
shape_property, // Property to whom the shape will be applied
shapes, // Dictionary of shapes for nodes
colors, // Dictionary of colors for nodes
background; // Background of the graph
Number.prototype.between = function(min, max) {
var min = (min || min === 0) ? min : Math.max(),
max = (max || max === 0) ? max : Math.min();
return ( this > min && this <= max ) || ( min === 0 && this === 0 );
};
Number.prototype.is_type = function() {
if ( typeof(this) === 'number' )
return ( Number.isInteger(this) ) ? 'int' : 'float';
else
return false;
}
String.prototype.is_type = function() {
return "string";
}
var lastFocusNode;
var _helpers = {
set_node: function(node, property, time) {
// Add nodes if data has more nodes than before
node.enter().append('circle')
.attr('class', 'node')
.attr('r', radius)
.style('fill', function (d) {
if ( Array.isArray(d[property]) ) {
var color_node = _helpers.set_color(property, d[property][0][0]);
d[property].forEach(function(p) {
if ( time.between(p[1], p[2]) ) color_node = _helpers.set_color(property, p[0]);
});
return color_node;
} else {
return _helpers.set_color(property, d[property]);
}
})
.style('stroke', function(d) {
if (_helpers.set_shape(d[shape_property]) !== (-1))
if ( Array.isArray(d[property]) ) {
var color_node = _helpers.set_color(property, d[property][0][0]);
d[property].forEach(function(p) {
if ( time.between(p[1], p[2]) ) color_node = _helpers.set_color(property, p[0]);
});
return color_node;
} else {
return _helpers.set_color(property, d[property]);
}
else
return '#ffffff';
})
// Cancel zoom movement so you can move the node
.on('mousedown', function(d) {
d3.event.stopPropagation();
})
// Double-click to focus neighbours
.on('dblclick', function(d) {
d3.event.stopPropagation();
if (d === lastFocusNode) {
lastFocusNode = undefined;
node.style('opacity', 1);
link.style('opacity', 1);
} else {
lastFocusNode = d;
_helpers.set_focus(d);
}
}).call(force.drag);
// Remove nodes if data has less nodes than before
node.exit().remove();
// Update existing nodes
node.attr('class', 'node')
.attr('r', radius)
.style('fill', function (d) {
if (_helpers.set_shape(d[shape_property]) !== (-1)) {
return 'url(#' + _helpers.set_shape(d[shape_property]) + ')';
}
if ( Array.isArray(d[property]) ) {
var color_node = _helpers.set_color(property, d[property][0][0]);
d[property].forEach(function(p) {
if ( time.between(p[1], p[2]) ) color_node = _helpers.set_color(property, p[0]);
});
return color_node;
} else {
return _helpers.set_color(property, d[property]);
}
})
.style('stroke', function(d) {
if (_helpers.set_shape(d[shape_property]) !== (-1))
if ( Array.isArray(d[property]) ) {
var color_node = _helpers.set_color(property, d[property][0][0]);
d[property].forEach(function(p) {
if ( time.between(p[1], p[2]) ) color_node = _helpers.set_color(property, p[0]);
});
return color_node;
} else {
return _helpers.set_color(property, d[property]);
}
else
return '#ffffff';
})
.on('dblclick', function(d) {
d3.event.stopPropagation();
if (d === lastFocusNode) {
lastFocusNode = undefined;
node.style('opacity', 1);
link.style('opacity', 1);
} else {
lastFocusNode = d;
_helpers.set_focus(d);
}
});
},
set_link: function(link) {
// Remove links if data has more links than before
link.enter().append('line')
.attr('class', 'link')
.style('stroke-width', function (d) {
return Math.sqrt(d.value);
});
// Remove links if data has less links than before
link.exit().remove();
},
isConnected: function(source, neighbour) {
return linkedByIndex[source.id + ',' + neighbour.id] ||
linkedByIndex[neighbour.id + ',' + source.id];
},
set_focus: function(d) {
node.style('opacity', function(o) {
return _helpers.isConnected(d,o) || d.index == o.index ? 1 : focus_opacity;
});
link.style('opacity', function(o) {
return o.source.index == d.index || o.target.index == d.index ? 1 : focus_opacity;
});
},
push_once: function(array, item, key) {
for (var i in array) {
if ( array[i][key] == item[key] ) return false;
}
array.push(item);
return true;
},
set_color: function(property, value) {
if ( colors instanceof Array ) {
for ( var c in colors ) {
if ( colors[c][property] == value ) { return colors[c]['color']; }
}
return color(value);
} else {
return color(value);
}
},
set_shape: function(value) {
if ( shapes instanceof Object && shape_property ) {
for ( var s in shapes ) {
var str_value = (value.includes('class')) ? value.split('.').pop().split('\'')[0] : value;
if ( str_value == s ) return shapes[s];
}
return (-1);
} else {
return (-1);
}
}
}
/**
* Graph Visualization Core Functions
* ----------------------------------
*
* The graph visualization functions themselves.
*/
function Graph() {
// Color
color = d3.scale.category20();
// Set up the force layout
force = d3.layout.force()
.charge(-500)
.linkDistance(30)
.size([width, height]);
// Append sections to svg to have nodes and edges separately
groot = svg.append('g').attr('id', 'root');
// Set background
if ( background !== undefined ) {
var rect = groot.append('rect').attr('fill', background_filter_color);
background_image = groot.append('image').attr('href', background).style('opacity', background_opacity);
graph_wrapper = groot.append('g') .attr('id', 'graph-wrapper');
glinks = graph_wrapper.append('g') .attr('id', 'links');
gnodes = graph_wrapper.append('g') .attr('id', 'nodes');
} else {
glinks = groot.append('g') .attr('id', 'links');
gnodes = groot.append('g') .attr('id', 'nodes');
}
// Add patterns for shapes
var defs = [];
for ( var i in shapes )
if (!defs.includes(shapes[i])) defs.push(shapes[i])
svg.append('defs')
.selectAll('pattern')
.data(defs)
.enter()
.append('pattern')
.attr('id', function(d, i) {
return d;
})
.attr('patternUnits', 'objectBoundingBox')
.attr('width', 1)
.attr('height', 1)
.append('image')
.attr('href', function(d) {
return window.location.protocol + '//' + window.location.host + '/img/svg/' + d + '.svg';
})
.attr('width', shape_size)
.attr('height', shape_size);
// Zoom
zoom = d3.behavior
.zoom()
.scaleExtent([1/5, 10])
.on('zoom', function () {
//console.trace("zoom", d3.event.translate, d3.event.scale);
groot.attr('transform',
'translate(' + d3.event.translate + ')scale(' + d3.event.scale + ')');
});
// Activate zoom for the svg item
svg.style('background-color', 'rgb(255,255,255)')
.call(zoom);
// Update linkedByIndex
linkedByIndex = {};
graph.links.forEach(function(d) {
linkedByIndex[d.source.id + ',' + d.target.id] = true;
});
// Creates the graph data structure out of the json data
force.nodes(graph.nodes)
.links(graph.links)
.start();
// Now we are giving the SVGs coordinates - the force layout is generating the coordinates
// which this code is using to update the attributes of the SVG elements
force.on('tick', function () {
link.attr('x1', function (d) {
if ( d.source.scx ) return d.source.scx;
else return d.source.x;
}).attr('y1', function (d) {
if ( d.source.scy ) return d.source.scy;
else return d.source.y;
}).attr('x2', function (d) {
if ( d.target.scx ) return d.target.scx;
else return d.target.x;
}).attr('y2', function (d) {
if ( d.target.scy ) return d.target.scy;
else return d.target.y;
});
node.attr('transform', function translate(d) {
if ( d.scx || d.scy ) return 'translate(' + d.scx + ',' + d.scy + ')';
else return 'translate(' + d.x + ',' + d.y + ')';
});
});
}
function update_data(property, time) {
// Reset data
var delete_links = true;
data_node = [];
data_link = graph.links.slice();
// Nodes
graph.nodes.forEach(function(node) {
if (Array.isArray(node.spells)) {
node.spells.forEach( function(d) {
if ( time.between(d[0], d[1]) ) {
data_node.push(node);
} else {
graph.links.forEach(function(link) {
if (link.source === node || link.target === node)
data_link.splice(data_link.indexOf(link), 1);
});
}
});
} else {
data_node.push(node);
}
});
// Links
graph.links.forEach(function(link) {
if ( !(time.between(link.start, link.end)) && data_link.includes(link) )
data_link.splice(data_link.indexOf(link), 1);
});
// Reset force
force.stop()
.nodes(data_node)
.links(data_link)
.start();
// Create all the line svgs but without locations
link = glinks.selectAll('.link').data(data_link);
_helpers.set_link(link);
// Do the same with the circles for the nodes - no
node = gnodes.selectAll('.node').data(data_node);
_helpers.set_node(node, property, time);
// Node Attributes
var statistics = {}
self.GraphVisualization.statistics = {};
data_node.forEach(function(n) {
// Count node properties
if ( Array.isArray(n[property]) ) {
n[property].forEach(function(p) {
if ( time.between(p[1], p[2]) ) statistics[p[0]] = (!statistics[p[0]]) ? 1 : statistics[p[0]] + 1;
});
} else { statistics[n[property]] = (!statistics[n[property]]) ? 1 : statistics[n[property]] + 1; }
});
for ( i in statistics ) {
statistics[i] = (statistics[i] / data_node.length * 100).toFixed(2);
}
self.GraphVisualization.statistics = statistics
}
function get_models(graph) {
var models = { 'dynamic': [], 'static': [] }
graph['nodes'].forEach(function(node) {
for ( var att in node ) {
if (!required_node.includes(att)) {
if ( Array.isArray(node[att]) ) _helpers.push_once(models['dynamic'], { 'title': att, 'type': node[att][0][0].is_type() }, 'title');
else _helpers.push_once(models['static'], { 'title': att, 'type': typeof(node[att]) }, 'title');
}
}
});
return models;
}
/**
* Public API
* -----------
*
* User-accessible functions.
*/
/**
* Create the space where the graph will we drawn.
* A function that identifies the svg item.
*
* @param {object} id The id of the svg item.
* @return {object} This class.
*/
function create(id, n_height, n_width, callback) {
name = id;
svg = d3.select('svg#' + name)
.attr('width', n_width)
.attr('height', n_height)
.style('background-color', 'rgba(128,128,128,0.1)');
height = n_height;
width = n_width
if (callback) { callback(this.GraphVisualization); }
else { return this.GraphVisualization }
}
/**
* Import JSON and attributes.
* A function that imports the graph and the attributes of all the nodes.
*
* @param {object} json The json structure of the graph.
* @param {object} callback A function called at the end.
*/
function importJSON(json, callback) {
reset()
graph = json;
// Create the graph itself
Graph();
self.GraphVisualization.nodes = graph.nodes.length;
self.GraphVisualization.links = graph.links.length;
self.GraphVisualization.model = get_models(json);
// Draw graph with default property and time for the first time
update_data(self.GraphVisualization.model.dynamic[0].title, 0);
if (callback) { callback(); }
}
/**
* Set link distance.
* A function that set the link distance. If it is not called, it uses 30 as default
*
* @param {object} distance Distance.
* @param {object} callback A function called at the end.
*/
function set_link_distance(distance, callback) {
if (graph) {
force.stop().linkDistance(distance).start();
// Update radius of the nodes to see them better
var r = d3.scale.linear().domain([30, 1000]).range([8, 24]);
radius = r(distance);
node.attr('r', radius);
var s = d3.scale.linear().domain([30, 1000]).range([16, 48]);
if ( shapes instanceof Object && shape_property ) {
svg.selectAll('pattern image').attr('width', s(distance)).attr('height', s(distance));
}
if (callback) { callback(radius); }
}
}
/**
* Set background image.
* A function that set a background image.
*
* @param {object} image Path to image.
*/
function set_background(image, set_opacity, set_color) {
background = image;
background_opacity = set_opacity || 0.8;
background_filter_color = set_color || 'white';
}
/**
* Set property and instant of time.
* A function that draws the graph depends on the property and instant of time selected.
*
* @param {object} property Property to show.
* @param {object} time Instant of time.
* @param {object} callback A function called at the end.
*/
function update_graph(property, time, callback) {
if (graph) {
update_data(property, time);
if (callback) { callback(); }
}
}
/**
* Set shapes and color of graph.
* A function that set the shapes and colors of the nodes depending on their status.
*
* @param {object} set_shapes Shapes for nodes.
* @param {object} set_colors Colors for nodes.
* @param {object} callback A function called at the end.
*/
function set_params(set_shape_property, set_shapes, set_colors, callback) {
shape_property = set_shape_property;
shapes = set_shapes;
colors = set_colors;
self.GraphVisualization.shapes = shapes;
self.GraphVisualization.colors = colors;
if (callback) { callback(); }
}
/**
* Adjust the graph to the whole area.
* A function that adjust the graph to the svg item.
*
* @param {object} padding Space from the graph to the border.
* 85% by default.
* @param {object} transition Duration of the zoom action.
* 750 milliseconds by default.
* @param {object} callback A function called at the end.
*/
function zoom_to_fit(padding, transition, callback) {
var bounds = groot.node().getBBox();
var parent = groot.node().parentElement;
var fullWidth = parent.clientWidth,
fullHeight = parent.clientHeight;
var widthBounds = bounds.width,
heightBounds = bounds.height;
var midX = bounds.x + widthBounds / 2,
midY = bounds.y + heightBounds / 2;
if (widthBounds == 0 || heightBounds == 0) return; // nothing to fit
var scale = (padding || 0.85) / Math.max(widthBounds / fullWidth, heightBounds / fullHeight);
var translate = [fullWidth / 2 - scale * midX, fullHeight / 2 - scale * midY];
//console.trace("zoomFit", translate, scale);
groot
.transition()
.duration(transition || 750) // milliseconds
.call(zoom.translate(translate).scale(scale).event);
if (callback) { callback(); }
}
/**
* Reset the whole graph.
* A function that reset the svg item.
*
*/
function reset() {
d3.select('svg#' + name)
.html('')
.attr('width', width)
.attr('height', height)
.style('background-color', 'rgba(128,128,128,0.1)');
}
/**
* Get color for a value.
* A function that get the color of a node or a group of nodes.
*
* @param {object} value Value.
* @return {object} color The color in hexadecimal.
*/
function color(property, value) {
if (graph) {
return _helpers.set_color(property, value);
}
}
/**
* Get attributes at one moment given.
* A function that get the attributes of all nodes at a specific time.
*
* @param {object} time Instant of time.
* @param {object} callback A function called at the end.
* @return {object} object An object with the number of nodes.
*/
function get_attributes(property, time, callback) {
var attrs = {}
graph.nodes.forEach(function(node) {
if (Array.isArray(node.spells)) {
node.spells.forEach( function(d) {
if ( time.between(d[0], d[1]) ) {
if (Array.isArray(node[property])) {
node[property].forEach( function(p) {
if ( time.between(p[1], p[2]) ) attrs[p[0]] = (!attrs[p[0]]) ? 1 : attrs[p[0]] + 1;
});
} else { attrs[node[property]] = (!attrs[node[property]]) ? 1 : attrs[node[property]] + 1; }
}
});
} else {
if (Array.isArray(node[property])) {
node[property].forEach( function(p) {
if ( time.between(p[1], p[2]) ) attrs[p[0]] = (!attrs[p[0]]) ? 1 : attrs[p[0]] + 1;
});
} else { attrs[node[property]] = (!attrs[node[property]]) ? 1 : attrs[node[property]] + 1; }
}
});
if (callback) { callback(attrs); }
else { return attrs }
}
/**
* Get nodes at one moment given.
* A function that get the number of nodes at a specific time.
*
* @param {object} time Instant of time.
* @param {object} callback A function called at the end.
* @return {object} number The number of nodes.
*/
function get_nodes(time, callback) {
var total_nodes = 0;
graph.nodes.forEach(function(node) {
if (Array.isArray(node.spells)) {
node.spells.forEach( function(d) {
if ( time.between(d[0], d[1]) ) { total_nodes++; }
});
} else {
total_nodes++;
}
});
if (callback) { callback(total_nodes); }
else { return total_nodes }
}
/**
* Exporting
* ---------
*/
this.GraphVisualization = {
// Functions
create: create,
import: importJSON,
update_graph: update_graph,
set_params: set_params,
set_link_distance: set_link_distance,
set_background: set_background,
fit: zoom_to_fit,
reset: reset,
// Attributes
model: {},
nodes: undefined,
links: undefined,
// Getters
color: color,
shapes: shapes,
colors: colors,
get_attributes: get_attributes,
get_nodes: get_nodes,
// Statistics
statistics: {},
// Version
version: '0.1'
};
}).call(this);