mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 22:55:35 +00:00
Compare commits
1 Commits
v3.0.0
...
feature/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0887429665 |
@@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
### STAGE 1: Build ###
|
|
||||||
FROM node:9.11.1-alpine as builder
|
|
||||||
ARG branch=develop
|
|
||||||
ENV BRANCH=$branch
|
|
||||||
WORKDIR /src/app
|
|
||||||
RUN mkdir -p /src/app/coriolis
|
|
||||||
RUN mkdir -p /src/app/coriolis-data
|
|
||||||
|
|
||||||
COPY ./coriolis/ /src/app/coriolis
|
|
||||||
COPY ./coriolis-data/ /src/app/coriolis-data
|
|
||||||
|
|
||||||
RUN apk update
|
|
||||||
RUN apk add git
|
|
||||||
|
|
||||||
RUN npm i -g npm
|
|
||||||
|
|
||||||
# Set up coriolis-data
|
|
||||||
WORKDIR /src/app/coriolis-data
|
|
||||||
RUN git fetch --all
|
|
||||||
RUN git reset --hard origin/$BRANCH
|
|
||||||
RUN npm install --no-package-lock
|
|
||||||
RUN npm start
|
|
||||||
|
|
||||||
WORKDIR /src/app/coriolis
|
|
||||||
RUN git fetch --all
|
|
||||||
RUN git reset --hard origin/$BRANCH
|
|
||||||
RUN npm install --no-package-lock
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
|
|
||||||
### STAGE 2: Production Environment ###
|
|
||||||
FROM nginx:1.13.12-alpine as web
|
|
||||||
COPY coriolis/.docker/nginx.conf /etc/nginx/nginx.conf
|
|
||||||
COPY --from=builder /src/app/coriolis/build /usr/share/nginx/html
|
|
||||||
WORKDIR /usr/share/nginx/html
|
|
||||||
EXPOSE 80
|
|
||||||
CMD ["nginx", "-c", "/etc/nginx/nginx.conf", "-g", "daemon off;"]
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
version: '2.2'
|
|
||||||
|
|
||||||
services:
|
|
||||||
coriolis_prod:
|
|
||||||
image: edcd/coriolis:master
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
networks:
|
|
||||||
- web
|
|
||||||
labels:
|
|
||||||
- "traefik.docker.network=web"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.basic.frontend.rule=Host:coriolis.io,coriolis.edcd.io"
|
|
||||||
- "traefik.basic.port=80"
|
|
||||||
- "traefik.basic.protocol=http"
|
|
||||||
|
|
||||||
coriolis_dev:
|
|
||||||
image: edcd/coriolis:develop
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
networks:
|
|
||||||
- web
|
|
||||||
labels:
|
|
||||||
- "traefik.docker.network=web"
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.basic.frontend.rule=Host:beta.coriolis.io,beta.coriolis.edcd.io"
|
|
||||||
- "traefik.basic.port=80"
|
|
||||||
- "traefik.basic.protocol=http"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
web:
|
|
||||||
external: true
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
worker_processes 1;
|
|
||||||
user nobody nobody;
|
|
||||||
error_log /tmp/error.log;
|
|
||||||
pid /tmp/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
sendfile on;
|
|
||||||
client_body_temp_path /tmp/client_body;
|
|
||||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
|
||||||
proxy_temp_path /tmp/proxy_temp;
|
|
||||||
scgi_temp_path /tmp/scgi_temp;
|
|
||||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
|
||||||
access_log /tmp/access.log;
|
|
||||||
error_log /tmp/error.log;
|
|
||||||
|
|
||||||
keepalive_timeout 3000;
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
index index.html;
|
|
||||||
server_name localhost;
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
autoindex on;
|
|
||||||
|
|
||||||
location ~* \.(?:manifest|appcache|html?|xml|json|css|js|map|jpg|jpeg|gif|png|ico|svg|eot|ttf|woff|woff2)$ {
|
|
||||||
expires -1;
|
|
||||||
add_header Access-Control-Allow-Origin *;
|
|
||||||
add_header Access-Control-Allow-Credentials true;
|
|
||||||
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
|
||||||
add_header Access-Control-Allow-Headers 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.html =404;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
103
.esdoc.json
103
.esdoc.json
@@ -1,103 +0,0 @@
|
|||||||
{
|
|
||||||
"source": "./src/app",
|
|
||||||
"includes": ["\\.js$", "\\.jsx$"],
|
|
||||||
"destination": "./docs",
|
|
||||||
"index": "./README.md",
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"name": "esdoc-standard-plugin",
|
|
||||||
"option": {
|
|
||||||
"lint": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"coverage": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"accessor": {
|
|
||||||
"access": [
|
|
||||||
"public",
|
|
||||||
"protected",
|
|
||||||
"private"
|
|
||||||
],
|
|
||||||
"autoPrivate": true
|
|
||||||
},
|
|
||||||
"undocumentIdentifier": {
|
|
||||||
"enable": true
|
|
||||||
},
|
|
||||||
"unexportedIdentifier": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"typeInference": {
|
|
||||||
"enable": true
|
|
||||||
},
|
|
||||||
"brand": {
|
|
||||||
"logo": "./src/images/logo/192x192.png",
|
|
||||||
"title": "Coriolis",
|
|
||||||
"description": "Coriolis Shipyard for Elite Dangerous",
|
|
||||||
"repository": "https://github.com/EDCD/coriolis",
|
|
||||||
"site": "https://coriolis.edcd.io",
|
|
||||||
"author": "https://github.com/edcd",
|
|
||||||
"image": "./src/images/logo/192x192.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "esdoc-ecmascript-proposal-plugin",
|
|
||||||
"option": {
|
|
||||||
"all": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "esdoc-react-plugin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "esdoc-standard-plugin",
|
|
||||||
"option": {
|
|
||||||
"lint": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"coverage": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"accessor": {
|
|
||||||
"access": [
|
|
||||||
"public",
|
|
||||||
"protected",
|
|
||||||
"private"
|
|
||||||
],
|
|
||||||
"autoPrivate": true
|
|
||||||
},
|
|
||||||
"undocumentIdentifier": {
|
|
||||||
"enable": true
|
|
||||||
},
|
|
||||||
"unexportedIdentifier": {
|
|
||||||
"enable": false
|
|
||||||
},
|
|
||||||
"typeInference": {
|
|
||||||
"enable": true
|
|
||||||
},
|
|
||||||
"brand": {
|
|
||||||
"logo": "./src/images/logo/192x192.png",
|
|
||||||
"title": "Coriolis",
|
|
||||||
"description": "Coriolis Shipyard for Elite Dangerous",
|
|
||||||
"repository": "https://github.com/EDCD/coriolis",
|
|
||||||
"site": "https://coriolis.edcd.io",
|
|
||||||
"author": "https://github.com/edcd",
|
|
||||||
"image": "./src/images/logo/192x192.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "esdoc-jsx-plugin",
|
|
||||||
"option": {
|
|
||||||
"enable": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "esdoc-publish-html-plugin",
|
|
||||||
"option": {
|
|
||||||
"template": "./node_modules/esdoc-custom-theme/template"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -9,8 +9,7 @@
|
|||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"node": true,
|
"node": true
|
||||||
"es6": true
|
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"react"
|
"react"
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,6 +8,3 @@ nginx.pid
|
|||||||
env
|
env
|
||||||
*.swp
|
*.swp
|
||||||
.project
|
.project
|
||||||
.vscode/
|
|
||||||
docs/
|
|
||||||
package-lock.json
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
|||||||
|
|
||||||
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) in the wiki.
|
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) in the wiki.
|
||||||
|
|
||||||
Also see [the documentation site.](https://coriolis.willb.info/)
|
|
||||||
|
|
||||||
### Ship and Module Database
|
### Ship and Module Database
|
||||||
|
|
||||||
|
|||||||
12862
package-lock.json
generated
Normal file
12862
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "coriolis_shipyard",
|
"name": "coriolis_shipyard",
|
||||||
"version": "3.0.0",
|
"version": "2.9.16",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EDCD/coriolis"
|
"url": "https://github.com/EDCD/coriolis"
|
||||||
@@ -65,16 +65,9 @@
|
|||||||
"babel-preset-react": "*",
|
"babel-preset-react": "*",
|
||||||
"babel-preset-stage-0": "*",
|
"babel-preset-stage-0": "*",
|
||||||
"create-react-class": "^15.6.2",
|
"create-react-class": "^15.6.2",
|
||||||
"cross-env": "^5.1.4",
|
|
||||||
"css-loader": "^0.28.0",
|
"css-loader": "^0.28.0",
|
||||||
|
"cross-env": "^5.1.4",
|
||||||
"d3-selection": "1",
|
"d3-selection": "1",
|
||||||
"esdoc": "^1.1.0",
|
|
||||||
"esdoc-custom-theme": "^1.4.2",
|
|
||||||
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
|
|
||||||
"esdoc-jsx-plugin": "^1.0.0",
|
|
||||||
"esdoc-publish-html-plugin": "^1.1.2",
|
|
||||||
"esdoc-react-plugin": "^1.0.1",
|
|
||||||
"esdoc-standard-plugin": "^1.0.0",
|
|
||||||
"eslint": "3.19.0",
|
"eslint": "3.19.0",
|
||||||
"eslint-plugin-react": "^6.10.3",
|
"eslint-plugin-react": "^6.10.3",
|
||||||
"expose-loader": "^0.7.3",
|
"expose-loader": "^0.7.3",
|
||||||
@@ -88,7 +81,7 @@
|
|||||||
"less": "^2.7.2",
|
"less": "^2.7.2",
|
||||||
"less-loader": "^4.0.3",
|
"less-loader": "^4.0.3",
|
||||||
"react-addons-perf": "^15.4.2",
|
"react-addons-perf": "^15.4.2",
|
||||||
"react-container-dimensions": "^1.4.1",
|
"react-measure": "^1.4.7",
|
||||||
"react-testutils-additions": "^15.2.0",
|
"react-testutils-additions": "^15.2.0",
|
||||||
"react-transition-group": "^1.1.2",
|
"react-transition-group": "^1.1.2",
|
||||||
"rimraf": "^2.6.1",
|
"rimraf": "^2.6.1",
|
||||||
@@ -98,10 +91,9 @@
|
|||||||
"uglify-js": "^2.4.11",
|
"uglify-js": "^2.4.11",
|
||||||
"url-loader": "^0.5.8",
|
"url-loader": "^0.5.8",
|
||||||
"webpack": "^2.4.1",
|
"webpack": "^2.4.1",
|
||||||
"webpack-bugsnag-plugins": "^1.1.1",
|
|
||||||
"webpack-dev-server": "^2.4.4",
|
"webpack-dev-server": "^2.4.4",
|
||||||
"webpack-notifier": "^1.6.0",
|
"webpack-notifier": "^1.6.0",
|
||||||
"workbox-webpack-plugin": "^3.4.1"
|
"webpack-bugsnag-plugins": "^1.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-polyfill": "*",
|
"babel-polyfill": "*",
|
||||||
@@ -111,7 +103,7 @@
|
|||||||
"d3": "4.8.0",
|
"d3": "4.8.0",
|
||||||
"detect-browser": "^1.7.0",
|
"detect-browser": "^1.7.0",
|
||||||
"fbemitter": "^2.1.1",
|
"fbemitter": "^2.1.1",
|
||||||
"lodash": "^4.17.10",
|
"lodash": "^4.17.4",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"pako": "^1.0.6",
|
"pako": "^1.0.6",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ export default class Coriolis extends React.Component {
|
|||||||
console && console.error && console.error(arguments); // eslint-disable-line no-console
|
console && console.error && console.error(arguments); // eslint-disable-line no-console
|
||||||
if (errObj) {
|
if (errObj) {
|
||||||
if (errObj instanceof Error) {
|
if (errObj instanceof Error) {
|
||||||
bugsnagClient.notify(errObj); // eslint-disable-line
|
bugsnagClient.notify(errObj) // eslint-disable-line
|
||||||
} else if (errObj instanceof String) {
|
} else if (errObj instanceof String) {
|
||||||
bugsnagClient.notify(msg, errObj); // eslint-disable-line
|
bugsnagClient.notify(msg, errObj) // eslint-disable-line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -180,13 +180,13 @@ export default class Coriolis extends React.Component {
|
|||||||
case 72: // 'h'
|
case 72: // 'h'
|
||||||
if (e.ctrlKey || e.metaKey) { // CTRL/CMD + h
|
if (e.ctrlKey || e.metaKey) { // CTRL/CMD + h
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._showModal(<ModalHelp/>);
|
this._showModal(<ModalHelp />);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 73: // 'i'
|
case 73: // 'i'
|
||||||
if (e.ctrlKey || e.metaKey) { // CTRL/CMD + i
|
if (e.ctrlKey || e.metaKey) { // CTRL/CMD + i
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._showModal(<ModalImport/>);
|
this._showModal(<ModalImport />);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 79: // 'o'
|
case 79: // 'o'
|
||||||
@@ -208,7 +208,7 @@ export default class Coriolis extends React.Component {
|
|||||||
* @param {React.Component} content Modal Content
|
* @param {React.Component} content Modal Content
|
||||||
*/
|
*/
|
||||||
_showModal(content) {
|
_showModal(content) {
|
||||||
let modal = <div className='modal-bg' onClick={(e) => this._hideModal()}>{content}</div>;
|
let modal = <div className='modal-bg' onClick={(e) => this._hideModal() }>{content}</div>;
|
||||||
this.setState({ modal });
|
this.setState({ modal });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ export default class Coriolis extends React.Component {
|
|||||||
return this.emitter.addListener('windowResize', listener);
|
return this.emitter.addListener('windowResize', listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a listener to global commands such as save,
|
* Add a listener to global commands such as save,
|
||||||
* @param {Function} listener Listener callback
|
* @param {Function} listener Listener callback
|
||||||
* @return {Object} Subscription token
|
* @return {Object} Subscription token
|
||||||
@@ -322,60 +322,14 @@ export default class Coriolis extends React.Component {
|
|||||||
*/
|
*/
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
// Listen for appcache updated event, present refresh to update view
|
// Listen for appcache updated event, present refresh to update view
|
||||||
// Check that service workers are registered
|
if (window.applicationCache) {
|
||||||
if (navigator.storage && navigator.storage.persist) {
|
window.applicationCache.addEventListener('updateready', () => {
|
||||||
window.addEventListener('load', () => {
|
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
|
||||||
navigator.storage.persist().then(granted => {
|
this.setState({ appCacheUpdate: true }); // Browser downloaded a new app cache.
|
||||||
if (granted)
|
}
|
||||||
console.log('Storage will not be cleared except by explicit user action');
|
|
||||||
else
|
|
||||||
console.log('Storage may be cleared by the UA under storage pressure.');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
// Your service-worker.js *must* be located at the top-level directory relative to your site.
|
|
||||||
// It won't be able to control pages unless it's located at the same level or higher than them.
|
|
||||||
// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
|
|
||||||
// See https://github.com/slightlyoff/ServiceWorker/issues/468
|
|
||||||
const self = this;
|
|
||||||
navigator.serviceWorker.register('/service-worker.js').then(function(reg) {
|
|
||||||
// updatefound is fired if service-worker.js changes.
|
|
||||||
reg.onupdatefound = function() {
|
|
||||||
// The updatefound event implies that reg.installing is set; see
|
|
||||||
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-updatefound-event
|
|
||||||
var installingWorker = reg.installing;
|
|
||||||
|
|
||||||
installingWorker.onstatechange = function() {
|
|
||||||
switch (installingWorker.state) {
|
|
||||||
case 'installed':
|
|
||||||
if (navigator.serviceWorker.controller) {
|
|
||||||
// At this point, the old content will have been purged and the fresh content will
|
|
||||||
// have been added to the cache.
|
|
||||||
// It's the perfect time to display a "New content is available; please refresh."
|
|
||||||
// message in the page's interface.
|
|
||||||
console.log('New or updated content is available.');
|
|
||||||
self.setState({ appCacheUpdate: true }); // Browser downloaded a new app cache.
|
|
||||||
} else {
|
|
||||||
// At this point, everything has been precached.
|
|
||||||
// It's the perfect time to display a "Content is cached for offline use." message.
|
|
||||||
console.log('Content is now available offline!');
|
|
||||||
self.setState({ appCacheUpdate: true }); // Browser downloaded a new app cache.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'redundant':
|
|
||||||
console.error('The installing service worker became redundant.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}).catch(function(e) {
|
|
||||||
console.error('Error during service worker registration:', e);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
window.onerror = this._onError.bind(this);
|
window.onerror = this._onError.bind(this);
|
||||||
window.addEventListener('resize', () => this.emitter.emit('windowResize'));
|
window.addEventListener('resize', () => this.emitter.emit('windowResize'));
|
||||||
document.getElementById('coriolis').addEventListener('scroll', () => this._tooltip());
|
document.getElementById('coriolis').addEventListener('scroll', () => this._tooltip());
|
||||||
@@ -393,22 +347,16 @@ export default class Coriolis extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
let currentMenu = this.state.currentMenu;
|
let currentMenu = this.state.currentMenu;
|
||||||
|
|
||||||
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
|
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu} className={ this.state.noTouch ? 'no-touch' : null }>
|
||||||
className={this.state.noTouch ? 'no-touch' : null}>
|
<Header appCacheUpdate={this.state.appCacheUpdate} currentMenu={currentMenu} />
|
||||||
<Header appCacheUpdate={this.state.appCacheUpdate} currentMenu={currentMenu}/>
|
{ this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) : <NotFoundPage/> }
|
||||||
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
|
{ this.state.modal }
|
||||||
<NotFoundPage/>}
|
{ this.state.tooltip }
|
||||||
{this.state.modal}
|
|
||||||
{this.state.tooltip}
|
|
||||||
<footer>
|
<footer>
|
||||||
<div className="right cap">
|
<div className="right cap">
|
||||||
<a href="https://github.com/EDCD/coriolis" target="_blank"
|
<a href="https://github.com/EDCD/coriolis" target="_blank" title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
||||||
title="Coriolis Github Project">{window.CORIOLIS_VERSION} - {window.CORIOLIS_DATE}</a>
|
|
||||||
<br/>
|
<br/>
|
||||||
<a
|
<a href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'} target="_blank" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits since last release ({window.CORIOLIS_DATE})</a>
|
||||||
href={'https://github.com/EDCD/coriolis/compare/edcd:develop@{' + window.CORIOLIS_DATE + '}...edcd:develop'}
|
|
||||||
target="_blank" title={'Coriolis Commits since' + window.CORIOLIS_DATE}>Commits since last release
|
|
||||||
({window.CORIOLIS_DATE})</a>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>;
|
</div>;
|
||||||
|
|||||||
@@ -258,15 +258,6 @@ Route.prototype.match = function(path, params) {
|
|||||||
* @param {string} path Path to track
|
* @param {string} path Path to track
|
||||||
*/
|
*/
|
||||||
function gaTrack(path) {
|
function gaTrack(path) {
|
||||||
const match = path.match(/\/outfit\/(.*)(\?code=.*)/);
|
|
||||||
if (match) {
|
|
||||||
if (match[1]) {
|
|
||||||
ReactGA.ga('set', 'contentGroup1', match[1]);
|
|
||||||
}
|
|
||||||
if (match[2]) {
|
|
||||||
ReactGA.ga('set', 'contentGroup2', match[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReactGA.pageview(path);
|
ReactGA.pageview(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ const GRPCAT = {
|
|||||||
'mr': 'ordnance',
|
'mr': 'ordnance',
|
||||||
'axmr': 'experimental',
|
'axmr': 'experimental',
|
||||||
'rcpl': 'experimental',
|
'rcpl': 'experimental',
|
||||||
'dtl': 'experimental',
|
|
||||||
'tbsc': 'experimental',
|
|
||||||
'tbem': 'experimental',
|
|
||||||
'tbrfl': 'experimental',
|
|
||||||
'mahr': 'experimental',
|
|
||||||
'rsl': 'experimental',
|
|
||||||
'tp': 'ordnance',
|
'tp': 'ordnance',
|
||||||
'nl': 'ordnance',
|
'nl': 'ordnance',
|
||||||
'sc': 'scanners',
|
'sc': 'scanners',
|
||||||
@@ -64,15 +58,10 @@ const GRPCAT = {
|
|||||||
'po': 'defence',
|
'po': 'defence',
|
||||||
'ec': 'defence',
|
'ec': 'defence',
|
||||||
'sfn': 'defence',
|
'sfn': 'defence',
|
||||||
// Guardian
|
// Standard
|
||||||
'gpp': 'guardian',
|
'gpp': 'guardian',
|
||||||
'gpc': 'guardian',
|
'gpc': 'guardian',
|
||||||
'gsrp': 'guardian',
|
'ggc': 'guardian'
|
||||||
'ggc': 'guardian',
|
|
||||||
'gfsb': 'guardian',
|
|
||||||
'gmrp': 'guardian',
|
|
||||||
'gsc': 'guardian',
|
|
||||||
'ghrp': 'guardian'
|
|
||||||
};
|
};
|
||||||
// Order here is the order in which items will be shown in the modules menu
|
// Order here is the order in which items will be shown in the modules menu
|
||||||
const CATEGORIES = {
|
const CATEGORIES = {
|
||||||
@@ -98,10 +87,10 @@ const CATEGORIES = {
|
|||||||
'defence': ['ch', 'po', 'ec'],
|
'defence': ['ch', 'po', 'ec'],
|
||||||
'scanners': ['sc', 'ss', 'cs', 'kw', 'ws'], // Overloaded with internal scanners
|
'scanners': ['sc', 'ss', 'cs', 'kw', 'ws'], // Overloaded with internal scanners
|
||||||
// Experimental
|
// Experimental
|
||||||
'experimental': ['axmc', 'axmr', 'rfl', 'tbrfl', 'tbsc', 'tbem', 'xs', 'sfn', 'rcpl', 'dtl', 'rsl', 'mahr', ],
|
'experimental': ['axmc', 'axmr', 'rfl', 'xs', 'sfn', 'rcpl'],
|
||||||
|
|
||||||
// Guardian
|
// Guardian
|
||||||
'guardian': ['gpp', 'gpd', 'gpc', 'ggc', 'gsrp', 'gfsb', 'ghrp', 'gmrp', 'gsc']
|
'guardian': ['gpp', 'gpc', 'ggc']
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -478,7 +467,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Handle focus if the component updates
|
* Handle focus if the component updates
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if(this.props.slotDiv) {
|
if(this.props.slotDiv) {
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ export default class Defence extends TranslatedComponent {
|
|||||||
shieldSourcesData.push({ value: Math.round(shield.generator), label: translate('generator') });
|
shieldSourcesData.push({ value: Math.round(shield.generator), label: translate('generator') });
|
||||||
shieldSourcesData.push({ value: Math.round(shield.boosters), label: translate('boosters') });
|
shieldSourcesData.push({ value: Math.round(shield.boosters), label: translate('boosters') });
|
||||||
shieldSourcesData.push({ value: Math.round(shield.cells), label: translate('cells') });
|
shieldSourcesData.push({ value: Math.round(shield.cells), label: translate('cells') });
|
||||||
shieldSourcesData.push({ value: Math.round(shield.addition), label: translate('shield addition') });
|
|
||||||
|
|
||||||
if (shield.generator > 0) {
|
if (shield.generator > 0) {
|
||||||
shieldSourcesTt.push(<div key='generator'>{translate('generator') + ' ' + formats.int(shield.generator)}{units.MJ}</div>);
|
shieldSourcesTt.push(<div key='generator'>{translate('generator') + ' ' + formats.int(shield.generator)}{units.MJ}</div>);
|
||||||
@@ -102,19 +101,19 @@ export default class Defence extends TranslatedComponent {
|
|||||||
|
|
||||||
// Add effective shield from resistances
|
// Add effective shield from resistances
|
||||||
const rawMj = shield.generator + shield.boosters + shield.cells;
|
const rawMj = shield.generator + shield.boosters + shield.cells;
|
||||||
const explosiveMj = rawMj / (shield.explosive.base) - rawMj;
|
const explosiveMj = rawMj / (shield.explosive.generator * shield.explosive.boosters) - rawMj;
|
||||||
if (explosiveMj != 0) effectiveShieldExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(explosiveMj)}{units.MJ}</div>);
|
if (explosiveMj != 0) effectiveShieldExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(explosiveMj)}{units.MJ}</div>);
|
||||||
const kineticMj = rawMj / (shield.kinetic.base) - rawMj;
|
const kineticMj = rawMj / (shield.kinetic.generator * shield.kinetic.boosters) - rawMj;
|
||||||
if (kineticMj != 0) effectiveShieldKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(kineticMj)}{units.MJ}</div>);
|
if (kineticMj != 0) effectiveShieldKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(kineticMj)}{units.MJ}</div>);
|
||||||
const thermalMj = rawMj / (shield.thermal.base) - rawMj;
|
const thermalMj = rawMj / (shield.thermal.generator * shield.thermal.boosters) - rawMj;
|
||||||
if (thermalMj != 0) effectiveShieldThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(thermalMj)}{units.MJ}</div>);
|
if (thermalMj != 0) effectiveShieldThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(thermalMj)}{units.MJ}</div>);
|
||||||
|
|
||||||
// Add effective shield from power distributor SYS pips
|
// Add effective shield from power distributor SYS pips
|
||||||
if (shield.absolute.sys != 1) {
|
if (shield.absolute.sys != 1) {
|
||||||
effectiveShieldAbsoluteTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.absolute.total - rawMj)}{units.MJ}</div>);
|
effectiveShieldAbsoluteTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.absolute.sys - rawMj)}{units.MJ}</div>);
|
||||||
effectiveShieldExplosiveTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.explosive.total - rawMj / shield.explosive.base)}{units.MJ}</div>);
|
effectiveShieldExplosiveTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.explosive.sys - rawMj)}{units.MJ}</div>);
|
||||||
effectiveShieldKineticTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.kinetic.total - rawMj / shield.kinetic.base)}{units.MJ}</div>);
|
effectiveShieldKineticTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.kinetic.sys - rawMj)}{units.MJ}</div>);
|
||||||
effectiveShieldThermalTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.thermal.total - rawMj / shield.thermal.base)}{units.MJ}</div>);
|
effectiveShieldThermalTt.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.int(rawMj / shield.thermal.sys - rawMj)}{units.MJ}</div>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,21 +159,18 @@ export default class Defence extends TranslatedComponent {
|
|||||||
const effectiveArmourExplosiveTt = [];
|
const effectiveArmourExplosiveTt = [];
|
||||||
const effectiveArmourKineticTt = [];
|
const effectiveArmourKineticTt = [];
|
||||||
const effectiveArmourThermalTt = [];
|
const effectiveArmourThermalTt = [];
|
||||||
const effectiveArmourCausticTt = [];
|
|
||||||
if (armour.bulkheads > 0) {
|
if (armour.bulkheads > 0) {
|
||||||
armourSourcesTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
armourSourcesTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
||||||
effectiveArmourAbsoluteTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
effectiveArmourAbsoluteTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
||||||
effectiveArmourExplosiveTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
effectiveArmourExplosiveTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
||||||
effectiveArmourKineticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
effectiveArmourKineticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
||||||
effectiveArmourThermalTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
effectiveArmourThermalTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
||||||
effectiveArmourCausticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.int(armour.bulkheads)}</div>);
|
|
||||||
if (armour.reinforcement > 0) {
|
if (armour.reinforcement > 0) {
|
||||||
armourSourcesTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
armourSourcesTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
||||||
effectiveArmourAbsoluteTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
effectiveArmourAbsoluteTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
||||||
effectiveArmourExplosiveTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
effectiveArmourExplosiveTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
||||||
effectiveArmourKineticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
effectiveArmourKineticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
||||||
effectiveArmourThermalTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
effectiveArmourThermalTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
||||||
effectiveArmourCausticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.int(armour.reinforcement)}</div>);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,22 +183,17 @@ export default class Defence extends TranslatedComponent {
|
|||||||
const armourDamageTakenExplosiveTt = [];
|
const armourDamageTakenExplosiveTt = [];
|
||||||
armourDamageTakenExplosiveTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.explosive.bulkheads)}</div>);
|
armourDamageTakenExplosiveTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.explosive.bulkheads)}</div>);
|
||||||
armourDamageTakenExplosiveTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.explosive.reinforcement)}</div>);
|
armourDamageTakenExplosiveTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.explosive.reinforcement)}</div>);
|
||||||
if (armour.explosive.total != 1) effectiveArmourExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.explosive.total - rawArmour)}</div>);
|
if (armour.explosive.bulkheads * armour.explosive.reinforcement != 1) effectiveArmourExplosiveTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.explosive.bulkheads * armour.explosive.reinforcement) - rawArmour)}</div>);
|
||||||
|
|
||||||
const armourDamageTakenKineticTt = [];
|
const armourDamageTakenKineticTt = [];
|
||||||
armourDamageTakenKineticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.kinetic.bulkheads)}</div>);
|
armourDamageTakenKineticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.kinetic.bulkheads)}</div>);
|
||||||
armourDamageTakenKineticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.kinetic.reinforcement)}</div>);
|
armourDamageTakenKineticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.kinetic.reinforcement)}</div>);
|
||||||
if (armour.kinetic.total != 1) effectiveArmourKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.kinetic.total - rawArmour)}</div>);
|
if (armour.kinetic.bulkheads * armour.kinetic.reinforcement != 1) effectiveArmourKineticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.kinetic.bulkheads * armour.kinetic.reinforcement) - rawArmour)}</div>);
|
||||||
|
|
||||||
const armourDamageTakenThermalTt = [];
|
const armourDamageTakenThermalTt = [];
|
||||||
armourDamageTakenThermalTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.thermal.bulkheads)}</div>);
|
armourDamageTakenThermalTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.thermal.bulkheads)}</div>);
|
||||||
armourDamageTakenThermalTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.thermal.reinforcement)}</div>);
|
armourDamageTakenThermalTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.thermal.reinforcement)}</div>);
|
||||||
if (armour.thermal.total != 1) effectiveArmourThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.thermal.total - rawArmour)}</div>);
|
if (armour.thermal.bulkheads * armour.thermal.reinforcement != 1) effectiveArmourThermalTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / (armour.thermal.bulkheads * armour.thermal.reinforcement) - rawArmour)}</div>);
|
||||||
|
|
||||||
const armourDamageTakenCausticTt = [];
|
|
||||||
armourDamageTakenCausticTt.push(<div key='bulkheads'>{translate('bulkheads') + ' ' + formats.pct1(armour.caustic.bulkheads)}</div>);
|
|
||||||
armourDamageTakenCausticTt.push(<div key='reinforcement'>{translate('reinforcement') + ' ' + formats.pct1(armour.caustic.reinforcement)}</div>);
|
|
||||||
if (armour.thermal.total != 1) effectiveArmourCausticTt.push(<div key='resistance'>{translate('resistance') + ' ' + formats.int(rawArmour / armour.caustic.total - rawArmour)}</div>);
|
|
||||||
|
|
||||||
const effectiveArmourData = [];
|
const effectiveArmourData = [];
|
||||||
const effectiveAbsoluteArmour = armour.total / armour.absolute.total;
|
const effectiveAbsoluteArmour = armour.total / armour.absolute.total;
|
||||||
@@ -213,15 +204,12 @@ export default class Defence extends TranslatedComponent {
|
|||||||
effectiveArmourData.push({ value: Math.round(effectiveKineticArmour), label: translate('kinetic'), tooltip: effectiveArmourKineticTt });
|
effectiveArmourData.push({ value: Math.round(effectiveKineticArmour), label: translate('kinetic'), tooltip: effectiveArmourKineticTt });
|
||||||
const effectiveThermalArmour = armour.total / armour.thermal.total;
|
const effectiveThermalArmour = armour.total / armour.thermal.total;
|
||||||
effectiveArmourData.push({ value: Math.round(effectiveThermalArmour), label: translate('thermal'), tooltip: effectiveArmourThermalTt });
|
effectiveArmourData.push({ value: Math.round(effectiveThermalArmour), label: translate('thermal'), tooltip: effectiveArmourThermalTt });
|
||||||
const effectiveCausticArmour = armour.total / armour.caustic.total;
|
|
||||||
effectiveArmourData.push({ value: Math.round(effectiveCausticArmour), label: translate('caustic'), tooltip: effectiveArmourCausticTt });
|
|
||||||
|
|
||||||
const armourDamageTakenData = [];
|
const armourDamageTakenData = [];
|
||||||
armourDamageTakenData.push({ value: Math.round(armour.absolute.total * 100), label: translate('absolute'), tooltip: armourDamageTakenTt });
|
armourDamageTakenData.push({ value: Math.round(armour.absolute.total * 100), label: translate('absolute'), tooltip: armourDamageTakenTt });
|
||||||
armourDamageTakenData.push({ value: Math.round(armour.explosive.total * 100), label: translate('explosive'), tooltip: armourDamageTakenExplosiveTt });
|
armourDamageTakenData.push({ value: Math.round(armour.explosive.total * 100), label: translate('explosive'), tooltip: armourDamageTakenExplosiveTt });
|
||||||
armourDamageTakenData.push({ value: Math.round(armour.kinetic.total * 100), label: translate('kinetic'), tooltip: armourDamageTakenKineticTt });
|
armourDamageTakenData.push({ value: Math.round(armour.kinetic.total * 100), label: translate('kinetic'), tooltip: armourDamageTakenKineticTt });
|
||||||
armourDamageTakenData.push({ value: Math.round(armour.thermal.total * 100), label: translate('thermal'), tooltip: armourDamageTakenThermalTt });
|
armourDamageTakenData.push({ value: Math.round(armour.thermal.total * 100), label: translate('thermal'), tooltip: armourDamageTakenThermalTt });
|
||||||
armourDamageTakenData.push({ value: Math.round(armour.caustic.total * 100), label: translate('caustic'), tooltip: armourDamageTakenCausticTt });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span id='defence'>
|
<span id='defence'>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export default class FSDProfile extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
_calcMaxRange(ship, fuel, mass) {
|
_calcMaxRange(ship, fuel, mass) {
|
||||||
// Obtain the maximum range
|
// Obtain the maximum range
|
||||||
return Calc.jumpRange(mass, ship.standard[2].m, Math.min(fuel, ship.standard[2].m.getMaxFuelPerJump()), ship);
|
return Calc.jumpRange(mass, ship.standard[2].m, Math.min(fuel, ship.standard[2].m.getMaxFuelPerJump()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,7 +77,7 @@ export default class FSDProfile extends TranslatedComponent {
|
|||||||
const maxMass = thrusters.getMaxMass();
|
const maxMass = thrusters.getMaxMass();
|
||||||
const mass = ship.unladenMass + fuel + cargo;
|
const mass = ship.unladenMass + fuel + cargo;
|
||||||
const minRange = 0;
|
const minRange = 0;
|
||||||
const maxRange = Calc.jumpRange(minMass + fsd.getMaxFuelPerJump(), fsd, fsd.getMaxFuelPerJump(), ship);
|
const maxRange = Calc.jumpRange(minMass + fsd.getMaxFuelPerJump(), fsd, fsd.getMaxFuelPerJump());
|
||||||
// Add a mark at our current mass
|
// Add a mark at our current mass
|
||||||
const mark = Math.min(mass, maxMass);
|
const mark = Math.min(mass, maxMass);
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export default class HardpointSlot extends Slot {
|
|||||||
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'cb'}>
|
<div className={'cb'}>
|
||||||
{ m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')} onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} { m.getClip() ? <span>({formats.round1(m.getSDps()) })</span> : null }</div> : null }
|
{ m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')} onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getDps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
|
||||||
{ m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')} onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }{u.MW})</span> : null }</div> : null }
|
{ m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')} onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }{u.MW})</span> : null }</div> : null }
|
||||||
{ m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
|
{ m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
|
||||||
{ m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null }
|
{ m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null }
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import { Cogs, CoriolisLogo, Hammer, Help, Rocket, StatsBars } from './SvgIcons'
|
|||||||
import { Ships } from 'coriolis-data/dist';
|
import { Ships } from 'coriolis-data/dist';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
import { toDetailedExport } from '../shipyard/Serializer';
|
import { toDetailedExport } from '../shipyard/Serializer';
|
||||||
import Ship from '../shipyard/Ship';
|
|
||||||
import ModalBatchOrbis from './ModalBatchOrbis';
|
|
||||||
import ModalDeleteAll from './ModalDeleteAll';
|
import ModalDeleteAll from './ModalDeleteAll';
|
||||||
import ModalExport from './ModalExport';
|
import ModalExport from './ModalExport';
|
||||||
import ModalHelp from './ModalHelp';
|
import ModalHelp from './ModalHelp';
|
||||||
@@ -237,43 +235,6 @@ export default class Header extends TranslatedComponent {
|
|||||||
/>);
|
/>);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Uploads all ship-builds to orbis
|
|
||||||
* @param {e} e Event
|
|
||||||
*/
|
|
||||||
_uploadAllBuildsToOrbis(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const data = Persist.getBuilds();
|
|
||||||
let postObject = [];
|
|
||||||
for (const ship in data) {
|
|
||||||
for (const code in data[ship]) {
|
|
||||||
const shipModel = ship;
|
|
||||||
if (!shipModel) {
|
|
||||||
throw 'No such ship found: "' + ship + '"';
|
|
||||||
}
|
|
||||||
const shipTemplate = Ships[shipModel];
|
|
||||||
const shipPostObject = {};
|
|
||||||
let shipInstance = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
|
|
||||||
shipInstance.buildWith(null);
|
|
||||||
shipInstance.buildFrom(data[ship][code]);
|
|
||||||
shipPostObject.coriolisId = shipInstance.id;
|
|
||||||
shipPostObject.coriolisShip = shipInstance;
|
|
||||||
|
|
||||||
shipPostObject.coriolisShip.url = window.location.origin + outfitURL(shipModel, data[ship][code], code);
|
|
||||||
shipPostObject.title = code || shipInstance.id;
|
|
||||||
shipPostObject.description = code || shipInstance.id;
|
|
||||||
shipPostObject.ShipName = shipInstance.id;
|
|
||||||
shipPostObject.Ship = shipInstance.id;
|
|
||||||
postObject.push(shipPostObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(postObject);
|
|
||||||
|
|
||||||
this.context.showModal(<ModalBatchOrbis
|
|
||||||
ships={postObject}
|
|
||||||
/>);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show export modal with detailed export
|
* Show export modal with detailed export
|
||||||
* @param {SyntheticEvent} e Event
|
* @param {SyntheticEvent} e Event
|
||||||
@@ -469,7 +430,6 @@ export default class Header extends TranslatedComponent {
|
|||||||
{translate('builds')} & {translate('comparisons')}
|
{translate('builds')} & {translate('comparisons')}
|
||||||
<li><Link href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._uploadAllBuildsToOrbis.bind(this)}>{translate('upload all builds to orbis')}</Link></li>
|
|
||||||
<li><Link href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</Link></li>
|
||||||
<li><Link href="#" className='block' onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</Link></li>
|
<li><Link href="#" className='block' onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -571,16 +531,6 @@ export default class Header extends TranslatedComponent {
|
|||||||
{openedMenu == 'comp' ? this._getComparisonsMenu() : null}
|
{openedMenu == 'comp' ? this._getComparisonsMenu() : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{window.location.origin.search('.edcd.io') >= 0 ?
|
|
||||||
<div className='l menu'>
|
|
||||||
<a href="https://youtu.be/4SvnLcefhtI" target="_blank">
|
|
||||||
<div className={cn('menu-header')}>
|
|
||||||
<Rocket className='warning'/><span className='menu-item-label'>{translate('please migrate to coriolis.io')}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className='r menu'>
|
<div className='r menu'>
|
||||||
<div className={cn('menu-header', { selected: openedMenu == 'settings' })} onClick={this._openSettings}>
|
<div className={cn('menu-header', { selected: openedMenu == 'settings' })} onClick={this._openSettings}>
|
||||||
<Cogs className='xl warning'/><span className='menu-item-label'>{translate('settings')}</span>
|
<Cogs className='xl warning'/><span className='menu-item-label'>{translate('settings')}</span>
|
||||||
|
|||||||
@@ -63,9 +63,6 @@ export default class InternalSlot extends Slot {
|
|||||||
{ m.getSpinup() ? <div className={'l'}>{translate('spinup')}: {formats.f1(m.getSpinup())}{u.s}</div> : null }
|
{ m.getSpinup() ? <div className={'l'}>{translate('spinup')}: {formats.f1(m.getSpinup())}{u.s}</div> : null }
|
||||||
{ m.getDuration() ? <div className={'l'}>{translate('duration')}: {formats.f1(m.getDuration())}{u.s}</div> : null }
|
{ m.getDuration() ? <div className={'l'}>{translate('duration')}: {formats.f1(m.getDuration())}{u.s}</div> : null }
|
||||||
{ m.grp === 'scb' ? <div className={'l'}>{translate('cells')}: {formats.int(m.getAmmo() + 1)}</div> : null }
|
{ m.grp === 'scb' ? <div className={'l'}>{translate('cells')}: {formats.int(m.getAmmo() + 1)}</div> : null }
|
||||||
{ m.grp === 'gsrp' ? <div className={'l'}>{translate('shield addition')}: {formats.f1(m.getShieldAddition())}{u.MJ}</div> : null }
|
|
||||||
{ m.grp === 'gfsb' ? <div className={'l'}>{translate('jump addition')}: {formats.f1(m.getJumpBoost())}{u.LY}</div> : null }
|
|
||||||
{ m.grp === 'gs' ? <div className={'l'}>{translate('shield addition')}: {formats.f1(m.getShieldAddition())}{u.MJ}</div> : null }
|
|
||||||
{ m.getShieldReinforcement() ? <div className={'l'}>{translate('shieldreinforcement')}: {formats.f1(m.getDuration() * m.getShieldReinforcement())}{u.MJ}</div> : null }
|
{ m.getShieldReinforcement() ? <div className={'l'}>{translate('shieldreinforcement')}: {formats.f1(m.getDuration() * m.getShieldReinforcement())}{u.MJ}</div> : null }
|
||||||
{ m.getShieldReinforcement() ? <div className={'l'}>{translate('total')}: {formats.int((m.getAmmo() + 1) * (m.getDuration() * m.getShieldReinforcement()))}{u.MJ}</div> : null }
|
{ m.getShieldReinforcement() ? <div className={'l'}>{translate('total')}: {formats.int((m.getAmmo() + 1) * (m.getDuration() * m.getShieldReinforcement()))}{u.MJ}</div> : null }
|
||||||
{ m.repair ? <div className={'l'}>{translate('repair')}: {m.repair}</div> : null }
|
{ m.repair ? <div className={'l'}>{translate('repair')}: {m.repair}</div> : null }
|
||||||
@@ -85,7 +82,6 @@ export default class InternalSlot extends Slot {
|
|||||||
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }
|
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }
|
||||||
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
|
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
|
||||||
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
|
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
|
||||||
{ showModuleResistances && m.getCausticResistance() ? <div className='l'>{translate('causres')}: {formats.pct(m.getCausticResistance())}</div> : null }
|
|
||||||
{ m.getHullReinforcement() ? <div className='l'>{translate('armour')}: {formats.int(m.getHullReinforcement() + ship.baseArmour * m.getModValue('hullboost') / 10000)}</div> : null }
|
{ m.getHullReinforcement() ? <div className='l'>{translate('armour')}: {formats.int(m.getHullReinforcement() + ship.baseArmour * m.getModValue('hullboost') / 10000)}</div> : null }
|
||||||
{ m.getProtection() ? <div className='l'>{translate('protection')}: {formats.rPct(m.getProtection())}</div> : null }
|
{ m.getProtection() ? <div className='l'>{translate('protection')}: {formats.rPct(m.getProtection())}</div> : null }
|
||||||
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default class JumpRange extends TranslatedComponent {
|
|||||||
const fuel = this.state.fuelLevel * ship.fuelCapacity;
|
const fuel = this.state.fuelLevel * ship.fuelCapacity;
|
||||||
|
|
||||||
// Obtain the jump range
|
// Obtain the jump range
|
||||||
return Calc.jumpRange(ship.unladenMass + fuel + cargo, fsd, fuel, ship);
|
return Calc.jumpRange(ship.unladenMass + fuel + cargo, fsd, fuel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,281 +1,283 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ContainerDimensions from 'react-container-dimensions';
|
import Measure from 'react-measure';
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
|
|
||||||
const MARGIN = { top: 15, right: 20, bottom: 35, left: 60 };
|
const MARGIN = { top: 15, right: 20, bottom: 35, left: 60 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line Chart
|
* Line Chart
|
||||||
*/
|
*/
|
||||||
export default class LineChart extends TranslatedComponent {
|
export default class LineChart extends TranslatedComponent {
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
code: '',
|
code: '',
|
||||||
xMin: 0,
|
xMin: 0,
|
||||||
yMin: 0,
|
yMin: 0,
|
||||||
points: 20,
|
points: 20,
|
||||||
colors: ['#ff8c0d'],
|
colors: ['#ff8c0d'],
|
||||||
aspect: 0.5
|
aspect: 0.5
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
func: PropTypes.func.isRequired,
|
func: PropTypes.func.isRequired,
|
||||||
xLabel: PropTypes.string.isRequired,
|
xLabel: PropTypes.string.isRequired,
|
||||||
xMin: PropTypes.number,
|
xMin: PropTypes.number,
|
||||||
xMax: PropTypes.number.isRequired,
|
xMax: PropTypes.number.isRequired,
|
||||||
xUnit: PropTypes.string.isRequired,
|
xUnit: PropTypes.string.isRequired,
|
||||||
xMark: PropTypes.number,
|
xMark: PropTypes.number,
|
||||||
yLabel: PropTypes.string.isRequired,
|
yLabel: PropTypes.string.isRequired,
|
||||||
yMin: PropTypes.number,
|
yMin: PropTypes.number,
|
||||||
yMax: PropTypes.number.isRequired,
|
yMax: PropTypes.number.isRequired,
|
||||||
yUnit: PropTypes.string,
|
yUnit: PropTypes.string,
|
||||||
series: PropTypes.array,
|
series: PropTypes.array,
|
||||||
colors: PropTypes.array,
|
colors: PropTypes.array,
|
||||||
points: PropTypes.number,
|
points: PropTypes.number,
|
||||||
aspect: PropTypes.number,
|
aspect: PropTypes.number,
|
||||||
code: PropTypes.string,
|
code: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
* @param {Object} context React Component context
|
* @param {Object} context React Component context
|
||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this._updateDimensions = this._updateDimensions.bind(this);
|
this._updateDimensions = this._updateDimensions.bind(this);
|
||||||
this._updateSeries = this._updateSeries.bind(this);
|
this._updateSeries = this._updateSeries.bind(this);
|
||||||
this._tooltip = this._tooltip.bind(this);
|
this._tooltip = this._tooltip.bind(this);
|
||||||
this._showTip = this._showTip.bind(this);
|
this._showTip = this._showTip.bind(this);
|
||||||
this._hideTip = this._hideTip.bind(this);
|
this._hideTip = this._hideTip.bind(this);
|
||||||
this._moveTip = this._moveTip.bind(this);
|
this._moveTip = this._moveTip.bind(this);
|
||||||
|
|
||||||
const series = props.series;
|
const series = props.series;
|
||||||
|
|
||||||
let xScale = d3.scaleLinear();
|
let xScale = d3.scaleLinear();
|
||||||
let yScale = d3.scaleLinear();
|
let yScale = d3.scaleLinear();
|
||||||
let xAxisScale = d3.scaleLinear();
|
let xAxisScale = d3.scaleLinear();
|
||||||
|
|
||||||
this.xAxis = d3.axisBottom(xAxisScale).tickSizeOuter(0);
|
this.xAxis = d3.axisBottom(xAxisScale).tickSizeOuter(0);
|
||||||
this.yAxis = d3.axisLeft(yScale).ticks(6).tickSizeOuter(0);
|
this.yAxis = d3.axisLeft(yScale).ticks(6).tickSizeOuter(0);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
xScale,
|
xScale,
|
||||||
xAxisScale,
|
xAxisScale,
|
||||||
yScale,
|
yScale,
|
||||||
tipHeight: 2 + (1.2 * (series ? series.length : 0.8)),
|
tipHeight: 2 + (1.2 * (series ? series.length : 0.8)),
|
||||||
};
|
dimensions: {
|
||||||
}
|
width: 100,
|
||||||
|
height: 100
|
||||||
/**
|
}
|
||||||
* Update tooltip content
|
};
|
||||||
* @param {number} xPos x coordinate
|
}
|
||||||
* @param {number} width current container width
|
|
||||||
*/
|
/**
|
||||||
_tooltip(xPos, width) {
|
* Update tooltip content
|
||||||
let { xLabel, yLabel, xUnit, yUnit, func, series } = this.props;
|
* @param {number} xPos x coordinate
|
||||||
let { xScale, yScale } = this.state;
|
*/
|
||||||
let { formats, translate } = this.context.language;
|
_tooltip(xPos) {
|
||||||
let x0 = xScale.invert(xPos),
|
let { xLabel, yLabel, xUnit, yUnit, func, series } = this.props;
|
||||||
y0 = func(x0),
|
let { xScale, yScale } = this.state;
|
||||||
tips = this.tipContainer,
|
let { width } = this.state.dimensions;
|
||||||
yTotal = 0,
|
let { formats, translate } = this.context.language;
|
||||||
flip = (xPos / width > 0.50),
|
let x0 = xScale.invert(xPos),
|
||||||
tipWidth = 0,
|
y0 = func(x0),
|
||||||
tipHeightPx = tips.selectAll('rect').node().getBoundingClientRect().height;
|
tips = this.tipContainer,
|
||||||
|
yTotal = 0,
|
||||||
|
flip = (xPos / width > 0.50),
|
||||||
xPos = xScale(x0); // Clamp xPos
|
tipWidth = 0,
|
||||||
|
tipHeightPx = tips.selectAll('rect').node().getBoundingClientRect().height;
|
||||||
tips.selectAll('text.text-tip.y').text(function(d, i) {
|
|
||||||
let yVal = series ? y0[series[i]] : y0;
|
|
||||||
yTotal += yVal;
|
xPos = xScale(x0); // Clamp xPos
|
||||||
return (series ? translate(series[i]) : '') + ' ' + formats.f2(yVal);
|
|
||||||
}).append('tspan').attr('class', 'metric').text(yUnit ? ' ' + yUnit : '');
|
tips.selectAll('text.text-tip.y').text(function(d, i) {
|
||||||
|
let yVal = series ? y0[series[i]] : y0;
|
||||||
tips.selectAll('text').each(function() {
|
yTotal += yVal;
|
||||||
if (this.getBBox().width > tipWidth) {
|
return (series ? translate(series[i]) : '') + ' ' + formats.f2(yVal);
|
||||||
tipWidth = Math.ceil(this.getBBox().width);
|
}).append('tspan').attr('class', 'metric').text(yUnit ? ' ' + yUnit : '');
|
||||||
}
|
|
||||||
});
|
tips.selectAll('text').each(function() {
|
||||||
|
if (this.getBBox().width > tipWidth) {
|
||||||
let tipY = Math.floor(yScale(yTotal / (series ? series.length : 1)) - (tipHeightPx / 2));
|
tipWidth = Math.ceil(this.getBBox().width);
|
||||||
|
}
|
||||||
tipWidth += 8;
|
});
|
||||||
tips.attr('transform', 'translate(' + xPos + ',' + tipY + ')');
|
|
||||||
tips.selectAll('text.text-tip').attr('x', flip ? -12 : 12).style('text-anchor', flip ? 'end' : 'start');
|
let tipY = Math.floor(yScale(yTotal / (series ? series.length : 1)) - (tipHeightPx / 2));
|
||||||
tips.selectAll('text.text-tip.x').text(formats.f2(x0)).append('tspan').attr('class', 'metric').text(' ' + xUnit);
|
|
||||||
tips.selectAll('rect').attr('width', tipWidth + 4).attr('x', flip ? -tipWidth - 12 : 8).attr('y', 0).style('text-anchor', flip ? 'end' : 'start');
|
tipWidth += 8;
|
||||||
this.markersContainer.selectAll('circle').attr('cx', xPos).attr('cy', (d, i) => yScale(series ? y0[series[i]] : y0));
|
tips.attr('transform', 'translate(' + xPos + ',' + tipY + ')');
|
||||||
}
|
tips.selectAll('text.text-tip').attr('x', flip ? -12 : 12).style('text-anchor', flip ? 'end' : 'start');
|
||||||
|
tips.selectAll('text.text-tip.x').text(formats.f2(x0)).append('tspan').attr('class', 'metric').text(' ' + xUnit);
|
||||||
/**
|
tips.selectAll('rect').attr('width', tipWidth + 4).attr('x', flip ? -tipWidth - 12 : 8).attr('y', 0).style('text-anchor', flip ? 'end' : 'start');
|
||||||
* Update dimensions based on properties and scale
|
this.markersContainer.selectAll('circle').attr('cx', xPos).attr('cy', (d, i) => yScale(series ? y0[series[i]] : y0));
|
||||||
* @param {Object} props React Component properties
|
}
|
||||||
* @param {number} scale size ratio / scale
|
|
||||||
* @param {number} width current width of the container
|
/**
|
||||||
* @returns {Object} calculated dimensions
|
* Update dimensions based on properties and scale
|
||||||
*/
|
* @param {Object} props React Component properties
|
||||||
_updateDimensions(props, scale, width) {
|
* @param {number} scale size ratio / scale
|
||||||
const { xMax, xMin, yMin, yMax } = props;
|
* @returns {Object} calculated dimensions
|
||||||
const innerWidth = width - MARGIN.left - MARGIN.right;
|
*/
|
||||||
const outerHeight = Math.round(width * props.aspect);
|
_updateDimensions(props, scale) {
|
||||||
const innerHeight = outerHeight - MARGIN.top - MARGIN.bottom;
|
const { xMax, xMin, yMin, yMax } = props;
|
||||||
|
const { width, height } = this.state.dimensions;
|
||||||
this.state.xScale.range([0, innerWidth]).domain([xMin, xMax || 1]).clamp(true);
|
const innerWidth = width - MARGIN.left - MARGIN.right;
|
||||||
this.state.xAxisScale.range([0, innerWidth]).domain([xMin, xMax]).clamp(true);
|
const outerHeight = Math.round(width * props.aspect);
|
||||||
this.state.yScale.range([innerHeight, 0]).domain([yMin, yMax + (yMax - yMin) * 0.1]); // 10% higher than maximum value for tooltip visibility
|
const innerHeight = outerHeight - MARGIN.top - MARGIN.bottom;
|
||||||
return { innerWidth, outerHeight, innerHeight };
|
|
||||||
}
|
this.state.xScale.range([0, innerWidth]).domain([xMin, xMax || 1]).clamp(true);
|
||||||
|
this.state.xAxisScale.range([0, innerWidth]).domain([xMin, xMax]).clamp(true);
|
||||||
/**
|
this.state.yScale.range([innerHeight, 0]).domain([yMin, yMax + (yMax - yMin) * 0.1]); // 10% higher than maximum value for tooltip visibility
|
||||||
* Show tooltip
|
return { innerWidth, outerHeight, innerHeight };
|
||||||
* @param {SyntheticEvent} e Event
|
}
|
||||||
*/
|
|
||||||
_showTip(e) {
|
/**
|
||||||
e.preventDefault();
|
* Show tooltip
|
||||||
this.tipContainer.style('display', null);
|
* @param {SyntheticEvent} e Event
|
||||||
this.markersContainer.style('display', null);
|
*/
|
||||||
this._moveTip(e);
|
_showTip(e) {
|
||||||
}
|
e.preventDefault();
|
||||||
|
this.tipContainer.style('display', null);
|
||||||
/**
|
this.markersContainer.style('display', null);
|
||||||
* Move and update tooltip
|
this._moveTip(e);
|
||||||
* @param {SyntheticEvent} e Event
|
}
|
||||||
* @param {number} width current container width
|
|
||||||
*/
|
/**
|
||||||
_moveTip(e, width) {
|
* Move and update tooltip
|
||||||
let clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
* @param {SyntheticEvent} e Event
|
||||||
this._tooltip(Math.round(clientX - e.currentTarget.getBoundingClientRect().left), width);
|
*/
|
||||||
}
|
_moveTip(e) {
|
||||||
|
let clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
||||||
/**
|
this._tooltip(Math.round(clientX - e.currentTarget.getBoundingClientRect().left));
|
||||||
* Hide tooltip
|
}
|
||||||
* @param {SyntheticEvent} e Event
|
|
||||||
*/
|
/**
|
||||||
_hideTip(e) {
|
* Hide tooltip
|
||||||
e.preventDefault();
|
* @param {SyntheticEvent} e Event
|
||||||
this.tipContainer.style('display', 'none');
|
*/
|
||||||
this.markersContainer.style('display', 'none');
|
_hideTip(e) {
|
||||||
}
|
e.preventDefault();
|
||||||
|
this.tipContainer.style('display', 'none');
|
||||||
/**
|
this.markersContainer.style('display', 'none');
|
||||||
* Update series generated from props
|
}
|
||||||
* @param {Object} props React Component properties
|
|
||||||
* @param {Object} state React Component state
|
/**
|
||||||
*/
|
* Update series generated from props
|
||||||
_updateSeries(props, state) {
|
* @param {Object} props React Component properties
|
||||||
let { func, xMin, xMax, series, points } = props;
|
* @param {Object} state React Component state
|
||||||
let delta = (xMax - xMin) / points;
|
*/
|
||||||
let seriesData = new Array(points);
|
_updateSeries(props, state) {
|
||||||
|
let { func, xMin, xMax, series, points } = props;
|
||||||
if (delta) {
|
let delta = (xMax - xMin) / points;
|
||||||
seriesData = new Array(points);
|
let seriesData = new Array(points);
|
||||||
for (let i = 0, x = xMin; i < points; i++) {
|
|
||||||
seriesData[i] = [x, func(x)];
|
if (delta) {
|
||||||
x += delta;
|
seriesData = new Array(points);
|
||||||
}
|
for (let i = 0, x = xMin; i < points; i++) {
|
||||||
seriesData[points - 1] = [xMax, func(xMax)];
|
seriesData[i] = [x, func(x)];
|
||||||
} else {
|
x += delta;
|
||||||
let yVal = func(xMin);
|
}
|
||||||
seriesData = [[0, yVal], [1, yVal]];
|
seriesData[points - 1] = [xMax, func(xMax)];
|
||||||
}
|
} else {
|
||||||
|
let yVal = func(xMin);
|
||||||
const markerElems = [];
|
seriesData = [[0, yVal], [1, yVal]];
|
||||||
const detailElems = [<text key='lbl' className='text-tip x' y='1.25em'/>];
|
}
|
||||||
const seriesLines = [];
|
|
||||||
for (let i = 0, l = series ? series.length : 1; i < l; i++) {
|
const markerElems = [];
|
||||||
const yAccessor = series ? function(d) { return state.yScale(d[1][this]); }.bind(series[i]) : (d) => state.yScale(d[1]);
|
const detailElems = [<text key='lbl' className='text-tip x' y='1.25em'/>];
|
||||||
seriesLines.push(d3.line().x((d, i) => this.state.xScale(d[0])).y(yAccessor));
|
const seriesLines = [];
|
||||||
detailElems.push(<text key={i} className='text-tip y' strokeWidth={0} fill={props.colors[i]} y={1.25 * (i + 2) + 'em'}/>);
|
for (let i = 0, l = series ? series.length : 1; i < l; i++) {
|
||||||
markerElems.push(<circle key={i} className='marker' r='4' />);
|
const yAccessor = series ? function(d) { return state.yScale(d[1][this]); }.bind(series[i]) : (d) => state.yScale(d[1]);
|
||||||
}
|
seriesLines.push(d3.line().x((d, i) => this.state.xScale(d[0])).y(yAccessor));
|
||||||
|
detailElems.push(<text key={i} className='text-tip y' strokeWidth={0} fill={props.colors[i]} y={1.25 * (i + 2) + 'em'}/>);
|
||||||
const tipHeight = 2 + (1.2 * (seriesLines ? seriesLines.length : 0.8));
|
markerElems.push(<circle key={i} className='marker' r='4' />);
|
||||||
|
}
|
||||||
this.setState({ markerElems, detailElems, seriesLines, seriesData, tipHeight });
|
|
||||||
}
|
const tipHeight = 2 + (1.2 * (seriesLines ? seriesLines.length : 0.8));
|
||||||
|
|
||||||
/**
|
this.setState({ markerElems, detailElems, seriesLines, seriesData, tipHeight });
|
||||||
* Update dimensions and series data based on props and context.
|
}
|
||||||
*/
|
|
||||||
componentWillMount() {
|
/**
|
||||||
this._updateSeries(this.props, this.state);
|
* Update dimensions and series data based on props and context.
|
||||||
}
|
*/
|
||||||
|
componentWillMount() {
|
||||||
/**
|
this._updateSeries(this.props, this.state);
|
||||||
* Update state based on property and context changes
|
}
|
||||||
* @param {Object} nextProps Incoming/Next properties
|
|
||||||
* @param {Object} nextContext Incoming/Next conext
|
/**
|
||||||
*/
|
* Update state based on property and context changes
|
||||||
componentWillReceiveProps(nextProps, nextContext) {
|
* @param {Object} nextProps Incoming/Next properties
|
||||||
const props = this.props;
|
* @param {Object} nextContext Incoming/Next conext
|
||||||
|
*/
|
||||||
if (props.code != nextProps.code) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
this._updateSeries(nextProps, this.state);
|
const props = this.props;
|
||||||
}
|
|
||||||
}
|
if (props.code != nextProps.code) {
|
||||||
|
this._updateSeries(nextProps, this.state);
|
||||||
/**
|
}
|
||||||
* Render the chart
|
}
|
||||||
* @return {React.Component} Chart SVG
|
|
||||||
*/
|
/**
|
||||||
render() {
|
* Render the chart
|
||||||
return (
|
* @return {React.Component} Chart SVG
|
||||||
<ContainerDimensions>
|
*/
|
||||||
{ ({ width, height }) => {
|
render() {
|
||||||
const { innerWidth, outerHeight, innerHeight } = this._updateDimensions(this.props, this.context.sizeRatio, width, height);
|
const { innerWidth, outerHeight, innerHeight } = this._updateDimensions(this.props, this.context.sizeRatio);
|
||||||
const { xMin, xMax, xLabel, yLabel, xUnit, yUnit, xMark, colors } = this.props;
|
const { width, height } = this.state.dimensions;
|
||||||
const { tipHeight, detailElems, markerElems, seriesData, seriesLines } = this.state;
|
const { xMin, xMax, xLabel, yLabel, xUnit, yUnit, xMark, colors } = this.props;
|
||||||
const lines = seriesLines.map((line, i) => <path key={i} className='line' fill='none' stroke={colors[i]} strokeWidth='1' d={line(seriesData)} />).reverse();
|
const { tipHeight, detailElems, markerElems, seriesData, seriesLines } = this.state;
|
||||||
|
const line = this.line;
|
||||||
const markX = xMark ? innerWidth * (xMark - xMin) / (xMax - xMin) : 0;
|
const lines = seriesLines.map((line, i) => <path key={i} className='line' fill='none' stroke={colors[i]} strokeWidth='1' d={line(seriesData)} />).reverse();
|
||||||
const xmark = xMark ? <path key={'mark'} className='line' fill='none' strokeDasharray='5,5' stroke={'#ff8c0d'} strokeWidth='1' d={'M ' + markX + ' ' + innerHeight + ' L ' + markX + ' 0'} /> : '';
|
|
||||||
return (
|
const markX = xMark ? innerWidth * (xMark - xMin) / (xMax - xMin) : 0;
|
||||||
<div width={width} height={height}>
|
const xmark = xMark ? <path key={'mark'} className='line' fill='none' strokeDasharray='5,5' stroke={'#ff8c0d'} strokeWidth='1' d={'M ' + markX + ' ' + innerHeight + ' L ' + markX + ' 0'} /> : '';
|
||||||
<svg style={{ width: '100%', height: outerHeight }}>
|
|
||||||
<g transform={`translate(${MARGIN.left},${MARGIN.top})`}>
|
return (
|
||||||
<g>{xmark}</g>
|
<Measure width='100%' whitelist={['width', 'top']} onMeasure={ (dimensions) => { this.setState({ dimensions }); }}>
|
||||||
<g>{lines}</g>
|
<div width={width} height={height}>
|
||||||
<g className='x axis' ref={(elem) => d3.select(elem).call(this.xAxis)} transform={`translate(0,${innerHeight})`}>
|
<svg style={{ width: '100%', height: outerHeight }}>
|
||||||
<text className='cap' y='30' dy='.1em' x={innerWidth / 2} style={{ textAnchor: 'middle' }}>
|
<g transform={`translate(${MARGIN.left},${MARGIN.top})`}>
|
||||||
<tspan>{xLabel}</tspan>
|
<g>{xmark}</g>
|
||||||
<tspan className='metric'> ({xUnit})</tspan>
|
<g>{lines}</g>
|
||||||
</text>
|
<g className='x axis' ref={(elem) => d3.select(elem).call(this.xAxis)} transform={`translate(0,${innerHeight})`}>
|
||||||
</g>
|
<text className='cap' y='30' dy='.1em' x={innerWidth / 2} style={{ textAnchor: 'middle' }}>
|
||||||
<g className='y axis' ref={(elem) => d3.select(elem).call(this.yAxis)}>
|
<tspan>{xLabel}</tspan>
|
||||||
<text className='cap' transform='rotate(-90)' y='-50' dy='.1em' x={innerHeight / -2} style={{ textAnchor: 'middle' }}>
|
<tspan className='metric'> ({xUnit})</tspan>
|
||||||
<tspan>{yLabel}</tspan>
|
</text>
|
||||||
{ yUnit && <tspan className='metric'> ({yUnit})</tspan> }
|
</g>
|
||||||
</text>
|
<g className='y axis' ref={(elem) => d3.select(elem).call(this.yAxis)}>
|
||||||
</g>
|
<text className='cap' transform='rotate(-90)' y='-50' dy='.1em' x={innerHeight / -2} style={{ textAnchor: 'middle' }}>
|
||||||
<g ref={(g) => this.tipContainer = d3.select(g)} style={{ display: 'none' }}>
|
<tspan>{yLabel}</tspan>
|
||||||
<rect className='tooltip' height={tipHeight + 'em'}></rect>
|
{ yUnit && <tspan className='metric'> ({yUnit})</tspan> }
|
||||||
{detailElems}
|
</text>
|
||||||
</g>
|
</g>
|
||||||
<g ref={(g) => this.markersContainer = d3.select(g)} style={{ display: 'none' }}>
|
<g ref={(g) => this.tipContainer = d3.select(g)} style={{ display: 'none' }}>
|
||||||
{markerElems}
|
<rect className='tooltip' height={tipHeight + 'em'}></rect>
|
||||||
</g>
|
{detailElems}
|
||||||
<rect
|
</g>
|
||||||
fillOpacity='0'
|
<g ref={(g) => this.markersContainer = d3.select(g)} style={{ display: 'none' }}>
|
||||||
height={innerHeight}
|
{markerElems}
|
||||||
width={innerWidth + 1}
|
</g>
|
||||||
onMouseEnter={this._showTip}
|
<rect
|
||||||
onTouchStart={this._showTip}
|
fillOpacity='0'
|
||||||
onMouseLeave={this._hideTip}
|
height={innerHeight}
|
||||||
onTouchEnd={this._hideTip}
|
width={innerWidth + 1}
|
||||||
onMouseMove={e => this._moveTip(e, width)}
|
onMouseEnter={this._showTip}
|
||||||
onTouchMove={e => this._moveTip(e, width)}
|
onTouchStart={this._showTip}
|
||||||
/>
|
onMouseLeave={this._hideTip}
|
||||||
</g>
|
onTouchEnd={this._hideTip}
|
||||||
</svg>
|
onMouseMove={this._moveTip}
|
||||||
</div>
|
onTouchMove={this._moveTip}
|
||||||
);
|
/>
|
||||||
}}
|
</g>
|
||||||
</ContainerDimensions>
|
</svg>
|
||||||
);
|
</div>
|
||||||
}
|
</Measure>
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import request from 'superagent';
|
|
||||||
import TranslatedComponent from './TranslatedComponent';
|
|
||||||
import { orbisUpload } from '../utils/ShortenUrl';
|
|
||||||
import Persist from '../stores/Persist';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Permalink modal
|
|
||||||
*/
|
|
||||||
export default class ModalBatchOrbis extends TranslatedComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
ships: PropTypes.any.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param {Object} props React Component properties
|
|
||||||
*/
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
orbisCreds: Persist.getOrbisCreds(),
|
|
||||||
resp: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send ship to Orbis.zone
|
|
||||||
* @param {SyntheticEvent} e React Event
|
|
||||||
* @return {Promise} Promise sending post request to orbis
|
|
||||||
*/
|
|
||||||
sendToOrbis(e) {
|
|
||||||
let agent;
|
|
||||||
try {
|
|
||||||
agent = request.agent(); // apparently this crashes somehow
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
if (!agent) {
|
|
||||||
agent = request;
|
|
||||||
}
|
|
||||||
const API_ORBIS = 'https://orbis.zone/api/builds/add/batch';
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
agent
|
|
||||||
.post(API_ORBIS)
|
|
||||||
.withCredentials()
|
|
||||||
.redirects(0)
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.send(this.props.ships)
|
|
||||||
.end((err, response) => {
|
|
||||||
console.log(response);
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
this.setState({ resp: response.text });
|
|
||||||
reject('Bad Request');
|
|
||||||
} else {
|
|
||||||
this.setState({ resp: 'All builds uploaded. Check https://orbis.zone' });
|
|
||||||
resolve('All builds uploaded. Check https://orbis.zone');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
reject(e.message ? e.message : e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the modal
|
|
||||||
* @return {React.Component} Modal Content
|
|
||||||
*/
|
|
||||||
render() {
|
|
||||||
let translate = this.context.language.translate;
|
|
||||||
this.sendToOrbis = this.sendToOrbis.bind(this);
|
|
||||||
|
|
||||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
|
||||||
<h2>{translate('permalink')}</h2>
|
|
||||||
<br/>
|
|
||||||
<a className='button' href="https://orbis.zone/api/auth">Log in / signup to Orbis</a>
|
|
||||||
<br/><br/>
|
|
||||||
<h3 >{translate('success')}</h3>
|
|
||||||
<input value={this.state.resp} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
|
||||||
<br/><br/>
|
|
||||||
<p>Orbis.zone is currently in a trial period, and may be wiped at any time as development progresses. Some elements are also still placeholders.</p>
|
|
||||||
<button className={'l cb dismiss cap'} disabled={!!this.state.failed} onClick={this.sendToOrbis}>{translate('PHASE_UPLOAD_ORBIS')}</button>
|
|
||||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -126,11 +126,7 @@ export default class ModalImport extends TranslatedComponent {
|
|||||||
if (importData.builds && typeof importData.builds == 'object') {
|
if (importData.builds && typeof importData.builds == 'object') {
|
||||||
for (let shipId in importData.builds) {
|
for (let shipId in importData.builds) {
|
||||||
for (let buildName in importData.builds[shipId]) {
|
for (let buildName in importData.builds[shipId]) {
|
||||||
try {
|
validateBuild(shipId, importData.builds[shipId][buildName], buildName);
|
||||||
validateBuild(shipId, importData.builds[shipId][buildName], buildName);
|
|
||||||
} catch (err) {
|
|
||||||
delete importData.builds[shipId][buildName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setState({ builds: importData.builds });
|
this.setState({ builds: importData.builds });
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import TranslatedComponent from './TranslatedComponent';
|
|
||||||
import { orbisUpload } from '../utils/ShortenUrl';
|
|
||||||
import Persist from '../stores/Persist';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Permalink modal
|
|
||||||
*/
|
|
||||||
export default class ModalOrbis extends TranslatedComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
ship: PropTypes.any.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
* @param {Object} props React Component properties
|
|
||||||
*/
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
orbisCreds: Persist.getOrbisCreds(),
|
|
||||||
orbisUrl: '...',
|
|
||||||
authenticatedStatus: 'Checking...'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send ship to Orbis.zone
|
|
||||||
* @param {SyntheticEvent} e React Event
|
|
||||||
*/
|
|
||||||
sendToOrbis(e) {
|
|
||||||
const target = e.target;
|
|
||||||
target.disabled = true;
|
|
||||||
this.setState({ orbisUrl: 'Sending...' }, () => {
|
|
||||||
orbisUpload(this.props.ship, this.state.orbisCreds)
|
|
||||||
.then(orbisUrl => {
|
|
||||||
target.disabled = false;
|
|
||||||
this.setState({ orbisUrl });
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
target.disabled = false;
|
|
||||||
this.setState({ orbisUrl: 'Error - ' + err });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Orbis.zone auth status
|
|
||||||
* @returns {Object} auth status
|
|
||||||
*/
|
|
||||||
getOrbisAuthStatus() {
|
|
||||||
return fetch('https://orbis.zone/api/checkauth', {
|
|
||||||
credentials: 'include',
|
|
||||||
mode: 'cors'
|
|
||||||
})
|
|
||||||
.then(data => data.json())
|
|
||||||
.then(res => {
|
|
||||||
this.setState({ authenticatedStatus: res.status || res.error });
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err);
|
|
||||||
this.setState({ authenticatedStatus: err.message });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for changing cmdr name
|
|
||||||
* @param {SyntheticEvent} e React Event
|
|
||||||
*/
|
|
||||||
orbisPasswordHandler(e) {
|
|
||||||
let password = e.target.value;
|
|
||||||
this.setState({ orbisCreds: { email: this.state.orbisCreds.email, password } }, () => {
|
|
||||||
Persist.setOrbisCreds(this.state.orbisCreds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for changing cmdr name
|
|
||||||
* @param {SyntheticEvent} e React Event
|
|
||||||
*/
|
|
||||||
orbisUsername(e) {
|
|
||||||
let orbisUsername = e.target.value;
|
|
||||||
this.setState({ orbisCreds: { email: orbisUsername, password: this.state.orbisCreds.password } }, () => {
|
|
||||||
Persist.setOrbisCreds(this.state.orbisCreds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the modal
|
|
||||||
* @return {React.Component} Modal Content
|
|
||||||
*/
|
|
||||||
render() {
|
|
||||||
let translate = this.context.language.translate;
|
|
||||||
this.orbisPasswordHandler = this.orbisPasswordHandler.bind(this);
|
|
||||||
this.orbisUsername = this.orbisUsername.bind(this);
|
|
||||||
this.sendToOrbis = this.sendToOrbis.bind(this);
|
|
||||||
this.getOrbisAuthStatus();
|
|
||||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
|
||||||
<h2>{translate('upload to orbis')}</h2>
|
|
||||||
<br/>
|
|
||||||
<label>Orbis auth status: </label>
|
|
||||||
<input value={this.state.authenticatedStatus} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
|
||||||
<br/><br/>
|
|
||||||
<a className='button' href="https://orbis.zone/api/auth">Log in / signup to Orbis</a>
|
|
||||||
<br/><br/>
|
|
||||||
<h3 >{translate('Orbis link')}</h3>
|
|
||||||
<input value={this.state.orbisUrl} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
|
||||||
<br/><br/>
|
|
||||||
<p>Orbis.zone is currently in a trial period, and may be wiped at any time as development progresses. Some elements are also still placeholders.</p>
|
|
||||||
<button className={'l cb dismiss cap'} disabled={!!this.state.failed} onClick={this.sendToOrbis}>{translate('PHASE_UPLOAD_ORBIS')}</button>
|
|
||||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import request from 'superagent';
|
import ShortenUrl from '../utils/ShortenUrl';
|
||||||
import Persist from '../stores/Persist';
|
import Persist from '../stores/Persist';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,11 +22,7 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
this.state = {
|
this.state = {
|
||||||
matsList: '',
|
matsList: '',
|
||||||
mats: {},
|
mats: {},
|
||||||
failed: false,
|
matsPerGrade: Persist.getRolls()
|
||||||
cmdrName: Persist.getCmdr().selected,
|
|
||||||
cmdrs: Persist.getCmdr().cmdrs,
|
|
||||||
matsPerGrade: Persist.getRolls(),
|
|
||||||
blueprints: []
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,114 +31,6 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.renderMats();
|
this.renderMats();
|
||||||
if (this.checkBrowserIsCompatible()) {
|
|
||||||
this.getCommanders();
|
|
||||||
this.registerBPs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all blueprints needed to make a build.
|
|
||||||
*/
|
|
||||||
registerBPs() {
|
|
||||||
const ship = this.props.ship;
|
|
||||||
let blueprints = [];
|
|
||||||
for (const module of ship.costList) {
|
|
||||||
if (module.type === 'SHIP') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (module.m && module.m.blueprint) {
|
|
||||||
if (!module.m.blueprint.grade || !module.m.blueprint.grades) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (module.m.blueprint.special) {
|
|
||||||
console.log(module.m.blueprint.special);
|
|
||||||
blueprints.push({ uuid: module.m.blueprint.special.uuid, number: 1 });
|
|
||||||
}
|
|
||||||
for (const g in module.m.blueprint.grades) {
|
|
||||||
if (!module.m.blueprint.grades.hasOwnProperty(g)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (g > module.m.blueprint.grade) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
blueprints.push({ uuid: module.m.blueprint.grades[g].uuid, number: this.state.matsPerGrade[g] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setState({ blueprints });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check browser isn't firefox.
|
|
||||||
* @return {boolean} true if compatible, false if not.
|
|
||||||
*/
|
|
||||||
checkBrowserIsCompatible() {
|
|
||||||
// Firefox 1.0+
|
|
||||||
return typeof InstallTrigger === 'undefined';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of commanders from EDEngineer.
|
|
||||||
*/
|
|
||||||
getCommanders() {
|
|
||||||
request
|
|
||||||
.get('http://localhost:44405/commanders')
|
|
||||||
.end((err, res) => {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
return this.setState({ failed: true });
|
|
||||||
}
|
|
||||||
const cmdrs = JSON.parse(res.text);
|
|
||||||
if (!this.state.cmdrName) {
|
|
||||||
this.setState({ cmdrName: cmdrs[0] });
|
|
||||||
}
|
|
||||||
this.setState({ cmdrs }, () => {
|
|
||||||
Persist.setCmdr({ selected: this.state.cmdrName, cmdrs });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send all blueprints to ED Engineer
|
|
||||||
* @param {Event} event React event
|
|
||||||
*/
|
|
||||||
sendToEDEng(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const target = event.target;
|
|
||||||
target.disabled = this.state.blueprints.length > 0;
|
|
||||||
if (this.state.blueprints.length === 0) {
|
|
||||||
target.innerText = 'No modded components.';
|
|
||||||
target.disabled = true;
|
|
||||||
setTimeout(() => {
|
|
||||||
target.innerText = 'Send to EDEngineer';
|
|
||||||
target.disabled = false;
|
|
||||||
}, 3000);
|
|
||||||
} else {
|
|
||||||
target.innerText = 'Sending...';
|
|
||||||
}
|
|
||||||
let countSent = 0;
|
|
||||||
let countTotal = this.state.blueprints.length;
|
|
||||||
|
|
||||||
for (const i of this.state.blueprints) {
|
|
||||||
request
|
|
||||||
.patch(`http://localhost:44405/${this.state.cmdrName}/shopping-list`)
|
|
||||||
.field('uuid', i.uuid)
|
|
||||||
.field('size', i.number)
|
|
||||||
.end(err => {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
if (err.message !== 'Bad Request') {
|
|
||||||
this.setState({ failed: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
countSent++;
|
|
||||||
if (countSent === countTotal) {
|
|
||||||
target.disabled = false;
|
|
||||||
target.innerText = 'Send to EDEngineer';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,16 +48,10 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const g in module.m.blueprint.grades) {
|
for (const g in module.m.blueprint.grades) {
|
||||||
if (!module.m.blueprint.grades.hasOwnProperty(g)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (g > module.m.blueprint.grade) {
|
if (g > module.m.blueprint.grade) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const i in module.m.blueprint.grades[g].components) {
|
for (const i in module.m.blueprint.grades[g].components) {
|
||||||
if (!module.m.blueprint.grades[g].components.hasOwnProperty(i)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (mats[i]) {
|
if (mats[i]) {
|
||||||
mats[i] += module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
mats[i] += module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
||||||
} else {
|
} else {
|
||||||
@@ -204,18 +86,6 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
this.setState({ matsPerGrade: newState });
|
this.setState({ matsPerGrade: newState });
|
||||||
Persist.setRolls(newState);
|
Persist.setRolls(newState);
|
||||||
this.renderMats();
|
this.renderMats();
|
||||||
this.registerBPs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for changing cmdr name
|
|
||||||
* @param {SyntheticEvent} e React Event
|
|
||||||
*/
|
|
||||||
cmdrChangeHandler(e) {
|
|
||||||
let cmdrName = e.target.value;
|
|
||||||
this.setState({ cmdrName }, () => {
|
|
||||||
Persist.setCmdr({ selected: this.state.cmdrName, cmdrs: this.state.cmdrs });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,9 +95,6 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
render() {
|
render() {
|
||||||
let translate = this.context.language.translate;
|
let translate = this.context.language.translate;
|
||||||
this.changeHandler = this.changeHandler.bind(this);
|
this.changeHandler = this.changeHandler.bind(this);
|
||||||
const compatible = this.checkBrowserIsCompatible();
|
|
||||||
this.cmdrChangeHandler = this.cmdrChangeHandler.bind(this);
|
|
||||||
this.sendToEDEng = this.sendToEDEng.bind(this);
|
|
||||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||||
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
|
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
|
||||||
<label>Grade 1 rolls </label>
|
<label>Grade 1 rolls </label>
|
||||||
@@ -247,15 +114,6 @@ export default class ModalShoppingList extends TranslatedComponent {
|
|||||||
<div>
|
<div>
|
||||||
<textarea className='cb json' readOnly value={this.state.matsList} />
|
<textarea className='cb json' readOnly value={this.state.matsList} />
|
||||||
</div>
|
</div>
|
||||||
<label hidden={!compatible} className={'l cap'}>CMDR Name </label>
|
|
||||||
<br/>
|
|
||||||
<select hidden={!compatible} className={'cmdr-select l cap'} onChange={this.cmdrChangeHandler} defaultValue={this.state.cmdrName}>
|
|
||||||
{this.state.cmdrs.map(e => <option key={e}>{e}</option>)}
|
|
||||||
</select>
|
|
||||||
<br/>
|
|
||||||
<p hidden={!this.state.failed} id={'failed'} className={'l'}>Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)</p>
|
|
||||||
<p hidden={compatible} id={'browserbad'} className={'l'}>Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.</p>
|
|
||||||
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send To EDEngineer')}</button>
|
|
||||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import NumberEditor from 'react-number-editor';
|
import NumberEditor from 'react-number-editor';
|
||||||
import { isValueBeneficial } from '../utils/BlueprintFunctions';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modification
|
* Modification
|
||||||
@@ -39,17 +38,30 @@ export default class Modification extends TranslatedComponent {
|
|||||||
* in a value by hand
|
* in a value by hand
|
||||||
*/
|
*/
|
||||||
_updateValue(value) {
|
_updateValue(value) {
|
||||||
let { m, name, ship } = this.props;
|
const name = this.props.name;
|
||||||
value = Math.max(Math.min(value, 50000), -50000);
|
let scaledValue = Math.round(Number(value) * 100);
|
||||||
ship.setModification(m, name, value, true, true);
|
// Limit to +1000% / -99.99%
|
||||||
|
if (scaledValue > 100000) {
|
||||||
|
scaledValue = 100000;
|
||||||
|
value = 1000;
|
||||||
|
}
|
||||||
|
if (scaledValue < -9999) {
|
||||||
|
scaledValue = -9999;
|
||||||
|
value = -99.99;
|
||||||
|
}
|
||||||
|
|
||||||
|
let m = this.props.m;
|
||||||
|
let ship = this.props.ship;
|
||||||
|
ship.setModification(m, name, scaledValue, true);
|
||||||
|
|
||||||
this.setState({ value });
|
this.setState({ value });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when an update to slider value is finished i.e. when losing focus
|
* Triggered when an update to slider value is finished i.e. when losing focus
|
||||||
*
|
*
|
||||||
* pnellesen (24/05/2018): added value check below - this should prevent experimental effects from being recalculated
|
* pnellesen (24/05/2018): added value check below - this should prevent experimental effects from being recalculated
|
||||||
* with each onBlur event, even when no change has actually been made to the field.
|
* with each onBlur event, even when no change has actually been made to the field.
|
||||||
*/
|
*/
|
||||||
_updateFinished() {
|
_updateFinished() {
|
||||||
if (this.props.value != this.state.value) {
|
if (this.props.value != this.state.value) {
|
||||||
@@ -63,50 +75,28 @@ export default class Modification extends TranslatedComponent {
|
|||||||
* @return {React.Component} modification
|
* @return {React.Component} modification
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
let { translate, formats, units } = this.context.language;
|
let translate = this.context.language.translate;
|
||||||
let { m, name } = this.props;
|
let { m, name } = this.props;
|
||||||
let modValue = m.getChange(name);
|
|
||||||
|
|
||||||
if (name === 'damagedist') {
|
if (name === 'damagedist') {
|
||||||
// We don't show damage distribution
|
// We don't show damage distribution
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let symbol;
|
||||||
|
if (name === 'jitter') {
|
||||||
|
symbol = '°';
|
||||||
|
} else if (name !== 'burst' && name != 'burstrof') {
|
||||||
|
symbol = '%';
|
||||||
|
}
|
||||||
|
if (symbol) {
|
||||||
|
symbol = ' (' + symbol + ')';
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onBlur={this._updateFinished.bind(this)} key={name}
|
<div onBlur={this._updateFinished.bind(this)} className={'cb'} key={name} ref={ modItem => this.props.modItems[name] = modItem }>
|
||||||
className={cn('cb', 'modification-container')}
|
<div className={'cb'}>{translate(name, m.grp)}{symbol}</div>
|
||||||
ref={ modItem => this.props.modItems[name] = modItem }>
|
<NumberEditor className={'cb'} style={{ width: '90%', textAlign: 'center' }} step={0.01} stepModifier={1} decimals={2} value={this.state.value} onValueChange={this._updateValue.bind(this)} onKeyDown={ this.props.onKeyDown } />
|
||||||
<span className={'cb'}>{translate(name, m.grp)}</span>
|
|
||||||
<span className={'header-adjuster'}></span>
|
|
||||||
<table style={{ width: '100%' }}>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td className={'input-container'}>
|
|
||||||
<span>
|
|
||||||
{this.props.editable ?
|
|
||||||
<NumberEditor className={'cb'} value={this.state.value}
|
|
||||||
decimals={2} style={{ textAlign: 'right' }} step={0.01}
|
|
||||||
stepModifier={1} onKeyDown={ this.props.onKeyDown }
|
|
||||||
onValueChange={this._updateValue.bind(this)} /> :
|
|
||||||
<input type="text" value={formats.f2(this.state.value)}
|
|
||||||
disabled className={'number-editor'}
|
|
||||||
style={{ textAlign: 'right', cursor: 'inherit' }}/>
|
|
||||||
}
|
|
||||||
<span className={'unit-container'}>
|
|
||||||
{units[m.getStoredUnitFor(name)]}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td style={{ textAlign: 'center' }} className={
|
|
||||||
modValue ?
|
|
||||||
isValueBeneficial(name, modValue) ? 'secondary': 'warning':
|
|
||||||
''
|
|
||||||
}>
|
|
||||||
{formats.f2(modValue / 100) || 0}%
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ import {
|
|||||||
specialToolTip
|
specialToolTip
|
||||||
} from '../utils/BlueprintFunctions';
|
} from '../utils/BlueprintFunctions';
|
||||||
|
|
||||||
const MODIFICATIONS_COMPARATOR = (mod1, mod2) => {
|
|
||||||
return mod1.props.name.localeCompare(mod2.props.name);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modifications menu
|
* Modifications menu
|
||||||
*/
|
*/
|
||||||
@@ -128,7 +124,7 @@ export default class ModificationsMenu extends TranslatedComponent {
|
|||||||
// Initial modification menu
|
// Initial modification menu
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.modItems[this.lastModId].focus();
|
this.modItems[this.lastModId].focus();
|
||||||
return;
|
return;
|
||||||
} else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) {
|
} else if (event.currentTarget.className.indexOf('button-inline-menu') >= 0 && event.currentTarget.previousElementSibling == null && this.lastNeId != null && this.modItems[this.lastNeId] != null) {
|
||||||
// shift-tab on first element in modifications menu. set focus to last number editor field if open
|
// shift-tab on first element in modifications menu. set focus to last number editor field if open
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -209,26 +205,15 @@ export default class ModificationsMenu extends TranslatedComponent {
|
|||||||
*/
|
*/
|
||||||
_renderModifications(props) {
|
_renderModifications(props) {
|
||||||
const { m, onChange, ship } = props;
|
const { m, onChange, ship } = props;
|
||||||
const modifiableModifications = [];
|
|
||||||
const modifications = [];
|
const modifications = [];
|
||||||
for (const modName of Modifications.modules[m.grp].modifications) {
|
for (const modName of Modifications.modules[m.grp].modifications) {
|
||||||
if (!Modifications.modifications[modName].hidden) {
|
if (!Modifications.modifications[modName].hidden) {
|
||||||
const key = modName + (m.getModValue(modName) / 100 || 0);
|
const key = modName + (m.getModValue(modName) / 100 || 0);
|
||||||
const editable = modName !== 'fallofffromrange' &&
|
|
||||||
m.blueprint.grades[m.blueprint.grade].features[modName];
|
|
||||||
this.lastNeId = modName;
|
this.lastNeId = modName;
|
||||||
(editable ? modifiableModifications : modifications).push(
|
modifications.push(<Modification key={ key } ship={ ship } m={ m } name={ modName } value={ m.getModValue(modName) / 100 || 0 } onChange={ onChange } onKeyDown={ this._keyDown } modItems={ this.modItems } handleModChange = {this._handleModChange} />);
|
||||||
<Modification key={ key } ship={ ship } m={ m }
|
|
||||||
value={m.getPretty(modName) || 0} modItems={this.modItems}
|
|
||||||
onChange={onChange} onKeyDown={this._keyDown} name={modName}
|
|
||||||
editable={editable} handleModChange = {this._handleModChange} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return modifications;
|
||||||
modifiableModifications.sort(MODIFICATIONS_COMPARATOR);
|
|
||||||
modifications.sort(MODIFICATIONS_COMPARATOR);
|
|
||||||
return modifiableModifications.concat(modifications);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,63 +42,6 @@ export function weaponComparator(translate, propComparator, desc) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a tooltip that shows damage by type.
|
|
||||||
* @param {function} translate Translation function
|
|
||||||
* @param {Object} formats Object that holds format functions
|
|
||||||
* @param {Calc.SDps} sdpsObject Object that holds sdps split up by type
|
|
||||||
* @returns {Array} Tooltip
|
|
||||||
*/
|
|
||||||
function getSDpsTooltip(translate, formats, sdpsObject) {
|
|
||||||
return Object.keys(sdpsObject).filter(key => sdpsObject[key])
|
|
||||||
.map(key => {
|
|
||||||
return (
|
|
||||||
<div key={key}>
|
|
||||||
{translate(key) + ' ' + formats.f1(sdpsObject[key])}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a data object used by {@link PieChart} that shows damage by type.
|
|
||||||
* @param {function} translate Translation function
|
|
||||||
* @param {Calc.SDps} sdpsObject Object that holds sdps split up by type
|
|
||||||
* @returns {Object} Data object
|
|
||||||
*/
|
|
||||||
function getSDpsData(translate, sdpsObject) {
|
|
||||||
return Object.keys(sdpsObject).map(key => {
|
|
||||||
return {
|
|
||||||
value: Math.round(sdpsObject[key]),
|
|
||||||
label: translate(key)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds all damage of `add` onto `addOn`.
|
|
||||||
* @param {Calc.SDps} addOn Object that holds sdps split up by type (will be mutated)
|
|
||||||
* @param {Calc.SDps} add Object that holds sdps split up by type
|
|
||||||
*/
|
|
||||||
function addSDps(addOn, add) {
|
|
||||||
Object.keys(addOn).map(k => addOn[k] += (add[k] ? add[k] : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the overall sdps of an sdps object.
|
|
||||||
* @param {Calc.SDps} sdpsObject Object that holds sdps spluit up by type
|
|
||||||
*/
|
|
||||||
function sumSDps(sdpsObject) {
|
|
||||||
if (sdpsObject.total) {
|
|
||||||
return sdpsObject.total;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(sdpsObject).reduce(
|
|
||||||
(acc, k) => acc + (sdpsObject[k] ? sdpsObject[k] : 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offence information
|
* Offence information
|
||||||
* Offence information consists of four panels:
|
* Offence information consists of four panels:
|
||||||
@@ -127,7 +70,7 @@ export default class Offence extends TranslatedComponent {
|
|||||||
this._sort = this._sort.bind(this);
|
this._sort = this._sort.bind(this);
|
||||||
|
|
||||||
const damage = Calc.offenceMetrics(props.ship, props.opponent, props.wep, props.opponentSys, props.engagementrange);
|
const damage = Calc.offenceMetrics(props.ship, props.opponent, props.wep, props.opponentSys, props.engagementrange);
|
||||||
this.state = {
|
this.state = {
|
||||||
predicate: 'n',
|
predicate: 'n',
|
||||||
desc: true,
|
desc: true,
|
||||||
damage
|
damage
|
||||||
@@ -201,36 +144,51 @@ export default class Offence extends TranslatedComponent {
|
|||||||
|
|
||||||
const timeToDrain = Calc.timeToDrainWep(ship, wep);
|
const timeToDrain = Calc.timeToDrainWep(ship, wep);
|
||||||
|
|
||||||
|
let absoluteShieldsSDps = 0;
|
||||||
|
let explosiveShieldsSDps = 0;
|
||||||
|
let kineticShieldsSDps = 0;
|
||||||
|
let thermalShieldsSDps = 0;
|
||||||
|
let absoluteArmourSDps = 0;
|
||||||
|
let explosiveArmourSDps = 0;
|
||||||
|
let kineticArmourSDps = 0;
|
||||||
|
let thermalArmourSDps = 0;
|
||||||
|
|
||||||
let totalSEps = 0;
|
let totalSEps = 0;
|
||||||
let totalSDpsObject = {'absolute': 0, 'explosive': 0, 'kinetic': 0, 'thermal': 0};
|
|
||||||
let shieldsSDpsObject = {'absolute': 0, 'explosive': 0, 'kinetic': 0, 'thermal': 0};
|
|
||||||
let armourSDpsObject = {'absolute': 0, 'explosive': 0, 'kinetic': 0, 'thermal': 0};
|
|
||||||
|
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (let i = 0; i < damage.length; i++) {
|
for (let i = 0; i < damage.length; i++) {
|
||||||
const weapon = damage[i];
|
const weapon = damage[i];
|
||||||
|
|
||||||
totalSEps += weapon.seps;
|
totalSEps += weapon.seps;
|
||||||
addSDps(totalSDpsObject, weapon.sdps.base);
|
absoluteShieldsSDps += weapon.sdps.shields.absolute;
|
||||||
addSDps(shieldsSDpsObject, weapon.sdps.shields);
|
explosiveShieldsSDps += weapon.sdps.shields.explosive;
|
||||||
addSDps(armourSDpsObject, weapon.sdps.armour);
|
kineticShieldsSDps += weapon.sdps.shields.kinetic;
|
||||||
|
thermalShieldsSDps += weapon.sdps.shields.thermal;
|
||||||
const baseSDpsTooltipDetails = getSDpsTooltip(translate, formats, weapon.sdps.base);
|
absoluteArmourSDps += weapon.sdps.armour.absolute;
|
||||||
|
explosiveArmourSDps += weapon.sdps.armour.explosive;
|
||||||
|
kineticArmourSDps += weapon.sdps.armour.kinetic;
|
||||||
|
thermalArmourSDps += weapon.sdps.armour.thermal;
|
||||||
|
|
||||||
const effectivenessShieldsTooltipDetails = [];
|
const effectivenessShieldsTooltipDetails = [];
|
||||||
effectivenessShieldsTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.shields.range)}</div>);
|
effectivenessShieldsTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.shields.range)}</div>);
|
||||||
effectivenessShieldsTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.shields.resistance)}</div>);
|
effectivenessShieldsTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.shields.resistance)}</div>);
|
||||||
effectivenessShieldsTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(weapon.effectiveness.shields.sys)}</div>);
|
effectivenessShieldsTooltipDetails.push(<div key='power distributor'>{translate('power distributor') + ' ' + formats.pct1(weapon.effectiveness.shields.sys)}</div>);
|
||||||
|
|
||||||
const effectiveShieldsSDpsTooltipDetails = getSDpsTooltip(translate, formats, weapon.sdps.armour);
|
const effectiveShieldsSDpsTooltipDetails = [];
|
||||||
|
if (weapon.sdps.shields.absolute) effectiveShieldsSDpsTooltipDetails.push(<div key='absolute'>{translate('absolute') + ' ' + formats.f1(weapon.sdps.shields.absolute)}</div>);
|
||||||
|
if (weapon.sdps.shields.explosive) effectiveShieldsSDpsTooltipDetails.push(<div key='explosive'>{translate('explosive') + ' ' + formats.f1(weapon.sdps.shields.explosive)}</div>);
|
||||||
|
if (weapon.sdps.shields.kinetic) effectiveShieldsSDpsTooltipDetails.push(<div key='kinetic'>{translate('kinetic') + ' ' + formats.f1(weapon.sdps.shields.kinetic)}</div>);
|
||||||
|
if (weapon.sdps.shields.thermal) effectiveShieldsSDpsTooltipDetails.push(<div key='thermal'>{translate('thermal') + ' ' + formats.f1(weapon.sdps.shields.thermal)}</div>);
|
||||||
|
|
||||||
const effectivenessArmourTooltipDetails = [];
|
const effectivenessArmourTooltipDetails = [];
|
||||||
effectivenessArmourTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.armour.range)}</div>);
|
effectivenessArmourTooltipDetails.push(<div key='range'>{translate('range') + ' ' + formats.pct1(weapon.effectiveness.armour.range)}</div>);
|
||||||
effectivenessArmourTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.armour.resistance)}</div>);
|
effectivenessArmourTooltipDetails.push(<div key='resistance'>{translate('resistance') + ' ' + formats.pct1(weapon.effectiveness.armour.resistance)}</div>);
|
||||||
effectivenessArmourTooltipDetails.push(<div key='hardness'>{translate('hardness') + ' ' + formats.pct1(weapon.effectiveness.armour.hardness)}</div>);
|
effectivenessArmourTooltipDetails.push(<div key='hardness'>{translate('hardness') + ' ' + formats.pct1(weapon.effectiveness.armour.hardness)}</div>);
|
||||||
|
const effectiveArmourSDpsTooltipDetails = [];
|
||||||
const effectiveArmourSDpsTooltipDetails = getSDpsTooltip(translate, formats, weapon.sdps.armour);
|
if (weapon.sdps.armour.absolute) effectiveArmourSDpsTooltipDetails.push(<div key='absolute'>{translate('absolute') + ' ' + formats.f1(weapon.sdps.armour.absolute)}</div>);
|
||||||
|
if (weapon.sdps.armour.explosive) effectiveArmourSDpsTooltipDetails.push(<div key='explosive'>{translate('explosive') + ' ' + formats.f1(weapon.sdps.armour.explosive)}</div>);
|
||||||
|
if (weapon.sdps.armour.kinetic) effectiveArmourSDpsTooltipDetails.push(<div key='kinetic'>{translate('kinetic') + ' ' + formats.f1(weapon.sdps.armour.kinetic)}</div>);
|
||||||
|
if (weapon.sdps.armour.thermal) effectiveArmourSDpsTooltipDetails.push(<div key='thermal'>{translate('thermal') + ' ' + formats.f1(weapon.sdps.armour.thermal)}</div>);
|
||||||
|
|
||||||
rows.push(
|
rows.push(
|
||||||
<tr key={weapon.id}>
|
<tr key={weapon.id}>
|
||||||
@@ -241,25 +199,27 @@ export default class Offence extends TranslatedComponent {
|
|||||||
{weapon.classRating} {translate(weapon.name)}
|
{weapon.classRating} {translate(weapon.name)}
|
||||||
{weapon.engineering ? ' (' + weapon.engineering + ')' : null }
|
{weapon.engineering ? ' (' + weapon.engineering + ')' : null }
|
||||||
</td>
|
</td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, baseSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.base.total)}</span></td>
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.shields.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessShieldsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.shields.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectiveArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.f1(weapon.sdps.armour.total)}</span></td>
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
|
<td className='ri'><span onMouseOver={termtip.bind(null, effectivenessArmourTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>{formats.pct1(weapon.effectiveness.armour.total)}</span></td>
|
||||||
</tr>);
|
</tr>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalSDps = sumSDps(totalSDpsObject);
|
const totalShieldsSDps = absoluteShieldsSDps + explosiveShieldsSDps + kineticShieldsSDps + thermalShieldsSDps;
|
||||||
const totalSDpsTooltipDetails = getSDpsTooltip(translate, formats, totalSDpsObject);
|
const totalArmourSDps = absoluteArmourSDps + explosiveArmourSDps + kineticArmourSDps + thermalArmourSDps;
|
||||||
const totalSDpsData = getSDpsData(translate, totalSDpsObject);
|
|
||||||
|
|
||||||
const totalShieldsSDps = sumSDps(shieldsSDpsObject);
|
const shieldsSDpsData = [];
|
||||||
const totalShieldsSDpsTooltipDetails = getSDpsTooltip(translate, formats, shieldsSDpsObject);
|
shieldsSDpsData.push({ value: Math.round(absoluteShieldsSDps), label: translate('absolute') });
|
||||||
const shieldsSDpsData = getSDpsData(translate, shieldsSDpsObject);
|
shieldsSDpsData.push({ value: Math.round(explosiveShieldsSDps), label: translate('explosive') });
|
||||||
|
shieldsSDpsData.push({ value: Math.round(kineticShieldsSDps), label: translate('kinetic') });
|
||||||
|
shieldsSDpsData.push({ value: Math.round(thermalShieldsSDps), label: translate('thermal') });
|
||||||
|
|
||||||
const totalArmourSDps = sumSDps(armourSDpsObject);
|
const armourSDpsData = [];
|
||||||
const totalArmourSDpsTooltipDetails = getSDpsTooltip(translate, formats, armourSDpsObject);
|
armourSDpsData.push({ value: Math.round(absoluteArmourSDps), label: translate('absolute') });
|
||||||
const armourSDpsData = getSDpsData(translate, armourSDpsObject);
|
armourSDpsData.push({ value: Math.round(explosiveArmourSDps), label: translate('explosive') });
|
||||||
|
armourSDpsData.push({ value: Math.round(kineticArmourSDps), label: translate('kinetic') });
|
||||||
|
armourSDpsData.push({ value: Math.round(thermalArmourSDps), label: translate('thermal') });
|
||||||
|
|
||||||
const timeToDepleteShields = Calc.timeToDeplete(opponentShields.total, totalShieldsSDps, totalSEps, pd.getWeaponsCapacity(), pd.getWeaponsRechargeRate() * (wep / 4));
|
const timeToDepleteShields = Calc.timeToDeplete(opponentShields.total, totalShieldsSDps, totalSEps, pd.getWeaponsCapacity(), pd.getWeaponsRechargeRate() * (wep / 4));
|
||||||
const timeToDepleteArmour = Calc.timeToDeplete(opponentArmour.total, totalArmourSDps, totalSEps, pd.getWeaponsCapacity(), pd.getWeaponsRechargeRate() * (wep / 4));
|
const timeToDepleteArmour = Calc.timeToDeplete(opponentArmour.total, totalArmourSDps, totalSEps, pd.getWeaponsCapacity(), pd.getWeaponsRechargeRate() * (wep / 4));
|
||||||
@@ -271,31 +231,19 @@ export default class Offence extends TranslatedComponent {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr className='main'>
|
<tr className='main'>
|
||||||
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
|
<th rowSpan='2' className='sortable' onClick={sortOrder.bind(this, 'n')}>{translate('weapon')}</th>
|
||||||
<th colSpan='1'>{translate('overall')}</th>
|
|
||||||
<th colSpan='2'>{translate('opponent\'s shields')}</th>
|
<th colSpan='2'>{translate('opponent\'s shields')}</th>
|
||||||
<th colSpan='2'>{translate('opponent\'s armour')}</th>
|
<th colSpan='2'>{translate('opponent\'s armour')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_SHIELDS')} onMouseOut={tooltip.bind(null, null)} onClick={sortOrder.bind(this, 'esdpss')}>{'sdps'}</th>
|
||||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
|
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_SHIELDS')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'es')}>{'eft'}</th>
|
||||||
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
|
<th className='lft sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVE_SDPS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'esdpsh')}>{'sdps'}</th>
|
||||||
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
|
<th className='sortable' onMouseOver={termtip.bind(null, 'TT_EFFECTIVENESS_ARMOUR')} onMouseOut={tooltip.bind(null, null)}onClick={sortOrder.bind(this, 'eh')}>{'eft'}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{rows}
|
{rows}
|
||||||
{rows.length > 0 &&
|
</tbody>
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalSDps)}</span></td>
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalShieldsSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalShieldsSDps)}</span></td>
|
|
||||||
<td></td>
|
|
||||||
<td className='ri'><span onMouseOver={termtip.bind(null, totalArmourSDpsTooltipDetails)} onMouseOut={tooltip.bind(null, null)}>={formats.f1(totalArmourSDps)}</span></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
@@ -306,10 +254,6 @@ export default class Offence extends TranslatedComponent {
|
|||||||
<h2 onMouseOver={termtip.bind(null, translate('TT_EFFECTIVE_SDPS_ARMOUR'))} onMouseOut={tooltip.bind(null, null)}>{translate('PHRASE_EFFECTIVE_SDPS_ARMOUR')}<br/>{formats.f1(totalArmourSDps)}</h2>
|
<h2 onMouseOver={termtip.bind(null, translate('TT_EFFECTIVE_SDPS_ARMOUR'))} onMouseOut={tooltip.bind(null, null)}>{translate('PHRASE_EFFECTIVE_SDPS_ARMOUR')}<br/>{formats.f1(totalArmourSDps)}</h2>
|
||||||
<h2 onMouseOver={termtip.bind(null, translate('TT_TIME_TO_REMOVE_ARMOUR'))} onMouseOut={tooltip.bind(null, null)}>{translate('PHRASE_TIME_TO_REMOVE_ARMOUR')}<br/>{timeToDepleteArmour === Infinity ? translate('never') : formats.time(timeToDepleteArmour)}</h2>
|
<h2 onMouseOver={termtip.bind(null, translate('TT_TIME_TO_REMOVE_ARMOUR'))} onMouseOut={tooltip.bind(null, null)}>{translate('PHRASE_TIME_TO_REMOVE_ARMOUR')}<br/>{timeToDepleteArmour === Infinity ? translate('never') : formats.time(timeToDepleteArmour)}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className='group quarter'>
|
|
||||||
<h2 onMouseOver={termtip.bind(null, translate('PHRASE_OVERALL_DAMAGE'))} onMouseOut={tooltip.bind(null, null)}>{translate('overall damage')}</h2>
|
|
||||||
<PieChart data={totalSDpsData} />
|
|
||||||
</div>
|
|
||||||
<div className='group quarter'>
|
<div className='group quarter'>
|
||||||
<h2 onMouseOver={termtip.bind(null, translate('PHRASE_SHIELD_DAMAGE'))} onMouseOut={tooltip.bind(null, null)}>{translate('shield damage sources')}</h2>
|
<h2 onMouseOver={termtip.bind(null, translate('PHRASE_SHIELD_DAMAGE'))} onMouseOut={tooltip.bind(null, null)}>{translate('shield damage sources')}</h2>
|
||||||
<PieChart data={shieldsSDpsData} />
|
<PieChart data={shieldsSDpsData} />
|
||||||
|
|||||||
@@ -1,92 +1,97 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ContainerDimensions from 'react-container-dimensions';
|
import Measure from 'react-measure';
|
||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
||||||
const LABEL_COLOUR = '#000000';
|
const LABEL_COLOUR = '#000000';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pie chart
|
* A pie chart
|
||||||
*/
|
*/
|
||||||
export default class PieChart extends Component {
|
export default class PieChart extends Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data : PropTypes.array.isRequired
|
data : PropTypes.array.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
* @param {Object} context React Component context
|
* @param {Object} context React Component context
|
||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.pie = d3.pie().value((d) => d.value);
|
this.pie = d3.pie().value((d) => d.value);
|
||||||
this.colors = CORIOLIS_COLOURS;
|
this.colors = CORIOLIS_COLOURS;
|
||||||
this.arc = d3.arc();
|
this.arc = d3.arc();
|
||||||
this.arc.innerRadius(0);
|
this.arc.innerRadius(0);
|
||||||
}
|
|
||||||
|
this.state = {
|
||||||
|
dimensions: {
|
||||||
/**
|
width: 100,
|
||||||
* Generate a slice of the pie chart
|
height: 100
|
||||||
* @param {Object} d the data for this slice
|
}
|
||||||
* @param {number} i the index of this slice
|
};
|
||||||
* @param {number} width the current width of the parent container
|
}
|
||||||
* @returns {Object} the SVG for the slice
|
|
||||||
*/
|
|
||||||
sliceGenerator(d, i, width) {
|
/**
|
||||||
if (!d || d.value == 0) {
|
* Generate a slice of the pie chart
|
||||||
// Ignore 0 values
|
* @param {Object} d the data for this slice
|
||||||
return null;
|
* @param {number} i the index of this slice
|
||||||
}
|
* @returns {Object} the SVG for the slice
|
||||||
|
*/
|
||||||
const { data } = this.props;
|
sliceGenerator(d, i) {
|
||||||
|
if (!d || d.value == 0) {
|
||||||
// Push the labels further out from the centre of the slice
|
// Ignore 0 values
|
||||||
let [labelX, labelY] = this.arc.centroid(d);
|
return null;
|
||||||
const labelTranslate = `translate(${labelX * 1.5}, ${labelY * 1.5})`;
|
}
|
||||||
|
|
||||||
// Put the keys in a line with equal spacing
|
const { width, height } = this.state.dimensions;
|
||||||
const nonZeroItems = data.filter(d => d.value != 0).length;
|
const { data } = this.props;
|
||||||
const thisItemIndex = data.slice(0, i + 1).filter(d => d.value != 0).length - 1;
|
|
||||||
const keyX = -width / 2 + (width / nonZeroItems) * (thisItemIndex + 0.5);
|
// Push the labels further out from the centre of the slice
|
||||||
const keyTranslate = `translate(${keyX}, ${width * 0.45})`;
|
let [labelX, labelY] = this.arc.centroid(d);
|
||||||
|
const labelTranslate = `translate(${labelX * 1.5}, ${labelY * 1.5})`;
|
||||||
return (
|
|
||||||
<g key={`group-${i}`}>
|
// Put the keys in a line with equal spacing
|
||||||
<path key={`arc-${i}`} d={this.arc(d)} style={{ fill: this.colors[i] }} />
|
const nonZeroItems = data.filter(d => d.value != 0).length;
|
||||||
<text key={`label-${i}`} transform={labelTranslate} style={{ strokeWidth: '0px', fill: LABEL_COLOUR }} textAnchor='middle'>{d.value}</text>
|
const thisItemIndex = data.slice(0, i + 1).filter(d => d.value != 0).length - 1;
|
||||||
<text key={`key-${i}`} transform={keyTranslate} style={{ strokeWidth:'0px', fill: this.colors[i] }} textAnchor='middle'>{d.data.label}</text>
|
const keyX = -width / 2 + (width / nonZeroItems) * (thisItemIndex + 0.5);
|
||||||
</g>
|
const keyTranslate = `translate(${keyX}, ${width * 0.45})`;
|
||||||
);
|
|
||||||
}
|
return (
|
||||||
|
<g key={`group-${i}`}>
|
||||||
/**
|
<path key={`arc-${i}`} d={this.arc(d)} style={{ fill: this.colors[i] }} />
|
||||||
* Render the component
|
<text key={`label-${i}`} transform={labelTranslate} style={{ strokeWidth: '0px', fill: LABEL_COLOUR }} textAnchor='middle'>{d.value}</text>
|
||||||
* @returns {object} Markup
|
<text key={`key-${i}`} transform={keyTranslate} style={{ strokeWidth:'0px', fill: this.colors[i] }} textAnchor='middle'>{d.data.label}</text>
|
||||||
*/
|
</g>
|
||||||
render() {
|
);
|
||||||
return (
|
}
|
||||||
<ContainerDimensions>
|
|
||||||
{ ({ width }) => {
|
/**
|
||||||
const pie = this.pie(this.props.data),
|
* Render the component
|
||||||
translate = `translate(${width / 2}, ${width * 0.4})`;
|
* @returns {object} Markup
|
||||||
|
*/
|
||||||
this.arc.outerRadius(width * 0.4);
|
render() {
|
||||||
return (
|
const { width, height } = this.state.dimensions;
|
||||||
<div width={width} height={width}>
|
const pie = this.pie(this.props.data),
|
||||||
<svg style={{ stroke: 'None' }} width={width} height={width * 0.9}>
|
translate = `translate(${width / 2}, ${width * 0.4})`;
|
||||||
<g transform={translate}>
|
|
||||||
{pie.map((d, i) => this.sliceGenerator(d, i, width))}
|
this.arc.outerRadius(width * 0.4);
|
||||||
</g>
|
|
||||||
</svg>
|
return (
|
||||||
</div>
|
<Measure width='100%' whitelist={['width', 'top']} onMeasure={ (dimensions) => { this.setState({ dimensions }); }}>
|
||||||
);
|
<div width={width} height={width}>
|
||||||
}}
|
<svg style={{ stroke: 'None' }} width={width} height={width * 0.9}>
|
||||||
</ContainerDimensions>
|
<g transform={translate}>
|
||||||
);
|
{pie.map((d, i) => this.sliceGenerator(d, i))}
|
||||||
}
|
</g>
|
||||||
}
|
</svg>
|
||||||
|
</div>
|
||||||
|
</Measure>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
const speedTooltip = canThrust ? 'TT_SUMMARY_SPEED' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
const speedTooltip = canThrust ? 'TT_SUMMARY_SPEED' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
||||||
const canBoost = ship.canBoost(cargo, ship.fuelCapacity);
|
const canBoost = ship.canBoost(cargo, ship.fuelCapacity);
|
||||||
const boostTooltip = canBoost ? 'TT_SUMMARY_BOOST' : canThrust ? 'TT_SUMMARY_BOOST_NONFUNCTIONAL' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
const boostTooltip = canBoost ? 'TT_SUMMARY_BOOST' : canThrust ? 'TT_SUMMARY_BOOST_NONFUNCTIONAL' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
|
||||||
const sgMetrics = Calc.shieldMetrics(ship, pips.sys);
|
const sgMetrics = Calc.shieldMetrics(ship, pips.sys || 2);
|
||||||
const shipBoost = canBoost ? Calc.calcBoost(ship) : 'No Boost';
|
const shipBoost = canBoost ? Calc.calcBoost(ship) : 'No Boost';
|
||||||
const armourMetrics = Calc.armourMetrics(ship);
|
const armourMetrics = Calc.armourMetrics(ship);
|
||||||
let shieldColour = 'blue';
|
let shieldColour = 'blue';
|
||||||
@@ -63,150 +63,130 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
|||||||
shieldColour
|
shieldColour
|
||||||
};
|
};
|
||||||
return <div id='summary'>
|
return <div id='summary'>
|
||||||
<div style={{display: "table", width: "100%"}}>
|
<table className={'summaryTable'}>
|
||||||
<div style={{display: "table-row"}}>
|
<thead>
|
||||||
<table className={'summaryTable'}>
|
<tr className='main'>
|
||||||
<thead>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canThrust }) }>{translate('speed')}</th>
|
||||||
<tr className='main'>
|
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canBoost }) }>{translate('boost')}</th>
|
||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canThrust }) }>{translate('speed')}</th>
|
<th colSpan={5}>{translate('jump range')}</th>
|
||||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !canBoost }) }>{translate('boost')}</th>
|
<th rowSpan={2}>{translate('shield')}</th>
|
||||||
<th colSpan={5}>{translate('jump range')}</th>
|
<th rowSpan={2}>{translate('integrity')}</th>
|
||||||
<th rowSpan={2}>{translate('shield')}</th>
|
<th rowSpan={2}>{translate('DPS')}</th>
|
||||||
<th rowSpan={2}>{translate('integrity')}</th>
|
<th rowSpan={2}>{translate('EPS')}</th>
|
||||||
<th rowSpan={2}>{translate('DPS')}</th>
|
<th rowSpan={2}>{translate('TTD')}</th>
|
||||||
<th rowSpan={2}>{translate('EPS')}</th>
|
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
|
||||||
<th rowSpan={2}>{translate('TTD')}</th>
|
<th rowSpan={2}>{translate('cargo')}</th>
|
||||||
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
|
<th rowSpan={2}>{translate('pax')}</th>
|
||||||
<th rowSpan={2}>{translate('cargo')}</th>
|
<th rowSpan={2}>{translate('fuel')}</th>
|
||||||
<th rowSpan={2}>{translate('pax')}</th>
|
<th colSpan={3}>{translate('mass')}</th>
|
||||||
<th rowSpan={2}>{translate('fuel')}</th>
|
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
|
||||||
<th colSpan={3}>{translate('mass')}</th>
|
<th rowSpan={2}>{translate('crew')}</th>
|
||||||
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
|
<th onMouseEnter={termtip.bind(null, 'mass lock factor', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
|
||||||
<th rowSpan={2}>{translate('crew')}</th>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_BOOST_TIME', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('boost time')}</th>
|
||||||
<th onMouseEnter={termtip.bind(null, 'mass lock factor', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
|
</tr>
|
||||||
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_BOOST_TIME', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('boost time')}</th>
|
<tr>
|
||||||
</tr>
|
<th className='lft'>{translate('max')}</th>
|
||||||
<tr>
|
<th>{translate('unladen')}</th>
|
||||||
<th className='lft'>{translate('max')}</th>
|
<th>{translate('laden')}</th>
|
||||||
<th>{translate('unladen')}</th>
|
<th>{translate('total unladen')}</th>
|
||||||
<th>{translate('laden')}</th>
|
<th>{translate('total laden')}</th>
|
||||||
<th>{translate('total unladen')}</th>
|
<th className='lft'>{translate('hull')}</th>
|
||||||
<th>{translate('total laden')}</th>
|
<th>{translate('unladen')}</th>
|
||||||
<th className='lft'>{translate('hull')}</th>
|
<th>{translate('laden')}</th>
|
||||||
<th>{translate('unladen')}</th>
|
</tr>
|
||||||
<th>{translate('laden')}</th>
|
</thead>
|
||||||
</tr>
|
<tbody>
|
||||||
</thead>
|
<tr>
|
||||||
<tbody>
|
<td onMouseEnter={termtip.bind(null, speedTooltip, { cap: 0 })} onMouseLeave={hide}>{ canThrust ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<tr>
|
<td onMouseEnter={termtip.bind(null, boostTooltip, { cap: 0 })} onMouseLeave={hide}>{ canBoost ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||||
<td onMouseEnter={termtip.bind(null, speedTooltip, { cap: 0 })} onMouseLeave={hide}>{ canThrust ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, false))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_MAX_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump()))}{u.LY}</span></td>
|
||||||
<td onMouseEnter={termtip.bind(null, boostTooltip, { cap: 0 })} onMouseLeave={hide}>{ canBoost ? <span>{int(ship.calcSpeed(4, ship.fuelCapacity, 0, true))}{u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY}</span></td>
|
||||||
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_MAX_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.standard[2].m.getMaxFuelPerJump(), ship.standard[2].m, ship.standard[2].m.getMaxFuelPerJump(), ship))}{u.LY}</span></td>
|
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY}</span></td>
|
||||||
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span></td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY}</td>
|
||||||
<td><span onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_SINGLE_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.jumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</span></td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity))}{u.LY}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</td>
|
<td className={sgClassNames} onMouseEnter={termtip.bind(null, sgTooltip, { cap: 0 })} onMouseLeave={hide}>{int(ship.shield)}{u.MJ}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_TOTAL_JUMP', { cap: 0 })} onMouseLeave={hide}>{f2(Calc.totalJumpRange(ship.unladenMass + ship.fuelCapacity + ship.cargoCapacity, ship.standard[2].m, ship.fuelCapacity, ship))}{u.LY}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_INTEGRITY', { cap: 0 })} onMouseLeave={hide}>{int(ship.armour)}</td>
|
||||||
<td className={sgClassNames} onMouseEnter={termtip.bind(null, sgTooltip, { cap: 0 })} onMouseLeave={hide}>{int(ship.shield)}{u.MJ}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_DPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalDps)}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_INTEGRITY', { cap: 0 })} onMouseLeave={hide}>{int(ship.armour)}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_EPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalEps)}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_DPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalDps)}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_TTD', { cap: 0 })} onMouseLeave={hide}>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_EPS', { cap: 0 })} onMouseLeave={hide}>{f1(ship.totalEps)}</td>
|
{/* <td>{f1(ship.totalHps)}</td> */}
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_TTD', { cap: 0 })} onMouseLeave={hide}>{timeToDrain === Infinity ? '∞' : time(timeToDrain)}</td>
|
<td>{round(ship.cargoCapacity)}{u.T}</td>
|
||||||
{/* <td>{f1(ship.totalHps)}</td> */}
|
<td>{ship.passengerCapacity}</td>
|
||||||
<td>{round(ship.cargoCapacity)}{u.T}</td>
|
<td>{round(ship.fuelCapacity)}{u.T}</td>
|
||||||
<td>{ship.passengerCapacity}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_HULL_MASS', { cap: 0 })} onMouseLeave={hide}>{ship.hullMass}{u.T}</td>
|
||||||
<td>{round(ship.fuelCapacity)}{u.T}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.unladenMass)}{u.T}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_HULL_MASS', { cap: 0 })} onMouseLeave={hide}>{ship.hullMass}{u.T}</td>
|
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.ladenMass)}{u.T}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_UNLADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.unladenMass)}{u.T}</td>
|
<td>{int(ship.hardness)}</td>
|
||||||
<td onMouseEnter={termtip.bind(null, 'TT_SUMMARY_LADEN_MASS', { cap: 0 })} onMouseLeave={hide}>{int(ship.ladenMass)}{u.T}</td>
|
<td>{ship.crew}</td>
|
||||||
<td>{int(ship.hardness)}</td>
|
<td>{ship.masslock}</td>
|
||||||
<td>{ship.crew}</td>
|
<td>{shipBoost !== 'No Boost' ? formats.time(shipBoost) : 'No Boost'}</td>
|
||||||
<td>{ship.masslock}</td>
|
</tr>
|
||||||
<td>{shipBoost !== 'No Boost' ? formats.time(shipBoost) : 'No Boost'}</td>
|
</tbody>
|
||||||
</tr>
|
</table>
|
||||||
</tbody>
|
<table className={'summaryTable'}>
|
||||||
</table>
|
<thead className={this.state.shieldColour}>
|
||||||
<table className={'summaryTable'}>
|
<tr>
|
||||||
<thead className={this.state.shieldColour}>
|
<th onMouseEnter={termtip.bind(null, 'shield', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('shield')}</th>
|
||||||
<tr>
|
<th onMouseEnter={termtip.bind(null, 'explres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('explres')}</th>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'shield', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('shield')}</th>
|
<th onMouseEnter={termtip.bind(null, 'kinres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('kinres')}</th>
|
||||||
<th colSpan={4} className='lft'>{translate('resistance')}</th>
|
<th onMouseEnter={termtip.bind(null, 'thermres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('thermres')}</th>
|
||||||
|
|
||||||
<th colSpan={5} onMouseEnter={termtip.bind(null, 'TT_SUMMARY_SHIELDS_SCB', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('HP')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_SHIELDS_SCB', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('absolute')} ${translate('HP')}`}</th>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECOVER', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('recovery')}</th>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_SHIELDS_SCB', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('explosive')} ${translate('HP')}`}</th>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECHARGE', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('recharge')}</th>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_SHIELDS_SCB', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('kinetic')} ${translate('HP')}`}</th>
|
||||||
</tr>
|
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_SHIELDS_SCB', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('thermal')} ${translate('HP')}`}</th>
|
||||||
<tr>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECOVER', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('recovery')}</th>
|
||||||
<th>{`${translate('explosive')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECHARGE', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('recharge')}</th>
|
||||||
<th>{`${translate('kinetic')}`}</th>
|
</tr>
|
||||||
<th>{`${translate('thermal')}`}</th>
|
</thead>
|
||||||
<th></th>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{translate(shieldGenerator && shieldGenerator.m.grp || 'No Shield')}</td>
|
||||||
|
<td>{int(ship.shieldExplRes * 100) + '%'}</td>
|
||||||
|
<td>{int(ship.shieldKinRes * 100) + '%'}</td>
|
||||||
|
<td>{int(ship.shieldThermRes * 100) + '%'}</td>
|
||||||
|
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.absolute.total : 0)}</td>
|
||||||
|
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.explosive.total : 0)}</td>
|
||||||
|
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.kinetic.total : 0)}</td>
|
||||||
|
<td>{int(sgMetrics && sgMetrics.generator ? sgMetrics.total / sgMetrics.thermal.total : 0)}</td>
|
||||||
|
<td>{sgMetrics && sgMetrics.recover ? formats.time(sgMetrics.recover) : 0}</td>
|
||||||
|
<td>{sgMetrics && sgMetrics.recharge ? formats.time(sgMetrics.recharge) : 0}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th onMouseEnter={termtip.bind(null, 'armour', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('armour')}</th>
|
||||||
|
<th onMouseEnter={termtip.bind(null, 'explres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('explres')}</th>
|
||||||
|
<th onMouseEnter={termtip.bind(null, 'kinres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('kinres')}</th>
|
||||||
|
<th onMouseEnter={termtip.bind(null, 'thermres', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('thermres')}</th>
|
||||||
|
|
||||||
<th className={'bordered'}>{`${translate('absolute')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_EFFECTIVE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('absolute')} ${translate('HP')}`}</th>
|
||||||
<th>{`${translate('explosive')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_EFFECTIVE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('explosive')} ${translate('HP')}`}</th>
|
||||||
<th>{`${translate('kinetic')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_EFFECTIVE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('kinetic')} ${translate('HP')}`}</th>
|
||||||
<th>{`${translate('thermal')}`}</th>
|
<th onMouseEnter={termtip.bind(null, 'PHRASE_EFFECTIVE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('thermal')} ${translate('HP')}`}</th>
|
||||||
<th></th>
|
<th onMouseEnter={termtip.bind(null, 'TT_MODULE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('raw module armour')}</th>
|
||||||
</tr>
|
<th onMouseEnter={termtip.bind(null, 'armour', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('internal protection')}</th>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>{translate(shieldGenerator && shieldGenerator.m.grp || 'No Shield')}</td>
|
|
||||||
<td>{formats.pct1(ship.shieldExplRes)}</td>
|
|
||||||
<td>{formats.pct1(ship.shieldKinRes)}</td>
|
|
||||||
<td>{formats.pct1(ship.shieldThermRes)}</td>
|
|
||||||
<td></td>
|
|
||||||
|
|
||||||
<td>{int(ship && ship.shield > 0 ? ship.shield : 0)}{u.MJ}</td>
|
|
||||||
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldExplRes)))) : 0)}{u.MJ}</td>
|
|
||||||
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldKinRes)))) : 0)}{u.MJ}</td>
|
|
||||||
<td>{int(ship && ship.shield > 0 ? ship.shield * ((1 / (1 - (ship.shieldThermRes)))) : 0)}{u.MJ}</td>
|
|
||||||
<td></td>
|
|
||||||
<td>{sgMetrics && sgMetrics.recover === Math.Inf ? translate('Never') : formats.time(sgMetrics.recover)}</td>
|
|
||||||
<td>{sgMetrics && sgMetrics.recharge === Math.Inf ? translate('Never') : formats.time(sgMetrics.recharge)}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'armour', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('armour')}</th>
|
|
||||||
<th colSpan={4} className='lft'>{translate('resistance')}</th>
|
|
||||||
|
|
||||||
<th colSpan={5} onMouseEnter={termtip.bind(null, 'PHRASE_EFFECTIVE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{`${translate('HP')}`}</th>
|
</tr>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'TT_MODULE_ARMOUR', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('raw module armour')}</th>
|
</thead>
|
||||||
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'TT_MODULE_PROTECTION_INTERNAL', { cap: 0 })} onMouseLeave={hide} className='lft'>{translate('internal protection')}</th>
|
<tbody>
|
||||||
</tr>
|
<tr>
|
||||||
<tr>
|
<td>{translate(ship && ship.bulkheads && ship.bulkheads.m && ship.bulkheads.m.name || 'No Armour')}</td>
|
||||||
<th>{`${translate('explosive')}`}</th>
|
<td>{int(ship.hullExplRes * 100) + '%'}</td>
|
||||||
<th>{`${translate('kinetic')}`}</th>
|
<td>{int(ship.hullKinRes * 100) + '%'}</td>
|
||||||
<th>{`${translate('thermal')}`}</th>
|
<td>{int(ship.hullThermRes * 100) + '%'}</td>
|
||||||
<th>{`${translate('caustic')}`}</th>
|
<td>{int(armourMetrics.total / armourMetrics.absolute.total)}</td>
|
||||||
|
<td>{int(armourMetrics.total / armourMetrics.explosive.total)}</td>
|
||||||
|
<td>{int(armourMetrics.total / armourMetrics.kinetic.total)}</td>
|
||||||
|
<td>{int(armourMetrics.total / armourMetrics.thermal.total)}</td>
|
||||||
|
<td>{int(armourMetrics.modulearmour)}</td>
|
||||||
|
<td>{int(armourMetrics.moduleprotection * 100) + '%'}</td>
|
||||||
|
|
||||||
<th className={'bordered'}>{`${translate('absolute')}`}</th>
|
</tr>
|
||||||
<th>{`${translate('explosive')}`}</th>
|
</tbody>
|
||||||
<th>{`${translate('kinetic')}`}</th>
|
</table>
|
||||||
<th>{`${translate('thermal')}`}</th>
|
|
||||||
<th>{`${translate('caustic')}`}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>{translate(ship && ship.bulkheads && ship.bulkheads.m && ship.bulkheads.m.name || 'No Armour')}</td>
|
|
||||||
<td>{formats.pct1(ship.hullExplRes)}</td>
|
|
||||||
<td>{formats.pct1(ship.hullKinRes)}</td>
|
|
||||||
<td>{formats.pct1(ship.hullThermRes)}</td>
|
|
||||||
<td>{formats.pct1(ship.hullCausRes)}</td>
|
|
||||||
<td>{int(ship.armour)}</td>
|
|
||||||
<td>{int(ship.armour * ((1 / (1 - (ship.hullExplRes)))))}</td>
|
|
||||||
<td>{int(ship.armour * ((1 / (1 - (ship.hullKinRes)))))}</td>
|
|
||||||
<td>{int(ship.armour * ((1 / (1 - (ship.hullThermRes)))))}</td>
|
|
||||||
<td>{int(ship.armour * ((1 / (1 - (ship.hullCausRes)))))}</td>
|
|
||||||
<td>{int(armourMetrics.modulearmour)}</td>
|
|
||||||
<td>{int(armourMetrics.moduleprotection * 100) + '%'}</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default class SlotSection extends TranslatedComponent {
|
|||||||
this.sectionId = sectionId;
|
this.sectionId = sectionId;
|
||||||
this.sectionName = sectionName;
|
this.sectionName = sectionName;
|
||||||
this.ssHeadRef = null;
|
this.ssHeadRef = null;
|
||||||
|
|
||||||
this.sectionRefArr = this.props.sectionMenuRefs[this.sectionId] = [];
|
this.sectionRefArr = this.props.sectionMenuRefs[this.sectionId] = [];
|
||||||
this.sectionRefArr['selectedRef'] = null;
|
this.sectionRefArr['selectedRef'] = null;
|
||||||
this._getSlots = this._getSlots.bind(this);
|
this._getSlots = this._getSlots.bind(this);
|
||||||
@@ -55,11 +55,11 @@ export default class SlotSection extends TranslatedComponent {
|
|||||||
// _contextMenu()
|
// _contextMenu()
|
||||||
// componentDidUpdate(prevProps)
|
// componentDidUpdate(prevProps)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: May either need to send the function to be triggered when Enter key is pressed, or else
|
* TODO: May either need to send the function to be triggered when Enter key is pressed, or else
|
||||||
* may need a separate keyDown handler for each subclass (StandardSlotSection, HardpointSlotSection, etc.)
|
* may need a separate keyDown handler for each subclass (StandardSlotSection, HardpointSlotSection, etc.)
|
||||||
* ex: _keyDown(_keyDownfn, event)
|
* ex: _keyDown(_keyDownfn, event)
|
||||||
*
|
*
|
||||||
* @param {SyntheticEvent} event KeyDown event
|
* @param {SyntheticEvent} event KeyDown event
|
||||||
*/
|
*/
|
||||||
_keyDown(event) {
|
_keyDown(event) {
|
||||||
@@ -85,14 +85,14 @@ export default class SlotSection extends TranslatedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set focus on appropriate Slot Section Menu element
|
* Set focus on appropriate Slot Section Menu element
|
||||||
* @param {Object} focusPrevProps prevProps for componentDidUpdate() from ...SlotSection.jsx
|
* @param {Object} focusPrevProps prevProps for componentDidUpdate() from ...SlotSection.jsx
|
||||||
* @param {String} firstRef id of the first ref in ...SlotSection.jsx
|
* @param {String} firstRef id of the first ref in ...SlotSection.jsx
|
||||||
* @param {String} lastRef id of the last ref in ...SlotSection.jsx
|
* @param {String} lastRef id of the last ref in ...SlotSection.jsx
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
_handleSectionFocus(focusPrevProps, firstRef, lastRef) {
|
_handleSectionFocus(focusPrevProps, firstRef, lastRef) {
|
||||||
if (this.selectedRefId !== null && this.sectionRefArr[this.selectedRefId]) {
|
if (this.selectedRefId !== null && this.sectionRefArr[this.selectedRefId]) {
|
||||||
@@ -228,18 +228,6 @@ export default class SlotSection extends TranslatedComponent {
|
|||||||
targetSlot.priority = targetPriority;
|
targetSlot.priority = targetPriority;
|
||||||
}
|
}
|
||||||
this.props.onChange();
|
this.props.onChange();
|
||||||
this.props.ship
|
|
||||||
.updatePowerGenerated()
|
|
||||||
.updatePowerUsed()
|
|
||||||
.recalculateMass()
|
|
||||||
.updateJumpStats()
|
|
||||||
.recalculateShield()
|
|
||||||
.recalculateShieldCells()
|
|
||||||
.recalculateArmour()
|
|
||||||
.recalculateDps()
|
|
||||||
.recalculateEps()
|
|
||||||
.recalculateHps()
|
|
||||||
.updateMovement();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,9 +67,6 @@ export default class StandardSlot extends TranslatedComponent {
|
|||||||
if (m && m.name && m.name === 'Guardian Hybrid Power Plant') {
|
if (m && m.name && m.name === 'Guardian Hybrid Power Plant') {
|
||||||
validMods = [];
|
validMods = [];
|
||||||
}
|
}
|
||||||
if (m && m.name && m.name === 'Guardian Power Distributor') {
|
|
||||||
validMods = [];
|
|
||||||
}
|
|
||||||
let showModuleResistances = Persist.showModuleResistances();
|
let showModuleResistances = Persist.showModuleResistances();
|
||||||
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
let mass = m.getMass() || m.cargo || m.fuel || 0;
|
||||||
|
|
||||||
|
|||||||
@@ -228,30 +228,6 @@ export class LinkIcon extends SvgIcon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Link / Permalink / Chain
|
|
||||||
*/
|
|
||||||
export class OrbisIcon extends SvgIcon {
|
|
||||||
/**
|
|
||||||
* Generate the SVG
|
|
||||||
* @return {React.Component} SVG Contents
|
|
||||||
*/
|
|
||||||
svg() {
|
|
||||||
return (
|
|
||||||
<g transform="scale(.037296)">
|
|
||||||
<path d="m429 319c60.75 0 110 49.248 110 110 0 60.75-49.247 110-110 110s-110-49.247-110-110c0-60.749 49.248-110 110-110m0-20c-34.724 0-67.369 13.522-91.922 38.075s-38.075 57.198-38.075 91.922 13.522 67.369 38.075 91.922c24.553 24.554 57.198 38.075 91.922 38.075s67.369-13.521 91.922-38.075c24.554-24.553 38.075-57.198 38.075-91.922s-13.521-67.369-38.075-91.922c-24.553-24.553-57.198-38.075-91.922-38.075z" />
|
|
||||||
<path d="m429 235c107.14 0 194 86.855 194 194s-86.855 194-194 194-194-86.855-194-194 86.855-194 194-194m0-20c-28.881 0-56.908 5.661-83.304 16.825-25.485 10.779-48.368 26.207-68.016 45.853-19.646 19.647-35.074 42.53-45.853 68.015-11.163 26.396-16.824 54.423-16.824 83.304s5.661 56.908 16.825 83.304c10.779 25.484 26.207 48.368 45.853 68.016 19.647 19.646 42.53 35.073 68.015 45.854 26.396 11.164 54.423 16.825 83.304 16.825s56.908-5.661 83.304-16.825c25.484-10.779 48.368-26.206 68.016-45.854 19.646-19.646 35.073-42.53 45.854-68.016 11.164-26.396 16.825-54.423 16.825-83.304s-5.661-56.908-16.825-83.304c-10.779-25.485-26.206-48.368-45.854-68.015-19.646-19.646-42.53-35.074-68.016-45.853-26.396-11.164-54.423-16.825-83.304-16.825z" />
|
|
||||||
<path d="m429 63c202.14 0 366 163.86 366 366s-163.86 366-366 366-366-163.86-366-366 163.86-366 366-366m0-20c-52.101 0-102.65 10.208-150.25 30.342-45.966 19.442-87.244 47.271-122.69 82.714s-63.272 76.721-82.714 122.69c-20.134 47.601-30.342 98.153-30.342 150.25s10.208 102.65 30.342 150.25c19.442 45.967 47.271 87.244 82.714 122.69 35.443 35.442 76.721 63.271 122.69 82.715 47.601 20.133 98.153 30.342 150.25 30.342s102.65-10.209 150.25-30.342c45.967-19.442 87.244-47.271 122.69-82.715 35.441-35.442 63.271-76.721 82.714-122.69 20.133-47.601 30.342-98.153 30.342-150.25s-10.209-102.65-30.342-150.25c-19.442-45.966-47.271-87.244-82.714-122.69s-76.722-63.272-122.69-82.714c-47.601-20.134-98.153-30.342-150.25-30.342z"/>
|
|
||||||
<path d="m429 63c202.14 0 366 163.86 366 366s-163.86 366-366 366-366-163.86-366-366 163.86-366 366-366m0-20c-52.101 0-102.65 10.208-150.25 30.342-45.966 19.442-87.244 47.271-122.69 82.714s-63.272 76.721-82.714 122.69c-20.134 47.601-30.342 98.153-30.342 150.25s10.208 102.65 30.342 150.25c19.442 45.967 47.271 87.244 82.714 122.69 35.443 35.442 76.721 63.271 122.69 82.715 47.601 20.133 98.153 30.342 150.25 30.342s102.65-10.209 150.25-30.342c45.967-19.442 87.244-47.271 122.69-82.715 35.441-35.442 63.271-76.721 82.714-122.69 20.133-47.601 30.342-98.153 30.342-150.25s-10.209-102.65-30.342-150.25c-19.442-45.966-47.271-87.244-82.714-122.69s-76.722-63.272-122.69-82.714c-47.601-20.134-98.153-30.342-150.25-30.342z" />
|
|
||||||
<path d="m429 20c225.88 0 409 183.11 409 409s-183.11 409-409 409-409-183.11-409-409 183.11-409 409-409m0-20c-57.905 0-114.09 11.345-166.99 33.721-51.087 21.608-96.963 52.538-136.36 91.93s-70.321 85.269-91.93 136.36c-22.376 52.902-33.721 109.09-33.721 166.99s11.345 114.09 33.721 166.99c21.608 51.087 52.538 96.964 91.93 136.35 39.392 39.392 85.269 70.321 136.36 91.931 52.902 22.375 109.09 33.721 166.99 33.721s114.09-11.346 166.99-33.721c51.087-21.608 96.964-52.538 136.35-91.931 39.392-39.392 70.321-85.269 91.931-136.35 22.375-52.902 33.721-109.09 33.721-166.99s-11.346-114.09-33.721-166.99c-21.608-51.087-52.538-96.963-91.931-136.36-39.392-39.392-85.269-70.321-136.35-91.93-52.902-22.376-109.09-33.721-166.99-33.721z"/>
|
|
||||||
<path d="m155.34 679.12 173.25-190.21-15.626-13.721-170.9 190.4zm31.01 31.714 202.41-169.1-16.418-14.417-198.76 170.43z"/>
|
|
||||||
<path d="m702.66 178.87-173.25 190.21 15.625 13.721 170.9-190.4zm-31.01-31.714-202.41 169.1 16.418 14.417 198.76-170.43z" />
|
|
||||||
<rect transform="matrix(-.7071 -.7071 .7071 -.7071 429.34 1036.2)" x="387.09" y="420.77" width="84.379" height="16.859" />
|
|
||||||
</g>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Material
|
* Material
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,105 +1,111 @@
|
|||||||
import TranslatedComponent from './TranslatedComponent';
|
import TranslatedComponent from './TranslatedComponent';
|
||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import ContainerDimensions from 'react-container-dimensions';
|
import Measure from 'react-measure';
|
||||||
import { BarChart, Bar, XAxis, YAxis } from 'recharts';
|
import { BarChart, Bar, XAxis, YAxis } from 'recharts';
|
||||||
|
|
||||||
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
||||||
const LABEL_COLOUR = '#000000';
|
const LABEL_COLOUR = '#000000';
|
||||||
const AXIS_COLOUR = '#C06400';
|
const AXIS_COLOUR = '#C06400';
|
||||||
|
|
||||||
const ASPECT = 1;
|
const ASPECT = 1;
|
||||||
|
|
||||||
const merge = function(one, two) {
|
const merge = function(one, two) {
|
||||||
return Object.assign({}, one, two);
|
return Object.assign({}, one, two);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A vertical bar chart
|
* A vertical bar chart
|
||||||
*/
|
*/
|
||||||
export default class VerticalBarChart extends TranslatedComponent {
|
export default class VerticalBarChart extends TranslatedComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
data : PropTypes.array.isRequired,
|
data : PropTypes.array.isRequired,
|
||||||
yMax : PropTypes.number
|
yMax : PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param {Object} props React Component properties
|
* @param {Object} props React Component properties
|
||||||
* @param {Object} context React Component context
|
* @param {Object} context React Component context
|
||||||
*/
|
*/
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this._termtip = this._termtip.bind(this);
|
this._termtip = this._termtip.bind(this);
|
||||||
}
|
|
||||||
|
this.state = {
|
||||||
/**
|
dimensions: {
|
||||||
* Render the bar chart
|
width: 300,
|
||||||
* @returns {Object} the markup
|
height: 300
|
||||||
*/
|
}
|
||||||
render() {
|
};
|
||||||
const { tooltip, termtip } = this.context;
|
}
|
||||||
|
|
||||||
// Calculate maximum for Y
|
/**
|
||||||
let dataMax = Math.max(...this.props.data.map(d => d.value));
|
* Render the bar chart
|
||||||
if (dataMax == -Infinity) dataMax = 0;
|
* @returns {Object} the markup
|
||||||
let yMax = this.props.yMax ? Math.round(this.props.yMax) : 0;
|
*/
|
||||||
const localMax = Math.max(dataMax, yMax);
|
render() {
|
||||||
|
const { width, height } = this.state.dimensions;
|
||||||
return (
|
const { tooltip, termtip } = this.context;
|
||||||
<ContainerDimensions>
|
|
||||||
{ ({ width }) => (
|
// Calculate maximum for Y
|
||||||
<div width='100%'>
|
let dataMax = Math.max(...this.props.data.map(d => d.value));
|
||||||
<BarChart width={width} height={width * ASPECT} data={this.props.data} margin={{ top: 5, right: 5, left: 5, bottom: 5 }}>
|
if (dataMax == -Infinity) dataMax = 0;
|
||||||
<XAxis interval={0} fontSize='0.8em' stroke={AXIS_COLOUR} dataKey='label' />
|
let yMax = this.props.yMax ? Math.round(this.props.yMax) : 0;
|
||||||
<YAxis interval={'preserveStart'} tickCount={11} fontSize='0.8em' stroke={AXIS_COLOUR} type='number' domain={[0, localMax]}/>
|
const localMax = Math.max(dataMax, yMax);
|
||||||
<Bar dataKey='value' label={<ValueLabel />} fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}/>
|
|
||||||
</BarChart>
|
return (
|
||||||
</div>
|
<Measure whitelist={['width', 'top']} onMeasure={ (dimensions) => this.setState({ dimensions }) }>
|
||||||
)}
|
<div width='100%'>
|
||||||
</ContainerDimensions>
|
<BarChart width={width} height={width * ASPECT} data={this.props.data} margin={{ top: 5, right: 5, left: 5, bottom: 5 }}>
|
||||||
);
|
<XAxis interval={0} fontSize='0.8em' stroke={AXIS_COLOUR} dataKey='label' />
|
||||||
}
|
<YAxis interval={'preserveStart'} tickCount={11} fontSize='0.8em' stroke={AXIS_COLOUR} type='number' domain={[0, localMax]}/>
|
||||||
|
<Bar dataKey='value' label={<ValueLabel />} fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}/>
|
||||||
/**
|
</BarChart>
|
||||||
* Generate a term tip
|
</div>
|
||||||
* @param {Object} d the data
|
</Measure>
|
||||||
* @param {number} i the index
|
);
|
||||||
* @param {Object} e the event
|
}
|
||||||
* @returns {Object} termtip markup
|
|
||||||
*/
|
/**
|
||||||
_termtip(d, i, e) {
|
* Generate a term tip
|
||||||
if (this.props.data[i].tooltip) {
|
* @param {Object} d the data
|
||||||
return this.context.termtip(this.props.data[i].tooltip, e);
|
* @param {number} i the index
|
||||||
} else {
|
* @param {Object} e the event
|
||||||
return null;
|
* @returns {Object} termtip markup
|
||||||
}
|
*/
|
||||||
}
|
_termtip(d, i, e) {
|
||||||
}
|
if (this.props.data[i].tooltip) {
|
||||||
|
return this.context.termtip(this.props.data[i].tooltip, e);
|
||||||
/**
|
} else {
|
||||||
* A label that displays the value within the bar of the chart
|
return null;
|
||||||
*/
|
}
|
||||||
class ValueLabel extends React.Component {
|
}
|
||||||
static propTypes = {
|
}
|
||||||
x: PropTypes.number,
|
|
||||||
y: PropTypes.number,
|
/**
|
||||||
payload: PropTypes.object,
|
* A label that displays the value within the bar of the chart
|
||||||
value: PropTypes.number
|
*/
|
||||||
};
|
class ValueLabel extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
/**
|
x: PropTypes.number,
|
||||||
* Render offence
|
y: PropTypes.number,
|
||||||
* @return {React.Component} contents
|
payload: PropTypes.object,
|
||||||
*/
|
value: PropTypes.number
|
||||||
render() {
|
};
|
||||||
const { x, y, payload, value } = this.props;
|
|
||||||
|
/**
|
||||||
const em = value < 1000 ? '1em' : value < 1000 ? '0.8em' : '0.7em';
|
* Render offence
|
||||||
|
* @return {React.Component} contents
|
||||||
return (
|
*/
|
||||||
<text x={x} y={y} fill="#000000" textAnchor="middle" dy={20} style={{ fontSize: em }}>{value}</text>
|
render() {
|
||||||
);
|
const { x, y, payload, value } = this.props;
|
||||||
}
|
|
||||||
};
|
const em = value < 1000 ? '1em' : value < 1000 ? '0.8em' : '0.7em';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<text x={x} y={y} fill="#000000" textAnchor="middle" dy={20} style={{ fontSize: em }}>{value}</text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default class WeaponDamageChart extends TranslatedComponent {
|
|||||||
* Calculate the maximum range of a ship's weapons
|
* Calculate the maximum range of a ship's weapons
|
||||||
* @param {Object} ship The ship
|
* @param {Object} ship The ship
|
||||||
* @returns {int} The maximum range, in metres
|
* @returns {int} The maximum range, in metres
|
||||||
*/
|
*/
|
||||||
_calcMaxRange(ship) {
|
_calcMaxRange(ship) {
|
||||||
let maxRange = 1000; // Minimum
|
let maxRange = 1000; // Minimum
|
||||||
for (let i = 0; i < ship.hardpoints.length; i++) {
|
for (let i = 0; i < ship.hardpoints.length; i++) {
|
||||||
@@ -184,7 +184,7 @@ export default class WeaponDamageChart extends TranslatedComponent {
|
|||||||
const code = `${ship.toString()}:${opponent.toString()}`;
|
const code = `${ship.toString()}:${opponent.toString()}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<span>
|
||||||
<LineChart
|
<LineChart
|
||||||
xMax={maxRange}
|
xMax={maxRange}
|
||||||
yMax={this.state.maxDps}
|
yMax={this.state.maxDps}
|
||||||
@@ -198,7 +198,7 @@ export default class WeaponDamageChart extends TranslatedComponent {
|
|||||||
points={200}
|
points={200}
|
||||||
code={code}
|
code={code}
|
||||||
/>
|
/>
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,20 +60,17 @@ export function getLanguage(langCode) {
|
|||||||
},
|
},
|
||||||
translate,
|
translate,
|
||||||
units: {
|
units: {
|
||||||
ang: '°', // Angle
|
|
||||||
CR: <u>{translate('CR')}</u>, // Credits
|
CR: <u>{translate('CR')}</u>, // Credits
|
||||||
kg: <u>{translate('kg')}</u>, // Kilograms
|
kg: <u>{translate('kg')}</u>, // Kilograms
|
||||||
kgs: <u>{translate('kg/s')}</u>, // Kilograms per second
|
kgs: <u>{translate('kg/s')}</u>, // Kilograms per second
|
||||||
km: <u>{translate('km')}</u>, // Kilometers
|
km: <u>{translate('km')}</u>, // Kilometers
|
||||||
Ls: <u>{translate('Ls')}</u>, // Light Seconds
|
Ls: <u>{translate('Ls')}</u>, // Light Seconds
|
||||||
LY: <u>{translate('LY')}</u>, // Light Years
|
LY: <u>{translate('LY')}</u>, // Light Years
|
||||||
m: <u>{translate('m')}</u>, // Meters
|
|
||||||
MJ: <u>{translate('MJ')}</u>, // Mega Joules
|
MJ: <u>{translate('MJ')}</u>, // Mega Joules
|
||||||
'm/s': <u>{translate('m/s')}</u>, // Meters per second
|
'm/s': <u>{translate('m/s')}</u>, // Meters per second
|
||||||
'°/s': <u>{translate('°/s')}</u>, // Degrees per second
|
'°/s': <u>{translate('°/s')}</u>, // Degrees per second
|
||||||
MW: <u>{translate('MW')}</u>, // Mega Watts (same as Mega Joules per second)
|
MW: <u>{translate('MW')}</u>, // Mega Watts (same as Mega Joules per second)
|
||||||
mps: <u>{translate('m/s')}</u>, // Metres per second
|
mps: <u>{translate('m/s')}</u>, // Metres per second
|
||||||
pct: '%', // Percent
|
|
||||||
ps: <u>{translate('/s')}</u>, // per second
|
ps: <u>{translate('/s')}</u>, // per second
|
||||||
pm: <u>{translate('/min')}</u>, // per minute
|
pm: <u>{translate('/min')}</u>, // per minute
|
||||||
s: <u>{translate('secs')}</u>, // Seconds
|
s: <u>{translate('secs')}</u>, // Seconds
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -20,11 +20,11 @@
|
|||||||
"PHRASE_BLUEPRINT_BEST": "Лучшие основные значения для чертежа",
|
"PHRASE_BLUEPRINT_BEST": "Лучшие основные значения для чертежа",
|
||||||
"PHRASE_BLUEPRINT_EXTREME": "Лучшие положительные и худшие отрицательные основные значения для чертежа",
|
"PHRASE_BLUEPRINT_EXTREME": "Лучшие положительные и худшие отрицательные основные значения для чертежа",
|
||||||
"PHRASE_BLUEPRINT_RESET": "Убрать все изменения и чертёж",
|
"PHRASE_BLUEPRINT_RESET": "Убрать все изменения и чертёж",
|
||||||
"PHRASE_SELECT_SPECIAL": "Нажмите, чтобы выбрать экспериментальный эффект",
|
"PHRASE_SELECT_SPECIAL": "Нажмите чтобы выбрать экспериментальный эффект",
|
||||||
"PHRASE_NO_SPECIAL": "Без экспериментального эффекта",
|
"PHRASE_NO_SPECIAL": "Без экспериментального эффекта",
|
||||||
"PHRASE_SHOPPING_LIST": "Станции, что продают эту сборку",
|
"PHRASE_SHOPPING_LIST": "Станции что продают эту сборку",
|
||||||
"PHRASE_REFIT_SHOPPING_LIST": "Станции, что продают необходимые модули",
|
"PHRASE_REFIT_SHOPPING_LIST": "Станции что продают необходимые модули",
|
||||||
"PHRASE_TOTAL_EFFECTIVE_SHIELD": "Общий урон, что может быть нанесён в каждым типе, если используются все щитонакопители",
|
"PHRASE_TOTAL_EFFECTIVE_SHIELD": "Общий урон что может быть нанесён в каждым типе, если используются все щитонакопители",
|
||||||
"PHRASE_TIME_TO_LOSE_SHIELDS": "Щиты продержатся",
|
"PHRASE_TIME_TO_LOSE_SHIELDS": "Щиты продержатся",
|
||||||
"PHRASE_TIME_TO_RECOVER_SHIELDS": "Щиты восстановятся за",
|
"PHRASE_TIME_TO_RECOVER_SHIELDS": "Щиты восстановятся за",
|
||||||
"PHRASE_TIME_TO_RECHARGE_SHIELDS": "Щиты будут заряжены за",
|
"PHRASE_TIME_TO_RECHARGE_SHIELDS": "Щиты будут заряжены за",
|
||||||
@@ -43,12 +43,12 @@
|
|||||||
"PHRASE_TIME_TO_REMOVE_ARMOUR": "Снимет броню за",
|
"PHRASE_TIME_TO_REMOVE_ARMOUR": "Снимет броню за",
|
||||||
"TT_TIME_TO_REMOVE_ARMOUR": "Непрерывным огнём из всех орудий",
|
"TT_TIME_TO_REMOVE_ARMOUR": "Непрерывным огнём из всех орудий",
|
||||||
"PHRASE_TIME_TO_DRAIN_WEP": "Опустошит ОРУЖ за",
|
"PHRASE_TIME_TO_DRAIN_WEP": "Опустошит ОРУЖ за",
|
||||||
"TT_TIME_TO_DRAIN_WEP": "Время, за которое опустошится аккумулятор ОРУЖ при стрельбе из всех орудий",
|
"TT_TIME_TO_DRAIN_WEP": "Время за которое опустошится аккумулятор ОРУЖ при стрельбе из всех орудий",
|
||||||
"TT_TIME_TO_LOSE_SHIELDS": "Против поддерживаемой стрельбы из всех орудий противника",
|
"TT_TIME_TO_LOSE_SHIELDS": "Против поддерживаемой стрельбы из всех орудий противника",
|
||||||
"TT_TIME_TO_LOSE_ARMOUR": "Против поддерживаемой стрельбы из всех орудий противника",
|
"TT_TIME_TO_LOSE_ARMOUR": "Против поддерживаемой стрельбы из всех орудий противника",
|
||||||
"TT_MODULE_ARMOUR": "Броня, защищающая модули от урона",
|
"TT_MODULE_ARMOUR": "Броня защищаюшае модули от урона",
|
||||||
"TT_MODULE_PROTECTION_EXTERNAL": "Процент урона, перенаправленного от гнёзд на наборы для усиления модулей",
|
"TT_MODULE_PROTECTION_EXTERNAL": "Процент урона перенаправленного от гнёзд на наборы для усиления модулей",
|
||||||
"TT_MODULE_PROTECTION_INTERNAL": "Процент урона, перенаправленного от модулей вне гнёзд на наборы для усиления модулей",
|
"TT_MODULE_PROTECTION_INTERNAL": "Процент урона перенаправленного от модулей вне гнёзд на наборы для усиления модулей",
|
||||||
"TT_EFFECTIVE_SDPS_SHIELDS": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
"TT_EFFECTIVE_SDPS_SHIELDS": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
||||||
"TT_EFFECTIVENESS_SHIELDS": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью без пунктов в СИС на 0 метрах",
|
"TT_EFFECTIVENESS_SHIELDS": "Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью без пунктов в СИС на 0 метрах",
|
||||||
"TT_EFFECTIVE_SDPS_ARMOUR": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
"TT_EFFECTIVE_SDPS_ARMOUR": "Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст",
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
"PHRASE_EFFECTIVE_SDPS_SHIELDS": "ПДПС против щитов",
|
"PHRASE_EFFECTIVE_SDPS_SHIELDS": "ПДПС против щитов",
|
||||||
"PHRASE_EFFECTIVE_SDPS_ARMOUR": "ПДПС против брони",
|
"PHRASE_EFFECTIVE_SDPS_ARMOUR": "ПДПС против брони",
|
||||||
"TT_SUMMARY_SPEED": "С полным топливным баком и 4 пунктами в ДВИ",
|
"TT_SUMMARY_SPEED": "С полным топливным баком и 4 пунктами в ДВИ",
|
||||||
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "Маневровые двигатели выключены или превышена максимальная масса с топливом и грузом",
|
"TT_SUMMARY_SPEED_NONFUNCTIONAL": "маневровые двигатели выключены или превышена максимальная масса с топливом и грузом",
|
||||||
"TT_SUMMARY_BOOST": "С полным топливным баком и 4 пунктами в ДВИ",
|
"TT_SUMMARY_BOOST": "С полным топливным баком и 4 пунктами в ДВИ",
|
||||||
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Распределитель питания не может обеспечить достаточно энергии для форсажа",
|
"TT_SUMMARY_BOOST_NONFUNCTIONAL": "Распределитель питания не может обеспечить достаточно энергии для форсажа",
|
||||||
"TT_SUMMARY_SHIELDS": "Чистая сила щита, включая усилители",
|
"TT_SUMMARY_SHIELDS": "Чистая сила щита, включая усилители",
|
||||||
@@ -68,16 +68,16 @@
|
|||||||
"TT_SUMMARY_DPS": "Урон в секунду при стрельбе из всех орудий",
|
"TT_SUMMARY_DPS": "Урон в секунду при стрельбе из всех орудий",
|
||||||
"TT_SUMMARY_EPS": "Расход аккумулятора ОРУЖ в секунду при стрельбе из всех орудий",
|
"TT_SUMMARY_EPS": "Расход аккумулятора ОРУЖ в секунду при стрельбе из всех орудий",
|
||||||
"TT_SUMMARY_TTD": "Время расхода аккумулятора ОРУЖ при стрельбе из всех орудий и с 4 пунктами в ОРУЖ",
|
"TT_SUMMARY_TTD": "Время расхода аккумулятора ОРУЖ при стрельбе из всех орудий и с 4 пунктами в ОРУЖ",
|
||||||
"TT_SUMMARY_MAX_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с топливом, достаточным только на сам прыжок",
|
"TT_SUMMARY_MAX_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с топливом достаточным только на сам прыжок",
|
||||||
"TT_SUMMARY_UNLADEN_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с полным топливным баком",
|
"TT_SUMMARY_UNLADEN_SINGLE_JUMP": "Самый дальний возможный прыжок без груза и с полным топливным баком",
|
||||||
"TT_SUMMARY_LADEN_SINGLE_JUMP": "Самый дальний возможный прыжок с полным грузовым отсеком и с полным топливным баком",
|
"TT_SUMMARY_LADEN_SINGLE_JUMP": "Самый дальний возможный прыжок с полным грузовым отсеком и с полным топливным баком",
|
||||||
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Самая дальняя общая дистанция без груза, с полным топливным баком и при прыжках на максимальное расстояние",
|
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Самая дальняя общая дистанция без груза, с полным топливным баком и при прыжках на максимальное расстояние",
|
||||||
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Самая дальняя общая дистанция с полным грузовым отсеком, с полным топливным баком и при прыжках на максимальное расстояние",
|
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Самая дальняя общая дистанция с полным грузовым отсеком, с полным топливным баком и при прыжках на максимальное расстояние",
|
||||||
"HELP_MODIFICATIONS_MENU": "Нажмите на номер, чтобы ввести новое значение, или потяните вдоль полосы для малых изменений",
|
"HELP_MODIFICATIONS_MENU": "Ткните на номер чтобы ввести новое значение, или потяните вдоль полосы для малых изменений",
|
||||||
"am": "Блок Автом. Полевого Ремонта",
|
"am": "Блок Автом. Полевого Ремонта",
|
||||||
"bh": "Переборки",
|
"bh": "Переборки",
|
||||||
"bl": "Пучковый лазер",
|
"bl": "Пучковый Лазер",
|
||||||
"bsg": "Двухпоточный щитогенератор",
|
"bsg": "Двухпоточный Щитогенератор",
|
||||||
"c": "Орудие",
|
"c": "Орудие",
|
||||||
"cc": "Контроллер магнитного снаряда для сбора",
|
"cc": "Контроллер магнитного снаряда для сбора",
|
||||||
"ch": "Разбрасыватель дипольных отражателей",
|
"ch": "Разбрасыватель дипольных отражателей",
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
"fh": "Ангар для истребителя",
|
"fh": "Ангар для истребителя",
|
||||||
"fi": "FSD-перехватчик",
|
"fi": "FSD-перехватчик",
|
||||||
"fs": "Топливозаборник",
|
"fs": "Топливозаборник",
|
||||||
"fsd": "Рамочно-сместительный двигатель",
|
"fsd": "Рамочно Сместительный двигатель",
|
||||||
"ft": "Топливный бак",
|
"ft": "Топливный бак",
|
||||||
"fx": "Контроллер магнитного снаряда для топлива",
|
"fx": "Контроллер магнитного снаряда для топлива",
|
||||||
"hb": "Контроллер магнитного снаряда для взлома трюма",
|
"hb": "Контроллер магнитного снаряда для взлома трюма",
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
"pcm": "Каюта пассажира первого класса",
|
"pcm": "Каюта пассажира первого класса",
|
||||||
"pcq": "Каюта пассажира класса люкс",
|
"pcq": "Каюта пассажира класса люкс",
|
||||||
"pd": "Распределитель питания",
|
"pd": "Распределитель питания",
|
||||||
"pl": "Импульсный лазер",
|
"pl": "Ипмульсный лазер",
|
||||||
"po": "Точечная оборона",
|
"po": "Точечная оборона",
|
||||||
"pp": "Силовая установка",
|
"pp": "Силовая установка",
|
||||||
"psg": "Призматический щитогенератор",
|
"psg": "Призматический щитогенератор",
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
"sc": "Сканер обнаружения",
|
"sc": "Сканер обнаружения",
|
||||||
"scb": "Щитонакопитель",
|
"scb": "Щитонакопитель",
|
||||||
"sg": "Щитогенератор",
|
"sg": "Щитогенератор",
|
||||||
"ss": "Сканер поверхностей",
|
"ss": "Сканер Поверхностей",
|
||||||
"t": "Маневровые двигатели",
|
"t": "Маневровые двигатели",
|
||||||
"tp": "Торпедная стойка",
|
"tp": "Торпедная стойка",
|
||||||
"ul": "Пульсирующие лазеры",
|
"ul": "Пульсирующие лазеры",
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
"emptyrestricted": "пусто (ограниченно)",
|
"emptyrestricted": "пусто (ограниченно)",
|
||||||
"damage dealt to": "Урон нанесён",
|
"damage dealt to": "Урон нанесён",
|
||||||
"damage received from": "Урон получен от",
|
"damage received from": "Урон получен от",
|
||||||
"against shields": "Против щитов",
|
"against shields": "Против шитов",
|
||||||
"against hull": "Против корпуса",
|
"against hull": "Против корпуса",
|
||||||
"total effective shield": "Общие эффективные щиты",
|
"total effective shield": "Общие эффективные щиты",
|
||||||
"ammunition": "Припасы",
|
"ammunition": "Припасы",
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
"eps": "Энергия в секунду",
|
"eps": "Энергия в секунду",
|
||||||
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
"epsseps": "Энергия в секунду (поддерживаемая энергия в секунду)",
|
||||||
"hps": "Нагрев в секунду",
|
"hps": "Нагрев в секунду",
|
||||||
"hpsshps": "Нагрев в секунду (поддерживаемый нагрев в секунду)",
|
"hpsshps": "Heat per second (sustained heat per second)",
|
||||||
"damage by": "Урон",
|
"damage by": "Урон",
|
||||||
"damage from": "Урон от",
|
"damage from": "Урон от",
|
||||||
"shield cells": "Щитонакопители",
|
"shield cells": "Щитонакопители",
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
"hullreinforcement": "Укрепление корпуса",
|
"hullreinforcement": "Укрепление корпуса",
|
||||||
"integrity": "Целостность",
|
"integrity": "Целостность",
|
||||||
"jitter": "Дрожание",
|
"jitter": "Дрожание",
|
||||||
"kinres": "Сопротивление кинетическому урону",
|
"kinres": "Сопротивление китетическому урону",
|
||||||
"maxfuel": "Макс. топлива на прыжок",
|
"maxfuel": "Макс. топлива на прыжок",
|
||||||
"mass": "Масса",
|
"mass": "Масса",
|
||||||
"optmass": "Оптимизированная масса",
|
"optmass": "Оптимизированная масса",
|
||||||
@@ -381,4 +381,4 @@
|
|||||||
"URL": "Ссылка",
|
"URL": "Ссылка",
|
||||||
"WEP": "ОРУЖ",
|
"WEP": "ОРУЖ",
|
||||||
"yes": "Да"
|
"yes": "Да"
|
||||||
}
|
}
|
||||||
@@ -44,12 +44,6 @@ export default class AboutPage extends Page {
|
|||||||
|
|
||||||
<h3>Supporting Coriolis</h3>
|
<h3>Supporting Coriolis</h3>
|
||||||
<p>Coriolis is an open source project, and I work on it in my free time. I have set up a patreon at <a href='https://www.patreon.com/coriolis_elite'>patreon.com/coriolis_elite</a>, which will be used to keep Coriolis up to date and the servers running.</p>
|
<p>Coriolis is an open source project, and I work on it in my free time. I have set up a patreon at <a href='https://www.patreon.com/coriolis_elite'>patreon.com/coriolis_elite</a>, which will be used to keep Coriolis up to date and the servers running.</p>
|
||||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
|
||||||
<input type="hidden" name="cmd" value="_s-xclick"/>
|
|
||||||
<input type="hidden" name="hosted_button_id" value="SJBKT2SWEEU68" />
|
|
||||||
<input type="image" src="https://www.paypalobjects.com/en_AU/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!" />
|
|
||||||
<img alt="" border="0" src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif" width="1" height="1" />
|
|
||||||
</form>
|
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,20 +7,11 @@ import Module from './Module';
|
|||||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||||
* @param {number} fuel Optional - The fuel consumed during the jump
|
* @param {number} fuel Optional - The fuel consumed during the jump
|
||||||
* @return {number} Distance in Light Years
|
* @return {number} Distance in Light Years
|
||||||
* @param {object} ship Ship instance
|
|
||||||
*/
|
*/
|
||||||
export function jumpRange(mass, fsd, fuel, ship) {
|
export function jumpRange(mass, fsd, fuel) {
|
||||||
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
||||||
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
||||||
let jumpAddition = 0;
|
return Math.pow(Math.min(fuel === undefined ? fsdMaxFuelPerJump : fuel, fsdMaxFuelPerJump) / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass;
|
||||||
if (ship) {
|
|
||||||
for (const module of ship.internal) {
|
|
||||||
if (module && module.m && module.m.grp === 'gfsb') {
|
|
||||||
jumpAddition += module.m.getJumpBoost();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (Math.pow(Math.min(fuel === undefined ? fsdMaxFuelPerJump : fuel, fsdMaxFuelPerJump) / fsd.fuelmul, 1 / fsd.fuelpower) * fsdOptimalMass / mass) + jumpAddition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,9 +21,8 @@ export function jumpRange(mass, fsd, fuel, ship) {
|
|||||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||||
* @param {number} fuel The total fuel available
|
* @param {number} fuel The total fuel available
|
||||||
* @return {number} Distance in Light Years
|
* @return {number} Distance in Light Years
|
||||||
* @param {object} ship Ship instance
|
|
||||||
*/
|
*/
|
||||||
export function totalJumpRange(mass, fsd, fuel, ship) {
|
export function totalJumpRange(mass, fsd, fuel) {
|
||||||
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
const fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
||||||
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
const fsdOptimalMass = fsd instanceof Module ? fsd.getOptMass() : fsd.optmass;
|
||||||
|
|
||||||
@@ -40,7 +30,7 @@ export function totalJumpRange(mass, fsd, fuel, ship) {
|
|||||||
let totalRange = 0;
|
let totalRange = 0;
|
||||||
while (fuelRemaining > 0) {
|
while (fuelRemaining > 0) {
|
||||||
const fuelForThisJump = Math.min(fuelRemaining, fsdMaxFuelPerJump);
|
const fuelForThisJump = Math.min(fuelRemaining, fsdMaxFuelPerJump);
|
||||||
totalRange += this.jumpRange(mass, fsd, fuelForThisJump, ship);
|
totalRange += this.jumpRange(mass, fsd, fuelForThisJump);
|
||||||
// Mass is reduced
|
// Mass is reduced
|
||||||
mass -= fuelForThisJump;
|
mass -= fuelForThisJump;
|
||||||
fuelRemaining -= fuelForThisJump;
|
fuelRemaining -= fuelForThisJump;
|
||||||
@@ -70,7 +60,7 @@ export function shieldStrength(mass, baseShield, sg, multiplier) {
|
|||||||
let ynorm = Math.pow(xnorm, exponent);
|
let ynorm = Math.pow(xnorm, exponent);
|
||||||
let mul = minMul + ynorm * (maxMul - minMul);
|
let mul = minMul + ynorm * (maxMul - minMul);
|
||||||
|
|
||||||
return (baseShield * mul * multiplier);
|
return baseShield * mul * multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,16 +86,6 @@ export function speed(mass, baseSpeed, thrusters, engpip) {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate pip multiplier for speed.
|
|
||||||
* @param {number} baseSpeed The base speed of ship in data
|
|
||||||
* @param {number} topSpeed The top speed of ship in data
|
|
||||||
* @return {number} The multiplier that pips affect speed.
|
|
||||||
*/
|
|
||||||
export function calcPipSpeed(baseSpeed, topSpeed) {
|
|
||||||
return (topSpeed - baseSpeed) / (4 * topSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate pitch of a ship based on mass and thrusters
|
* Calculate pitch of a ship based on mass and thrusters
|
||||||
* @param {number} mass the mass of the ship
|
* @param {number} mass the mass of the ship
|
||||||
@@ -221,7 +201,7 @@ function calcValue(minMass, optMass, maxMass, minMul, optMul, maxMul, mass, base
|
|||||||
* Calculate speed for a given setup
|
* Calculate speed for a given setup
|
||||||
* @param {number} mass the mass of the ship
|
* @param {number} mass the mass of the ship
|
||||||
* @param {number} baseSpeed the base speed of the ship
|
* @param {number} baseSpeed the base speed of the ship
|
||||||
* @param {object} thrusters the thrusters of the ship
|
* @param {ojbect} thrusters the thrusters of the ship
|
||||||
* @param {number} engpip the multiplier per pip to engines
|
* @param {number} engpip the multiplier per pip to engines
|
||||||
* @param {number} eng the pips to engines
|
* @param {number} eng the pips to engines
|
||||||
* @param {number} boostFactor the boost factor for ths ship
|
* @param {number} boostFactor the boost factor for ths ship
|
||||||
@@ -249,7 +229,7 @@ export function calcSpeed(mass, baseSpeed, thrusters, engpip, eng, boostFactor,
|
|||||||
* Calculate pitch for a given setup
|
* Calculate pitch for a given setup
|
||||||
* @param {number} mass the mass of the ship
|
* @param {number} mass the mass of the ship
|
||||||
* @param {number} basePitch the base pitch of the ship
|
* @param {number} basePitch the base pitch of the ship
|
||||||
* @param {object} thrusters the thrusters of the ship
|
* @param {ojbect} thrusters the thrusters of the ship
|
||||||
* @param {number} engpip the multiplier per pip to engines
|
* @param {number} engpip the multiplier per pip to engines
|
||||||
* @param {number} eng the pips to engines
|
* @param {number} eng the pips to engines
|
||||||
* @param {number} boostFactor the boost factor for ths ship
|
* @param {number} boostFactor the boost factor for ths ship
|
||||||
@@ -340,76 +320,41 @@ export function shieldMetrics(ship, sys) {
|
|||||||
const maxSysResistance = this.sysResistance(4);
|
const maxSysResistance = this.sysResistance(4);
|
||||||
|
|
||||||
let shield = {};
|
let shield = {};
|
||||||
const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
|
|
||||||
|
|
||||||
const shieldGeneratorSlot = ship.findInternalByGroup('sg');
|
const shieldGeneratorSlot = ship.findInternalByGroup('sg');
|
||||||
if (shieldGeneratorSlot && shieldGeneratorSlot.enabled && shieldGeneratorSlot.m) {
|
if (shieldGeneratorSlot && shieldGeneratorSlot.enabled && shieldGeneratorSlot.m) {
|
||||||
const shieldGenerator = shieldGeneratorSlot.m;
|
const shieldGenerator = shieldGeneratorSlot.m;
|
||||||
let res = {
|
|
||||||
kin: shieldGenerator.kinres,
|
|
||||||
therm: shieldGenerator.thermres,
|
|
||||||
expl: shieldGenerator.explres
|
|
||||||
};
|
|
||||||
// Boosters
|
// Boosters
|
||||||
let boost = 1;
|
let boost = 1;
|
||||||
let boosterExplDmg = 1;
|
let boosterExplDmg = 1;
|
||||||
let boosterKinDmg = 1;
|
let boosterKinDmg = 1;
|
||||||
let boosterThermDmg = 1;
|
let boosterThermDmg = 1;
|
||||||
// const explDim = dimReturnLine(shieldGenerator.explres);
|
|
||||||
// const thermDim = dimReturnLine(shieldGenerator.thermres);
|
|
||||||
// const kinDim = dimReturnLine(shieldGenerator.kinres);
|
|
||||||
for (let slot of ship.hardpoints) {
|
for (let slot of ship.hardpoints) {
|
||||||
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
|
if (slot.enabled && slot.m && slot.m.grp == 'sb') {
|
||||||
boost += slot.m.getShieldBoost();
|
boost += slot.m.getShieldBoost();
|
||||||
res.expl += slot.m.getExplosiveResistance();
|
|
||||||
res.kin += slot.m.getKineticResistance();
|
|
||||||
res.therm += slot.m.getThermalResistance();
|
|
||||||
boosterExplDmg = boosterExplDmg * (1 - slot.m.getExplosiveResistance());
|
boosterExplDmg = boosterExplDmg * (1 - slot.m.getExplosiveResistance());
|
||||||
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
|
boosterKinDmg = boosterKinDmg * (1 - slot.m.getKineticResistance());
|
||||||
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
|
boosterThermDmg = boosterThermDmg * (1 - slot.m.getThermalResistance());
|
||||||
}
|
}
|
||||||
if (slot.m && slot.m.grp == 'gsrp') {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate diminishing returns for boosters
|
// Calculate diminishing returns for boosters
|
||||||
// Diminishing returns not currently in-game
|
// Diminishing returns not currently in-game
|
||||||
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
|
// boost = Math.min(boost, (1 - Math.pow(Math.E, -0.7 * boost)) * 2.5);
|
||||||
|
|
||||||
|
|
||||||
// Remove base shield generator strength
|
// Remove base shield generator strength
|
||||||
boost -= 1;
|
boost -= 1;
|
||||||
|
// Apply diminishing returns
|
||||||
|
boosterExplDmg = boosterExplDmg > 0.7 ? boosterExplDmg : 0.7 - (0.7 - boosterExplDmg) / 2;
|
||||||
|
boosterKinDmg = boosterKinDmg > 0.7 ? boosterKinDmg : 0.7 - (0.7 - boosterKinDmg) / 2;
|
||||||
|
boosterThermDmg = boosterThermDmg > 0.7 ? boosterThermDmg : 0.7 - (0.7 - boosterThermDmg) / 2;
|
||||||
|
|
||||||
// if (res.expl > explDim) {
|
const generatorStrength = this.shieldStrength(ship.hullMass, ship.baseShieldStrength, shieldGenerator, 1);
|
||||||
// const overage = (res.expl - explDim) * 0.5;
|
|
||||||
// res.expl = explDim + overage;
|
|
||||||
// boosterExplDmg = explDim + overage;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (res.therm > thermDim) {
|
|
||||||
// const overage = (res.therm - thermDim) * 0.5;
|
|
||||||
// res.therm = thermDim + overage;
|
|
||||||
// boosterThermDmg = thermDim + overage;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (res.kin > kinDim) {
|
|
||||||
// const overage = (res.kin - kinDim) * 0.5;
|
|
||||||
// res.kin = kinDim + overage;
|
|
||||||
// boosterKinDmg = kinDim + overage;
|
|
||||||
// }
|
|
||||||
let shieldAddition = 0;
|
|
||||||
if (ship) {
|
|
||||||
for (const module of ship.internal) {
|
|
||||||
if (module && module.m && module.m.grp === 'gsrp') {
|
|
||||||
shieldAddition += module.m.getShieldAddition();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let generatorStrength = this.shieldStrength(ship.hullMass, ship.baseShieldStrength, shieldGenerator, 1);
|
|
||||||
const boostersStrength = generatorStrength * boost;
|
const boostersStrength = generatorStrength * boost;
|
||||||
|
|
||||||
// Recover time is the time taken to go from 0 to 50%. It includes a 16-second wait before shields start to recover
|
// Recover time is the time taken to go from 0 to 50%. It includes a 16-second wait before shields start to recover
|
||||||
const shieldToRecover = (generatorStrength + boostersStrength + shieldAddition) / 2;
|
const shieldToRecover = (generatorStrength + boostersStrength) / 2;
|
||||||
const powerDistributor = ship.standard[4].m;
|
const powerDistributor = ship.standard[4].m;
|
||||||
const sysRechargeRate = this.sysRechargeRate(powerDistributor, sys);
|
const sysRechargeRate = this.sysRechargeRate(powerDistributor, sys);
|
||||||
|
|
||||||
@@ -428,7 +373,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
const remainingShieldToRecover = shieldToRecover - capacitorLifetime * shieldGenerator.getBrokenRegenerationRate();
|
const remainingShieldToRecover = shieldToRecover - capacitorLifetime * shieldGenerator.getBrokenRegenerationRate();
|
||||||
if (sys === 0) {
|
if (sys === 0) {
|
||||||
// No system pips so will never recover shields
|
// No system pips so will never recover shields
|
||||||
recover = Math.Infinity;
|
recover = Math.Inf;
|
||||||
} else {
|
} else {
|
||||||
// Recover remaining shields at the rate of the power distributor's recharge
|
// Recover remaining shields at the rate of the power distributor's recharge
|
||||||
recover += remainingShieldToRecover / (sysRechargeRate / 0.6);
|
recover += remainingShieldToRecover / (sysRechargeRate / 0.6);
|
||||||
@@ -436,7 +381,7 @@ export function shieldMetrics(ship, sys) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recharge time is the time taken to go from 50% to 100%
|
// Recharge time is the time taken to go from 50% to 100%
|
||||||
const shieldToRecharge = (generatorStrength + boostersStrength + shieldAddition) / 2;
|
const shieldToRecharge = (generatorStrength + boostersStrength) / 2;
|
||||||
|
|
||||||
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
// Our initial regeneration comes from the SYS capacitor store, which is replenished as it goes
|
||||||
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
// 0.6 is a magic number from FD: each 0.6 MW of energy from the power distributor recharges 1 MJ/s of regeneration
|
||||||
@@ -463,9 +408,8 @@ export function shieldMetrics(ship, sys) {
|
|||||||
shield = {
|
shield = {
|
||||||
generator: generatorStrength,
|
generator: generatorStrength,
|
||||||
boosters: boostersStrength,
|
boosters: boostersStrength,
|
||||||
addition: shieldAddition,
|
|
||||||
cells: ship.shieldCells,
|
cells: ship.shieldCells,
|
||||||
total: generatorStrength + boostersStrength + ship.shieldCells + shieldAddition,
|
total: generatorStrength + boostersStrength + ship.shieldCells,
|
||||||
recover,
|
recover,
|
||||||
recharge,
|
recharge,
|
||||||
};
|
};
|
||||||
@@ -480,71 +424,44 @@ export function shieldMetrics(ship, sys) {
|
|||||||
max: 1 - maxSysResistance
|
max: 1 - maxSysResistance
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* An object that stores a selection of difference damage multipliers that
|
|
||||||
* deal with a ship's shield strength.
|
|
||||||
* @typedef {Object} ShieldDamageMults
|
|
||||||
* @property {number} generator Base damage multiplier of the shield
|
|
||||||
* contributing it's base resistance.
|
|
||||||
* @property {number} boosters Damage multiplier contributed by all
|
|
||||||
* boosters, i.e. `rawMj / (generator * boosters)` equals shield strength
|
|
||||||
* with 0 pips to sys.
|
|
||||||
* @property {number} sys Damage multiplier contributed by pips to sys.
|
|
||||||
* @property {number} base Damage multiplier with 0 pips to sys; just
|
|
||||||
* boosters and shield generator. Equals `generator * boosters`.
|
|
||||||
* @property {number} total Damage multiplier with current pip settings.
|
|
||||||
* @property {number} max Damage multiplier with 4 pips to sys.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let sgExplosiveDmg = 1 - shieldGenerator.getExplosiveResistance();
|
|
||||||
let sgSbExplosiveDmg = diminishDamageMult(sgExplosiveDmg * 0.7, (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg);
|
|
||||||
/** @type {ShieldDamageMults} */
|
|
||||||
shield.explosive = {
|
shield.explosive = {
|
||||||
generator: sgExplosiveDmg,
|
generator: 1 - shieldGenerator.getExplosiveResistance(),
|
||||||
boosters: sgSbExplosiveDmg / sgExplosiveDmg,
|
boosters: boosterExplDmg,
|
||||||
sys: (1 - sysResistance),
|
sys: (1 - sysResistance),
|
||||||
base: sgSbExplosiveDmg,
|
total: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - sysResistance),
|
||||||
total: sgSbExplosiveDmg * (1 - sysResistance),
|
max: (1 - shieldGenerator.getExplosiveResistance()) * boosterExplDmg * (1 - maxSysResistance)
|
||||||
max: sgSbExplosiveDmg * (1 - maxSysResistance),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let sgKineticDmg = 1 - shieldGenerator.getKineticResistance();
|
|
||||||
let sgSbKineticDmg = diminishDamageMult(sgKineticDmg * 0.7, (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg);
|
|
||||||
/** @type {ShieldDamageMults} */
|
|
||||||
shield.kinetic = {
|
shield.kinetic = {
|
||||||
generator: sgKineticDmg,
|
generator: 1 - shieldGenerator.getKineticResistance(),
|
||||||
boosters: sgSbKineticDmg / sgKineticDmg,
|
boosters: boosterKinDmg,
|
||||||
sys: (1 - sysResistance),
|
sys: (1 - sysResistance),
|
||||||
base: sgSbKineticDmg,
|
total: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - sysResistance),
|
||||||
total: sgSbKineticDmg * (1 - sysResistance),
|
max: (1 - shieldGenerator.getKineticResistance()) * boosterKinDmg * (1 - maxSysResistance)
|
||||||
max: sgSbKineticDmg * (1 - maxSysResistance),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let sgThermalDmg = 1 - shieldGenerator.getThermalResistance();
|
|
||||||
let sgSbThermalDmg = diminishDamageMult(sgThermalDmg * 0.7, (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg);
|
|
||||||
/** @type {ShieldDamageMults} */
|
|
||||||
shield.thermal = {
|
shield.thermal = {
|
||||||
generator: sgThermalDmg,
|
generator: 1 - shieldGenerator.getThermalResistance(),
|
||||||
boosters: sgSbThermalDmg / sgThermalDmg,
|
boosters: boosterThermDmg,
|
||||||
sys: (1 - sysResistance),
|
sys: (1 - sysResistance),
|
||||||
base: sgSbThermalDmg,
|
total: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - sysResistance),
|
||||||
total: sgSbThermalDmg * (1 - sysResistance),
|
max: (1 - shieldGenerator.getThermalResistance()) * boosterThermDmg * (1 - maxSysResistance)
|
||||||
max: sgSbThermalDmg * (1 - maxSysResistance),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return shield;
|
return shield;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate time from one boost to another
|
* Calculate time from one boost to another
|
||||||
* @return {number} Boost frequency in seconds
|
* @return {number} Boost frequency in seconds
|
||||||
* @param {Ship} ship Ship object
|
* @param ship
|
||||||
*/
|
*/
|
||||||
export function calcBoost(ship) {
|
export function calcBoost(ship) {
|
||||||
if (!ship.boostEnergy || !ship.standard[4] || !ship.standard[4].m) {
|
if (!ship.boostEnergy || !ship.standard[4] || !ship.standard[4].m) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return ship.boostEnergy / ship.standard[4].m.getEnginesRechargeRate();
|
return ship.boostEnergy / ship.standard[4].m.engrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -560,58 +477,33 @@ export function armourMetrics(ship) {
|
|||||||
|
|
||||||
let moduleArmour = 0;
|
let moduleArmour = 0;
|
||||||
let moduleProtection = 1;
|
let moduleProtection = 1;
|
||||||
const bulkheads = ship.bulkheads.m;
|
|
||||||
let hullExplDmg = 1;
|
let hullExplDmg = 1;
|
||||||
let hullKinDmg = 1;
|
let hullKinDmg = 1;
|
||||||
let hullThermDmg = 1;
|
let hullThermDmg = 1;
|
||||||
let hullCausDmg = 1;
|
|
||||||
// const dimReturnLine = (res) => 1 - (1 - res) * 0.7;
|
|
||||||
// let res = {
|
|
||||||
// kin: 0,
|
|
||||||
// therm: 0,
|
|
||||||
// expl: 0
|
|
||||||
// };
|
|
||||||
// Armour from HRPs and module armour from MRPs
|
// Armour from HRPs and module armour from MRPs
|
||||||
for (let slot of ship.internal) {
|
for (let slot of ship.internal) {
|
||||||
if (slot.m && (slot.m.grp === 'hr' || slot.m.grp === 'ghrp' || slot.m.grp == 'mahr')) {
|
if (slot.m && slot.m.grp == 'hr') {
|
||||||
armourReinforcement += slot.m.getHullReinforcement();
|
armourReinforcement += slot.m.getHullReinforcement();
|
||||||
// Hull boost for HRPs is applied against the ship's base armour
|
// Hull boost for HRPs is applied against the ship's base armour
|
||||||
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
|
armourReinforcement += ship.baseArmour * slot.m.getModValue('hullboost') / 10000;
|
||||||
// res.expl += slot.m.getExplosiveResistance();
|
|
||||||
// res.kin += slot.m.getKineticResistance();
|
|
||||||
// res.therm += slot.m.getThermalResistance();
|
|
||||||
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
|
hullExplDmg = hullExplDmg * (1 - slot.m.getExplosiveResistance());
|
||||||
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
|
hullKinDmg = hullKinDmg * (1 - slot.m.getKineticResistance());
|
||||||
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
|
hullThermDmg = hullThermDmg * (1 - slot.m.getThermalResistance());
|
||||||
hullCausDmg = hullCausDmg * (1 - slot.m.getCausticResistance());
|
|
||||||
}
|
}
|
||||||
if (slot.m && (slot.m.grp == 'mrp' || slot.m.grp == 'gmrp')) {
|
if (slot.m && slot.m.grp == 'mrp') {
|
||||||
moduleArmour += slot.m.getIntegrity();
|
moduleArmour += slot.m.getIntegrity();
|
||||||
moduleProtection = moduleProtection * (1 - slot.m.getProtection());
|
moduleProtection = moduleProtection * (1 - slot.m.getProtection());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
moduleProtection = 1 - moduleProtection;
|
moduleProtection = 1 - moduleProtection;
|
||||||
|
|
||||||
// const explDim = dimReturnLine(bulkheads.explres);
|
// Apply diminishing returns
|
||||||
// const thermDim = dimReturnLine(bulkheads.thermres);
|
hullExplDmg = hullExplDmg > 0.7 ? hullExplDmg : 0.7 - (0.7 - hullExplDmg) / 2;
|
||||||
// const kinDim = dimReturnLine(bulkheads.kinres);
|
hullKinDmg = hullKinDmg > 0.7 ? hullKinDmg : 0.7 - (0.7 - hullKinDmg) / 2;
|
||||||
// if (res.expl > explDim) {
|
hullThermDmg = hullThermDmg > 0.7 ? hullThermDmg : 0.7 - (0.7 - hullThermDmg) / 2;
|
||||||
// const overage = (res.expl - explDim) * 0.5;
|
|
||||||
// res.expl = explDim + overage;
|
|
||||||
// hullExplDmg = explDim + overage;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (res.therm > thermDim) {
|
|
||||||
// const overage = (res.therm - thermDim) * 0.5;
|
|
||||||
// res.therm = thermDim + overage;
|
|
||||||
// hullThermDmg = thermDim + overage;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (res.kin > kinDim) {
|
|
||||||
// const overage = (res.kin - kinDim) * 0.5;
|
|
||||||
// res.kin = kinDim + overage;
|
|
||||||
// hullKinDmg = kinDim + overage;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const armour = {
|
const armour = {
|
||||||
bulkheads: armourBulkheads,
|
bulkheads: armourBulkheads,
|
||||||
@@ -629,41 +521,24 @@ export function armourMetrics(ship) {
|
|||||||
total: 1
|
total: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourExplDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getExplosiveResistance());
|
|
||||||
let armourReinforcedExplDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg);
|
|
||||||
armour.explosive = {
|
armour.explosive = {
|
||||||
bulkheads: armourExplDmg,
|
bulkheads: 1 - ship.bulkheads.m.getExplosiveResistance(),
|
||||||
reinforcement: armourReinforcedExplDmg / armourExplDmg,
|
reinforcement: hullExplDmg,
|
||||||
total: armourReinforcedExplDmg,
|
total: (1 - ship.bulkheads.m.getExplosiveResistance()) * hullExplDmg
|
||||||
res: 1 - armourReinforcedExplDmg
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourKinDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getKineticResistance());
|
|
||||||
let armourReinforcedKinDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg);
|
|
||||||
armour.kinetic = {
|
armour.kinetic = {
|
||||||
bulkheads: armourKinDmg,
|
bulkheads: 1 - ship.bulkheads.m.getKineticResistance(),
|
||||||
reinforcement: armourReinforcedKinDmg / armourKinDmg,
|
reinforcement: hullKinDmg,
|
||||||
total: armourReinforcedKinDmg,
|
total: (1 - ship.bulkheads.m.getKineticResistance()) * hullKinDmg
|
||||||
res: 1 - armourReinforcedKinDmg
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourThermDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getThermalResistance());
|
|
||||||
let armourReinforcedThermDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg);
|
|
||||||
armour.thermal = {
|
armour.thermal = {
|
||||||
bulkheads: armourThermDmg,
|
bulkheads: 1 - ship.bulkheads.m.getThermalResistance(),
|
||||||
reinforcement: armourReinforcedThermDmg / armourThermDmg,
|
reinforcement: hullThermDmg,
|
||||||
total: armourReinforcedThermDmg,
|
total: (1 - ship.bulkheads.m.getThermalResistance()) * hullThermDmg
|
||||||
res: 1 - armourReinforcedThermDmg
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let armourCausDmg = diminishDamageMult(0.7, 1 - ship.bulkheads.m.getCausticResistance());
|
|
||||||
let armourReinforcedCausDmg = diminishDamageMult(0.7, (1 - ship.bulkheads.m.getCausticResistance()) * hullCausDmg);
|
|
||||||
armour.caustic = {
|
|
||||||
bulkheads: armourCausDmg,
|
|
||||||
reinforcement: armourReinforcedCausDmg / armourCausDmg,
|
|
||||||
total: armourReinforcedCausDmg,
|
|
||||||
res: 1 - armourReinforcedCausDmg,
|
|
||||||
};
|
|
||||||
return armour;
|
return armour;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,55 +710,20 @@ export function _sustainedDps(ship, opponent, opponentShields, opponentArmour, e
|
|||||||
return { shieldsdps, armoursdps, eps };
|
return { shieldsdps, armoursdps, eps };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores SDPS split up by type.
|
|
||||||
* @typedef {Object} SDps
|
|
||||||
* @property {number} absolute Damage of type absolute
|
|
||||||
* @property {number} explosive Damage of type explosive
|
|
||||||
* @property {number} kinetic Damage of type kinetic
|
|
||||||
* @property {number} thermal Damage of type thermal
|
|
||||||
* @property {number} [total] Sum of all damage types
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object that holds information about SDPS for a given weapon and opponent.
|
|
||||||
* @typedef {Object} WeaponDamage
|
|
||||||
* @property {number} eps Energy per second
|
|
||||||
* @property {Object} damage An object that stores damage inflicted by
|
|
||||||
* the weapon.
|
|
||||||
* @property {Object} effectiveness An object that stores the effectiveness of
|
|
||||||
* the weapon against the opponent given.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores overall SDPS and against a given opponent's shields and armour.
|
|
||||||
* @typedef {Object} WeaponDamage~damage
|
|
||||||
* @property {SDps} base Overall SDPS.
|
|
||||||
* @property {SDps} shields SDPS against the given opponent's shields.
|
|
||||||
* @property {SDps} armour SDPS against the given opponent's armour.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the sustained DPS for a weapon at a given range
|
* Calculate the sustained DPS for a weapon at a given range
|
||||||
* @param {Object} m The weapon
|
* @param {Object} m The weapon
|
||||||
* @param {Object} opponent The opponent ship
|
* @param {Object} opponent The opponent ship
|
||||||
* @param {Object} opponentShields The opponent's shield resistances
|
* @param {Object} opponentShields The opponent's shield resistances
|
||||||
* @param {Object} opponentArmour The opponent's armour resistances
|
* @param {Object} opponentArmour The opponent's armour resistances
|
||||||
* @param {int} engagementrange The range between the ship and opponent
|
* @param {int} engagementrange The range between the ship and opponent
|
||||||
* @returns {WeaponDamage} Sustained DPS for shield and armour
|
* @returns {Object} Sustained DPS for shield and armour
|
||||||
*/
|
*/
|
||||||
export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour, engagementrange) {
|
export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour, engagementrange) {
|
||||||
const opponentHasShields = opponentShields.generator ? true : false;
|
const opponentHasShields = opponentShields.generator ? true : false;
|
||||||
const weapon = {
|
const weapon = {
|
||||||
eps: 0,
|
eps: 0,
|
||||||
damage: {
|
damage: {
|
||||||
base: {
|
|
||||||
absolute: 0,
|
|
||||||
explosive: 0,
|
|
||||||
kinetic: 0,
|
|
||||||
thermal: 0,
|
|
||||||
total: 0,
|
|
||||||
},
|
|
||||||
shields: {
|
shields: {
|
||||||
absolute: 0,
|
absolute: 0,
|
||||||
explosive: 0,
|
explosive: 0,
|
||||||
@@ -917,7 +757,7 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
|||||||
weapon.eps = m.getClip() ? (m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()) : m.getEps();
|
weapon.eps = m.getClip() ? (m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()) : m.getEps();
|
||||||
|
|
||||||
// Initial sustained DPS
|
// Initial sustained DPS
|
||||||
let sDps = m.getSDps();
|
let sDps = m.getClip() ? (m.getClip() * m.getDps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()) : m.getDps();
|
||||||
|
|
||||||
// Take fall-off in to account
|
// Take fall-off in to account
|
||||||
const falloff = m.getFalloff();
|
const falloff = m.getFalloff();
|
||||||
@@ -928,12 +768,6 @@ export function _weaponSustainedDps(m, opponent, opponentShields, opponentArmour
|
|||||||
sDps *= dropoff;
|
sDps *= dropoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
weapon.damage.base.absolute = sDps * m.getDamageDist().A;
|
|
||||||
weapon.damage.base.explosive = sDps * m.getDamageDist().E;
|
|
||||||
weapon.damage.base.kinetic = sDps * m.getDamageDist().K;
|
|
||||||
weapon.damage.base.thermal = sDps * m.getDamageDist().T;
|
|
||||||
weapon.damage.base.total = sDps;
|
|
||||||
|
|
||||||
// Piercing/hardness modifier (for armour only)
|
// Piercing/hardness modifier (for armour only)
|
||||||
const armourMultiple = m.getPiercing() >= opponent.hardness ? 1 : m.getPiercing() / opponent.hardness;
|
const armourMultiple = m.getPiercing() >= opponent.hardness ? 1 : m.getPiercing() / opponent.hardness;
|
||||||
weapon.effectiveness.armour.hardness = armourMultiple;
|
weapon.effectiveness.armour.hardness = armourMultiple;
|
||||||
@@ -1031,17 +865,3 @@ export function timeToDeplete(amount, dps, eps, capacity, recharge) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies diminishing returns to resistances.
|
|
||||||
* @param {number} diminishFrom The base resistance up to which no diminishing returns are applied.
|
|
||||||
* @param {number} damageMult Resistance as damage multiplier
|
|
||||||
* @returns {number} Actual damage multiplier
|
|
||||||
*/
|
|
||||||
export function diminishDamageMult(diminishFrom, damageMult) {
|
|
||||||
if (damageMult > diminishFrom) {
|
|
||||||
return damageMult;
|
|
||||||
} else {
|
|
||||||
return (diminishFrom / 2) + 0.5 * damageMult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const ModuleGroupToName = {
|
|||||||
// Standard
|
// Standard
|
||||||
pp: 'Power Plant',
|
pp: 'Power Plant',
|
||||||
gpp: 'Guardian Hybrid Power Plant',
|
gpp: 'Guardian Hybrid Power Plant',
|
||||||
gpd: 'Guardian Power Distributor',
|
gpd: 'Guardian Hybrid Power Distributor',
|
||||||
t: 'Thrusters',
|
t: 'Thrusters',
|
||||||
fsd: 'Frame Shift Drive',
|
fsd: 'Frame Shift Drive',
|
||||||
ls: 'Life Support',
|
ls: 'Life Support',
|
||||||
@@ -52,11 +52,6 @@ export const ModuleGroupToName = {
|
|||||||
pcq: 'Luxury Passenger Cabin',
|
pcq: 'Luxury Passenger Cabin',
|
||||||
cc: 'Collector Limpet Controller',
|
cc: 'Collector Limpet Controller',
|
||||||
ss: 'Surface Scanner',
|
ss: 'Surface Scanner',
|
||||||
gsrp: 'Guardian Shield Reinforcement Packages',
|
|
||||||
gfsb: 'Guardian Frame Shift Drive Booster',
|
|
||||||
ghrp: 'Guardian Hull Reinforcement Package',
|
|
||||||
gmrp: 'Guardian Module Reinforcement Package',
|
|
||||||
mahr: 'Meta Alloy Hull Reinforcement Package',
|
|
||||||
|
|
||||||
// Hard Points
|
// Hard Points
|
||||||
bl: 'Beam Laser',
|
bl: 'Beam Laser',
|
||||||
@@ -86,14 +81,8 @@ export const ModuleGroupToName = {
|
|||||||
sfn: 'Shutdown Field Neutraliser',
|
sfn: 'Shutdown Field Neutraliser',
|
||||||
xs: 'Xeno Scanner',
|
xs: 'Xeno Scanner',
|
||||||
rcpl: 'Recon Limpet Controller',
|
rcpl: 'Recon Limpet Controller',
|
||||||
rsl: 'Research Limpet Controller',
|
|
||||||
dtl: 'Decontamination Limpet Controller',
|
|
||||||
gpc: 'Guardian Plasma Charger',
|
gpc: 'Guardian Plasma Charger',
|
||||||
ggc: 'Guardian Gauss Cannon',
|
ggc: 'Guardian Gauss Cannon',
|
||||||
tbsc: 'Shock Cannon',
|
|
||||||
gsc: 'Guardian Shard Cannon',
|
|
||||||
tbem: 'Enzyme Missile Rack',
|
|
||||||
tbrfl: 'Remote Release Flechette Launcher',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let GrpNameToCodeMap = {};
|
let GrpNameToCodeMap = {};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -7,10 +7,9 @@ import LZString from 'lz-string';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import isEqual from 'lodash/lang';
|
import isEqual from 'lodash/lang';
|
||||||
import { Ships, Modifications } from 'coriolis-data/dist';
|
import { Ships, Modifications } from 'coriolis-data/dist';
|
||||||
import { chain } from 'lodash';
|
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
|
|
||||||
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh', 'gfsb'];
|
const UNIQUE_MODULES = ['psg', 'sg', 'bsg', 'rf', 'fs', 'fh'];
|
||||||
|
|
||||||
// Constants for modifications struct
|
// Constants for modifications struct
|
||||||
const SLOT_ID_DONE = -1;
|
const SLOT_ID_DONE = -1;
|
||||||
@@ -152,7 +151,7 @@ export default class Ship {
|
|||||||
* @return {Number} Jump range in Light Years
|
* @return {Number} Jump range in Light Years
|
||||||
*/
|
*/
|
||||||
calcLadenRange(massDelta, fuel, fsd) {
|
calcLadenRange(massDelta, fuel, fsd) {
|
||||||
return Calc.jumpRange(this.ladenMass + (massDelta || 0), fsd || this.standard[2].m, fuel, this);
|
return Calc.jumpRange(this.ladenMass + (massDelta || 0), fsd || this.standard[2].m, fuel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,7 +164,7 @@ export default class Ship {
|
|||||||
calcUnladenRange(massDelta, fuel, fsd) {
|
calcUnladenRange(massDelta, fuel, fsd) {
|
||||||
fsd = fsd || this.standard[2].m;
|
fsd = fsd || this.standard[2].m;
|
||||||
let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
let fsdMaxFuelPerJump = fsd instanceof Module ? fsd.getMaxFuelPerJump() : fsd.maxfuel;
|
||||||
return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsdMaxFuelPerJump, fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel, this);
|
return Calc.jumpRange(this.unladenMass + (massDelta || 0) + Math.min(fsdMaxFuelPerJump, fuel || this.fuelCapacity), fsd || this.standard[2].m, fuel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,6 +239,7 @@ export default class Ship {
|
|||||||
}
|
}
|
||||||
sg = sgSlot.m;
|
sg = sgSlot.m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Not accurate if the ship has modified shield boosters
|
// TODO Not accurate if the ship has modified shield boosters
|
||||||
return Calc.shieldStrength(this.hullMass, this.baseShieldStrength, sg, 1 + (multiplierDelta || 0));
|
return Calc.shieldStrength(this.hullMass, this.baseShieldStrength, sg, 1 + (multiplierDelta || 0));
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,10 @@ export default class Ship {
|
|||||||
* @param {Object} m The module for which to clear the blueprint
|
* @param {Object} m The module for which to clear the blueprint
|
||||||
*/
|
*/
|
||||||
clearModuleSpecial(m) {
|
clearModuleSpecial(m) {
|
||||||
this.setModuleSpecial(m, null);
|
if (m.blueprint) {
|
||||||
|
m.blueprint.special = null;
|
||||||
|
}
|
||||||
|
this.recalculateDps().recalculateHps().recalculateEps();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -494,62 +497,68 @@ export default class Ship {
|
|||||||
* @param {Object} name The name of the modification to change
|
* @param {Object} name The name of the modification to change
|
||||||
* @param {Number} value The new value of the modification. The value of the modification is scaled to provide two decimal places of precision in an integer. For example 1.23% is stored as 123
|
* @param {Number} value The new value of the modification. The value of the modification is scaled to provide two decimal places of precision in an integer. For example 1.23% is stored as 123
|
||||||
* @param {bool} sentfromui True if this update was sent from the UI
|
* @param {bool} sentfromui True if this update was sent from the UI
|
||||||
* @param {bool} isAbsolute True if value is an absolute value and not a
|
|
||||||
* modification value
|
|
||||||
*/
|
*/
|
||||||
setModification(m, name, value, sentfromui, isAbsolute) {
|
setModification(m, name, value, sentfromui) {
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
// Value passed is invalid; reset it to 0
|
// Value passed is invalid; reset it to 0
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAbsolute) {
|
|
||||||
m.setPretty(name, value, sentfromui);
|
|
||||||
} else {
|
|
||||||
m.setModValue(name, value, sentfromui);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle special cases
|
// Handle special cases
|
||||||
if (name === 'pgen') {
|
if (name === 'pgen') {
|
||||||
// Power generation
|
// Power generation
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.updatePowerGenerated();
|
this.updatePowerGenerated();
|
||||||
} else if (name === 'power') {
|
} else if (name === 'power') {
|
||||||
// Power usage
|
// Power usage
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.updatePowerUsed();
|
this.updatePowerUsed();
|
||||||
} else if (name === 'mass') {
|
} else if (name === 'mass') {
|
||||||
// Mass
|
// Mass
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.recalculateMass();
|
this.recalculateMass();
|
||||||
this.updateMovement();
|
this.updateMovement();
|
||||||
this.updateJumpStats();
|
this.updateJumpStats();
|
||||||
} else if (name === 'maxfuel') {
|
} else if (name === 'maxfuel') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.updateJumpStats();
|
this.updateJumpStats();
|
||||||
} else if (name === 'optmass') {
|
} else if (name === 'optmass') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
// Could be for any of thrusters, FSD or shield
|
// Could be for any of thrusters, FSD or shield
|
||||||
this.updateMovement();
|
this.updateMovement();
|
||||||
this.updateJumpStats();
|
this.updateJumpStats();
|
||||||
this.recalculateShield();
|
this.recalculateShield();
|
||||||
} else if (name === 'optmul') {
|
} else if (name === 'optmul') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
// Could be for any of thrusters, FSD or shield
|
// Could be for any of thrusters, FSD or shield
|
||||||
this.updateMovement();
|
this.updateMovement();
|
||||||
this.updateJumpStats();
|
this.updateJumpStats();
|
||||||
this.recalculateShield();
|
this.recalculateShield();
|
||||||
} else if (name === 'shieldboost') {
|
} else if (name === 'shieldboost') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.recalculateShield();
|
this.recalculateShield();
|
||||||
} else if (name === 'hullboost' || name === 'hullreinforcement' || name === 'modulereinforcement') {
|
} else if (name === 'hullboost' || name === 'hullreinforcement' || name === 'modulereinforcement') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.recalculateArmour();
|
this.recalculateArmour();
|
||||||
} else if (name === 'shieldreinforcement') {
|
} else if (name === 'shieldreinforcement') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.recalculateShieldCells();
|
this.recalculateShieldCells();
|
||||||
} else if (name === 'burst' || name == 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
} else if (name === 'burst' || name == 'burstrof' || name === 'clip' || name === 'damage' || name === 'distdraw' || name === 'jitter' || name === 'piercing' || name === 'range' || name === 'reload' || name === 'rof' || name === 'thermload') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
this.recalculateDps();
|
this.recalculateDps();
|
||||||
this.recalculateHps();
|
this.recalculateHps();
|
||||||
this.recalculateEps();
|
this.recalculateEps();
|
||||||
} else if (name === 'explres' || name === 'kinres' || name === 'thermres') {
|
} else if (name === 'explres' || name === 'kinres' || name === 'thermres') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
// Could be for shields or armour
|
// Could be for shields or armour
|
||||||
this.recalculateArmour();
|
this.recalculateArmour();
|
||||||
this.recalculateShield();
|
this.recalculateShield();
|
||||||
} else if (name === 'engcap') {
|
} else if (name === 'engcap') {
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
// Might have resulted in a change in boostability
|
// Might have resulted in a change in boostability
|
||||||
this.updateMovement();
|
this.updateMovement();
|
||||||
|
} else {
|
||||||
|
// Generic
|
||||||
|
m.setModValue(name, value, sentfromui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -932,14 +941,9 @@ export default class Ship {
|
|||||||
let epsChanged = n && n.getEps() || old && old.getEps();
|
let epsChanged = n && n.getEps() || old && old.getEps();
|
||||||
let hpsChanged = n && n.getHps() || old && old.getHps();
|
let hpsChanged = n && n.getHps() || old && old.getHps();
|
||||||
|
|
||||||
let armourChange = (slot === this.bulkheads) ||
|
let armourChange = (slot === this.bulkheads) || (n && n.grp === 'hr') || (old && old.grp === 'hr') || (n && n.grp === 'mrp') || (old && old.grp === 'mrp');
|
||||||
(n && n.grp === 'hr') || (old && old.grp === 'hr') ||
|
|
||||||
(n && n.grp === 'ghrp') || (old && old.grp === 'ghrp') ||
|
|
||||||
(n && n.grp == 'mahr') || (old && old.grp == 'mahr') ||
|
|
||||||
(n && n.grp === 'mrp') || (old && old.grp === 'mrp') ||
|
|
||||||
(n && n.grp === 'gmrp') || (old && old.grp == 'gmrp');
|
|
||||||
|
|
||||||
let shieldChange = (n && n.grp === 'bsg') || (old && old.grp === 'bsg') || (n && n.grp === 'psg') || (old && old.grp === 'psg') || (n && n.grp === 'sg') || (old && old.grp === 'sg') || (n && n.grp === 'sb') || (old && old.grp === 'sb') || (old && old.grp === 'gsrp') || (n && n.grp === 'gsrp');
|
let shieldChange = (n && n.grp === 'bsg') || (old && old.grp === 'bsg') || (n && n.grp === 'psg') || (old && old.grp === 'psg') || (n && n.grp === 'sg') || (old && old.grp === 'sg') || (n && n.grp === 'sb') || (old && old.grp === 'sb');
|
||||||
|
|
||||||
let shieldCellsChange = (n && n.grp === 'scb') || (old && old.grp === 'scb');
|
let shieldCellsChange = (n && n.grp === 'scb') || (old && old.grp === 'scb');
|
||||||
|
|
||||||
@@ -996,6 +1000,25 @@ export default class Ship {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate diminishing returns value, where values below a given limit are returned
|
||||||
|
* as-is, and values between the lower and upper limit of the diminishing returns are
|
||||||
|
* given at half value.
|
||||||
|
* Commonly used for resistances.
|
||||||
|
* @param {Number} val The value
|
||||||
|
* @param {Number} drll The lower limit for diminishing returns
|
||||||
|
* @param {Number} drul The upper limit for diminishing returns
|
||||||
|
* @return {this} The ship instance (for chaining operations)
|
||||||
|
*/
|
||||||
|
diminishingReturns(val, drll, drul) {
|
||||||
|
if (val < drll) {
|
||||||
|
val = drll;
|
||||||
|
} else if (val < drul) {
|
||||||
|
val = drul - (drul - val) / 2;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate damage per second and related items for weapons
|
* Calculate damage per second and related items for weapons
|
||||||
* @return {this} The ship instance (for chaining operations)
|
* @return {this} The ship instance (for chaining operations)
|
||||||
@@ -1182,35 +1205,38 @@ export default class Ship {
|
|||||||
|
|
||||||
unladenMass += this.bulkheads.m.getMass();
|
unladenMass += this.bulkheads.m.getMass();
|
||||||
|
|
||||||
let slots = this.standard.concat(this.internal, this.hardpoints);
|
for (let slotNum in this.standard) {
|
||||||
// TODO: create class for slot and also add slot.get
|
const slot = this.standard[slotNum];
|
||||||
// handle unladen mass
|
if (slot.m) {
|
||||||
unladenMass += chain(slots)
|
unladenMass += slot.m.getMass();
|
||||||
.map(slot => slot.m ? slot.m.get('mass') : null)
|
if (slot.m.grp === 'ft') {
|
||||||
.filter()
|
fuelCapacity += slot.m.fuel;
|
||||||
.reduce((sum, mass) => sum + mass)
|
}
|
||||||
.value();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handle fuel capacity
|
for (let slotNum in this.internal) {
|
||||||
fuelCapacity += chain(slots)
|
const slot = this.internal[slotNum];
|
||||||
.map(slot => slot.m ? slot.m.get('fuel') : null)
|
if (slot.m) {
|
||||||
.filter()
|
unladenMass += slot.m.getMass();
|
||||||
.reduce((sum, fuel) => sum + fuel)
|
if (slot.m.grp === 'ft') {
|
||||||
.value();
|
fuelCapacity += slot.m.fuel;
|
||||||
|
} else if (slot.m.grp === 'cr') {
|
||||||
|
cargoCapacity += slot.m.cargo;
|
||||||
|
} else if (slot.m.grp.slice(0,2) === 'pc') {
|
||||||
|
if (slot.m.passengers) {
|
||||||
|
passengerCapacity += slot.m.passengers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handle cargo capacity
|
for (let slotNum in this.hardpoints) {
|
||||||
cargoCapacity += chain(slots)
|
const slot = this.hardpoints[slotNum];
|
||||||
.map(slot => slot.m ? slot.m.get('cargo') : null)
|
if (slot.m) {
|
||||||
.filter()
|
unladenMass += slot.m.getMass();
|
||||||
.reduce((sum, cargo) => sum + cargo)
|
}
|
||||||
.value();
|
}
|
||||||
|
|
||||||
// handle passenger capacity
|
|
||||||
passengerCapacity += chain(slots)
|
|
||||||
.map(slot => slot.m ? slot.m.get('passengers') : null)
|
|
||||||
.filter()
|
|
||||||
.reduce((sum, passengers) => sum + passengers)
|
|
||||||
.value();
|
|
||||||
|
|
||||||
// Update global stats
|
// Update global stats
|
||||||
this.unladenMass = unladenMass;
|
this.unladenMass = unladenMass;
|
||||||
@@ -1251,7 +1277,7 @@ export default class Ship {
|
|||||||
// Obtain shield metrics with 0 pips to sys (parts affected by SYS aren't used here)
|
// Obtain shield metrics with 0 pips to sys (parts affected by SYS aren't used here)
|
||||||
const metrics = Calc.shieldMetrics(this, 0);
|
const metrics = Calc.shieldMetrics(this, 0);
|
||||||
|
|
||||||
this.shield = metrics.generator ? metrics.generator + metrics.boosters + metrics.addition : 0;
|
this.shield = metrics.generator ? metrics.generator + metrics.boosters : 0;
|
||||||
this.shieldExplRes = this.shield > 0 ? 1 - metrics.explosive.total : null;
|
this.shieldExplRes = this.shield > 0 ? 1 - metrics.explosive.total : null;
|
||||||
this.shieldKinRes = this.shield > 0 ? 1 - metrics.kinetic.total : null;
|
this.shieldKinRes = this.shield > 0 ? 1 - metrics.kinetic.total : null;
|
||||||
this.shieldThermRes = this.shield > 0 ? 1 - metrics.thermal.total : null;
|
this.shieldThermRes = this.shield > 0 ? 1 - metrics.thermal.total : null;
|
||||||
@@ -1284,15 +1310,45 @@ export default class Ship {
|
|||||||
*/
|
*/
|
||||||
recalculateArmour() {
|
recalculateArmour() {
|
||||||
// Armour from bulkheads
|
// Armour from bulkheads
|
||||||
let metrics = Calc.armourMetrics(this);
|
let bulkhead = this.bulkheads.m;
|
||||||
|
let armour = this.baseArmour + (this.baseArmour * bulkhead.getHullBoost());
|
||||||
|
let modulearmour = 0;
|
||||||
|
let moduleprotection = 1;
|
||||||
|
let hullExplRes = 1 - bulkhead.getExplosiveResistance();
|
||||||
|
const hullExplResDRStart = hullExplRes * 0.7;
|
||||||
|
const hullExplResDREnd = hullExplRes * 0;
|
||||||
|
let hullKinRes = 1 - bulkhead.getKineticResistance();
|
||||||
|
const hullKinResDRStart = hullKinRes * 0.7;
|
||||||
|
const hullKinResDREnd = hullKinRes * 0;
|
||||||
|
let hullThermRes = 1 - bulkhead.getThermalResistance();
|
||||||
|
const hullThermResDRStart = hullThermRes * 0.7;
|
||||||
|
const hullThermResDREnd = hullThermRes * 0;
|
||||||
|
|
||||||
|
// Armour from HRPs and module armour from MRPs
|
||||||
|
for (let slot of this.internal) {
|
||||||
|
if (slot.m && slot.m.grp == 'hr') {
|
||||||
|
armour += slot.m.getHullReinforcement();
|
||||||
|
// Hull boost for HRPs is applied against the ship's base armour
|
||||||
|
armour += this.baseArmour * slot.m.getModValue('hullboost') / 10000;
|
||||||
|
|
||||||
|
hullExplRes *= (1 - slot.m.getExplosiveResistance());
|
||||||
|
hullKinRes *= (1 - slot.m.getKineticResistance());
|
||||||
|
hullThermRes *= (1 - slot.m.getThermalResistance());
|
||||||
|
}
|
||||||
|
if (slot.m && slot.m.grp == 'mrp') {
|
||||||
|
modulearmour += slot.m.getIntegrity();
|
||||||
|
moduleprotection = moduleprotection * (1 - slot.m.getProtection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moduleprotection = 1 - moduleprotection;
|
||||||
|
|
||||||
|
this.armour = armour;
|
||||||
|
this.modulearmour = modulearmour;
|
||||||
|
this.moduleprotection = moduleprotection;
|
||||||
|
this.hullExplRes = 1 - this.diminishingReturns(hullExplRes, hullExplResDREnd, hullExplResDRStart);
|
||||||
|
this.hullKinRes = 1 - this.diminishingReturns(hullKinRes, hullKinResDREnd, hullKinResDRStart);
|
||||||
|
this.hullThermRes = 1 - this.diminishingReturns(hullThermRes, hullThermResDREnd, hullThermResDRStart);
|
||||||
|
|
||||||
this.armour = metrics.total ? metrics.total : 0;
|
|
||||||
this.modulearmour = metrics.modulearmour;
|
|
||||||
this.moduleprotection = metrics.moduleprotection;
|
|
||||||
this.hullExplRes = 1 - metrics.explosive.total;
|
|
||||||
this.hullKinRes = 1 - metrics.kinetic.total;
|
|
||||||
this.hullThermRes = 1 - metrics.thermal.total;
|
|
||||||
this.hullCausRes = 1 - metrics.caustic.total;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,10 +1360,10 @@ export default class Ship {
|
|||||||
let fsd = this.standard[2].m; // Frame Shift Drive;
|
let fsd = this.standard[2].m; // Frame Shift Drive;
|
||||||
let { unladenMass, fuelCapacity } = this;
|
let { unladenMass, fuelCapacity } = this;
|
||||||
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
|
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
|
||||||
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, this); // Full Tank
|
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd); // Full Tank
|
||||||
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
|
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
|
||||||
this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity, this);
|
this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity);
|
||||||
this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity, this);
|
this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity);
|
||||||
this.maxJumpCount = Math.ceil(fuelCapacity / fsd.getMaxFuelPerJump());
|
this.maxJumpCount = Math.ceil(fuelCapacity / fsd.getMaxFuelPerJump());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
export const SI_PREFIXES = {
|
|
||||||
'Y': 1e+24, // Yotta
|
|
||||||
'Z': 1e+21, // Zetta
|
|
||||||
'E': 1e+18, // Peta
|
|
||||||
'P': 1e+15, // Peta
|
|
||||||
'T': 1e+12, // Tera
|
|
||||||
'G': 1e+9, // Giga
|
|
||||||
'M': 1e+6, // Mega
|
|
||||||
'k': 1e+3, // Kilo
|
|
||||||
'h': 1e+2, // Hekto
|
|
||||||
'da': 1e+1, // Deka
|
|
||||||
'': 1,
|
|
||||||
'd': 1e-1, // Dezi
|
|
||||||
'c': 1e-2, // Zenti
|
|
||||||
'm': 1e-3, // Milli
|
|
||||||
'μ': 1e-6, // mikro not supported due to charset
|
|
||||||
'n': 10e-9, // Nano
|
|
||||||
'p': 1e-12, // Nano
|
|
||||||
'f': 1e-15, // Femto
|
|
||||||
'a': 1e-18, // Atto
|
|
||||||
'z': 1e-21, // Zepto
|
|
||||||
'y': 1e-24 // Yokto
|
|
||||||
};
|
|
||||||
|
|
||||||
export const STATS_FORMATTING = {
|
|
||||||
'ammo': { 'format': 'int', },
|
|
||||||
'boot': { 'format': 'int', 'unit': 'secs' },
|
|
||||||
'brokenregen': { 'format': 'round1', 'unit': 'ps' },
|
|
||||||
'burst': { 'format': 'int' },
|
|
||||||
'burstrof': { 'format': 'round1', 'unit': 'ps' },
|
|
||||||
'causres': { 'format': 'pct' },
|
|
||||||
'clip': { 'format': 'int' },
|
|
||||||
'damage': { 'format': 'round' },
|
|
||||||
'dps': { 'format': 'round', 'units': 'ps', 'synthetic': 'getDps' },
|
|
||||||
'dpe': { 'format': 'round', 'units': 'ps', 'synthetic': 'getDpe' },
|
|
||||||
'distdraw': { 'format': 'round', 'unit': 'MW' },
|
|
||||||
'duration': { 'format': 'round1', 'unit': 's' },
|
|
||||||
'eff': { 'format': 'round2' },
|
|
||||||
'engcap': { 'format': 'round1', 'unit': 'MJ' },
|
|
||||||
'engrate': { 'format': 'round1', 'unit': 'MW' },
|
|
||||||
'eps': { 'format': 'round', 'units': 'ps', 'synthetic': 'getEps' },
|
|
||||||
'explres': { 'format': 'pct' },
|
|
||||||
'facinglimit': { 'format': 'round1', 'unit': 'ang' },
|
|
||||||
'falloff': { 'format': 'round', 'unit': 'km', 'storedUnit': 'm' },
|
|
||||||
'fallofffromrange': { 'format': 'round', 'unit': 'km', 'storedUnit': 'm', 'synthetic': 'getFalloff' },
|
|
||||||
'hps': { 'format': 'round', 'units': 'ps', 'synthetic': 'getHps' },
|
|
||||||
'hullboost': { 'format': 'pct1', 'change': 'additive' },
|
|
||||||
'hullreinforcement': { 'format': 'int' },
|
|
||||||
'integrity': { 'format': 'round1' },
|
|
||||||
'jitter': { 'format': 'round', 'unit': 'ang' },
|
|
||||||
'kinres': { 'format': 'pct' },
|
|
||||||
'mass': { 'format': 'round1', 'unit': 'T' },
|
|
||||||
'maxfuel': { 'format': 'round1', 'unit': 'T' },
|
|
||||||
'optmass': { 'format': 'int', 'unit': 'T' },
|
|
||||||
'optmul': { 'format': 'pct', 'change': 'additive' },
|
|
||||||
'pgen': { 'format': 'round1', 'unit': 'MW' },
|
|
||||||
'piercing': { 'format': 'int' },
|
|
||||||
'power': { 'format': 'round', 'unit': 'MW' },
|
|
||||||
'protection': { 'format': 'pct' },
|
|
||||||
'range': { 'format': 'f2', 'unit': 'km', 'storedUnit': 'm' },
|
|
||||||
'ranget': { 'format': 'f1', 'unit': 's' },
|
|
||||||
'regen': { 'format': 'round1', 'unit': 'ps' },
|
|
||||||
'reload': { 'format': 'int', 'unit': 's' },
|
|
||||||
'rof': { 'format': 'round1', 'unit': 'ps' },
|
|
||||||
'angle': { 'format': 'round1', 'unit': 'ang' },
|
|
||||||
'scanrate': { 'format': 'int' },
|
|
||||||
'scantime': { 'format': 'round1', 'unit': 's' },
|
|
||||||
'sdps': { 'format': 'round1', 'units': 'ps', 'synthetic': 'getSDps' },
|
|
||||||
'shield': { 'format': 'int', 'unit': 'MJ' },
|
|
||||||
'shieldaddition': { 'format': 'round1', 'unit': 'MJ' },
|
|
||||||
'shieldboost': { 'format': 'pct1', 'change': 'additive' },
|
|
||||||
'shieldreinforcement': { 'format': 'round1', 'unit': 'MJ' },
|
|
||||||
'shotspeed': { 'format': 'int', 'unit': 'm/s' },
|
|
||||||
'spinup': { 'format': 'round1', 'unit': 's' },
|
|
||||||
'syscap': { 'format': 'round1', 'unit': 'MJ' },
|
|
||||||
'sysrate': { 'format': 'round1', 'unit': 'MW' },
|
|
||||||
'thermload': { 'format': 'round1' },
|
|
||||||
'thermres': { 'format': 'pct' },
|
|
||||||
'wepcap': { 'format': 'round1', 'unit': 'MJ' },
|
|
||||||
'weprate': { 'format': 'round1', 'unit': 'MW' },
|
|
||||||
'jumpboost': { 'format': 'round1', 'unit': 'LY' }
|
|
||||||
};
|
|
||||||
@@ -5,7 +5,6 @@ const LS_KEY_BUILDS = 'builds';
|
|||||||
const LS_KEY_COMPARISONS = 'comparisons';
|
const LS_KEY_COMPARISONS = 'comparisons';
|
||||||
const LS_KEY_LANG = 'NG_TRANSLATE_LANG_KEY';
|
const LS_KEY_LANG = 'NG_TRANSLATE_LANG_KEY';
|
||||||
const LS_KEY_COST_TAB = 'costTab';
|
const LS_KEY_COST_TAB = 'costTab';
|
||||||
const LS_KEY_CMDR_NAME = 'cmdrName';
|
|
||||||
const LS_KEY_OUTFITTING_TAB = 'outfittingTab';
|
const LS_KEY_OUTFITTING_TAB = 'outfittingTab';
|
||||||
const LS_KEY_INSURANCE = 'insurance';
|
const LS_KEY_INSURANCE = 'insurance';
|
||||||
const LS_KEY_SHIP_DISCOUNT = 'shipDiscount';
|
const LS_KEY_SHIP_DISCOUNT = 'shipDiscount';
|
||||||
@@ -15,7 +14,6 @@ const LS_KEY_SIZE_RATIO = 'sizeRatio';
|
|||||||
const LS_KEY_TOOLTIPS = 'tooltips';
|
const LS_KEY_TOOLTIPS = 'tooltips';
|
||||||
const LS_KEY_MODULE_RESISTANCES = 'moduleResistances';
|
const LS_KEY_MODULE_RESISTANCES = 'moduleResistances';
|
||||||
const LS_KEY_ROLLS = 'matsPerGrade';
|
const LS_KEY_ROLLS = 'matsPerGrade';
|
||||||
const LS_KEY_ORBIS = 'orbis';
|
|
||||||
|
|
||||||
let LS;
|
let LS;
|
||||||
|
|
||||||
@@ -88,7 +86,6 @@ export class Persist extends EventEmitter {
|
|||||||
|
|
||||||
let moduleResistances = _get(LS_KEY_MODULE_RESISTANCES);
|
let moduleResistances = _get(LS_KEY_MODULE_RESISTANCES);
|
||||||
let matsPerGrade = _get(LS_KEY_ROLLS);
|
let matsPerGrade = _get(LS_KEY_ROLLS);
|
||||||
let cmdrName = _get(LS_KEY_CMDR_NAME);
|
|
||||||
let tips = _get(LS_KEY_TOOLTIPS);
|
let tips = _get(LS_KEY_TOOLTIPS);
|
||||||
let insurance = _getString(LS_KEY_INSURANCE);
|
let insurance = _getString(LS_KEY_INSURANCE);
|
||||||
let shipDiscount = _get(LS_KEY_SHIP_DISCOUNT);
|
let shipDiscount = _get(LS_KEY_SHIP_DISCOUNT);
|
||||||
@@ -96,7 +93,6 @@ export class Persist extends EventEmitter {
|
|||||||
let buildJson = _get(LS_KEY_BUILDS);
|
let buildJson = _get(LS_KEY_BUILDS);
|
||||||
let comparisonJson = _get(LS_KEY_COMPARISONS);
|
let comparisonJson = _get(LS_KEY_COMPARISONS);
|
||||||
|
|
||||||
this.orbisCreds = _get(LS_KEY_ORBIS) || { email: '', password: '' };
|
|
||||||
this.onStorageChange = this.onStorageChange.bind(this);
|
this.onStorageChange = this.onStorageChange.bind(this);
|
||||||
this.langCode = _getString(LS_KEY_LANG) || 'en';
|
this.langCode = _getString(LS_KEY_LANG) || 'en';
|
||||||
this.insurance = insurance && Insurance[insurance.toLowerCase()] !== undefined ? insurance : 'standard';
|
this.insurance = insurance && Insurance[insurance.toLowerCase()] !== undefined ? insurance : 'standard';
|
||||||
@@ -115,7 +111,6 @@ export class Persist extends EventEmitter {
|
|||||||
4: 4,
|
4: 4,
|
||||||
5: 10
|
5: 10
|
||||||
};
|
};
|
||||||
this.cmdrName = cmdrName || { selected: '', cmdrs: [] };
|
|
||||||
this.tooltipsEnabled = tips === null ? true : tips;
|
this.tooltipsEnabled = tips === null ? true : tips;
|
||||||
this.moduleResistancesEnabled = moduleResistances === null ? true : moduleResistances;
|
this.moduleResistancesEnabled = moduleResistances === null ? true : moduleResistances;
|
||||||
|
|
||||||
@@ -170,10 +165,6 @@ export class Persist extends EventEmitter {
|
|||||||
this.matsPerGrade = JSON.parse(newValue);
|
this.matsPerGrade = JSON.parse(newValue);
|
||||||
this.emit('matsPerGrade', this.matsPerGrade);
|
this.emit('matsPerGrade', this.matsPerGrade);
|
||||||
break;
|
break;
|
||||||
case LS_KEY_ORBIS:
|
|
||||||
this.orbisCreds = JSON.parse(newValue);
|
|
||||||
this.emit('orbis', this.orbisCreds);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// On JSON.Parse Error - don't sync or do anything
|
// On JSON.Parse Error - don't sync or do anything
|
||||||
@@ -199,24 +190,6 @@ export class Persist extends EventEmitter {
|
|||||||
this.emit('language', langCode);
|
this.emit('language', langCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current orbis.zone credentials
|
|
||||||
* @return {String} language code
|
|
||||||
*/
|
|
||||||
getOrbisCreds() {
|
|
||||||
return this.orbisCreds;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update and save the orbis.zone credentials
|
|
||||||
* @param {Object} creds object with username and password properties.
|
|
||||||
*/
|
|
||||||
setOrbisCreds(creds) {
|
|
||||||
this.langCode = creds;
|
|
||||||
_put(LS_KEY_ORBIS, creds);
|
|
||||||
this.emit('orbis', creds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show tooltips setting
|
* Show tooltips setting
|
||||||
* @param {boolean} show Optional - update setting
|
* @param {boolean} show Optional - update setting
|
||||||
@@ -514,14 +487,6 @@ export class Persist extends EventEmitter {
|
|||||||
return this.matsPerGrade;
|
return this.matsPerGrade;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the saved Mats per grade
|
|
||||||
* @return {Object} # of rolls per grade
|
|
||||||
*/
|
|
||||||
getCmdr() {
|
|
||||||
return this.cmdrName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist selected cost tab
|
* Persist selected cost tab
|
||||||
* @param {number} tabName Cost tab name
|
* @param {number} tabName Cost tab name
|
||||||
@@ -531,16 +496,6 @@ export class Persist extends EventEmitter {
|
|||||||
_put(LS_KEY_COST_TAB, tabName);
|
_put(LS_KEY_COST_TAB, tabName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Persist cmdr name
|
|
||||||
* @param {Object} cmdrName Commander name for EDEngineer
|
|
||||||
*/
|
|
||||||
setCmdr(cmdrName) {
|
|
||||||
this.cmdrName = cmdrName;
|
|
||||||
_put(LS_KEY_CMDR_NAME, cmdrName);
|
|
||||||
this.emit('cmdr');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the saved discount
|
* Get the saved discount
|
||||||
* @return {number} val Discount value/amount
|
* @return {number} val Discount value/amount
|
||||||
|
|||||||
@@ -294,6 +294,21 @@ export function getBlueprint(name, module) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const blueprint = JSON.parse(JSON.stringify(found));
|
const blueprint = JSON.parse(JSON.stringify(found));
|
||||||
|
if (module) {
|
||||||
|
if (module.grp === 'sb') {
|
||||||
|
// Shield boosters are treated internally as straight modifiers, so rather than (for example)
|
||||||
|
// being a 4% boost they are a 104% multiplier. We need to fix the values here so that they look
|
||||||
|
// accurate as per the information in Elite
|
||||||
|
for (const grade in blueprint.grades) {
|
||||||
|
for (const feature in blueprint.grades[grade].features) {
|
||||||
|
if (feature === 'shieldboost') {
|
||||||
|
blueprint.grades[grade].features[feature][0] = ((1 + blueprint.grades[grade].features[feature][0]) * (1 + module.shieldboost) - 1) / module.shieldboost - 1;
|
||||||
|
blueprint.grades[grade].features[feature][1] = ((1 + blueprint.grades[grade].features[feature][1]) * (1 + module.shieldboost) - 1) / module.shieldboost - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return blueprint;
|
return blueprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,9 +387,7 @@ export function getPercent(m) {
|
|||||||
|
|
||||||
let value = _getValue(m, featureName);
|
let value = _getValue(m, featureName);
|
||||||
let mult;
|
let mult;
|
||||||
if (featureName == 'shieldboost') {
|
if (Modifications.modifications[featureName].higherbetter) {
|
||||||
mult = ((1 + value) * (1 + m.shieldboost)) - 1 - m.shieldboost;
|
|
||||||
} else if (Modifications.modifications[featureName].higherbetter) {
|
|
||||||
// Higher is better, but is this making it better or worse?
|
// Higher is better, but is this making it better or worse?
|
||||||
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
if (features[featureName][0] < 0 || (features[featureName][0] === 0 && features[featureName][1] < 0)) {
|
||||||
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
|
mult = Math.round((value - features[featureName][1]) / (features[featureName][0] - features[featureName][1]) * 100);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { getBlueprint } from '../utils/BlueprintFunctions';
|
|||||||
import * as ModuleUtils from '../shipyard/ModuleUtils';
|
import * as ModuleUtils from '../shipyard/ModuleUtils';
|
||||||
|
|
||||||
// mapping from fd's ship model names to coriolis'
|
// mapping from fd's ship model names to coriolis'
|
||||||
export const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
||||||
'Adder': 'adder',
|
'Adder': 'adder',
|
||||||
'Anaconda': 'anaconda',
|
'Anaconda': 'anaconda',
|
||||||
'Asp': 'asp',
|
'Asp': 'asp',
|
||||||
@@ -29,7 +29,6 @@ export const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
|||||||
'FerDeLance': 'fer_de_lance',
|
'FerDeLance': 'fer_de_lance',
|
||||||
'Hauler': 'hauler',
|
'Hauler': 'hauler',
|
||||||
'Independant_Trader': 'keelback',
|
'Independant_Trader': 'keelback',
|
||||||
'Krait_MkII': 'krait_mkii',
|
|
||||||
'Orca': 'orca',
|
'Orca': 'orca',
|
||||||
'Python': 'python',
|
'Python': 'python',
|
||||||
'SideWinder': 'sidewinder',
|
'SideWinder': 'sidewinder',
|
||||||
@@ -38,8 +37,6 @@ export const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
|
|||||||
'Type9': 'type_9_heavy',
|
'Type9': 'type_9_heavy',
|
||||||
'Type9_Military': 'type_10_defender',
|
'Type9_Military': 'type_10_defender',
|
||||||
'TypeX': 'alliance_chieftain',
|
'TypeX': 'alliance_chieftain',
|
||||||
'TypeX_2': 'alliance_crusader',
|
|
||||||
'TypeX_3': 'alliance_challenger',
|
|
||||||
'Viper': 'viper',
|
'Viper': 'viper',
|
||||||
'Viper_MkIV': 'viper_mk_iv',
|
'Viper_MkIV': 'viper_mk_iv',
|
||||||
'Vulture': 'vulture'
|
'Vulture': 'vulture'
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
|
let ship = new Ship(shipModel, shipTemplate.properties, shipTemplate.slots);
|
||||||
ship.buildWith(null);
|
ship.buildWith(null);
|
||||||
// Initial Ship building, don't do engineering yet.
|
// Initial Ship building, don't do engineering yet.
|
||||||
let modsToAdd = [];
|
let opts = [];
|
||||||
|
|
||||||
for (const module of json.Modules) {
|
for (const module of json.Modules) {
|
||||||
switch (module.Slot.toLowerCase()) {
|
switch (module.Slot.toLowerCase()) {
|
||||||
@@ -176,7 +176,7 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
ship.use(ship.hardpoints[hardpointArrayNum], hardpoint, true);
|
||||||
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
|
ship.hardpoints[hardpointArrayNum].enabled = hardpointSlot.On;
|
||||||
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
|
ship.hardpoints[hardpointArrayNum].priority = hardpointSlot.Priority;
|
||||||
modsToAdd.push({ coriolisMod: hardpoint, json: hardpointSlot });
|
opts.push({ coriolisMod: hardpoint, json: hardpointSlot });
|
||||||
}
|
}
|
||||||
hardpointArrayNum++;
|
hardpointArrayNum++;
|
||||||
}
|
}
|
||||||
@@ -185,9 +185,6 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
let internalSlotNum = 1;
|
let internalSlotNum = 1;
|
||||||
let militarySlotNum = 1;
|
let militarySlotNum = 1;
|
||||||
for (let i in shipTemplate.slots.internal) {
|
for (let i in shipTemplate.slots.internal) {
|
||||||
if (!shipTemplate.slots.internal.hasOwnProperty(i)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false;
|
const isMilitary = isNaN(shipTemplate.slots.internal[i]) ? shipTemplate.slots.internal[i].name = 'military' : false;
|
||||||
|
|
||||||
// The internal slot might be a standard or a military slot. Military slots have a different naming system
|
// The internal slot might be a standard or a military slot. Military slots have a different naming system
|
||||||
@@ -201,7 +198,7 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
while (internalSlot === null && internalSlotNum < 99) {
|
while (internalSlot === null && internalSlotNum < 99) {
|
||||||
// Slot sizes have no relationship to the actual size, either, so check all possibilities
|
// Slot sizes have no relationship to the actual size, either, so check all possibilities
|
||||||
for (let slotsize = 0; slotsize < 9; slotsize++) {
|
for (let slotsize = 0; slotsize < 9; slotsize++) {
|
||||||
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '0') + internalSlotNum + '_Size' + slotsize;
|
const internalName = 'Slot' + (internalSlotNum <= 9 ? '0' : '') + internalSlotNum + '_Size' + slotsize;
|
||||||
if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) {
|
if (json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase())) {
|
||||||
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
|
internalSlot = json.Modules.find(elem => elem.Slot.toLowerCase() === internalName.toLowerCase());
|
||||||
break;
|
break;
|
||||||
@@ -213,23 +210,23 @@ export function shipFromLoadoutJSON(json) {
|
|||||||
|
|
||||||
if (!internalSlot) {
|
if (!internalSlot) {
|
||||||
// This can happen with old imports that don't contain new slots
|
// This can happen with old imports that don't contain new slots
|
||||||
|
} else if (!internalSlot) {
|
||||||
|
// No module
|
||||||
} else {
|
} else {
|
||||||
const internalJson = internalSlot;
|
const internalJson = internalSlot;
|
||||||
const internal = _moduleFromFdName(internalJson.Item);
|
const internal = _moduleFromFdName(internalJson.Item);
|
||||||
ship.use(ship.internal[i], internal, true);
|
ship.use(ship.internal[i], internal, true);
|
||||||
ship.internal[i].enabled = internalJson.On === true;
|
ship.internal[i].enabled = internalJson.On === true;
|
||||||
ship.internal[i].priority = internalJson.Priority;
|
ship.internal[i].priority = internalJson.Priority;
|
||||||
modsToAdd.push({ coriolisMod: internal, json: internalSlot });
|
opts.push({ coriolisMod: internal, json: internalSlot });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const i of modsToAdd) {
|
for (const i of opts) {
|
||||||
if (i.json.Engineering) {
|
if (i.json.Engineering) _addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect);
|
||||||
_addModifications(i.coriolisMod, i.json.Engineering.Modifiers, i.json.Engineering.BlueprintName, i.json.Engineering.Level, i.json.Engineering.ExperimentalEffect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// We don't have any information on it so guess it's priority 5 and disabled
|
// We don't have any information on it so guess it's priority 5 and disabled
|
||||||
if (!ship.cargoHatch) {
|
if (!ship.cargoHatch) {
|
||||||
@@ -255,16 +252,6 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
|
|||||||
if (specialModifications) {
|
if (specialModifications) {
|
||||||
special = Modifications.specials[specialModifications];
|
special = Modifications.specials[specialModifications];
|
||||||
}
|
}
|
||||||
// Add the blueprint definition, grade and special
|
|
||||||
if (blueprint) {
|
|
||||||
module.blueprint = getBlueprint(blueprint, module);
|
|
||||||
if (grade) {
|
|
||||||
module.blueprint.grade = Number(grade);
|
|
||||||
}
|
|
||||||
if (special) {
|
|
||||||
module.blueprint.special = special;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const i in modifiers) {
|
for (const i in modifiers) {
|
||||||
// Some special modifications
|
// Some special modifications
|
||||||
// Look up the modifiers to find what we need to do
|
// Look up the modifiers to find what we need to do
|
||||||
@@ -281,17 +268,24 @@ function _addModifications(module, modifiers, blueprint, grade, specialModificat
|
|||||||
if (modifiers[i].Label.search('Resistance') >= 0) {
|
if (modifiers[i].Label.search('Resistance') >= 0) {
|
||||||
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
value = (modifiers[i].Value * 100) - (modifiers[i].OriginalValue * 100);
|
||||||
}
|
}
|
||||||
if (modifiers[i].Label.search('ShieldMultiplier') >= 0 || modifiers[i].Label.search('DefenceModifierHealthMultiplier') >= 0) {
|
|
||||||
value = ((100 + modifiers[i].Value) / (100 + modifiers[i].OriginalValue) * 100 - 100) * 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Carry out the required changes
|
// Carry out the required changes
|
||||||
for (const action in modifierActions) {
|
for (const action in modifierActions) {
|
||||||
if (isNaN(modifierActions[action])) {
|
if (isNaN(modifierActions[action])) {
|
||||||
module.setModValue(action, modifierActions[action]);
|
module.setModValue(action, modifierActions[action]);
|
||||||
} else {
|
} else {
|
||||||
module.setModValue(action, value, true);
|
module.setModValue(action, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the blueprint definition, grade and special
|
||||||
|
if (blueprint) {
|
||||||
|
module.blueprint = getBlueprint(blueprint, module);
|
||||||
|
if (grade) {
|
||||||
|
module.blueprint.grade = Number(grade);
|
||||||
|
}
|
||||||
|
if (special) {
|
||||||
|
module.blueprint.special = special;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
import request from 'superagent';
|
import request from 'superagent';
|
||||||
|
|
||||||
let agent;
|
|
||||||
try {
|
|
||||||
agent = request.agent(); // apparently this crashes somehow
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
if (!agent) {
|
|
||||||
agent = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shorten a URL
|
* Shorten a URL
|
||||||
* @param {string} url The URL to shorten
|
* @param {string} url The URL to shorten
|
||||||
* @param {function} success Success callback
|
* @param {function} success Success callback
|
||||||
* @param {function} error Failure/Error callback
|
* @param {function} error Failure/Error callback
|
||||||
*/
|
*/
|
||||||
export default function shorternUrl(url, success, error) {
|
export default function shorternUrl(url, success, error) {
|
||||||
orbisShorten(url, success, error);
|
shortenUrlOrbis(url, success, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHORTEN_API_GOOGLE = 'https://www.googleapis.com/urlshortener/v1/url?key=';
|
const SHORTEN_API_GOOGLE = 'https://www.googleapis.com/urlshortener/v1/url?key=';
|
||||||
@@ -74,67 +65,31 @@ function shortenUrlEddp(url, success, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHORTEN_API_ORBIS = 'https://s.orbis.zone/api.php';
|
const SHORTEN_API_ORBIS = 'https://s.orbis.zone/a';
|
||||||
/**
|
/**
|
||||||
* Shorten a URL using Orbis's URL shortener API
|
* Shorten a URL using Orbis's URL shortener API
|
||||||
* @param {string} url The URL to shorten
|
* @param {string} url The URL to shorten
|
||||||
* @param {function} success Success callback
|
* @param {function} success Success callback
|
||||||
* @param {function} error Failure/Error callback
|
* @param {function} error Failure/Error callback
|
||||||
*/
|
*/
|
||||||
function orbisShorten(url, success, error) {
|
function shortenUrlOrbis(url, success, error) {
|
||||||
if (window.navigator.onLine) {
|
if (window.navigator.onLine) {
|
||||||
try {
|
try {
|
||||||
request.post(SHORTEN_API_ORBIS)
|
request.post(SHORTEN_API_ORBIS)
|
||||||
.field('action', 'shorturl')
|
.field('lsturl', url)
|
||||||
.field('url', url)
|
|
||||||
.field('format', 'json')
|
.field('format', 'json')
|
||||||
.end(function(err, response) {
|
.end(function(err, response) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
|
||||||
error('Bad Request');
|
error('Bad Request');
|
||||||
} else {
|
} else {
|
||||||
success(response.body.shorturl);
|
success(response.body.short);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e)
|
||||||
error(e.message ? e.message : e);
|
error(e.message ? e.message : e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error('Not Online');
|
error('Not Online');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_ORBIS = 'https://orbis.zone/api/builds/add';
|
|
||||||
/**
|
|
||||||
* Upload to Orbis
|
|
||||||
* @param {object} ship The URL to shorten
|
|
||||||
* @param {object} creds Orbis credentials
|
|
||||||
* @return {Promise<any>} Either a URL or error message.
|
|
||||||
*/
|
|
||||||
export function orbisUpload(ship, creds) {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
if (window.navigator.onLine) {
|
|
||||||
try {
|
|
||||||
agent
|
|
||||||
.post(API_ORBIS)
|
|
||||||
.withCredentials()
|
|
||||||
.redirects(0)
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.send(ship)
|
|
||||||
.end(function(err, response) {
|
|
||||||
if (err) {
|
|
||||||
reject('Bad Request');
|
|
||||||
} else {
|
|
||||||
resolve(response.body.link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
reject(e.message ? e.message : e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reject('Not Online');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html manifest="/">
|
<html <%= htmlWebpackPlugin.options.appCache ? 'manifest=/' + htmlWebpackPlugin.options.appCache : '' %> >
|
||||||
<head>
|
<head>
|
||||||
<title>Coriolis EDCD Edition</title>
|
<title>Coriolis EDCD Edition</title>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
@@ -26,8 +26,7 @@
|
|||||||
<script>
|
<script>
|
||||||
window.CORIOLIS_GAPI_KEY = '<%- htmlWebpackPlugin.options.gapiKey %>';
|
window.CORIOLIS_GAPI_KEY = '<%- htmlWebpackPlugin.options.gapiKey %>';
|
||||||
window.CORIOLIS_VERSION = '<%- htmlWebpackPlugin.options.version %>';
|
window.CORIOLIS_VERSION = '<%- htmlWebpackPlugin.options.version %>';
|
||||||
window.CORIOLIS_DATE = '<%- htmlWebpackPlugin.options.date.toISOString().slice(0, 10) %>';
|
window.CORIOLIS_DATE = '<%- new Date().toISOString().slice(0, 10) %>';
|
||||||
window.BUGSNAG_VERSION = '<%- htmlWebpackPlugin.options.version + '-' + htmlWebpackPlugin.options.date.toISOString() %>';
|
|
||||||
</script>
|
</script>
|
||||||
<% if (htmlWebpackPlugin.options.uaTracking) { %>
|
<% if (htmlWebpackPlugin.options.uaTracking) { %>
|
||||||
<script>
|
<script>
|
||||||
@@ -37,7 +36,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
<script async src='https://www.google-analytics.com/analytics.js'></script>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<!-- Piwik -->
|
<!-- Piwik -->
|
||||||
<!-- <script type="text/javascript">
|
<!-- <script type="text/javascript">
|
||||||
var _paq = _paq || [];
|
var _paq = _paq || [];
|
||||||
@@ -59,7 +58,7 @@
|
|||||||
<script src="//d2wy8f7a9ursnm.cloudfront.net/v4/bugsnag.min.js"></script>
|
<script src="//d2wy8f7a9ursnm.cloudfront.net/v4/bugsnag.min.js"></script>
|
||||||
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-plugins/v1/bugsnag-react.min.js"></script>
|
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-plugins/v1/bugsnag-react.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
|
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.CORIOLIS_VERSION || undefined})
|
||||||
window.Bugsnag = window.bugsnagClient
|
window.Bugsnag = window.bugsnagClient
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -93,9 +93,6 @@
|
|||||||
color: @primary-bg;
|
color: @primary-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
& thead th.bordered {
|
|
||||||
border-left: 1px solid @primary-bg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,6 @@ select {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cmdr-select {
|
|
||||||
border: 1px solid @primary;
|
|
||||||
padding: 0.5em 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
color: @primary-disabled;
|
color: @primary-disabled;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -37,35 +37,6 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modification-container {
|
|
||||||
@input-container-width: 75%;
|
|
||||||
td {
|
|
||||||
width: 100% - @input-container-width;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-container {
|
|
||||||
width: @input-container-width;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-container {
|
|
||||||
width: 30px;
|
|
||||||
padding: 3px;
|
|
||||||
text-align: left;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-adjuster {
|
|
||||||
width: 100% - @input-container-width;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cb {
|
.cb {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@@ -74,11 +45,6 @@
|
|||||||
border-color:#fff;
|
border-color:#fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:disabled {
|
|
||||||
border-color: #888;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.l {
|
.l {
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
margin-right: 0.8em;
|
margin-right: 0.8em;
|
||||||
|
|||||||
46
src/sw.js
46
src/sw.js
@@ -1,46 +0,0 @@
|
|||||||
console.log('Hello from sw.js');
|
|
||||||
|
|
||||||
if (workbox) {
|
|
||||||
workbox.skipWaiting();
|
|
||||||
workbox.clientsClaim();
|
|
||||||
console.log('Yay! Workbox is loaded 🎉');
|
|
||||||
workbox.routing.registerRoute(
|
|
||||||
new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
|
|
||||||
workbox.strategies.cacheFirst({
|
|
||||||
cacheName: 'google-fonts',
|
|
||||||
plugins: [
|
|
||||||
new workbox.expiration.Plugin({
|
|
||||||
maxEntries: 30
|
|
||||||
}),
|
|
||||||
new workbox.cacheableResponse.Plugin({
|
|
||||||
statuses: [0, 200]
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
);
|
|
||||||
workbox.routing.registerRoute(
|
|
||||||
/\.(?:png|gif|jpg|jpeg|svg)$/,
|
|
||||||
workbox.strategies.cacheFirst({
|
|
||||||
cacheName: 'images',
|
|
||||||
plugins: [
|
|
||||||
new workbox.expiration.Plugin({
|
|
||||||
maxEntries: 60,
|
|
||||||
maxAgeSeconds: 30 * 24 * 60 * 60 // 30 Days
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
);
|
|
||||||
workbox.routing.registerRoute(
|
|
||||||
/\.(?:js|css)$/,
|
|
||||||
workbox.strategies.staleWhileRevalidate({
|
|
||||||
cacheName: 'static-resources'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
workbox.googleAnalytics.initialize();
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Probably an ad-blocker');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('Boo! Workbox didn\'t load 😬');
|
|
||||||
}
|
|
||||||
@@ -1,27 +1,27 @@
|
|||||||
const path = require('path');
|
const path = require('path')
|
||||||
const exec = require('child_process').exec;
|
const exec = require('child_process').exec
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack')
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||||
const WebpackNotifierPlugin = require('webpack-notifier');
|
const WebpackNotifierPlugin = require('webpack-notifier')
|
||||||
const pkgJson = require('./package');
|
const pkgJson = require('./package')
|
||||||
const buildDate = new Date();
|
|
||||||
function CopyDirPlugin(source, destination) {
|
function CopyDirPlugin(source, destination) {
|
||||||
this.source = source;
|
this.source = source
|
||||||
this.destination = destination;
|
this.destination = destination
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyDirPlugin.prototype.apply = function(compiler) {
|
CopyDirPlugin.prototype.apply = function (compiler) {
|
||||||
compiler.plugin('done', () => {
|
compiler.plugin('done', () => {
|
||||||
console.log(compiler.outputPath, this.destination);
|
console.log(compiler.outputPath, this.destination)
|
||||||
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination));
|
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination))
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
devServer: {
|
devServer: {
|
||||||
headers: { 'Access-Control-Allow-Origin': '*' }
|
headers: {'Access-Control-Allow-Origin': '*'}
|
||||||
},
|
},
|
||||||
entry: {
|
entry: {
|
||||||
app: ['webpack-dev-server/client?http://0.0.0.0:3300', 'webpack/hot/only-dev-server', path.join(__dirname, 'src/app/index.js')],
|
app: ['webpack-dev-server/client?http://0.0.0.0:3300', 'webpack/hot/only-dev-server', path.join(__dirname, 'src/app/index.js')],
|
||||||
@@ -46,7 +46,6 @@ module.exports = {
|
|||||||
inject: false,
|
inject: false,
|
||||||
template: path.join(__dirname, 'src/index.ejs'),
|
template: path.join(__dirname, 'src/index.ejs'),
|
||||||
version: pkgJson.version,
|
version: pkgJson.version,
|
||||||
date: buildDate,
|
|
||||||
gapiKey: process.env.CORIOLIS_GAPI_KEY || ''
|
gapiKey: process.env.CORIOLIS_GAPI_KEY || ''
|
||||||
}),
|
}),
|
||||||
new ExtractTextPlugin({
|
new ExtractTextPlugin({
|
||||||
@@ -54,20 +53,20 @@ module.exports = {
|
|||||||
disable: false,
|
disable: false,
|
||||||
allChunks: true
|
allChunks: true
|
||||||
}),
|
}),
|
||||||
new WebpackNotifierPlugin({ alwaysNotify: true }),
|
new WebpackNotifierPlugin({alwaysNotify: true}),
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new webpack.NoEmitOnErrorsPlugin()
|
new webpack.NoEmitOnErrorsPlugin()
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
|
{test: /\.css$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader'})},
|
||||||
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' }) },
|
{test: /\.less$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!less-loader'})},
|
||||||
{ test: /\.(js|jsx)$/, loaders: ['babel-loader'], include: path.join(__dirname, 'src') },
|
{test: /\.(js|jsx)$/, loaders: ['babel-loader'], include: path.join(__dirname, 'src')},
|
||||||
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
||||||
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
||||||
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream' },
|
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
|
||||||
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader' },
|
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'},
|
||||||
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml' }
|
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
const path = require('path');
|
const path = require('path')
|
||||||
const exec = require('child_process').exec;
|
const exec = require('child_process').exec
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack')
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||||
const { InjectManifest } = require('workbox-webpack-plugin');
|
const AppCachePlugin = require('appcache-webpack-plugin')
|
||||||
|
const {BugsnagSourceMapUploaderPlugin} = require('webpack-bugsnag-plugins')
|
||||||
|
const pkgJson = require('./package')
|
||||||
|
|
||||||
const { BugsnagSourceMapUploaderPlugin } = require('webpack-bugsnag-plugins');
|
function CopyDirPlugin (source, destination) {
|
||||||
const pkgJson = require('./package');
|
this.source = source
|
||||||
const buildDate = new Date();
|
this.destination = destination
|
||||||
function CopyDirPlugin(source, destination) {
|
|
||||||
this.source = source;
|
|
||||||
this.destination = destination;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyDirPlugin.prototype.apply = function(compiler) {
|
CopyDirPlugin.prototype.apply = function (compiler) {
|
||||||
compiler.plugin('done', () => {
|
compiler.plugin('done', () => {
|
||||||
console.log(compiler.outputPath, this.destination);
|
console.log(compiler.outputPath, this.destination)
|
||||||
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination));
|
exec('cp -r ' + this.source + ' ' + path.join(compiler.outputPath, this.destination))
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
cache: true,
|
cache: true,
|
||||||
@@ -41,10 +40,10 @@ module.exports = {
|
|||||||
'screw-ie8': true,
|
'screw-ie8': true,
|
||||||
sourceMap: true
|
sourceMap: true
|
||||||
}),
|
}),
|
||||||
// new webpack.optimize.CommonsChunkPlugin({
|
//new webpack.optimize.CommonsChunkPlugin({
|
||||||
// name: 'lib',
|
// name: 'lib',
|
||||||
// filename: 'lib.[chunkhash:6].js'
|
// filename: 'lib.[chunkhash:6].js'
|
||||||
// }),
|
//}),
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
inject: false,
|
inject: false,
|
||||||
appCache: 'coriolis.appcache',
|
appCache: 'coriolis.appcache',
|
||||||
@@ -61,7 +60,6 @@ module.exports = {
|
|||||||
template: path.join(__dirname, 'src/index.ejs'),
|
template: path.join(__dirname, 'src/index.ejs'),
|
||||||
uaTracking: process.env.CORIOLIS_UA_TRACKING || '',
|
uaTracking: process.env.CORIOLIS_UA_TRACKING || '',
|
||||||
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
|
gapiKey: process.env.CORIOLIS_GAPI_KEY || '',
|
||||||
date: buildDate,
|
|
||||||
version: pkgJson.version
|
version: pkgJson.version
|
||||||
}),
|
}),
|
||||||
new ExtractTextPlugin({
|
new ExtractTextPlugin({
|
||||||
@@ -71,27 +69,28 @@ module.exports = {
|
|||||||
}),
|
}),
|
||||||
new BugsnagSourceMapUploaderPlugin({
|
new BugsnagSourceMapUploaderPlugin({
|
||||||
apiKey: 'ba9fae819372850fb660755341fa6ef5',
|
apiKey: 'ba9fae819372850fb660755341fa6ef5',
|
||||||
appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
|
appVersion: pkgJson.version
|
||||||
}),
|
}),
|
||||||
new CopyDirPlugin(path.join(__dirname, 'src/schemas'), 'schemas'),
|
new CopyDirPlugin(path.join(__dirname, 'src/schemas'), 'schemas'),
|
||||||
new CopyDirPlugin(path.join(__dirname, 'src/images/logo/*'), ''),
|
new CopyDirPlugin(path.join(__dirname, 'src/images/logo/*'), ''),
|
||||||
new CopyDirPlugin(path.join(__dirname, 'src/.htaccess'), ''),
|
new CopyDirPlugin(path.join(__dirname, 'src/.htaccess'), ''),
|
||||||
new InjectManifest({
|
new AppCachePlugin({
|
||||||
swSrc: './src/sw.js',
|
network: ['*'],
|
||||||
importWorkboxFrom: 'cdn',
|
settings: ['prefer-online'],
|
||||||
swDest: 'service-worker.js'
|
exclude: ['index.html', /.*\.map$/],
|
||||||
}),
|
output: 'coriolis.appcache'
|
||||||
|
})
|
||||||
],
|
],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
|
{test: /\.css$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader'})},
|
||||||
{ test: /\.less$/, loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader!less-loader' }) },
|
{test: /\.less$/, loader: ExtractTextPlugin.extract({fallback: 'style-loader', use: 'css-loader!less-loader'})},
|
||||||
{ test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src') },
|
{test: /\.(js|jsx)$/, loader: 'babel-loader?cacheDirectory=true', include: path.join(__dirname, 'src')},
|
||||||
{ test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
{test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
||||||
{ test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff' },
|
{test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/font-woff'},
|
||||||
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream' },
|
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
|
||||||
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader' },
|
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file-loader'},
|
||||||
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml' }
|
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user