summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE.md21
-rw-r--r--README.md91
-rw-r--r--bower.json17
-rw-r--r--gulpfile.js252
-rw-r--r--images/opendc-frontend-component-diagram.pngbin100492 -> 0 bytes
-rw-r--r--images/opendc-frontend-interaction-state-diagram.pngbin41421 -> 0 bytes
-rw-r--r--package.json43
-rw-r--r--src/404.html29
-rw-r--r--src/app.html456
-rw-r--r--src/favicon.icobin99678 -> 0 bytes
-rw-r--r--src/humans.txt27
-rw-r--r--src/img/app/coolingitem.pngbin2853 -> 0 bytes
-rw-r--r--src/img/app/loading.gifbin36550 -> 0 bytes
-rw-r--r--src/img/app/node-cpu.pngbin4062 -> 0 bytes
-rw-r--r--src/img/app/node-gpu.pngbin2227 -> 0 bytes
-rw-r--r--src/img/app/node-memory.pngbin1980 -> 0 bytes
-rw-r--r--src/img/app/node-network.pngbin3058 -> 0 bytes
-rw-r--r--src/img/app/node-storage.pngbin4038 -> 0 bytes
-rw-r--r--src/img/app/psu.pngbin1523 -> 0 bytes
-rw-r--r--src/img/app/rack-energy.pngbin893 -> 0 bytes
-rw-r--r--src/img/app/rack-space.pngbin957 -> 0 bytes
-rw-r--r--src/img/datacenter-drawing.pngbin219576 -> 0 bytes
-rw-r--r--src/img/email-icon.pngbin14761 -> 0 bytes
-rw-r--r--src/img/favicon.pngbin2788 -> 0 bytes
-rw-r--r--src/img/github-icon.pngbin6441 -> 0 bytes
-rw-r--r--src/img/logo.pngbin2825 -> 0 bytes
-rw-r--r--src/img/opendc-splash.pngbin304805 -> 0 bytes
-rw-r--r--src/img/portraits/aiosup.pngbin111629 -> 0 bytes
-rw-r--r--src/img/portraits/gandreadis.pngbin118477 -> 0 bytes
-rw-r--r--src/img/portraits/loverweel.pngbin107768 -> 0 bytes
-rw-r--r--src/img/portraits/mbijman.pngbin111670 -> 0 bytes
-rw-r--r--src/img/stakeholders/Developer.pngbin11411 -> 0 bytes
-rw-r--r--src/img/stakeholders/Manager.pngbin9946 -> 0 bytes
-rw-r--r--src/img/stakeholders/Researcher.pngbin10984 -> 0 bytes
-rw-r--r--src/img/stakeholders/Sales.pngbin10074 -> 0 bytes
-rw-r--r--src/img/stakeholders/Student.pngbin12960 -> 0 bytes
-rw-r--r--src/img/technologies/arrow.pngbin2153 -> 0 bytes
-rw-r--r--src/img/technologies/cogs-icon.pngbin11500 -> 0 bytes
-rw-r--r--src/img/technologies/database-icon.pngbin7848 -> 0 bytes
-rw-r--r--src/img/technologies/webserver-icon.pngbin5762 -> 0 bytes
-rw-r--r--src/img/technologies/www-icon.pngbin11205 -> 0 bytes
-rw-r--r--src/img/tudelfticon.pngbin4387 -> 0 bytes
-rw-r--r--src/index.html413
-rw-r--r--src/navbar.html18
-rw-r--r--src/profile.html62
-rw-r--r--src/projects.html93
-rw-r--r--src/robots.txt4
-rw-r--r--src/scripts/colors.ts43
-rw-r--r--src/scripts/controllers/connection/api.ts1738
-rw-r--r--src/scripts/controllers/connection/cache.ts85
-rw-r--r--src/scripts/controllers/connection/socket.ts76
-rw-r--r--src/scripts/controllers/mapcontroller.ts520
-rw-r--r--src/scripts/controllers/modes/building.ts113
-rw-r--r--src/scripts/controllers/modes/node.ts297
-rw-r--r--src/scripts/controllers/modes/object.ts296
-rw-r--r--src/scripts/controllers/modes/room.ts382
-rw-r--r--src/scripts/controllers/scaleindicator.ts45
-rw-r--r--src/scripts/controllers/simulation/chart.ts241
-rw-r--r--src/scripts/controllers/simulation/statecache.ts321
-rw-r--r--src/scripts/controllers/simulation/taskview.ts64
-rw-r--r--src/scripts/controllers/simulation/timeline.ts161
-rw-r--r--src/scripts/controllers/simulationcontroller.ts586
-rw-r--r--src/scripts/definitions.ts318
-rw-r--r--src/scripts/error404.entry.ts26
-rw-r--r--src/scripts/main.entry.ts69
-rw-r--r--src/scripts/profile.entry.ts40
-rw-r--r--src/scripts/projects.entry.ts651
-rw-r--r--src/scripts/serverconnection.ts59
-rw-r--r--src/scripts/splash.entry.ts157
-rw-r--r--src/scripts/tests/util.spec.ts326
-rw-r--r--src/scripts/user-authentication.ts65
-rw-r--r--src/scripts/util.ts613
-rw-r--r--src/scripts/views/layers/dcobject.ts250
-rw-r--r--src/scripts/views/layers/dcprogressbar.ts99
-rw-r--r--src/scripts/views/layers/gray.ts145
-rw-r--r--src/scripts/views/layers/grid.ts59
-rw-r--r--src/scripts/views/layers/hover.ts129
-rw-r--r--src/scripts/views/layers/layer.ts8
-rw-r--r--src/scripts/views/layers/room.ts177
-rw-r--r--src/scripts/views/layers/roomtext.ts68
-rw-r--r--src/scripts/views/layers/wall.ts62
-rw-r--r--src/scripts/views/mapview.ts373
-rw-r--r--src/styles/404.less147
-rw-r--r--src/styles/main.less1196
-rw-r--r--src/styles/navbar.less158
-rw-r--r--src/styles/profile.less22
-rw-r--r--src/styles/projects.less391
-rw-r--r--src/styles/splash.less440
-rw-r--r--src/unit-tests.html15
-rw-r--r--tsconfig.json45
-rw-r--r--tslint.json75
-rw-r--r--typings.json16
92 files changed, 0 insertions, 12693 deletions
diff --git a/LICENSE.md b/LICENSE.md
deleted file mode 100644
index 6fa9989a..00000000
--- a/LICENSE.md
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2017 tudelft-atlarge
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
deleted file mode 100644
index 8d28e84a..00000000
--- a/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# OpenDC Frontend
-
-The OpenDC frontend is the user-facing component of the OpenDC stack, allowing users to build and interact with their own (virtual) datacenters. It is built in TypeScript, using CreateJS for canvas interactions and Gulp for build-automation.
-
-This document gives a high-level view of the frontend architecture ([jump](#architecture)), and describes how to set it up for local development ([jump](#setup-for-local-development)).
-
-## Architecture
-
-### Application Interaction Model
-Let's first take a look at how the user interacts with the frontend.
-
-#### Pages
-The user starts at the splashpage (`index.html`) where he/she gets a first impression of OpenDC, including screenshots and features. After signing in with Google Authentication, the user is redirected to the page listing all projects (`projects.html`) shared or owned by that user. Here the user also has the possibility to open a particular project, redirecting to the main application page (`app.html`).
-
-#### Main Application
-The main application allows the user to construct and simulate a datacenter. To understand how the user can do this, have a look at the state diagram below. It visualizes the main interactions a user can make with the application, as well as under which conditions those can happen.
-
-![OpenDC Frontend Interaction State Diagram](https://raw.githubusercontent.com/atlarge-research/opendc-frontend/master/images/opendc-frontend-interaction-state-diagram.png)
-
-### Components
-Under the hood, this looks as follows:
-
-![OpenDC Frontend Component Diagram](https://raw.githubusercontent.com/atlarge-research/opendc-frontend/master/images/opendc-frontend-component-diagram.png)
-
-*Squared-off colored boxes indicate packages (colors become more saturated as packages are nested); rounded-off boxes indicate individual components; dotted lines indicate control flow; and solid lines indicate data flow.*
-
-#### Entry Scripts
-The entry scripts are the first entities triggered on page load of the respective pages. They are responsible for instantiating the corresponding view and controller.
-
-#### Controllers
-In the main web-application, the controllers handle user input and state. They also initiate re-renders of views when a part of their managed state changes. There are different classes of controllers; some concerning themselves with the API connection, others with the different modes of interaction, and others with simulation-specific actions. This all is orchestrated by a central class called the `MapController`.
-
-#### Views
-The views are responsible for drawing content to the canvas. They are split up into different layers, corresponding to the way they are rendered.
-
-## Setup for Local Development
-
-### Initial setup
-
-#### Setting up the server
-To be able to see the frontend run in your browser, first set up the web server. The steps needed for this are listed on [the `opendc-web-server` repo](https://github.com/atlarge-research/opendc-web-server).
-
-Once the web-server is set up, clone [this frontend-repo](https://github.com/atlarge-research/opendc-frontend.git) into the same base-directory as the repos you cloned during server setup:
-
-```bash
-git clone https://github.com/atlarge-research/opendc-frontend.git
-```
-
-Change directory to that new directory, and you're ready to continue to the frontend setup steps below.
-
-#### Resolving dependencies
-We use the NPM package repository to manage our third-party dependencies on the frontend. To fetch and install these dependencies, you'll need to have the [Node.js](https://nodejs.org/en/) environment installed.
-
-For easier fetching, we recommend the [Yarn Package Manager](https://yarnpkg.com), but the standard NPM tool will suffice, too. You can get your build setup installed by executing the following two commands:
-
-```bash
-npm install -g yarn
-npm install -g gulp
-```
-
-You may need to prepend these commands with `sudo`, if you are on a Debian-based Linux machine. If you're having trouble giving NPM the necessary permissions on such a machine, have a look at [this NPM documentation page](https://docs.npmjs.com/getting-started/fixing-npm-permissions).
-
-### Building the project
-First, create a configuration file called `config.json` in the root of the `opendc-frontend` directory, with the following template:
-
-```json
-{
- "OAUTH_CLIENT_ID": "the-google-oauth-client-id",
- "SERVER_BASE_URL": "http://localhost:8081"
-}
-```
-
-Be sure to replace `the-google-oauth-client-id` with your actual OAuth client ID.
-
-Finally, run the following commands from this directory to fetch dependencies and compile the code of the frontend side:
-
-```bash
-yarn
-gulp
-```
-
-*Note: If you wish to use a configuration file from a different location, pass a `--config=...` parameter to the `gulp` command, providing the relative path to the file to be used.*
-
-### Automatically triggered builds
-To make development easier, we've set up a `watch` task. With this task, you can quickly see what effects a certain change has on the program. It runs in the background, automatically triggering a rebuild of relevant files on file-change.
-
-Start it by executing:
-
-```bash
-gulp watch
-```
diff --git a/bower.json b/bower.json
deleted file mode 100644
index 1dcf5964..00000000
--- a/bower.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name": "opendc",
- "description": "Datacenter simulator",
- "authors": [
- "Georgios Andreadis <g.andreadis@student.tudelft.nl>"
- ],
- "license": "MIT",
- "homepage": "http://opendc.org",
- "private": true,
- "dependencies": {
- "EaselJS": "^0.8.2",
- "PreloadJS": "^0.6.2",
- "TweenJS": "^0.6.2",
- "bootstrap": "^3.3.6",
- "c3": "^0.4.11"
- }
-}
diff --git a/gulpfile.js b/gulpfile.js
deleted file mode 100644
index f674055e..00000000
--- a/gulpfile.js
+++ /dev/null
@@ -1,252 +0,0 @@
-/**
- * Build file for the frontend codebase of OpenDC.
- *
- * Usage:
- * $ gulp --config=config.json # for a single build
- * $ gulp watch --config=config.json # to run once, watch for changes, and rebuild when something changed
- *
- * If the `config` argument is omitted, the config file is assumed to be named `config.json` and present in this
- * directory.
- */
-
-'use strict';
-
-const argv = require('yargs').argv;
-
-const gulp = require('gulp');
-const notify = require('gulp-notify');
-const gulpUtil = require('gulp-util');
-const rename = require('gulp-rename');
-const replace = require('gulp-replace');
-const del = require('del');
-const fs = require('fs');
-const runSequence = require('run-sequence');
-const source = require('vinyl-source-stream');
-const es = require('event-stream');
-const less = require('gulp-less');
-const browserify = require('browserify');
-const watchify = require('watchify');
-const tsify = require('tsify');
-const gulpTypings = require("gulp-typings");
-const processHTML = require('gulp-processhtml');
-const bower = require('gulp-bower');
-
-
-/**
- * Checks whether the configuration file is specified and reads its contents.
- *
- * @throws an Exception if the config file could not be found or read (logs appropriately to the console)
- * @returns {Object} the config file contents.
- */
-function getConfigFile() {
- let configInput = argv.config;
-
- if (configInput === undefined) {
- if (!fs.existsSync("./config.json")) {
- gulpUtil.log(gulpUtil.colors.red('Config file argument missing\n'), 'Usage:\n' +
- ' $ gulp --config=config.json');
- throw new Exception();
- } else {
- gulpUtil.log(gulpUtil.colors.magenta('No config file argument, assuming `config.json`.'));
- configInput = "config.json";
- }
- }
-
- try {
- let configFilePath;
- if (configInput.indexOf('/') === -1) {
- configFilePath = './' + configInput;
- } else {
- configFilePath = configInput;
- }
-
- return require(configFilePath);
- } catch (error) {
- gulpUtil.log(gulpUtil.colors.red('Config file could not be read'), error);
- throw new Exception();
- }
-}
-
-
-/**
- * Stylesheet task.
- */
-const stylesRootDir = './src/styles/';
-const stylesDestDir = './build/styles/';
-
-const styleFileNames = ['main', 'splash', 'projects', 'profile', 'navbar', '404'];
-const styleFilePaths = styleFileNames.map(function (fileName) {
- return stylesRootDir + fileName + '.less';
-});
-
-gulp.task('styles', function () {
- return gulp.src(styleFilePaths)
- .pipe(less())
- .pipe(gulp.dest(stylesDestDir))
- .pipe(notify({message: 'Styles task complete', onLast: true}));
-});
-
-
-/**
- * Script task.
- */
-const scriptsRootDir = './src/scripts/';
-const scriptsDestDir = './build/scripts/';
-
-const postfix = '.entry';
-const scriptsFileNames = ['splash', 'main', 'projects', 'profile', 'error404'];
-const scriptsFilePaths = scriptsFileNames.map(function (fileName) {
- return scriptsRootDir + fileName + postfix + '.ts';
-});
-
-gulp.task('scripts', function () {
- const configFile = getConfigFile();
-
- const tasks = scriptsFilePaths.map(function (entry, index) {
- return browserify({
- entries: [entry],
- debug: false,
- insertGlobals: true,
- cache: {},
- packageCache: {}
- })
- .plugin(tsify)
- .bundle()
- .pipe(source(scriptsFileNames[index] + postfix + '.js'))
- .pipe(replace('SERVER_BASE_URL', configFile.SERVER_BASE_URL))
- .pipe(gulp.dest(scriptsDestDir));
- });
- return es.merge.apply(null, tasks)
- .pipe(notify({message: 'Scripts task complete', onLast: true}));
-});
-
-function getWatchifyHandler(bundler, fileName) {
- const configFile = getConfigFile();
-
- return () => {
- gulpUtil.log('Beginning build for ' + fileName);
- return bundler
- .bundle()
- .pipe(source(fileName + postfix + '.js'))
- .pipe(replace('SERVER_BASE_URL', configFile.SERVER_BASE_URL))
- .pipe(gulp.dest(scriptsDestDir));
- };
-}
-
-gulp.task('watch-scripts', function () {
- const tasks = scriptsFilePaths.map(function (entry, index) {
- const watchedBrowserify = watchify(browserify({
- entries: [entry],
- debug: false,
- cache: {},
- packageCache: {},
- insertGlobals: true,
- poll: 100
- }).plugin(tsify));
- const watchFunction = getWatchifyHandler(watchedBrowserify, scriptsFileNames[index]);
-
- watchedBrowserify.on('update', watchFunction);
- watchedBrowserify.on('log', gulpUtil.log);
- return watchFunction();
- });
-
- return es.merge.apply(null, tasks)
- .pipe(notify({message: 'Scripts watch task complete', onLast: true}));
-});
-
-
-/**
- * TypeScript definitions task.
- */
-gulp.task("typings", function () {
- return gulp.src("./typings.json")
- .pipe(gulpTypings())
- .pipe(notify({message: 'Typings task complete'}));
-});
-
-
-/**
- * HTML task.
- */
-const htmlRootDir = './src/';
-const htmlDestDir = './build/';
-
-const htmlFileNames = ['index', 'app', 'projects', 'profile', '404'];
-const htmlFilePaths = htmlFileNames.map(function (fileName) {
- return htmlRootDir + fileName + '.html';
-});
-
-gulp.task('html', function () {
- const configFile = getConfigFile();
-
- return gulp.src(htmlFilePaths)
- .pipe(replace('OAUTH_CLIENT_ID', configFile.OAUTH_CLIENT_ID))
- .pipe(replace('SERVER_BASE_URL', configFile.SERVER_BASE_URL))
- .pipe(processHTML())
- .pipe(gulp.dest(htmlDestDir))
- .pipe(notify({message: 'HTML task complete', onLast: true}));
-});
-
-
-/**
- * Images task.
- */
-const imagesRootDir = './src/img/';
-const imagesDestDir = './build/img/';
-
-const imagesFilePaths = [imagesRootDir + '**/*.png', imagesRootDir + '**/*.gif'];
-
-gulp.task('images', function () {
- return gulp.src(imagesFilePaths)
- .pipe(gulp.dest(imagesDestDir))
- .pipe(notify({message: 'Images task complete', onLast: true}));
-});
-
-
-/**
- * Clean task.
- */
-gulp.task('clean', function () {
- return del(['./build']);
-});
-
-
-/**
- * Bower task.
- */
-gulp.task('bower', function () {
- return bower({cmd: 'install'}, ['--allow-root'])
- .pipe(notify({message: 'Bower task complete', onLast: true}));
-});
-
-
-/**
- * Default build task.
- */
-gulp.task('default', function () {
- try {
- getConfigFile();
- } catch (error) {
- return;
- }
- runSequence('clean', 'typings', 'styles', 'bower', 'scripts', 'html', 'images');
-});
-
-
-/**
- * Watch task.
- */
-gulp.task('watch', function () {
- try {
- getConfigFile();
- } catch (error) {
- return;
- }
-
- runSequence('default', () => {
- gulp.watch(stylesRootDir + '**/*.less', ['styles']);
- gulp.start('watch-scripts');
- gulp.watch(htmlRootDir + '**/*.html', ['html']);
- gulp.watch(imagesRootDir + '**/*.png', ['images']);
- });
-});
diff --git a/images/opendc-frontend-component-diagram.png b/images/opendc-frontend-component-diagram.png
deleted file mode 100644
index 5d6c4704..00000000
--- a/images/opendc-frontend-component-diagram.png
+++ /dev/null
Binary files differ
diff --git a/images/opendc-frontend-interaction-state-diagram.png b/images/opendc-frontend-interaction-state-diagram.png
deleted file mode 100644
index 7c93358a..00000000
--- a/images/opendc-frontend-interaction-state-diagram.png
+++ /dev/null
Binary files differ
diff --git a/package.json b/package.json
deleted file mode 100644
index c4f24dd3..00000000
--- a/package.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "name": "opendc",
- "version": "0.0.1",
- "description": "Datacenter simulator",
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "https://github.com/tudelft-atlarge/opendc"
- },
- "dependencies": {
- "bower": "^1.7.9",
- "browserify": "^13.1.1",
- "c3": "^0.4.11",
- "del": "^2.2.2",
- "event-stream": "^3.3.4",
- "file-loader": "^0.9.0",
- "gulp": "^3.9.1",
- "gulp-bower": "^0.0.13",
- "gulp-less": "^3.3.0",
- "gulp-notify": "^2.2.0",
- "gulp-processhtml": "^1.1.0",
- "gulp-rename": "^1.2.2",
- "gulp-replace": "^0.5.4",
- "gulp-typings": "^2.0.4",
- "gulp-util": "^3.0.8",
- "jquery": "^3.1.0",
- "jquery-mousewheel": "^3.1.13",
- "jquery.easing": "^1.4.1",
- "less": "^2.7.1",
- "run-sequence": "^1.2.2",
- "socket.io-client": "^1.4.8",
- "tsify": "^2.0.2",
- "tslint": "^3.10.2",
- "typescript": "^2.1.4",
- "typings": "^1.3.2",
- "vinyl-source-stream": "^1.1.0",
- "watchify": "^3.9.0",
- "yargs": "^6.6.0"
- },
- "devDependencies": {
- "jasmine-core": "^2.4.1"
- }
-}
diff --git a/src/404.html b/src/404.html
deleted file mode 100644
index 10f79525..00000000
--- a/src/404.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <title>404 Error | OpenDC</title>
-
- <link href="styles/404.css" rel="stylesheet" type="text/css">
-
- <!-- Favicon -->
- <link href="img/logo.png" rel="icon">
-</head>
-<body>
-<div class="terminal-window">
- <div class="terminal-header">Terminal -- bash</div>
- <div class="terminal-body">
- <div class="segfault">$ status <br>
- opendc[4264]: segfault at 0000051497be459d1 err 12 in libopendc.9.0.4<br>
- opendc[4269]: segfault at 000004234855fc2db err 3 in libopendc.9.0.4<br>
- opendc[4270]: STDERR Page does not exist
- </div>
- <div class="code-block"></div>
- <div class="sub-title">Got lost?<span class="cursor">_</span></div>
- <a class="home-btn" href="SERVER_BASE_URL">GET ME BACK TO OPENDC</a>
- </div>
-</div>
-
-<script src="scripts/error404.entry.js"></script>
-</body>
-</html>
diff --git a/src/app.html b/src/app.html
deleted file mode 100644
index 5b669910..00000000
--- a/src/app.html
+++ /dev/null
@@ -1,456 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="google-signin-client_id" content="OAUTH_CLIENT_ID">
-
- <title>OpenDC</title>
-
- <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
- <link href="bower_components/c3/c3.min.css" rel="stylesheet">
-
- <link href="styles/navbar.css" rel="stylesheet" type="text/css">
- <link href="styles/main.css" rel="stylesheet" type="text/css">
-
- <link href="img/logo.png" rel="icon">
-</head>
-<body>
-<!-- build:include navbar.html -->
-<!-- /build -->
-<div class="app-content">
- <!-- The main map canvas (the dimensions given are fallbacks, for when dynamic resizing doesn't work)-->
- <canvas id="main-canvas" width="800" height="600">
- Sorry, but it seems your browser does not support the HTML5 canvas.
- </canvas>
-
- <div class="side-menu-container right-middle-side">
- <div class="menu-container level-menu hidden" id="node-menu">
- <div class="menu-header-bar">
- Node
- <button class="menu-exit btn btn-default btn-circle">
- <i class="glyphicon glyphicon-remove"></i>
- </button>
- <button class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <ul class="nav nav-tabs">
- <li class="active">
- <a data-toggle="tab" href="#cpu-tab">
- <img src="img/app/node-cpu.png" alt="CPU tab">
- </a>
- </li>
- <li>
- <a data-toggle="tab" href="#gpu-tab">
- <img src="img/app/node-gpu.png" alt="GPU tab">
- </a>
- </li>
- <li>
- <a data-toggle="tab" href="#memory-tab">
- <img src="img/app/node-memory.png" alt="Memory unit tab">
- </a>
- </li>
- <li>
- <a data-toggle="tab" href="#storage-tab">
- <img src="img/app/node-storage.png" alt="Storage unit tab">
- </a>
- </li>
- <li>
- <a data-toggle="tab" href="#network-tab">
- <img src="img/app/node-network.png" alt="Network unit tab">
- </a>
- </li>
- </ul>
- <div class="tab-content">
- <div id="cpu-tab" class="tab-pane fade in active">
- <h3>CPUs</h3>
- <h4>Add a new CPU</h4>
- <div class="unit-add-input input-group" id="add-cpu-form">
- <select class="form-control" title="Generation">
- <!-- Populated at runtime with a list of available units -->
- </select>
- <span class="input-group-btn"><button class="btn btn-default add-unit">Add</button></span>
- </div>
- <div class="panel-group" id="cpu-accordion">
- <!-- Populated at runtime with CPU info -->
- </div>
- </div>
- <div id="gpu-tab" class="tab-pane fade">
- <h3>GPUs</h3>
- <h4>Add a new GPU</h4>
- <div class="unit-add-input input-group" id="add-gpu-form">
- <select class="form-control" title="Generation">
- <!-- Populated at runtime with a list of available units -->
- </select>
- <span class="input-group-btn"><button class="btn btn-default add-unit">Add</button></span>
- </div>
- <div class="panel-group" id="gpu-accordion">
- <!-- Populated at runtime with GPU info -->
- </div>
- </div>
- <div id="memory-tab" class="tab-pane fade">
- <h3>Memory Units</h3>
- <h4>Add a new memory unit</h4>
- <div class="unit-add-input input-group" id="add-memory-form">
- <select class="form-control" title="Generation">
- <!-- Populated at runtime with a list of available units -->
- </select>
- <span class="input-group-btn"><button class="btn btn-default add-unit">Add</button></span>
- </div>
- <div class="panel-group" id="memory-accordion">
- <!-- Populated at runtime with memory info -->
- </div>
- </div>
- <div id="storage-tab" class="tab-pane fade">
- <h3>Storage Units</h3>
- <h4>Add a new storage unit</h4>
- <div class="unit-add-input input-group" id="add-storage-form">
- <select class="form-control" title="Generation">
- <!-- Populated at runtime with a list of available units -->
- </select>
- <span class="input-group-btn"><button class="btn btn-default add-unit">Add</button></span>
- </div>
- <div class="panel-group" id="storage-accordion">
- <!-- Populated at runtime with storage info -->
- </div>
- </div>
- <div id="network-tab" class="tab-pane fade">
- <h3>Network cards</h3>
- <div>This machine has a standard, industry-grade network unit</div>
- </div>
- </div>
- </div>
- <div class="menu-body simulation">
- <div id="machine-statistics-chart"></div>
- </div>
- </div>
- </div>
-
- <div class="side-menu-container right-side">
- <div class="menu-container level-menu" id="building-menu">
- <div class="menu-header-bar">
- Building
- <button type="button" class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <div class="btn btn-primary btn-block" id="room-construction">
- Construct new room
- </div>
- <div class="btn btn-default btn-block" id="room-construction-cancel">
- Cancel
- </div>
- </div>
- <div class="menu-body simulation">
- <div class="building-stats-list">
- <!-- Populated at runtime with dynamic simulation stats -->
- </div>
- </div>
- </div>
-
- <div class="menu-container level-menu hidden" id="room-menu">
- <div class="menu-header-bar">
- Room
- <button type="button" class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <div class="input-group">
- <input type="text" class="form-control" id="room-name-input" placeholder="Room name...">
- <span class="input-group-btn"><button class="btn btn-default" id="room-name-save"
- type="button">Save</button></span>
- </div>
- <div class="input-group">
- <div class="input-group-addon">Room type:</div>
- <select class="form-control" title="Room Type" id="roomtype-select">
- <!-- Populated at runtime with all available room types -->
- </select>
- </div>
- <label id="add-objects-label">Add objects:</label>
- <div class="dc-component-container hidden" id="add-rack-btn" data-active="false">
- <div class="dc-component dc-rack"></div>
- <div class="dc-component-label">Rack</div>
- </div>
- <div class="dc-component-container hidden" id="add-psu-btn" data-active="false">
- <div class="dc-component dc-psu"></div>
- <div class="dc-component-label">Power Supply Unit</div>
- </div>
- <div class="dc-component-container hidden" id="add-cooling-item-btn" data-active="false">
- <div class="dc-component dc-cooling-item"></div>
- <div class="dc-component-label">Cooling Item</div>
- </div>
- <label class="hidden" id="no-objects-info">
- No objects are allowed in this type of room. <br>
- Change the room type to be able to add elements.
- </label>
- <div class="btn btn-danger btn-block" id="room-deletion">
- Delete this room
- </div>
- </div>
- <div class="menu-body simulation">
- <h3 id="room-name-field"></h3>
- <h5 id="room-type-field"></h5>
- <div class="room-stats-list">
- <!-- Populated at runtime, with simulation stats per rack -->
- </div>
- </div>
- </div>
-
- <div class="menu-container level-menu hidden" id="object-menu">
- <div id="rack-sub-menu" class="object-sub-menu">
- <div class="menu-header-bar">
- Rack
- <button class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <div class="input-group">
- <input type="text" class="form-control" id="rack-name-input" placeholder="Rack name...">
- <span class="input-group-btn"><button class="btn btn-default" id="rack-name-save"
- type="button">Save</button></span>
- </div>
- <div class="node-list-container">
- <!-- Populated at runtime with node data -->
- </div>
- <div class="btn btn-danger btn-block" id="rack-deletion">
- Delete this rack
- </div>
- </div>
- <div class="menu-body simulation">
- <div class="node-list-container">
- <!-- Populated at runtime with node simulation stats -->
- </div>
- </div>
- </div>
- <div id="psu-sub-menu" class="object-sub-menu">
- <div class="menu-header-bar">
- Power Supply Unit
- <button class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <div class="btn btn-danger btn-block" id="psu-deletion">
- Delete this PSU
- </div>
- </div>
- <div class="menu-body simulation">
- </div>
- </div>
- <div id="cooling-item-sub-menu" class="object-sub-menu">
- <div class="menu-header-bar">
- Cooling Item
- <button class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body construction">
- <div class="btn btn-danger btn-block" id="cooling-item-deletion">
- Delete this cooling item
- </div>
- </div>
- <div class="menu-body simulation">
- </div>
- </div>
- </div>
- <div class="menu-container hidden" id="statistics-menu">
- <div class="menu-header-bar">
- Statistics
- <button type="button" class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body simulation">
- <div id="statistics-chart"></div>
- </div>
- </div>
- </div>
-
- <div class="side-menu-container left-side">
- <div class="mode-switch" data-selected="construction" role="group" aria-label="Mode switch">
- <div id="construction-mode-switch">Construction</div>
- <div id="simulation-mode-switch">Simulation</div>
- </div>
- <div id="save-version-btn" data-saved="true">Save version</div>
- <div class="menu-container hidden" id="experiment-menu">
- <div class="menu-header-bar">
- Experiment
- <button type="button" class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body simulation">
- <p><strong>Name:</strong> <span id="experiment-menu-name">Name</span></p>
- <p><strong>Path:</strong> <span id="experiment-menu-path">Path</span></p>
- <p><strong>Trace:</strong> <span id="experiment-menu-trace">Trace</span></p>
- <p><strong>Scheduler:</strong> <span id="experiment-menu-scheduler">Scheduler</span></p>
- <div id="change-experiment-btn" class="btn btn-default btn-block">Change experiment</div>
- </div>
- </div>
- <div class="menu-container hidden" id="tasks-menu">
- <div class="menu-header-bar">
- Tasks
- <button type="button" class="menu-collapse btn btn-default btn-circle">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- </div>
- <div class="menu-body simulation">
- <div class="task-list">
- <!-- Populated at runtime with a number of task elements -->
- </div>
- </div>
- </div>
- </div>
-
- <div class="tool-panel">
- <button type="button" class="btn btn-default btn-circle" id="zoom-plus" title="Zoom in">
- <i class="glyphicon glyphicon-plus"></i>
- </button>
- <button type="button" class="btn btn-default btn-circle" id="zoom-minus" title="Zoom out">
- <i class="glyphicon glyphicon-minus"></i>
- </button>
- <button type="button" class="btn btn-success btn-circle export-canvas" title="Export Canvas to PNG Image">
- <i class="glyphicon glyphicon-camera"></i>
- </button>
- </div>
-
- <!-- Map indicators -->
- <div class="indicators">
- <div class="scale-indicator">
- 0.5m
- </div>
- <div class="color-indicator hidden">
- <div class="intensity-labels">
- <div>0</div>
- <div>25</div>
- <div>50</div>
- <div>75</div>
- <div>100</div>
- </div>
- <div class="intensity-colors">
- <div class="intensity-low"></div>
- <div class="intensity-mid-low"></div>
- <div class="intensity-mid-high"></div>
- <div class="intensity-high"></div>
- </div>
- </div>
- </div>
-
- <!-- Timeline bar, for simulation playback -->
- <div class="timeline-bar">
- <div class="timeline-container hidden">
- <div class="labels">
- <div class="start-time-label">00:00:00</div>
- <div class="end-time-label">00:00:00</div>
- </div>
- <div class="controls">
- <div class="play-btn glyphicon glyphicon-play"><img src="img/app/loading.gif"></div>
- <div class="timeline">
- <div class="cache-section"></div>
- <div class="time-marker"></div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Informational Balloon Popup -->
- <div class="info-balloon">
- <span></span>Test Info
- </div>
-
- <!-- Overlay for DC loading process -->
- <div class="loading-overlay">
- <div class="loading-overlay-content">
- <img src="img/logo.png">
- <div class="loading-text">
- <h3>Loading your project...</h3>
- <p class="muted">Fetching the DC</p>
- </div>
- </div>
- </div>
-</div>
-
-<div class="modal fade" id="confirm-delete" tabindex="-1" role="dialog" aria-labelledby="confirm-delete-header">
- <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" id="confirm-delete-header">Confirm delete</h4>
- </div>
- <div class="modal-body">
- Are you sure you want to delete this item?
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-danger confirm">Delete</button>
- </div>
- </div>
- </div>
-</div>
-
-<div class="window-overlay">
- <div class="experiments-window" id="experiments-window">
- <div class="window-close glyphicon glyphicon-remove"></div>
- <div class="window-body">
- <div class="window-heading">Experiments</div>
- <form class="form-inline experiment-add-form">
- <div class="form-group">
- <label for="new-experiment-name-input">Name</label>
- <input type="text" class="form-control" id="new-experiment-name-input"
- placeholder="Experiment name">
- <label for="new-experiment-path-select">Path</label>
- <select class="form-control" id="new-experiment-path-select">
- </select>
- </div>
- <div class="form-group">
- <label for="new-experiment-trace-select">Trace</label>
- <select class="form-control" id="new-experiment-trace-select">
- </select>
- <label for="new-experiment-scheduler-select">Scheduler</label>
- <select class="form-control" id="new-experiment-scheduler-select">
- </select>
- <div class="btn btn-default" id="new-experiment-btn">Save &amp; Launch</div>
- </div>
- </form>
- <strong class="experiments-table-label">Previous Experiments</strong>
- <div class="experiment-list">
- <div class="list-head">
- <div>Name</div>
- <div>Path</div>
- <div>Trace</div>
- <div>Scheduler</div>
- <div></div>
- </div>
- <div class="list-body">
- </div>
- </div>
- <div class="no-experiments-alert alert alert-info">
- <span class="glyphicon glyphicon-info-sign"></span>
- <strong>No experiments here yet...</strong> Add some with the form above!
- </div>
- <div class="experiment-name-alert alert alert-danger" role="alert">
- <strong>Warning:</strong> Your experiment needs a name!
- </div>
- </div>
- </div>
-</div>
-
-<!-- Bower dependencies that cannot be included via the module system -->
-<script src="bower_components/EaselJS/lib/easeljs-0.8.2.min.js"></script>
-<script src="bower_components/TweenJS/lib/tweenjs-0.6.2.min.js"></script>
-<script src="bower_components/PreloadJS/lib/preloadjs-0.6.2.min.js"></script>
-
-<script src="scripts/main.entry.js"></script>
-
-<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
-
-<!-- Google API -->
-<script src="https://apis.google.com/js/platform.js?onload=gapiSigninButton" async defer></script>
-
-</body>
-</html>
diff --git a/src/favicon.ico b/src/favicon.ico
deleted file mode 100644
index c2f40a0d..00000000
--- a/src/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/src/humans.txt b/src/humans.txt
deleted file mode 100644
index 652f9cd2..00000000
--- a/src/humans.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-/* TEAM */
-Benevolent Dictator for Life: Alexandru Iosup.
-Site: http://www.ds.ewi.tudelft.nl/~iosup/
-Twitter: aiosup.
-Location: Delft, Netherlands.
-
-Backend Engineer: Leon Overweel.
-Site: http://leonoverweel.com/
-Twitter: layon_overwhale.
-Location: Delft, Netherlands.
-
-Frontend Engineer: Georgios Andreadis.
-Site: https://github.com/gandreadis
-Location: Delft, Netherlands.
-
-Simulation Engineer: Matthijs Bijman.
-Site: https://github.com/MDBijman
-Location: Delft, Netherlands.
-
-/* THANKS */
-Executive Producer: Vincent van Beek.
-Executive Producer: Tim Hegeman.
-
-/* SITE */
-Standards: HTML5, CSS3, ES5
-Components: jQuery, Bootstrap, CreateJS, c3.js
-Software: WebStorm, Vim, Visual Studio \ No newline at end of file
diff --git a/src/img/app/coolingitem.png b/src/img/app/coolingitem.png
deleted file mode 100644
index 16c18be0..00000000
--- a/src/img/app/coolingitem.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/loading.gif b/src/img/app/loading.gif
deleted file mode 100644
index c6394822..00000000
--- a/src/img/app/loading.gif
+++ /dev/null
Binary files differ
diff --git a/src/img/app/node-cpu.png b/src/img/app/node-cpu.png
deleted file mode 100644
index 07cfbd31..00000000
--- a/src/img/app/node-cpu.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/node-gpu.png b/src/img/app/node-gpu.png
deleted file mode 100644
index 55d4fb05..00000000
--- a/src/img/app/node-gpu.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/node-memory.png b/src/img/app/node-memory.png
deleted file mode 100644
index 36e8a44e..00000000
--- a/src/img/app/node-memory.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/node-network.png b/src/img/app/node-network.png
deleted file mode 100644
index 795e173b..00000000
--- a/src/img/app/node-network.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/node-storage.png b/src/img/app/node-storage.png
deleted file mode 100644
index 7a39cb6f..00000000
--- a/src/img/app/node-storage.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/psu.png b/src/img/app/psu.png
deleted file mode 100644
index 471af6ee..00000000
--- a/src/img/app/psu.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/rack-energy.png b/src/img/app/rack-energy.png
deleted file mode 100644
index 1088c61b..00000000
--- a/src/img/app/rack-energy.png
+++ /dev/null
Binary files differ
diff --git a/src/img/app/rack-space.png b/src/img/app/rack-space.png
deleted file mode 100644
index 387d7ea6..00000000
--- a/src/img/app/rack-space.png
+++ /dev/null
Binary files differ
diff --git a/src/img/datacenter-drawing.png b/src/img/datacenter-drawing.png
deleted file mode 100644
index 401168e3..00000000
--- a/src/img/datacenter-drawing.png
+++ /dev/null
Binary files differ
diff --git a/src/img/email-icon.png b/src/img/email-icon.png
deleted file mode 100644
index ced9e175..00000000
--- a/src/img/email-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/favicon.png b/src/img/favicon.png
deleted file mode 100644
index 85d74964..00000000
--- a/src/img/favicon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/github-icon.png b/src/img/github-icon.png
deleted file mode 100644
index 1e221600..00000000
--- a/src/img/github-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/logo.png b/src/img/logo.png
deleted file mode 100644
index d743038b..00000000
--- a/src/img/logo.png
+++ /dev/null
Binary files differ
diff --git a/src/img/opendc-splash.png b/src/img/opendc-splash.png
deleted file mode 100644
index 99fd8658..00000000
--- a/src/img/opendc-splash.png
+++ /dev/null
Binary files differ
diff --git a/src/img/portraits/aiosup.png b/src/img/portraits/aiosup.png
deleted file mode 100644
index 30de349c..00000000
--- a/src/img/portraits/aiosup.png
+++ /dev/null
Binary files differ
diff --git a/src/img/portraits/gandreadis.png b/src/img/portraits/gandreadis.png
deleted file mode 100644
index 403870fa..00000000
--- a/src/img/portraits/gandreadis.png
+++ /dev/null
Binary files differ
diff --git a/src/img/portraits/loverweel.png b/src/img/portraits/loverweel.png
deleted file mode 100644
index d12a9e86..00000000
--- a/src/img/portraits/loverweel.png
+++ /dev/null
Binary files differ
diff --git a/src/img/portraits/mbijman.png b/src/img/portraits/mbijman.png
deleted file mode 100644
index decf9fdd..00000000
--- a/src/img/portraits/mbijman.png
+++ /dev/null
Binary files differ
diff --git a/src/img/stakeholders/Developer.png b/src/img/stakeholders/Developer.png
deleted file mode 100644
index d2638e6c..00000000
--- a/src/img/stakeholders/Developer.png
+++ /dev/null
Binary files differ
diff --git a/src/img/stakeholders/Manager.png b/src/img/stakeholders/Manager.png
deleted file mode 100644
index 92db7459..00000000
--- a/src/img/stakeholders/Manager.png
+++ /dev/null
Binary files differ
diff --git a/src/img/stakeholders/Researcher.png b/src/img/stakeholders/Researcher.png
deleted file mode 100644
index d87edd39..00000000
--- a/src/img/stakeholders/Researcher.png
+++ /dev/null
Binary files differ
diff --git a/src/img/stakeholders/Sales.png b/src/img/stakeholders/Sales.png
deleted file mode 100644
index 5b7c3a72..00000000
--- a/src/img/stakeholders/Sales.png
+++ /dev/null
Binary files differ
diff --git a/src/img/stakeholders/Student.png b/src/img/stakeholders/Student.png
deleted file mode 100644
index a4900303..00000000
--- a/src/img/stakeholders/Student.png
+++ /dev/null
Binary files differ
diff --git a/src/img/technologies/arrow.png b/src/img/technologies/arrow.png
deleted file mode 100644
index 374f78bf..00000000
--- a/src/img/technologies/arrow.png
+++ /dev/null
Binary files differ
diff --git a/src/img/technologies/cogs-icon.png b/src/img/technologies/cogs-icon.png
deleted file mode 100644
index d19e1c20..00000000
--- a/src/img/technologies/cogs-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/technologies/database-icon.png b/src/img/technologies/database-icon.png
deleted file mode 100644
index 26738e76..00000000
--- a/src/img/technologies/database-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/technologies/webserver-icon.png b/src/img/technologies/webserver-icon.png
deleted file mode 100644
index c627106e..00000000
--- a/src/img/technologies/webserver-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/technologies/www-icon.png b/src/img/technologies/www-icon.png
deleted file mode 100644
index e69a54f2..00000000
--- a/src/img/technologies/www-icon.png
+++ /dev/null
Binary files differ
diff --git a/src/img/tudelfticon.png b/src/img/tudelfticon.png
deleted file mode 100644
index a7a2d56a..00000000
--- a/src/img/tudelfticon.png
+++ /dev/null
Binary files differ
diff --git a/src/index.html b/src/index.html
deleted file mode 100644
index c3df0c02..00000000
--- a/src/index.html
+++ /dev/null
@@ -1,413 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <title>OpenDC</title>
-
- <meta name="description" content="Collaborative Datacenter Simulation and Exploration for Everybody">
- <meta name="author" content="Alexandru Iosup, Leon Overweel, Georgios Andreadis, Matthijs Bijman">
- <meta name="keywords" content="OpenDC, Datacenter, Simulation, Simulator, Collaborative, Distributed, Cluster">
-
- <!-- OpenGraph meta tags -->
- <meta property="og:title" content="OpenDC: Collaborative Datacenter Simulation and Exploration for Everybody">
- <meta property="og:type" content="website">
- <meta property="og:image" content="SERVER_BASE_URL/img/opendc-splash.png">
- <meta property="og:url" content="SERVER_BASE_URL">
- <meta property="og:description"
- content="OpenDC provides collaborative online datacenter modeling, diverse and effective datacenter
- simulation, and exploratory datacenter performance feedback.">
- <meta property="og:locale" content="en_US">
-
- <!-- Google Sign-in -->
- <meta name="google-signin-client_id" content="OAUTH_CLIENT_ID">
-
- <!-- Set viewport -->
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-
- <!-- Style sheets -->
- <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
- <link href="styles/splash.css" rel="stylesheet">
-
- <!-- Favicon -->
- <link href="img/logo.png" rel="icon">
-
- <!-- humans.txt -->
- <link type="text/plain" rel="author" href="humans.txt">
-</head>
-<body id="page-top" data-spy="scroll" data-target=".navbar-fixed-top">
-
-<div class="body-wrapper">
-
- <nav class="navbar navbar-inverse navbar-fixed-top navbar-transparent" role="navigation">
- <div class="container">
- <div class="navbar-header page-scroll">
- <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
- <span class="sr-only">Toggle navigation</span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- <span class="icon-bar"></span>
- </button>
- <a class="navbar-brand page-scroll" href="#page-top">
- <img src="img/logo.png" alt="OpenDC Logo">
- </a>
- </div>
-
- <div class="collapse navbar-collapse">
- <ul class="nav navbar-nav">
- <li class="hidden">
- <a class="page-scroll" href="#page-top"></a>
- </li>
- <li>
- <a class="page-scroll" href="#stakeholders">Stakeholders</a>
- </li>
- <li>
- <a class="page-scroll" href="#modeling">Modeling</a>
- </li>
- <li>
- <a class="page-scroll" href="#simulation">Simulation</a>
- </li>
- <li>
- <a class="page-scroll" href="#technologies">Technologies</a>
- </li>
- <li>
- <a class="page-scroll" href="#team">Team</a>
- </li>
- <li>
- <a class="page-scroll" href="#contact">Contact</a>
- </li>
- </ul>
- <div id="google-signin" class="navbar-right"></div>
- <div class="logged-in navbar-right">
- <a class="projects-btn" href="projects">My Projects</a>
- <a class="sign-out glyphicon glyphicon-off" title="Sign out" href="javascript:void(0)"></a>
- </div>
- </div>
-
- </div>
- </nav>
-
- <section class="header-section">
- <div class="container">
- <div class="jumbotron">
- <h1>Open<span class="dc">DC</span></h1>
- <h2>
- Collaborative Datacenter Simulation and Exploration for Everybody
- </h2>
- </div>
- </div>
- </section>
-
- <section id="intro" class="intro-section">
- <div class="container">
- <div class="row">
- <div class="row pitch-container">
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-8
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-2 pitch-column">
- <h3>The datacenter (DC) industry...</h3>
- <ul class="info-points">
- <li>Is worth over $15 bn, and growing</li>
- <li>Has many hard-to-grasp concepts</li>
- <li>Needs to become accessible to many</li>
- </ul>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-8
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-2">
- <img src="img/datacenter-drawing.png" class="col-lg-12 col-md-12 col-sm-12 col-xs-12 dc-image"
- alt="Schematic top-down view on a datacenter">
- <p class="col-lg-12 col-md-12 col-sm-12 col-xs-12 img-source">Image source:
- <a href="http://www.dolphinhosts.co.uk/wp-content/uploads/2013/07/data-centers.gif">
- http://www.dolphinhosts.co.uk/wp-content/uploads/2013/07/data-centers.gif
- </a>
- </p>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-4 col-xs-8
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-2 pitch-column">
- <h3>OpenDC provides...</h3>
- <ul class="info-points">
- <li>Collaborative online DC modeling</li>
- <li>Diverse and effective DC simulation</li>
- <li>Exploratory DC performance feedback</li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="stakeholders" class="stakeholder-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-10 col-md-10 col-sm-10 col-xs-12 col-lg-offset-1 col-md-offset-1 col-sm-offset-1 col-xs-offset-0">
- <h1>Stakeholders</h1>
- <div class="row stakeholder-container">
- <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
- <img src="img/stakeholders/Manager.png" class="col-lg-4 col-md-4 col-sm-4 col-xs-2"
- alt="Managers">
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-10">
- <h3>Managers</h3>
- <p>Seeing is deciding</p>
- </div>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
- <img src="img/stakeholders/Sales.png" class="col-lg-4 col-md-4 col-sm-4 col-xs-2"
- alt="Sales">
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-10">
- <h3>Sales</h3>
- <p>Demo concepts</p>
- </div>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12">
- <img src="img/stakeholders/Developer.png" class="col-lg-4 col-md-4 col-sm-4 col-xs-2"
- alt="DevOps">
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-10">
- <h3>DevOps</h3>
- <p>Develop & tune</p>
- </div>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12 col-lg-offset-2 col-md-offset-2 col-sm-offset-0 col-xs-offset-0">
- <img src="img/stakeholders/Researcher.png" class="col-lg-4 col-md-4 col-sm-4 col-xs-2"
- alt="Researchers">
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-10">
- <h3>Researchers</h3>
- <p>Understand & design</p>
- </div>
- </div>
- <div class="col-lg-4 col-md-4 col-sm-6 col-xs-12 col-md-offset-0 col-sm-offset-3 col-xs-offset-0">
- <img src="img/stakeholders/Student.png" class="col-lg-4 col-md-4 col-sm-4 col-xs-2"
- alt="Students">
- <div class="col-lg-8 col-md-8 col-sm-8 col-xs-10">
- <h3>Students</h3>
- <p>Grasp complex concepts</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="modeling" class="modeling-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h1>Datacenter Modeling</h1>
- <div class="row">
- <div class="col-lg-5 col-md-5 col-sm-5 col-xs-12 text-left">
- <strong class="info-points">Collaboratively...</strong>
- <ul class="info-points key-points">
- <li>Model DC layout, and room locations and types</li>
- <li>Place racks in rooms and nodes in racks</li>
- <li>Add real-world CPU, GPU, memory, storage and network units to each node</li>
- <li>Select from diverse scheduling policies</li>
- </ul>
- </div>
-
-
- <div class="col-lg-7 col-md-7 col-sm-7 col-xs-12">
- <img src="https://github.com/atlarge-research/opendc/raw/master/images/opendc-frontend-construction.PNG" class="col-lg-12 col-md-12 col-sm-12 col-xs-10
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-1"
- alt="Mockup of the datacenter construction interface">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 img-caption">
- Mockup of the datacenter construction interface
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="simulation" class="simulation-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h1>Datacenter Simulation</h1>
- <div class="row simulation-building-row">
- <div class="col-lg-5 col-md-5 col-sm-5 col-xs-12 text-left">
- <strong class="info-points">Working with OpenDC:</strong>
- <ul class="info-points key-points">
- <li>Seamlessly switch between construction and simulation modes
- <li>Choose one of several predefined workloads (Big Data, Bag of Tasks,
- Hadoop, etc.)
- <li>Play, pause, and skip around the informative simulation timeline
- <li>Visualize and demo live
- </ul>
- </div>
- <div class="col-lg-7 col-md-7 col-sm-7 col-xs-12">
- <img src="https://github.com/atlarge-research/opendc/raw/master/images/opendc-frontend-simulation.PNG" class="col-lg-12 col-md-12 col-sm-12 col-xs-10
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-1"
- alt="Mockup of the datacenter simulation interface at room level">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 img-caption">
- Mockup of the datacenter simulation interface at room level
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-lg-5 col-md-5 col-sm-5 col-xs-12 text-left">
- <strong class="info-points">Key features:</strong>
- <ul class="info-points key-points">
- <li>Live load or power use metrics on building, room, and rack levels
- <li>Diverse scenarios from common operation to model-based failures
- <li>Retrospective performance review of datacenter simulations
- <li>Compare resource management practices
- </ul>
- </div>
- <div class="col-lg-7 col-md-7 col-sm-7 col-xs-12">
- <img src="https://github.com/atlarge-research/opendc/raw/master/images/opendc-frontend-simulation-zoom.PNG" class="col-lg-12 col-md-12 col-sm-12 col-xs-10
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-1"
- alt="Mockup of the same simulation at node level">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 img-caption">
- Mockup of the same simulation at node level
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="technologies" class="technologies-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h1>Technologies</h1>
- <div class="tech-rows row col-lg-6 col-md-6 col-sm-12 col-xs-12
- col-lg-offset-3 col-md-offset-3 col-sm-offset-0 col-xs-offset-0">
- <div class="browser-tech tech-row row">
- <img src="img/technologies/www-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Web browser">
- <div class="col-lg-10 col-md-10 col-sm-10 col-xs-10 text-left">
- <h3>Browser</h3>
- <p class="info-points">HTML5 canvas, CreateJS, TypeScript, SocketIO</p>
- </div>
- </div>
- <div class="server-tech tech-row row">
- <img src="img/technologies/webserver-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Web Server">
- <div class="col-lg-10 col-md-10 col-sm-10 col-xs-10 text-left">
- <h3>Web Server</h3>
- <p class="info-points">Python, Flask, FlaskSocketIO, OpenAPI</p>
- </div>
- </div>
- <div class="database-tech tech-row row">
- <img src="img/technologies/database-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Database">
- <div class="col-lg-10 col-md-10 col-sm-10 col-xs-10 text-left">
- <h3>Database</h3>
- <p class="info-points">SQLite</p>
- </div>
- </div>
- <div class="simulator-tech tech-row row">
- <img src="img/technologies/cogs-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Simulator">
- <div class="col-lg-10 col-md-10 col-sm-10 col-xs-10 text-left">
- <h3>Simulator</h3>
- <p class="info-points">C++</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="team" class="team-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h1 class="col-lg-12 col-md-12 col-sm-12 col-xs-12 row">The Team</h1>
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 row">
- <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
- <img src="img/portraits/aiosup.png" class="col-lg-12 col-md-12 col-sm-12 col-xs-6
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-3">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h3>Prof. dr. ir. Alexandru Iosup</h3>
- <div class="team-member-description">
- Project Lead
- </div>
- </div>
- </div>
- <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
- <img src="img/portraits/loverweel.png" class="col-lg-12 col-md-12 col-sm-12 col-xs-6
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-3">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h3>Leon Overweel</h3>
- <div class="team-member-description">
- Product Lead and Software Engineer responsible for the web server, database, and
- API
- specification
- </div>
- </div>
- </div>
- <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
- <img src="img/portraits/gandreadis.png" class="col-lg-12 col-md-12 col-sm-12 col-xs-6
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-3">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h3>Georgios Andreadis</h3>
- <div class="team-member-description">
- Software Engineer responsible for the frontend web application and splash page
- </div>
- </div>
- </div>
- <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
- <img src="img/portraits/mbijman.png" class="col-lg-12 col-md-12 col-sm-12 col-xs-6
- col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-3">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h3>Matthijs Bijman</h3>
- <div class="team-member-description">
- Software Engineer responsible for the datacenter simulator
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <section id="contact" class="contact-section content-section">
- <div class="container">
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
- <h1>Contact</h1>
- <div class="row">
- <img src="img/tudelfticon.png" class="col-lg-2 col-md-2 col-sm-3 col-xs-6
- col-lg-offset-4 col-md-offset-4 col-sm-offset-3 col-xs-offset-3 tudelft-icon"
- alt="TU Delft Logo">
- <div class="col-lg-4 col-md-5 col-sm-6 col-xs-10 col-lg-offset-0 col-md-offset-0 col-sm-offset-0 col-xs-offset-1 text-left">
- <div class="row vcenter">
- <img src="img/email-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Email Icon">
- <div class="info-points col-lg-10 col-md-10 col-sm-10 col-xs-10">
- <a href="mailto:opendc@atlarge-research.com">opendc@atlarge-research.com</a>
- </div>
- </div>
- <div class="row vcenter">
- <img src="img/github-icon.png" class="col-lg-2 col-md-2 col-sm-2 col-xs-2"
- alt="Github Icon">
- <div class="info-points col-lg-10 col-md-10 col-sm-10 col-xs-10">
- <a href="https://github.com/atlarge-research/opendc">atlarge-research/opendc</a>
- </div>
- </div>
- </div>
- </div>
- <div class="atlarge-footer row">
- A project by the <a href="http://atlarge-research.com"><strong>@Large Research Group</strong></a>.
- </div>
- </div>
- </div>
- </div>
- </section>
-
- <script src="scripts/splash.entry.js"></script>
-
- <!-- Bower dependencies -->
- <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
-
- <!-- Google API -->
- <script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
-
-</div>
-
-</body>
-</html>
diff --git a/src/navbar.html b/src/navbar.html
deleted file mode 100644
index 92c79000..00000000
--- a/src/navbar.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<nav class="top-navbar">
- <a class="opendc-brand" href="/">
- <img src="img/logo.png" alt="OpenDC Logo">
- <div class="opendc-title">Open<strong>DC</strong></div>
- </a>
- <div class="navigation navbar-button-group">
- <a class="projects" title="Projects" href="projects">Projects</a>
- </div>
- <div class="user navbar-button-group">
- <a class="support glyphicon glyphicon-question-sign" title="Support"
- href="mailto:opendc.tudelft@gmail.com?Subject=OpenDC%20Support"></a>
- <a class="username" title="My Profile" href="profile">Profile</a>
- <a class="sign-out glyphicon glyphicon-off" title="Sign out" href="javascript:void(0)"></a>
- </div>
-
- <!--Hidden Google signin button for authentication-->
- <div id="google-signin" class="navbar-right"></div>
-</nav> \ No newline at end of file
diff --git a/src/profile.html b/src/profile.html
deleted file mode 100644
index 1cdb560b..00000000
--- a/src/profile.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="google-signin-client_id" content="OAUTH_CLIENT_ID">
-
- <title>OpenDC - Profile</title>
-
- <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
-
- <link href="styles/navbar.css" rel="stylesheet">
- <link href="styles/profile.css" rel="stylesheet">
-
- <link href="img/logo.png" rel="icon">
-</head>
-<body>
-<!-- build:include navbar.html -->
-<!-- /build -->
-<div class="content">
- <div class="main-body profile-page">
- <h2>Profile Settings</h2>
- <div id="delete-account" class="btn btn-danger">Delete my account on OpenDC</div>
- <div class="delete-info">This does not delete your Google account, it simply disconnects it from the OpenDC app
- and deletes any datacenter info that is associated with you (simulation projects you own, and any
- authorizations you may have on other projects).
- </div>
- <div class="account-delete-alert alert alert-danger" role="alert">
- <strong>Oops!</strong> Something went wrong while attempting to delete your account, here is the message:
- <code></code>
- </div>
- </div>
-</div>
-
-<div class="modal fade" id="confirm-delete-account" tabindex="-1" role="dialog" aria-labelledby="confirm-delete-header">
- <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" id="confirm-delete-header">Confirm account deletion</h4>
- </div>
- <div class="modal-body">
- Are you really sure you want us to delete your account? This action <strong>can not</strong> be undone.
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-danger confirm">Delete my account</button>
- </div>
- </div>
- </div>
-</div>
-
-<script src="scripts/profile.entry.js"></script>
-
-<!-- Bower dependencies -->
-<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
-
-<!-- Google API -->
-<script src="https://apis.google.com/js/platform.js?onload=gapiSigninButton" async defer></script>
-
-</body>
-</html>
diff --git a/src/projects.html b/src/projects.html
deleted file mode 100644
index 6c5effb7..00000000
--- a/src/projects.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
- <meta charset="UTF-8">
- <meta name="google-signin-client_id" content="OAUTH_CLIENT_ID">
-
- <title>OpenDC - Projects</title>
-
- <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
-
- <link href="styles/navbar.css" rel="stylesheet">
- <link href="styles/projects.css" rel="stylesheet">
-
- <link href="img/logo.png" rel="icon">
-</head>
-<body>
-
-<!-- build:include navbar.html -->
-<!-- /build -->
-
-<div class="content">
- <div class="main-body">
- <div class="filter-menu">
- <div class="project-filters">
- <div class="all-projects active">All Projects</div>
- <div class="my-projects">My Projects</div>
- <div class="shared-projects">Projects shared with me</div>
- </div>
- </div>
- <div class="no-projects-alert alert alert-info">
- <span class="glyphicon glyphicon-info-sign"></span>
- <strong>No projects here yet...</strong> Add some with the 'New Project' button!
- </div>
- <div class="project-list">
- <div class="list-head">
- <div>Project name</div>
- <div>Last edited</div>
- <div>Access rights</div>
- </div>
- <div class="list-body">
- </div>
- </div>
- <div class="new-project-btn"><span class="glyphicon glyphicon-plus"></span> New Project</div>
- </div>
-</div>
-
-<div class="window-overlay">
- <div class="projects-window">
- <div class="window-close glyphicon glyphicon-remove"></div>
- <div class="window-body">
- <div class="window-heading">Edit project</div>
- <form class="form-inline project-name-form">
- <div class="form-group">
- <label for="newProjectNameInput">Name</label>
- <input type="text" class="form-control" id="newProjectNameInput" placeholder="Project name">
- <div class="btn btn-default">Save</div>
- </div>
- </form>
- <strong class="participants-table-label">Participants</strong>
- <div class="participants-table">
- </div>
- <form class="form-inline participant-add-form">
- <div class="form-group">
- <label for="participantAddInput" class="glyphicon glyphicon-plus"></label>
- <input type="email" class="form-control" id="participantAddInput"
- placeholder="Add a participant (by email)">
- <div class="btn btn-default">Add</div>
- </div>
- </form>
- <div class="participant-email-alert alert alert-danger" role="alert">
- <strong>Warning:</strong> We couldn't find that email in our database. Misspelled something?
- </div>
- <div class="project-name-alert alert alert-danger" role="alert">
- <strong>Warning:</strong> Your project needs a name!
- </div>
- </div>
- <div class="window-footer">
- <div class="project-open-btn btn btn-primary pull-left">Open</div>
- <div class="project-create-open-btn btn btn-primary pull-left">Create & Open</div>
- <div class="project-create-btn btn btn-info pull-left">Create</div>
- <div class="project-delete-btn btn btn-danger pull-right">Delete</div>
- <div class="project-cancel-btn btn btn-default pull-right">Cancel</div>
- </div>
- </div>
-</div>
-
-<script src="scripts/projects.entry.js"></script>
-
-<!-- Google API -->
-<script src="https://apis.google.com/js/platform.js?onload=gapiSigninButton" async defer></script>
-
-</body>
-</html>
diff --git a/src/robots.txt b/src/robots.txt
deleted file mode 100644
index 2329e38e..00000000
--- a/src/robots.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-User-agent: *
-Disallow: /app.html
-Disallow: /profile.html
-Disallow: /projects.html \ No newline at end of file
diff --git a/src/scripts/colors.ts b/src/scripts/colors.ts
deleted file mode 100644
index 559b7ee3..00000000
--- a/src/scripts/colors.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Class serving as a color palette for the application.
- */
-export class Colors {
- public static GRID_COLOR = "rgba(0, 0, 0, 0.5)";
-
- public static WALL_COLOR = "rgba(0, 0, 0, 1)";
-
- public static ROOM_DEFAULT = "rgba(150, 150, 150, 1)";
- public static ROOM_SELECTED = "rgba(51, 153, 255, 1)";
- public static ROOM_HOVER_VALID = "rgba(51, 153, 255, 0.5)";
- public static ROOM_HOVER_INVALID = "rgba(255, 102, 0, 0.5)";
- public static ROOM_NAME_COLOR = "rgba(245, 245, 245, 1)";
- public static ROOM_TYPE_COLOR = "rgba(245, 245, 245, 1)";
-
- public static RACK_BACKGROUND = "rgba(170, 170, 170, 1)";
- public static RACK_BORDER = "rgba(0, 0, 0, 1)";
- public static RACK_SPACE_BAR_BACKGROUND = "rgba(222, 235, 247, 1)";
- public static RACK_SPACE_BAR_FILL = "rgba(91, 155, 213, 1)";
- public static RACK_ENERGY_BAR_BACKGROUND = "rgba(255, 242, 204, 1)";
- public static RACK_ENERGY_BAR_FILL = "rgba(255, 192, 0, 1)";
-
- public static COOLING_ITEM_BACKGROUND = "rgba(40, 50, 230, 1)";
- public static COOLING_ITEM_BORDER = "rgba(0, 0, 0, 1)";
-
- public static PSU_BACKGROUND = "rgba(230, 50, 60, 1)";
- public static PSU_BORDER = "rgba(0, 0, 0, 1)";
-
- public static GRAYED_OUT_AREA = "rgba(0, 0, 0, 0.6)";
-
- public static INFO_BALLOON_INFO = "rgba(40, 50, 230, 1)";
- public static INFO_BALLOON_WARNING = "rgba(230, 60, 70, 1)";
-
- public static INFO_BALLOON_MAP = {
- "info": Colors.INFO_BALLOON_INFO,
- "warning": Colors.INFO_BALLOON_WARNING
- };
-
- public static SIM_LOW = "rgba(197, 224, 180, 1)";
- public static SIM_MID_LOW = "rgba(255, 230, 153, 1)";
- public static SIM_MID_HIGH = "rgba(248, 203, 173, 1)";
- public static SIM_HIGH = "rgba(249, 165, 165, 1)";
-}
diff --git a/src/scripts/controllers/connection/api.ts b/src/scripts/controllers/connection/api.ts
deleted file mode 100644
index 1a1c122f..00000000
--- a/src/scripts/controllers/connection/api.ts
+++ /dev/null
@@ -1,1738 +0,0 @@
-///<reference path="../../definitions.ts" />
-///<reference path="../../../../typings/index.d.ts" />
-import {Util} from "../../util";
-import {ServerConnection} from "../../serverconnection";
-
-
-export class APIController {
- constructor(onConnect: (api: APIController) => any) {
- ServerConnection.connect(() => {
- onConnect(this);
- });
- }
-
-
- ///
- // PATH: /users
- ///
-
- // METHOD: GET
- public getUserByEmail(email: string): Promise<IUser> {
- return ServerConnection.send({
- path: "/users",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {
- email
- }
- }
- });
- }
-
- // METHOD: POST
- public addUser(user: IUser): Promise<IUser> {
- return ServerConnection.send({
- path: "/users",
- method: "POST",
- parameters: {
- body: {
- user: user
- },
- path: {},
- query: {}
- }
- });
- }
-
- ///
- // PATH: /users/{id}
- ///
-
- // METHOD: GET
- public getUser(userId: number): Promise<IUser> {
- return ServerConnection.send({
- path: "/users/{userId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- userId
- },
- query: {}
- }
- });
- }
-
- // METHOD: PUT
- public updateUser(userId: number, user: IUser): Promise<IUser> {
- return ServerConnection.send({
- path: "/users/{userId}",
- method: "PUT",
- parameters: {
- body: {
- user: {
- givenName: user.givenName,
- familyName: user.familyName
- }
- },
- path: {
- userId
- },
- query: {}
- }
- });
- }
-
- // METHOD: DELETE
- public deleteUser(userId: number): Promise<IUser> {
- return ServerConnection.send({
- path: "/users/{userId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- userId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /users/{userId}/authorizations
- ///
-
- // METHOD: GET
- public getAuthorizationsByUser(userId: number): Promise<IAuthorization[]> {
- let authorizations = [];
- return ServerConnection.send({
- path: "/users/{userId}/authorizations",
- method: "GET",
- parameters: {
- body: {},
- path: {
- userId
- },
- query: {}
- }
- }).then((data: any) => {
- authorizations = data;
- return this.getUser(userId);
- }).then((userData: any) => {
- const promises = [];
- authorizations.forEach((authorization: IAuthorization) => {
- authorization.user = userData;
- promises.push(this.getSimulation(authorization.simulationId).then((simulationData: any) => {
- authorization.simulation = simulationData;
- }));
- });
- return Promise.all(promises);
- }).then((data: any) => {
- return authorizations;
- });
- }
-
- ///
- // PATH: /simulations
- ///
-
- // METHOD: POST
- public addSimulation(simulation: ISimulation): Promise<ISimulation> {
- return ServerConnection.send({
- path: "/simulations",
- method: "POST",
- parameters: {
- body: {
- simulation: Util.packageForSending(simulation)
- },
- path: {},
- query: {}
- }
- }).then((data: any) => {
- this.parseSimulationTimestamps(data);
- return data;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}
- ///
-
- // METHOD: GET
- public getSimulation(simulationId: number): Promise<ISimulation> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- this.parseSimulationTimestamps(data);
- return data;
- });
- }
-
- // METHOD: PUT
- public updateSimulation(simulation: ISimulation): Promise<ISimulation> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}",
- method: "PUT",
- parameters: {
- body: {
- simulation: Util.packageForSending(simulation)
- },
- path: {
- simulationId: simulation.id
- },
- query: {}
- }
- }).then((data: any) => {
- this.parseSimulationTimestamps(data);
- return data;
- });
- }
-
- // METHOD: DELETE
- public deleteSimulation(simulationId: number): Promise<ISimulation> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/authorizations
- ///
-
- // METHOD: GET
- public getAuthorizationsBySimulation(simulationId: number): Promise<IAuthorization[]> {
- let authorizations = [];
- return ServerConnection.send({
- path: "/simulations/{simulationId}/authorizations",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- authorizations = data;
- return this.getSimulation(simulationId);
- }).then((simulationData: any) => {
- const promises = [];
- authorizations.forEach((authorization: IAuthorization) => {
- authorization.simulation = simulationData;
- promises.push(this.getUser(authorization.userId).then((userData: any) => {
- authorization.user = userData;
- }));
- });
- return Promise.all(promises);
- }).then((data: any) => {
- return authorizations;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/authorizations/{userId}
- ///
-
- // METHOD: GET
- // Not needed
-
- // METHOD: POST
- public addAuthorization(authorization: IAuthorization): Promise<IAuthorization> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/authorizations/{userId}",
- method: "POST",
- parameters: {
- body: {
- authorization: {
- authorizationLevel: authorization.authorizationLevel
- }
- },
- path: {
- simulationId: authorization.simulationId,
- userId: authorization.userId
- },
- query: {}
- }
- });
- }
-
- // METHOD: PUT
- public updateAuthorization(authorization: IAuthorization): Promise<IAuthorization> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/authorizations/{userId}",
- method: "PUT",
- parameters: {
- body: {
- authorization: {
- authorizationLevel: authorization.authorizationLevel
- }
- },
- path: {
- simulationId: authorization.simulationId,
- userId: authorization.userId
- },
- query: {}
- }
- });
- }
-
- // METHOD: DELETE
- public deleteAuthorization(authorization: IAuthorization): Promise<IAuthorization> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/authorizations/{userId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId: authorization.simulationId,
- userId: authorization.userId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}
- ///
-
- // METHOD: GET
- public getDatacenter(simulationId: number, datacenterId: number): Promise<IDatacenter> {
- let datacenter;
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId
- },
- query: {}
- }
- }).then((data: any) => {
- datacenter = data;
-
- return this.getRoomsByDatacenter(simulationId, datacenterId);
- }).then((data: any) => {
- datacenter.rooms = data;
- return datacenter;
- });
- }
-
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms
- ///
-
- // METHOD: GET
- public getRoomsByDatacenter(simulationId: number, datacenterId: number): Promise<IRoom[]> {
- let rooms;
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId
- },
- query: {}
- }
- }).then((data: any) => {
- rooms = data;
-
- const promises = [];
- rooms.forEach((room: IRoom) => {
- promises.push(this.loadRoomTiles(simulationId, datacenterId, room));
- });
- return Promise.all(promises).then((data: any) => {
- return rooms;
- });
- });
- }
-
- // METHOD: POST
- public addRoomToDatacenter(simulationId: number, datacenterId: number): Promise<IRoom> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms",
- method: "POST",
- parameters: {
- body: {
- room: {
- id: -1,
- datacenterId,
- roomType: "SERVER"
- }
- },
- path: {
- simulationId,
- datacenterId
- },
- query: {}
- }
- }).then((data: any) => {
- data.tiles = [];
- return data;
- });
- }
-
- ///
- // PATH: /room-types
- ///
-
- // METHOD: GET
- public getAllRoomTypes(): Promise<string[]> {
- return ServerConnection.send({
- path: "/room-types",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- }).then((data: any) => {
- const result = [];
- data.forEach((roomType: any) => {
- result.push(roomType.name);
- });
- return result;
- });
- }
-
- ///
- // PATH: /room-types/{name}/allowed-objects
- ///
-
- // METHOD: GET
- public getAllowedObjectsByRoomType(name: string): Promise<string[]> {
- return ServerConnection.send({
- path: "/room-types/{name}/allowed-objects",
- method: "GET",
- parameters: {
- body: {},
- path: {
- name
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}
- ///
-
- // METHOD: GET
- public getRoom(simulationId: number, datacenterId: number, roomId: number): Promise<IRoom> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadRoomTiles(simulationId, datacenterId, data);
- });
- }
-
- // METHOD: PUT
- public updateRoom(simulationId: number, datacenterId: number, room: IRoom): Promise<IRoom> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}",
- method: "PUT",
- parameters: {
- body: {
- room: Util.packageForSending(room)
- },
- path: {
- simulationId,
- datacenterId,
- roomId: room.id
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadRoomTiles(simulationId, datacenterId, data);
- });
- }
-
- // METHOD: DELETE
- public deleteRoom(simulationId: number, datacenterId: number, roomId: number): Promise<IRoom> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles
- ///
-
- // METHOD: GET
- public getTilesByRoom(simulationId: number, datacenterId: number, roomId: number): Promise<ITile[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((item) => {
- return this.loadTileObject(simulationId, datacenterId, roomId, item);
- });
-
- return Promise.all(promises).then(() => {
- return data;
- })
- });
- }
-
- // METHOD: POST
- public addTileToRoom(simulationId: number, datacenterId: number, roomId: number, tile: ITile): Promise<ITile> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles",
- method: "POST",
- parameters: {
- body: {
- tile: Util.packageForSending(tile)
- },
- path: {
- simulationId,
- datacenterId,
- roomId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadTileObject(simulationId, datacenterId, roomId, data);
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}
- ///
-
- // METHOD: GET
- // Not needed (yet)
-
- // METHOD: DELETE
- public deleteTile(simulationId: number, datacenterId: number, roomId: number, tileId: number): Promise<ITile> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/cooling-item
- ///
-
- // METHOD: GET
- public getCoolingItem(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<ICoolingItem> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/cooling-item",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadFailureModel(data);
- });
- }
-
- // METHOD: POST
- public addCoolingItem(simulationId: number, datacenterId: number, roomId: number, tileId: number,
- coolingItem: ICoolingItem): Promise<ICoolingItem> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/cooling-item",
- method: "POST",
- parameters: {
- body: {
- coolingItem: Util.packageForSending(coolingItem)
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadFailureModel(data);
- });
- }
-
- // METHOD: PUT
- // Not needed (yet)
-
- // METHOD: DELETE
- public deleteCoolingItem(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<ICoolingItem> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/cooling-item",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/psu
- ///
-
- // METHOD: GET
- public getPSU(simulationId: number, datacenterId: number, roomId: number, tileId: number): Promise<IPSU> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/psu",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadFailureModel(data);
- });
- }
-
- // METHOD: POST
- public addPSU(simulationId: number, datacenterId: number, roomId: number, tileId: number,
- psu: IPSU): Promise<IPSU> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/psu",
- method: "POST",
- parameters: {
- body: {
- psu: Util.packageForSending(psu)
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadFailureModel(data);
- });
- }
-
- // METHOD: PUT
- // Not needed (yet)
-
- // METHOD: DELETE
- public deletePSU(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<IPSU> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/psu",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack
- ///
-
- // METHOD: GET
- public getRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<IRack> {
- let rack = {};
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- rack = data;
- return this.getMachinesByRack(simulationId, datacenterId, roomId, tileId);
- }).then((machines: any) => {
- const promises = machines.map((machine) => {
- return this.loadMachineUnits(machine);
- });
-
-
- return Promise.all(promises).then(() => {
- rack["machines"] = [];
-
- machines.forEach((machine: IMachine) => {
- rack["machines"][machine.position] = machine;
- });
-
- for (let i = 0; i < rack["capacity"]; i++) {
- if (rack["machines"][i] === undefined) {
- rack["machines"][i] = null;
- }
- }
-
- return <IRack>rack;
- });
- });
- }
-
- // METHOD: POST
- public addRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number, rack: IRack): Promise<IRack> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack",
- method: "POST",
- parameters: {
- body: {
- rack: Util.packageForSending(rack)
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- data.machines = [];
-
- for (let i = 0; i < data.capacity; i++) {
- data.machines.push(null);
- }
-
- return data;
- });
- }
-
- // METHOD: PUT
- public updateRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number, rack: IRack): Promise<IRack> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack",
- method: "PUT",
- parameters: {
- body: {
- rack
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- data.machines = rack.machines;
-
- return data;
- });
- }
-
- // METHOD: DELETE
- public deleteRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<IRack> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines
- ///
-
- // METHOD: GET
- public getMachinesByRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number): Promise<IMachine[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((machine) => {
- return this.loadMachineUnits(machine);
- });
-
- return Promise.all(promises).then(() => {
- return data;
- });
- });
- }
-
- // METHOD: POST
- public addMachineToRack(simulationId: number, datacenterId: number, roomId: number,
- tileId: number, machine: IMachine): Promise<IMachine> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines",
- method: "POST",
- parameters: {
- body: {
- machine: Util.packageForSending(machine)
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadMachineUnits(data);
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines/{position}
- ///
-
- // METHOD: GET
- // Not needed (yet)
-
- // METHOD: PUT
- public updateMachine(simulationId: number, datacenterId: number, roomId: number,
- tileId: number, machine: IMachine): Promise<IMachine> {
- machine["tags"] = [];
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines/{position}",
- method: "PUT",
- parameters: {
- body: {
- machine: Util.packageForSending(machine)
- },
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId,
- position: machine.position
- },
- query: {}
- }
- }).then((data: any) => {
- return this.loadMachineUnits(data);
- });
- }
-
- // METHOD: DELETE
- public deleteMachine(simulationId: number, datacenterId: number, roomId: number,
- tileId: number, position: number): Promise<any> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/datacenters/{datacenterId}/rooms/{roomId}/tiles/{tileId}/rack/machines/{position}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- simulationId,
- datacenterId,
- roomId,
- tileId,
- position
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments
- ///
-
- // METHOD: GET
- public getExperimentsBySimulation(simulationId: number): Promise<IExperiment[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((item: any) => {
- return this.getTrace(item.traceId).then((traceData: any) => {
- item.trace = traceData;
- });
- });
- return Promise.all(promises).then(() => {
- return data;
- });
- });
- }
-
- // METHOD: POST
- public addExperimentToSimulation(simulationId: number, experiment: IExperiment): Promise<IExperiment> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments",
- method: "POST",
- parameters: {
- body: {
- experiment: Util.packageForSending(experiment)
- },
- path: {
- simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.getTrace(data.traceId).then((traceData: any) => {
- data.trace = traceData;
-
- return data;
- });
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}
- ///
-
- // METHOD: GET
- // Not needed (yet)
-
- // METHOD: PUT
- public updateExperiment(experiment: IExperiment): Promise<IExperiment> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}",
- method: "PUT",
- parameters: {
- body: {
- experiment: Util.packageForSending(experiment)
- },
- path: {
- experimentId: experiment.id,
- simulationId: experiment.simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.getTrace(data.traceId).then((traceData: any) => {
- data.trace = traceData;
-
- return data;
- });
- });
- }
-
- // METHOD: DELETE
- public deleteExperiment(simulationId: number, experimentId: number): Promise<any> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}",
- method: "DELETE",
- parameters: {
- body: {},
- path: {
- experimentId,
- simulationId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}/last-simulated-tick
- ///
-
- // METHOD: GET
- public getLastSimulatedTickByExperiment(simulationId: number, experimentId: number): Promise<number> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}/last-simulated-tick",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- experimentId
- },
- query: {}
- }
- }).then((data: any) => {
- return data.lastSimulatedTick;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}/machine-states
- ///
-
- // METHOD: GET
- public getMachineStates(simulationId: number, experimentId: number, machines: {[keys: number]: IMachine},
- tick?: number): Promise<IMachineState[]> {
- let query;
- if (tick !== undefined) {
- query = {tick};
- } else {
- query = {};
- }
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}/machine-states",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- experimentId
- },
- query
- }
- }).then((data: any) => {
- data.forEach((item: any) => {
- item.machine = machines[item.machineId];
- });
-
- return data;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}/rack-states
- ///
-
- // METHOD: GET
- public getRackStates(simulationId: number, experimentId: number, racks: {[keys: number]: IRack},
- tick?: number): Promise<IRackState[]> {
- let query;
- if (tick !== undefined) {
- query = {tick};
- } else {
- query = {};
- }
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}/rack-states",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- experimentId
- },
- query: query
- }
- }).then((data: any) => {
- data.forEach((item: any) => {
- item.rack = racks[item.rackId];
- });
-
- return data;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}/room-states
- ///
-
- // METHOD: GET
- public getRoomStates(simulationId: number, experimentId: number, rooms: {[keys: number]: IRoom},
- tick?: number): Promise<IRoomState[]> {
- let query;
- if (tick !== undefined) {
- query = {tick};
- } else {
- query = {};
- }
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}/room-states",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- experimentId
- },
- query
- }
- }).then((data: any) => {
- data.forEach((item: any) => {
- item.room = rooms[item.roomId];
- });
-
- return data;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/experiments/{experimentId}/task-states
- ///
-
- // METHOD: GET
- public getTaskStates(simulationId: number, experimentId: number, tasks: {[keys: number]: ITask},
- tick?: number): Promise<ITaskState[]> {
- let query;
- if (tick === undefined) {
- query = {tick};
- } else {
- query = {};
- }
-
- return ServerConnection.send({
- path: "/simulations/{simulationId}/experiments/{experimentId}/task-states",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- experimentId
- },
- query
- }
- }).then((data: any) => {
- data.forEach((item: any) => {
- item.task = tasks[item.taskId];
- });
-
- return data;
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/paths
- ///
-
- // METHOD: GET
- public getPathsBySimulation(simulationId: number): Promise<IPath[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((item: any) => {
- return this.getSectionsByPath(simulationId, item.id).then((sectionsData: any) => {
- item.sections = sectionsData;
- });
- });
- return Promise.all(promises).then(() => {
- return data;
- });
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/paths/{pathId}
- ///
-
- // METHOD: GET
- public getPath(simulationId: number, pathId: number): Promise<IPath> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths/{pathId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- pathId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.getSectionsByPath(simulationId, pathId).then((sectionsData: any) => {
- data.sections = sectionsData;
- return data;
- });
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/paths/{pathId}/branches
- ///
-
- // METHOD: GET
- public getBranchesByPath(simulationId: number, pathId: number): Promise<IPath[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths/{pathId}/branches",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- pathId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((item: any) => {
- return this.getSectionsByPath(simulationId, item.id).then((sectionsData: any) => {
- item.sections = sectionsData;
- });
- });
- return Promise.all(promises).then(() => {
- return data;
- });
- });
- }
-
- // METHOD: POST
- public branchFromPath(simulationId: number, pathId: number, startTick: number): Promise<IPath> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths/{pathId}/branches",
- method: "POST",
- parameters: {
- body: {
- section: {
- startTick
- }
- },
- path: {
- simulationId,
- pathId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.getSectionsByPath(simulationId, data.id).then((sectionsData: any) => {
- data.sections = sectionsData;
- return data;
- });
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/paths/{pathId}/sections
- ///
-
- // METHOD: GET
- public getSectionsByPath(simulationId: number, pathId: number): Promise<IPath[]> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths/{pathId}/sections",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- pathId
- },
- query: {}
- }
- }).then((data: any) => {
- const promises = data.map((path: ISection) => {
- return this.getDatacenter(simulationId, path.datacenterId).then((datacenter: any) => {
- path.datacenter = datacenter;
- });
- });
- return Promise.all(promises).then(() => {
- return data;
- });
- });
- }
-
- ///
- // PATH: /simulations/{simulationId}/paths/{pathId}/sections/{sectionId}
- ///
-
- // METHOD: GET
- public getSection(simulationId: number, pathId: number, sectionId: number): Promise<ISection> {
- return ServerConnection.send({
- path: "/simulations/{simulationId}/paths/{pathId}/sections/{sectionId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- simulationId,
- pathId,
- sectionId
- },
- query: {}
- }
- }).then((data: any) => {
- return this.getDatacenter(simulationId, data.datacenterId).then((datacenter: any) => {
- data.datacenter = datacenter;
- return data;
- });
- });
- }
-
- ///
- // PATH: /specifications/psus
- ///
-
- // METHOD: GET
- public getAllPSUSpecs(): Promise<IPSU[]> {
- let psus;
- return ServerConnection.send({
- path: "/specifications/psus",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- }).then((data: any) => {
- psus = data;
-
- const promises = [];
- data.forEach((psu: IPSU) => {
- promises.push(this.getFailureModel(psu.failureModelId));
- });
- return Promise.all(promises);
- }).then((data: any) => {
- return psus;
- });
- }
-
- ///
- // PATH: /specifications/psus/{id}
- ///
-
- // METHOD: GET
- public getPSUSpec(id: number): Promise<IPSU> {
- let psu;
-
- return ServerConnection.send({
- path: "/specifications/psus/{id}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- id
- },
- query: {}
- }
- }).then((data: any) => {
- psu = data;
- return this.getFailureModel(data.failureModelId);
- }).then((data: any) => {
- psu.failureModel = data;
- return psu;
- });
- }
-
- ///
- // PATH: /specifications/cooling-items
- ///
-
- // METHOD: GET
- public getAllCoolingItemSpecs(): Promise<ICoolingItem[]> {
- let coolingItems;
-
- return ServerConnection.send({
- path: "/specifications/cooling-items",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- }).then((data: any) => {
- coolingItems = data;
-
- const promises = [];
- data.forEach((item: ICoolingItem) => {
- promises.push(this.getFailureModel(item.failureModelId));
- });
- return Promise.all(promises);
- }).then((data: any) => {
- return coolingItems;
- });
- }
-
- ///
- // PATH: /specifications/cooling-items/{id}
- ///
-
- // METHOD: GET
- public getCoolingItemSpec(id: number): Promise<IPSU> {
- let coolingItem;
-
- return ServerConnection.send({
- path: "/specifications/cooling-items/{id}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- id
- },
- query: {}
- }
- }).then((data: any) => {
- coolingItem = data;
- return this.getFailureModel(data.failureModelId);
- }).then((data: any) => {
- coolingItem.failureModel = data;
- return coolingItem;
- });
- }
-
- ///
- // PATH: /schedulers
- ///
-
- // METHOD: GET
- public getAllSchedulers(): Promise<IScheduler[]> {
- return ServerConnection.send({
- path: "/schedulers",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- });
- }
-
- ///
- // PATH: /traces
- ///
-
- // METHOD: GET
- public getAllTraces(): Promise<ITrace[]> {
- return ServerConnection.send({
- path: "/traces",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- });
- }
-
- ///
- // PATH: /traces/{traceId}
- ///
-
- // METHOD: GET
- public getTrace(traceId: number): Promise<ITrace> {
- let trace;
-
- return ServerConnection.send({
- path: "/traces/{traceId}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- traceId
- },
- query: {}
- }
- }).then((data: any) => {
- trace = data;
- return this.getTasksByTrace(traceId);
- }).then((data: any) => {
- trace.tasks = data;
- return trace;
- });
- }
-
- ///
- // PATH: /traces/{traceId}/tasks
- ///
-
- // METHOD: GET
- public getTasksByTrace(traceId: number): Promise<ITask[]> {
- return ServerConnection.send({
- path: "/traces/{traceId}/tasks",
- method: "GET",
- parameters: {
- body: {},
- path: {
- traceId
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /specifications/failure-models
- ///
-
- // METHOD: GET
- public getAllFailureModels(): Promise<IFailureModel[]> {
- return ServerConnection.send({
- path: "/specifications/failure-models",
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- });
- }
-
- ///
- // PATH: /specifications/failure-models/{id}
- ///
-
- // METHOD: GET
- public getFailureModel(id: number): Promise<IFailureModel> {
- return ServerConnection.send({
- path: "/specifications/failure-models/{id}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- id
- },
- query: {}
- }
- });
- }
-
- ///
- // PATH: /specifications/[units]
- ///
-
- // METHOD: GET
- public getAllSpecificationsOfType(typePlural: string): Promise<INodeUnit> {
- let specs: any;
- return ServerConnection.send({
- path: "/specifications/" + typePlural,
- method: "GET",
- parameters: {
- body: {},
- path: {},
- query: {}
- }
- }).then((data: any) => {
- specs = data;
-
- const promises = [];
- data.forEach((unit: INodeUnit) => {
- promises.push(this.getFailureModel(unit.failureModelId));
- });
- return Promise.all(promises);
- }).then((data: any) => {
- return specs;
- });
- }
-
- ///
- // PATH: /specifications/[units]/{id}
- ///
-
- // METHOD: GET
- public getSpecificationOfType(typePlural: string, id: number): Promise<INodeUnit> {
- let spec;
-
- return ServerConnection.send({
- path: "/specifications/" + typePlural + "/{id}",
- method: "GET",
- parameters: {
- body: {},
- path: {
- id
- },
- query: {}
- }
- }).then((data: any) => {
- spec = data;
- return this.getFailureModel(data.failureModelId);
- }).then((data: any) => {
- spec.failureModel = data;
- return spec;
- });
- }
-
-
- ///
- // HELPER METHODS
- ///
-
- private loadRoomTiles(simulationId: number, datacenterId: number, room: IRoom): Promise<IRoom> {
- return this.getTilesByRoom(simulationId, datacenterId, room.id).then((data: any) => {
- room.tiles = data;
- return room;
- });
- }
-
- private loadTileObject(simulationId: number, datacenterId: number, roomId: number, tile: ITile): Promise<ITile> {
- let promise;
-
- switch (tile.objectType) {
- case "RACK":
- promise = this.getRack(simulationId, datacenterId, roomId, tile.id).then((data: IRack) => {
- tile.object = data;
- });
- break;
- case "PSU":
- promise = this.getPSU(simulationId, datacenterId, roomId, tile.id).then((data: IPSU) => {
- tile.object = data;
- });
- break;
- case "COOLING_ITEM":
- promise = this.getCoolingItem(simulationId, datacenterId, roomId, tile.id).then((data: ICoolingItem) => {
- tile.object = data;
- });
- break;
- default:
- promise = new Promise((resolve, reject) => {
- resolve(undefined);
- });
- }
-
- return promise.then(() => {
- return tile;
- })
- }
-
- private parseSimulationTimestamps(simulation: ISimulation): void {
- simulation.datetimeCreatedParsed = Util.parseDateTime(simulation.datetimeCreated);
- simulation.datetimeLastEditedParsed = Util.parseDateTime(simulation.datetimeLastEdited);
- }
-
- private loadFailureModel(data: any): Promise<any> {
- return this.getFailureModel(data.failureModelId).then((failureModel: IFailureModel) => {
- data.failureModel = failureModel;
- return data;
- });
- }
-
- private loadUnitsOfType(idListName: string, objectListName: string, machine: IMachine): Promise<IMachine> {
- machine[objectListName] = [];
-
- const promises = machine[idListName].map((item) => {
- return this.getSpecificationOfType(objectListName, item).then((data) => {
- machine[objectListName].push(data);
- });
- });
-
- return Promise.all(promises).then(() => {
- return machine;
- })
- }
-
- private loadMachineUnits(machine: IMachine): Promise<IMachine> {
- const listNames = [
- {
- idListName: "cpuIds",
- objectListName: "cpus"
- }, {
- idListName: "gpuIds",
- objectListName: "gpus"
- }, {
- idListName: "memoryIds",
- objectListName: "memories"
- }, {
- idListName: "storageIds",
- objectListName: "storages"
- }
- ];
-
- const promises = listNames.map((item: any) => {
- return this.loadUnitsOfType(item.idListName, item.objectListName, machine);
- });
-
- return Promise.all(promises).then(() => {
- return machine;
- });
- }
-}
diff --git a/src/scripts/controllers/connection/cache.ts b/src/scripts/controllers/connection/cache.ts
deleted file mode 100644
index c1c47c2d..00000000
--- a/src/scripts/controllers/connection/cache.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-export enum CacheStatus {
- MISS,
- FETCHING,
- HIT,
- NOT_CACHABLE
-}
-
-
-interface ICachableObject {
- status: CacheStatus;
- object: any;
- callbacks: any[];
-}
-
-
-export class CacheController {
- private static CACHABLE_ROUTES = [
- "/specifications/psus/{id}",
- "/specifications/cooling-items/{id}",
- "/specifications/cpus/{id}",
- "/specifications/gpus/{id}",
- "/specifications/memories/{id}",
- "/specifications/storages/{id}",
- "/specifications/failure-models/{id}",
- ];
-
- // Maps every route name to a map of IDs => objects
- private routeCaches: { [keys: string]: { [keys: number]: ICachableObject } };
-
-
- constructor() {
- this.routeCaches = {};
-
- CacheController.CACHABLE_ROUTES.forEach((routeName: string) => {
- this.routeCaches[routeName] = {};
- })
- }
-
- public checkCache(request: IRequest): CacheStatus {
- if (request.method === "GET" && CacheController.CACHABLE_ROUTES.indexOf(request.path) !== -1) {
- if (this.routeCaches[request.path][request.parameters.path["id"]] === undefined) {
- this.routeCaches[request.path][request.parameters.path["id"]] = {
- status: CacheStatus.MISS,
- object: null,
- callbacks: []
- };
- return CacheStatus.MISS;
- } else {
- return this.routeCaches[request.path][request.parameters.path["id"]].status;
- }
- } else {
- return CacheStatus.NOT_CACHABLE;
- }
- }
-
- public fetchFromCache(request: IRequest): any {
- return this.routeCaches[request.path][request.parameters.path["id"]].object;
- }
-
- public setToFetching(request: IRequest): void {
- this.routeCaches[request.path][request.parameters.path["id"]].status = CacheStatus.FETCHING;
- }
-
- public onFetch(request: IRequest, response: IResponse): any {
- const pathWithoutVersion = request.path.replace(/\/v\d+/, "");
- this.routeCaches[pathWithoutVersion][request.parameters.path["id"]].status = CacheStatus.HIT;
- this.routeCaches[pathWithoutVersion][request.parameters.path["id"]].object = response.content;
-
- this.routeCaches[pathWithoutVersion][request.parameters.path["id"]].callbacks.forEach((callback) => {
- callback({
- status: {
- code: 200
- },
- content: response.content,
- id: request.id
- });
- });
-
- this.routeCaches[pathWithoutVersion][request.parameters.path["id"]].callbacks = [];
- }
-
- public registerCallback(request: IRequest, callback): any {
- this.routeCaches[request.path][request.parameters.path["id"]].callbacks.push(callback);
- }
-}
diff --git a/src/scripts/controllers/connection/socket.ts b/src/scripts/controllers/connection/socket.ts
deleted file mode 100644
index 91a0f9e4..00000000
--- a/src/scripts/controllers/connection/socket.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import {CacheController, CacheStatus} from "./cache";
-import * as io from "socket.io-client";
-
-
-export class SocketController {
- private static id = 1;
- private _socket: SocketIOClient.Socket;
- private _cacheController: CacheController;
-
- // Mapping from request IDs to their registered callbacks
- private callbacks: { [keys: number]: (response: IResponse) => any };
-
-
- constructor(onConnect: () => any) {
- this.callbacks = {};
- this._cacheController = new CacheController();
-
- this._socket = io.connect('SERVER_BASE_URL');
- this._socket.on('connect', onConnect);
-
- this._socket.on('response', (jsonResponse: string) => {
- const response: IResponse = JSON.parse(jsonResponse);
- console.log("Response, ID:", response.id, response);
- this.callbacks[response.id](response);
- delete this.callbacks[response.id];
- });
- }
-
- /**
- * Sends a request to the server socket and registers the callback to be triggered on response.
- *
- * @param request The request instance to be sent
- * @param callback A function to be called with the response object once the socket has received a response
- */
- public sendRequest(request: IRequest, callback: (response: IResponse) => any): void {
- // Check local cache, in case request is for cachable GET route
- const cacheStatus = this._cacheController.checkCache(request);
-
- if (cacheStatus === CacheStatus.HIT) {
- callback({
- status: {
- code: 200
- },
- content: this._cacheController.fetchFromCache(request),
- id: -1
- });
- } else if (cacheStatus === CacheStatus.FETCHING) {
- this._cacheController.registerCallback(request, callback);
- } else if (cacheStatus === CacheStatus.MISS || cacheStatus === CacheStatus.NOT_CACHABLE) {
- if (!this._socket.connected) {
- console.error("Socket not connected, sending request failed");
- }
-
- if (cacheStatus === CacheStatus.MISS) {
- this._cacheController.setToFetching(request);
-
- this.callbacks[SocketController.id] = (response: IResponse) => {
- this._cacheController.onFetch(request, response);
- callback(response);
- };
- } else {
- this.callbacks[SocketController.id] = callback;
- }
-
- // Setup request object
- request.id = SocketController.id;
- request.token = localStorage.getItem("googleToken");
- request.path = "/v1" + request.path;
-
- console.log("Request, ID:", request.id, request);
- this._socket.emit("request", request);
-
- SocketController.id++;
- }
- }
-}
diff --git a/src/scripts/controllers/mapcontroller.ts b/src/scripts/controllers/mapcontroller.ts
deleted file mode 100644
index 4ad1b20b..00000000
--- a/src/scripts/controllers/mapcontroller.ts
+++ /dev/null
@@ -1,520 +0,0 @@
-///<reference path="../../../typings/index.d.ts" />
-///<reference path="../views/mapview.ts" />
-import * as $ from "jquery";
-import {Colors} from "../colors";
-import {Util} from "../util";
-import {SimulationController} from "./simulationcontroller";
-import {MapView} from "../views/mapview";
-import {APIController} from "./connection/api";
-import {BuildingModeController} from "./modes/building";
-import {RoomModeController, RoomInteractionMode} from "./modes/room";
-import {ObjectModeController} from "./modes/object";
-import {NodeModeController} from "./modes/node";
-import {ScaleIndicatorController} from "./scaleindicator";
-
-export const CELL_SIZE = 50;
-
-
-export enum AppMode {
- CONSTRUCTION,
- SIMULATION
-}
-
-
-/**
- * The current level of datacenter hierarchy that is selected
- */
-export enum InteractionLevel {
- BUILDING,
- ROOM,
- OBJECT,
- NODE
-}
-
-
-/**
- * Possible states that the application can be in, in terms of interaction
- */
-export enum InteractionMode {
- DEFAULT,
- SELECT_ROOM
-}
-
-
-/**
- * Class responsible for handling user input in the map.
- */
-export class MapController {
- public stage: createjs.Stage;
- public mapView: MapView;
-
- public appMode: AppMode;
- public interactionLevel: InteractionLevel;
- public interactionMode: InteractionMode;
-
- public buildingModeController: BuildingModeController;
- public roomModeController: RoomModeController;
- public objectModeController: ObjectModeController;
- public nodeModeController: NodeModeController;
-
- public simulationController: SimulationController;
- public api: APIController;
- private scaleIndicatorController: ScaleIndicatorController;
-
- private canvas: JQuery;
- private gridDragging: boolean;
-
- private infoTimeOut: any;
- // Current mouse coordinates on the stage canvas (mainly for zooming purposes)
- private currentStageMouseX: number;
-
- private currentStageMouseY: number;
- // Keep start coordinates relative to the grid to compute dragging offset later
- private gridDragBeginX: number;
-
- private gridDragBeginY: number;
- // Keep start coordinates on stage to compute delta values
- private stageDragBeginX: number;
- private stageDragBeginY: number;
-
- private MAX_DELTA = 5;
-
-
- /**
- * Hides all side menus except for the active one.
- *
- * @param activeMenu An identifier (e.g. #room-menu) for the menu container
- */
- public static hideAndShowMenus(activeMenu: string): void {
- $(".menu-container.level-menu").each((index: number, elem: Element) => {
- if ($(elem).is(activeMenu)) {
- $(elem).removeClass("hidden");
- } else {
- $(elem).addClass("hidden");
- }
- });
- }
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.stage = this.mapView.stage;
-
- new APIController((apiInstance: APIController) => {
- this.api = apiInstance;
-
- this.buildingModeController = new BuildingModeController(this);
- this.roomModeController = new RoomModeController(this);
- this.objectModeController = new ObjectModeController(this);
- this.nodeModeController = new NodeModeController(this);
- this.simulationController = new SimulationController(this);
-
- this.scaleIndicatorController = new ScaleIndicatorController(this);
-
- this.canvas = $("#main-canvas");
-
- $(window).on("resize", () => {
- this.onWindowResize();
- });
-
- this.gridDragging = false;
-
- this.appMode = AppMode.CONSTRUCTION;
- this.interactionLevel = InteractionLevel.BUILDING;
- this.interactionMode = InteractionMode.DEFAULT;
-
- this.setAllMenuModes();
-
- this.setupMapInteractionHandlers();
- this.setupEventListeners();
- this.buildingModeController.setupEventListeners();
- this.roomModeController.setupEventListeners();
- this.objectModeController.setupEventListeners();
- this.nodeModeController.setupEventListeners();
-
- this.scaleIndicatorController.init($(".scale-indicator"));
- this.scaleIndicatorController.update();
-
- this.mapView.roomLayer.setClickable(true);
-
- this.matchUserAuthLevel();
- });
- }
-
- /**
- * Hides and shows the menu bodies corresponding to the current mode (construction or simulation).
- */
- public setAllMenuModes(): void {
- $(".menu-body" + (this.appMode === AppMode.CONSTRUCTION ? ".construction" : ".simulation")).show();
- $(".menu-body" + (this.appMode === AppMode.CONSTRUCTION ? ".simulation" : ".construction")).hide();
- }
-
- /**
- * Checks whether the mapContainer is still within its legal bounds.
- *
- * Resets, if necessary, to the most similar still legal position.
- */
- public checkAndResetCanvasMovement(): void {
- if (this.mapView.mapContainer.x + this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX < this.mapView.canvasWidth) {
- this.mapView.mapContainer.x = this.mapView.canvasWidth - this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX;
- }
- if (this.mapView.mapContainer.x > 0) {
- this.mapView.mapContainer.x = 0;
- }
- if (this.mapView.mapContainer.y + this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX < this.mapView.canvasHeight) {
- this.mapView.mapContainer.y = this.mapView.canvasHeight - this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX;
- }
- if (this.mapView.mapContainer.y > 0) {
- this.mapView.mapContainer.y = 0;
- }
- }
-
- /**
- * Checks whether the mapContainer is still within its legal bounds and generates corrections if needed.
- *
- * Does not change the x and y coordinates, only returns.
- */
- public checkCanvasMovement(x: number, y: number, scale: number): IGridPosition {
- const result: IGridPosition = {x: x, y: y};
- if (x + this.mapView.gridLayer.gridPixelSize * scale < this.mapView.canvasWidth) {
- result.x = this.mapView.canvasWidth - this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX;
- }
- if (x > 0) {
- result.x = 0;
- }
- if (y + this.mapView.gridLayer.gridPixelSize * scale < this.mapView.canvasHeight) {
- result.y = this.mapView.canvasHeight - this.mapView.gridLayer.gridPixelSize *
- this.mapView.mapContainer.scaleX;
- }
- if (y > 0) {
- result.y = 0;
- }
-
- return result;
- }
-
- /**
- * Checks whether the current interaction mode is a hover mode (meaning that there is a hover item present).
- *
- * @returns {boolean} Whether it is in hover mode.
- */
- public isInHoverMode(): boolean {
- return this.roomModeController !== undefined &&
- (this.interactionMode === InteractionMode.SELECT_ROOM ||
- this.roomModeController.roomInteractionMode === RoomInteractionMode.ADD_RACK ||
- this.roomModeController.roomInteractionMode === RoomInteractionMode.ADD_PSU ||
- this.roomModeController.roomInteractionMode === RoomInteractionMode.ADD_COOLING_ITEM);
- }
-
- public static showConfirmDeleteDialog(itemType: string, onConfirm: () => void): void {
- const modalDialog = <any>$("#confirm-delete");
- modalDialog.find(".modal-body").text("Are you sure you want to delete this " + itemType + "?");
-
- const callback = () => {
- onConfirm();
- modalDialog.modal("hide");
- modalDialog.find("button.confirm").first().off("click");
- $(document).off("keypress");
- };
-
- $(document).on("keypress", (event: JQueryEventObject) => {
- if (event.which === 13) {
- callback();
- } else if (event.which === 27) {
- modalDialog.modal("hide");
- $(document).off("keypress");
- modalDialog.find("button.confirm").first().off("click");
- }
- });
- modalDialog.find("button.confirm").first().on("click", callback);
- modalDialog.modal("show");
- }
-
- /**
- * Shows an informational popup in a corner of the screen, communicating a certain event.
- *
- * @param message The message to be displayed in the body of the popup
- * @param type The severity of the message; Currently supported: "info" and "warning"
- */
- public showInfoBalloon(message: string, type: string): void {
- const balloon = $(".info-balloon");
- balloon.html('<span></span>' + message);
- const callback = () => {
- balloon.fadeOut(300);
-
- this.infoTimeOut = undefined;
- };
- const DISPLAY_TIME = 3000;
-
- const balloonIcon = balloon.find("span").first();
- balloonIcon.removeClass();
-
- balloon.css("background", Colors.INFO_BALLOON_MAP[type]);
- balloonIcon.addClass("glyphicon");
- if (type === "info") {
- balloonIcon.addClass("glyphicon-info-sign");
- } else if (type === "warning") {
- balloonIcon.addClass("glyphicon-exclamation-sign");
- }
-
- if (this.infoTimeOut === undefined) {
- balloon.fadeIn(300);
- this.infoTimeOut = setTimeout(callback, DISPLAY_TIME);
- } else {
- clearTimeout(this.infoTimeOut);
- this.infoTimeOut = setTimeout(callback, DISPLAY_TIME);
- }
- }
-
- private setupMapInteractionHandlers(): void {
- this.stage.enableMouseOver(20);
-
- // Listen for mouse movement events to update hover positions
- this.stage.on("stagemousemove", (event: createjs.MouseEvent) => {
- this.currentStageMouseX = event.stageX;
- this.currentStageMouseY = event.stageY;
-
- const gridPos = this.convertScreenCoordsToGridCoords([event.stageX, event.stageY]);
- const tileX = gridPos.x;
- const tileY = gridPos.y;
-
- // Check whether the coordinates of the hover location have changed since the last draw
- if (this.mapView.hoverLayer.hoverTilePosition.x !== tileX) {
- this.mapView.hoverLayer.hoverTilePosition.x = tileX;
- this.mapView.updateScene = true;
- }
- if (this.mapView.hoverLayer.hoverTilePosition.y !== tileY) {
- this.mapView.hoverLayer.hoverTilePosition.y = tileY;
- this.mapView.updateScene = true;
- }
- });
-
- // Handle mousedown interaction
- this.stage.on("mousedown", (e: createjs.MouseEvent) => {
- this.stageDragBeginX = e.stageX;
- this.stageDragBeginY = e.stageY;
- });
-
- // Handle map dragging interaction
- // Drag begin and progress handlers
- this.mapView.mapContainer.on("pressmove", (e: createjs.MouseEvent) => {
- if (!this.gridDragging) {
- this.gridDragBeginX = e.stageX - this.mapView.mapContainer.x;
- this.gridDragBeginY = e.stageY - this.mapView.mapContainer.y;
- this.stageDragBeginX = e.stageX;
- this.stageDragBeginY = e.stageY;
- this.gridDragging = true;
- } else {
- this.mapView.mapContainer.x = e.stageX - this.gridDragBeginX;
- this.mapView.mapContainer.y = e.stageY - this.gridDragBeginY;
-
- this.checkAndResetCanvasMovement();
-
- this.mapView.updateScene = true;
- }
- });
-
- // Drag exit handlers
- this.mapView.mapContainer.on("pressup", (e: createjs.MouseEvent) => {
- if (this.gridDragging) {
- this.gridDragging = false;
- }
-
- if (Math.abs(e.stageX - this.stageDragBeginX) < this.MAX_DELTA &&
- Math.abs(e.stageY - this.stageDragBeginY) < this.MAX_DELTA) {
- this.handleCanvasMouseClick(e.stageX, e.stageY);
- }
- });
-
- // Disable an ongoing drag action if the mouse leaves the canvas
- this.mapView.stage.on("mouseleave", () => {
- if (this.gridDragging) {
- this.gridDragging = false;
- }
- });
-
- // Relay scroll events to the MapView zoom handler
- $("#main-canvas").on("mousewheel", (event: JQueryEventObject) => {
- const originalEvent = (<any>event.originalEvent);
- this.mapView.zoom([this.currentStageMouseX, this.currentStageMouseY], -0.7 * originalEvent.deltaY);
- this.scaleIndicatorController.update();
- });
- }
-
- /**
- * Connects clickable UI elements to their respective event listeners.
- */
- private setupEventListeners(): void {
- // Zooming elements
- $("#zoom-plus").on("click", () => {
- this.mapView.zoom([
- this.mapView.canvasWidth / 2,
- this.mapView.canvasHeight / 2
- ], 20);
- });
- $("#zoom-minus").on("click", () => {
- this.mapView.zoom([
- this.mapView.canvasWidth / 2,
- this.mapView.canvasHeight / 2
- ], -20);
- });
-
- $(".export-canvas").click(() => {
- this.exportCanvasToImage();
- });
-
- // Menu panels
- $(".menu-header-bar .menu-collapse").on("click", (event: JQueryEventObject) => {
- const container = $(event.target).closest(".menu-container");
- if (this.appMode === AppMode.CONSTRUCTION) {
- container.children(".menu-body.construction").first().slideToggle(300);
- } else if (this.appMode === AppMode.SIMULATION) {
- container.children(".menu-body.simulation").first().slideToggle(300);
- }
-
- });
-
- // Menu close button
- $(".menu-header-bar .menu-exit").on("click", (event: JQueryEventObject) => {
- const nearestMenuContainer = $(event.target).closest(".menu-container");
- if (nearestMenuContainer.is("#node-menu")) {
- this.interactionLevel = InteractionLevel.OBJECT;
- $(".node-element-overlay").addClass("hidden");
- }
- nearestMenuContainer.addClass("hidden");
- });
-
- // Handler for the construction mode switch
- $("#construction-mode-switch").on("click", () => {
- this.simulationController.exitMode();
- });
-
- // Handler for the simulation mode switch
- $("#simulation-mode-switch").on("click", () => {
- this.simulationController.enterMode();
- });
-
- // Handler for the version-save button
- $("#save-version-btn").on("click", (event: JQueryEventObject) => {
- const target = $(event.target);
-
- target.attr("data-saved", "false");
- const lastPath = this.mapView.simulation.paths[this.mapView.simulation.paths.length - 1];
- this.api.branchFromPath(
- this.mapView.simulation.id, lastPath.id, lastPath.sections[lastPath.sections.length - 1].startTick + 1
- ).then((data: IPath) => {
- this.mapView.simulation.paths.push(data);
- this.mapView.currentDatacenter = data.sections[data.sections.length - 1].datacenter;
- target.attr("data-saved", "true");
- });
- });
-
- $(document).on("keydown", (event: JQueryKeyEventObject) => {
- if ($(event.target).is('input')) {
- return;
- }
-
- if (event.which === 83) {
- this.simulationController.enterMode();
- } else if (event.which === 67) {
- this.simulationController.exitMode();
- } else if (event.which == 32) {
- if (this.appMode === AppMode.SIMULATION) {
- this.simulationController.timelineController.togglePlayback();
- }
- }
- });
- }
-
- /**
- * Handles a simple mouse click (without drag) on the canvas.
- *
- * @param stageX The x coordinate of the location in pixels on the stage
- * @param stageY The y coordinate of the location in pixels on the stage
- */
- private handleCanvasMouseClick(stageX: number, stageY: number): void {
- const gridPos = this.convertScreenCoordsToGridCoords([stageX, stageY]);
-
- if (this.interactionLevel === InteractionLevel.BUILDING) {
- if (this.interactionMode === InteractionMode.DEFAULT) {
- const roomIndex = Util.roomCollisionIndexOf(this.mapView.currentDatacenter.rooms, gridPos);
-
- if (roomIndex !== -1) {
- this.interactionLevel = InteractionLevel.ROOM;
- this.roomModeController.enterMode(this.mapView.currentDatacenter.rooms[roomIndex]);
- }
- } else if (this.interactionMode === InteractionMode.SELECT_ROOM) {
- if (this.mapView.roomLayer.checkHoverTileValidity(gridPos)) {
- this.buildingModeController.addSelectedTile(this.mapView.hoverLayer.hoverTilePosition);
- } else if (Util.tileListContainsPosition(this.mapView.roomLayer.selectedTiles, gridPos)) {
- this.buildingModeController.removeSelectedTile(this.mapView.hoverLayer.hoverTilePosition);
- }
- }
- } else if (this.interactionLevel === InteractionLevel.ROOM) {
- this.roomModeController.handleCanvasMouseClick(gridPos);
- } else if (this.interactionLevel === InteractionLevel.OBJECT) {
- if (gridPos.x !== this.mapView.grayLayer.currentObjectTile.position.x ||
- gridPos.y !== this.mapView.grayLayer.currentObjectTile.position.y) {
- this.objectModeController.goToRoomMode();
- }
- } else if (this.interactionLevel === InteractionLevel.NODE) {
- this.interactionLevel = InteractionLevel.OBJECT;
- this.nodeModeController.goToObjectMode();
- }
- }
-
- /**
- * Takes screen (stage) coordinates and returns the grid cell position they belong to.
- *
- * @param stagePosition The raw x and y coordinates of the wanted position
- * @returns {Array} The corresponding grid cell coordinates
- */
- private convertScreenCoordsToGridCoords(stagePosition: number[]): IGridPosition {
- const result = {x: 0, y: 0};
- result.x = Math.floor((stagePosition[0] - this.mapView.mapContainer.x) /
- (this.mapView.mapContainer.scaleX * CELL_SIZE));
- result.y = Math.floor((stagePosition[1] - this.mapView.mapContainer.y) /
- (this.mapView.mapContainer.scaleY * CELL_SIZE));
- return result;
- }
-
- /**
- * Adjusts the canvas size to fit the window perfectly.
- */
- private onWindowResize() {
- const parent = this.canvas.parent(".app-content");
- parent.height($(window).height() - 50);
- this.canvas.attr("width", parent.width());
- this.canvas.attr("height", parent.height());
- this.mapView.canvasWidth = parent.width();
- this.mapView.canvasHeight = parent.height();
-
- if (this.interactionLevel === InteractionLevel.BUILDING) {
- this.mapView.zoomOutOnDC();
- } else if (this.interactionLevel === InteractionLevel.ROOM) {
- this.mapView.zoomInOnRoom(this.roomModeController.currentRoom);
- } else {
- this.mapView.zoomInOnRoom(this.roomModeController.currentRoom, true);
- }
-
- this.mapView.updateScene = true;
- }
-
- private matchUserAuthLevel() {
- const authLevel = localStorage.getItem("simulationAuthLevel");
- if (authLevel === "VIEW") {
- $(".side-menu-container.right-middle-side, .side-menu-container.right-side").hide();
- }
- }
-
- private exportCanvasToImage() {
- const canvasData = (<HTMLCanvasElement>this.canvas.get(0)).toDataURL("image/png");
- const newWindow = window.open('about:blank', 'OpenDC Canvas Export');
- newWindow.document.write("<img src='" + canvasData + "' alt='Canvas Image Export'/>");
- newWindow.document.title = "OpenDC Canvas Export";
- }
-}
diff --git a/src/scripts/controllers/modes/building.ts b/src/scripts/controllers/modes/building.ts
deleted file mode 100644
index 217f5935..00000000
--- a/src/scripts/controllers/modes/building.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-import {InteractionMode, MapController} from "../mapcontroller";
-import {MapView} from "../../views/mapview";
-import * as $ from "jquery";
-
-
-/**
- * Class responsible for handling building mode interactions.
- */
-export class BuildingModeController {
- public newRoomId: number;
-
- private mapController: MapController;
- private mapView: MapView;
-
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = this.mapController.mapView;
- }
-
- /**
- * Connects all DOM event listeners to their respective element targets.
- */
- public setupEventListeners() {
- const resetConstructionButtons = () => {
- this.mapController.interactionMode = InteractionMode.DEFAULT;
- this.mapView.hoverLayer.setHoverTileVisibility(false);
- $("#room-construction").text("Construct new room");
- $("#room-construction-cancel").slideToggle(300);
- };
-
- // Room construction button
- $("#room-construction").on("click", (event: JQueryEventObject) => {
- if (this.mapController.interactionMode === InteractionMode.DEFAULT) {
- this.mapController.interactionMode = InteractionMode.SELECT_ROOM;
- this.mapView.hoverLayer.setHoverTileVisibility(true);
- this.mapController.api.addRoomToDatacenter(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id).then((room: IRoom) => {
- this.newRoomId = room.id;
- });
- $(event.target).text("Finalize room");
- $("#room-construction-cancel").slideToggle(300);
- } else if (this.mapController.interactionMode === InteractionMode.SELECT_ROOM) {
- resetConstructionButtons();
- this.finalizeRoom();
- }
- });
-
- // Cancel button for room construction
- $("#room-construction-cancel").on("click", () => {
- resetConstructionButtons();
- this.cancelRoomConstruction();
- });
- }
-
- /**
- * Cancels room construction and deletes the temporary room created previously.
- */
- public cancelRoomConstruction() {
- this.mapController.api.deleteRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.newRoomId).then(() => {
- this.mapView.roomLayer.cancelRoomConstruction();
- });
- }
-
- /**
- * Finalizes room construction by triggering a redraw of the room layer with the new room added.
- */
- public finalizeRoom() {
- this.mapController.api.getRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.newRoomId).then((room: IRoom) => {
- this.mapView.roomLayer.finalizeRoom(room);
- });
- }
-
- /**
- * Adds a newly selected tile to the list of selected tiles.
- *
- * @param position The new tile position to be added
- */
- public addSelectedTile(position: IGridPosition): void {
- const tile = {
- id: -1,
- roomId: this.newRoomId,
- position: {x: position.x, y: position.y}
- };
- this.mapController.api.addTileToRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.newRoomId, tile).then((tile: ITile) => {
- this.mapView.roomLayer.addSelectedTile(tile);
- });
- }
-
- /**
- * Removes a previously selected tile.
- *
- * @param position The position of the tile to be removed
- */
- public removeSelectedTile(position: IGridPosition): void {
- let objectIndex = -1;
-
- for (let i = 0; i < this.mapView.roomLayer.selectedTileObjects.length; i++) {
- const tile = this.mapView.roomLayer.selectedTileObjects[i];
- if (tile.position.x === position.x && tile.position.y === position.y) {
- objectIndex = i;
- }
- }
- this.mapController.api.deleteTile(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.newRoomId,
- this.mapView.roomLayer.selectedTileObjects[objectIndex].tileObject.id).then(() => {
- this.mapView.roomLayer.removeSelectedTile(position, objectIndex);
- });
- }
-}
diff --git a/src/scripts/controllers/modes/node.ts b/src/scripts/controllers/modes/node.ts
deleted file mode 100644
index cef61bba..00000000
--- a/src/scripts/controllers/modes/node.ts
+++ /dev/null
@@ -1,297 +0,0 @@
-import {MapController, AppMode, InteractionLevel} from "../mapcontroller";
-import {MapView} from "../../views/mapview";
-import * as $ from "jquery";
-
-
-/**
- * Class responsible for rendering node mode and handling UI interactions within it.
- */
-export class NodeModeController {
- public currentMachine: IMachine;
-
- private mapController: MapController;
- private mapView: MapView;
-
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = this.mapController.mapView;
-
- this.loadAddDropdowns();
- }
-
- /**
- * Moves the UI model into node mode.
- *
- * @param machine The machine that was selected in rack mode
- */
- public enterMode(machine: IMachine): void {
- this.currentMachine = machine;
- this.populateUnitLists();
- $("#node-menu").removeClass("hidden");
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromRackToNode();
- }
- }
-
- /**
- * Performs cleanup and closing actions before allowing transferal to rack mode.
- */
- public goToObjectMode(): void {
- $("#node-menu").addClass("hidden");
- $(".node-element-overlay").addClass("hidden");
- this.currentMachine = undefined;
- this.mapController.interactionLevel = InteractionLevel.OBJECT;
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromNodeToRack();
- }
- }
-
- /**
- * Connects all DOM event listeners to their respective element targets.
- */
- public setupEventListeners(): void {
- const nodeMenu = $("#node-menu");
-
- nodeMenu.find(".panel-group").on("click", ".remove-unit", (event: JQueryEventObject) => {
- MapController.showConfirmDeleteDialog("unit", () => {
- const index = $(event.target).closest(".panel").index();
-
- if (index === -1) {
- return;
- }
-
- const closestTabPane = $(event.target).closest(".panel-group");
-
- let objectList, idList;
- if (closestTabPane.is("#cpu-accordion")) {
- objectList = this.currentMachine.cpus;
- idList = this.currentMachine.cpuIds;
- } else if (closestTabPane.is("#gpu-accordion")) {
- objectList = this.currentMachine.gpus;
- idList = this.currentMachine.gpuIds;
- } else if (closestTabPane.is("#memory-accordion")) {
- objectList = this.currentMachine.memories;
- idList = this.currentMachine.memoryIds;
- } else if (closestTabPane.is("#storage-accordion")) {
- objectList = this.currentMachine.storages;
- idList = this.currentMachine.storageIds;
- }
-
- idList.splice(idList.indexOf(objectList[index]).id, 1);
- objectList.splice(index, 1);
-
- this.mapController.api.updateMachine(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id, this.currentMachine).then(
- () => {
- this.populateUnitLists();
- this.mapController.objectModeController.updateNodeComponentOverlays();
- });
- });
- });
-
- nodeMenu.find(".add-unit").on("click", (event: JQueryEventObject) => {
- const dropdown = $(event.target).closest(".input-group-btn").siblings("select").first();
-
- const closestTabPane = $(event.target).closest(".input-group").siblings(".panel-group").first();
- let objectList, idList, typePlural;
- if (closestTabPane.is("#cpu-accordion")) {
- objectList = this.currentMachine.cpus;
- idList = this.currentMachine.cpuIds;
- typePlural = "cpus";
- } else if (closestTabPane.is("#gpu-accordion")) {
- objectList = this.currentMachine.gpus;
- idList = this.currentMachine.gpuIds;
- typePlural = "gpus";
- } else if (closestTabPane.is("#memory-accordion")) {
- objectList = this.currentMachine.memories;
- idList = this.currentMachine.memoryIds;
- typePlural = "memories";
- } else if (closestTabPane.is("#storage-accordion")) {
- objectList = this.currentMachine.storages;
- idList = this.currentMachine.storageIds;
- typePlural = "storages";
- }
-
- if (idList.length + 1 > 4) {
- this.mapController.showInfoBalloon("Machine has only 4 slots", "warning");
- return;
- }
-
- const id = parseInt(dropdown.val());
- idList.push(id);
- this.mapController.api.getSpecificationOfType(typePlural, id).then((spec: INodeUnit) => {
- objectList.push(spec);
-
- this.mapController.api.updateMachine(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id, this.currentMachine).then(
- () => {
- this.populateUnitLists();
- this.mapController.objectModeController.updateNodeComponentOverlays();
- });
- });
- });
- }
-
- /**
- * Populates the "add" dropdowns with all available unit options.
- */
- private loadAddDropdowns(): void {
- const unitTypes = [
- "cpus", "gpus", "memories", "storages"
- ];
- const dropdowns = [
- $("#add-cpu-form").find("select"),
- $("#add-gpu-form").find("select"),
- $("#add-memory-form").find("select"),
- $("#add-storage-form").find("select"),
- ];
-
- unitTypes.forEach((type: string, index: number) => {
- this.mapController.api.getAllSpecificationsOfType(type).then((data: any) => {
- data.forEach((option: INodeUnit) => {
- dropdowns[index].append($("<option>").val(option.id).text(option.manufacturer + " " + option.family +
- " " + option.model + " (" + option.generation + ")"));
- });
- });
- });
- }
-
- /**
- * Generates and inserts dynamically HTML code concerning all units of a machine.
- */
- private populateUnitLists(): void {
- // Contains the skeleton of a unit element and inserts the given data into it
- const generatePanel = (type: string, index: number, list: any, specSection: string): string => {
- return '<div class="panel panel-default">' +
- ' <div class="panel-heading">' +
- ' <h4 class="panel-title">' +
- ' <a class="glyphicon glyphicon-remove remove-unit" href="javascript:void(0)"></a>' +
- ' <a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#' + type + '-accordion"' +
- ' href="#' + type + '-' + index + '">' +
- list[index].manufacturer + ' ' + list[index].family + ' ' + list[index].model +
- ' </a>' +
- ' </h4>' +
- ' </div>' +
- ' <div id="' + type + '-' + index + '" class="panel-collapse collapse">' +
- ' <table class="spec-table">' +
- ' <tbody>' +
- specSection +
- ' </tbody>' +
- ' </table>' +
- ' </div>' +
- '</div>';
- };
-
- // Generates the structure of the specification list of a processing unit
- const generateProcessingUnitHtml = (element: IProcessingUnit) => {
- return ' <tr>' +
- ' <td class="glyphicon glyphicon-tasks"></td>' +
- ' <td>Number of Cores</td>' +
- ' <td>' + element.numberOfCores + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-dashboard"></td>' +
- ' <td>Clockspeed (MHz)</td>' +
- ' <td>' + element.clockRateMhz + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-flash"></td>' +
- ' <td>Energy Consumption (W)</td>' +
- ' <td>' + element.energyConsumptionW + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-alert"></td>' +
- ' <td>Failure Rate (%)</td>' +
- ' <td>' + element.failureModel.rate + '</td>' +
- ' </tr>';
- };
-
- // Generates the structure of the spec list of a storage unit
- const generateStorageUnitHtml = (element: IStorageUnit) => {
- return ' <tr>' +
- ' <td class="glyphicon glyphicon-floppy-disk"></td>' +
- ' <td>Size (Mb)</td>' +
- ' <td>' + element.sizeMb + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-dashboard"></td>' +
- ' <td>Speed (Mb/s)</td>' +
- ' <td>' + element.speedMbPerS + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-flash"></td>' +
- ' <td>Energy Consumption (W)</td>' +
- ' <td>' + element.energyConsumptionW + '</td>' +
- ' </tr>' +
- ' <tr>' +
- ' <td class="glyphicon glyphicon-alert"></td>' +
- ' <td>Failure Rate (%)</td>' +
- ' <td>' + element.failureModel.rate + '</td>' +
- ' </tr>';
- };
-
- // Inserts a "No units" message into the container of the given unit type
- const addNoUnitsMessage = (type: string) => {
- $("#" + type + "-accordion").append("<p>There are currently no units present here. " +
- "<em>Add some with the dropdown below!</em></p>");
- };
-
- let container = $("#cpu-accordion");
- container.children().remove(".panel");
- container.children().remove("p");
-
- if (this.currentMachine.cpus.length === 0) {
- addNoUnitsMessage("cpu");
- } else {
- this.currentMachine.cpus.forEach((element: ICPU, i: number) => {
- const specSection = generateProcessingUnitHtml(element);
- const content = generatePanel("cpu", i, this.currentMachine.cpus, specSection);
- container.append(content);
- });
- }
-
- container = $("#gpu-accordion");
- container.children().remove(".panel");
- container.children().remove("p");
- if (this.currentMachine.gpus.length === 0) {
- addNoUnitsMessage("gpu");
- } else {
- this.currentMachine.gpus.forEach((element: IGPU, i: number) => {
- const specSection = generateProcessingUnitHtml(element);
- const content = generatePanel("gpu", i, this.currentMachine.gpus, specSection);
- container.append(content);
- });
- }
-
- container = $("#memory-accordion");
- container.children().remove(".panel");
- container.children().remove("p");
- if (this.currentMachine.memories.length === 0) {
- addNoUnitsMessage("memory");
- } else {
- this.currentMachine.memories.forEach((element: IMemory, i: number) => {
- const specSection = generateStorageUnitHtml(element);
- const content = generatePanel("memory", i, this.currentMachine.memories, specSection);
- container.append(content);
- });
- }
-
- container = $("#storage-accordion");
- container.children().remove(".panel");
- container.children().remove("p");
- if (this.currentMachine.storages.length === 0) {
- addNoUnitsMessage("storage");
- } else {
- this.currentMachine.storages.forEach((element: IMemory, i: number) => {
- const specSection = generateStorageUnitHtml(element);
- const content = generatePanel("storage", i, this.currentMachine.storages, specSection);
- container.append(content);
- });
- }
- }
-}
diff --git a/src/scripts/controllers/modes/object.ts b/src/scripts/controllers/modes/object.ts
deleted file mode 100644
index bc358d71..00000000
--- a/src/scripts/controllers/modes/object.ts
+++ /dev/null
@@ -1,296 +0,0 @@
-import {AppMode, InteractionLevel, MapController} from "../mapcontroller";
-import {MapView} from "../../views/mapview";
-import * as $ from "jquery";
-
-
-/**
- * Class responsible for rendering object mode and handling its UI interactions.
- */
-export class ObjectModeController {
- public currentObject: IDCObject;
- public objectType: string;
- public currentRack: IRack;
- public currentPSU: IPSU;
- public currentCoolingItem: ICoolingItem;
- public currentObjectTile: ITile;
-
- private mapController: MapController;
- private mapView: MapView;
-
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = this.mapController.mapView;
- }
-
- /**
- * Performs the necessary setup actions and enters object mode.
- *
- * @param tile A reference to the tile containing the rack that was selected.
- */
- public enterMode(tile: ITile) {
- this.currentObjectTile = tile;
- this.mapView.grayLayer.currentObjectTile = tile;
- this.currentObject = tile.object;
- this.objectType = tile.objectType;
-
- // Show the corresponding sub-menu of object mode
- $(".object-sub-menu").hide();
-
- switch (this.objectType) {
- case "RACK":
- $("#rack-sub-menu").show();
- this.currentRack = <IRack>this.currentObject;
- $("#rack-name-input").val(this.currentRack.name);
- this.populateNodeList();
-
- break;
-
- case "PSU":
- $("#psu-sub-menu").show();
- this.currentPSU = <IPSU>this.currentObject;
-
- break;
-
- case "COOLING_ITEM":
- $("#cooling-item-sub-menu").show();
- this.currentCoolingItem = <ICoolingItem>this.currentObject;
-
- break;
- }
-
- this.mapView.grayLayer.drawRackLevel();
- MapController.hideAndShowMenus("#object-menu");
- this.scrollToBottom();
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromRoomToRack();
- }
- }
-
- /**
- * Leaves object mode and transfers to room mode.
- */
- public goToRoomMode() {
- this.mapController.interactionLevel = InteractionLevel.ROOM;
- this.mapView.grayLayer.hideRackLevel();
- MapController.hideAndShowMenus("#room-menu");
- this.mapController.roomModeController.enterMode(this.mapController.roomModeController.currentRoom);
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromRackToRoom();
- }
- }
-
- /**
- * Connects all DOM event listeners to their respective element targets.
- */
- public setupEventListeners() {
- // Handler for saving a new rack name
- $("#rack-name-save").on("click", () => {
- this.currentRack.name = $("#rack-name-input").text();
- this.mapController.api.updateRack(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id, this.currentRack).then(
- () => {
- this.mapController.showInfoBalloon("Rack name saved", "info");
- });
- });
-
- const nodeListContainer = $(".node-list-container");
-
- // Handler for the 'add' button of each machine slot of the rack
- nodeListContainer.on("click", ".add-node", (event: JQueryEventObject) => {
- // Convert the DOM element index to a JS array index
- const index = this.currentRack.machines.length - $(event.target).closest(".node-element").index() - 1;
-
- // Insert an empty machine at the selected position
- this.mapController.api.addMachineToRack(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id, {
- id: -1,
- rackId: this.currentRack.id,
- position: index,
- tags: [],
- cpuIds: [],
- gpuIds: [],
- memoryIds: [],
- storageIds: []
- }).then((data: IMachine) => {
- this.currentRack.machines[index] = data;
- this.populateNodeList();
- this.mapView.dcObjectLayer.draw();
- });
-
- event.stopPropagation();
- });
-
- // Handler for the 'remove' button of each machine slot of the rack
- nodeListContainer.on("click", ".remove-node", (event: JQueryEventObject) => {
- const target = $(event.target);
- MapController.showConfirmDeleteDialog("machine", () => {
- // Convert the DOM element index to a JS array index
- const index = this.currentRack.machines.length - target.closest(".node-element").index() - 1;
-
- this.mapController.api.deleteMachine(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id,
- index).then(() => {
- this.currentRack.machines[index] = null;
- this.populateNodeList();
- this.mapView.dcObjectLayer.draw();
- });
- });
- event.stopPropagation();
- });
-
- // Handler for every node element, triggering node mode
- nodeListContainer.on("click", ".node-element", (event: JQueryEventObject) => {
- const domIndex = $(event.target).closest(".node-element").index();
- const index = this.currentRack.machines.length - domIndex - 1;
- const machine = this.currentRack.machines[index];
-
- if (machine != null) {
- this.mapController.interactionLevel = InteractionLevel.NODE;
-
- // Gray out the other nodes
- $(event.target).closest(".node-list-container").children(".node-element").each((nodeIndex: number, element: Element) => {
- if (nodeIndex !== domIndex) {
- $(element).children(".node-element-overlay").removeClass("hidden");
- } else {
- $(element).children(".node-element-overlay").addClass("hidden");
- }
- });
-
- this.mapController.nodeModeController.enterMode(machine);
- }
- });
-
- // Handler for rack deletion button
- $("#rack-deletion").on("click", () => {
- MapController.showConfirmDeleteDialog("rack", () => {
- this.mapController.api.deleteRack(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id).then(() => {
- this.currentObjectTile.object = undefined;
- this.currentObjectTile.objectType = undefined;
- this.currentObjectTile.objectId = undefined;
- this.mapView.redrawMap();
- this.goToRoomMode();
- });
- });
- });
-
- // Handler for PSU deletion button
- $("#psu-deletion").on("click", () => {
- MapController.showConfirmDeleteDialog("PSU", () => {
- this.mapController.api.deletePSU(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id).then(() => {
- this.mapView.redrawMap();
- this.goToRoomMode();
- });
- this.currentObjectTile.object = undefined;
- this.currentObjectTile.objectType = undefined;
- this.currentObjectTile.objectId = undefined;
- });
- });
-
- // Handler for Cooling Item deletion button
- $("#cooling-item-deletion").on("click", () => {
- MapController.showConfirmDeleteDialog("cooling item", () => {
- this.mapController.api.deleteCoolingItem(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.mapController.roomModeController.currentRoom.id,
- this.mapController.objectModeController.currentObjectTile.id).then(() => {
- this.mapView.redrawMap();
- this.goToRoomMode();
- });
- this.currentObjectTile.object = undefined;
- this.currentObjectTile.objectType = undefined;
- this.currentObjectTile.objectId = undefined;
- });
- });
- }
-
- public updateNodeComponentOverlays(): void {
- if (this.currentRack === undefined || this.currentRack.machines === undefined) {
- return;
- }
-
- for (let i = 0; i < this.currentRack.machines.length; i++) {
- if (this.currentRack.machines[i] === null) {
- continue;
- }
-
- const container = this.mapController.appMode === AppMode.CONSTRUCTION ? ".construction" : ".simulation";
- const element = $(container + " .node-element").eq(this.currentRack.machines.length - i - 1);
- if (this.currentRack.machines[i].cpus.length !== 0) {
- element.find(".overlay-cpu").addClass("hidden");
- } else {
- element.find(".overlay-cpu").removeClass("hidden");
- }
- if (this.currentRack.machines[i].gpus.length !== 0) {
- element.find(".overlay-gpu").addClass("hidden");
- } else {
- element.find(".overlay-gpu").removeClass("hidden");
- }
- if (this.currentRack.machines[i].memories.length !== 0) {
- element.find(".overlay-memory").addClass("hidden");
- } else {
- element.find(".overlay-memory").removeClass("hidden");
- }
- if (this.currentRack.machines[i].storages.length !== 0) {
- element.find(".overlay-storage").addClass("hidden");
- } else {
- element.find(".overlay-storage").removeClass("hidden");
- }
- }
- }
-
- /**
- * Dynamically generates and inserts HTML code for every node in the current rack.
- */
- private populateNodeList(): void {
- const container = $(".node-list-container");
-
- // Remove any previously present node elements
- container.children().remove(".node-element");
-
- for (let i = 0; i < this.currentRack.machines.length; i++) {
- // Depending on whether the current machine slot is filled, allow removing or adding a new machine by adding
- // the appropriate button next to the machine slot
- const type = (this.currentRack.machines[i] == null ? "glyphicon-plus add-node" : "glyphicon-remove remove-node");
- let content =
- '<div class="node-element" data-id="' + (this.currentRack.machines[i] === null ?
- "" : this.currentRack.machines[i].id) + '">' +
- ' <div class="node-element-overlay hidden"></div>' +
- ' <a class="node-element-btn glyphicon ' + type + '" href="javascript:void(0)"></a>' +
- ' <div class="node-element-number">' + (i + 1) + '</div>';
- if (this.currentRack.machines[i] !== null) {
- content +=
- '<div class="node-element-content">' +
- ' <img src="img/app/node-cpu.png">' +
- ' <img src="img/app/node-gpu.png">' +
- ' <img src="img/app/node-memory.png">' +
- ' <img src="img/app/node-storage.png">' +
- ' <img src="img/app/node-network.png">' +
- ' <div class="icon-overlay overlay-cpu hidden"></div>' +
- ' <div class="icon-overlay overlay-gpu hidden"></div>' +
- ' <div class="icon-overlay overlay-memory hidden"></div>' +
- ' <div class="icon-overlay overlay-storage hidden"></div>' +
- ' <div class="icon-overlay overlay-network"></div>' +
- '</div>';
- }
- content += '</div>';
- // Insert the generated machine slot into the DOM
- container.prepend(content);
- }
-
- this.updateNodeComponentOverlays();
- }
-
- private scrollToBottom(): void {
- const scrollContainer = $('.node-list-container');
- scrollContainer.scrollTop(scrollContainer[0].scrollHeight);
- }
-}
diff --git a/src/scripts/controllers/modes/room.ts b/src/scripts/controllers/modes/room.ts
deleted file mode 100644
index dc7f4a41..00000000
--- a/src/scripts/controllers/modes/room.ts
+++ /dev/null
@@ -1,382 +0,0 @@
-import {Util} from "../../util";
-import {AppMode, InteractionLevel, MapController} from "../mapcontroller";
-import {MapView} from "../../views/mapview";
-import * as $ from "jquery";
-
-
-export enum RoomInteractionMode {
- DEFAULT,
- ADD_RACK,
- ADD_PSU,
- ADD_COOLING_ITEM
-}
-
-
-export class RoomModeController {
- public currentRoom: IRoom;
- public roomInteractionMode: RoomInteractionMode;
-
- private mapController: MapController;
- private mapView: MapView;
- private roomTypes: string[];
- private roomTypeMap: IRoomTypeMap;
- private availablePSUs: IPSU[];
- private availableCoolingItems: ICoolingItem[];
-
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = this.mapController.mapView;
-
- this.mapController.api.getAllRoomTypes().then((roomTypes: string[]) => {
- this.roomTypes = roomTypes;
- this.roomTypeMap = {};
-
- this.roomTypes.forEach((type: string) => {
- this.mapController.api.getAllowedObjectsByRoomType(type).then((objects: string[]) => {
- this.roomTypeMap[type] = objects;
- });
- });
-
- this.populateRoomTypeDropdown();
- });
-
- // this.mapController.api.getAllPSUSpecs().then((specs: IPSU[]) => {
- // this.availablePSUs = specs;
- // });
- //
- // this.mapController.api.getAllCoolingItemSpecs().then((specs: ICoolingItem[]) => {
- // this.availableCoolingItems = specs;
- // });
-
- this.roomInteractionMode = RoomInteractionMode.DEFAULT;
- }
-
- public enterMode(room: IRoom) {
- this.currentRoom = room;
- this.roomInteractionMode = RoomInteractionMode.DEFAULT;
-
- this.mapView.roomTextLayer.setVisibility(false);
-
- this.mapView.zoomInOnRoom(this.currentRoom);
- $("#room-name-input").val(this.currentRoom.name);
- MapController.hideAndShowMenus("#room-menu");
-
- // Pre-select the type of the current room in the dropdown
- const roomTypeDropdown = $("#roomtype-select");
- roomTypeDropdown.find('option').prop("selected", "false");
- const roomTypeIndex = this.roomTypes.indexOf(this.currentRoom.roomType);
- if (roomTypeIndex !== -1) {
- roomTypeDropdown.find('option[value="' + roomTypeIndex + '"]').prop("selected", "true");
- } else {
- roomTypeDropdown.val([]);
- }
-
- this.populateAllowedObjectTypes();
-
- this.mapView.roomLayer.setClickable(false);
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromBuildingToRoom();
- }
- }
-
- public goToBuildingMode() {
- this.mapController.interactionLevel = InteractionLevel.BUILDING;
-
- if (this.roomInteractionMode !== RoomInteractionMode.DEFAULT) {
- this.roomInteractionMode = RoomInteractionMode.DEFAULT;
- this.mapView.hoverLayer.setHoverItemVisibility(false);
- $("#add-rack-btn").attr("data-active", "false");
- $("#add-psu-btn").attr("data-active", "false");
- $("#add-cooling-item-btn").attr("data-active", "false");
- }
-
- this.mapView.roomTextLayer.setVisibility(true);
-
- this.mapView.zoomOutOnDC();
- MapController.hideAndShowMenus("#building-menu");
-
- this.mapView.roomLayer.setClickable(true);
-
- if (this.mapController.appMode === AppMode.SIMULATION) {
- this.mapController.simulationController.transitionFromRoomToBuilding();
- }
- }
-
- public setupEventListeners(): void {
- // Component buttons
- const addRackBtn = $("#add-rack-btn");
- const addPSUBtn = $("#add-psu-btn");
- const addCoolingItemBtn = $("#add-cooling-item-btn");
-
- const roomTypeDropdown = $("#roomtype-select");
-
- addRackBtn.on("click", () => {
- this.handleItemClick("RACK");
- });
- addPSUBtn.on("click", () => {
- this.handleItemClick("PSU");
- });
- addCoolingItemBtn.on("click", () => {
- this.handleItemClick("COOLING_ITEM");
- });
-
- // Handler for saving a new room name
- $("#room-name-save").on("click", () => {
- this.currentRoom.name = $("#room-name-input").text();
- this.mapController.api.updateRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom).then(() => {
- this.mapView.roomTextLayer.draw();
- this.mapController.showInfoBalloon("Room name saved", "info");
- });
- });
-
- // Handler for room deletion button
- $("#room-deletion").on("click", () => {
- MapController.showConfirmDeleteDialog("room", () => {
- this.mapController.api.deleteRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom.id).then(() => {
- const roomIndex = this.mapView.currentDatacenter.rooms.indexOf(this.currentRoom);
- this.mapView.currentDatacenter.rooms.splice(roomIndex, 1);
-
- this.mapView.redrawMap();
- this.goToBuildingMode();
- });
- });
- });
-
- // Handler for the room type dropdown component
- roomTypeDropdown.on("change", () => {
- const newRoomType = this.roomTypes[roomTypeDropdown.val()];
- if (!this.checkRoomTypeLegality(newRoomType)) {
- roomTypeDropdown.val(this.roomTypes.indexOf(this.currentRoom.roomType));
- this.mapController.showInfoBalloon("Room type couldn't be changed, illegal objects", "warning");
- return;
- }
-
- this.currentRoom.roomType = newRoomType;
- this.mapController.api.updateRoom(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom).then(() => {
- this.populateAllowedObjectTypes();
- this.mapView.roomTextLayer.draw();
- this.mapController.showInfoBalloon("Room type changed", "info");
- });
- });
- }
-
- public handleCanvasMouseClick(gridPos: IGridPosition): void {
- if (this.roomInteractionMode === RoomInteractionMode.DEFAULT) {
- const tileIndex = Util.tileListPositionIndexOf(this.currentRoom.tiles, gridPos);
-
- if (tileIndex !== -1) {
- const tile = this.currentRoom.tiles[tileIndex];
-
- if (tile.object !== undefined) {
- this.mapController.interactionLevel = InteractionLevel.OBJECT;
- this.mapController.objectModeController.enterMode(tile);
- }
- } else {
- this.goToBuildingMode();
- }
- } else if (this.roomInteractionMode === RoomInteractionMode.ADD_RACK) {
- this.addObject(this.mapView.hoverLayer.hoverTilePosition, "RACK");
-
- } else if (this.roomInteractionMode === RoomInteractionMode.ADD_PSU) {
- this.addObject(this.mapView.hoverLayer.hoverTilePosition, "PSU");
-
- } else if (this.roomInteractionMode === RoomInteractionMode.ADD_COOLING_ITEM) {
- this.addObject(this.mapView.hoverLayer.hoverTilePosition, "COOLING_ITEM");
-
- }
- }
-
- private handleItemClick(type: string): void {
- const addRackBtn = $("#add-rack-btn");
- const addPSUBtn = $("#add-psu-btn");
- const addCoolingItemBtn = $("#add-cooling-item-btn");
- const allObjectContainers = $(".dc-component-container");
- const objectTypes = [
- {
- type: "RACK",
- mode: RoomInteractionMode.ADD_RACK,
- btn: addRackBtn
- },
- {
- type: "PSU",
- mode: RoomInteractionMode.ADD_PSU,
- btn: addPSUBtn
- },
- {
- type: "COOLING_ITEM",
- mode: RoomInteractionMode.ADD_COOLING_ITEM,
- btn: addCoolingItemBtn
- }
- ];
-
- allObjectContainers.attr("data-active", "false");
-
- if (this.roomInteractionMode === RoomInteractionMode.DEFAULT) {
- this.mapView.hoverLayer.setHoverItemVisibility(true, type);
-
- if (type === "RACK") {
- this.roomInteractionMode = RoomInteractionMode.ADD_RACK;
- addRackBtn.attr("data-active", "true");
- } else if (type === "PSU") {
- this.roomInteractionMode = RoomInteractionMode.ADD_PSU;
- addPSUBtn.attr("data-active", "true");
- } else if (type === "COOLING_ITEM") {
- this.roomInteractionMode = RoomInteractionMode.ADD_COOLING_ITEM;
- addCoolingItemBtn.attr("data-active", "true");
- }
-
- return;
- }
-
- let changed = false;
- objectTypes.forEach((objectType: any, index: number) => {
- if (this.roomInteractionMode === objectType.mode) {
- if (changed) {
- return;
- }
- if (type === objectType.type) {
- this.roomInteractionMode = RoomInteractionMode.DEFAULT;
- this.mapView.hoverLayer.setHoverItemVisibility(false);
- objectType.btn.attr("data-active", "false");
- } else {
- objectTypes.forEach((otherObjectType, otherIndex: number) => {
- if (index !== otherIndex) {
- if (type === otherObjectType.type) {
- this.mapView.hoverLayer.setHoverItemVisibility(true, type);
- otherObjectType.btn.attr("data-active", "true");
- this.roomInteractionMode = otherObjectType.mode;
- }
- }
- });
- }
- changed = true;
- }
- });
- }
-
- private addObject(position: IGridPosition, type: string): void {
- if (!this.mapView.roomLayer.checkHoverTileValidity(position)) {
- return;
- }
-
- const tileList = this.mapView.mapController.roomModeController.currentRoom.tiles;
-
- for (let i = 0; i < tileList.length; i++) {
- if (tileList[i].position.x === position.x && tileList[i].position.y === position.y) {
- if (type === "RACK") {
- this.mapController.api.addRack(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom.id, tileList[i].id, {
- id: -1,
- objectType: "RACK",
- name: "",
- capacity: 42,
- powerCapacityW: 5000
- }).then((rack: IRack) => {
- tileList[i].object = rack;
- tileList[i].objectId = rack.id;
- tileList[i].objectType = type;
- this.mapView.dcObjectLayer.populateObjectList();
- this.mapView.dcObjectLayer.draw();
-
- this.mapView.updateScene = true;
- });
- } else if (type === "PSU") {
- this.mapController.api.addPSU(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom.id, tileList[i].id, this.availablePSUs[0])
- .then((psu: IPSU) => {
- tileList[i].object = psu;
- tileList[i].objectId = psu.id;
- tileList[i].objectType = type;
- this.mapView.dcObjectLayer.populateObjectList();
- this.mapView.dcObjectLayer.draw();
-
- this.mapView.updateScene = true;
- });
- } else if (type === "COOLING_ITEM") {
- this.mapController.api.addCoolingItem(this.mapView.simulation.id,
- this.mapView.currentDatacenter.id, this.currentRoom.id, tileList[i].id,
- this.availableCoolingItems[0]).then((coolingItem: ICoolingItem) => {
- tileList[i].object = coolingItem;
- tileList[i].objectId = coolingItem.id;
- tileList[i].objectType = type;
- this.mapView.dcObjectLayer.populateObjectList();
- this.mapView.dcObjectLayer.draw();
-
- this.mapView.updateScene = true;
- });
- }
-
- break;
- }
- }
- }
-
- /**
- * Populates the room-type dropdown element with all available room types
- */
- private populateRoomTypeDropdown(): void {
- const dropdown = $("#roomtype-select");
-
- this.roomTypes.forEach((type: string, index: number) => {
- dropdown.append($('<option>').text(Util.toSentenceCase(type)).val(index));
- });
- }
-
- /**
- * Loads all object types that are allowed in the current room into the menu.
- */
- private populateAllowedObjectTypes(): void {
- const addObjectsLabel = $("#add-objects-label");
- const noObjectsInfo = $("#no-objects-info");
- const allowedObjectTypes = this.roomTypeMap[this.currentRoom.roomType];
-
- $(".dc-component-container").addClass("hidden");
-
- if (allowedObjectTypes === undefined || allowedObjectTypes === null || allowedObjectTypes.length === 0) {
- addObjectsLabel.addClass("hidden");
- noObjectsInfo.removeClass("hidden");
-
- return;
- }
-
- addObjectsLabel.removeClass("hidden");
- noObjectsInfo.addClass("hidden");
- allowedObjectTypes.forEach((type: string) => {
- switch (type) {
- case "RACK":
- $("#add-rack-btn").removeClass("hidden");
- break;
- case "PSU":
- $("#add-psu-btn").removeClass("hidden");
- break;
- case "COOLING_ITEM":
- $("#add-cooling-item-btn").removeClass("hidden");
- break;
- }
- });
- }
-
- /**
- * Checks whether a given room type can be assigned to the current room based on units already present.
- *
- * @param newRoomType The new room type to be validated
- * @returns {boolean} Whether it is allowed to change the room's type to the new type
- */
- private checkRoomTypeLegality(newRoomType: string): boolean {
- let legality = true;
-
- this.currentRoom.tiles.forEach((tile: ITile) => {
- if (tile.objectType !== undefined && tile.objectType !== null && tile.objectType !== "" &&
- this.roomTypeMap[newRoomType].indexOf(tile.objectType) === -1) {
- legality = false;
- }
- });
-
- return legality;
- }
-}
diff --git a/src/scripts/controllers/scaleindicator.ts b/src/scripts/controllers/scaleindicator.ts
deleted file mode 100644
index 789f2cc7..00000000
--- a/src/scripts/controllers/scaleindicator.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import {MapController, CELL_SIZE} from "./mapcontroller";
-import {MapView} from "../views/mapview";
-
-
-export class ScaleIndicatorController {
- private static MIN_WIDTH = 50;
- private static MAX_WIDTH = 100;
-
- private mapController: MapController;
- private mapView: MapView;
-
- private jqueryObject: JQuery;
- private currentDivisor: number;
-
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = mapController.mapView;
- }
-
- public init(jqueryObject: JQuery): void {
- this.jqueryObject = jqueryObject;
- this.currentDivisor = 1;
- }
-
- public update(): void {
- const currentZoom = this.mapView.mapContainer.scaleX;
- let newWidth;
- do {
- newWidth = (currentZoom * CELL_SIZE) / this.currentDivisor;
-
- if (newWidth < ScaleIndicatorController.MIN_WIDTH) {
- this.currentDivisor /= 2;
- } else if (newWidth > ScaleIndicatorController.MAX_WIDTH) {
- this.currentDivisor *= 2;
- } else {
- break;
- }
- } while (true);
-
-
- this.jqueryObject.text(MapView.CELL_SIZE_METERS / this.currentDivisor + "m");
- this.jqueryObject.width(newWidth);
- }
-}
diff --git a/src/scripts/controllers/simulation/chart.ts b/src/scripts/controllers/simulation/chart.ts
deleted file mode 100644
index 1b67934b..00000000
--- a/src/scripts/controllers/simulation/chart.ts
+++ /dev/null
@@ -1,241 +0,0 @@
-import * as c3 from "c3";
-import {InteractionLevel, MapController} from "../mapcontroller";
-import {ColorRepresentation, SimulationController} from "../simulationcontroller";
-import {Util} from "../../util";
-
-
-export interface IStateColumn {
- loadFractions: string[] | number[];
- inUseMemoryMb: string[] | number[];
- temperatureC: string[] | number[];
-}
-
-
-export class ChartController {
- public roomSeries: { [key: number]: IStateColumn };
- public rackSeries: { [key: number]: IStateColumn };
- public machineSeries: { [key: number]: IStateColumn };
- public chart: c3.ChartAPI;
- public machineChart: c3.ChartAPI;
-
- private simulationController: SimulationController;
- private mapController: MapController;
- private chartData: (string | number)[][];
- private xSeries: (string | number)[];
- private names: { [key: string]: string };
-
-
- constructor(simulationController: SimulationController) {
- this.simulationController = simulationController;
- this.mapController = simulationController.mapController;
- }
-
- public setup(): void {
- this.names = {};
-
- this.roomSeries = {};
- this.rackSeries = {};
- this.machineSeries = {};
-
- this.simulationController.sections.forEach((simulationSection: ISection) => {
- simulationSection.datacenter.rooms.forEach((room: IRoom) => {
- if (room.roomType === "SERVER" && this.roomSeries[room.id] === undefined) {
- this.names["ro" + room.id] = (room.name === "" || room.name === undefined) ?
- "Unnamed room" : room.name;
-
- this.roomSeries[room.id] = {
- loadFractions: ["ro" + room.id],
- inUseMemoryMb: ["ro" + room.id],
- temperatureC: ["ro" + room.id]
- };
- }
-
- room.tiles.forEach((tile: ITile) => {
- if (tile.object !== undefined && tile.objectType === "RACK" && this.rackSeries[tile.objectId] === undefined) {
- const objectName = (<IRack>tile.object).name;
- this.names["ra" + tile.objectId] = objectName === "" || objectName === undefined ?
- "Unnamed rack" : objectName;
-
- this.rackSeries[tile.objectId] = {
- loadFractions: ["ra" + tile.objectId],
- inUseMemoryMb: ["ra" + tile.objectId],
- temperatureC: ["ra" + tile.objectId]
- };
-
- (<IRack>tile.object).machines.forEach((machine: IMachine) => {
- if (machine === null || this.machineSeries[machine.id] !== undefined) {
- return;
- }
-
- this.names["ma" + machine.id] = "Machine at position " + (machine.position + 1).toString();
-
- this.machineSeries[machine.id] = {
- loadFractions: ["ma" + machine.id],
- inUseMemoryMb: ["ma" + machine.id],
- temperatureC: ["ma" + machine.id]
- };
- });
- }
- });
- });
- });
-
-
- this.xSeries = ["time"];
- this.chartData = [this.xSeries];
-
- this.chart = this.chartSetup("#statistics-chart");
- this.machineChart = this.chartSetup("#machine-statistics-chart");
- }
-
- public chartSetup(chartId: string): c3.ChartAPI {
- return c3.generate({
- bindto: chartId,
- data: {
- // xFormat: '%S',
- x: "time",
- columns: this.chartData,
- names: this.names
- },
- axis: {
- x: {
- type: "timeseries",
- tick: {
- format: function (time: Date) {
- let formattedTime = time.getSeconds() + "s";
-
- if (time.getMinutes() > 0) {
- formattedTime = time.getMinutes() + "m" + formattedTime;
- }
- if (time.getHours() > 0) {
- formattedTime = time.getHours() + "h" + formattedTime;
- }
-
- return formattedTime;
- },
- culling: {
- max: 5
- },
- count: 8
- },
- padding: {
- left: 0,
- right: 10
- }
- },
- y: {
- min: 0,
- max: 1,
- padding: {
- top: 0,
- bottom: 0
- },
- tick: {
- format: function (d) {
- return (Math.round(d * 100) / 100).toString();
- }
- }
- }
- }
- });
- }
-
- public update(): void {
- this.xSeries = (<(number|string)[]>["time"]).concat(<any[]> Util.timeRange(this.simulationController.currentTick));
-
- this.chartData = [this.xSeries];
-
- let prefix = "";
- let machineId = -1;
- if (this.mapController.interactionLevel === InteractionLevel.BUILDING) {
- for (let roomId in this.roomSeries) {
- if (this.roomSeries.hasOwnProperty(roomId)) {
- if (this.simulationController.colorRepresentation === ColorRepresentation.LOAD) {
- this.chartData.push(this.roomSeries[roomId].loadFractions);
- }
- }
- }
- prefix = "ro";
- } else if (this.mapController.interactionLevel === InteractionLevel.ROOM) {
- for (let rackId in this.rackSeries) {
- if (this.rackSeries.hasOwnProperty(rackId) &&
- this.simulationController.rackToRoomMap[rackId] ===
- this.mapController.roomModeController.currentRoom.id) {
- if (this.simulationController.colorRepresentation === ColorRepresentation.LOAD) {
- this.chartData.push(this.rackSeries[rackId].loadFractions);
- }
- }
- }
- prefix = "ra";
- } else if (this.mapController.interactionLevel === InteractionLevel.NODE) {
- if (this.simulationController.colorRepresentation === ColorRepresentation.LOAD) {
- this.chartData.push(
- this.machineSeries[this.mapController.nodeModeController.currentMachine.id].loadFractions
- );
- }
- prefix = "ma";
- machineId = this.mapController.nodeModeController.currentMachine.id;
- }
-
- const unloads: string[] = [];
- for (let id in this.names) {
- if (this.names.hasOwnProperty(id)) {
- if (machineId === -1) {
- if (id.substr(0, 2) !== prefix ||
- (this.mapController.interactionLevel === InteractionLevel.ROOM &&
- this.simulationController.rackToRoomMap[parseInt(id.substr(2))] !==
- this.mapController.roomModeController.currentRoom.id)) {
- unloads.push(id);
- }
- }
- else {
- if (id !== prefix + machineId) {
- unloads.push(id);
- }
- }
- }
- }
-
- let targetChart: c3.ChartAPI;
- if (this.mapController.interactionLevel === InteractionLevel.NODE) {
- targetChart = this.machineChart;
- } else {
- targetChart = this.chart;
- }
-
- targetChart.load({
- columns: this.chartData,
- unload: unloads
- });
-
- }
-
- public tickUpdated(tick: number): void {
- const roomStates: IRoomState[] = this.simulationController.stateCache.stateList[tick].roomStates;
- roomStates.forEach((roomState: IRoomState) => {
- ChartController.insertAtIndex(this.roomSeries[roomState.roomId].loadFractions, tick + 1, roomState.loadFraction);
- });
-
- const rackStates: IRackState[] = this.simulationController.stateCache.stateList[tick].rackStates;
- rackStates.forEach((rackState: IRackState) => {
- ChartController.insertAtIndex(this.rackSeries[rackState.rackId].loadFractions, tick + 1, rackState.loadFraction);
- });
-
- const machineStates: IMachineState[] = this.simulationController.stateCache.stateList[tick].machineStates;
- machineStates.forEach((machineState: IMachineState) => {
- ChartController.insertAtIndex(this.machineSeries[machineState.machineId].loadFractions, tick + 1, machineState.loadFraction);
- });
- }
-
- private static insertAtIndex(list: any[], index: number, data: any): void {
- if (index > list.length) {
- let i = list.length;
- while (i < index) {
- list[i] = null;
- i++;
- }
- }
-
- list[index] = data;
- }
-}
diff --git a/src/scripts/controllers/simulation/statecache.ts b/src/scripts/controllers/simulation/statecache.ts
deleted file mode 100644
index 0a7767fa..00000000
--- a/src/scripts/controllers/simulation/statecache.ts
+++ /dev/null
@@ -1,321 +0,0 @@
-import {SimulationController} from "../simulationcontroller";
-
-
-export class StateCache {
- public static CACHE_INTERVAL = 10000;
- private static PREFERRED_CACHE_ADVANCE = 5;
-
- public stateList: {[key: number]: ITickState};
- public lastCachedTick: number;
- public cacheBlock: boolean;
-
- private simulationController: SimulationController;
- private intervalId: any;
- private caching: boolean;
-
- // Item caches
- private machineCache: {[keys: number]: IMachine};
- private rackCache: {[keys: number]: IRack};
- private roomCache: {[keys: number]: IRoom};
- private taskCache: {[keys: number]: ITask};
-
-
- constructor(simulationController: SimulationController) {
- this.stateList = {};
- this.lastCachedTick = 0;
- this.cacheBlock = true;
- this.simulationController = simulationController;
- this.caching = false;
- }
-
- public startCaching(): void {
- this.machineCache = {};
- this.rackCache = {};
- this.roomCache = {};
- this.taskCache = {};
-
- this.simulationController.mapView.currentDatacenter.rooms.forEach((room: IRoom) => {
- this.addRoomToCache(room);
- });
- this.simulationController.currentExperiment.trace.tasks.forEach((task: ITask) => {
- this.taskCache[task.id] = task;
- });
-
- this.caching = true;
-
- this.cache();
- this.intervalId = setInterval(() => {
- this.cache();
- }, StateCache.CACHE_INTERVAL);
- }
-
- private addRoomToCache(room: IRoom) {
- this.roomCache[room.id] = room;
-
- room.tiles.forEach((tile: ITile) => {
- if (tile.objectType === "RACK") {
- this.rackCache[tile.objectId] = <IRack>tile.object;
-
- (<IRack> tile.object).machines.forEach((machine: IMachine) => {
- if (machine !== null) {
- this.machineCache[machine.id] = machine;
- }
- });
- }
- });
- }
-
- public stopCaching(): void {
- if (this.caching) {
- this.caching = false;
- clearInterval(this.intervalId);
- }
- }
-
- private cache(): void {
- const tick = this.lastCachedTick + 1;
-
- this.updateLastTick().then(() => {
- // Check if end of simulated region has been reached
- if (this.lastCachedTick > this.simulationController.lastSimulatedTick) {
- return;
- }
-
- this.fetchAllAvailableStates().then((data) => {
- this.stateList = data;
-
- // Determine last cached tick
- const ticks = Object.keys(this.stateList).sort((a, b) => {
- return parseInt(a) - parseInt(b);
- });
- if (ticks.length > 0) {
- this.lastCachedTick = parseInt(ticks[ticks.length - 1]);
- }
-
- for (let i = 1; i <= this.lastCachedTick; i++) {
- this.updateTasksForNewTick(i);
-
- // Update chart cache
- this.simulationController.chartController.tickUpdated(i);
- }
-
- if (!this.cacheBlock && this.lastCachedTick - this.simulationController.currentTick <= 0) {
- this.cacheBlock = true;
- return;
- }
-
- if (this.cacheBlock) {
- if (this.lastCachedTick - this.simulationController.currentTick >= StateCache.PREFERRED_CACHE_ADVANCE) {
- this.cacheBlock = false;
- }
- }
- });
- });
- }
-
- private updateTasksForNewTick(tick: number): void {
- const taskIDsInTick = [];
-
- this.stateList[tick].taskStates.forEach((taskState: ITaskState) => {
- taskIDsInTick.push(taskState.taskId);
- if (this.stateList[tick - 1] !== undefined) {
- let previousFlops = 0;
- const previousStates = this.stateList[tick - 1].taskStates;
-
- for (let i = 0; i < previousStates.length; i++) {
- if (previousStates[i].taskId === taskState.taskId) {
- previousFlops = previousStates[i].flopsLeft;
- break;
- }
- }
-
- if (previousFlops > 0 && taskState.flopsLeft === 0) {
- taskState.task.finishedTick = tick;
- }
- }
- });
-
- // Generate pseudo-task-states for tasks that haven't started yet or have already finished
- const traceTasks = this.simulationController.currentExperiment.trace.tasks;
- if (taskIDsInTick.length !== traceTasks.length) {
- traceTasks
- .filter((task: ITask) => {
- return taskIDsInTick.indexOf(task.id) === -1;
- })
- .forEach((task: ITask) => {
- const flopStateCount = task.startTick >= tick ? task.totalFlopCount : 0;
-
- this.stateList[tick].taskStates.push({
- id: -1,
- taskId: task.id,
- task: task,
- experimentId: this.simulationController.currentExperiment.id,
- tick,
- flopsLeft: flopStateCount
- });
- });
- }
-
- this.stateList[tick].taskStates.sort((a: ITaskState, b: ITaskState) => {
- return a.task.startTick - b.task.startTick;
- });
- }
-
- private updateLastTick(): Promise<void> {
- return this.simulationController.mapController.api.getLastSimulatedTickByExperiment(
- this.simulationController.simulation.id, this.simulationController.currentExperiment.id).then((data) => {
- this.simulationController.lastSimulatedTick = data;
- });
- }
-
- private fetchAllAvailableStates(): Promise<{[key: number]: ITickState}> {
- let machineStates, rackStates, roomStates, taskStates;
- const promises = [];
-
- promises.push(
- this.simulationController.mapController.api.getMachineStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.machineCache
- ).then((states: IMachineState[]) => {
- machineStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getRackStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.rackCache
- ).then((states: IRackState[]) => {
- rackStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getRoomStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.roomCache
- ).then((states: IRoomState[]) => {
- roomStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getTaskStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.taskCache
- ).then((states: ITaskState[]) => {
- taskStates = states;
- })
- );
-
- return Promise.all(promises).then(() => {
- const tickStates: {[key: number]: ITickState} = {};
-
- machineStates.forEach((machineState: IMachineState) => {
- if (tickStates[machineState.tick] === undefined) {
- tickStates[machineState.tick] = {
- tick: machineState.tick,
- machineStates: [machineState],
- rackStates: [],
- roomStates: [],
- taskStates: []
- };
- } else {
- tickStates[machineState.tick].machineStates.push(machineState);
- }
- });
- rackStates.forEach((rackState: IRackState) => {
- if (tickStates[rackState.tick] === undefined) {
- tickStates[rackState.tick] = {
- tick: rackState.tick,
- machineStates: [],
- rackStates: [rackState],
- roomStates: [],
- taskStates: []
- };
- } else {
- tickStates[rackState.tick].rackStates.push(rackState);
- }
- });
- roomStates.forEach((roomState: IRoomState) => {
- if (tickStates[roomState.tick] === undefined) {
- tickStates[roomState.tick] = {
- tick: roomState.tick,
- machineStates: [],
- rackStates: [],
- roomStates: [roomState],
- taskStates: []
- };
- } else {
- tickStates[roomState.tick].roomStates.push(roomState);
- }
- });
- taskStates.forEach((taskState: ITaskState) => {
- if (tickStates[taskState.tick] === undefined) {
- tickStates[taskState.tick] = {
- tick: taskState.tick,
- machineStates: [],
- rackStates: [],
- roomStates: [],
- taskStates: [taskState]
- };
- } else {
- tickStates[taskState.tick].taskStates.push(taskState);
- }
- });
-
- return tickStates;
- });
- }
-
- private fetchAllStatesOfTick(tick: number): Promise<ITickState> {
- const tickState: ITickState = {
- tick,
- machineStates: [],
- rackStates: [],
- roomStates: [],
- taskStates: []
- };
- const promises = [];
-
- promises.push(
- this.simulationController.mapController.api.getMachineStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.machineCache, tick
- ).then((states: IMachineState[]) => {
- tickState.machineStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getRackStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.rackCache, tick
- ).then((states: IRackState[]) => {
- tickState.rackStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getRoomStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.roomCache, tick
- ).then((states: IRoomState[]) => {
- tickState.roomStates = states;
- })
- );
-
- promises.push(
- this.simulationController.mapController.api.getTaskStates(
- this.simulationController.mapView.simulation.id, this.simulationController.currentExperiment.id,
- this.taskCache, tick
- ).then((states: ITaskState[]) => {
- tickState.taskStates = states;
- })
- );
-
- return Promise.all(promises).then(() => {
- return tickState;
- });
- }
-}
diff --git a/src/scripts/controllers/simulation/taskview.ts b/src/scripts/controllers/simulation/taskview.ts
deleted file mode 100644
index d989e103..00000000
--- a/src/scripts/controllers/simulation/taskview.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import * as $ from "jquery";
-import {SimulationController} from "../simulationcontroller";
-import {Util} from "../../util";
-
-
-export class TaskViewController {
- private simulationController: SimulationController;
-
-
- constructor(simulationController: SimulationController) {
- this.simulationController = simulationController;
- }
-
- /**
- * Populates and displays the list of tasks with their current state.
- */
- public update() {
- const container = $(".task-list");
- container.children().remove(".task-element");
-
- this.simulationController.stateCache.stateList[this.simulationController.currentTick].taskStates
- .forEach((taskState: ITaskState) => {
- const html = this.generateTaskElementHTML(taskState);
- container.append(html);
- });
- }
-
- private generateTaskElementHTML(taskState: ITaskState) {
- let iconType, timeInfo;
-
- if (taskState.task.startTick > this.simulationController.currentTick) {
- iconType = "glyphicon-time";
- timeInfo = "Not started yet";
- } else if (taskState.task.startTick <= this.simulationController.currentTick && taskState.flopsLeft > 0) {
- iconType = "glyphicon-refresh";
- timeInfo = "Started at " + Util.convertSecondsToFormattedTime(taskState.task.startTick);
- } else if (taskState.flopsLeft === 0) {
- iconType = "glyphicon-ok";
- timeInfo = "Started at " + Util.convertSecondsToFormattedTime(taskState.task.startTick);
- }
-
- // Calculate progression ratio
- const progress = 1 - (taskState.flopsLeft / taskState.task.totalFlopCount);
-
- // Generate completion text
- const flopsCompleted = taskState.task.totalFlopCount - taskState.flopsLeft;
- const completionInfo = "Completed: " + flopsCompleted + " / " + taskState.task.totalFlopCount + " FLOPS";
-
- return '<div class="task-element">' +
- ' <div class="task-icon glyphicon ' + iconType + '"></div>' +
- ' <div class="task-info">' +
- ' <div class="task-time">' + timeInfo +
- ' </div>' +
- ' <div class="progress">' +
- ' <div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="' +
- progress * 100 + '%"' +
- ' aria-valuemin="0" aria-valuemax="100" style="width: ' + progress * 100 + '%">' +
- ' </div>' +
- ' </div>' +
- ' <div class="task-flops">' + completionInfo + '</div>' +
- ' </div>' +
- '</div>';
- }
-}
diff --git a/src/scripts/controllers/simulation/timeline.ts b/src/scripts/controllers/simulation/timeline.ts
deleted file mode 100644
index ec3d8cb4..00000000
--- a/src/scripts/controllers/simulation/timeline.ts
+++ /dev/null
@@ -1,161 +0,0 @@
-import {SimulationController} from "../simulationcontroller";
-import {Util} from "../../util";
-import * as $ from "jquery";
-
-
-export class TimelineController {
- private simulationController: SimulationController;
- private startLabel: JQuery;
- private endLabel: JQuery;
- private playButton: JQuery;
- private loadingIcon: JQuery;
- private cacheSection: JQuery;
- private timeMarker: JQuery;
- private timeline: JQuery;
- private timeUnitFraction: number;
- private timeMarkerWidth: number;
- private timelineWidth: number;
-
-
- constructor(simulationController: SimulationController) {
- this.simulationController = simulationController;
- this.startLabel = $(".timeline-container .labels .start-time-label");
- this.endLabel = $(".timeline-container .labels .end-time-label");
- this.playButton = $(".timeline-container .play-btn");
- this.loadingIcon = this.playButton.find("img");
- this.cacheSection = $(".timeline-container .timeline .cache-section");
- this.timeMarker = $(".timeline-container .timeline .time-marker");
- this.timeline = $(".timeline-container .timeline");
- this.timeMarkerWidth = this.timeMarker.width();
- this.timelineWidth = this.timeline.width();
- }
-
- public togglePlayback(): void {
- if (this.simulationController.stateCache.cacheBlock) {
- this.simulationController.playing = false;
- return;
- }
- this.simulationController.playing = !this.simulationController.playing;
- this.setButtonIcon();
- }
-
- public setupListeners(): void {
- this.playButton.on("click", () => {
- this.togglePlayback();
- });
-
- $(".timeline-container .timeline").on("click", (event: JQueryEventObject) => {
- const parentOffset = $(event.target).closest(".timeline").offset();
- const clickX = event.pageX - parentOffset.left;
-
- let newTick = Math.round(clickX / (this.timelineWidth * this.timeUnitFraction));
-
- if (newTick > this.simulationController.stateCache.lastCachedTick) {
- newTick = this.simulationController.stateCache.lastCachedTick;
- }
- this.simulationController.currentTick = newTick;
- this.simulationController.checkCurrentSimulationSection();
- this.simulationController.update();
- });
- }
-
- public setButtonIcon(): void {
- if (this.simulationController.playing && !this.playButton.hasClass("glyphicon-pause")) {
- this.playButton.removeClass("glyphicon-play").addClass("glyphicon-pause");
- } else if (!this.simulationController.playing && !this.playButton.hasClass("glyphicon-play")) {
- this.playButton.removeClass("glyphicon-pause").addClass("glyphicon-play");
- }
- }
-
- public update(): void {
- this.timeUnitFraction = 1 / (this.simulationController.lastSimulatedTick + 1);
- this.timelineWidth = $(".timeline-container .timeline").width();
-
- this.updateTimeLabels();
-
- this.cacheSection.css("width", this.calculateTickPosition(this.simulationController.stateCache.lastCachedTick));
- this.timeMarker.css("left", this.calculateTickPosition(this.simulationController.currentTick));
-
- this.updateTaskIndicators();
- this.updateSectionMarkers();
-
- if (this.simulationController.stateCache.cacheBlock) {
- this.playButton.removeClass("glyphicon-pause").removeClass("glyphicon-play");
- this.loadingIcon.show();
- } else {
- this.loadingIcon.hide();
- this.setButtonIcon();
- }
- }
-
- private updateTimeLabels(): void {
- this.startLabel.text(Util.convertSecondsToFormattedTime(this.simulationController.currentTick));
- this.endLabel.text(Util.convertSecondsToFormattedTime(this.simulationController.lastSimulatedTick));
- }
-
- private updateSectionMarkers(): void {
- $(".section-marker").remove();
-
- this.simulationController.sections.forEach((simulationSection: ISection) => {
- if (simulationSection.startTick === 0) {
- return;
- }
-
- this.timeline.append(
- $('<div class="section-marker">')
- .css("left", this.calculateTickPosition(simulationSection.startTick))
- );
- });
- }
-
- private updateTaskIndicators(): void {
- $(".task-indicator").remove();
-
- const tickStateTypes = {
- "queueEntryTick": "task-queued",
- "startTick": "task-started",
- "finishedTick": "task-finished"
- };
-
- if (this.simulationController.stateCache.lastCachedTick === -1) {
- return;
- }
-
- const indicatorCountList = new Array(this.simulationController.stateCache.lastCachedTick);
- let indicator;
- this.simulationController.currentExperiment.trace.tasks.forEach((task: ITask) => {
- for (let tickStateType in tickStateTypes) {
- if (!tickStateTypes.hasOwnProperty(tickStateType)) {
- continue;
- }
-
- if (task[tickStateType] !== undefined &&
- task[tickStateType] <= this.simulationController.stateCache.lastCachedTick) {
-
- let bottomOffset;
- if (indicatorCountList[task[tickStateType]] === undefined) {
- indicatorCountList[task[tickStateType]] = 1;
- bottomOffset = 0;
- } else {
- bottomOffset = indicatorCountList[task[tickStateType]] * 10;
- indicatorCountList[task[tickStateType]]++;
- }
- indicator = $('<div class="task-indicator ' + tickStateTypes[tickStateType] + '">')
- .css("left", this.calculateTickPosition(task[tickStateType]))
- .css("bottom", bottomOffset);
- this.timeline.append(indicator);
- }
- }
- });
- }
-
- private calculateTickPosition(tick: number): string {
- let correction = 0;
- if (this.timeUnitFraction * this.timelineWidth > this.timeMarkerWidth) {
- correction = (this.timeUnitFraction * this.timelineWidth - this.timeMarkerWidth) *
- ((tick - 1) / this.simulationController.lastSimulatedTick);
- }
-
- return (100 * (this.timeUnitFraction * (tick - 1) + correction / this.timelineWidth)) + "%";
- }
-}
diff --git a/src/scripts/controllers/simulationcontroller.ts b/src/scripts/controllers/simulationcontroller.ts
deleted file mode 100644
index 1185087d..00000000
--- a/src/scripts/controllers/simulationcontroller.ts
+++ /dev/null
@@ -1,586 +0,0 @@
-///<reference path="../../../typings/index.d.ts" />
-///<reference path="mapcontroller.ts" />
-import * as $ from "jquery";
-import {MapView} from "../views/mapview";
-import {AppMode, InteractionLevel, MapController} from "./mapcontroller";
-import {Util} from "../util";
-import {StateCache} from "./simulation/statecache";
-import {ChartController} from "./simulation/chart";
-import {TaskViewController} from "./simulation/taskview";
-import {TimelineController} from "./simulation/timeline";
-
-
-export enum ColorRepresentation {
- LOAD,
- TEMPERATURE,
- MEMORY
-}
-
-
-export class SimulationController {
- public mapView: MapView;
- public mapController: MapController;
-
- public playing: boolean;
- public currentTick: number;
- public stateCache: StateCache;
- public lastSimulatedTick: number;
- public simulation: ISimulation;
- public experiments: IExperiment[];
- public currentExperiment: IExperiment;
- public currentPath: IPath;
- public sections: ISection[];
- public currentSection: ISection;
- public experimentSelectionMode: boolean;
- public traces: ITrace[];
- public schedulers: IScheduler[];
- public sectionIndex: number;
- public chartController: ChartController;
- public timelineController: TimelineController;
-
- public colorRepresentation: ColorRepresentation;
- public rackToRoomMap: {[key: number]: number;};
-
- private taskViewController: TaskViewController;
- private tickerId: any;
-
-
- public static showOrHideSimComponents(visibility: boolean): void {
- if (visibility) {
- $("#statistics-menu").removeClass("hidden");
- $("#experiment-menu").removeClass("hidden");
- $("#tasks-menu").removeClass("hidden");
- $(".timeline-container").removeClass("hidden");
- } else {
- $("#statistics-menu").addClass("hidden");
- $("#experiment-menu").addClass("hidden");
- $("#tasks-menu").addClass("hidden");
- $(".timeline-container").addClass("hidden");
- }
- }
-
- constructor(mapController: MapController) {
- this.mapController = mapController;
- this.mapView = this.mapController.mapView;
- this.simulation = this.mapController.mapView.simulation;
- this.experiments = this.simulation.experiments;
- this.taskViewController = new TaskViewController(this);
- this.timelineController = new TimelineController(this);
- this.chartController = new ChartController(this);
-
- this.timelineController.setupListeners();
- this.experimentSelectionMode = true;
- this.sectionIndex = 0;
-
- this.currentTick = 1;
- this.playing = false;
- this.stateCache = new StateCache(this);
- this.colorRepresentation = ColorRepresentation.LOAD;
-
- this.traces = [];
- this.schedulers = [];
-
- this.mapController.api.getAllTraces().then((data) => {
- this.traces = data;
- });
-
- this.mapController.api.getAllSchedulers().then((data) => {
- this.schedulers = data;
- });
- }
-
- public enterMode() {
- this.experimentSelectionMode = true;
-
- if (this.mapController.interactionLevel === InteractionLevel.BUILDING) {
- this.mapView.roomLayer.coloringMode = true;
- this.mapView.dcObjectLayer.coloringMode = false;
- } else if (this.mapController.interactionLevel === InteractionLevel.ROOM ||
- this.mapController.interactionLevel === InteractionLevel.OBJECT) {
- this.mapView.roomLayer.coloringMode = false;
- this.mapView.dcObjectLayer.coloringMode = true;
- } else if (this.mapController.interactionLevel === InteractionLevel.NODE) {
- this.mapController.nodeModeController.goToObjectMode();
- }
-
- this.mapController.appMode = AppMode.SIMULATION;
- this.mapView.dcObjectLayer.detailedMode = false;
- this.mapView.gridLayer.setVisibility(false);
- this.mapView.updateScene = true;
-
- this.mapController.setAllMenuModes();
- SimulationController.showOrHideSimComponents(true);
- $(".mode-switch").attr("data-selected", "simulation");
- $("#save-version-btn").hide();
- $(".color-indicator").removeClass("hidden");
-
- $("#change-experiment-btn").click(() => {
- this.playing = false;
- this.stateCache.stopCaching();
- this.timelineController.update();
- this.showExperimentsDialog();
- });
-
- this.setupColorMenu();
- this.showExperimentsDialog();
- }
-
- private launchSimulation(): void {
- this.onSimulationSectionChange();
-
- this.chartController.setup();
-
- this.stateCache.startCaching();
-
- this.tickerId = setInterval(() => {
- this.simulationTick();
- }, 1000);
- }
-
- private onSimulationSectionChange(): void {
- this.currentSection = this.currentPath.sections[this.sectionIndex];
- this.mapView.currentDatacenter = this.currentSection.datacenter;
-
- // Generate a map of all rack IDs in relation to their room IDs for use in room stats
- this.rackToRoomMap = {};
- this.currentSection.datacenter.rooms.forEach((room: IRoom) => {
- room.tiles.forEach((tile: ITile) => {
- if (tile.object !== undefined && tile.objectType === "RACK") {
- this.rackToRoomMap[tile.objectId] = room.id;
- }
- });
- });
-
- if (this.mapController.interactionLevel === InteractionLevel.NODE) {
- this.mapController.nodeModeController.goToObjectMode();
- }
- if (this.mapController.interactionLevel === InteractionLevel.OBJECT) {
- this.mapController.objectModeController.goToRoomMode();
- }
- if (this.mapController.interactionLevel === InteractionLevel.ROOM) {
- this.mapController.roomModeController.goToBuildingMode();
- }
-
- this.mapView.redrawMap();
-
- this.mapView.zoomOutOnDC();
- }
-
- public exitMode() {
- this.closeExperimentsDialog();
-
- this.mapController.appMode = AppMode.CONSTRUCTION;
- this.mapView.dcObjectLayer.detailedMode = true;
- this.mapView.gridLayer.setVisibility(true);
- this.mapView.redrawMap();
-
- this.stateCache.stopCaching();
- this.playing = false;
-
- this.mapController.setAllMenuModes();
- SimulationController.showOrHideSimComponents(false);
-
- this.setColors();
- $(".color-indicator").addClass("hidden")["popover"]("hide").off();
- $(".mode-switch").attr("data-selected", "construction");
- $("#save-version-btn").show();
-
- clearInterval(this.tickerId);
- }
-
- public update() {
- if (this.stateCache.cacheBlock) {
- return;
- }
-
- this.setColors();
- this.updateBuildingStats();
- this.updateRoomStats();
- this.chartController.update();
- this.taskViewController.update();
- }
-
- public simulationTick(): void {
- this.timelineController.update();
-
- if (this.currentTick > this.lastSimulatedTick) {
- this.currentTick = this.lastSimulatedTick;
- this.playing = false;
- this.timelineController.setButtonIcon();
- }
-
- if (this.playing) {
- this.checkCurrentSimulationSection();
- this.update();
-
- if (!this.stateCache.cacheBlock) {
- this.currentTick++;
- }
- }
- }
-
- public checkCurrentSimulationSection(): void {
- for (let i = this.sections.length - 1; i >= 0; i--) {
- if (this.currentTick >= this.sections[i].startTick) {
- if (this.sectionIndex !== i) {
- this.sectionIndex = i;
- this.onSimulationSectionChange();
- }
- break;
- }
- }
- }
-
- public transitionFromBuildingToRoom(): void {
- this.mapView.roomLayer.coloringMode = false;
- this.mapView.dcObjectLayer.coloringMode = true;
-
- this.setColors();
- this.updateRoomStats();
- this.chartController.update();
- }
-
- public transitionFromRoomToBuilding(): void {
- this.mapView.roomLayer.coloringMode = true;
- this.mapView.dcObjectLayer.coloringMode = false;
-
- this.setColors();
- this.updateBuildingStats();
- this.chartController.update();
- }
-
- public transitionFromRoomToRack(): void {
- this.setColors();
- $("#statistics-menu").addClass("hidden");
- this.chartController.update();
- }
-
- public transitionFromRackToRoom(): void {
- this.setColors();
- $("#statistics-menu").removeClass("hidden");
- }
-
- public transitionFromRackToNode(): void {
- this.chartController.update();
- }
-
- public transitionFromNodeToRack(): void {
- }
-
- private showExperimentsDialog(): void {
- $(".experiment-name-alert").hide();
-
- this.populateExperimentsList();
- this.populateDropdowns();
-
- $(".experiment-row").click((event: JQueryEventObject) => {
- if ($(event.target).hasClass("remove-experiment")) {
- return;
- }
-
- const row = $(event.target).closest(".experiment-row");
- this.prepareAndLaunchExperiment(this.experiments[row.index()]);
- });
-
- $(".experiment-list .list-body").on("click", ".remove-experiment", (event: JQueryEventObject) => {
- event.stopPropagation();
- const affectedRow = $(event.target).closest(".experiment-row");
- const index = affectedRow.index();
- const affectedExperiment = this.experiments[index];
-
- MapController.showConfirmDeleteDialog("experiment", () => {
- this.mapController.api.deleteExperiment(affectedExperiment.simulationId, affectedExperiment.id)
- .then(() => {
- this.experiments.splice(index, 1);
- this.populateExperimentsList();
- });
- });
- });
-
- let newExperimentBtn = $("#new-experiment-btn");
- // Remove previously added event handlers
- newExperimentBtn.off();
-
- newExperimentBtn.click(() => {
- const nameInput = $("#new-experiment-name-input");
- if (nameInput.val() === "") {
- $(".experiment-name-alert").show();
- return;
- } else {
- $(".experiment-name-alert").hide();
- }
-
- const newExperiment: IExperiment = {
- id: -1,
- name: nameInput.text(),
- pathId: parseInt($("#new-experiment-path-select").val()),
- schedulerName: $("#new-experiment-scheduler-select").val(),
- traceId: parseInt($("#new-experiment-trace-select").val()),
- simulationId: this.simulation.id
- };
-
- this.mapController.api.addExperimentToSimulation(this.simulation.id, newExperiment)
- .then((data: IExperiment) => {
- this.simulation.experiments.push(data);
- this.prepareAndLaunchExperiment(data);
- });
- });
-
- $(".window-close").click(() => {
- this.exitMode();
- });
-
- $(".window-overlay").fadeIn(200);
- }
-
- private prepareAndLaunchExperiment(experiment: IExperiment): void {
- this.prepareSimulationData(experiment);
- this.launchSimulation();
- this.closeExperimentsDialog();
- }
-
- private prepareSimulationData(experiment: IExperiment): void {
- this.currentExperiment = experiment;
- this.currentPath = this.getPathById(this.currentExperiment.pathId);
- this.sections = this.currentPath.sections;
- this.sectionIndex = 0;
- this.currentTick = 1;
- this.playing = false;
- this.stateCache = new StateCache(this);
- this.colorRepresentation = ColorRepresentation.LOAD;
-
- this.sections.sort((a: ISection, b: ISection) => {
- return a.startTick - b.startTick;
- });
-
- $("#experiment-menu-name").text(experiment.name);
- $("#experiment-menu-path").text(SimulationController.getPathName(this.currentPath));
- $("#experiment-menu-scheduler").text(experiment.schedulerName);
- $("#experiment-menu-trace").text(experiment.trace.name);
- }
-
- private closeExperimentsDialog(): void {
- $(".window-overlay").fadeOut(200);
- $(".window-overlay input").val("");
- }
-
- private populateDropdowns(): void {
- const pathDropdown = $("#new-experiment-path-select");
- const traceDropdown = $("#new-experiment-trace-select");
- const schedulerDropdown = $("#new-experiment-scheduler-select");
-
- pathDropdown.empty();
- for (let i = 0; i < this.simulation.paths.length; i++) {
- pathDropdown.append(
- $("<option>").text(SimulationController.getPathName(this.simulation.paths[i]))
- .val(this.simulation.paths[i].id)
- );
- }
-
- traceDropdown.empty();
- for (let i = 0; i < this.traces.length; i++) {
- traceDropdown.append(
- $("<option>").text(this.traces[i].name)
- .val(this.traces[i].id)
- );
- }
-
- schedulerDropdown.empty();
- for (let i = 0; i < this.schedulers.length; i++) {
- schedulerDropdown.append(
- $("<option>").text(this.schedulers[i].name)
- .val(this.schedulers[i].name)
- );
- }
- }
-
- /**
- * Populates the list of experiments.
- */
- private populateExperimentsList(): void {
- const table = $(".experiment-list .list-body");
- table.empty();
-
- console.log("EXPERIMENT", this.experiments);
- console.log("SIMULATION", this.simulation);
-
- if (this.experiments.length === 0) {
- $(".experiment-list").hide();
- $(".no-experiments-alert").show();
- } else {
- $(".no-experiments-alert").hide();
- this.experiments.forEach((experiment: IExperiment) => {
- table.append(
- '<div class="experiment-row">' +
- ' <div>' + experiment.name + '</div>' +
- ' <div>' + this.getPathNameById(experiment.pathId) + '</div>' +
- ' <div>' + experiment.trace.name + '</div>' +
- ' <div>' + experiment.schedulerName + '</div>' +
- ' <div class="remove-experiment glyphicon glyphicon-remove"></div>' +
- '</div>'
- );
- });
- }
- }
-
- private getPathNameById(id: number): string {
- for (let i = 0; i < this.simulation.paths.length; i++) {
- if (id === this.simulation.paths[i].id) {
- return SimulationController.getPathName(this.simulation.paths[i]);
- }
- }
- }
-
- private getPathById(id: number): IPath {
- for (let i = 0; i < this.simulation.paths.length; i++) {
- if (id === this.simulation.paths[i].id) {
- return this.simulation.paths[i];
- }
- }
- }
-
- private static getPathName(path: IPath): string {
- if (path.name === null) {
- return "Path " + path.id;
- } else {
- return path.name;
- }
- }
-
- private setColors() {
- if (this.mapController.appMode === AppMode.SIMULATION) {
- if (this.mapController.interactionLevel === InteractionLevel.BUILDING) {
- this.mapView.roomLayer.intensityLevels = {};
-
- this.stateCache.stateList[this.currentTick].roomStates.forEach((roomState: IRoomState) => {
- if (this.colorRepresentation === ColorRepresentation.LOAD) {
- this.mapView.roomLayer.intensityLevels[roomState.roomId] =
- Util.determineLoadIntensityLevel(roomState.loadFraction);
- }
- });
-
- this.mapView.roomLayer.draw();
- this.mapView.dcObjectLayer.draw();
- } else if (this.mapController.interactionLevel === InteractionLevel.ROOM ||
- this.mapController.interactionLevel === InteractionLevel.OBJECT) {
- this.mapView.dcObjectLayer.intensityLevels = {};
-
- this.stateCache.stateList[this.currentTick].rackStates.forEach((rackState: IRackState) => {
- if (this.colorRepresentation === ColorRepresentation.LOAD) {
- this.mapView.dcObjectLayer.intensityLevels[rackState.rackId] =
- Util.determineLoadIntensityLevel(rackState.loadFraction);
- }
- });
-
- this.mapView.roomLayer.draw();
- this.mapView.dcObjectLayer.draw();
- }
-
- if (this.mapController.interactionLevel === InteractionLevel.OBJECT ||
- this.mapController.interactionLevel === InteractionLevel.NODE) {
- this.stateCache.stateList[this.currentTick].machineStates.forEach((machineState: IMachineState) => {
- let element = $('.node-element[data-id="' + machineState.machineId + '"] .node-element-content');
- element.css("background-color", Util.convertIntensityToColor(
- Util.determineLoadIntensityLevel(machineState.loadFraction)
- ));
-
- // Color all transparent icon overlays, as well
- element = $('.node-element[data-id="' + machineState.machineId + '"] .icon-overlay');
- element.css("background-color", Util.convertIntensityToColor(
- Util.determineLoadIntensityLevel(machineState.loadFraction)
- ));
- });
- }
- } else {
- this.mapView.roomLayer.coloringMode = false;
- this.mapView.dcObjectLayer.coloringMode = false;
-
- this.mapView.roomLayer.draw();
- this.mapView.dcObjectLayer.draw();
- }
- }
-
- /**
- * Populates the building simulation menu with dynamic statistics concerning the state of all rooms in the building.
- */
- private updateBuildingStats(): void {
- if (this.mapController.interactionLevel !== InteractionLevel.BUILDING) {
- return;
- }
-
- const container = $(".building-stats-list");
-
- container.children().remove("div");
-
- this.stateCache.stateList[this.currentTick].roomStates.forEach((roomState: IRoomState) => {
- if (this.colorRepresentation === ColorRepresentation.LOAD && roomState.room !== undefined) {
- const html = '<div>' +
- ' <h4>' + roomState.room.name + '</h4>' +
- ' <p>Load: ' + Math.round(roomState.loadFraction * 100) + '%</p>' +
- '</div>';
- container.append(html);
- }
- });
-
- }
-
- /**
- * Populates the room simulation menu with dynamic statistics concerning the state of all racks in the room.
- */
- private updateRoomStats(): void {
- if (this.mapController.interactionLevel !== InteractionLevel.ROOM) {
- return;
- }
-
- $("#room-name-field").text(this.mapController.roomModeController.currentRoom.name);
- $("#room-type-field").text(this.mapController.roomModeController.currentRoom.roomType);
-
- const container = $(".room-stats-list");
-
- container.children().remove("div");
-
- this.stateCache.stateList[this.currentTick].rackStates.forEach((rackState: IRackState) => {
- if (this.rackToRoomMap[rackState.rackId] !== this.mapController.roomModeController.currentRoom.id) {
- return;
- }
- if (this.colorRepresentation === ColorRepresentation.LOAD) {
- const html = '<div>' +
- ' <h4>' + rackState.rack.name + '</h4>' +
- ' <p>Load: ' + Math.round(rackState.loadFraction * 100) + '%</p>' +
- '</div>';
- container.append(html);
- }
- });
- }
-
- private setupColorMenu(): void {
- const html =
- '<select class="form-control" title="Color Representation" id="color-representation-select">' +
- ' <option value="1" selected>Load</option>' +
- ' <option value="2">Power use</option>' +
- '</select>';
-
- const indicator = $(".color-indicator");
- indicator["popover"]({
- animation: true,
- content: html,
- html: true,
- placement: "top",
- title: "Colors represent:",
- trigger: "manual"
- });
- indicator.click(() => {
- //noinspection JSJQueryEfficiency // suppressed for dynamic element insertion
- if ($("#color-representation-select").length) {
- indicator["popover"]("hide");
- } else {
- indicator["popover"]("show");
-
- const selectElement = $("#color-representation-select");
- selectElement.change(() => {
- console.log(selectElement.val());
- });
- }
- });
- }
-}
diff --git a/src/scripts/definitions.ts b/src/scripts/definitions.ts
deleted file mode 100644
index e187af09..00000000
--- a/src/scripts/definitions.ts
+++ /dev/null
@@ -1,318 +0,0 @@
-/**
- * JSON Specification of the data model.
- *
- * Represents the data model after populating it (based on the DB ideas retrieved from the backend). Unpopulated
- * objects end with 'Stub'.
- */
-
-// Webpack require declaration
-//declare var require: {
-// <T>(path: string): T;
- // (paths: string[], callback: (...modules: any[]) => void): void;
- //ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void) => void;
-//};
-
-// Meta-constructs
-interface IDateTime {
- year: number;
- month: number;
- day: number;
- hour: number;
- minute: number;
- second: number;
-}
-
-interface IGridPosition {
- x: number;
- y: number;
-}
-
-interface IBounds {
- min: number[];
- center: number[];
- max: number[];
-}
-
-interface IRoomNamePos {
- topLeft: IGridPosition;
- length: number;
-}
-
-interface IRoomWall {
- startPos: number[];
- horizontal: boolean;
- length: number;
-}
-
-interface TilePositionObject {
- position: IGridPosition;
- tileObject: createjs.Shape;
-}
-
-type IRoomTypeMap = { [key: string]: string[]; };
-
-interface ITickState {
- tick: number;
- roomStates: IRoomState[];
- rackStates: IRackState[];
- machineStates: IMachineState[];
- taskStates: ITaskState[];
-}
-
-// Communication
-interface IRequest {
- id?: number;
- path: string;
- method: string;
- parameters: {
- body: any;
- path: any;
- query: any;
- };
- token?: string;
-}
-
-interface IResponse {
- id?: number;
- status: {
- code: number;
- description?: string;
- };
- content: any;
-}
-
-// Simulation
-interface ISimulation {
- id: number;
- name: string;
- paths?: IPath[];
- experiments?: IExperiment[];
- datetimeCreated: string;
- datetimeCreatedParsed?: IDateTime;
- datetimeLastEdited: string;
- datetimeLastEditedParsed?: IDateTime;
-}
-
-interface ISection {
- id: number;
- startTick: number;
- simulationId: number;
- datacenterId: number;
- datacenter?: IDatacenter;
-}
-
-interface IPath {
- id: number;
- simulationId: number;
- sections?: ISection[];
- name: string;
- datetimeCreated: string;
-}
-
-interface ITrace {
- id: number;
- name: string;
- tasks?: ITask[];
-}
-
-interface IScheduler {
- name: string;
-}
-
-interface ITask {
- id: number;
- traceId: number;
- queueEntryTick: number;
- startTick?: number;
- finishedTick?: number;
- totalFlopCount: number;
-}
-
-interface IExperiment {
- id: number;
- simulationId: number;
- pathId: number;
- traceId: number;
- trace?: ITrace;
- schedulerName: string;
- name: string;
-}
-
-// Authorization
-interface IAuthorization {
- userId: number;
- user?: IUser;
- simulationId: number;
- simulation?: ISimulation;
- authorizationLevel: string;
-}
-
-interface IUser {
- id: number;
- googleId: number;
- email: string;
- givenName: string;
- familyName: string;
-}
-
-// DC Layout
-interface IDatacenter {
- id: number;
- rooms?: IRoom[];
-}
-
-interface IRoom {
- id: number;
- datacenterId: number;
- name: string;
- roomType: string;
- tiles?: ITile[];
-}
-
-interface ITile {
- id: number;
- roomId: number;
- objectId?: number;
- objectType?: string;
- object?: IDCObject;
- position: IGridPosition;
-}
-
-// State
-interface IMachineState {
- id: number;
- machineId: number;
- machine?: IMachine;
- experimentId: number;
- tick: number;
- temperatureC: number;
- inUseMemoryMb: number;
- loadFraction: number;
-}
-
-interface IRackState {
- id: number;
- rackId: number;
- rack?: IRack;
- experimentId: number;
- tick: number;
- temperatureC: number;
- inUseMemoryMb: number;
- loadFraction: number;
-}
-
-interface IRoomState {
- id: number;
- roomId: number;
- room?: IRoom;
- experimentId: number;
- tick: number;
- temperatureC: number;
- inUseMemoryMb: number;
- loadFraction: number;
-}
-
-interface ITaskState {
- id: number;
- taskId: number;
- task?: ITask;
- experimentId: number;
- tick: number;
- flopsLeft: number;
-}
-
-// Generalization of a datacenter object
-type IDCObject = IRack | ICoolingItem | IPSU;
-
-interface IRack {
- id: number;
- objectType?: string;
- name: string;
- capacity: number;
- powerCapacityW: number;
- machines?: IMachine[];
-}
-
-interface ICoolingItem {
- id: number;
- objectType?: string;
- energyConsumptionW: number;
- type: string;
- failureModelId: number;
- failureModel?: IFailureModel;
-}
-
-interface IPSU {
- id: number;
- objectType?: string;
- energyKwh: number;
- type: string;
- failureModelId: number;
- failureModel?: IFailureModel;
-}
-
-// Machine
-interface IMachine {
- id: number;
- rackId: number;
- position: number;
- tags: string[];
- cpuIds: number[];
- cpus?: ICPU[];
- gpuIds: number[];
- gpus?: IGPU[];
- memoryIds: number[];
- memories?: IMemory[];
- storageIds: number[];
- storages?: IPermanentStorage[];
-}
-
-interface IProcessingUnit {
- id: number;
- manufacturer: string;
- family: string;
- generation: string;
- model: string;
- clockRateMhz: number;
- numberOfCores: number;
- energyConsumptionW: number;
- failureModelId: number;
- failureModel?: IFailureModel;
-}
-
-interface ICPU extends IProcessingUnit {
-
-}
-
-interface IGPU extends IProcessingUnit {
-
-}
-
-interface IStorageUnit {
- id: number;
- manufacturer: string;
- family: string;
- generation: string;
- model: string;
- speedMbPerS: number;
- sizeMb: number;
- energyConsumptionW: number;
- failureModelId: number;
- failureModel?: IFailureModel;
-}
-
-interface IMemory extends IStorageUnit {
-
-}
-
-interface IPermanentStorage extends IStorageUnit {
-
-}
-
-type INodeUnit = IProcessingUnit & IStorageUnit;
-
-interface IFailureModel {
- id: number;
- name: string;
- rate: number;
-}
diff --git a/src/scripts/error404.entry.ts b/src/scripts/error404.entry.ts
deleted file mode 100644
index 477a46c0..00000000
--- a/src/scripts/error404.entry.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-///<reference path="../../typings/globals/jquery/index.d.ts" />
-import * as $ from "jquery";
-
-
-$(document).ready(() => {
- const text =
- " oo oooo oo <br>" +
- " oo oo oo oo <br>" +
- " oo oo oo oo <br>" +
- " oooooo oo oo oooooo <br>" +
- " oo oo oo oo <br>" +
- " oo oooo oo <br>";
- const charList = text.split('');
-
- const binaryString = "01001111011100000110010101101110010001000100001100100001";
-
- let binaryIndex = 0;
- for (let i = 0; i < charList.length; i++) {
- if (charList[i] === "o") {
- charList[i] = binaryString[binaryIndex];
- binaryIndex++;
- }
- }
-
- $(".code-block").html(charList.join(""));
-});
diff --git a/src/scripts/main.entry.ts b/src/scripts/main.entry.ts
deleted file mode 100644
index 84726ed4..00000000
--- a/src/scripts/main.entry.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-///<reference path="../../typings/index.d.ts" />
-///<reference path="./views/mapview.ts" />
-import * as $ from "jquery";
-import {MapView} from "./views/mapview";
-import {APIController} from "./controllers/connection/api";
-window["$"] = $;
-require("jquery-mousewheel");
-window["jQuery"] = $;
-
-require("./user-authentication");
-
-
-$(document).ready(function () {
- new Display(); //tslint:disable-line:no-unused-expression
-});
-
-
-/**
- * Class responsible for launching the main view.
- */
-class Display {
- private stage: createjs.Stage;
- private view: MapView;
-
-
- /**
- * Adjusts the canvas size to fit the window's initial dimensions (full expansion).
- */
- private static fitCanvasSize() {
- const canvas = $("#main-canvas");
- const parent = canvas.parent();
- parent.height($(window).height() - 50);
- canvas.attr("width", parent.width());
- canvas.attr("height", parent.height());
- }
-
- constructor() {
- // Check whether project has been selected before going to the app page
- if (localStorage.getItem("simulationId") === null) {
- window.location.replace("projects");
- return;
- }
-
- Display.fitCanvasSize();
- this.stage = new createjs.Stage("main-canvas");
-
- new APIController((api: APIController) => {
- api.getSimulation(parseInt(localStorage.getItem("simulationId")))
- .then((simulationData: ISimulation) => {
- if (simulationData.name !== "") {
- document.title = simulationData.name + " | OpenDC";
- }
-
- api.getPathsBySimulation(simulationData.id)
- .then((pathData: IPath[]) => {
- simulationData.paths = pathData;
- }).then(() => {
- return api.getExperimentsBySimulation(simulationData.id);
- }).then((experimentData: IExperiment[]) => {
- $(".loading-overlay").hide();
-
- simulationData.experiments = experimentData;
- this.view = new MapView(simulationData, this.stage);
- });
- });
- });
-
- }
-}
diff --git a/src/scripts/profile.entry.ts b/src/scripts/profile.entry.ts
deleted file mode 100644
index 0cb77f50..00000000
--- a/src/scripts/profile.entry.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-///<reference path="../../typings/index.d.ts" />
-import * as $ from "jquery";
-import {APIController} from "./controllers/connection/api";
-import {removeUserInfo} from "./user-authentication";
-window["jQuery"] = $;
-
-
-$(document).ready(() => {
- const api = new APIController(() => {
- });
-
- $("#delete-account").on("click", () => {
- const modalDialog = <any>$("#confirm-delete-account");
-
- // Function called on delete confirmation
- const callback = () => {
- api.deleteUser(parseInt(localStorage.getItem("userId"))).then(() => {
- removeUserInfo();
- gapi.auth2.getAuthInstance().signOut().then(() => {
- window.location.href = "/";
- });
- }, (reason: any) => {
- modalDialog.find("button.confirm").off();
- modalDialog.modal("hide");
-
- const alert = $(".account-delete-alert");
- alert.find("code").text(reason.code + ": " + reason.description);
-
- alert.slideDown(200);
-
- setTimeout(() => {
- alert.slideUp(200);
- }, 5000);
- });
- };
-
- modalDialog.find("button.confirm").on("click", callback);
- modalDialog.modal("show");
- });
-});
diff --git a/src/scripts/projects.entry.ts b/src/scripts/projects.entry.ts
deleted file mode 100644
index daa0e2d6..00000000
--- a/src/scripts/projects.entry.ts
+++ /dev/null
@@ -1,651 +0,0 @@
-///<reference path="../../typings/globals/jquery/index.d.ts" />
-import * as $ from "jquery";
-import {APIController} from "./controllers/connection/api";
-import {Util} from "./util";
-window["jQuery"] = $;
-
-require("./user-authentication");
-
-
-$(document).ready(() => {
- let api;
- new APIController((apiInstance: APIController) => {
- api = apiInstance;
- api.getAuthorizationsByUser(parseInt(localStorage.getItem("userId"))).then((data: any) => {
- const projectsController = new ProjectsController(data, api);
- new WindowController(projectsController, api);
- });
- });
-});
-
-
-/**
- * Controller class responsible for rendering the authorization list views and handling interactions with them.
- */
-class ProjectsController {
- public static authIconMap = {
- "OWN": "glyphicon-home",
- "EDIT": "glyphicon-pencil",
- "VIEW": "glyphicon-eye-open"
- };
-
- public currentUserId: number;
- public authorizations: IAuthorization[];
- public authorizationsFiltered: IAuthorization[];
- public windowController: WindowController;
-
- private api: APIController;
-
-
- /**
- * 'Opens' a project, by putting the relevant simulation ID into local storage and referring to the app page.
- *
- * @param authorization The user's authorization belonging to the project to be opened
- */
- public static openProject(authorization: IAuthorization): void {
- localStorage.setItem("simulationId", authorization.simulationId.toString());
- localStorage.setItem("simulationAuthLevel", authorization.authorizationLevel);
- window.location.href = "app";
- }
-
- /**
- * Converts a list of authorizations into DOM objects, and adds them to the main list body of the page.
- *
- * @param list The list of authorizations to be displayed
- */
- public static populateList(list: IAuthorization[]): void {
- const body = $(".project-list .list-body");
- body.empty();
-
- list.forEach((element: IAuthorization) => {
- body.append(
- $('<div class="project-row">').append(
- $('<div>').text(element.simulation.name),
- $('<div>').text(Util.formatDateTime(element.simulation.datetimeLastEditedParsed)),
- $('<div>').append($('<span class="glyphicon">')
- .addClass(this.authIconMap[element.authorizationLevel]),
- Util.toSentenceCase(element.authorizationLevel)
- )
- ).attr("data-id", element.simulationId)
- );
- });
- };
-
- /**
- * Filters an authorization list based on what authorization level is required.
- *
- * Leaves the original list intact.
- *
- * @param list The authorization list to be filtered
- * @param ownedByUser Whether only authorizations should be included that are owned by the user, or whether only
- * authorizations should be included that the user has no ownership over
- * @returns {IAuthorization[]} A filtered list of authorizations
- */
- public static filterList(list: IAuthorization[], ownedByUser: boolean): IAuthorization[] {
- const resultList: IAuthorization[] = [];
-
- list.forEach((element: IAuthorization) => {
- if (element.authorizationLevel === "OWN") {
- if (ownedByUser) {
- resultList.push(element);
- }
- } else {
- if (!ownedByUser) {
- resultList.push(element);
- }
- }
- });
-
- return resultList;
- };
-
- /**
- * Activates a certain filter heading button, while deactivating the rest.
- *
- * @param target The event target to activate
- */
- private static activateFilterViewButton(target: JQuery): void {
- target.addClass("active");
- target.siblings().removeClass("active");
- };
-
- constructor(authorizations: IAuthorization[], api: APIController) {
- this.currentUserId = parseInt(localStorage.getItem("userId"));
- this.authorizations = authorizations;
- this.authorizationsFiltered = authorizations;
- this.api = api;
-
- this.updateNoProjectsAlert();
-
- this.handleFilterClick();
-
- // Show a project view upon clicking on a simulation row
- $("body").on("click", ".project-row", (event: JQueryEventObject) => {
- this.displayProjectView($(event.target));
- });
- }
-
- /**
- * Update the list of authorizations, by fetching them from the server and reloading the list.
- *
- * Goes to the 'All Projects' page after this refresh.
- */
- public updateAuthorizations(): void {
- this.api.getAuthorizationsByUser(this.currentUserId).then((data: any) => {
- this.authorizations = data;
- this.authorizationsFiltered = this.authorizations;
-
- this.updateNoProjectsAlert();
-
- this.goToAllProjects();
- });
- }
-
- /**
- * Show (or hide) the 'No projects here' alert in the list view, based on whether there are projects present.
- */
- private updateNoProjectsAlert(): void {
- if (this.authorizationsFiltered.length === 0) {
- $(".no-projects-alert").show();
- $(".project-list").hide();
- } else {
- $(".no-projects-alert").hide();
- $(".project-list").show();
- }
- }
-
- /**
- * Displays a project view with authorizations and entry buttons, inline within the table.
- *
- * @param target The element that was clicked on to launch this view
- */
- private displayProjectView(target: JQuery): void {
- const closestRow = target.closest(".project-row");
- const activeElement = $(".project-row.active");
-
- // Disable previously selected row elements and remove any project-views, to have only one view open at a time
- if (activeElement.length > 0) {
- const view = $(".project-view").first();
-
- view.slideUp(200, () => {
- activeElement.removeClass("active");
- view.remove();
- });
-
- if (closestRow.is(activeElement)) {
- return;
- }
- }
-
- const simulationId = parseInt(closestRow.attr("data-id"), 10);
-
- // Generate a list of participants of this project
- this.api.getAuthorizationsBySimulation(simulationId).then((data: any) => {
- const simAuthorizations = data;
- const participants = [];
-
- Util.sortAuthorizations(simAuthorizations);
-
- // For each participant of this simulation, include his/her name along with an icon of their authorization
- // level in the list
- simAuthorizations.forEach((authorization: IAuthorization) => {
- const authorizationString = ' (<span class="glyphicon ' +
- ProjectsController.authIconMap[authorization.authorizationLevel] + '"></span>)';
- if (authorization.userId === this.currentUserId) {
- participants.push(
- 'You' + authorizationString
- );
- } else {
- participants.push(
- authorization.user.givenName + ' ' + authorization.user.familyName + authorizationString
- );
- }
- });
-
- // Generate a project view component with participants and relevant actions
- const object = $('<div class="project-view">').append(
- $('<div class="participants">').append(
- $('<strong>').text("Participants"),
- $('<div>').html(participants.join(", "))
- ),
- $('<div class="access-buttons">').append(
- $('<div class="inline-btn edit">').text("Edit"),
- $('<div class="inline-btn open">').text("Open")
- )
- ).hide();
-
- closestRow.after(object);
-
- // Hide the 'edit' button for non-owners and -editors
- const currentAuth = this.authorizationsFiltered[closestRow.index(".project-row")];
- if (currentAuth.authorizationLevel !== "OWN") {
- $(".project-view .inline-btn.edit").hide();
- }
-
- object.find(".edit").click(() => {
- this.windowController.showEditProjectWindow(simAuthorizations);
- });
-
- object.find(".open").click(() => {
- ProjectsController.openProject(currentAuth);
- });
-
- closestRow.addClass("active");
- object.slideDown(200);
- });
- }
-
- /**
- * Controls the filtered authorization list, based on clicks from the side menu.
- */
- private handleFilterClick(): void {
- $(".all-projects").on("click", () => {
- this.goToAllProjects();
- });
-
- $(".my-projects").on("click", () => {
- this.goToMyProjects();
- });
-
- $(".shared-projects").on("click", () => {
- this.goToSharedProjects();
- });
-
- this.goToAllProjects();
- }
-
- /**
- * Show a list containing all projects (regardless of the authorization level the user has over them).
- */
- private goToAllProjects(): void {
- this.authorizationsFiltered = this.authorizations;
- ProjectsController.populateList(this.authorizations);
- this.updateNoProjectsAlert();
-
- ProjectsController.activateFilterViewButton($(".all-projects"));
- }
-
- /**
- * Show a list containing only projects that the user owns.
- */
- private goToMyProjects(): void {
- this.authorizationsFiltered = ProjectsController.filterList(this.authorizations, true);
- ProjectsController.populateList(this.authorizationsFiltered);
- this.updateNoProjectsAlert();
-
- ProjectsController.activateFilterViewButton($(".my-projects"));
- }
-
- /**
- * Show a list containing only projects that the user does not own (but can edit or view).
- */
- private goToSharedProjects(): void {
- this.authorizationsFiltered = ProjectsController.filterList(this.authorizations, false);
- ProjectsController.populateList(this.authorizationsFiltered);
- this.updateNoProjectsAlert();
-
- ProjectsController.activateFilterViewButton($(".shared-projects"));
- }
-}
-
-
-/**
- * Controller class responsible for rendering the project add/edit window and handle user interaction with it.
- */
-class WindowController {
- private projectsController: ProjectsController;
- private windowOverlay: JQuery;
- private window: JQuery;
- private table: JQuery;
- private closeCallback: () => any;
- private simAuthorizations: IAuthorization[];
- private simulationId: number;
- private editMode: boolean;
- private api: APIController;
-
-
- constructor(projectsController: ProjectsController, api: APIController) {
- this.projectsController = projectsController;
- this.windowOverlay = $(".window-overlay");
- this.window = $(".projects-window");
- this.table = $(".participants-table");
- this.projectsController.windowController = this;
- this.simAuthorizations = [];
- this.editMode = false;
- this.api = api;
-
- $(".window-footer .btn").hide();
-
- $(".participant-add-form").submit((event: JQueryEventObject) => {
- event.preventDefault();
- $(".participant-add-form .btn").trigger("click");
- });
-
- $(".project-name-form").submit((event: JQueryEventObject) => {
- event.preventDefault();
- $(".project-name-form .btn").trigger("click");
- });
-
- // Clean-up actions to occur after every window-close
- this.closeCallback = () => {
- this.table.empty();
- $(".project-name-form .btn").off();
- $(".participant-add-form .btn").off();
- $(".window-footer .btn").hide().off();
- $(".participant-email-alert").hide();
- $(".participant-level div").removeClass("active").off();
- this.table.off("click", ".participant-remove div");
-
- $(".project-name-form input").val("");
- $(".participant-add-form input").val("");
-
- if (this.editMode) {
- this.projectsController.updateAuthorizations();
- }
- };
-
- $(".new-project-btn").click(() => {
- this.showAddProjectWindow();
- });
-
- // Stop click events on the window from closing it indirectly
- this.window.click((event: JQueryEventObject) => {
- event.stopPropagation();
- });
-
- $(".window-close, .window-overlay").click(() => {
- this.closeWindow();
- });
- }
-
- /**
- * Displays a window for project edits (used for adding participants and changing the name).
- *
- * @param authorizations The authorizations of the simulation project to be edited.
- */
- public showEditProjectWindow(authorizations: IAuthorization[]): void {
- this.editMode = true;
- this.simAuthorizations = [];
- this.simulationId = authorizations[0].simulation.id;
-
- // Filter out the user's authorization from the authorization list (not to be displayed in the list)
- authorizations.forEach((authorization: IAuthorization) => {
- if (authorization.userId !== this.projectsController.currentUserId) {
- this.simAuthorizations.push(authorization);
- }
- });
-
- $(".window .window-heading").text("Edit project");
-
- $(".project-name-form input").val(authorizations[0].simulation.name);
-
- $(".project-name-form .btn").css("display", "inline-block").click(() => {
- const nameInput = $(".project-name-form input").text();
- if (nameInput !== "") {
- authorizations[0].simulation.name = nameInput;
- this.api.updateSimulation(authorizations[0].simulation);
- }
- });
-
- $(".project-open-btn").show().click(() => {
- ProjectsController.openProject({
- userId: this.projectsController.currentUserId,
- simulationId: this.simulationId,
- authorizationLevel: "OWN"
- });
- });
-
- $(".project-delete-btn").show().click(() => {
- this.api.deleteSimulation(authorizations[0].simulationId).then(() => {
- this.projectsController.updateAuthorizations();
- this.closeWindow();
- });
- });
-
- $(".participant-add-form .btn").click(() => {
- this.handleParticipantAdd((userId: number) => {
- this.api.addAuthorization({
- userId: userId,
- simulationId: authorizations[0].simulationId,
- authorizationLevel: "VIEW"
- });
- });
- });
-
- this.table.on("click", ".participant-level div", (event: JQueryEventObject) => {
- this.handleParticipantLevelChange(event, (authorization: IAuthorization) => {
- this.api.updateAuthorization(authorization);
- });
- });
-
- this.table.on("click", ".participant-remove div", (event: JQueryEventObject) => {
- this.handleParticipantDelete(event, (authorization) => {
- this.api.deleteAuthorization(authorization);
- });
- });
-
- this.populateParticipantList();
-
- this.windowOverlay.fadeIn(200);
- }
-
- /**
- * Shows a window to be used for creating a new project.
- */
- public showAddProjectWindow(): void {
- this.editMode = false;
- this.simAuthorizations = [];
-
- $(".project-name-form .btn").hide();
-
- $(".window .window-heading").text("Create a project");
-
- $(".project-create-open-btn").show().click(() => {
- if ($(".project-name-form input").val() === "") {
- this.showAlert(".project-name-alert");
- return;
- }
- this.createSimulation((simulationId: number) => {
- ProjectsController.openProject({
- userId: this.projectsController.currentUserId,
- simulationId,
- authorizationLevel: "OWN"
- });
- });
- });
-
- $(".project-create-btn").show().click(() => {
- if ($(".project-name-form input").val() === "") {
- this.showAlert(".project-name-alert");
- return;
- }
- this.createSimulation(() => {
- this.projectsController.updateAuthorizations();
- this.closeWindow();
- });
- });
-
- $(".project-cancel-btn").show().click(() => {
- this.closeWindow();
- });
-
- this.table.empty();
-
- $(".project-name-form input").val("");
- $(".participant-add-form input").val("");
-
- $(".participant-add-form .btn").click(() => {
- this.handleParticipantAdd(() => {
- });
- });
-
- this.table.on("click", ".participant-level div", (event: JQueryEventObject) => {
- this.handleParticipantLevelChange(event, () => {
- });
- });
-
- this.table.on("click", ".participant-remove div", (event: JQueryEventObject) => {
- this.handleParticipantDelete(event, () => {
- });
- });
-
- this.windowOverlay.fadeIn(200);
- }
-
- /**
- * Creates a new simulation with the current name input and all currently present authorizations added in the
- * project 'add' window.
- *
- * @param callback The function to be called when this operation has succeeded
- */
- private createSimulation(callback: (simulationId: number) => any): void {
- this.api.addSimulation({
- id: -1,
- name: $(".project-name-form input").text(),
- datetimeCreated: Util.getCurrentDateTime(),
- datetimeLastEdited: Util.getCurrentDateTime()
- }).then((data: any) => {
- let asyncCounter = this.simAuthorizations.length;
- this.simAuthorizations.forEach((authorization: IAuthorization) => {
- authorization.simulationId = data.id;
- this.api.addAuthorization(authorization).then((data: any) => {
- asyncCounter--;
-
- if (asyncCounter <= 0) {
- callback(data.id);
- }
- });
- });
- if (this.simAuthorizations.length === 0) {
- callback(data.id);
- }
- });
- }
-
- /**
- * Displays an alert of the given class name, to disappear again after a certain pre-defined timeout.
- *
- * @param name A selector that uniquely identifies the alert body to be shown.
- */
- private showAlert(name): void {
- const alert = $(name);
- alert.slideDown(200);
-
- setTimeout(() => {
- alert.slideUp(200);
- }, 5000);
- }
-
- /**
- * Closes the window with a transition, and calls the relevant callback after that transition has ended.
- */
- private closeWindow(): void {
- this.windowOverlay.fadeOut(200, () => {
- this.closeCallback();
- });
- }
-
- /**
- * Handles the click on an authorization icon in the project window authorization list.
- *
- * @param event The JQuery click event
- * @param callback The function to be called after the authorization was changed
- */
- private handleParticipantLevelChange(event: JQueryEventObject,
- callback: (authorization: IAuthorization) => any): void {
- $(event.target).closest(".participant-level").find("div").removeClass("active");
- $(event.target).addClass("active");
-
- const affectedRow = $(event.target).closest(".participant-row");
-
- for (let level in ProjectsController.authIconMap) {
- if (!ProjectsController.authIconMap.hasOwnProperty(level)) {
- continue;
- }
- if ($(event.target).is("." + ProjectsController.authIconMap[level])) {
- this.simAuthorizations[affectedRow.index()].authorizationLevel = level;
- callback(this.simAuthorizations[affectedRow.index()]);
- break;
- }
- }
- }
-
- /**
- * Handles the event where a user seeks to add a participant.
- *
- * @param callback The function to be called if the participant could be found and can be added.
- */
- private handleParticipantAdd(callback: (userId: number) => any): void {
- const inputForm = $(".participant-add-form input");
- this.api.getUserByEmail(inputForm.text()).then((data: any) => {
- let insert = true;
- for (let i = 0; i < this.simAuthorizations.length; i++) {
- if (this.simAuthorizations[i].userId === data.id) {
- insert = false;
- }
- }
-
- const simulationId = this.editMode ? this.simulationId : -1;
- if (data.id !== this.projectsController.currentUserId && insert) {
- this.simAuthorizations.push({
- userId: data.id,
- user: data,
- simulationId: simulationId,
- authorizationLevel: "VIEW"
- });
- callback(data.id);
- Util.sortAuthorizations(this.simAuthorizations);
- this.populateParticipantList();
- }
-
- // Clear input field after submission
- inputForm.val("");
- }, (reason: any) => {
- if (reason.code === 404) {
- this.showAlert(".participant-email-alert");
- }
- });
- }
-
- /**
- * Handles click events on the 'remove' icon next to each participant.
- *
- * @param event The JQuery click event
- * @param callback The function to be executed on removal of the participant from the internal list
- */
- private handleParticipantDelete(event: JQueryEventObject, callback: (authorization: IAuthorization) => any): void {
- const affectedRow = $(event.target).closest(".participant-row");
- const index = affectedRow.index();
- const authorization = this.simAuthorizations[index];
- this.simAuthorizations.splice(index, 1);
- this.populateParticipantList();
- callback(authorization);
- }
-
- /**
- * Populates the list of participants in the project edit window with all current authorizations.
- */
- private populateParticipantList(): void {
- this.table.empty();
-
- this.simAuthorizations.forEach((authorization: IAuthorization) => {
- this.table.append(
- '<div class="participant-row">' +
- ' <div class="participant-name">' + authorization.user.givenName + ' ' +
- authorization.user.familyName + '</div>' +
- ' <div class="participant-level">' +
- ' <div class="participant-level-view glyphicon glyphicon-eye-open ' +
- (authorization.authorizationLevel === "VIEW" ? 'active' : '') + '"></div>' +
- ' <div class="participant-level-edit glyphicon glyphicon-pencil ' +
- (authorization.authorizationLevel === "EDIT" ? 'active' : '') + '"></div>' +
- ' <div class="participant-level-own glyphicon glyphicon-home ' +
- (authorization.authorizationLevel === "OWN" ? 'active' : '') + '"></div>' +
- ' </div>' +
- ' <div class="participant-remove">' +
- ' <div class="glyphicon glyphicon-remove"></div>' +
- ' </div>' +
- '</div>'
- );
- });
- }
-}
diff --git a/src/scripts/serverconnection.ts b/src/scripts/serverconnection.ts
deleted file mode 100644
index e5cbf48a..00000000
--- a/src/scripts/serverconnection.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import {SocketController} from "./controllers/connection/socket";
-
-
-export class ServerConnection {
- private static _socketControllerInstance: SocketController;
-
-
- public static connect(onConnect: () => any): void {
- this._socketControllerInstance = new SocketController(onConnect);
- }
-
- public static send(request: IRequest): Promise<any> {
- return new Promise((resolve, reject) => {
- const checkUnimplemented = ServerConnection.interceptUnimplementedEndpoint(request);
- if (checkUnimplemented) {
- resolve(checkUnimplemented.content);
- return;
- }
-
- this._socketControllerInstance.sendRequest(request, (response: IResponse) => {
- if (response.status.code === 200) {
- ServerConnection.convertFlatToNestedPositionData(response.content, resolve);
- } else {
- reject(response.status);
- }
- });
- })
- }
-
- public static convertFlatToNestedPositionData(responseContent, resolve): void {
- const nestPositionCoords = (content: any) => {
- if (content["positionX"] !== undefined) {
- content["position"] = {
- x: content["positionX"],
- y: content["positionY"]
- };
- }
- };
-
- if (responseContent instanceof Array) {
- responseContent.forEach(nestPositionCoords);
- } else {
- nestPositionCoords(responseContent);
- }
-
- resolve(responseContent);
- }
-
- /**
- * Intercepts endpoints that are still unimplemented and responds with mock data.
- *
- * @param request The request
- * @returns {any} A response, or null if the endpoint is not on the list of unimplemented ones.
- */
- public static interceptUnimplementedEndpoint(request: IRequest): IResponse {
- // Endpoints that are unimplemented can be intercepted here
- return null;
- }
-}
diff --git a/src/scripts/splash.entry.ts b/src/scripts/splash.entry.ts
deleted file mode 100644
index 6abd9518..00000000
--- a/src/scripts/splash.entry.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-///<reference path="../../typings/index.d.ts" />
-///<reference path="./definitions.ts" />
-import * as $ from "jquery";
-import {APIController} from "./controllers/connection/api";
-window["jQuery"] = $;
-require("jquery.easing");
-
-
-// Variable to check whether user actively logged in by clicking the login button
-let hasClickedLogin = false;
-
-
-$(document).ready(() => {
- /**
- * jQuery for page scrolling feature
- */
- $('a.page-scroll').bind('click', function (event) {
- const $anchor = $(this);
- $('html, body').stop().animate({
- scrollTop: $($anchor.attr('href')).offset().top
- }, 1000, 'easeInOutExpo', () => {
- if ($anchor.attr('href') === "#page-top") {
- location.hash = '';
- } else {
- location.hash = $anchor.attr('href');
- }
- });
- event.preventDefault();
- });
-
- const checkScrollState = () => {
- const startY = 100;
-
- if ($(window).scrollTop() > startY || window.innerWidth < 768) {
- $('.navbar').removeClass("navbar-transparent");
- } else {
- $('.navbar').addClass("navbar-transparent");
- }
- };
-
- $(window).on("scroll load resize", function () {
- checkScrollState();
- });
-
- checkScrollState();
-
- const googleSigninBtn = $("#google-signin");
- googleSigninBtn.click(() => {
- hasClickedLogin = true;
- });
-
- /**
- * Display appropriate user buttons
- */
- if (localStorage.getItem("googleToken") !== null) {
- googleSigninBtn.hide();
- $(".navbar .logged-in").css("display", "inline-block");
- $(".logged-in .sign-out").click(() => {
- const auth2 = gapi.auth2.getAuthInstance();
-
- auth2.signOut().then(() => {
- // Remove session storage items
- localStorage.removeItem("googleToken");
- localStorage.removeItem("googleTokenExpiration");
- localStorage.removeItem("googleName");
- localStorage.removeItem("googleEmail");
- localStorage.removeItem("userId");
- localStorage.removeItem("simulationId");
-
- location.reload();
- });
- });
-
- // Check whether Google auth. token has expired and signin again if necessary
- const currentTime = (new Date()).getTime();
- if (parseInt(localStorage.getItem("googleTokenExpiration")) - currentTime <= 0) {
- gapi.auth2.getAuthInstance().signIn().then(() => {
- const authResponse = gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse();
- localStorage.setItem("googleToken", authResponse.id_token);
- const expirationTime = (new Date()).getTime() / 1000 + parseInt(authResponse.expires_in) - 5;
- localStorage.setItem("googleTokenExpiration", expirationTime.toString());
- });
- }
- }
-});
-
-/**
- * Google signin button
- */
-window["renderButton"] = () => {
- gapi.signin2.render('google-signin', {
- 'scope': 'profile email',
- 'width': 100,
- 'height': 30,
- 'longtitle': false,
- 'theme': 'dark',
- 'onsuccess': (googleUser) => {
- let api;
- new APIController((apiInstance: APIController) => {
- api = apiInstance;
- const email = googleUser.getBasicProfile().getEmail();
-
- const getUser = (userId: number) => {
- const reload = localStorage.getItem("userId") === null;
-
- localStorage.setItem("userId", userId.toString());
-
- // Redirect to the projects page
- if (hasClickedLogin) {
- window.location.href = "projects";
- } else if (reload) {
- window.location.reload();
- }
-
- };
-
- // Send the token to the server
- const id_token = googleUser.getAuthResponse().id_token;
- // Calculate token expiration time (in seconds since epoch)
- const expirationTime = (new Date()).getTime() / 1000 + googleUser.getAuthResponse().expires_in - 5;
-
- $.post('SERVER_BASE_URL/tokensignin', {
- idtoken: id_token
- }, (data: any) => {
- // Save user information in session storage for later use on other pages
- localStorage.setItem("googleToken", id_token);
- localStorage.setItem("googleTokenExpiration", expirationTime.toString());
- localStorage.setItem("googleName", googleUser.getBasicProfile().getGivenName() + " " +
- googleUser.getBasicProfile().getFamilyName());
- localStorage.setItem("googleEmail", email);
-
- if (data.isNewUser === true) {
- api.addUser({
- id: -1,
- email,
- googleId: googleUser.getBasicProfile().getId(),
- givenName: googleUser.getBasicProfile().getGivenName(),
- familyName: googleUser.getBasicProfile().getFamilyName()
- }).then((userData: any) => {
- getUser(userData.id);
- });
- } else {
- getUser(data.userId);
- }
- });
- });
- },
- 'onfailure': () => {
- console.log("Oops, something went wrong with your Google signin... Try again?");
- }
- });
-};
-
-// Set the language of the GAuth button to be English
-window["___gcfg"] = {
- lang: 'en'
-};
diff --git a/src/scripts/tests/util.spec.ts b/src/scripts/tests/util.spec.ts
deleted file mode 100644
index 74d62dfa..00000000
--- a/src/scripts/tests/util.spec.ts
+++ /dev/null
@@ -1,326 +0,0 @@
-///<reference path="../util.ts" />
-///<reference path="../../../typings/globals/jasmine/index.d.ts" />
-import {Util} from "../util";
-
-
-class TestUtils {
- /**
- * Checks whether the two (three-dimensional) wall lists are equivalent in content.
- *
- * This is a set-compare method, meaning that the order of the elements does not matter, but that they are present
- * in both arrays.
- *
- * Example of such a list: [[[1, 1], [2, 1]], [[3, 1], [0, 0]]]
- *
- * @param list1 The first list
- * @param list2 The second list
- */
- public static wallListEquals(list1: IRoomWall[], list2: IRoomWall[]): void {
- let current, found, counter;
-
- counter = 0;
- while (list1.length > 0) {
- current = list1.pop();
- found = false;
- list2.forEach((e: IRoomWall) => {
- if (current.startPos[0] === e.startPos[0] && current.startPos[1] === e.startPos[1] &&
- current.horizontal === e.horizontal && current.length === e.length) {
- counter++;
- found = true;
- }
- });
- if (!found) {
- fail();
- }
- }
- expect(list2.length).toEqual(counter);
- }
-
- /**
- * Does the same as wallList3DEquals, only for two lists of tiles.
- *
- * @param expected
- * @param actual
- */
- public static positionListEquals(expected: IGridPosition[], actual: IGridPosition[]): void {
- let current, found;
- let counter = 0;
-
- while (expected.length > 0) {
- current = expected.pop();
- found = false;
- actual.forEach((e) => {
- if (current.x === e.x && current.y === e.y) {
- counter++;
- found = true;
- }
- });
- if (!found) {
- fail();
- }
- }
-
- expect(actual.length).toEqual(counter);
- }
-
- public static boundsEquals(actual: IBounds, expected: IBounds): void {
- expect(actual.min[0]).toBe(expected.min[0]);
- expect(actual.min[1]).toBe(expected.min[1]);
- expect(actual.center[0]).toBe(expected.center[0]);
- expect(actual.center[1]).toBe(expected.center[1]);
- expect(actual.max[0]).toBe(expected.max[0]);
- expect(actual.max[1]).toBe(expected.max[1]);
- }
-}
-
-describe("Deriving wall locations", () => {
- it("should generate walls around a single tile", () => {
- let room = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }]
- };
-
- let result = Util.deriveWallLocations([
- room
- ]);
- let expected: IRoomWall[] = [
- {
- startPos: [1, 1],
- horizontal: false,
- length: 1
- },
- {
- startPos: [2, 1],
- horizontal: false,
- length: 1
- },
- {
- startPos: [1, 1],
- horizontal: true,
- length: 1
- },
- {
- startPos: [1, 2],
- horizontal: true,
- length: 1
- }
- ];
-
- TestUtils.wallListEquals(expected, result);
- }
- );
-
- it("should generate walls around two tiles connected by an edge", () => {
- let room = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [
- {
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }, {
- id: -1,
- roomId: -1,
- position: {x: 1, y: 2}
- }
- ]
- };
-
- let result = Util.deriveWallLocations([
- room
- ]);
- let expected: IRoomWall[] = [
- {
- startPos: [1, 1],
- horizontal: false,
- length: 2
- },
- {
- startPos: [2, 1],
- horizontal: false,
- length: 2
- },
- {
- startPos: [1, 1],
- horizontal: true,
- length: 1
- },
- {
- startPos: [1, 3],
- horizontal: true,
- length: 1
- }
- ];
-
- TestUtils.wallListEquals(expected, result);
- }
- );
-
- it("should generate walls around two independent rooms with one tile each", () => {
- let room1 = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [
- {
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }
- ]
- };
-
- let room2 = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 3}
- }
- ]
- };
-
- let result = Util.deriveWallLocations([
- room1, room2
- ]);
- let expected: IRoomWall[] = [
- {
- startPos: [1, 1],
- horizontal: false,
- length: 1
- },
- {
- startPos: [1, 3],
- horizontal: false,
- length: 1
- },
- {
- startPos: [2, 1],
- horizontal: false,
- length: 1
- },
- {
- startPos: [2, 3],
- horizontal: false,
- length: 1
- },
- {
- startPos: [1, 1],
- horizontal: true,
- length: 1
- },
- {
- startPos: [1, 2],
- horizontal: true,
- length: 1
- },
- {
- startPos: [1, 3],
- horizontal: true,
- length: 1
- },
- {
- startPos: [1, 4],
- horizontal: true,
- length: 1
- }
- ];
-
- TestUtils.wallListEquals(expected, result);
- }
- );
-});
-
-describe("Deriving valid next tile positions", () => {
- it("should derive correctly 4 valid tile positions around 1 selected tile with no other rooms", () => {
- let result = Util.deriveValidNextTilePositions([], [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }]);
- let expected = [
- {x: 1, y: 0}, {x: 2, y: 1}, {x: 1, y: 2}, {x: 0, y: 1}
- ];
-
- TestUtils.positionListEquals(expected, result);
- });
-
- it("should derive correctly 6 valid tile positions around 2 selected tiles with no other rooms", () => {
- let result = Util.deriveValidNextTilePositions([], [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }, {
- id: -1,
- roomId: -1,
- position: {x: 2, y: 1}
- }]);
- let expected = [
- {x: 1, y: 0}, {x: 2, y: 0}, {x: 3, y: 1}, {x: 1, y: 2}, {x: 2, y: 2}, {x: 0, y: 1}
- ];
-
- TestUtils.positionListEquals(expected, result);
- });
-
- it("should derive correctly 3 valid tile positions around 1 selected tiles with 1 adjacent room", () => {
- let room = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [{
- id: -1,
- roomId: -1,
- position: {x: 0, y: 1}
- }]
- };
- let result = Util.deriveValidNextTilePositions([room], [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }]);
- let expected = [
- {x: 1, y: 0}, {x: 2, y: 1}, {x: 1, y: 2}
- ];
-
- TestUtils.positionListEquals(expected, result);
- });
-});
-
-describe("Calculating the bounds and average point of a list of rooms", () => {
- it("should calculate correctly the bounds of a 1-tile room", () => {
- let room = {
- id: -1,
- datacenterId: -1,
- name: "testroom",
- roomType: "none",
- tiles: [{
- id: -1,
- roomId: -1,
- position: {x: 1, y: 1}
- }]
- };
- let result = Util.calculateRoomListBounds([room]);
- let expected = {
- min: [1, 1],
- center: [1.5, 1.5],
- max: [2, 2]
- };
-
- TestUtils.boundsEquals(result, expected);
- });
-});
diff --git a/src/scripts/user-authentication.ts b/src/scripts/user-authentication.ts
deleted file mode 100644
index e9d13091..00000000
--- a/src/scripts/user-authentication.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-///<reference path="../../typings/index.d.ts" />
-import * as $ from "jquery";
-
-
-// Redirect the user to the splash page, if not signed in
-if (localStorage.getItem("googleToken") === null) {
- window.location.replace("/");
-}
-
-// Set the username in the navbar
-$("nav .user .username").text(localStorage.getItem("googleName"));
-
-
-// Set the language of the GAuth button to be English
-window["___gcfg"] = {
- lang: 'en'
-};
-
-/**
- * Google signin button.
- */
-window["gapiSigninButton"] = () => {
- gapi.signin2.render('google-signin', {
- 'scope': 'profile email',
- 'onsuccess': (googleUser) => {
- const auth2 = gapi.auth2.getAuthInstance();
-
- // Handle signout click
- $("nav .user .sign-out").click(() => {
- removeUserInfo();
- auth2.signOut().then(() => {
- window.location.href = "/";
- });
- });
-
- // Check if the token has expired
- const currentTime = (new Date()).getTime() / 1000;
-
- if (parseInt(localStorage.getItem("googleTokenExpiration")) - currentTime <= 0) {
- auth2.signIn().then(() => {
- localStorage.setItem("googleToken", googleUser.getAuthResponse().id_token);
- const expirationTime = (new Date()).getTime() / 1000 + parseInt(googleUser.getAuthResponse().expires_in) - 5;
- localStorage.setItem("googleTokenExpiration", expirationTime.toString());
- });
- }
- },
- 'onfailure': () => {
- window.location.href = "/";
- console.log("Oops, something went wrong with your Google signin... Try again?");
- }
- });
-};
-
-
-/**
- * Removes session storage items.
- */
-export function removeUserInfo() {
- localStorage.removeItem("googleToken");
- localStorage.removeItem("googleTokenExpiration");
- localStorage.removeItem("googleName");
- localStorage.removeItem("googleEmail");
- localStorage.removeItem("userId");
- localStorage.removeItem("simulationId");
-}
diff --git a/src/scripts/util.ts b/src/scripts/util.ts
deleted file mode 100644
index d3a2ea58..00000000
--- a/src/scripts/util.ts
+++ /dev/null
@@ -1,613 +0,0 @@
-///<reference path="definitions.ts" />
-import {Colors} from "./colors";
-
-
-export enum IntensityLevel {
- LOW,
- MID_LOW,
- MID_HIGH,
- HIGH
-}
-
-
-export class Util {
- private static authorizationLevels = [
- "OWN", "EDIT", "VIEW"
- ];
-
-
- /**
- * Derives the wall locations given a list of rooms.
- *
- * Does so by computing an outline around all tiles in the rooms.
- */
- public static deriveWallLocations(rooms: IRoom[]): IRoomWall[] {
- const verticalWalls = {};
- const horizontalWalls = {};
- let doInsert;
- rooms.forEach((room: IRoom) => {
- room.tiles.forEach((tile: ITile) => {
- const x = tile.position.x, y = tile.position.y;
- for (let dX = -1; dX <= 1; dX++) {
- for (let dY = -1; dY <= 1; dY++) {
- if (Math.abs(dX) === Math.abs(dY)) {
- continue;
- }
-
- doInsert = true;
- room.tiles.forEach((otherTile: ITile) => {
- if (otherTile.position.x === x + dX && otherTile.position.y === y + dY) {
- doInsert = false;
- }
- });
-
- if (doInsert) {
- if (dX === -1) {
- if (verticalWalls[x] === undefined) {
- verticalWalls[x] = [];
- }
- if (verticalWalls[x].indexOf(y) === -1) {
- verticalWalls[x].push(y);
- }
- } else if (dX === 1) {
- if (verticalWalls[x + 1] === undefined) {
- verticalWalls[x + 1] = [];
- }
- if (verticalWalls[x + 1].indexOf(y) === -1) {
- verticalWalls[x + 1].push(y);
- }
- } else if (dY === -1) {
- if (horizontalWalls[y] === undefined) {
- horizontalWalls[y] = [];
- }
- if (horizontalWalls[y].indexOf(x) === -1) {
- horizontalWalls[y].push(x);
- }
- } else if (dY === 1) {
- if (horizontalWalls[y + 1] === undefined) {
- horizontalWalls[y + 1] = [];
- }
- if (horizontalWalls[y + 1].indexOf(x) === -1) {
- horizontalWalls[y + 1].push(x);
- }
- }
- }
- }
- }
- });
- });
-
- const result: IRoomWall[] = [];
- const walls = [verticalWalls, horizontalWalls];
- for (let i = 0; i < 2; i++) {
- const wallList = walls[i];
- for (let a in wallList) {
- if (!wallList.hasOwnProperty(a)) {
- return;
- }
-
- wallList[a].sort((a: number, b: number) => {
- return a - b;
- });
-
- let startPos = wallList[a][0];
- const positionArray = (i === 1 ? <number[]>[startPos, parseInt(a)] : <number[]>[parseInt(a), startPos]);
-
- if (wallList[a].length === 1) {
- result.push({
- startPos: positionArray,
- horizontal: i === 1,
- length: 1
- });
- } else {
- let consecutiveCount = 1;
- for (let b = 0; b < wallList[a].length - 1; b++) {
- if (b + 1 === wallList[a].length - 1) {
- if (wallList[a][b + 1] - wallList[a][b] > 1) {
- result.push({
- startPos: (i === 1 ? <number[]>[startPos, parseInt(a)] : <number[]>[parseInt(a), startPos]),
- horizontal: i === 1,
- length: consecutiveCount
- });
- consecutiveCount = 0;
- startPos = wallList[a][b + 1];
- }
- result.push({
- startPos: (i === 1 ? <number[]>[startPos, parseInt(a)] : <number[]>[parseInt(a), startPos]),
- horizontal: i === 1,
- length: consecutiveCount + 1
- });
- break;
- } else if (wallList[a][b + 1] - wallList[a][b] > 1) {
- result.push({
- startPos: (i === 1 ? <number[]>[startPos, parseInt(a)] : <number[]>[parseInt(a), startPos]),
- horizontal: i === 1,
- length: consecutiveCount
- });
- startPos = wallList[a][b + 1];
- consecutiveCount = 0;
- }
- consecutiveCount++;
- }
- }
- }
- }
-
- return result;
- }
-
- /**
- * Generates a list of all valid tile positions around the currently selected room under construction.
- *
- * @param rooms The rooms that already exist in the model
- * @param selectedTiles The tiles that the user has already selected to form a new room
- * @returns {Array} A 2D list of tile positions that are valid next tile choices.
- */
- public static deriveValidNextTilePositions(rooms: IRoom[], selectedTiles: ITile[]): IGridPosition[] {
- const result = [], newPosition = {x: 0, y: 0};
- let isSurroundingTile;
-
- selectedTiles.forEach((tile: ITile) => {
- const x = tile.position.x, y = tile.position.y;
- for (let dX = -1; dX <= 1; dX++) {
- for (let dY = -1; dY <= 1; dY++) {
- if (Math.abs(dX) === Math.abs(dY)) {
- continue;
- }
-
- newPosition.x = x + dX;
- newPosition.y = y + dY;
-
- isSurroundingTile = true;
- selectedTiles.forEach((otherTile: ITile) => {
- if (otherTile.position.x === newPosition.x && otherTile.position.y === newPosition.y) {
- isSurroundingTile = false;
- }
- });
-
- if (isSurroundingTile && !Util.checkRoomCollision(rooms, newPosition)) {
- result.push({x: newPosition.x, y: newPosition.y});
- }
- }
- }
- });
-
- return result;
- }
-
- /**
- * Determines whether a position is contained in a list of tiles.
- *
- * @param list A list of tiles
- * @param position A position
- * @returns {boolean} Whether the list contains the position
- */
- public static tileListContainsPosition(list: ITile[], position: IGridPosition): boolean {
- return Util.tileListPositionIndexOf(list, position) !== -1;
- }
-
- /**
- * Determines the index of a position in a list of tiles.
- *
- * @param list A list of tiles
- * @param position A position
- * @returns {number} Index of the position in the list of tiles, -1 if not found
- */
- public static tileListPositionIndexOf(list: ITile[], position: IGridPosition): number {
- let index = -1;
-
- for (let i = 0; i < list.length; i++) {
- const element = list[i];
- if (position.x === element.position.x && position.y === element.position.y) {
- index = i;
- break;
- }
- }
-
- return index;
- }
-
- /**
- * Determines whether a position is contained in a list of positions.
- *
- * @param list A list of positions
- * @param position A position
- * @returns {boolean} Whether the list contains the position
- */
- public static positionListContainsPosition(list: IGridPosition[], position: IGridPosition): boolean {
- return Util.positionListPositionIndexOf(list, position) !== -1;
- }
-
- /**
- * Determines the index of a position in a list of positions.
- *
- * @param list A list of positions
- * @param position A position
- * @returns {number} Index of the position in the list of tiles, -1 if not found
- */
- public static positionListPositionIndexOf(list: IGridPosition[], position: IGridPosition): number {
- let index = -1;
-
- for (let i = 0; i < list.length; i++) {
- const element = list[i];
- if (position.x === element.x && position.y === element.y) {
- index = i;
- break;
- }
- }
-
- return index;
- }
-
- /**
- * Determines the index of a room that is colliding with a given grid tile.
- *
- * Returns -1 if no collision is found.
- *
- * @param rooms An array of Room objects that should be checked for collisions
- * @param position A position
- * @returns {number} The index of the room in the rooms list if found, else -1
- */
- public static roomCollisionIndexOf(rooms: IRoom[], position: IGridPosition): number {
- let index = -1;
-
- for (let i = 0; i < rooms.length; i++) {
- const room = rooms[i];
- if (Util.tileListContainsPosition(room.tiles, position)) {
- index = i;
- break;
- }
- }
-
- return index;
- }
-
- /**
- * Checks whether a tile location collides with an existing room.
- *
- * @param rooms A list of rooms to be analyzed
- * @param position A position
- * @returns {boolean} Whether the tile lies in an existing room
- */
- public static checkRoomCollision(rooms: IRoom[], position: IGridPosition): boolean {
- return Util.roomCollisionIndexOf(rooms, position) !== -1;
- }
-
- /**
- * Calculates the minimum, center, and maximum of a list of rooms in stage coordinates.
- *
- * This center is calculated by averaging the most outlying tiles of all rooms.
- *
- * @param rooms The rooms to be analyzed
- * @returns {IBounds} The coordinates of the minimum, center, and maximum
- */
- public static calculateRoomListBounds(rooms: IRoom[]): IBounds {
- const min = [Number.MAX_VALUE, Number.MAX_VALUE];
- const max = [-1, -1];
-
- rooms.forEach((room: IRoom) => {
- room.tiles.forEach((tile: ITile) => {
- if (tile.position.x < min[0]) {
- min[0] = tile.position.x;
- }
- if (tile.position.y < min[1]) {
- min[1] = tile.position.y;
- }
-
- if (tile.position.x > max[0]) {
- max[0] = tile.position.x;
- }
- if (tile.position.y > max[1]) {
- max[1] = tile.position.y;
- }
- });
- });
-
- max[0]++;
- max[1]++;
-
- const gridCenter = [min[0] + (max[0] - min[0]) / 2.0, min[1] + (max[1] - min[1]) / 2.0];
-
- return {
- min: min,
- center: gridCenter,
- max: max
- };
- }
-
- /**
- * Does the same as 'calculateRoomListBounds', only for one room.
- *
- * @param room The room to be analyzed
- * @returns {IBounds} The coordinates of the minimum, center, and maximum
- */
- public static calculateRoomBounds(room: IRoom): IBounds {
- return Util.calculateRoomListBounds([room]);
- }
-
- public static calculateRoomNamePosition(room: IRoom): IRoomNamePos {
- const result: IRoomNamePos = {
- topLeft: {x: 0, y: 0},
- length: 0
- };
-
- // Look for the top-most tile y-coordinate
- let topMin = Number.MAX_VALUE;
- room.tiles.forEach((tile: ITile) => {
- if (tile.position.y < topMin) {
- topMin = tile.position.y;
- }
- });
-
- // If there is no tile at the top, meaning that the room has no tiles, exit
- if (topMin === Number.MAX_VALUE) {
- return null;
- }
-
- // Find the left-most tile at the top and the length of its adjacent tiles to the right
- const topTilePositions: number[] = [];
- room.tiles.forEach((tile: ITile) => {
- if (tile.position.y === topMin) {
- topTilePositions.push(tile.position.x);
- }
- });
- topTilePositions.sort();
- const leftMin = topTilePositions[0];
- let length = 0;
-
- while (length < topTilePositions.length && topTilePositions[length] - leftMin === length) {
- length++;
- }
-
- result.topLeft.x = leftMin;
- result.topLeft.y = topMin;
- result.length = length;
-
- return result;
- }
-
- /**
- * Analyzes an array of objects and calculates its fill ratio, by looking at the number of elements != null and
- * comparing that number to the array length.
- *
- * @param inputList The list to be analyzed
- * @returns {number} A fill ratio (between 0 and 1), representing the relative amount of objects != null in the list
- */
- public static getFillRatio(inputList: any[]): number {
- let numNulls = 0;
-
- if (inputList.length === 0) {
- return 0;
- }
-
- inputList.forEach((element: any) => {
- if (element == null) {
- numNulls++;
- }
- });
-
- return (inputList.length - numNulls) / inputList.length;
- }
-
- /**
- * Calculates the energy consumption ration of the given rack.
- *
- * @param rack The rack of which the power consumption should be analyzed
- * @returns {number} The energy consumption ratio
- */
- public static getEnergyRatio(rack: IRack): number {
- let energySum = 0;
-
- rack.machines.forEach((machine: IMachine) => {
- if (machine === null) {
- return;
- }
-
- let machineConsumption = 0;
-
- let nodeUnitList: INodeUnit[] = <INodeUnit[]>machine.cpus.concat(machine.gpus);
- nodeUnitList = nodeUnitList.concat(<INodeUnit[]>machine.memories);
- nodeUnitList = nodeUnitList.concat(<INodeUnit[]>machine.storages);
- nodeUnitList.forEach((unit: INodeUnit) => {
- machineConsumption += unit.energyConsumptionW;
- });
-
- energySum += machineConsumption;
- });
-
- return energySum / rack.powerCapacityW;
- }
-
- /**
- * Parses date-time expresses of the form YYYY-MM-DDTHH:MM:SS and returns a parsed object.
- *
- * @param input A string expressing a date and a time, in the above mentioned format
- * @returns {IDateTime} A DateTime object with the parsed date and time information as content
- */
- public static parseDateTime(input: string): IDateTime {
- const output: IDateTime = {
- year: 0,
- month: 0,
- day: 0,
- hour: 0,
- minute: 0,
- second: 0
- };
-
- const dateAndTime = input.split("T");
- const dateComponents = dateAndTime[0].split("-");
- output.year = parseInt(dateComponents[0], 10);
- output.month = parseInt(dateComponents[1], 10);
- output.day = parseInt(dateComponents[2], 10);
-
- const timeComponents = dateAndTime[1].split(":");
- output.hour = parseInt(timeComponents[0], 10);
- output.minute = parseInt(timeComponents[1], 10);
- output.second = parseInt(timeComponents[2], 10);
-
- return output;
- }
-
- public static formatDateTime(input: IDateTime) {
- let date;
- const currentDate = new Date();
-
- date = Util.addPaddingToTwo(input.day) + "/" +
- Util.addPaddingToTwo(input.month) + "/" +
- Util.addPaddingToTwo(input.year);
-
- if (input.year === currentDate.getFullYear() &&
- input.month === currentDate.getMonth() + 1) {
- if (input.day === currentDate.getDate()) {
- date = "Today";
- } else if (input.day === currentDate.getDate() - 1) {
- date = "Yesterday";
- }
- }
-
- return date + ", " +
- Util.addPaddingToTwo(input.hour) + ":" +
- Util.addPaddingToTwo(input.minute);
- }
-
- public static getCurrentDateTime(): string {
- const currentDate = new Date();
- return currentDate.getFullYear() + "-" + Util.addPaddingToTwo(currentDate.getMonth() + 1) + "-" +
- Util.addPaddingToTwo(currentDate.getDate()) + "T" + Util.addPaddingToTwo(currentDate.getHours()) + ":" +
- Util.addPaddingToTwo(currentDate.getMinutes()) + ":" + Util.addPaddingToTwo(currentDate.getSeconds());
- }
-
- /**
- * Removes all populated object properties from a given object, and returns a copy without them.
- *
- * An exception of such an object property is made in the case of a position object (of type GridPosition), which
- * is copied over as well.
- *
- * Does not manipulate the original object in any way, except if your object has quantum-like properties, which
- * change upon inspection. In such a case, I'm afraid that this method can do little for you.
- *
- * @param object The input object
- * @returns {any} A copy of the object without any populated properties (of type object).
- */
- public static packageForSending(object: any) {
- const result: any = {};
- for (let prop in object) {
- if (object.hasOwnProperty(prop)) {
- if (typeof object[prop] !== "object") {
- result[prop] = object[prop];
- } else {
- if (object[prop] instanceof Array) {
- if (object[prop].length === 0 || !(object[prop][0] instanceof Object)) {
- result[prop] = [];
- for (let i = 0; i < object[prop].length; i++) {
- result[prop][i] = object[prop][i];
- }
- }
- }
- if (object[prop] != null && object[prop].hasOwnProperty("x") && object[prop].hasOwnProperty("y")) {
- result["positionX"] = object[prop].x;
- result["positionY"] = object[prop].y;
- }
- }
- }
- }
- return result;
- }
-
- public static addPaddingToTwo(integer: number): string {
- if (integer < 10) {
- return "0" + integer.toString();
- } else {
- return integer.toString();
- }
- }
-
- public static convertSecondsToFormattedTime(seconds: number): string {
- let hour = Math.floor(seconds / 3600);
- let minute = Math.floor(seconds / 60) % 60;
- let second = seconds % 60;
-
- hour = isNaN(hour) ? 0 : hour;
- minute = isNaN(minute) ? 0 : minute;
- second = isNaN(second) ? 0 : second;
-
- return this.addPaddingToTwo(hour) + ":" +
- this.addPaddingToTwo(minute) + ":" +
- this.addPaddingToTwo(second);
- }
-
- public static determineLoadIntensityLevel(loadFraction: number): IntensityLevel {
- if (loadFraction < 0.25) {
- return IntensityLevel.LOW;
- } else if (loadFraction < 0.5) {
- return IntensityLevel.MID_LOW;
- } else if (loadFraction < 0.75) {
- return IntensityLevel.MID_HIGH;
- } else {
- return IntensityLevel.HIGH;
- }
- }
-
- public static convertIntensityToColor(intensityLevel: IntensityLevel): string {
- if (intensityLevel === IntensityLevel.LOW) {
- return Colors.SIM_LOW;
- } else if (intensityLevel === IntensityLevel.MID_LOW) {
- return Colors.SIM_MID_LOW;
- } else if (intensityLevel === IntensityLevel.MID_HIGH) {
- return Colors.SIM_MID_HIGH;
- } else if (intensityLevel === IntensityLevel.HIGH) {
- return Colors.SIM_HIGH;
- }
- }
-
- /**
- * Gives the sentence-cased alternative for a given string.
- *
- * @example Input: TEST, Output: Test
- *
- * @param input The input string
- * @returns {any} The sentence-cased string
- */
- public static toSentenceCase(input: string): string {
- if (input === undefined || input === null) {
- return undefined;
- }
- if (input.length === 0) {
- return "";
- }
-
- return input[0].toUpperCase() + input.substr(1).toLowerCase();
- }
-
- /**
- * Sort a list of authorizations based on the levels of authorizations.
- *
- * @param list The list to be sorted (in-place)
- */
- public static sortAuthorizations(list: IAuthorization[]): void {
- list.sort((a: IAuthorization, b: IAuthorization): number => {
- return this.authorizationLevels.indexOf(a.authorizationLevel) -
- this.authorizationLevels.indexOf(b.authorizationLevel);
- });
- }
-
- /**
- * Returns an array containing all numbers of a range from 0 to x (including x).
- */
- public static range(x: number): number[] {
- return Array.apply(null, Array(x + 1)).map((_, i) => {
- return i.toString();
- })
- }
-
- /**
- * Returns an array containing all numbers of a range from 0 to x (including x).
- */
- public static timeRange(x: number): Date[] {
- return Util.range(x).map((tick: number) => {
- const t = new Date(1970, 0, 1); // Epoch
- t.setSeconds(tick);
- return t;
- });
- }
-}
diff --git a/src/scripts/views/layers/dcobject.ts b/src/scripts/views/layers/dcobject.ts
deleted file mode 100644
index f883a218..00000000
--- a/src/scripts/views/layers/dcobject.ts
+++ /dev/null
@@ -1,250 +0,0 @@
-import {Colors} from "../../colors";
-import {Util, IntensityLevel} from "../../util";
-import {MapView} from "../mapview";
-import {DCProgressBar} from "./dcprogressbar";
-import {Layer} from "./layer";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-export class DCObjectLayer implements Layer {
- public static ITEM_MARGIN = CELL_SIZE / 7.0;
- public static ITEM_PADDING = CELL_SIZE / 10.0;
- public static STROKE_WIDTH = CELL_SIZE / 20.0;
- public static PROGRESS_BAR_DISTANCE = CELL_SIZE / 17.0;
- public static CONTENT_SIZE = CELL_SIZE - DCObjectLayer.ITEM_MARGIN * 2 - DCObjectLayer.ITEM_PADDING * 3;
-
- public container: createjs.Container;
- public detailedMode: boolean;
- public coloringMode: boolean;
- public intensityLevels: { [key: number]: IntensityLevel; } = {};
-
- private mapView: MapView;
- private preload: createjs.LoadQueue;
- private rackSpaceBitmap: createjs.Bitmap;
- private rackEnergyBitmap: createjs.Bitmap;
- private psuBitmap: createjs.Bitmap;
- private coolingItemBitmap: createjs.Bitmap;
-
- // This associative lookup object keeps all DC display objects with as property name the index of the global map
- // array that they are located in.
- private dcObjectMap: { [key: number]: any; };
-
-
- public static drawHoverRack(position: IGridPosition): createjs.Container {
- const result = new createjs.Container();
-
- DCObjectLayer.drawItemRectangle(
- position, Colors.RACK_BACKGROUND, Colors.RACK_BORDER, result
- );
- DCProgressBar.drawItemProgressRectangle(
- position, Colors.RACK_SPACE_BAR_BACKGROUND, result, 0, 1
- );
- DCProgressBar.drawItemProgressRectangle(
- position, Colors.RACK_ENERGY_BAR_BACKGROUND, result, 1, 1
- );
-
- return result;
- }
-
- public static drawHoverPSU(position: IGridPosition): createjs.Container {
- const result = new createjs.Container();
-
- DCObjectLayer.drawItemRectangle(
- position, Colors.PSU_BACKGROUND, Colors.PSU_BORDER, result
- );
-
- return result;
- }
-
- public static drawHoverCoolingItem(position: IGridPosition): createjs.Container {
- const result = new createjs.Container();
-
- DCObjectLayer.drawItemRectangle(
- position, Colors.COOLING_ITEM_BACKGROUND, Colors.COOLING_ITEM_BORDER, result
- );
-
- return result;
- }
-
- /**
- * Draws an object rectangle in a given grid cell, with margin around its border.
- *
- * @param position The coordinates of the grid cell in which it should be located
- * @param color The background color of the item
- * @param borderColor The border color
- * @param container The container to which it should be drawn
- * @returns {createjs.Shape} The drawn shape
- */
- private static drawItemRectangle(position: IGridPosition, color: string, borderColor: string,
- container: createjs.Container): createjs.Shape {
- const shape = new createjs.Shape();
- shape.graphics.beginStroke(borderColor);
- shape.graphics.setStrokeStyle(DCObjectLayer.STROKE_WIDTH);
- shape.graphics.beginFill(color);
- shape.graphics.drawRect(
- position.x * CELL_SIZE + DCObjectLayer.ITEM_MARGIN,
- position.y * CELL_SIZE + DCObjectLayer.ITEM_MARGIN,
- CELL_SIZE - DCObjectLayer.ITEM_MARGIN * 2,
- CELL_SIZE - DCObjectLayer.ITEM_MARGIN * 2
- );
- container.addChild(shape);
- return shape;
- }
-
- /**
- * Draws an bitmap in item format.
- *
- * @param position The coordinates of the grid cell in which it should be located
- * @param container The container to which it should be drawn
- * @param originBitmap The bitmap that should be drawn
- * @returns {createjs.Bitmap} The drawn bitmap
- */
- private static drawItemIcon(position: IGridPosition, container: createjs.Container,
- originBitmap: createjs.Bitmap): createjs.Bitmap {
- const bitmap = originBitmap.clone();
- container.addChild(bitmap);
- bitmap.x = position.x * CELL_SIZE + DCObjectLayer.ITEM_MARGIN + DCObjectLayer.ITEM_PADDING * 1.5;
- bitmap.y = position.y * CELL_SIZE + DCObjectLayer.ITEM_MARGIN + DCObjectLayer.ITEM_PADDING * 1.5;
- return bitmap;
- }
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
-
- this.detailedMode = true;
- this.coloringMode = false;
-
- this.preload = new createjs.LoadQueue();
- this.preload.addEventListener("complete", () => {
- this.rackSpaceBitmap = new createjs.Bitmap(<HTMLImageElement>this.preload.getResult("rack-space"));
- this.rackEnergyBitmap = new createjs.Bitmap(<HTMLImageElement>this.preload.getResult("rack-energy"));
- this.psuBitmap = new createjs.Bitmap(<HTMLImageElement>this.preload.getResult("psu"));
- this.coolingItemBitmap = new createjs.Bitmap(<HTMLImageElement>this.preload.getResult("coolingitem"));
-
- // Scale the images
- this.rackSpaceBitmap.scaleX = DCProgressBar.PROGRESS_BAR_WIDTH / this.rackSpaceBitmap.image.width;
- this.rackSpaceBitmap.scaleY = DCProgressBar.PROGRESS_BAR_WIDTH / this.rackSpaceBitmap.image.height;
-
- this.rackEnergyBitmap.scaleX = DCProgressBar.PROGRESS_BAR_WIDTH / this.rackEnergyBitmap.image.width;
- this.rackEnergyBitmap.scaleY = DCProgressBar.PROGRESS_BAR_WIDTH / this.rackEnergyBitmap.image.height;
-
- this.psuBitmap.scaleX = DCObjectLayer.CONTENT_SIZE / this.psuBitmap.image.width;
- this.psuBitmap.scaleY = DCObjectLayer.CONTENT_SIZE / this.psuBitmap.image.height;
-
- this.coolingItemBitmap.scaleX = DCObjectLayer.CONTENT_SIZE / this.coolingItemBitmap.image.width;
- this.coolingItemBitmap.scaleY = DCObjectLayer.CONTENT_SIZE / this.coolingItemBitmap.image.height;
-
-
- this.populateObjectList();
- this.draw();
-
- this.mapView.updateScene = true;
- });
-
- this.preload.loadFile({id: "rack-space", src: 'img/app/rack-space.png'});
- this.preload.loadFile({id: "rack-energy", src: 'img/app/rack-energy.png'});
- this.preload.loadFile({id: "psu", src: 'img/app/psu.png'});
- this.preload.loadFile({id: "coolingitem", src: 'img/app/coolingitem.png'});
- }
-
- /**
- * Generates a list of DC objects with their associated display objects.
- */
- public populateObjectList(): void {
- this.dcObjectMap = {};
-
- this.mapView.currentDatacenter.rooms.forEach((room: IRoom) => {
- room.tiles.forEach((tile: ITile) => {
- if (tile.object !== undefined) {
- const index = tile.position.y * MapView.MAP_SIZE + tile.position.x;
-
- switch (tile.objectType) {
- case "RACK":
- this.dcObjectMap[index] = {
- spaceBar: new DCProgressBar(this.container,
- Colors.RACK_SPACE_BAR_BACKGROUND, Colors.RACK_SPACE_BAR_FILL,
- this.rackSpaceBitmap, tile.position, 0,
- Util.getFillRatio((<IRack>tile.object).machines)),
- energyBar: new DCProgressBar(this.container,
- Colors.RACK_ENERGY_BAR_BACKGROUND, Colors.RACK_ENERGY_BAR_FILL,
- this.rackEnergyBitmap, tile.position, 1,
- Util.getFillRatio((<IRack>tile.object).machines)),
- itemRect: createjs.Shape,
- tile: tile, model: tile.object, position: tile.position, type: tile.objectType
- };
-
- break;
- case "COOLING_ITEM":
- this.dcObjectMap[index] = {
- itemRect: createjs.Shape, batteryIcon: createjs.Bitmap,
- tile: tile, model: tile.object, position: tile.position, type: tile.objectType
- };
- break;
- case "PSU":
- this.dcObjectMap[index] = {
- itemRect: createjs.Shape, freezeIcon: createjs.Bitmap,
- tile: tile, model: tile.object, position: tile.position, type: tile.objectType
- };
- break;
- }
- }
- });
- });
- }
-
- public draw(): void {
- this.container.removeAllChildren();
-
- this.container.cursor = "pointer";
-
- for (let property in this.dcObjectMap) {
- if (this.dcObjectMap.hasOwnProperty(property)) {
- const currentObject = this.dcObjectMap[property];
-
- switch (currentObject.type) {
- case "RACK":
- let color = Colors.RACK_BACKGROUND;
-
- if (this.coloringMode && currentObject.tile.roomId ===
- this.mapView.mapController.roomModeController.currentRoom.id) {
- color = Util.convertIntensityToColor(this.intensityLevels[currentObject.model.id]);
- }
-
- currentObject.itemRect = DCObjectLayer.drawItemRectangle(
- currentObject.position, color, Colors.RACK_BORDER, this.container
- );
-
- if (this.detailedMode) {
- currentObject.spaceBar.fillRatio = Util.getFillRatio(currentObject.model.machines);
- currentObject.energyBar.fillRatio = Util.getEnergyRatio(currentObject.model);
-
- currentObject.spaceBar.draw();
- currentObject.energyBar.draw();
- }
- break;
- case "COOLING_ITEM":
- currentObject.itemRect = DCObjectLayer.drawItemRectangle(
- currentObject.position, Colors.COOLING_ITEM_BACKGROUND, Colors.COOLING_ITEM_BORDER,
- this.container
- );
-
- currentObject.freezeIcon = DCObjectLayer.drawItemIcon(currentObject.position, this.container,
- this.coolingItemBitmap);
- break;
- case "PSU":
- currentObject.itemRect = DCObjectLayer.drawItemRectangle(
- currentObject.position, Colors.PSU_BACKGROUND, Colors.PSU_BORDER,
- this.container
- );
-
- currentObject.batteryIcon = DCObjectLayer.drawItemIcon(currentObject.position, this.container,
- this.psuBitmap);
- break;
- }
- }
- }
-
- this.mapView.updateScene = true;
- }
-}
diff --git a/src/scripts/views/layers/dcprogressbar.ts b/src/scripts/views/layers/dcprogressbar.ts
deleted file mode 100644
index e518ead4..00000000
--- a/src/scripts/views/layers/dcprogressbar.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import {DCObjectLayer} from "./dcobject";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-export class DCProgressBar {
- public static PROGRESS_BAR_WIDTH = CELL_SIZE / 7.0;
-
- public container: createjs.Container;
- public fillRatio: number;
-
- private backgroundRect: createjs.Shape;
- private backgroundColor: string;
- private fillRect: createjs.Shape;
- private fillColor: string;
- private bitmap: createjs.Bitmap;
- private position: IGridPosition;
- private distanceFromBottom: number;
-
-
- /**
- * Draws a progress rectangle with rounded ends.
- *
- * @param position The coordinates of the grid cell in which it should be located
- * @param color The background color of the item
- * @param container The container to which it should be drawn
- * @param distanceFromBottom The index of its vertical position, counted from the bottom (0 is the lowest position)
- * @param fractionFilled The fraction of the available horizontal space that the progress bar should take up
- * @returns {createjs.Shape} The drawn shape
- */
- public static drawItemProgressRectangle(position: IGridPosition, color: string,
- container: createjs.Container, distanceFromBottom: number,
- fractionFilled: number): createjs.Shape {
- const shape = new createjs.Shape();
- shape.graphics.beginFill(color);
- let x = position.x * CELL_SIZE + DCObjectLayer.ITEM_MARGIN + DCObjectLayer.ITEM_PADDING;
- let y = (position.y + 1) * CELL_SIZE - DCObjectLayer.ITEM_MARGIN - DCObjectLayer.ITEM_PADDING -
- DCProgressBar.PROGRESS_BAR_WIDTH - distanceFromBottom *
- (DCProgressBar.PROGRESS_BAR_WIDTH + DCObjectLayer.PROGRESS_BAR_DISTANCE);
- let width = (CELL_SIZE - (DCObjectLayer.ITEM_MARGIN + DCObjectLayer.ITEM_PADDING) * 2) * fractionFilled;
- let height;
- let radius;
-
- if (width < DCProgressBar.PROGRESS_BAR_WIDTH) {
- height = width;
- radius = width / 2;
- y += (DCProgressBar.PROGRESS_BAR_WIDTH - height) / 2;
- } else {
- height = DCProgressBar.PROGRESS_BAR_WIDTH;
- radius = DCProgressBar.PROGRESS_BAR_WIDTH / 2;
- }
-
- shape.graphics.drawRoundRect(
- x, y, width, height, radius
- );
- container.addChild(shape);
- return shape;
- }
-
- /**
- * Draws an bitmap in progressbar format.
- *
- * @param position The coordinates of the grid cell in which it should be located
- * @param container The container to which it should be drawn
- * @param originBitmap The bitmap that should be drawn
- * @param distanceFromBottom The index of its vertical position, counted from the bottom (0 is the lowest position)
- * @returns {createjs.Bitmap} The drawn bitmap
- */
- public static drawProgressbarIcon(position: IGridPosition, container: createjs.Container, originBitmap: createjs.Bitmap,
- distanceFromBottom: number): createjs.Bitmap {
- const bitmap = originBitmap.clone();
- container.addChild(bitmap);
- bitmap.x = (position.x + 0.5) * CELL_SIZE - DCProgressBar.PROGRESS_BAR_WIDTH * 0.5;
- bitmap.y = (position.y + 1) * CELL_SIZE - DCObjectLayer.ITEM_MARGIN - DCObjectLayer.ITEM_PADDING -
- DCProgressBar.PROGRESS_BAR_WIDTH - distanceFromBottom *
- (DCProgressBar.PROGRESS_BAR_WIDTH + DCObjectLayer.PROGRESS_BAR_DISTANCE);
- return bitmap;
- }
-
- constructor(container: createjs.Container, backgroundColor: string,
- fillColor: string, bitmap: createjs.Bitmap, position: IGridPosition,
- indexFromBottom: number, fillRatio: number) {
- this.container = container;
- this.backgroundColor = backgroundColor;
- this.fillColor = fillColor;
- this.bitmap = bitmap;
- this.position = position;
- this.distanceFromBottom = indexFromBottom;
- this.fillRatio = fillRatio;
- }
-
- public draw() {
- this.backgroundRect = DCProgressBar.drawItemProgressRectangle(this.position, this.backgroundColor,
- this.container, this.distanceFromBottom, 1);
- this.fillRect = DCProgressBar.drawItemProgressRectangle(this.position, this.fillColor, this.container,
- this.distanceFromBottom, this.fillRatio);
-
- DCProgressBar.drawProgressbarIcon(this.position, this.container, this.bitmap, this.distanceFromBottom);
- }
-}
diff --git a/src/scripts/views/layers/gray.ts b/src/scripts/views/layers/gray.ts
deleted file mode 100644
index 63911d19..00000000
--- a/src/scripts/views/layers/gray.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-import {MapView} from "../mapview";
-import {Colors} from "../../colors";
-import {Util} from "../../util";
-import {Layer} from "./layer";
-
-
-/**
- * Class responsible for graying out non-active UI elements.
- */
-export class GrayLayer implements Layer {
- public container: createjs.Container;
- public currentRoom: IRoom;
- public currentObjectTile: ITile;
-
- private mapView: MapView;
- private grayRoomShape: createjs.Shape;
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
- }
-
- /**
- * Draws grayed out areas around a currently selected room.
- *
- * @param redraw Whether this is a redraw, or an initial draw action
- */
- public draw(redraw?: boolean): void {
- if (this.currentRoom === undefined) {
- return;
- }
-
- this.container.removeAllChildren();
-
- const roomBounds = Util.calculateRoomBounds(this.currentRoom);
-
- const shape = new createjs.Shape();
- shape.graphics.beginFill(Colors.GRAYED_OUT_AREA);
- shape.cursor = "pointer";
-
- this.drawLargeRects(shape, roomBounds);
- this.drawFineGrainedRects(shape, roomBounds);
-
- this.container.addChild(shape);
- if (redraw === true) {
- shape.alpha = 1;
- } else {
- shape.alpha = 0;
- this.mapView.animate(shape, {alpha: 1});
- }
-
- if (this.grayRoomShape !== undefined && !this.grayRoomShape.visible) {
- this.grayRoomShape = undefined;
- this.drawRackLevel(redraw);
- }
-
- this.mapView.updateScene = true;
- }
-
- private drawLargeRects(shape: createjs.Shape, roomBounds: IBounds): void {
- if (roomBounds.min[0] > 0) {
- MapView.drawRectangleToShape({x: 0, y: 0}, shape, roomBounds.min[0], MapView.MAP_SIZE);
- }
- if (roomBounds.min[1] > 0) {
- MapView.drawRectangleToShape({x: roomBounds.min[0], y: 0}, shape, roomBounds.max[0] - roomBounds.min[0],
- roomBounds.min[1]);
- }
- if (roomBounds.max[0] < MapView.MAP_SIZE - 1) {
- MapView.drawRectangleToShape({x: roomBounds.max[0], y: 0}, shape, MapView.MAP_SIZE - roomBounds.max[0],
- MapView.MAP_SIZE);
- }
- if (roomBounds.max[1] < MapView.MAP_SIZE - 1) {
- MapView.drawRectangleToShape({x: roomBounds.min[0], y: roomBounds.max[1]}, shape,
- roomBounds.max[0] - roomBounds.min[0], MapView.MAP_SIZE - roomBounds.max[1]);
- }
- }
-
- private drawFineGrainedRects(shape: createjs.Shape, roomBounds: IBounds): void {
- for (let x = roomBounds.min[0]; x < roomBounds.max[0]; x++) {
- for (let y = roomBounds.min[1]; y < roomBounds.max[1]; y++) {
- if (!Util.tileListContainsPosition(this.currentRoom.tiles, {x: x, y: y})) {
- MapView.drawRectangleToShape({x: x, y: y}, shape);
- }
- }
- }
- }
-
- public drawRackLevel(redraw?: boolean): void {
- if (this.currentObjectTile === undefined) {
- return;
- }
-
- this.grayRoomShape = new createjs.Shape();
- this.grayRoomShape.graphics.beginFill(Colors.GRAYED_OUT_AREA);
- this.grayRoomShape.cursor = "pointer";
- this.grayRoomShape.alpha = 0;
-
- this.currentRoom.tiles.forEach((tile: ITile) => {
- if (this.currentObjectTile.position.x !== tile.position.x ||
- this.currentObjectTile.position.y !== tile.position.y) {
- MapView.drawRectangleToShape({x: tile.position.x, y: tile.position.y}, this.grayRoomShape);
- }
- });
-
- this.container.addChild(this.grayRoomShape);
- if (redraw === true) {
- this.grayRoomShape.alpha = 1;
- } else {
- this.grayRoomShape.alpha = 0;
- this.mapView.animate(this.grayRoomShape, {alpha: 1});
- }
- }
-
- public hideRackLevel(): void {
- if (this.currentObjectTile === undefined) {
- return;
- }
-
- this.mapView.animate(this.grayRoomShape, {
- alpha: 0, visible: false
- });
- }
-
- /**
- * Clears the container.
- */
- public clear(): void {
- this.mapView.animate(this.container, {alpha: 0}, () => {
- this.container.removeAllChildren();
- this.container.alpha = 1;
- });
- this.grayRoomShape = undefined;
- this.currentRoom = undefined;
- }
-
- /**
- * Checks whether there is already an active room with grayed out areas around it.
- *
- * @returns {boolean} Whether the room is grayed out
- */
- public isGrayedOut(): boolean {
- return this.currentRoom !== undefined;
- }
-}
diff --git a/src/scripts/views/layers/grid.ts b/src/scripts/views/layers/grid.ts
deleted file mode 100644
index 9a52b2af..00000000
--- a/src/scripts/views/layers/grid.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import {Layer} from "./layer";
-import {MapView} from "../mapview";
-import {Colors} from "../../colors";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-/**
- * Class responsible for rendering the grid.
- */
-export class GridLayer implements Layer {
- public container: createjs.Container;
- public gridPixelSize: number;
-
- private mapView: MapView;
- private gridLineWidth: number;
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
-
- this.gridLineWidth = 0.5;
- this.gridPixelSize = MapView.MAP_SIZE * CELL_SIZE;
-
- this.draw();
- }
-
- /**
- * Draws the entire grid (later to be navigated around with offsets).
- */
- public draw(): void {
- this.container.removeAllChildren();
-
- let currentCellX = 0;
- let currentCellY = 0;
-
- while (currentCellX <= MapView.MAP_SIZE) {
- MapView.drawLine(
- currentCellX * CELL_SIZE, 0,
- currentCellX * CELL_SIZE, MapView.MAP_SIZE * CELL_SIZE,
- this.gridLineWidth, Colors.GRID_COLOR, this.container);
-
- currentCellX++;
- }
-
- while (currentCellY <= MapView.MAP_SIZE) {
- MapView.drawLine(
- 0, currentCellY * CELL_SIZE,
- MapView.MAP_SIZE * CELL_SIZE, currentCellY * CELL_SIZE,
- this.gridLineWidth, Colors.GRID_COLOR, this.container);
-
- currentCellY++;
- }
- }
-
- public setVisibility(value: boolean): void {
- this.container.visible = value;
- }
-} \ No newline at end of file
diff --git a/src/scripts/views/layers/hover.ts b/src/scripts/views/layers/hover.ts
deleted file mode 100644
index b9f5509c..00000000
--- a/src/scripts/views/layers/hover.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import {Layer} from "./layer";
-import {MapView} from "../mapview";
-import {Colors} from "../../colors";
-import {DCObjectLayer} from "./dcobject";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-/**
- * Class responsible for rendering the hover layer.
- */
-export class HoverLayer implements Layer {
- public container: createjs.Container;
- public hoverTilePosition: IGridPosition;
-
- private mapView: MapView;
- private hoverTile: createjs.Shape;
- private hoverRack: createjs.Container;
- private hoverPSU: createjs.Container;
- private hoverCoolingItem: createjs.Container;
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
-
- this.initialDraw();
- }
-
- /**
- * Draws the hover tile to the container at its current location and with its current color.
- */
- public draw(): void {
- let color;
-
- if (this.mapView.roomLayer.checkHoverTileValidity(this.hoverTilePosition)) {
- color = Colors.ROOM_HOVER_VALID;
- } else {
- color = Colors.ROOM_HOVER_INVALID;
- }
-
- this.hoverTile.graphics.clear().beginFill(color)
- .drawRect(this.hoverTilePosition.x * CELL_SIZE, this.hoverTilePosition.y * CELL_SIZE,
- CELL_SIZE, CELL_SIZE)
- .endFill();
- if (this.hoverRack.visible) {
- this.hoverRack.x = this.hoverTilePosition.x * CELL_SIZE;
- this.hoverRack.y = this.hoverTilePosition.y * CELL_SIZE;
- } else if (this.hoverPSU.visible) {
- this.hoverPSU.x = this.hoverTilePosition.x * CELL_SIZE;
- this.hoverPSU.y = this.hoverTilePosition.y * CELL_SIZE;
- } else if (this.hoverCoolingItem.visible) {
- this.hoverCoolingItem.x = this.hoverTilePosition.x * CELL_SIZE;
- this.hoverCoolingItem.y = this.hoverTilePosition.y * CELL_SIZE;
- }
- }
-
- /**
- * Performs the initial drawing action.
- */
- public initialDraw(): void {
- this.container.removeAllChildren();
-
- this.hoverTile = new createjs.Shape();
-
- this.hoverTilePosition = {x: 0, y: 0};
-
- this.hoverTile = MapView.drawRectangle(this.hoverTilePosition, Colors.ROOM_HOVER_VALID, this.container);
- this.hoverTile.visible = false;
-
- this.hoverRack = DCObjectLayer.drawHoverRack(this.hoverTilePosition);
- this.hoverPSU = DCObjectLayer.drawHoverPSU(this.hoverTilePosition);
- this.hoverCoolingItem = DCObjectLayer.drawHoverCoolingItem(this.hoverTilePosition);
-
- this.container.addChild(this.hoverRack);
- this.container.addChild(this.hoverPSU);
- this.container.addChild(this.hoverCoolingItem);
-
- this.hoverRack.visible = false;
- this.hoverPSU.visible = false;
- this.hoverCoolingItem.visible = false;
- }
-
- /**
- * Sets the hover tile visibility to true/false.
- *
- * @param value The visibility value
- */
- public setHoverTileVisibility(value: boolean): void {
- this.hoverTile.visible = value;
- this.mapView.updateScene = true;
- }
-
- /**
- * Sets the hover item visibility to true/false.
- *
- * @param value The visibility value
- * @param type The type of the object to be shown
- */
- public setHoverItemVisibility(value: boolean, type?: string): void {
- if (value === true) {
- this.hoverTile.visible = true;
-
- this.setHoverItemVisibilities(type);
- } else {
- this.hoverTile.visible = false;
- this.hoverRack.visible = false;
- this.hoverPSU.visible = false;
- this.hoverCoolingItem.visible = false;
- }
-
- this.mapView.updateScene = true;
- }
-
- private setHoverItemVisibilities(type: string): void {
- if (type === "RACK") {
- this.hoverRack.visible = true;
- this.hoverPSU.visible = false;
- this.hoverCoolingItem.visible = false;
- } else if (type === "PSU") {
- this.hoverRack.visible = false;
- this.hoverPSU.visible = true;
- this.hoverCoolingItem.visible = false;
- } else if (type === "COOLING_ITEM") {
- this.hoverRack.visible = false;
- this.hoverPSU.visible = false;
- this.hoverCoolingItem.visible = true;
- }
- }
-} \ No newline at end of file
diff --git a/src/scripts/views/layers/layer.ts b/src/scripts/views/layers/layer.ts
deleted file mode 100644
index 5e5295ac..00000000
--- a/src/scripts/views/layers/layer.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * Interface for a subview, representing a layer of the map view.
- */
-export interface Layer {
- container: createjs.Container;
-
- draw(): void;
-}
diff --git a/src/scripts/views/layers/room.ts b/src/scripts/views/layers/room.ts
deleted file mode 100644
index c1989206..00000000
--- a/src/scripts/views/layers/room.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-import {InteractionLevel} from "../../controllers/mapcontroller";
-import {Util, IntensityLevel} from "../../util";
-import {Colors} from "../../colors";
-import {MapView} from "../mapview";
-import {Layer} from "./layer";
-
-
-/**
- * Class responsible for rendering the rooms.
- */
-export class RoomLayer implements Layer {
- public container: createjs.Container;
- public coloringMode: boolean;
- public selectedTiles: ITile[];
- public selectedTileObjects: TilePositionObject[];
- public intensityLevels: { [key: number]: IntensityLevel; } = {};
-
- private mapView: MapView;
- private allRoomTileObjects: TilePositionObject[];
- private validNextTilePositions: IGridPosition[];
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
-
- this.allRoomTileObjects = [];
- this.selectedTiles = [];
- this.validNextTilePositions = [];
- this.selectedTileObjects = [];
- this.coloringMode = false;
-
- this.draw();
- }
-
- /**
- * Draws all rooms to the canvas.
- */
- public draw() {
- this.container.removeAllChildren();
-
- this.mapView.currentDatacenter.rooms.forEach((room: IRoom) => {
- let color = Colors.ROOM_DEFAULT;
-
- if (this.coloringMode && room.roomType === "SERVER" && this.intensityLevels[room.id] !== undefined) {
- color = Util.convertIntensityToColor(this.intensityLevels[room.id]);
- }
-
- room.tiles.forEach((tile: ITile) => {
- this.allRoomTileObjects.push({
- position: tile.position,
- tileObject: MapView.drawRectangle(tile.position, color, this.container)
- });
- });
- });
- }
-
- /**
- * Adds a newly selected tile to the list of selected tiles.
- *
- * If the tile was already selected beforehand, it is removed.
- *
- * @param tile The tile to be added
- */
- public addSelectedTile(tile: ITile): void {
- this.selectedTiles.push(tile);
-
- const tileObject = MapView.drawRectangle(tile.position, Colors.ROOM_SELECTED, this.container);
- this.selectedTileObjects.push({
- position: {x: tile.position.x, y: tile.position.y},
- tileObject: tileObject
- });
-
- this.validNextTilePositions = Util.deriveValidNextTilePositions(
- this.mapView.currentDatacenter.rooms, this.selectedTiles);
-
- this.mapView.updateScene = true;
- }
-
- /**
- * Removes a selected tile (upon being clicked on again).
- *
- * @param position The position at which a selected tile should be removed
- * @param objectIndex The index of the tile in the selectedTileObjects array
- */
- public removeSelectedTile(position: IGridPosition, objectIndex: number): void {
- const index = Util.tileListPositionIndexOf(this.selectedTiles, position);
-
- // Check whether the given position doesn't belong to an already removed tile
- if (index === -1) {
- return;
- }
-
- this.selectedTiles.splice(index, 1);
-
- this.container.removeChild(this.selectedTileObjects[objectIndex].tileObject);
- this.selectedTileObjects.splice(objectIndex, 1);
-
- this.validNextTilePositions = Util.deriveValidNextTilePositions(
- this.mapView.currentDatacenter.rooms, this.selectedTiles);
-
- this.mapView.updateScene = true;
- }
-
- /**
- * Checks whether a hovered tile is in a valid location.
- *
- * @param position The tile location to be checked
- * @returns {boolean} Whether it is a valid location
- */
- public checkHoverTileValidity(position: IGridPosition): boolean {
- if (this.mapView.mapController.interactionLevel === InteractionLevel.BUILDING) {
- if (this.selectedTiles.length === 0) {
- return !Util.checkRoomCollision(this.mapView.currentDatacenter.rooms, position);
- }
- return Util.positionListContainsPosition(this.validNextTilePositions, position);
- } else if (this.mapView.mapController.interactionLevel === InteractionLevel.ROOM) {
- let valid = false;
- this.mapView.mapController.roomModeController.currentRoom.tiles.forEach((element: ITile) => {
- if (position.x === element.position.x && position.y === element.position.y &&
- element.object === undefined) {
- valid = true;
- }
- });
- return valid;
- }
- }
-
- /**
- * Cancels room tile selection by removing all selected tiles from the scene.
- */
- public cancelRoomConstruction(): void {
- if (this.selectedTiles.length === 0) {
- return;
- }
-
- this.selectedTileObjects.forEach((tileObject: TilePositionObject) => {
- this.container.removeChild(tileObject.tileObject);
- });
-
- this.resetTileLists();
-
- this.mapView.updateScene = true;
- }
-
- /**
- * Finalizes the selected room tiles into a standard room.
- */
- public finalizeRoom(room: IRoom): void {
- if (this.selectedTiles.length === 0) {
- return;
- }
-
- this.mapView.currentDatacenter.rooms.push(room);
-
- this.resetTileLists();
-
- // Trigger a redraw
- this.draw();
- this.mapView.wallLayer.generateWalls();
- this.mapView.wallLayer.draw();
-
- this.mapView.updateScene = true;
- }
-
- private resetTileLists(): void {
- this.selectedTiles = [];
- this.validNextTilePositions = [];
- this.selectedTileObjects = [];
- }
-
- public setClickable(value: boolean): void {
- this.allRoomTileObjects.forEach((tileObj: TilePositionObject) => {
- tileObj.tileObject.cursor = value ? "pointer" : "default";
- });
- }
-}
diff --git a/src/scripts/views/layers/roomtext.ts b/src/scripts/views/layers/roomtext.ts
deleted file mode 100644
index 63fab0ed..00000000
--- a/src/scripts/views/layers/roomtext.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import {MapView} from "../mapview";
-import {Colors} from "../../colors";
-import {Util} from "../../util";
-import {Layer} from "./layer";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-export class RoomTextLayer implements Layer {
- private static TEXT_PADDING = 4;
-
- public container: createjs.Container;
-
- private mapView: MapView;
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
-
- this.draw();
- }
-
- public draw(): void {
- this.container.removeAllChildren();
-
- this.mapView.currentDatacenter.rooms.forEach((room: IRoom) => {
- if (room.name !== "" && room.roomType !== "") {
- this.renderTextOverlay(room);
- }
- });
- }
-
- public setVisibility(value: boolean): void {
- this.mapView.animate(this.container, {alpha: value === true ? 1 : 0});
- }
-
- /**
- * Draws a name and type overlay over the given room.
- */
- private renderTextOverlay(room: IRoom): void {
- if (room.name === null || room.tiles.length === 0) {
- return;
- }
-
- const textPos = Util.calculateRoomNamePosition(room);
-
- const bottomY = this.renderText(room.name, "12px Arial", textPos,
- textPos.topLeft.y * CELL_SIZE + RoomTextLayer.TEXT_PADDING);
- this.renderText("Type: " + Util.toSentenceCase(room.roomType), "10px Arial", textPos, bottomY + 5);
- }
-
- private renderText(text: string, font: string, textPos: IRoomNamePos, startY: number): number {
- const name = new createjs.Text(text, font, Colors.ROOM_NAME_COLOR);
-
- if (name.getMeasuredWidth() > textPos.length * CELL_SIZE - RoomTextLayer.TEXT_PADDING * 2) {
- name.scaleX = name.scaleY = (textPos.length * CELL_SIZE - RoomTextLayer.TEXT_PADDING * 2) /
- name.getMeasuredWidth();
- }
-
- // Position the text to the top left of the selected tile
- name.x = textPos.topLeft.x * CELL_SIZE + RoomTextLayer.TEXT_PADDING;
- name.y = startY;
-
- this.container.addChild(name);
-
- return name.y + name.getMeasuredHeight() * name.scaleY;
- }
-}
diff --git a/src/scripts/views/layers/wall.ts b/src/scripts/views/layers/wall.ts
deleted file mode 100644
index 06ba4675..00000000
--- a/src/scripts/views/layers/wall.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import {Colors} from "../../colors";
-import {MapView} from "../mapview";
-import {Util} from "../../util";
-import {Layer} from "./layer";
-import {CELL_SIZE} from "../../controllers/mapcontroller";
-
-
-/**
- * Class responsible for rendering the walls.
- */
-export class WallLayer implements Layer {
- public container: createjs.Container;
-
- private mapView: MapView;
- private walls: IRoomWall[];
- private wallLineWidth: number;
-
-
- constructor(mapView: MapView) {
- this.mapView = mapView;
- this.container = new createjs.Container();
- this.wallLineWidth = CELL_SIZE / 20.0;
-
- this.generateWalls();
- this.draw();
- }
-
- /**
- * Calls the Util.deriveWallLocations function to generate the wall locations.
- */
- public generateWalls(): void {
- this.walls = Util.deriveWallLocations(this.mapView.currentDatacenter.rooms);
- }
-
- /**
- * Draws all walls to the canvas.
- */
- public draw(): void {
- this.container.removeAllChildren();
-
- // Draw walls
- this.walls.forEach((element: IRoomWall) => {
- if (element.horizontal) {
- MapView.drawLine(
- CELL_SIZE * element.startPos[0] - this.wallLineWidth / 2.0,
- CELL_SIZE * element.startPos[1],
- CELL_SIZE * (element.startPos[0] + element.length) + this.wallLineWidth / 2.0,
- CELL_SIZE * element.startPos[1],
- this.wallLineWidth, Colors.WALL_COLOR, this.container
- );
- } else {
- MapView.drawLine(
- CELL_SIZE * element.startPos[0],
- CELL_SIZE * element.startPos[1] - this.wallLineWidth / 2.0,
- CELL_SIZE * element.startPos[0],
- CELL_SIZE * (element.startPos[1] + element.length) + this.wallLineWidth / 2.0,
- this.wallLineWidth, Colors.WALL_COLOR, this.container
- );
- }
- });
- }
-} \ No newline at end of file
diff --git a/src/scripts/views/mapview.ts b/src/scripts/views/mapview.ts
deleted file mode 100644
index 50fc2e45..00000000
--- a/src/scripts/views/mapview.ts
+++ /dev/null
@@ -1,373 +0,0 @@
-///<reference path="../../../typings/globals/createjs-lib/index.d.ts" />
-///<reference path="../../../typings/globals/easeljs/index.d.ts" />
-///<reference path="../../../typings/globals/tweenjs/index.d.ts" />
-///<reference path="../../../typings/globals/preloadjs/index.d.ts" />
-///<reference path="../definitions.ts" />
-///<reference path="../controllers/mapcontroller.ts" />
-import * as $ from "jquery";
-import {Util} from "../util";
-import {MapController, CELL_SIZE} from "../controllers/mapcontroller";
-import {GridLayer} from "./layers/grid";
-import {RoomLayer} from "./layers/room";
-import {HoverLayer} from "./layers/hover";
-import {WallLayer} from "./layers/wall";
-import {DCObjectLayer} from "./layers/dcobject";
-import {GrayLayer} from "./layers/gray";
-import {RoomTextLayer} from "./layers/roomtext";
-
-
-/**
- * Class responsible for rendering the map, by delegating the rendering tasks to appropriate instances.
- */
-export class MapView {
- public static MAP_SIZE = 100;
- public static CELL_SIZE_METERS = 0.5;
- public static MIN_ZOOM = 0.5;
- public static DEFAULT_ZOOM = 2;
- public static MAX_ZOOM = 6;
- public static GAP_CORRECTION_DELTA = 0.2;
- public static ANIMATION_LENGTH = 250;
-
- // Models
- public simulation: ISimulation;
- public currentDatacenter: IDatacenter;
-
- // Controllers
- public mapController: MapController;
-
- // Canvas objects
- public stage: createjs.Stage;
- public mapContainer: createjs.Container;
-
- // Flag indicating whether the scene should be redrawn
- public updateScene: boolean;
- public animating: boolean;
-
- // Subviews
- public gridLayer: GridLayer;
- public roomLayer: RoomLayer;
- public dcObjectLayer: DCObjectLayer;
- public roomTextLayer: RoomTextLayer;
- public hoverLayer: HoverLayer;
- public wallLayer: WallLayer;
- public grayLayer: GrayLayer;
-
- // Dynamic canvas attributes
- public canvasWidth: number;
- public canvasHeight: number;
-
-
- /**
- * Draws a line from (x1, y1) to (x2, y2).
- *
- * @param x1 The x coord. of start point
- * @param y1 The y coord. of start point
- * @param x2 The x coord. of end point
- * @param y2 The y coord. of end point
- * @param lineWidth The width of the line to be drawn
- * @param color The color to be used
- * @param container The container to be drawn to
- */
- public static drawLine(x1: number, y1: number, x2: number, y2: number,
- lineWidth: number, color: string, container: createjs.Container): createjs.Shape {
- const line = new createjs.Shape();
- line.graphics.setStrokeStyle(lineWidth).beginStroke(color);
- line.graphics.moveTo(x1, y1);
- line.graphics.lineTo(x2, y2);
- container.addChild(line);
- return line;
- }
-
- /**
- * Draws a tile at the given location with the given color.
- *
- * @param position The grid coordinates of the tile
- * @param color The color with which the rectangle should be drawn
- * @param container The container to be drawn to
- * @param sizeX Optional parameter specifying the width of the tile to be drawn (in grid units)
- * @param sizeY Optional parameter specifying the height of the tile to be drawn (in grid units)
- */
- public static drawRectangle(position: IGridPosition, color: string, container: createjs.Container,
- sizeX?: number, sizeY?: number): createjs.Shape {
- const tile = new createjs.Shape();
- tile.graphics.setStrokeStyle(0);
- tile.graphics.beginFill(color);
- tile.graphics.drawRect(
- position.x * CELL_SIZE - MapView.GAP_CORRECTION_DELTA,
- position.y * CELL_SIZE - MapView.GAP_CORRECTION_DELTA,
- CELL_SIZE * (sizeX === undefined ? 1 : sizeX) + MapView.GAP_CORRECTION_DELTA * 2,
- CELL_SIZE * (sizeY === undefined ? 1 : sizeY) + MapView.GAP_CORRECTION_DELTA * 2
- );
- container.addChild(tile);
- return tile;
- }
-
- /**
- * Draws a tile at the given location with the given color, and add it to the given shape object.
- *
- * The fill color must be set beforehand, in order to not set it repeatedly and produce unwanted transparent overlap
- * artifacts.
- *
- * @param position The grid coordinates of the tile
- * @param shape The shape to be drawn to
- * @param sizeX Optional parameter specifying the width of the tile to be drawn (in grid units)
- * @param sizeY Optional parameter specifying the height of the tile to be drawn (in grid units)
- */
- public static drawRectangleToShape(position: IGridPosition, shape: createjs.Shape,
- sizeX?: number, sizeY?: number) {
- shape.graphics.drawRect(
- position.x * CELL_SIZE - MapView.GAP_CORRECTION_DELTA,
- position.y * CELL_SIZE - MapView.GAP_CORRECTION_DELTA,
- CELL_SIZE * (sizeX === undefined ? 1 : sizeX) + MapView.GAP_CORRECTION_DELTA * 2,
- CELL_SIZE * (sizeY === undefined ? 1 : sizeY) + MapView.GAP_CORRECTION_DELTA * 2
- );
- }
-
- constructor(simulation: ISimulation, stage: createjs.Stage) {
- this.simulation = simulation;
- const path = this.simulation.paths[this.simulation.paths.length - 1];
- this.currentDatacenter = path.sections[path.sections.length - 1].datacenter;
-
- this.stage = stage;
-
- console.log("THE DATA", simulation);
-
- const canvas = $("#main-canvas");
- this.canvasWidth = canvas.width();
- this.canvasHeight = canvas.height();
-
- this.mapContainer = new createjs.Container();
-
- this.initializeLayers();
-
- this.drawMap();
- this.updateScene = true;
- this.animating = false;
-
- this.mapController = new MapController(this);
-
- // Zoom DC to fit, if rooms are present
- if (this.currentDatacenter.rooms.length > 0) {
- this.zoomOutOnDC();
- }
-
- // Checks at every rendering tick whether the scene has changed, and updates accordingly
- createjs.Ticker.addEventListener("tick", (event: createjs.TickerEvent) => {
- if (this.updateScene || this.animating) {
- if (this.mapController.isInHoverMode()) {
- this.hoverLayer.draw();
- }
-
- this.updateScene = false;
- this.stage.update(event);
- }
- });
- }
-
- private initializeLayers(): void {
- this.gridLayer = new GridLayer(this);
- this.roomLayer = new RoomLayer(this);
- this.dcObjectLayer = new DCObjectLayer(this);
- this.roomTextLayer = new RoomTextLayer(this);
- this.hoverLayer = new HoverLayer(this);
- this.wallLayer = new WallLayer(this);
- this.grayLayer = new GrayLayer(this);
- }
-
- /**
- * Triggers a redraw and re-population action on all layers.
- */
- public redrawMap(): void {
- this.gridLayer.draw();
- this.roomLayer.draw();
- this.dcObjectLayer.populateObjectList();
- this.dcObjectLayer.draw();
- this.roomTextLayer.draw();
- this.hoverLayer.initialDraw();
- this.wallLayer.generateWalls();
- this.wallLayer.draw();
- this.grayLayer.draw(true);
- this.updateScene = true;
- }
-
- /**
- * Zooms in on a given position with a given amount.
- *
- * @param position The position that should appear centered after the zoom action
- * @param amount The amount of zooming that should be performed
- */
- public zoom(position: number[], amount: number): void {
- const newZoom = this.mapContainer.scaleX + 0.01 * amount;
-
- // Check whether zooming too far in / out
- if (newZoom > MapView.MAX_ZOOM ||
- newZoom < MapView.MIN_ZOOM) {
- return;
- }
-
- // Calculate position difference if zoomed, in order to later compensate for this
- // unwanted movement
- const oldPosition = [
- position[0] - this.mapContainer.x, position[1] - this.mapContainer.y
- ];
- const newPosition = [
- (oldPosition[0] / this.mapContainer.scaleX) * newZoom,
- (oldPosition[1] / this.mapContainer.scaleX) * newZoom
- ];
- const positionDelta = [
- newPosition[0] - oldPosition[0], newPosition[1] - oldPosition[1]
- ];
-
- // Apply the transformation operation to keep the selected position static
- const newX = this.mapContainer.x - positionDelta[0];
- const newY = this.mapContainer.y - positionDelta[1];
-
- const finalPos = this.mapController.checkCanvasMovement(newX, newY, newZoom);
-
- if (!this.animating) {
- this.animate(this.mapContainer, {
- scaleX: newZoom, scaleY: newZoom,
- x: finalPos.x, y: finalPos.y
- });
- }
- }
-
- /**
- * Adjusts the viewing scale to fully display a selected room and center it in view.
- *
- * @param room The room to be centered
- * @param redraw Optional argument specifying whether this is a scene redraw
- */
- public zoomInOnRoom(room: IRoom, redraw?: boolean): void {
- this.zoomInOnRooms([room]);
-
- if (redraw === undefined || redraw === false) {
- if (!this.grayLayer.isGrayedOut()) {
- this.grayLayer.currentRoom = room;
- this.grayLayer.draw();
- }
- }
-
- this.updateScene = true;
- }
-
- /**
- * Zooms out to global building view.
- */
- public zoomOutOnDC(): void {
- this.grayLayer.clear();
-
- if (this.currentDatacenter.rooms.length > 0) {
- this.zoomInOnRooms(this.currentDatacenter.rooms);
- }
-
- this.updateScene = true;
- }
-
- /**
- * Fits a given list of rooms to view, by scaling the viewport appropriately and moving the mapContainer.
- *
- * @param rooms The array of rooms to be viewed
- */
- private zoomInOnRooms(rooms: IRoom[]): void {
- const bounds = Util.calculateRoomListBounds(rooms);
- const newScale = this.calculateNewScale(bounds);
-
- // Coordinates of the center of the room, relative to the global origin of the map
- const roomCenterCoords = [
- bounds.center[0] * CELL_SIZE * newScale,
- bounds.center[1] * CELL_SIZE * newScale
- ];
- // Coordinates of the center of the stage (the visible part of the canvas), relative to the global map origin
- const stageCenterCoords = [
- -this.mapContainer.x + this.canvasWidth / 2,
- -this.mapContainer.y + this.canvasHeight / 2
- ];
-
- const newX = this.mapContainer.x - roomCenterCoords[0] + stageCenterCoords[0];
- const newY = this.mapContainer.y - roomCenterCoords[1] + stageCenterCoords[1];
-
- const newPosition = this.mapController.checkCanvasMovement(newX, newY, newScale);
-
- this.animate(this.mapContainer, {
- scaleX: newScale, scaleY: newScale,
- x: newPosition.x, y: newPosition.y
- });
- }
-
- private calculateNewScale(bounds: IBounds): number {
- const viewPadding = 30;
- const sideMenuWidth = 350;
-
- const width = bounds.max[0] - bounds.min[0];
- const height = bounds.max[1] - bounds.min[1];
-
- const scaleX = (this.canvasWidth - 2 * sideMenuWidth) / (width * CELL_SIZE + 2 * viewPadding);
- const scaleY = this.canvasHeight / (height * CELL_SIZE + 2 * viewPadding);
-
- let newScale = Math.min(scaleX, scaleY);
-
- if (this.mapContainer.scaleX > MapView.MAX_ZOOM) {
- newScale = MapView.MAX_ZOOM;
- } else if (this.mapContainer.scaleX < MapView.MIN_ZOOM) {
- newScale = MapView.MIN_ZOOM;
- }
-
- return newScale;
- }
-
- /**
- * Draws all tiles contained in the MapModel.
- */
- private drawMap(): void {
- // Create and draw the container for the entire map
- const gridPixelSize = CELL_SIZE * MapView.MAP_SIZE;
-
- // Add a white background to the entire container
- const background = new createjs.Shape();
- background.graphics.beginFill("#fff");
- background.graphics.drawRect(0, 0,
- gridPixelSize, gridPixelSize);
- this.mapContainer.addChild(background);
-
- this.stage.addChild(this.mapContainer);
-
- // Set the map container to a default offset and zoom state (overridden if rooms are present)
- this.mapContainer.x = -50;
- this.mapContainer.y = -50;
- this.mapContainer.scaleX = this.mapContainer.scaleY = MapView.DEFAULT_ZOOM;
-
- this.addLayerContainers();
- }
-
- private addLayerContainers(): void {
- this.mapContainer.addChild(this.gridLayer.container);
- this.mapContainer.addChild(this.roomLayer.container);
- this.mapContainer.addChild(this.dcObjectLayer.container);
- this.mapContainer.addChild(this.roomTextLayer.container);
- this.mapContainer.addChild(this.hoverLayer.container);
- this.mapContainer.addChild(this.wallLayer.container);
- this.mapContainer.addChild(this.grayLayer.container);
- }
-
- /**
- * Wrapper function for TweenJS animate functionality.
- *
- * @param target What to animate
- * @param properties Properties to be passed on to TweenJS
- * @param callback To be called when animation ready
- */
- public animate(target: any, properties: any, callback?: () => any): void {
- this.animating = true;
- createjs.Tween.get(target)
- .to(properties, MapView.ANIMATION_LENGTH, createjs.Ease.getPowInOut(4))
- .call(() => {
- this.animating = false;
- this.updateScene = true;
-
- if (callback !== undefined) {
- callback();
- }
- });
- }
-}
diff --git a/src/styles/404.less b/src/styles/404.less
deleted file mode 100644
index 8842b621..00000000
--- a/src/styles/404.less
+++ /dev/null
@@ -1,147 +0,0 @@
-html, body {
- padding: 0;
- margin: 0;
- width: 100%;
- height: 100%;
-
- background-image: linear-gradient(135deg, #00678a, #008fbf, #00A6D6);
-}
-
-.terminal-window {
- width: 600px;
- height: 400px;
- display: block;
-
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-
- margin: auto;
-
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- cursor: default;
-
- overflow: hidden;
-
- box-shadow: 5px 5px 20px #444444;
-}
-
-.terminal-header {
- font-family: monospace;
- background: #cccccc;
- color: #444444;
- height: 30px;
- line-height: 30px;
- padding-left: 10px;
-
- border-top-left-radius: 7px;
- border-top-right-radius: 7px;
-}
-
-.terminal-body {
- font-family: monospace;
- text-align: center;
- background-color: #333333;
- color: #eeeeee;
- padding: 10px;
-
- height: 100%;
-}
-
-.segfault {
- text-align: left;
-}
-
-.cursor {
- -webkit-animation: 1s blink step-end infinite;
- -moz-animation: 1s blink step-end infinite;
- -ms-animation: 1s blink step-end infinite;
- -o-animation: 1s blink step-end infinite;
- animation: 1s blink step-end infinite;
-}
-
-.code-block {
- white-space: pre-wrap;
-
- margin-top: 60px;
-}
-
-.sub-title {
- margin-top: 20px;
-}
-
-.home-btn {
- margin-top: 10px;
- padding: 5px;
- display: inline-block;
- border: 1px solid #eeeeee;
- color: #eeeeee;
- text-decoration: none;
- cursor: pointer;
-
- -webkit-transition: all 200ms;
- -moz-transition: all 200ms;
- -ms-transition: all 200ms;
- -o-transition: all 200ms;
- transition: all 200ms;
-}
-
-.home-btn:hover {
- background: #eeeeee;
- color: #333333;
-}
-
-.home-btn:active {
- background: #333333;
- color: #eeeeee;
-}
-
-@keyframes blink {
- from, to {
- color: #eeeeee;
- }
- 50% {
- color: #333333;
- }
-}
-
-@-moz-keyframes blink {
- from, to {
- color: #eeeeee;
- }
- 50% {
- color: #333333;
- }
-}
-
-@-webkit-keyframes blink {
- from, to {
- color: #eeeeee;
- }
- 50% {
- color: #333333;
- }
-}
-
-@-ms-keyframes blink {
- from, to {
- color: #eeeeee;
- }
- 50% {
- color: #333333;
- }
-}
-
-@-o-keyframes blink {
- from, to {
- color: #eeeeee;
- }
- 50% {
- color: #333333;
- }
-} \ No newline at end of file
diff --git a/src/styles/main.less b/src/styles/main.less
deleted file mode 100644
index ee7e56aa..00000000
--- a/src/styles/main.less
+++ /dev/null
@@ -1,1196 +0,0 @@
-/* Colors */
-@gray-dark: #aaa;
-@gray-semi-dark: #bbb;
-@gray-semi-light: #ccc;
-@gray-light: #ddd;
-@gray-very-light: #eee;
-@blue: #00A6D6;
-@blue-dark: #0087b5;
-@blue-very-dark: #006182;
-@blue-light: #deebf7;
-
-/* Sizes, Margins and Paddings*/
-@document-padding: 20px;
-@inter-element-margin: 5px;
-@standard-border-radius: 5px;
-@side-menu-width: 350px;
-@color-indicator-width: 140px;
-
-@global-padding: 30px;
-@transition-length: 150ms;
-@side-bar-width: 250px;
-@navbar-height: 50px;
-
-html, body {
- width: 100%;
- height: 100%;
- margin: 0;
-
- font-family: Helvetica, Verdana, sans-serif;
-
- overflow: hidden;
-
- background: #eee;
-}
-
-a:hover {
- text-decoration: none;
-}
-
-#main-canvas {
- float: left;
-}
-
-.app-content {
- position: relative;
- width: 100%;
- height: 100%;
-
- z-index: 1;
-}
-
-/* Mixin for cross-platform prevention of user-text-selection */
-.user-select-def {
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-/* Mixin for cross-platform transitions */
-.transition-def(@property, @time) {
- -webkit-transition: @property @time;
- -moz-transition: @property @time;
- -ms-transition: @property @time;
- -o-transition: @property @time;
- transition: @property @time;
-}
-
-/* Mixin for cross-platform border-radius properties */
-.border-radius-def(@length) {
- -webkit-border-radius: @length;
- -moz-border-radius: @length;
- border-radius: @length;
-}
-
-/* General Button Abstractions */
-.clickable {
- cursor: pointer;
- .user-select-def;
-}
-
-.button {
- text-align: center;
- padding: 5px;
-
- background-color: @gray-semi-dark;
-
- .border-radius-def(@standard-border-radius);
- .clickable;
-
- .transition-def(all, 200ms);
-}
-
-.button:hover {
- background-color: @gray-semi-light;
-}
-
-.button:active {
- background-color: @gray-dark;
-}
-
-/* Container for menu panels */
-.side-menu-container {
- display: inline-block;
- position: absolute;
- top: @document-padding;
- width: @side-menu-width;
- height: calc(100% - @document-padding);
- margin-top: 10px;
-
- pointer-events: none;
-}
-
-.left-side {
- left: @document-padding;
-}
-
-.right-side {
- right: @document-padding;
-}
-
-.right-middle-side {
- right: @document-padding * 2 + @side-menu-width;
-}
-
-/* Collapsible menu panel */
-.menu-container {
- margin-bottom: 10px;
- border: 1px solid @gray-dark;
-
- -webkit-border-radius: @standard-border-radius;
- -moz-border-radius: @standard-border-radius;
- border-radius: @standard-border-radius;
-
- overflow: hidden;
- pointer-events: all;
-}
-
-.menu-header-bar {
- display: block;
- padding: 5px;
-
- font-weight: bold;
-
- background-color: @gray-semi-light;
- border-bottom-width: 0;
-}
-
-.menu-body {
- display: block;
- padding: 10px 5px;
-
- background-color: @gray-very-light;
-
- .dropdown {
- margin: @inter-element-margin 0;
- display: inline-block;
- }
-
- .dropdown-label {
- display: inline-block;
- margin-right: 10px;
- }
-}
-
-.menu-body.simulation {
- display: none;
-}
-
-.side-menu-container .menu-collapse, .side-menu-container .menu-exit {
- display: inline-block;
- float: right;
- width: 20px;
- height: 20px;
-
- text-align: center;
- line-height: 20px;
- padding: 0;
- font-size: 9pt;
-
- color: #777;
-}
-
-#room-menu {
- .input-group {
- margin-bottom: 5px;
- }
-
- label {
- margin-top: 10px;
- }
-}
-
-#room-construction-cancel {
- display: none;
-}
-
-/* DC components */
-.dc-component-container {
- .border-radius-def(@standard-border-radius);
-
- margin-bottom: @inter-element-margin;
- padding: 10px;
-
- cursor: pointer;
-
- .transition-def(background-color, 150ms);
-
- .dc-component {
- display: inline-block;
- width: 50px;
- height: 50px;
- float: left;
-
- border: 4px solid #000;
- }
-
- .dc-component-label {
- display: inline-block;
- padding-left: 20px;
- line-height: 50px;
- font-size: 1.3em;
- }
-}
-
-.dc-component-container:hover {
- background-color: @gray-semi-dark;
-}
-
-.dc-component-container:active {
- background-color: @blue-dark;
-}
-
-.dc-component-container[data-active="true"] {
- background-color: @blue;
-}
-
-/* DC Object colors */
-.dc-rack {
- background-color: rgb(170, 170, 170);
-}
-
-.dc-psu {
- background-color: rgb(230, 50, 60);
-}
-
-.dc-cooling-item {
- background-color: rgb(40, 50, 230);
-}
-
-/* Rack menu */
-.node-list-container {
- border: 2px solid #000000;
- overflow: auto;
- max-height: 300px;
-
- margin: @inter-element-margin 0;
- padding: 0;
- @node-height: 50px;
-
- .node-element {
- position: relative;
-
- @img-size: 34px;
- height: @node-height;
- cursor: hand;
-
- background-color: @gray-semi-light;
-
- .node-element-btn {
- display: inline-block;
- float: left;
- width: 40px;
- height: @node-height - 1px;
-
- color: #000;
-
- line-height: @node-height - 1px;
- text-align: center;
- }
-
- .node-element-btn:hover {
- text-decoration: none;
- }
-
- .node-element-content {
- @element-padding-top: 2px;
- @element-padding-left: 12px;
- @img-margin: 7px;
-
- position: relative;
-
- display: inline-flex;
- overflow: hidden;
- margin: 5px;
- padding: @element-padding-top @element-padding-left;
-
- border: 1px solid #000;
- background: #eeeeee;
-
- img {
- width: @img-size;
- height: @img-size;
- }
-
- img:not(:last-of-type) {
- margin-right: @img-margin;
- }
-
- .icon-overlay {
- position: absolute;
- top: @element-padding-top;
- width: @img-size;
- height: @img-size;
-
- background: #eeeeee;
- opacity: 0.6;
- }
-
- .overlay-cpu {
- left: @element-padding-left;
- }
-
- .overlay-gpu {
- left: @element-padding-left + @img-size + @img-margin;
- }
-
- .overlay-memory {
- left: @element-padding-left + (@img-size + @img-margin) * 2;
- }
-
- .overlay-storage {
- left: @element-padding-left + (@img-size + @img-margin) * 3;
- }
-
- .overlay-network {
- left: @element-padding-left + (@img-size + @img-margin) * 4;
- }
- }
-
- .node-element-number {
- display: inline-block;
- float: right;
- width: 30px;
- height: 100%;
-
- line-height: 50px;
- text-align: right;
- padding-right: 10px;
- }
- }
-
- .node-element:not(:last-of-type) {
- border-bottom: 1px solid #666;
- }
-
- .node-element:last-of-type .node-element-content {
- margin-bottom: 0;
- }
-
- .node-element-overlay {
- position: absolute;
- top: 0;
- left: 0;
-
- width: 100%;
- height: @node-height;
-
- background: #eeeeee;
- opacity: 0.6;
-
- z-index: 100;
- }
-}
-
-#node-menu {
- .nav-tabs {
- li.active, li.active a {
- background-color: @gray-very-light;
- }
-
- img {
- width: 30px;
- height: 30px;
- }
- }
-
- .tab-content {
- overflow: hidden;
-
- .panel-heading .accordion-toggle:after {
- //noinspection CssNoGenericFontName
- font-family: 'Glyphicons Halflings';
- content: "\e114";
- float: right;
- color: grey;
- }
-
- .panel-heading .accordion-toggle.collapsed:after {
- content: "\e080";
- }
- }
-
- .remove-unit:hover {
- text-decoration: none;
- }
-
- .unit-add-input {
- margin-bottom: 10px;
- }
-
- .spec-table td {
- height: 40px;
- line-height: 40px;
- padding: 0 10px;
- }
-
- .spec-table tr td:first-child {
- width: 50px;
- text-align: right;
- }
-
- .spec-table tr td:nth-child(2) {
- width: 200px;
- }
-
- .spec-table tr td:nth-child(3) {
- width: 50px;
- }
-}
-
-/* Tasks menu */
-#tasks-menu .menu-body {
- overflow-y: auto;
- max-height: 350px;
-}
-
-#tasks-menu .menu-body .task-element {
- height: 70px;
-
- .task-icon {
- @icon-size: 35px;
-
- display: inline-block;
- position: relative;
- float: left;
-
- top: 13px;
- left: 10px;
-
- width: @icon-size;
- height: @icon-size;
- font-size: @icon-size;
-
- }
-
- .task-info {
- display: inline-block;
- width: 270px;
- float: right;
-
- .task-time {
- display: block;
- }
-
- .progress {
- margin-bottom: 0;
- }
-
- .task-flops {
- display: block;
- }
- }
-
- &:not(:last-child) {
- border-bottom: 1px solid #bbb;
- margin-bottom: 10px;
- }
-}
-
-#statistics-chart, #machine-statistics-chart {
- display: block;
- height: 200px;
- margin-right: 15px;
-}
-
-/* Container for Zooming buttons */
-.tool-panel {
- display: inline-block;
- position: absolute;
- bottom: @document-padding;
- left: @document-padding;
-
- z-index: 1000;
-}
-
-.btn-circle {
- width: 30px;
- height: 30px;
- text-align: center;
- padding: 6px 0;
- font-size: 12px;
- line-height: 1.428571429;
- border-radius: 15px;
-
- border-color: @gray-dark;
-}
-
-/* Indicators*/
-.indicators {
- display: inline-block;
- position: absolute;
- bottom: @document-padding;
- right: @document-padding;
-}
-
-/* Scale indicator */
-.scale-indicator {
- display: inline-block;
- width: 100px;
- height: 18px;
- line-height: 18px;
-
- text-align: right;
-
- border-top-width: 0;
- border-right-width: 0;
- border-bottom: 2px solid #000;
- border-left: 2px solid #000;
-
- .user-select-def;
-}
-
-/* Color indicator */
-.color-indicator {
- @color-indicator-padding: 7px;
- @element-width: (@color-indicator-width - @color-indicator-padding * 2) / 4;
-
- display: inline-block;
- position: relative;
- top: 5px;
- margin-left: 15px;
- cursor: pointer;
- padding: @color-indicator-padding;
- .border-radius-def(@standard-border-radius);
- .transition-def(background, @transition-length);
- z-index: 100;
-
- width: @color-indicator-width;
-
- &:hover {
- background: rgba(127, 127, 127, 0.5);
- }
-
- .intensity-labels {
- height: 20px;
- line-height: 20px;
-
- font-size: 8pt;
-
- div {
- display: inline-block;
- width: @element-width;
- margin-right: -3px;
-
- text-align: center;
- }
-
- div:first-of-type {
- width: @element-width / 2;
- text-align: left;
- }
-
- div:last-of-type {
- width: @element-width / 2;
- text-align: right;
- }
- }
-
- .intensity-colors {
- height: 15px;
-
- div {
- display: inline-block;
- width: @element-width + 1;
- height: 100%;
- margin-right: -5px;
- border: 1px solid #444;
- }
-
- .intensity-low {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
- background: rgba(197, 224, 180, 1);
- }
-
- .intensity-mid-low {
- background: rgba(255, 230, 153, 1);
- }
-
- .intensity-mid-high {
- background: rgba(248, 203, 173, 1);
- }
-
- .intensity-high {
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
- background: rgba(249, 165, 165, 1);
- }
- }
-}
-
-@global-control-height: 40px;
-
-/* Mode switch */
-.mode-switch {
- display: block;
- width: 100%;
- height: @global-control-height;
- line-height: @global-control-height;
-
- margin-bottom: 10px;
- pointer-events: all;
-
- background-color: #fff;
- border: 1px solid @gray-dark;
- .border-radius-def(@standard-border-radius);
- overflow: hidden;
-
- div {
- display: inline-block;
- width: 50%;
- height: 100%;
- text-align: center;
-
- font-size: 1.2em;
- .clickable;
- }
-
- div:first-child {
- float: left;
- }
-
- div:last-child {
- float: right;
- }
-}
-
-#save-version-btn {
- width: 50%;
- height: @global-control-height;
- line-height: @global-control-height;
- text-align: center;
- margin-bottom: 10px;
- font-size: 1.2em;
- color: #fff;
-
- .clickable;
- pointer-events: all;
- .border-radius-def(@standard-border-radius);
-}
-
-#save-version-btn[data-saved="true"] {
- background-color: #4dba31;
-
- &:hover {
- background: #3b8e25;
- }
-}
-
-#save-version-btn[data-saved="false"] {
- background-color: #d69931;
-
- &:hover {
- background: #af7b2d;
- }
-}
-
-.mode-switch[data-selected="construction"] {
- #construction-mode-switch {
- background: @blue;
- color: #fff;
- }
-
- #construction-mode-switch:hover {
- background: @blue-dark;
- }
-
- #simulation-mode-switch {
- background: #fff;
- color: #000;
- }
-
- #simulation-mode-switch:hover {
- background: #eee;
- }
-}
-
-.mode-switch[data-selected="simulation"] {
- #construction-mode-switch {
- background: #fff;
- color: #000;
- }
-
- #construction-mode-switch:hover {
- background: #eee;
- }
-
- #simulation-mode-switch {
- background: @blue;
- color: #fff;
- }
-
- #simulation-mode-switch:hover {
- background: @blue-dark;
- }
-}
-
-#experiment-menu h2 {
- margin-top: 0;
- font-size: 12pt;
-}
-
-/* Timeline controls */
-.timeline-bar {
- display: block;
- position: absolute;
- left: 0;
- bottom: @document-padding;
- width: 100%;
- text-align: center;
-}
-
-.timeline-container {
- @container-size: 500px;
- @play-btn-size: 40px;
- @border-width: 1px;
- @timeline-border: @border-width solid @gray-semi-dark;
-
- display: inline-block;
- margin: 0 auto;
- text-align: left;
-
- width: @container-size;
-
- .labels {
- display: block;
- height: 25px;
- line-height: 25px;
-
- div {
- display: inline-block;
- }
-
- .start-time-label {
- margin-left: @play-btn-size - @border-width;
- padding-left: 4px;
- }
-
- .end-time-label {
- padding-right: 4px;
- float: right;
- }
- }
-
- .controls {
- display: flex;
- border: @timeline-border;
- overflow: hidden;
-
- // Fix for border-radius overflow in Chrome/Webkit
- -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
-
- .border-radius-def(@standard-border-radius);
-
- .play-btn {
- width: @play-btn-size;
- height: @play-btn-size + @border-width;
- line-height: @play-btn-size + @border-width;
- text-align: center;
- float: left;
-
- margin-top: -@border-width;
-
- font-size: 16pt;
- background: #333;
- color: #eee;
-
- .transition-def(background, @transition-length);
-
- .user-select-def;
- .clickable;
-
- // Loading icon
- img {
- display: none;
- position: relative;
- width: 70%;
- height: 70%;
- margin-top: -10px;
- }
- }
-
- .play-btn::before {
- position: relative;
- top: -1px;
- left: 1px;
- }
-
- .play-btn:hover {
- background: #656565;
- }
-
- .play-btn:active {
- background: #000;
- }
-
- .timeline {
- position: relative;
- flex: 1;
- height: @play-btn-size;
- line-height: @play-btn-size;
- float: right;
-
- background: @blue-light;
-
- z-index: 500;
-
- div {
- .transition-def(all, @transition-length);
- }
-
- .time-marker {
- position: absolute;
- top: 0;
- left: 0;
-
- width: 6px;
- height: 100%;
-
- background: @blue-very-dark;
-
- .border-radius-def(2px);
-
- z-index: 503;
- }
-
- .section-marker {
- position: absolute;
- top: 0;
- left: 0;
-
- width: 3px;
- height: 100%;
-
- background: #222222;
-
- z-index: 504;
- }
-
- .cache-section {
- position: absolute;
- top: 0;
- left: 0;
-
- width: 0;
- height: 100%;
-
- background: @blue;
-
- z-index: 501;
- }
-
- .task-indicator {
- display: inline-block;
- position: absolute;
- bottom: 0;
- width: 10px;
- height: 10px;
-
- border: 1px solid #000;
-
- z-index: 502;
- }
-
- .task-queued {
- background: #fff340;
- }
-
- .task-started {
- background: #ff72a0;
- }
-
- .task-finished {
- background: #c036ff;
- }
- }
- }
-}
-
-/* Informational message container, for communicating events to the user */
-.info-balloon {
- display: none;
- position: absolute;
- bottom: @document-padding;
- right: @document-padding;
-
- padding-left: 15px;
- padding-right: 15px;
-
- height: 30px;
- line-height: 30px;
-
- background: @blue;
- color: #fff;
-
- .border-radius-def(15px);
-
- span {
- line-height: 30px;
- margin-right: 10px;
- }
-}
-
-/* Loading overlay, shown during setup */
-.loading-overlay {
- z-index: 1000;
- position: absolute;
- width: 100%;
- height: 100%;
-
- background: rgba(0, 124, 159, 0.7);
-
- .loading-overlay-content {
- text-align: center;
- display: inline-block;
-
- width: 300px;
- height: 200px;
-
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-
- margin: auto;
-
- img {
- position: relative;
- bottom: -10px;
-
- animation: bounce 3s ease infinite;
- }
-
- .loading-text {
- padding: 3px 10px;
- background-color: #eeeeee;
- .border-radius-def(@standard-border-radius);
- }
- }
-}
-
-@keyframes bounce {
- 0% {
- bottom: -10px;
- }
- 50% {
- bottom: 40px;
- }
- 100% {
- bottom: -10px;
- }
-}
-
-/* Experiments */
-.experiment-list {
- display: block;
- font-size: 12pt;
- border: 0;
-
- .list-head, .list-body .experiment-row {
- display: block;
- position: relative;
- }
-
- .list-head div, .list-body .project-row div {
- padding: 0 10px;
- display: inline-block;
- }
-
- .list-head {
- font-weight: bold;
- }
-
- .list-body {
- max-height: 200px;
- overflow-y: auto;
- overflow-x: hidden;
- }
-
- .experiment-row {
- background: #f8f8f8;
- border: 1px solid #b6b6b6;
- height: 40px;
- line-height: 40px;
- clear: both;
-
- .transition-def(background, @transition-length);
- .clickable;
- }
-
- .experiment-row:hover {
- background: #fff;
- }
-
- .experiment-row:active {
- background: #cccccc;
- }
-
- .experiment-row:not(:first-of-type) {
- margin-top: -1px;
- }
-
- // Sizing of table columns
- .experiment-row, .list-head {
- div {
- display: inline-block;
- width: 20%;
-
- padding-left: 5px;
- margin-right: -4px; // Address default margin between inline-blocks
- }
-
- div:last-of-type {
- text-align: right;
- padding-right: 10px;
- }
- }
-}
-
-.no-experiments-alert {
- display: none;
- position: relative;
- padding-left: 50px;
- span {
- position: absolute;
- top: 11px;
- left: 10px;
- bottom: 10px;
- font-size: 20pt;
- }
-}
-
-.window-overlay {
- display: none;
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
-
- background: rgba(0, 0, 0, 0.5);
-
- z-index: 5000;
-}
-
-.experiments-window {
- width: 80%;
- height: 80%;
-
- position: absolute;
- left: 0;
- top: 0;
- bottom: 0;
- right: 0;
- margin: auto;
-
- overflow: hidden;
-
- .window-body {
- width: 100%;
- height: 500px;
-
- padding: 10px;
-
- background: rgba(230, 230, 230, 0.9);
-
- .border-radius-def(5px);
-
- .window-heading {
- font-size: 20pt;
- color: #000000;
-
- .user-select-def;
-
- font-weight: bold;
-
- padding-left: 5px;
- }
-
- .experiment-add-form {
- margin: 20px;
-
- input, select {
- width: 200px;
- }
-
- label {
- width: 80px;
- text-align: right;
-
- .user-select-def;
- }
- }
-
- .experiments-table-label {
- display: block;
- padding-left: 20px;
- margin-bottom: 5px;
-
- font-size: 18px;
-
- .user-select-def;
- }
-
- .experiment-name-alert {
- position: absolute;
- bottom: 0;
- left: 20px;
- display: none;
- }
- }
-
- .window-footer {
- width: 100%;
- height: 60px;
-
- background: rgba(56, 56, 56, 0.9);
-
- padding: 12px 10px;
-
- .btn.pull-left {
- margin-right: 5px;
- }
-
- .btn.pull-right {
- margin-left: 5px;
- }
- }
-}
-
-.window-close {
- display: inline-block;
- font-size: 16pt;
- position: absolute;
- top: 10px;
- right: 10px;
- cursor: pointer;
- color: #888888;
-}
-
-/* Internal page */
-/* Main content body (side-menu and main-body) */
-.content {
- position: relative;
- top: -@navbar-height;
- width: 100%;
- height: 100%;
- padding-top: @navbar-height;
- z-index: 1;
-}
-
-/* Content body */
-.main-body {
- position: relative;
- display: block;
- margin: auto;
- width: 900px;
- max-width: 900px;
- height: 100%;
- padding: 40px;
-
- border-left: 1px solid #bbb;
- border-right: 1px solid #bbb;
- background: #f7f7f7;
-
- h2 {
- font-weight: bold;
- margin: 10px 0 20px 0;
- }
-}
-
-.modal {
- z-index: 10000;
-}
diff --git a/src/styles/navbar.less b/src/styles/navbar.less
deleted file mode 100644
index 3eba0982..00000000
--- a/src/styles/navbar.less
+++ /dev/null
@@ -1,158 +0,0 @@
-@import "main.less";
-
-/* Navbar */
-.top-navbar {
- @navbar-padding: 10px;
-
- position: relative;
- display: block;
- width: 100%;
- height: @navbar-height;
-
- color: #eee;
- background: #343434;
-
- z-index: 100;
-
- -webkit-box-shadow: -10px 8px 3px 12px #000;
- -moz-box-shadow: -10px 8px 3px 12px #000;
- box-shadow: -10px -10px 3px 12px #000;
-
- .opendc-brand {
- display: inline-block;
- float: left;
- margin-left: @global-padding;
-
- padding: 0 10px;
-
- cursor: pointer;
- color: #eee;
- height: 100%;
-
- .transition-def(background, @transition-length);
-
- img {
- display: inline-block;
- float: left;
- margin: @navbar-padding 0;
-
- width: @navbar-height - @navbar-padding * 2;
- height: @navbar-height - @navbar-padding * 2;
- vertical-align: middle;
- }
-
- .opendc-title {
- display: inline-block;
- float: right;
- margin-left: 20px;
-
- font-size: 16pt;
- line-height: @navbar-height;
- }
- }
-
- .opendc-brand:hover {
- background: @blue;
- }
-
- .opendc-brand:active {
- background: @blue-dark;
- }
-
- .navbar-button-group {
- display: inline-block;
- height: 100%;
-
- a {
- display: inline-block;
- line-height: @navbar-height;
- text-align: center;
- color: #eee;
-
- border-left: 1px solid #464646;
-
- .clickable;
- .transition-def(background, @transition-length);
- }
-
- a:last-of-type {
- border-right: 1px solid #464646;
- }
- }
-
- .navigation {
- margin-left: 30px;
-
- .projects {
- float: left;
- padding: 0 20px;
-
- font-size: 12pt;
- }
-
- .projects:hover {
- background: #606060;
- }
-
- .projects:active {
- background: #161616;
- }
- }
-
- .user {
- float: right;
- margin-right: @global-padding;
-
- .support {
- float: left;
- margin-top: -1px;
-
- width: @navbar-height;
-
- font-size: 14pt;
- }
-
- .support:hover {
- background: #41a0cd;
- }
-
- .support:active {
- background: #307798;
- }
-
- .username {
- float: left;
- padding: 0 20px;
-
- font-size: 12pt;
- }
-
- .username:hover {
- background: #4eae44;
- }
-
- .username:active {
- background: #2d6527;
- }
-
- .sign-out {
- float: right;
- margin-top: -1px;
- width: @navbar-height;
-
- font-size: 14pt;
- }
-
- .sign-out:hover {
- background: #e3474d;
- }
-
- .sign-out:active {
- background: #a73438;
- }
- }
-}
-
-#google-signin {
- display: none;
-}
diff --git a/src/styles/profile.less b/src/styles/profile.less
deleted file mode 100644
index 40bf49f8..00000000
--- a/src/styles/profile.less
+++ /dev/null
@@ -1,22 +0,0 @@
-@import "main.less";
-
-.main-body.profile-page {
- text-align: center;
-
- :not(.btn) {
- text-align: left;
- }
-}
-
-#delete-account {
- margin: 10px 0;
-}
-
-.delete-info {
- color: #999999;
- padding: 0 80px;
-}
-
-.account-delete-alert {
- display: none;
-} \ No newline at end of file
diff --git a/src/styles/projects.less b/src/styles/projects.less
deleted file mode 100644
index 926ea8ec..00000000
--- a/src/styles/projects.less
+++ /dev/null
@@ -1,391 +0,0 @@
-@import "main.less";
-
-/* Buttons */
-.new-project-btn {
- @button-height: 35px;
-
- display: inline-block;
- position: absolute;
- bottom: 40px;
- right: 40px;
- padding: 0 20px;
- height: @button-height;
- line-height: @button-height;
- font-size: 12pt;
-
- background: #679436;
- color: #eee;
- border: 1px solid #507830;
-
- .border-radius-def(@standard-border-radius);
- .clickable;
- .transition-def(all, @transition-length);
-}
-
-.new-project-btn:hover {
- background: #73ac45;
-}
-
-.new-project-btn:active {
- background: #5c8835;
-}
-
-/* Side menu */
-.filter-menu {
- display: block;
-
- background: #0761b1;
- border: 1px solid #06326b;
- color: #eee;
-
- text-align: center;
-
- .border-radius-def(@standard-border-radius);
- overflow: hidden;
-
- margin-bottom: 20px;
-
- .project-filters {
- display: block;
- overflow: hidden;
- margin-left: -2px;
-
- div {
- display: inline-block;
- width: 33.3%;
- margin-right: -4px;
- padding: 10px @global-padding;
-
- font-size: 12pt;
- border-right: 1px solid #06326b;
-
- .clickable;
- .transition-def(background, @transition-length);
- }
-
- div:last-of-type {
- border: 0;
- }
-
- div:hover {
- background: #0c60bf;
- }
-
- div:active, div.active {
- background: #073d7d;
- }
- }
-}
-
-/* Message shown when no projects present */
-.no-projects-alert {
- display: none;
- position: relative;
- padding-left: 50px;
- span {
- position: absolute;
- top: 11px;
- left: 10px;
- bottom: 10px;
- font-size: 20pt;
- }
-}
-
-/* List of simulation projects */
-.project-list {
- display: block;
- font-size: 12pt;
- border: 0;
-
- .list-head, .list-body .project-row {
- display: block;
- position: relative;
- }
-
- .list-head div, .list-body .project-row div {
- padding: 0 10px;
- display: inline-block;
- }
-
- .list-head {
- font-weight: bold;
-
- div {
- margin-right: -4px; // Address default margin between inline-blocks
- }
- }
-
- .project-row {
- background: #f8f8f8;
- border: 1px solid #b6b6b6;
- height: 40px;
- line-height: 40px;
- clear: both;
-
- .transition-def(background, @transition-length);
- .clickable;
- }
-
- .project-row:hover {
- background: #fff;
- }
-
- .project-row:active {
- background: #cccccc;
- }
-
- .project-row:not(:first-of-type) {
- margin-top: -1px;
- }
-
- // Sizing of table columns
- .project-row, .list-head {
- div:first-of-type {
- width: 50%;
- }
-
- div:nth-of-type(2) {
- width: 30%;
- }
-
- div:last-of-type {
- width: 20%;
-
- span {
- margin-right: 10px;
- }
- }
- }
-
- .project-row.active {
- border-bottom: 0;
- background: #3442b1;
- color: #eee;
- }
-
- .project-row.active::before {
- //noinspection CssNoGenericFontName
- font-family: 'Glyphicons Halflings';
- content: "\2212";
- font-size: 14pt;
- position: absolute;
- top: 0;
- right: 10px;
- }
-
- .project-view {
- padding: 10px;
- overflow: hidden;
- border: 1px solid #b6b6b6;
- border-top: 0;
-
- background: #3442b1;
- color: #eee;
-
- .participants {
- display: inline-block;
- float: left;
- }
-
- .access-buttons {
- display: inline-block;
- float: right;
-
- .inline-btn {
- margin-left: 10px;
- }
-
- .open {
- background: #e38829;
- }
-
- .open:hover {
- background: #ff992e;
- }
-
- .open:active {
- background: #ba6f21;
- }
-
- .edit {
- background: #2c3897;
- }
-
- .edit:hover {
- background: #3a4ac8;
- }
-
- .edit:active {
- background: #242d7a;
- }
- }
- }
-}
-
-.inline-btn {
- display: inline-block;
- height: 30px;
- line-height: 30px;
- font-size: 10pt;
- width: 70px;
-
- text-transform: uppercase;
- text-align: center;
-
- color: #eee;
-
- .clickable;
- .transition-def(background, @transition-length);
-}
-
-.projects-window {
- width: 600px;
- height: 400px;
-
- position: absolute;
- left: 0;
- top: 0;
- bottom: 0;
- right: 0;
- margin: auto;
-
- .border-radius-def(5px);
- overflow: hidden;
-
- .window-body {
- width: 100%;
- height: 340px;
-
- padding: 10px;
-
- background: rgba(230, 230, 230, 0.9);
-
- .window-heading {
- font-size: 20pt;
- color: #000000;
-
- .user-select-def;
-
- font-weight: bold;
-
- padding-left: 5px;
- }
-
- .project-name-form, .participant-add-form {
- margin: 20px;
-
- input {
- width: 300px;
- }
-
- label {
- padding-right: 5px;
- width: 40px;
- text-align: right;
-
- .user-select-def;
- }
- }
-
- .participants-table-label {
- display: block;
- padding-left: 20px;
- margin-bottom: 5px;
-
- .user-select-def;
- }
-
- .participants-table {
- background: #ffffff;
- .border-radius-def(5px);
-
- margin: 0 20px;
-
- max-height: 135px;
- overflow: auto;
-
- .participant-row {
- height: 40px;
- line-height: 40px;
-
- div {
- display: inline-block;
- margin-right: -4px; // Address default margin between inline-blocks
- }
-
- .participant-name {
- padding-left: 10px;
- width: 60%;
- }
-
- .participant-level {
- width: 30%;
-
- .user-select-def;
-
- div {
- display: inline-block;
-
- width: 25px;
- height: 25px;
-
- padding: 5px;
-
- margin-right: 3px;
-
- cursor: pointer;
-
- .border-radius-def(5px);
- .transition-def(all, @transition-length);
- }
-
- div.active, div:hover {
- background-color: #415973;
- color: #eeeeee;
- }
- }
-
- .participant-remove {
- position: relative;
- width: 10%;
- text-align: right;
- padding-right: 10px;
- }
-
- .participant-remove div {
- top: 2px;
- right: 5px;
- cursor: pointer;
- }
- }
- }
-
- .participant-add-form {
- margin-top: 10px;
- }
-
- .participant-email-alert, .project-name-alert {
- position: absolute;
- bottom: 0;
- left: 20px;
- display: none;
- }
- }
-
- .window-footer {
- width: 100%;
- height: 60px;
-
- background: rgba(56, 56, 56, 0.9);
-
- padding: 12px 10px;
-
- .btn.pull-left {
- margin-right: 5px;
- }
-
- .btn.pull-right {
- margin-left: 5px;
- }
- }
-}
diff --git a/src/styles/splash.less b/src/styles/splash.less
deleted file mode 100644
index c462aa43..00000000
--- a/src/styles/splash.less
+++ /dev/null
@@ -1,440 +0,0 @@
-@screen-sm: 768px;
-@screen-md: 992px;
-@screen-lg: 1200px;
-
-html, body {
- width: 100%;
- height: 100%;
- margin: 0;
-}
-
-/* Fix for the white space appearing otherwise on the right of the page, on mobile */
-.body-wrapper {
- overflow-x: hidden;
- overflow-y: hidden;
-}
-
-/* NAVBAR */
-@media screen and (min-width: @screen-sm) {
- .navbar {
- padding: 20px 0;
- -webkit-transition: background 200ms ease-in-out, padding 200ms ease-in-out;
- -moz-transition: background 200ms ease-in-out, padding 200ms ease-in-out;
- transition: background 200ms ease-in-out, padding 200ms ease-in-out;
- }
-
- .top-nav-collapse {
- padding: 0;
- }
-}
-
-.navbar {
- text-transform: uppercase;
-}
-
-.navbar-transparent {
- background: transparent;
- border: none;
-
- .collapse li a, .projects-btn {
- color: #eee;
- }
-}
-
-.navbar-toggle {
- margin-right: 30px;
-}
-
-.navbar-fixed-top {
- padding: 0;
-}
-
-.navbar .logged-in {
- display: none;
-}
-
-.sign-out {
- padding: 10px;
- width: 40px;
- margin-top: 5px;
- margin-left: 5px;
-
- font-size: 14pt;
- color: #eeeeee;
-
- -webkit-border-radius: 25px;
- -moz-border-radius: 25px;
- border-radius: 25px;
-
- -webkit-transition: background 200ms;
- -moz-transition: background 200ms;
- -ms-transition: background 200ms;
- -o-transition: background 200ms;
- transition: background 200ms;
-}
-
-.sign-out:hover {
- background: #e3474d;
- color: #eeeeee;
-}
-
-.sign-out:active {
- background: #a73438;
-}
-
-.projects-btn {
- position: relative;
- top: -4px;
- color: #eee;
-}
-
-.projects-btn:hover {
- color: #fff;
-}
-
-a.navbar-brand {
- width: 40px;
- height: 40px;
- padding: 0;
- margin-right: 5px;
- margin-top: 5px;
-
- -webkit-border-radius: 20px;
- -moz-border-radius: 20px;
- border-radius: 20px;
-
- -webkit-transition: background-color 200ms ease-in-out;
- -moz-transition: background-color 200ms ease-in-out;
- -ms-transition: background-color 200ms ease-in-out;
- -o-transition: background-color 200ms ease-in-out;
- transition: background-color 200ms ease-in-out;
-}
-
-a.navbar-brand:hover {
- background: #eee !important;
-}
-
-a.navbar-brand:active, a.navbar-brand:visited, .active a.navbar-brand {
- background: #ccc !important;
-}
-
-.navbar-brand > img {
- padding: 5px;
- margin: 0;
- width: auto;
- height: 100%;
-}
-
-@media screen and (max-width: @screen-sm) {
- .navbar-brand {
- margin-left: 15px;
- }
-}
-
-#google-signin {
- margin-top: 10px;
- margin-bottom: 10px;
-}
-
-/* GENERAL CONTENT RULES */
-a {
- text-decoration: none;
-}
-
-a:hover {
- text-decoration: none;
-}
-
-.content-section {
- padding-top: 50px;
- padding-bottom: 150px;
- text-align: center;
-}
-
-.img-caption {
- margin-top: 10px;
- color: #666;
-}
-
-@media screen and (min-width: @screen-sm) and (max-width: @screen-md) {
- .content-section h1 {
- font-size: 2em;
- margin-bottom: 40px;
- }
-
- .content-section h3 {
- font-size: 1.5em;
- }
-}
-
-@media screen and (min-width: @screen-md) and (max-width: @screen-lg) {
- .content-section h1 {
- font-size: 3em;
- margin-bottom: 40px;
- }
-
- .content-section h3 {
- font-size: 1.8em;
- }
-}
-
-@media screen and (min-width: @screen-lg) {
- .content-section h1 {
- font-size: 3em;
- margin-bottom: 40px;
- }
-}
-
-.info-points {
- font-size: 1.2em;
-}
-
-@media screen and (min-width: @screen-sm) and (max-width: @screen-md) {
- .info-points {
- font-size: 1em;
- }
-}
-
-@media screen and (min-width: @screen-md) and (max-width: @screen-lg) {
- .info-points {
- font-size: 1.1em;
- }
-}
-
-.atlarge-footer {
- color: #dddddd;
-}
-
-.pitch-column {
- text-align: left;
-}
-
-.jumbotron ul, .content-section ul {
- list-style: none;
- padding-left: 25px;
-}
-
-.jumbotron ul li, .content-section ul li {
- display: block;
-}
-
-.jumbotron ul li:before, .content-section ul li:before {
- content: "\e080";
- font-family: 'Glyphicons Halflings', monospace;
- font-size: 10px;
- float: left;
- margin-top: 6px;
- margin-left: -17px;
- color: #aaa;
-}
-
-/* CONTENT SECTION COLORS */
-.intro-section {
- background-color: #fff;
-}
-
-.stakeholder-section {
- background-color: #f2f2f2;
-}
-
-.modeling-section {
- background-color: #fff;
-}
-
-.simulation-section {
- background-color: #f2f2f2;
-}
-
-.technologies-section {
- background-color: #fff;
-}
-
-.team-section {
- background-color: #f2f2f2;
-}
-
-.contact-section {
- background-color: #444;
-}
-
-/* HEADING SECTION */
-.header-section {
- background-image: linear-gradient(135deg, #1c2e48, #005bbf, #00c5d6);
-}
-
-.jumbotron {
- margin: 140px 0 120px 0;
- background-color: inherit;
-}
-
-.jumbotron h1 {
- color: #eee;
-}
-
-.jumbotron h1 .dc {
- color: #eee;
- font-weight: bold;
-}
-
-.jumbotron h2 {
- margin-top: 50px;
- color: #eee;
-
-}
-
-/* INTRO SECTION*/
-.intro-section {
- padding-top: 0;
- padding-bottom: 50px;
- text-align: center;
-}
-
-.pitch-container {
- margin-top: 50px;
-}
-
-p.img-source {
- font-size: 0.6em;
- position: relative;
- top: 20px;
-}
-
-@media screen and (max-width: @screen-sm) {
- p.img-source {
- top: 0;
- }
-}
-
-/* STAKEHOLDERS */
-@media screen and (max-width: @screen-sm) {
- .stakeholder-section img {
- position: relative;
- top: 15px;
- }
-}
-
-@media screen and (min-width: @screen-sm) and (max-width: @screen-md) {
- .stakeholder-section img {
- position: relative;
- top: 5px;
- }
-
- .stakeholder-section h3 {
- font-size: 1.5em;
- }
-}
-
-@media screen and (min-width: @screen-md) and (max-width: @screen-lg) {
- .stakeholder-section img {
- position: relative;
- top: 15px;
- }
-
- .stakeholder-section h3 {
- font-size: 1.7em;
- }
-}
-
-.stakeholder-container div {
- text-align: left;
-}
-
-/* MOCKUPS */
-.construction-container {
- margin-top: 20px;
- margin-bottom: 60px;
-}
-
-.simulation-container > div:first-child {
- margin-bottom: 30px;
-}
-
-.img-construction-building {
- margin-top: 10px;
-}
-
-.modeling-section img, .simulation-section img {
- outline: 2px solid #3f3f3f;
- padding-right: 0;
- padding-left: 0;
-}
-
-.simulation-building-row {
- margin-bottom: 40px;
-}
-
-.key-points {
- padding-right: 50px;
-}
-
-/* TECHNOLOGIES */
-.web-flow {
- font-size: 4em;
-}
-
-.technologies-section {
- h3 {
- margin-top: 0;
- }
-
- .tech-row {
- padding: 15px;
-
- -webkit-border-radius: 10px;
- -moz-border-radius: 10px;
- border-radius: 10px;
-
- margin-bottom: 10px;
- }
-
- .browser-tech {
- background-color: #82d0e7;
- }
-
- .server-tech {
- background-color: #edd667;
- }
-
- .database-tech {
- background-color: #ed9c67;
- }
-
- .simulator-tech {
- background-color: #49d65f;
- }
-}
-
-.technology-arrow {
- margin-bottom: 20px;
- margin-top: 15px;
-}
-
-/* TEAM */
-.team-member-description {
- margin-bottom: 30px;
-}
-
-/* CONTACT */
-.contact-section {
- margin-bottom: -5px; // Fixes an unwanted margin that appeared when adding the sign-in button to the nav
-
- h1 {
- color: #ddd;
- }
-
- .names {
- color: #ddd;
- }
-
- a {
- color: #ddd;
- }
-
- a:hover {
- color: #fff;
- }
-}
-
-.tudelft-icon {
- margin-bottom: 10px;
-} \ No newline at end of file
diff --git a/src/unit-tests.html b/src/unit-tests.html
deleted file mode 100644
index 877bda6d..00000000
--- a/src/unit-tests.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!--suppress HtmlUnknownTarget -->
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html;charset=utf-8">
- <title>OpenDC Unit Tests</title>
- <link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
- <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
- <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
- <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
-</head>
-<body>
-<script src="scripts/test.entry.js"></script>
-</body>
-</html> \ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644
index 436c6181..00000000
--- a/tsconfig.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "compilerOptions": {
- "target": "es5",
- "module": "commonjs",
- "sourceMap": false,
- "rootDir": "src/scripts",
- "outDir": "build/scripts"
- },
- "files": [
- "src/scripts/colors.ts",
- "src/scripts/definitions.ts",
- "src/scripts/serverconnection.ts",
- "src/scripts/user-authentication.ts",
- "src/scripts/util.ts",
- "src/scripts/controllers/mapcontroller.ts",
- "src/scripts/controllers/simulationcontroller.ts",
- "src/scripts/controllers/scaleindicator.ts",
- "src/scripts/controllers/connection/api.ts",
- "src/scripts/controllers/connection/cache.ts",
- "src/scripts/controllers/connection/socket.ts",
- "src/scripts/controllers/simulation/chart.ts",
- "src/scripts/controllers/simulation/statecache.ts",
- "src/scripts/controllers/simulation/taskview.ts",
- "src/scripts/controllers/simulation/timeline.ts",
- "src/scripts/controllers/modes/building.ts",
- "src/scripts/controllers/modes/room.ts",
- "src/scripts/controllers/modes/object.ts",
- "src/scripts/controllers/modes/node.ts",
- "src/scripts/error404.entry.ts",
- "src/scripts/main.entry.ts",
- "src/scripts/profile.entry.ts",
- "src/scripts/projects.entry.ts",
- "src/scripts/splash.entry.ts",
- "src/scripts/views/mapview.ts",
- "src/scripts/views/layers/dcobject.ts",
- "src/scripts/views/layers/dcprogressbar.ts",
- "src/scripts/views/layers/gray.ts",
- "src/scripts/views/layers/grid.ts",
- "src/scripts/views/layers/hover.ts",
- "src/scripts/views/layers/layer.ts",
- "src/scripts/views/layers/room.ts",
- "src/scripts/views/layers/roomtext.ts",
- "src/scripts/views/layers/wall.ts"
- ]
-}
diff --git a/tslint.json b/tslint.json
deleted file mode 100644
index 75b8d041..00000000
--- a/tslint.json
+++ /dev/null
@@ -1,75 +0,0 @@
-{
- "rules": {
- "class-name": true,
- "comment-format": false,
- "curly": true,
- "eofline": true,
- "forin": true,
- "indent": [true, "spaces"],
- "label-position": true,
- "label-undefined": true,
- "max-line-length": [true, 140],
- "member-access": true,
- "member-ordering": [true,
- "public-before-private",
- "static-before-instance",
- "variables-before-functions"
- ],
- "no-arg": true,
- "no-bitwise": true,
- "no-console": [true,
- "debug",
- "info",
- "time",
- "timeEnd",
- "trace"
- ],
- "no-construct": true,
- "no-debugger": true,
- "no-duplicate-key": true,
- "no-duplicate-variable": true,
- "no-empty": true,
- "no-eval": true,
- "no-inferrable-types": true,
- "no-shadowed-variable": true,
- "no-string-literal": false,
- "no-switch-case-fall-through": true,
- "no-trailing-whitespace": true,
- "no-unused-expression": true,
- "no-unused-variable": true,
- "no-unreachable": true,
- "no-use-before-declare": true,
- "no-var-keyword": true,
- "object-literal-sort-keys": false,
- "one-line": [true,
- "check-open-brace",
- "check-catch",
- "check-else",
- "check-whitespace"
- ],
- "quotemark": false,
- "radix": false,
- "semicolon": true,
- "trailing-comma": [
- false, {
- "singleline": "never",
- "multiline": "always"
- }],
- "triple-equals": [true, "allow-null-check"],
- "typedef-whitespace": [true, {
- "call-signature": "nospace",
- "index-signature": "nospace",
- "parameter": "nospace",
- "property-declaration": "nospace",
- "variable-declaration": "nospace"
- }],
- "variable-name": false,
- "whitespace": [true,
- "check-branch",
- "check-decl",
- "check-operator",
- "check-separator",
- "check-type"
- ]
- }
-}
diff --git a/typings.json b/typings.json
deleted file mode 100644
index af79634b..00000000
--- a/typings.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "name": "open-dc",
- "globalDependencies": {
- "c3": "github:DefinitelyTyped/DefinitelyTyped/c3/c3.d.ts#bc38caf4c4781b8a9b13785a0529fcd47fd1bfb4",
- "createjs-lib": "github:DefinitelyTyped/DefinitelyTyped/createjs-lib/createjs-lib.d.ts#07378f4a20ef709de8aea9507144fcf48c38897d",
- "d3": "github:DefinitelyTyped/DefinitelyTyped/d3/d3.d.ts#bc38caf4c4781b8a9b13785a0529fcd47fd1bfb4",
- "easeljs": "github:DefinitelyTyped/DefinitelyTyped/easeljs/easeljs.d.ts#571cd2bb8cdd6cf48428dca6ae6f4c486be7e2ec",
- "es6-promise": "registry:dt/es6-promise#0.0.0+20160614011821",
- "gapi.auth2": "registry:dt/gapi.auth2#0.0.0+20160602144801",
- "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#f481e77dfca5a146db1b4f5f20f15929b30c8729",
- "jquery": "github:DefinitelyTyped/DefinitelyTyped/jquery/jquery.d.ts#571cd2bb8cdd6cf48428dca6ae6f4c486be7e2ec",
- "preloadjs": "github:DefinitelyTyped/DefinitelyTyped/preloadjs/preloadjs.d.ts#07378f4a20ef709de8aea9507144fcf48c38897d",
- "socket.io-client": "registry:dt/socket.io-client#1.4.4+20160317120654",
- "tweenjs": "github:DefinitelyTyped/DefinitelyTyped/tweenjs/tweenjs.d.ts#571cd2bb8cdd6cf48428dca6ae6f4c486be7e2ec"
- }
-}