Compare commits
277 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b49eb06101 | ||
|
|
eeb4a86a13 | ||
|
|
3a265b2804 | ||
|
|
5ebabd6e6e | ||
|
|
6e6c337bbb | ||
|
|
31b56354e0 | ||
|
|
fd1adbe55c | ||
|
|
3d0259c304 | ||
|
|
6f1b86118e | ||
|
|
b3fcfa7808 | ||
|
|
4ead80a37c | ||
|
|
72dc73e090 | ||
|
|
bb19dc25c0 | ||
|
|
1729636657 | ||
|
|
92809d1d24 | ||
|
|
4e81c828df | ||
|
|
f5bd7d2ecb | ||
|
|
a989bd5b5d | ||
|
|
1bedbb1909 | ||
|
|
9775e1c742 | ||
|
|
19228a9c56 | ||
|
|
363bf7fd2a | ||
|
|
15748066c9 | ||
|
|
c3fe0a0cef | ||
|
|
1544deb350 | ||
|
|
f060eb1b62 | ||
|
|
32795ea678 | ||
|
|
d744d15132 | ||
|
|
bfcef18c02 | ||
|
|
b04c2ed2f5 | ||
|
|
f51998b1c2 | ||
|
|
d7000bfebf | ||
|
|
3e2b3e33fb | ||
|
|
87dd52c043 | ||
|
|
05bc8ebb93 | ||
|
|
09b945d29e | ||
|
|
67b5d749df | ||
|
|
a19fd69d0b | ||
|
|
cfb65396ab | ||
|
|
a4a0f96502 | ||
|
|
1390339024 | ||
|
|
43d19f1dbb | ||
|
|
c20439264a | ||
|
|
61c3941618 | ||
|
|
da277e4eaa | ||
|
|
51d24a1105 | ||
|
|
138931c0cf | ||
|
|
7b3c3a1236 | ||
|
|
524b05159e | ||
|
|
e2170c9d2f | ||
|
|
34b4690e1a | ||
|
|
f25152f378 | ||
|
|
3491d62b99 | ||
|
|
36bffe1758 | ||
|
|
33fd30a377 | ||
|
|
78ff84630e | ||
|
|
b357573add | ||
|
|
05e160f702 | ||
|
|
9175fb60af | ||
|
|
d783a38588 | ||
|
|
b42a812a45 | ||
|
|
9af87ae88e | ||
|
|
a2f91cf620 | ||
|
|
8227a4e361 | ||
|
|
653cb30dd9 | ||
|
|
8e28408a8d | ||
|
|
eb70eb417a | ||
|
|
126e8ca59b | ||
|
|
c81d7bf302 | ||
|
|
78e85f2c6a | ||
|
|
973af84b73 | ||
|
|
3c8b1f7d6a | ||
|
|
62d9749660 | ||
|
|
7db185e635 | ||
|
|
e69bdac75c | ||
|
|
231f7e9267 | ||
|
|
ab0019424f | ||
|
|
2ef44e38b3 | ||
|
|
d051829f98 | ||
|
|
01e8e71b28 | ||
|
|
14681aa9fa | ||
|
|
035f6b3efa | ||
|
|
79224f4f9a | ||
|
|
b93572b18d | ||
|
|
41c4b4243a | ||
|
|
f5127c2475 | ||
|
|
db4303d3c8 | ||
|
|
8bc100714f | ||
|
|
fabd370f4a | ||
|
|
769c20154d | ||
|
|
2b5edd75cb | ||
|
|
1b56d39356 | ||
|
|
8d1d6d63ad | ||
|
|
ed637addb8 | ||
|
|
a713105878 | ||
|
|
c527a62ce6 | ||
|
|
16c76b2598 | ||
|
|
ad134330c4 | ||
|
|
05438daf48 | ||
|
|
afebf68cae | ||
|
|
ab4bdf355c | ||
|
|
0f4abd6ace | ||
|
|
2901c978dc | ||
|
|
21e9dbc381 | ||
|
|
b2ceafa89e | ||
|
|
d8633a8411 | ||
|
|
f4bf09eaab | ||
|
|
f0c40aae34 | ||
|
|
90ed8ed198 | ||
|
|
9af6a529dd | ||
|
|
269dfbdc1d | ||
|
|
d01cd24b0d | ||
|
|
93ac3b217f | ||
|
|
a38d6cf839 | ||
|
|
bd656b46ef | ||
|
|
20cce4dcda | ||
|
|
d286dda07f | ||
|
|
45b6dabcd2 | ||
|
|
d476c58a9c | ||
|
|
e837bb68fb | ||
|
|
e2adc7bdc4 | ||
|
|
22716517c5 | ||
|
|
8b82965c12 | ||
|
|
65cf975a35 | ||
|
|
1c78fea48f | ||
|
|
08f49c8339 | ||
|
|
bed81d26b2 | ||
|
|
38b13fca27 | ||
|
|
0869230b13 | ||
|
|
80d4b6b431 | ||
|
|
fb7e9136d4 | ||
|
|
059ff367ff | ||
|
|
d322e062ad | ||
|
|
f807f4222f | ||
|
|
1d4b046723 | ||
|
|
b9fc114e02 | ||
|
|
50047411c3 | ||
|
|
610ded2f83 | ||
|
|
2a644e787a | ||
|
|
90b339e5c3 | ||
|
|
a213ad12d0 | ||
|
|
a4b8b942a1 | ||
|
|
df7ef0fbdb | ||
|
|
f42dc481df | ||
|
|
623be748c0 | ||
|
|
35c84ee0f0 | ||
|
|
4d84f271be | ||
|
|
5458c548fb | ||
|
|
a9be057fe8 | ||
|
|
564c228d41 | ||
|
|
3f6875abb6 | ||
|
|
a2aa829b45 | ||
|
|
08b6ec9e31 | ||
|
|
ee99d33275 | ||
|
|
7b9e8dbc7d | ||
|
|
44f45e7e93 | ||
|
|
a49f7ec594 | ||
|
|
9ee12e4167 | ||
|
|
33ad7d909a | ||
|
|
e5e29dc6cb | ||
|
|
34dd40bcbf | ||
|
|
0e8e9f5cbc | ||
|
|
d39cbb3ef5 | ||
|
|
5470b241f6 | ||
|
|
6507c22355 | ||
|
|
96c2f4b3b6 | ||
|
|
b0c521246e | ||
|
|
5c0616ad47 | ||
|
|
523f37ccc1 | ||
|
|
5e2768bbf6 | ||
|
|
61b3e7d47d | ||
|
|
ed6fc32d76 | ||
|
|
4c74675edd | ||
|
|
d43ee25e71 | ||
|
|
46f00e0bc7 | ||
|
|
d3cea71e50 | ||
|
|
0516a6f54d | ||
|
|
eb8373f8b4 | ||
|
|
202bbbd357 | ||
|
|
b9e404c4da | ||
|
|
e16ce83c03 | ||
|
|
83c266d083 | ||
|
|
349b8f436c | ||
|
|
e9a0a01e14 | ||
|
|
457b8920f2 | ||
|
|
31b63e9a87 | ||
|
|
8dc3725b47 | ||
|
|
e2096ba9f4 | ||
|
|
231fcbb3bc | ||
|
|
75c22de166 | ||
|
|
d196127392 | ||
|
|
fb4dc906aa | ||
|
|
9937ba8039 | ||
|
|
d92722f1c2 | ||
|
|
69096d7816 | ||
|
|
2846827959 | ||
|
|
67bd56e692 | ||
|
|
95f5e8e5ae | ||
|
|
eb52a7548c | ||
|
|
b479b61926 | ||
|
|
726a08b05b | ||
|
|
fc2f76c31c | ||
|
|
839e1a5cbd | ||
|
|
12beeffae0 | ||
|
|
83ad7d9f6c | ||
|
|
6e65d67f14 | ||
|
|
a127e2f5a5 | ||
|
|
9154b7f38c | ||
|
|
c2d8cad249 | ||
|
|
e9ffe5baec | ||
|
|
fffa325e83 | ||
|
|
ed14ed2bb7 | ||
|
|
7c9e020b88 | ||
|
|
d711d1519b | ||
|
|
3361f7e435 | ||
|
|
3a79f99f77 | ||
|
|
ff25b55c1f | ||
|
|
ae6f6b0da1 | ||
|
|
6dc714371d | ||
|
|
5762b133e5 | ||
|
|
50741657a5 | ||
|
|
ff9a38f23f | ||
|
|
3b11b31e7c | ||
|
|
44e5dfb4d4 | ||
|
|
30ea10830c | ||
|
|
eb0f611d78 | ||
|
|
96ef192738 | ||
|
|
1970616443 | ||
|
|
aac4c9a872 | ||
|
|
aebfb62ac4 | ||
|
|
9748043466 | ||
|
|
b6f98e741b | ||
|
|
b513cca4b5 | ||
|
|
65f53a3fa4 | ||
|
|
bf217e7fdd | ||
|
|
09e646ee95 | ||
|
|
ab18228131 | ||
|
|
164e9f5c8a | ||
|
|
faa8759851 | ||
|
|
c2a84606a1 | ||
|
|
42d51b7612 | ||
|
|
38dc4319c0 | ||
|
|
fda966be02 | ||
|
|
bf47a81dc1 | ||
|
|
eef4e06f29 | ||
|
|
2d2c2b75e3 | ||
|
|
0066e7fd40 | ||
|
|
d596723b7b | ||
|
|
c7269423ed | ||
|
|
ee60e4d043 | ||
|
|
c98a73c6a8 | ||
|
|
0116523c63 | ||
|
|
c1afa7c385 | ||
|
|
6630ff8fee | ||
|
|
14f303c581 | ||
|
|
0728af14dd | ||
|
|
1edacf3eba | ||
|
|
3d6d210563 | ||
|
|
df09da4b0a | ||
|
|
b02de43b50 | ||
|
|
1b3ca2f697 | ||
|
|
886614527f | ||
|
|
5f05bf0dc5 | ||
|
|
59710ce2cf | ||
|
|
b533191bc9 | ||
|
|
4fa1115e8f | ||
|
|
be5a069b23 | ||
|
|
80da41c866 | ||
|
|
d278a7c1fd | ||
|
|
69de209aba | ||
|
|
15616d112f | ||
|
|
95adca5cde | ||
|
|
82c5460936 | ||
|
|
b850695715 | ||
|
|
d5af972272 | ||
|
|
8946f9b97c | ||
|
|
348339520d |
61
.eslintrc
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"classes": true,
|
||||
"modules": true
|
||||
},
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"extends": "plugin:react/recommended",
|
||||
"settings": {
|
||||
"react": {
|
||||
"pragma": "React"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"strict": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"valid-jsdoc": [2, {
|
||||
"requireReturn": false
|
||||
}],
|
||||
"require-jsdoc": [2, {
|
||||
"require": {
|
||||
"FunctionDeclaration": true,
|
||||
"MethodDefinition": true,
|
||||
"ClassDeclaration": true
|
||||
}
|
||||
}],
|
||||
"no-console": 2,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"indent": [2, 2, { "SwitchCase": 1, "VariableDeclarator": 2 }],
|
||||
"quotes": [2, "single"],
|
||||
"no-spaced-func": 2,
|
||||
"operator-linebreak": [2, "after"],
|
||||
"padded-blocks": [2, "never"],
|
||||
"semi": [2, "always"],
|
||||
"no-undef": 2,
|
||||
"semi-spacing": [2, { "before": false, "after": true }],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "never"],
|
||||
"object-curly-spacing": [2, "always"],
|
||||
"array-bracket-spacing": [2, "never"],
|
||||
"computed-property-spacing": [2, "never"],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"spaced-comment": [2, "always"],
|
||||
"no-var": 2,
|
||||
"object-shorthand": [2, "always"],
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/react-in-jsx-scope": 2
|
||||
}
|
||||
}
|
||||
5
.gitignore
vendored
@@ -1,10 +1,5 @@
|
||||
node_modules
|
||||
bower_components
|
||||
bower_components/*
|
||||
build
|
||||
.DS_Store
|
||||
*.log
|
||||
app/js/db.js
|
||||
app/db.json
|
||||
nginx.pid
|
||||
template_cache.js
|
||||
12
.travis.yml
@@ -3,17 +3,13 @@ notifications:
|
||||
email: false
|
||||
sudo: false
|
||||
node_js:
|
||||
- "0.12"
|
||||
- "4.2.6"
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- bower_components
|
||||
|
||||
before_script:
|
||||
- npm install -g gulp
|
||||
- npm install -g bower
|
||||
- bower install
|
||||
|
||||
script:
|
||||
- gulp lint
|
||||
- gulp build-prod
|
||||
- gulp test
|
||||
- npm run lint
|
||||
- npm test
|
||||
13
README.md
@@ -1,12 +1,11 @@
|
||||
[](https://travis-ci.org/cmmcleod/coriolis) [](https://waffle.io/cmmcleod/coriolis) [](http://waffle.io/cmmcleod/coriolis)
|
||||
|
||||
 [](https://travis-ci.org/cmmcleod/coriolis) [](https://waffle.io/cmmcleod/coriolis) [](http://waffle.io/cmmcleod/coriolis) [](https://www.hipchat.com/gfYQiZcmy)
|
||||
|
||||
|
||||
## About
|
||||
|
||||
The Coriolis project was inspired by [E:D Shipyard](http://www.edshipyard.com/) and, of course, [Elite Dangerous](http://www.elitedangerous.com). The ultimate goal of Coriolis is to provide rich features to support in-game play and planning while engaging the E:D community to support its development.
|
||||
|
||||
Coriolis was created for non-commercial purposes. Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments and no employee of Frontier Developments was involved in the making of it.
|
||||
Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments and no employee of Frontier Developments was involved in the making of it.
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -14,6 +13,8 @@ Please [submit issues](https://github.com/cmmcleod/coriolis/issues), or better y
|
||||
|
||||
### Feature Requests, Suggestions & Bugs
|
||||
|
||||
Chat to us on [HipChat](https://www.hipchat.com/gfYQiZcmy)!
|
||||
|
||||
All such requests are managed and tracked through [issues](https://github.com/cmmcleod/coriolis/issues). An overview of these can be found [here](https://waffle.io/cmmcleod/coriolis).
|
||||
|
||||
## Development
|
||||
@@ -21,14 +22,14 @@ All such requests are managed and tracked through [issues](https://github.com/cm
|
||||
See the [Developer's Guide](https://github.com/cmmcleod/coriolis/wiki/Developer's-Guide) in the wiki.
|
||||
|
||||
|
||||
### Ship and Component Database
|
||||
### Ship and Module Database
|
||||
|
||||
See [Data wiki](https://github.com/cmmcleod/coriolis/wiki/Database) for details on structure, etc.
|
||||
See the [Data wiki](https://github.com/cmmcleod/coriolis-data/wiki) for details on structure, etc.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
All Data and [associated JSON](https://github.com/cmmcleod/coriolis/tree/master/data) files are intellectual property and copyright of Frontier Developments plc ('Frontier', 'Frontier Developments') and are subject to their
|
||||
All Data and [associated JSON](https://github.com/cmmcleod/coriolis-data) files are intellectual property and copyright of Frontier Developments plc ('Frontier', 'Frontier Developments') and are subject to their
|
||||
[terms and conditions](https://www.frontierstore.net/terms-and-conditions/).
|
||||
|
||||
The code (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.
|
||||
|
||||
@@ -1,93 +1,128 @@
|
||||
{
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/1.json#",
|
||||
"name": "Test",
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/3.json#",
|
||||
"name": "Test My Ship",
|
||||
"ship": "Anaconda",
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b?bn=Test",
|
||||
"code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b",
|
||||
"url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA?bn=Test%20My%20Ship",
|
||||
"old-code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA",
|
||||
"code": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA",
|
||||
"shipId": "anaconda"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"standard": {
|
||||
"bulkheads": "Reactive Surface Composite",
|
||||
"cargoHatch": {
|
||||
"enabled": false,
|
||||
"priority": 5
|
||||
},
|
||||
"powerPlant": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 6,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 6,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 3
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 5,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"sensors": {
|
||||
"class": 8,
|
||||
"rating": "A"
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 5,
|
||||
"rating": "C"
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
}
|
||||
},
|
||||
"hardpoints": [
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Plasma Accelerator",
|
||||
"mount": "Fixed"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cannon",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cannon",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "F",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "F",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Beam Laser",
|
||||
"mount": "Turret"
|
||||
}
|
||||
@@ -96,39 +131,53 @@
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Booster"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Booster"
|
||||
},
|
||||
null,
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Kill Warrant Scanner"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cargo Scanner"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "F",
|
||||
"enabled": false,
|
||||
"priority": 1,
|
||||
"group": "Countermeasure",
|
||||
"name": "Electronic Countermeasure"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Countermeasure",
|
||||
"name": "Chaff Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Countermeasure",
|
||||
"name": "Point Defence"
|
||||
}
|
||||
@@ -137,26 +186,36 @@
|
||||
{
|
||||
"class": 7,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Generator"
|
||||
},
|
||||
{
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Cell Bank"
|
||||
},
|
||||
{
|
||||
"class": 6,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Hull Reinforcement Package"
|
||||
},
|
||||
{
|
||||
"class": 5,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
null,
|
||||
@@ -164,56 +223,66 @@
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 3,
|
||||
"group": "Fuel Scoop"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"group": "FSD Interdictor"
|
||||
"enabled": true,
|
||||
"priority": 3,
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 3,
|
||||
"hullCost": 141889932,
|
||||
"hullCost": 141889930,
|
||||
"speed": 180,
|
||||
"topSpeed": 186.5,
|
||||
"boost": 240,
|
||||
"boostEnergy": 29,
|
||||
"topBoost": 248.66,
|
||||
"agility": 2,
|
||||
"baseShieldStrength": 350,
|
||||
"baseArmour": 945,
|
||||
"hullMass": 400,
|
||||
"masslock": 23,
|
||||
"shipCostMultiplier": 1,
|
||||
"componentCostMultiplier": 1,
|
||||
"pipSpeed": 0.14,
|
||||
"moduleCostMultiplier": 1,
|
||||
"fuelCapacity": 32,
|
||||
"cargoCapacity": 128,
|
||||
"ladenMass": 1339.2,
|
||||
"armour": 2078,
|
||||
"armourAdded": 240,
|
||||
"armour": 2228,
|
||||
"armourAdded": 390,
|
||||
"armourMultiplier": 1.95,
|
||||
"shieldMultiplier": 1.4,
|
||||
"totalCost": 882362049,
|
||||
"totalCost": 882362060,
|
||||
"unladenMass": 1179.2,
|
||||
"totalDps": 29,
|
||||
"powerAvailable": 36,
|
||||
"powerRetracted": 23.93,
|
||||
"powerDeployed": 35.56,
|
||||
"powerRetracted": 23.33,
|
||||
"powerDeployed": 34.76,
|
||||
"unladenRange": 18.49,
|
||||
"fullTankRange": 18.12,
|
||||
"ladenRange": 16.39,
|
||||
"unladenTotalRange": 73.21,
|
||||
"ladenTotalRange": 66.15,
|
||||
"unladenFastestRange": 73.21,
|
||||
"ladenFastestRange": 66.15,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 833
|
||||
}
|
||||
22
__tests__/fixtures/ed-shipyard-import-invalid.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"buildText": "[Imaginary Ship]\nbla bla",
|
||||
"errorMsg": "No such ship found: \"Imaginary Ship\""
|
||||
},
|
||||
{
|
||||
"buildText": "[Viper]\nS: 1F/F Pulse Laser\nsome un-parseable nonsense\nS: 1F/F Pulse Laser\n",
|
||||
"errorMsg": "Error parsing: \"some un-parseable nonsense\""
|
||||
},
|
||||
{
|
||||
"buildText": "[Sidewinder]\nS: 2F/F Pulse Laser\nS: 1F/F Pulse Laser\n",
|
||||
"errorMsg": "2F Pulse Laser exceeds slot size: \"S: 2F/F Pulse Laser\""
|
||||
},
|
||||
{
|
||||
"buildText": "[Sidewinder]\nL: 2F/F Pulse Laser\nS: 1F/F Pulse Laser\n",
|
||||
"errorMsg": "No hardpoint slot available for: \"L: 2F/F Pulse Laser\""
|
||||
},
|
||||
{
|
||||
"buildText": "[Sidewinder]\nS: 1F/F Magic Thing\nS: 1F/F Pulse Laser\n",
|
||||
"errorMsg": "Unknown component: \"S: 1F/F Magic Thing\""
|
||||
}
|
||||
]
|
||||
32
__tests__/fixtures/ed-shipyard-import-valid.json
Normal file
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"shipId": "anaconda",
|
||||
"buildName": "Imported Anaconda",
|
||||
"buildCode": "0pyttFolodDsyf5------1717--------05044j-03--2h--00.Iw18ZlA=.Aw18ZlA=",
|
||||
"buildText": "[Anaconda]\nS: 1F/F Pulse Laser\nS: 1F/F Pulse Laser\n\nBH: 1I Lightweight Alloy\nRB: 8E Power Plant\nTM: 7E Thrusters\nFH: 6E Frame Shift Drive\nEC: 5E Life Support\nPC: 8E Power Distributor\nSS: 8E Sensors\nFS: 5C Fuel Tank (Capacity: 32)\n\n7: 6E Cargo Rack (Capacity: 64)\n6: 5E Cargo Rack (Capacity: 32)\n6: 6E Shield Generator\n5: 4E Cargo Rack (Capacity: 16)\n4: 1E Basic Discovery Scanner\n2: 1E Cargo Rack (Capacity: 2)\n"
|
||||
},
|
||||
{
|
||||
"shipId": "anaconda",
|
||||
"buildName": "Imported Anaconda",
|
||||
"buildCode": "0pyttFolodDsyf5------1717--------05044j-03--2h--00.Iw18ZlA=.Aw18ZlA=",
|
||||
"buildText": "\n\n \t[Anaconda]\nS: 1F/F Pulse Laser\nS: 1F/F Pulse Laser\n\nBH: 1I Lightweight Alloy\nRB: 8E Power Plant\nTM: 7E Thrusters\nFH: 6E Frame Shift Drive\nEC: 5E Life Support\nPC: 8E Power Distributor\nSS: 8E Sensors\nFS: 5C Fuel Tank (Capacity: 32)\n\n7: 6E Cargo Rack (Capacity: 64)\n6: 5E Cargo Rack (Capacity: 32)\n6: 6E Shield Generator\n5: 4E Cargo Rack (Capacity: 16)\n4: 1E Basic Discovery Scanner\n2: 1E Cargo Rack (Capacity: 2)\n"
|
||||
},
|
||||
{
|
||||
"shipId": "cobra_mk_iii",
|
||||
"buildName": "Imported Cobra Mk III",
|
||||
"buildCode": "0patcFeldd5sdf41712222503040202490f242h.Iw1-kA==.Aw1-kA==",
|
||||
"buildText": "[Cobra Mk III]\nM: 1F/F Pulse Laser\nM: 1G/G Burst Laser\nS: 1E/T Fragment Cannon\nS: 1G/T Multi-cannon\nU: 0I Point Defence\nU: 0A Shield Booster\n\nBH: 1I Lightweight Alloy\nRB: 4A Power Plant\nTM: 4C Thrusters\nFH: 4E Frame Shift Drive\nEC: 3D Life Support\nPC: 2A Power Distributor\nSS: 3D Sensors\nFS: 4C Fuel Tank (Capacity: 16)\n\n4: 3E Cargo Rack (Capacity: 8)\n4: 3E Cargo Rack (Capacity: 8)\n4: 4E Shield Generator\n2: 2C Auto Field-Maintenance Unit\n2: 1E Standard Docking Computer\n2: 1E Basic Discovery Scanner\n---\nShield: 112.29 MJ\nPower : 10.45 MW retracted (67%)\n 12.16 MW deployed (78%)\n 15.60 MW available\nCargo : 16 T\nFuel : 16 T\nMass : 235.5 T empty\n 267.5 T full\nRange : 10.69 LY unladen\n 10.05 LY laden\nPrice : 2,929,040 CR\nRe-Buy: 146,452 CR @ 95% insurance\n"
|
||||
},
|
||||
{
|
||||
"shipId": "type_9_heavy",
|
||||
"buildName": "Imported Type-9 Heavy",
|
||||
"buildCode": "3pftsFklkdisif57e2k2f2h110001020306054j03022f01242i.Iw18eQ==.Aw18eQ==",
|
||||
"buildText": "[Type-9 Heavy]\nM: 2D/G Fragment Cannon\nM: 2I/F Mine Launcher\nM: 2B/FD Missile Rack\nS: 1I/FS Torpedo Pylon\nS: 1F/F Burst Laser\nU: 0I Chaff Launcher\nU: 0F Electronic Countermeasure\nU: 0I Heat Sink Launcher\nU: 0I Point Defence\n\nBH: 1I Mirrored Surface Composite\nRB: 5A Power Plant\nTM: 7D Thrusters\nFH: 6A Frame Shift Drive\nEC: 5A Life Support\nPC: 4D Power Distributor\nSS: 4D Sensors\nFS: 5C Fuel Tank (Capacity: 32)\n\n8: 7E Cargo Rack (Capacity: 128)\n7: 6E Cargo Rack (Capacity: 64)\n6: 6E Shield Generator\n5: 4E Cargo Rack (Capacity: 16)\n4: 3E Cargo Rack (Capacity: 8)\n4: 1C Advanced Discovery Scanner\n3: 2E Cargo Rack (Capacity: 4)\n3: 1E Standard Docking Computer\n2: 1C Detailed Surface Scanner\n"
|
||||
},
|
||||
{
|
||||
"shipId": "vulture",
|
||||
"buildName": "Imported Vulture",
|
||||
"buildCode": "4patfFalddksif31e1e0e0j04044a0n532jf1.Iw19kA==.Aw19kA==",
|
||||
"buildText": "[Vulture]\nL: 3E/G Pulse Laser\nL: 3E/G Pulse Laser\nU: 0A Frame Shift Wake Scanner\nU: 0A Kill Warrant Scanner\nU: 0A Shield Booster\nU: 0A Shield Booster\n\nBH: 1I Reactive Surface Composite\nRB: 4A Power Plant\nTM: 5A Thrusters\nFH: 4A Frame Shift Drive\nEC: 3D Life Support\nPC: 5A Power Distributor\nSS: 4D Sensors\nFS: 3C Fuel Tank (Capacity: 8)\n\n5: 5A Shield Generator\n4: 4A Auto Field-Maintenance Unit\n2: 2A Shield Cell Bank\n1: 1A Fuel Scoop\n1: 1C Fuel Tank (Capacity: 2)"
|
||||
}
|
||||
]
|
||||
50
__tests__/fixtures/expected-builds.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"type_6_transporter": {
|
||||
"Cargo": "0p0tdFal8d8s8f4-----04040303430101.Iw1-kA==.Aw1-kA==",
|
||||
"Miner": "0p5tdFal8d8s8f42l2l---040403451q0101.Iw1-kA==.Aw1-kA==",
|
||||
"Hopper": "0p0tdFal8d0s8f41717---030302024300-.Iw1-kA==.Aw1-kA=="
|
||||
},
|
||||
"type_7_transport": {
|
||||
"Cargo": "0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==",
|
||||
"Miner": "0pdtiFflid8sdf5--2l2l----0505041v03450000.Iw18aQ==.Aw18aQ=="
|
||||
},
|
||||
"federal_dropship": {
|
||||
"Cargo": "0pdtiFflnddsif4-1717------05040448020201.Iw18aQ==.Aw18aQ=="
|
||||
},
|
||||
"asp": {
|
||||
"Miner": "2pftfFflidfskf50s0s24242l2l---04054a1q02022o27.Iw18WQ==.Aw18WQ=="
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "0p5tiFflndisnf4--0s0s----0605450302020101.Iw18aQ==.Aw18aQ==",
|
||||
"Dream": "2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o-.Iw18aQ==.Aw18aQ==",
|
||||
"Current": "0patkFflndfskf4----------------.Iw18aQ==.Aw18aQ=="
|
||||
},
|
||||
"type_9_heavy": {
|
||||
"Current": "0patsFklndnsif6---------0706054a0303020224.Iw18eQ==.Aw18eQ=="
|
||||
},
|
||||
"python": {
|
||||
"Cargo": "0patnFflidsssf5---------050505040448020201.Iw18eQ==.Aw18eQ==",
|
||||
"Miner": "0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o.Iw18eQ==.Aw18eQ==",
|
||||
"Dream": "2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201.Iw18eQ==.Aw18eQ==",
|
||||
"Missile": "0pttoFjljdystf52f2g2d2ePh----04044j03---002h.Iw18eQ==.Aw18eQ=="
|
||||
},
|
||||
"anaconda": {
|
||||
"Dream": "4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d040303326b.Iw18ZlA=.Aw18ZlA=",
|
||||
"Cargo": "0patnFklndnsxf5----------------0605050504040445030301.Iw18ZlA=.Aw18ZlA=",
|
||||
"Current": "0patnFklndksxf5----------------0605050504040403034524.Iw18ZlA=.Aw18ZlA=",
|
||||
"Explorer": "0patnFklndksxf5--------0202------f7050505040s372f2i4524.Iw18ZlA=.Aw18ZlA=",
|
||||
"Test": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18ZlA=.Aw18ZlA="
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Explorer": "0p0tdFfldddsdf5---0202--320p432i2f.Iw1-kA==.Aw1-kA=="
|
||||
},
|
||||
"vulture": {
|
||||
"Bounty Hunter": "3patcFalddksff31e1e0404-0l4a5d27662j.Iw19kA==.Aw19kA=="
|
||||
},
|
||||
"fer_de_lance": {
|
||||
"Attack": "2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.Aw18aQ=="
|
||||
},
|
||||
"eagle": {
|
||||
"Figther": "4p0t5F5l3d5s5f20p0p24-40532j-.Iw1-EA==.Aw1-EA=="
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"Miner": "25A5A5A4D4A5A5C0s0s24242l2l---04054a1q02022o27"
|
||||
},
|
||||
"cobra_mk_iii": {
|
||||
"Example": "24A4A4A3D3A3A4C0s0s2d2d0m0445032b2o2753.AwRj4yKA.CwBhEYyrKhmMQ===",
|
||||
"Example": "24A4A4A3D3A3A4C0s0s2d2d0m0445032b2o2753.AwRj4yKA.CwBhEYyrKhmMQ==="
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "03A5D5A5D4D5D4C--0s0s----0605450302020101",
|
||||
@@ -117,8 +117,8 @@
|
||||
"unladenRange": 32.48,
|
||||
"fullTankRange": 30.27,
|
||||
"ladenRange": 19.61,
|
||||
"unladenTotalRange": 176.71,
|
||||
"ladenTotalRange": 112.92,
|
||||
"unladenFastestRange": 176.71,
|
||||
"ladenFastestRange": 112.92,
|
||||
"maxJumpCount": 6,
|
||||
"shieldStrength": 86.49
|
||||
}
|
||||
@@ -251,8 +251,8 @@
|
||||
"unladenRange": 30.24,
|
||||
"fullTankRange": 28.32,
|
||||
"ladenRange": 19.8,
|
||||
"unladenTotalRange": 164.89,
|
||||
"ladenTotalRange": 114.03,
|
||||
"unladenFastestRange": 164.89,
|
||||
"ladenFastestRange": 114.03,
|
||||
"maxJumpCount": 6,
|
||||
"shieldStrength": 149.2
|
||||
}
|
||||
@@ -381,8 +381,8 @@
|
||||
"unladenRange": 31.71,
|
||||
"fullTankRange": 29.61,
|
||||
"ladenRange": 23.58,
|
||||
"unladenTotalRange": 172.68,
|
||||
"ladenTotalRange": 136.46,
|
||||
"unladenFastestRange": 172.68,
|
||||
"ladenFastestRange": 136.46,
|
||||
"maxJumpCount": 6,
|
||||
"shieldStrength": 86.49
|
||||
}
|
||||
@@ -513,8 +513,8 @@
|
||||
"unladenRange": 26.41,
|
||||
"fullTankRange": 24.97,
|
||||
"ladenRange": 17.36,
|
||||
"unladenTotalRange": 172.04,
|
||||
"ladenTotalRange": 118.55,
|
||||
"unladenFastestRange": 172.04,
|
||||
"ladenFastestRange": 118.55,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 89.07
|
||||
}
|
||||
@@ -655,8 +655,8 @@
|
||||
"unladenRange": 25.77,
|
||||
"fullTankRange": 24.39,
|
||||
"ladenRange": 17.98,
|
||||
"unladenTotalRange": 167.93,
|
||||
"ladenTotalRange": 122.84,
|
||||
"unladenFastestRange": 167.93,
|
||||
"ladenFastestRange": 122.84,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 125.07
|
||||
}
|
||||
@@ -793,8 +793,8 @@
|
||||
"unladenRange": 19.27,
|
||||
"fullTankRange": 18.95,
|
||||
"ladenRange": 15.43,
|
||||
"unladenTotalRange": 67.34,
|
||||
"ladenTotalRange": 54.75,
|
||||
"unladenFastestRange": 67.34,
|
||||
"ladenFastestRange": 54.75,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 111.07
|
||||
}
|
||||
@@ -956,8 +956,8 @@
|
||||
"unladenRange": 27.1,
|
||||
"fullTankRange": 25.58,
|
||||
"ladenRange": 21.94,
|
||||
"unladenTotalRange": 176.39,
|
||||
"ladenTotalRange": 150.58,
|
||||
"unladenFastestRange": 176.39,
|
||||
"ladenFastestRange": 150.58,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 253.58
|
||||
}
|
||||
@@ -1098,8 +1098,8 @@
|
||||
"unladenRange": 26.01,
|
||||
"fullTankRange": 25.42,
|
||||
"ladenRange": 17.19,
|
||||
"unladenTotalRange": 90.67,
|
||||
"ladenTotalRange": 61.04,
|
||||
"unladenFastestRange": 90.67,
|
||||
"ladenFastestRange": 61.04,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 191.82
|
||||
}
|
||||
@@ -1262,8 +1262,8 @@
|
||||
"unladenRange": 15.19,
|
||||
"fullTankRange": 14.99,
|
||||
"ladenRange": 14.99,
|
||||
"unladenTotalRange": 53.15,
|
||||
"ladenTotalRange": 53.15,
|
||||
"unladenFastestRange": 53.15,
|
||||
"ladenFastestRange": 53.15,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 489.6
|
||||
}
|
||||
@@ -1362,8 +1362,8 @@
|
||||
"unladenRange": 24.25,
|
||||
"fullTankRange": 23.73,
|
||||
"ladenRange": 23.73,
|
||||
"unladenTotalRange": 84.56,
|
||||
"ladenTotalRange": 84.56,
|
||||
"unladenFastestRange": 84.56,
|
||||
"ladenFastestRange": 84.56,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 0
|
||||
}
|
||||
@@ -1501,8 +1501,8 @@
|
||||
"unladenRange": 19.51,
|
||||
"fullTankRange": 18.58,
|
||||
"ladenRange": 13.09,
|
||||
"unladenTotalRange": 152.32,
|
||||
"ladenTotalRange": 106.49,
|
||||
"unladenFastestRange": 152.32,
|
||||
"ladenFastestRange": 106.49,
|
||||
"maxJumpCount": 8,
|
||||
"shieldStrength": 170.57
|
||||
}
|
||||
@@ -1639,8 +1639,8 @@
|
||||
"unladenRange": 28.25,
|
||||
"fullTankRange": 26.6,
|
||||
"ladenRange": 16.67,
|
||||
"unladenTotalRange": 183.67,
|
||||
"ladenTotalRange": 113.69,
|
||||
"unladenFastestRange": 183.67,
|
||||
"ladenFastestRange": 113.69,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 214.26
|
||||
}
|
||||
@@ -1810,8 +1810,8 @@
|
||||
"unladenRange": 20.32,
|
||||
"fullTankRange": 19.46,
|
||||
"ladenRange": 14.65,
|
||||
"unladenTotalRange": 133.17,
|
||||
"ladenTotalRange": 99.65,
|
||||
"unladenFastestRange": 133.17,
|
||||
"ladenFastestRange": 99.65,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 486.35
|
||||
}
|
||||
@@ -1989,8 +1989,8 @@
|
||||
"unladenRange": 14.32,
|
||||
"fullTankRange": 13.89,
|
||||
"ladenRange": 13.46,
|
||||
"unladenTotalRange": 94.42,
|
||||
"ladenTotalRange": 91.49,
|
||||
"unladenFastestRange": 94.42,
|
||||
"ladenFastestRange": 91.49,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 645.57
|
||||
}
|
||||
@@ -2188,7 +2188,7 @@
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"group": "FSD Interdictor"
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2219,8 +2219,8 @@
|
||||
"unladenRange": 16.99,
|
||||
"fullTankRange": 16.68,
|
||||
"ladenRange": 15.91,
|
||||
"unladenTotalRange": 67.35,
|
||||
"ladenTotalRange": 64.2,
|
||||
"unladenFastestRange": 67.35,
|
||||
"ladenFastestRange": 64.2,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 952
|
||||
}
|
||||
@@ -2374,8 +2374,8 @@
|
||||
"unladenRange": 39.26,
|
||||
"fullTankRange": 37.65,
|
||||
"ladenRange": 21.21,
|
||||
"unladenTotalRange": 153.79,
|
||||
"ladenTotalRange": 85.82,
|
||||
"unladenFastestRange": 153.79,
|
||||
"ladenFastestRange": 85.82,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 372.98
|
||||
}
|
||||
@@ -2530,8 +2530,8 @@
|
||||
"unladenRange": 38.44,
|
||||
"fullTankRange": 36.89,
|
||||
"ladenRange": 21.04,
|
||||
"unladenTotalRange": 150.62,
|
||||
"ladenTotalRange": 85.16,
|
||||
"unladenFastestRange": 150.62,
|
||||
"ladenFastestRange": 85.16,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 372.98
|
||||
}
|
||||
@@ -2698,8 +2698,8 @@
|
||||
"unladenRange": 38.04,
|
||||
"fullTankRange": 30.11,
|
||||
"ladenRange": 23.03,
|
||||
"unladenTotalRange": 675.7,
|
||||
"ladenTotalRange": 501.97,
|
||||
"unladenFastestRange": 675.7,
|
||||
"ladenFastestRange": 501.97,
|
||||
"maxJumpCount": 20,
|
||||
"shieldStrength": 372.98
|
||||
}
|
||||
@@ -2885,7 +2885,7 @@
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"group": "FSD Interdictor"
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2916,8 +2916,8 @@
|
||||
"unladenRange": 18.49,
|
||||
"fullTankRange": 18.12,
|
||||
"ladenRange": 16.39,
|
||||
"unladenTotalRange": 73.21,
|
||||
"ladenTotalRange": 66.15,
|
||||
"unladenFastestRange": 73.21,
|
||||
"ladenFastestRange": 66.15,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 833
|
||||
}
|
||||
@@ -3044,8 +3044,8 @@
|
||||
"unladenRange": 35.99,
|
||||
"fullTankRange": 33.36,
|
||||
"ladenRange": 33.36,
|
||||
"unladenTotalRange": 232.28,
|
||||
"ladenTotalRange": 232.28,
|
||||
"unladenFastestRange": 232.28,
|
||||
"ladenFastestRange": 232.28,
|
||||
"maxJumpCount": 7,
|
||||
"shieldStrength": 92.25
|
||||
}
|
||||
@@ -3145,7 +3145,7 @@
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "A",
|
||||
"group": "FSD Interdictor"
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
@@ -3181,8 +3181,8 @@
|
||||
"unladenRange": 15.06,
|
||||
"fullTankRange": 14.86,
|
||||
"ladenRange": 14.86,
|
||||
"unladenTotalRange": 42.5,
|
||||
"ladenTotalRange": 42.5,
|
||||
"unladenFastestRange": 42.5,
|
||||
"ladenFastestRange": 42.5,
|
||||
"maxJumpCount": 3,
|
||||
"shieldStrength": 548.74
|
||||
}
|
||||
@@ -3335,8 +3335,8 @@
|
||||
"unladenRange": 12.51,
|
||||
"fullTankRange": 12.38,
|
||||
"ladenRange": 12.38,
|
||||
"unladenTotalRange": 35.35,
|
||||
"ladenTotalRange": 35.35,
|
||||
"unladenFastestRange": 35.35,
|
||||
"ladenFastestRange": 35.35,
|
||||
"maxJumpCount": 3,
|
||||
"shieldStrength": 760.16
|
||||
}
|
||||
@@ -3348,8 +3348,8 @@
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "http://localhost:3300/outfit/eagle/42A3A3A1D2A2A2C0p0p24-40532j.AwRj49iA.AwgsIkEZigmIA%3D%3D%3D?bn=Figther",
|
||||
"code": "42A3A3A1D2A2A2C0p0p24-40532j.AwRj49iA.AwgsIkEZigmIA===",
|
||||
"url": "http://localhost:3300/outfit/eagle/42A3A3A1D2A2A2C0p0p24-40532j-.Iw1-EA==.Aw1-EA==?bn=Figther",
|
||||
"code": "42A3A3A1D2A2A2C0p0p24-40532j-.Iw1-EA==.Aw1-EA==",
|
||||
"shipId": "eagle"
|
||||
}
|
||||
],
|
||||
@@ -3423,7 +3423,8 @@
|
||||
"class": 1,
|
||||
"rating": "A",
|
||||
"group": "Fuel Scoop"
|
||||
}
|
||||
},
|
||||
null
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
@@ -3453,8 +3454,8 @@
|
||||
"unladenRange": 17.12,
|
||||
"fullTankRange": 16.71,
|
||||
"ladenRange": 16.71,
|
||||
"unladenTotalRange": 42.4,
|
||||
"ladenTotalRange": 42.4,
|
||||
"unladenFastestRange": 42.4,
|
||||
"ladenFastestRange": 42.4,
|
||||
"maxJumpCount": 3,
|
||||
"shieldStrength": 102
|
||||
}
|
||||
@@ -3611,8 +3612,8 @@
|
||||
"unladenRange": 8.43,
|
||||
"fullTankRange": 8.09,
|
||||
"ladenRange": 7.25,
|
||||
"unladenTotalRange": 81.5,
|
||||
"ladenTotalRange": 72.9,
|
||||
"unladenFastestRange": 81.5,
|
||||
"ladenFastestRange": 72.9,
|
||||
"maxJumpCount": 10,
|
||||
"shieldStrength": 299.48
|
||||
}
|
||||
225
__tests__/test-import.js
Normal file
@@ -0,0 +1,225 @@
|
||||
jest.dontMock('../src/app/stores/Persist');
|
||||
jest.dontMock('../src/app/components/TranslatedComponent');
|
||||
jest.dontMock('../src/app/components/ModalImport');
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import TU from 'react-testutils-additions';
|
||||
import Utils from './testUtils';
|
||||
import { getLanguage } from '../src/app/i18n/Language';
|
||||
|
||||
describe('Import Modal', function() {
|
||||
|
||||
let MockRouter = require('../src/app/Router').default;
|
||||
const Persist = require('../src/app/stores/Persist').default;
|
||||
const ModalImport = require('../src/app/components/ModalImport').default;
|
||||
const mockContext = {
|
||||
language: getLanguage('en'),
|
||||
sizeRatio: 1,
|
||||
openMenu: jest.genMockFunction(),
|
||||
closeMenu: jest.genMockFunction(),
|
||||
showModal: jest.genMockFunction(),
|
||||
hideModal: jest.genMockFunction(),
|
||||
tooltip: jest.genMockFunction(),
|
||||
termtip: jest.genMockFunction(),
|
||||
onWindowResize: jest.genMockFunction()
|
||||
};
|
||||
|
||||
let modal, render, ContextProvider = Utils.createContextProvider(mockContext);
|
||||
|
||||
/**
|
||||
* Clear saved builds, and reset React DOM
|
||||
*/
|
||||
function reset() {
|
||||
MockRouter.go.mockClear();
|
||||
Persist.deleteAll();
|
||||
render = TU.renderIntoDocument(<ContextProvider><ModalImport /></ContextProvider>);
|
||||
modal = TU.findRenderedComponentWithType(render, ModalImport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate user import text entry / paste
|
||||
* @param {string} text Import text / raw data
|
||||
*/
|
||||
function pasteText(text) {
|
||||
let textarea = TU.findRenderedDOMComponentWithTag(render, 'textarea');
|
||||
TU.Simulate.change(textarea, { target: { value: text } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate click on Proceed button
|
||||
*/
|
||||
function clickProceed() {
|
||||
let proceedButton = TU.findRenderedDOMComponentWithId(render, 'proceed');
|
||||
TU.Simulate.click(proceedButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate click on Import button
|
||||
*/
|
||||
function clickImport() {
|
||||
let importButton = TU.findRenderedDOMComponentWithId(render, 'import');
|
||||
TU.Simulate.click(importButton);
|
||||
}
|
||||
|
||||
describe('Import Backup', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid backup', function() {
|
||||
let importData = require('./fixtures/valid-backup');
|
||||
let importString = JSON.stringify(importData);
|
||||
|
||||
expect(modal.state.importValid).toEqual(false);
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
pasteText(importString);
|
||||
expect(modal.state.importValid).toBe(true);
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
expect(modal.state.builds).toEqual(importData.builds);
|
||||
expect(modal.state.comparisons).toEqual(importData.comparisons);
|
||||
expect(modal.state.shipDiscount).toEqual(importData.discounts[0]);
|
||||
expect(modal.state.moduleDiscount).toEqual(importData.discounts[1]);
|
||||
expect(modal.state.insurance).toBe(importData.insurance.toLowerCase());
|
||||
clickProceed();
|
||||
expect(modal.state.processed).toBe(true);
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
clickImport();
|
||||
expect(Persist.getBuilds()).toEqual(importData.builds);
|
||||
expect(Persist.getComparisons()).toEqual(importData.comparisons);
|
||||
expect(Persist.getInsurance()).toEqual(importData.insurance.toLowerCase());
|
||||
expect(Persist.getShipDiscount()).toEqual(importData.discounts[0]);
|
||||
expect(Persist.getModuleDiscount()).toEqual(importData.discounts[1]);
|
||||
});
|
||||
|
||||
it('imports an old valid backup', function() {
|
||||
const importData = require('./fixtures/old-valid-export');
|
||||
const importStr = JSON.stringify(importData);
|
||||
|
||||
pasteText(importStr);
|
||||
expect(modal.state.builds).toEqual(importData.builds);
|
||||
expect(modal.state.importValid).toBe(true);
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
clickProceed();
|
||||
expect(modal.state.processed).toBeTruthy();
|
||||
clickImport();
|
||||
expect(Persist.getBuilds()).toEqual(importData.builds);
|
||||
});
|
||||
|
||||
it('catches an invalid backup', function() {
|
||||
const importData = require('./fixtures/valid-backup');
|
||||
let invalidImportData = Object.assign({}, importData);
|
||||
invalidImportData.builds.asp = null; // Remove Asp Miner build used in comparison
|
||||
|
||||
pasteText('"this is not valid"');
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Must be an object or array!');
|
||||
pasteText('{ "builds": "Should not be a string" }');
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('builds must be an object!');
|
||||
pasteText(JSON.stringify(importData).replace('anaconda', 'invalid_ship'));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('"invalid_ship" is not a valid Ship Id!');
|
||||
pasteText(JSON.stringify(importData).replace('Dream', ''));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Imperial Clipper build "" must be a string at least 1 character long!');
|
||||
pasteText(JSON.stringify(invalidImportData));
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('asp build "Miner" data is missing!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Detailed Build', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid v3 build', function() {
|
||||
const importData = require('./fixtures/anaconda-test-detailed-export-v3');
|
||||
pasteText(JSON.stringify(importData));
|
||||
|
||||
expect(modal.state.importValid).toBeTruthy();
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
expect(modal.state.singleBuild).toBe(true);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/anaconda/4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA?bn=Test%20My%20Ship');
|
||||
});
|
||||
|
||||
it('catches an invalid build', function() {
|
||||
const importData = require('./fixtures/anaconda-test-detailed-export-v3');
|
||||
pasteText(JSON.stringify(importData).replace('components', 'comps'));
|
||||
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Anaconda Build "Test My Ship": Invalid data');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Detaild Builds Array', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports all builds', function() {
|
||||
const importData = require('./fixtures/valid-detailed-export');
|
||||
const expectedBuilds = require('./fixtures/expected-builds');
|
||||
|
||||
pasteText(JSON.stringify(importData));
|
||||
expect(modal.state.importValid).toBeTruthy();
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
clickProceed();
|
||||
expect(modal.state.processed).toBeTruthy();
|
||||
clickImport();
|
||||
|
||||
let builds = Persist.getBuilds();
|
||||
|
||||
for (let s in builds) {
|
||||
for (let b in builds[s]) {
|
||||
expect(builds[s][b]).toEqual(expectedBuilds[s][b]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import E:D Shipyard Builds', function() {
|
||||
|
||||
it('imports a valid builds', function() {
|
||||
const imports = require('./fixtures/ed-shipyard-import-valid');
|
||||
|
||||
for (let i = 0; i < imports.length; i++ ) {
|
||||
reset();
|
||||
let fixture = imports[i];
|
||||
pasteText(fixture.buildText);
|
||||
expect(modal.state.importValid).toBeTruthy();
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
clickProceed();
|
||||
expect(MockRouter.go.mock.calls.length).toBe(1);
|
||||
expect(MockRouter.go.mock.calls[0][0]).toBe('/outfit/' + fixture.shipId + '/' + fixture.buildCode + '?bn=' + encodeURIComponent(fixture.buildName));
|
||||
}
|
||||
});
|
||||
|
||||
it('catches invalid builds', function() {
|
||||
const imports = require('./fixtures/ed-shipyard-import-invalid');
|
||||
|
||||
for (let i = 0; i < imports.length; i++ ) {
|
||||
reset();
|
||||
pasteText(imports[i].buildText);
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual(imports[i].errorMsg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Imports from a Comparison', function() {
|
||||
|
||||
it('imports a valid comparison', function() {
|
||||
const importBuilds = require('./fixtures/valid-backup').builds;
|
||||
Persist.deleteAll();
|
||||
render = TU.renderIntoDocument(<ContextProvider><ModalImport builds={importBuilds} /></ContextProvider>);
|
||||
modal = TU.findRenderedComponentWithType(render, ModalImport);
|
||||
|
||||
expect(modal.state.processed).toBe(true);
|
||||
expect(modal.state.errorMsg).toEqual(null);
|
||||
clickImport();
|
||||
expect(Persist.getBuilds()).toEqual(importBuilds);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
143
__tests__/test-persist.js
Normal file
@@ -0,0 +1,143 @@
|
||||
jest.dontMock('../src/app/stores/Persist');
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import TU from 'react-testutils-additions';
|
||||
|
||||
let origAddEventListener = window.addEventListener;
|
||||
let storageListener;
|
||||
let ls = {};
|
||||
|
||||
// Implment mock localStorage
|
||||
let localStorage = {
|
||||
getItem: function(key) {
|
||||
return ls[key];
|
||||
},
|
||||
setItem: function(key, value) {
|
||||
ls[key] = value;
|
||||
},
|
||||
removeItem: function(key) {
|
||||
delete ls[key];
|
||||
},
|
||||
clear: function() {
|
||||
ls = {};
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener = function(eventName, listener) {
|
||||
|
||||
if(eventName == 'storage') {
|
||||
storageListener = listener; // Keep track of latest storage listener
|
||||
} else {
|
||||
origAddEventListener.apply(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Persist', function() {
|
||||
|
||||
const Persist = require('../src/app/stores/Persist').Persist;
|
||||
|
||||
describe('Multi tab/window', function() {
|
||||
it("syncs builds", function() {
|
||||
window.localStorage = localStorage;
|
||||
ls = {};
|
||||
let p = new Persist();
|
||||
let newBuilds = {
|
||||
anaconda: { test: '1234' }
|
||||
};
|
||||
|
||||
storageListener({ key: 'builds', newValue: JSON.stringify(newBuilds) });
|
||||
expect(p.getBuild('anaconda', 'test')).toBe('1234');
|
||||
});
|
||||
});
|
||||
|
||||
describe('General and Settings', function() {
|
||||
it("has defaults", function() {
|
||||
window.localStorage = localStorage;
|
||||
ls = {};
|
||||
let p = new Persist();
|
||||
expect(p.getLangCode()).toBe('en');
|
||||
expect(p.showTooltips()).toBe(true);
|
||||
expect(p.getInsurance()).toBe('standard');
|
||||
expect(p.getShipDiscount()).toBe(0);
|
||||
expect(p.getModuleDiscount()).toBe(0);
|
||||
expect(p.getSizeRatio()).toBe(1);
|
||||
});
|
||||
|
||||
it("loads from localStorage correctly", function() {
|
||||
window.localStorage = localStorage;
|
||||
let savedData = require('./fixtures/valid-backup');
|
||||
ls = {};
|
||||
ls.builds = JSON.stringify(savedData.builds);
|
||||
ls.NG_TRANSLATE_LANG_KEY = 'de';
|
||||
ls.insurance = 'Standard';
|
||||
ls.shipDiscount = 0.25;
|
||||
ls.moduleDiscount = 0.15;
|
||||
let p = new Persist();
|
||||
|
||||
expect(p.getInsurance()).toBe('standard');
|
||||
expect(p.getShipDiscount()).toBe(0.25);
|
||||
expect(p.getModuleDiscount()).toBe(0.15);
|
||||
expect(p.getLangCode()).toEqual('de');
|
||||
expect(p.getBuilds('anaconda')).toEqual(savedData.builds.anaconda);
|
||||
expect(p.getBuilds('python')).toEqual(savedData.builds.python);
|
||||
expect(p.getBuildsNamesFor('imperial_clipper')).toEqual(['Cargo', 'Current', 'Dream', 'Multi-purpose']);
|
||||
expect(p.getBuild('type_7_transport', 'Cargo')).toEqual('02A5D5A4D3D3D5C--------0505040403480101');
|
||||
});
|
||||
|
||||
it("uses defaults from a corrupted localStorage", function() {
|
||||
window.localStorage = localStorage;
|
||||
ls = {};
|
||||
ls.builds = "not valid json";
|
||||
ls.comparisons = "1, 3, 4";
|
||||
ls.insurance = 'this insurance does not exist';
|
||||
ls.shipDiscount = 'this is not a number';
|
||||
ls.moduleDiscount = 10; // Way to big
|
||||
|
||||
let p = new Persist();
|
||||
expect(p.getLangCode()).toBe('en');
|
||||
expect(p.showTooltips()).toBe(true);
|
||||
expect(p.getInsurance()).toBe('standard');
|
||||
expect(p.getShipDiscount()).toBe(0);
|
||||
expect(p.getModuleDiscount()).toBe(0);
|
||||
expect(p.getBuilds()).toEqual({});
|
||||
expect(p.getComparisons()).toEqual({});
|
||||
});
|
||||
|
||||
it("works without localStorage", function() {
|
||||
window.localStorage = null;
|
||||
let p = new Persist();
|
||||
expect(p.getLangCode()).toBe('en');
|
||||
expect(p.showTooltips()).toBe(true);
|
||||
expect(p.getInsurance()).toBe('standard');
|
||||
expect(p.getShipDiscount()).toBe(0);
|
||||
expect(p.getModuleDiscount()).toBe(0);
|
||||
expect(p.getSizeRatio()).toBe(1);
|
||||
|
||||
p.saveBuild('anaconda', 'test', '12345');
|
||||
expect(p.getBuild('anaconda', 'test')).toBe('12345');
|
||||
|
||||
p.deleteBuild('anaconda', 'test');
|
||||
expect(p.hasBuilds()).toBe(false);
|
||||
});
|
||||
|
||||
it("generates the backup", function() {
|
||||
window.localStorage = localStorage;
|
||||
let savedData = require('./fixtures/valid-backup');
|
||||
ls = {};
|
||||
ls.builds = JSON.stringify(savedData.builds);
|
||||
ls.insurance = 'Beta';
|
||||
ls.shipDiscount = 0.25;
|
||||
ls.moduleDiscount = 0.15;
|
||||
|
||||
let p = new Persist();
|
||||
let backup = p.getAll();
|
||||
|
||||
expect(backup.insurance).toBe('beta');
|
||||
expect(backup.shipDiscount).toBe(0.25);
|
||||
expect(backup.moduleDiscount).toBe(0.15);
|
||||
expect(backup.builds).toEqual(savedData.builds);
|
||||
expect(backup.comparisons).toEqual({});
|
||||
});
|
||||
});
|
||||
})
|
||||
63
__tests__/test-serializer.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import Ship from '../src/app/shipyard/Ship';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import * as Serializer from '../src/app/shipyard/Serializer';
|
||||
import jsen from 'jsen';
|
||||
|
||||
describe("Serializer", function() {
|
||||
const anacondaTestExport = require.requireActual('./fixtures/anaconda-test-detailed-export-v3');
|
||||
const code = anacondaTestExport.references[0].code;
|
||||
const anaconda = Ships.anaconda;
|
||||
const validate = jsen(require('../src/schemas/ship-loadout/3'));
|
||||
|
||||
describe("To Detailed Build", function() {
|
||||
let testBuild = new Ship('anaconda', anaconda.properties, anaconda.slots).buildFrom(code);
|
||||
let exportData = Serializer.toDetailedBuild('Test My Ship', testBuild);
|
||||
|
||||
it("conforms to the v3 ship-loadout schema", function() {
|
||||
expect(validate(exportData)).toBe(true);
|
||||
});
|
||||
|
||||
it("contains the correct components and stats", function() {
|
||||
expect(exportData.components).toEqual(anacondaTestExport.components);
|
||||
expect(exportData.stats).toEqual(anacondaTestExport.stats);
|
||||
expect(exportData.ship).toEqual(anacondaTestExport.ship);
|
||||
expect(exportData.name).toEqual(anacondaTestExport.name);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("Export Detailed Builds", function() {
|
||||
const expectedExport = require('./fixtures/valid-detailed-export');
|
||||
const builds = require('./fixtures/expected-builds');
|
||||
const exportData = Serializer.toDetailedExport(builds);
|
||||
|
||||
it("conforms to the v3 ship-loadout schema", function() {
|
||||
expect(exportData instanceof Array).toBe(true);
|
||||
|
||||
for (let detailedBuild of exportData) {
|
||||
expect(validate(detailedBuild)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("From Detailed Build", function() {
|
||||
|
||||
it("builds the ship correctly", function() {
|
||||
let testBuildA = new Ship('anaconda', anaconda.properties, anaconda.slots);
|
||||
testBuildA.buildFrom(code);
|
||||
let testBuildB = Serializer.fromDetailedBuild(anacondaTestExport);
|
||||
|
||||
for(var p in testBuildB) {
|
||||
if (p == 'availCS') {
|
||||
continue;
|
||||
}
|
||||
expect(testBuildB[p]).toEqual(testBuildA[p], p + ' does not match');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -1,48 +1,45 @@
|
||||
describe("Ship Factory", function() {
|
||||
import Ship from '../src/app/shipyard/Ship';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
|
||||
|
||||
var Ship;
|
||||
var Components;
|
||||
|
||||
beforeEach(module('shipyard'));
|
||||
beforeEach(inject(['Ship', 'Components', function (_Ship_, _Components_) {
|
||||
Ship = _Ship_;
|
||||
Components = _Components_;
|
||||
}]));
|
||||
describe("Ship", function() {
|
||||
|
||||
it("can build all ships", function() {
|
||||
for (var s in DB.ships) {
|
||||
var shipData = DB.ships[s];
|
||||
var ship = new Ship(s, shipData.properties, shipData.slots);
|
||||
for (let s in Ships) {
|
||||
let shipData = Ships[s];
|
||||
let ship = new Ship(s, shipData.properties, shipData.slots);
|
||||
|
||||
for (p in shipData.properties) {
|
||||
for (let p in shipData.properties) {
|
||||
expect(ship[p]).toEqual(shipData.properties[p], s + ' property [' + p + '] does not match when built');
|
||||
}
|
||||
|
||||
ship.buildWith(shipData.defaults);
|
||||
|
||||
expect(ship.totalCost).toEqual(shipData.retailCost, s + ' retail cost does not match default build cost');
|
||||
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' cargo');
|
||||
expect(ship.cargoCapacity).toBeDefined(s + ' cargo');
|
||||
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' priorityBands');
|
||||
expect(ship.powerAvailable).toBeGreaterThan(0, s + ' powerAvailable');
|
||||
expect(ship.unladenRange).toBeGreaterThan(0, s + ' unladenRange');
|
||||
expect(ship.ladenRange).toBeGreaterThan(0, s + ' ladenRange');
|
||||
expect(ship.fuelCapacity).toBeGreaterThan(0, s + ' fuelCapacity');
|
||||
expect(ship.unladenTotalRange).toBeGreaterThan(0, s + ' unladenTotalRange');
|
||||
expect(ship.ladenTotalRange).toBeGreaterThan(0, s + ' ladenTotalRange');
|
||||
expect(ship.unladenFastestRange).toBeGreaterThan(0, s + ' unladenFastestRange');
|
||||
expect(ship.ladenFastestRange).toBeGreaterThan(0, s + ' ladenFastestRange');
|
||||
expect(ship.shieldStrength).toBeGreaterThan(0, s + ' shieldStrength');
|
||||
expect(ship.armour).toBeGreaterThan(0, s + ' armour');
|
||||
expect(ship.topSpeed).toBeGreaterThan(0, s + ' topSpeed');
|
||||
}
|
||||
});
|
||||
|
||||
it("resets and rebuilds properly", function() {
|
||||
var id = 'cobra_mk_iii';
|
||||
var cobra = DB.ships[id];
|
||||
var cobra = Ships[id];
|
||||
var shipA = new Ship(id, cobra.properties, cobra.slots);
|
||||
var shipB = new Ship(id, cobra.properties, cobra.slots);
|
||||
var testShip = new Ship(id, cobra.properties, cobra.slots);
|
||||
|
||||
var buildA = cobra.defaults;
|
||||
var buildB = {
|
||||
common:['4A', '4A', '4A', '3D', '3A', '3A', '4C'],
|
||||
standard:['4A', '4A', '4A', '3D', '3A', '3A', '4C'],
|
||||
hardpoints: ['0s', '0s', '2d', '2d', 0, '04'],
|
||||
internal: ['45', '03', '2b', '2o', '27', '53']
|
||||
};
|
||||
@@ -52,102 +49,108 @@ describe("Ship Factory", function() {
|
||||
testShip.buildWith(buildA);
|
||||
|
||||
for(var p in testShip) {
|
||||
if (p == 'availCS') {
|
||||
continue;
|
||||
}
|
||||
expect(testShip[p]).toEqual(shipA[p], p + ' does not match');
|
||||
}
|
||||
|
||||
testShip.buildWith(buildB);
|
||||
|
||||
for(var p in testShip) {
|
||||
if (p == 'availCS') {
|
||||
continue;
|
||||
}
|
||||
expect(testShip[p]).toEqual(shipB[p], p + ' does not match');
|
||||
}
|
||||
|
||||
testShip.buildWith(buildA);
|
||||
|
||||
for(var p in testShip) {
|
||||
if (p == 'availCS') {
|
||||
continue;
|
||||
}
|
||||
expect(testShip[p]).toEqual(shipA[p], p + ' does not match');
|
||||
}
|
||||
});
|
||||
|
||||
it("discounts hull and components properly", function() {
|
||||
var id = 'cobra_mk_iii';
|
||||
var cobra = DB.ships[id];
|
||||
var cobra = Ships[id];
|
||||
var testShip = new Ship(id, cobra.properties, cobra.slots);
|
||||
testShip.buildWith(cobra.defaults);
|
||||
|
||||
var originalHullCost = testShip.hullCost;
|
||||
var originalTotalCost = testShip.totalCost;
|
||||
var discount = 0.9;
|
||||
var discount = 0.1;
|
||||
|
||||
expect(testShip.c.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
|
||||
expect(testShip.m.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
|
||||
|
||||
testShip.applyDiscounts(discount, discount);
|
||||
|
||||
// Floating point errors cause miniscule decimal places which are handled in the app by rounding/formatting
|
||||
|
||||
expect(Math.floor(testShip.c.discountedCost)).toEqual(Math.floor(originalHullCost * discount), 'Discounted Hull cost does not match');
|
||||
expect(Math.floor(testShip.totalCost)).toEqual(Math.floor(originalTotalCost * discount), 'Discounted Total cost does not match');
|
||||
expect(Math.floor(testShip.m.discountedCost)).toEqual(Math.floor(originalHullCost * (1 - discount)), 'Discounted Hull cost does not match');
|
||||
expect(Math.floor(testShip.totalCost)).toEqual(Math.floor(originalTotalCost * (1 - discount)), 'Discounted Total cost does not match');
|
||||
|
||||
testShip.applyDiscounts(1, 1); // No discount, 100% of cost
|
||||
testShip.applyDiscounts(0, 0); // No discount, 100% of cost
|
||||
|
||||
expect(testShip.c.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
|
||||
expect(testShip.m.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
|
||||
expect(testShip.totalCost).toEqual(originalTotalCost, 'Total cost does not match');
|
||||
|
||||
testShip.applyDiscounts(discount, 1); // Only discount hull
|
||||
testShip.applyDiscounts(discount, 0); // Only discount hull
|
||||
|
||||
expect(Math.floor(testShip.c.discountedCost)).toEqual(Math.round(originalHullCost * discount), 'Discounted Hull cost does not match');
|
||||
expect(testShip.totalCost).toEqual(originalTotalCost - originalHullCost + testShip.c.discountedCost, 'Total cost does not match');
|
||||
expect(Math.floor(testShip.m.discountedCost)).toEqual(Math.round(originalHullCost * (1 - discount)), 'Discounted Hull cost does not match');
|
||||
expect(testShip.totalCost).toEqual(originalTotalCost - originalHullCost + testShip.m.discountedCost, 'Total cost does not match');
|
||||
|
||||
});
|
||||
|
||||
it("enforces a single shield generator", function() {
|
||||
var id = 'anaconda';
|
||||
var anacondaData = DB.ships[id];
|
||||
var anacondaData = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
expect(anaconda.internal[2].c.grp).toEqual('sg', 'Anaconda default shield generator slot');
|
||||
expect(anaconda.internal[2].m.grp).toEqual('sg', 'Anaconda default shield generator slot');
|
||||
|
||||
anaconda.use(anaconda.internal[1], '4j', Components.internal('4j')); // 6E Shield Generator
|
||||
anaconda.use(anaconda.internal[1], ModuleUtils.internal('4j')); // 6E Shield Generator
|
||||
|
||||
expect(anaconda.internal[2].c).toEqual(null, 'Anaconda default shield generator slot is empty');
|
||||
expect(anaconda.internal[2].id).toEqual(null, 'Anaconda default shield generator slot id is null');
|
||||
expect(anaconda.internal[1].id).toEqual('4j', 'Slot 1 should have SG 4j in it');
|
||||
expect(anaconda.internal[1].c.grp).toEqual('sg','Slot 1 should have SG 4j in it');
|
||||
expect(anaconda.internal[2].m).toEqual(null, 'Anaconda default shield generator slot is empty');
|
||||
expect(anaconda.internal[1].m.id).toEqual('4j', 'Slot 1 should have SG 4j in it');
|
||||
expect(anaconda.internal[1].m.grp).toEqual('sg','Slot 1 should have SG 4j in it');
|
||||
|
||||
});
|
||||
|
||||
it("enforces a single shield fuel scoop", function() {
|
||||
var id = 'anaconda';
|
||||
var anacondaData = DB.ships[id];
|
||||
var anacondaData = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
anaconda.use(anaconda.internal[4], '32', Components.internal('32')); // 4A Fuel Scoop
|
||||
expect(anaconda.internal[4].c.grp).toEqual('fs', 'Anaconda fuel scoop slot');
|
||||
anaconda.use(anaconda.internal[4], ModuleUtils.internal('32')); // 4A Fuel Scoop
|
||||
expect(anaconda.internal[4].m.grp).toEqual('fs', 'Anaconda fuel scoop slot');
|
||||
|
||||
anaconda.use(anaconda.internal[3], '32', Components.internal('32'));
|
||||
anaconda.use(anaconda.internal[3], ModuleUtils.internal('32'));
|
||||
|
||||
expect(anaconda.internal[4].c).toEqual(null, 'Anaconda original fuel scoop slot is empty');
|
||||
expect(anaconda.internal[4].id).toEqual(null, 'Anaconda original fuel scoop slot id is null');
|
||||
expect(anaconda.internal[3].id).toEqual('32', 'Slot 1 should have FS 32 in it');
|
||||
expect(anaconda.internal[3].c.grp).toEqual('fs','Slot 1 should have FS 32 in it');
|
||||
expect(anaconda.internal[4].m).toEqual(null, 'Anaconda original fuel scoop slot is empty');
|
||||
expect(anaconda.internal[3].m.id).toEqual('32', 'Slot 1 should have FS 32 in it');
|
||||
expect(anaconda.internal[3].m.grp).toEqual('fs','Slot 1 should have FS 32 in it');
|
||||
});
|
||||
|
||||
it("enforces a single refinery", function() {
|
||||
var id = 'anaconda';
|
||||
var anacondaData = DB.ships[id];
|
||||
var anacondaData = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
anaconda.use(anaconda.internal[4], '23', Components.internal('23')); // 4E Refinery
|
||||
expect(anaconda.internal[4].c.grp).toEqual('rf', 'Anaconda refinery slot');
|
||||
anaconda.use(anaconda.internal[4], ModuleUtils.internal('23')); // 4E Refinery
|
||||
expect(anaconda.internal[4].m.grp).toEqual('rf', 'Anaconda refinery slot');
|
||||
|
||||
anaconda.use(anaconda.internal[3], '23', Components.internal('23'));
|
||||
anaconda.use(anaconda.internal[3], ModuleUtils.internal('23'));
|
||||
|
||||
expect(anaconda.internal[4].c).toEqual(null, 'Anaconda original refinery slot is empty');
|
||||
expect(anaconda.internal[4].id).toEqual(null, 'Anaconda original refinery slot id is null');
|
||||
expect(anaconda.internal[3].id).toEqual('23', 'Slot 1 should have RF 23 in it');
|
||||
expect(anaconda.internal[3].c.grp).toEqual('rf','Slot 1 should have RF 23 in it');
|
||||
expect(anaconda.internal[4].m).toEqual(null, 'Anaconda original refinery slot is empty');
|
||||
expect(anaconda.internal[3].m.id).toEqual('23', 'Slot 1 should have RF 23 in it');
|
||||
expect(anaconda.internal[3].m.grp).toEqual('rf','Slot 1 should have RF 23 in it');
|
||||
});
|
||||
|
||||
});
|
||||
24
__tests__/testUtils.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import React from 'react';
|
||||
|
||||
const TestUtils = {
|
||||
createContextProvider: function(context) {
|
||||
var _contextTypes = {};
|
||||
|
||||
Object.keys(context).forEach(function(key) {
|
||||
_contextTypes[key] = React.PropTypes.any;
|
||||
});
|
||||
|
||||
return React.createClass({
|
||||
displayName: 'ContextProvider',
|
||||
childContextTypes: _contextTypes,
|
||||
getChildContext() { return context; },
|
||||
|
||||
render() {
|
||||
return React.Children.only(this.props.children);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export default TestUtils;
|
||||
@@ -1,397 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="orbitronregular" horiz-adv-x="1695" >
|
||||
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||
<missing-glyph horiz-adv-x="557" />
|
||||
<glyph horiz-adv-x="0" />
|
||||
<glyph unicode="
" horiz-adv-x="681" />
|
||||
<glyph unicode=" " horiz-adv-x="557" />
|
||||
<glyph unicode="	" horiz-adv-x="557" />
|
||||
<glyph unicode=" " horiz-adv-x="557" />
|
||||
<glyph unicode="!" horiz-adv-x="450" d="M119 0v168h168v-168h-168zM119 416v1059h168v-1059h-168z" />
|
||||
<glyph unicode=""" horiz-adv-x="761" d="M121 1188v287h168v-287h-168zM438 1188v287h168v-287h-168z" />
|
||||
<glyph unicode="#" horiz-adv-x="1632" d="M66 350v168h260l145 451h-340v168h393l115 336h166l-117 -336h535l114 336h166l-117 -336h197v-168h-248l-145 -451h326v-168h-379l-109 -350h-168l111 350h-533l-108 -350h-168l110 350h-206zM494 518h530l145 451h-532z" />
|
||||
<glyph unicode="$" horiz-adv-x="1613" d="M70 248v59h168v-59q0 -33 23.5 -56.5t55.5 -23.5h414v487h-414q-102 0 -174.5 72t-72.5 176v324q0 104 72.5 177t174.5 73h414v233h168v-233h412q104 0 177 -73t73 -177v-58h-170v58q0 33 -24 56.5t-56 23.5h-412v-484h412q104 0 177 -72.5t73 -175.5v-327 q0 -102 -73 -175t-177 -73h-412v-233h-168v233h-414q-102 0 -174.5 72.5t-72.5 175.5zM238 903q0 -33 23.5 -56.5t55.5 -23.5h414v484h-414q-33 0 -56 -23.5t-23 -56.5v-324zM899 168h412q33 0 56.5 23.5t23.5 56.5v327q0 33 -23.5 56.5t-56.5 23.5h-412v-487z" />
|
||||
<glyph unicode="%" horiz-adv-x="1978" d="M98 1053v172q0 104 73 177t177 73h193q104 0 177 -73t73 -177v-172q0 -102 -73 -175t-177 -73h-193q-104 0 -177 72.5t-73 175.5zM223 1010q0 -33 23.5 -56.5t56.5 -23.5h283q33 0 56.5 23.5t23.5 56.5v258q0 33 -24 56.5t-56 23.5h-283q-33 0 -56.5 -24t-23.5 -56v-258z M281 0v221l1491 1256v-220zM1219 246v174q0 102 71.5 175t175.5 73h195q102 0 175 -73t73 -175v-174q0 -102 -73 -175t-175 -73h-195q-104 0 -175.5 72.5t-71.5 175.5zM1343 203q0 -33 23.5 -56.5t56.5 -23.5h281q33 0 56.5 23.5t23.5 56.5v260q0 33 -23.5 56.5t-56.5 23.5 h-281q-33 0 -56.5 -23.5t-23.5 -56.5v-260z" />
|
||||
<glyph unicode="&" horiz-adv-x="1921" d="M109 248v440q0 45 55 89t147 44q-117 88 -116 197v205q0 104 72.5 177t174.5 73h842q84 0 154.5 -62.5t95.5 -146.5v-113h-170v70q0 33 -23.5 56t-56.5 23h-842q-33 0 -56.5 -23.5t-23.5 -55.5v-285l1068 -539v285h167v-340l275 -162v-147l-281 157q-35 -86 -99.5 -138 t-141.5 -52h-994q-102 0 -174.5 72.5t-72.5 175.5zM276 248q0 -33 23.5 -56.5t56.5 -23.5h994q23 0 45 20.5t37 53.5l-1045 526h-31q-33 0 -56.5 -23.5t-23.5 -56.5v-440z" />
|
||||
<glyph unicode="'" horiz-adv-x="458" d="M121 1188v287h168v-287h-168z" />
|
||||
<glyph unicode="(" horiz-adv-x="567" d="M106 248v977q0 104 73 177t175 73h60v-170h-60q-33 0 -56.5 -24t-23.5 -56v-977q0 -33 23.5 -56.5t56.5 -23.5h60v-168h-60q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode=")" horiz-adv-x="569" d="M115 0v168h57q33 0 56.5 23.5t23.5 56.5v977q0 33 -23.5 56.5t-56.5 23.5h-57v170h57q102 0 176 -73t74 -177v-977q0 -102 -74 -175t-176 -73h-57z" />
|
||||
<glyph unicode="*" horiz-adv-x="1005" d="M51 1096l49 161l301 -100v316h168v-314l297 98l56 -161l-299 -97l184 -256q-25 -18 -67 -48.5t-68 -49.5l-187 252l-184 -252q-31 23 -74 52.5t-63 43.5l184 258z" />
|
||||
<glyph unicode="+" horiz-adv-x="886" d="M35 522v168h311v314h168v-314h320v-168h-320v-317h-168v317h-311z" />
|
||||
<glyph unicode="," horiz-adv-x="395" d="M111 168h168v-201q0 -82 -47.5 -146.5t-120.5 -88.5v436z" />
|
||||
<glyph unicode="-" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
|
||||
<glyph unicode="." horiz-adv-x="438" d="M111 0v168h168v-168h-168z" />
|
||||
<glyph unicode="/" horiz-adv-x="1067" d="M12 0v217l1037 1258v-213z" />
|
||||
<glyph unicode="0" horiz-adv-x="1708" d="M117 248v977q0 104 72 177t176 73h993q102 0 175 -73t73 -177v-977q0 -102 -73 -175t-175 -73h-993q-104 0 -176 72.5t-72 175.5zM285 371l1130 934h-1050q-33 0 -56.5 -24t-23.5 -56v-854zM305 168h1053q33 0 56.5 23.5t23.5 56.5v854z" />
|
||||
<glyph unicode="1" horiz-adv-x="800" d="M2 1014l387 461h229v-1475h-169v1286q-29 -37 -114 -137t-114 -135h-219z" />
|
||||
<glyph unicode="2" horiz-adv-x="1699" d="M117 0v553q0 104 71.5 176t176.5 72h993q33 0 56.5 23.5t23.5 56.5v346q0 33 -23.5 56.5t-56.5 23.5h-993q-33 0 -56.5 -23.5t-23.5 -56.5v-58h-168v58q0 104 72 177t176 73h993q102 0 175 -73t73 -177v-346q0 -102 -73 -175t-175 -73h-993q-33 0 -56.5 -23.5 t-23.5 -56.5v-305q0 -33 23.5 -56.5t56.5 -23.5h1241v-168h-1489z" />
|
||||
<glyph unicode="3" horiz-adv-x="1691" d="M109 248v33h170v-33q0 -33 23.5 -56.5t55.5 -23.5h994q33 0 56.5 23.5t23.5 56.5v342q0 33 -24 56.5t-56 23.5h-961v168h895q33 0 56.5 23.5t23.5 56.5v309q0 33 -23.5 56.5t-56.5 23.5h-928q-33 0 -56 -23.5t-23 -56.5v-53h-170v53q0 104 72.5 177t176.5 73h928 q104 0 176 -73t72 -177v-309q0 -54 -25 -107l9 -37q82 -76 81 -184v-342q0 -102 -72.5 -175t-174.5 -73h-994q-104 0 -176.5 72.5t-72.5 175.5z" />
|
||||
<glyph unicode="4" horiz-adv-x="1495" d="M12 381v188l1008 908h188v-928h230v-168h-230v-381h-168v381h-1028zM227 549h813v659z" />
|
||||
<glyph unicode="5" horiz-adv-x="1699" d="M117 248v59h168v-59q0 -33 23.5 -56.5t56.5 -23.5h993q33 0 56.5 23.5t23.5 56.5v348q0 33 -23.5 56.5t-56.5 23.5h-1241v801h1489v-170h-1241q-33 0 -56.5 -23.5t-23.5 -56.5v-301q0 -33 23.5 -57.5t56.5 -24.5h993q102 0 175 -72t73 -176v-348q0 -102 -73 -175 t-175 -73h-993q-104 0 -176 72.5t-72 175.5z" />
|
||||
<glyph unicode="6" horiz-adv-x="1679" d="M117 248v979q0 104 71.5 177t176.5 73h983v-170h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-295q0 -33 23.5 -57.5t56.5 -24.5h993q102 0 175 -71.5t73 -176.5v-354q0 -102 -73 -175t-175 -73h-993q-104 0 -176 72.5t-72 175.5zM285 248q0 -33 23.5 -56.5t56.5 -23.5h993 q33 0 56.5 23.5t23.5 56.5v354q0 33 -23.5 56.5t-56.5 23.5h-1073v-434z" />
|
||||
<glyph unicode="7" horiz-adv-x="1351" d="M6 1307v170h983q102 0 175 -73t73 -177v-1227h-168v1227q0 33 -23.5 56.5t-56.5 23.5h-983z" />
|
||||
<glyph unicode="8" horiz-adv-x="1708" d="M117 248v348q0 84 61 164q-61 84 -61 166v301q0 104 71.5 177t176.5 73h993q82 0 152.5 -62.5t95.5 -146.5v-342q0 -82 -62 -166q61 -80 62 -164v-348q0 -102 -73 -175t-175 -73h-993q-104 0 -176 72.5t-72 175.5zM285 248q0 -33 23.5 -56.5t56.5 -23.5h993 q33 0 56.5 23.5t23.5 56.5v348q0 33 -23.5 56.5t-56.5 23.5h-993q-33 0 -56.5 -23.5t-23.5 -56.5v-348zM285 901q0 -33 23.5 -56.5t56.5 -23.5h993q33 0 56.5 23.5t23.5 56.5v324q0 33 -23.5 56.5t-56.5 23.5h-993q-33 0 -56.5 -24t-23.5 -56v-324z" />
|
||||
<glyph unicode="9" d="M104 872v355q0 104 73 177t177 73h994q102 0 174.5 -73t72.5 -177v-979q0 -102 -72.5 -175t-174.5 -73h-994q-80 0 -145.5 47t-89.5 121h1229q33 0 56 23.5t23 56.5v297q0 33 -23 56.5t-56 23.5h-994q-104 0 -177 72.5t-73 174.5zM274 872q0 -33 24 -56t56 -23h1073v434 q0 33 -23.5 56.5t-55.5 23.5h-994q-33 0 -56.5 -23.5t-23.5 -56.5v-355z" />
|
||||
<glyph unicode=":" horiz-adv-x="438" d="M111 0v168h168v-168h-168zM111 1036v168h168v-168h-168z" />
|
||||
<glyph unicode=";" horiz-adv-x="395" d="M104 168h168v-201q0 -82 -47 -146.5t-121 -88.5v436zM104 1036v168h168v-168h-168z" />
|
||||
<glyph unicode="<" horiz-adv-x="968" d="M10 508v199l824 473v-195l-656 -379l656 -379v-194z" />
|
||||
<glyph unicode="=" horiz-adv-x="1306" d="M121 309v168h1059v-168h-1059zM121 719v168h1059v-168h-1059z" />
|
||||
<glyph unicode=">" horiz-adv-x="972" d="M121 29v194l655 379l-655 379v195l823 -474v-198z" />
|
||||
<glyph unicode="?" horiz-adv-x="1388" d="M63 1303v172l1059 -2q102 0 175 -73t73 -177v-398q0 -102 -72.5 -174.5t-175.5 -72.5h-561q-33 0 -56.5 -24t-23.5 -56v-86h-168v86q0 104 73 175.5t175 71.5h561q33 0 56.5 24t23.5 56v398q0 33 -23.5 56.5t-56.5 23.5h-1059zM313 0v168h168v-168h-168z" />
|
||||
<glyph unicode="@" horiz-adv-x="1701" d="M117 248v977q0 104 71.5 177t176.5 73h993q102 0 175 -73t73 -177v-832h-842q-104 0 -176 73t-72 177v172q0 102 72 175t176 73h194q102 0 175 -72.5t73 -175.5v-295h232v705q0 33 -23.5 56.5t-56.5 23.5h-993q-33 0 -56.5 -24t-23.5 -56v-977q0 -33 23.5 -56.5 t56.5 -23.5h1241v-168h-1241q-104 0 -176 72.5t-72 175.5zM641 600q0 -33 23.5 -56.5t56.5 -23.5h360v338q0 33 -23.5 56.5t-56.5 23.5h-280q-33 0 -56.5 -23.5t-23.5 -56.5v-258z" />
|
||||
<glyph unicode="A" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524z" />
|
||||
<glyph unicode="B" horiz-adv-x="1703" d="M121 0v1475h1165q102 0 174 -72t72 -174v-314q0 -55 -27 -108l8 -35q82 -76 82 -182v-344q0 -102 -71.5 -174t-173.5 -72h-1229zM287 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v344q0 33 -24 56.5t-56 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5 v-344zM287 915q0 -33 23.5 -56t56.5 -23h919q33 0 55.5 23.5t22.5 55.5v314q0 33 -22.5 56.5t-55.5 23.5h-919q-33 0 -56.5 -23.5t-23.5 -56.5v-314z" />
|
||||
<glyph unicode="C" horiz-adv-x="1683" d="M115 246v983q0 102 71.5 174t173.5 72h1225v-166h-1225q-33 0 -56 -23.5t-23 -56.5v-983q0 -33 23.5 -56.5t55.5 -23.5h1225v-166h-1225q-102 0 -173.5 71.5t-71.5 174.5z" />
|
||||
<glyph unicode="D" horiz-adv-x="1708" d="M119 0v1475h1229q102 0 173.5 -72t71.5 -174v-983q0 -102 -71.5 -174t-173.5 -72h-1229zM285 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56 23.5t23 56.5v983q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-983z" />
|
||||
<glyph unicode="E" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345z" />
|
||||
<glyph unicode="F" horiz-adv-x="1480" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-653h-166z" />
|
||||
<glyph unicode="G" horiz-adv-x="1699" d="M115 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-60h-166v60q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56 -23.5t-23 -56.5v-983q0 -33 23.5 -56.5t55.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v364h-364v168h530v-532q0 -102 -71.5 -174t-174.5 -72h-983 q-102 0 -173.5 71.5t-71.5 174.5z" />
|
||||
<glyph unicode="H" horiz-adv-x="1742" d="M117 0v1475h166v-654h1177v654h168v-1475h-168v653h-1177v-653h-166z" />
|
||||
<glyph unicode="I" horiz-adv-x="450" d="M117 0v1475h166v-1475h-166z" />
|
||||
<glyph unicode="J" horiz-adv-x="1597" d="M8 246v116h166v-116q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -72 -174t-174 -72h-983q-102 0 -174 71.5t-72 174.5z" />
|
||||
<glyph unicode="K" horiz-adv-x="1632" d="M117 0v1475h168v-654h475l549 654h213l-617 -738l619 -737h-215l-549 653h-475v-653h-168z" />
|
||||
<glyph unicode="L" horiz-adv-x="1595" d="M117 0v1477h166v-1311h1308v-166h-1474z" />
|
||||
<glyph unicode="M" horiz-adv-x="1900" d="M115 0v1475h227l612 -730l613 730h227v-1475h-166v1286l-674 -801l-673 801v-1286h-166z" />
|
||||
<glyph unicode="N" horiz-adv-x="1703" d="M115 0v1475h227l1081 -1287v1287h166v-1475h-227l-1081 1286v-1286h-166z" />
|
||||
<glyph unicode="O" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983z" />
|
||||
<glyph unicode="P" horiz-adv-x="1619" d="M115 0v1473h1228q102 0 174 -72t72 -174v-432q0 -102 -71.5 -174t-174.5 -72h-983q-18 0 -79 8v-557h-166zM281 795q0 -33 23.5 -55.5t55.5 -22.5h983q33 0 56.5 22.5t23.5 55.5v432q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56 -23.5t-23 -56.5v-432z" />
|
||||
<glyph unicode="Q" horiz-adv-x="1810" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -19 -8 -80h201v-166h-1422q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56.5 -23.5 t-23.5 -56.5v-983z" />
|
||||
<glyph unicode="R" horiz-adv-x="1689" d="M113 0v1473h1228q102 0 174 -72t72 -174v-432q0 -102 -71.5 -174t-174.5 -72h-225l463 -549h-219l-461 549h-541q-18 0 -79 8v-557h-166zM279 795q0 -33 23 -55.5t56 -22.5h983q33 0 55.5 22.5t22.5 55.5v432q0 33 -22.5 56.5t-55.5 23.5h-983q-33 0 -56 -23.5t-23 -56.5 v-432z" />
|
||||
<glyph unicode="S" horiz-adv-x="1683" d="M104 246v57h166v-57q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v329q0 33 -23.5 55.5t-56.5 22.5h-983q-102 0 -174 72t-72 174v330q0 102 72 174t174 72h983q102 0 174 -72t72 -174v-58h-166v58q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56.5 -23.5 t-23.5 -56.5v-330q0 -33 23.5 -55.5t56.5 -22.5h983q102 0 174 -71.5t72 -174.5v-329q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -174 71.5t-72 174.5z" />
|
||||
<glyph unicode="T" horiz-adv-x="1554" d="M41 1309v166h1475v-166h-654v-1309h-166v1309h-655z" />
|
||||
<glyph unicode="U" d="M111 246v1229h165v-1229q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5z" />
|
||||
<glyph unicode="V" horiz-adv-x="2054" d="M72 1475h194l756 -1313l754 1313h194l-852 -1475h-192z" />
|
||||
<glyph unicode="W" horiz-adv-x="2414" d="M72 1475h176l432 -1184l430 1184h201l432 -1184l428 1184h180l-536 -1475h-146l-459 1260l-458 -1260h-144z" />
|
||||
<glyph unicode="X" horiz-adv-x="1662" d="M94 0l619 737l-619 738h213l514 -609l512 609h213l-618 -738l620 -737h-215l-512 608l-514 -608h-213z" />
|
||||
<glyph unicode="Y" horiz-adv-x="1650" d="M35 1475h190l572 -721l565 721h194l-677 -920v-555h-166v555z" />
|
||||
<glyph unicode="Z" horiz-adv-x="1681" d="M104 0v227l1287 1082h-1287v166h1475v-228l-1286 -1081h1286v-166h-1475z" />
|
||||
<glyph unicode="[" horiz-adv-x="563" d="M111 0v1477h307v-170h-139v-1139h139v-168h-307z" />
|
||||
<glyph unicode="\" horiz-adv-x="1064" d="M10 1272v213l1037 -1266v-217z" />
|
||||
<glyph unicode="]" horiz-adv-x="565" d="M104 0v168h138v1139h-138v170h308v-1477h-308z" />
|
||||
<glyph unicode="_" d="M111 0h1491v-168h-1491v168z" />
|
||||
<glyph unicode="`" horiz-adv-x="436" d="M66 2071h165l70 -285h-164z" />
|
||||
<glyph unicode="a" horiz-adv-x="1421" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262z" />
|
||||
<glyph unicode="b" horiz-adv-x="1366" d="M111 0v1577h168v-389h794q102 0 175 -73t73 -175v-692q0 -102 -72.5 -175t-175.5 -73h-962zM279 248q0 -33 24.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -57 -23.5t-24 -56.5v-692z" />
|
||||
<glyph unicode="c" horiz-adv-x="1423" d="M104 248v692q0 102 73 175t175 73h959v-168h-959q-33 0 -56.5 -23.5t-23.5 -56.5v-692q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode="d" horiz-adv-x="1366" d="M47 248v692q0 102 73 175t177 73h793v389h167v-1577h-960q-104 0 -177 72.5t-73 175.5zM217 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -24 56.5t-56 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-692z" />
|
||||
<glyph unicode="e" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-430h-1043v-262q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5zM272 678h873v262q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-262z" />
|
||||
<glyph unicode="f" horiz-adv-x="833" d="M109 0v1329q0 104 71.5 176t175.5 72h435v-168h-435q-33 0 -56.5 -23.5t-23.5 -56.5v-141h515v-168h-515v-1020h-167z" />
|
||||
<glyph unicode="g" horiz-adv-x="1398" d="M84 248v692q0 102 72.5 175t175.5 73h712q104 0 176 -73t72 -175v-1159q0 -104 -71.5 -177t-176.5 -73h-741v170h741q33 0 56.5 23.5t23.5 56.5v219h-792q-102 0 -175 72.5t-73 175.5zM252 248q0 -33 23.5 -56.5t56.5 -23.5h712q33 0 56.5 23.5t23.5 56.5v692 q0 33 -23.5 56.5t-56.5 23.5h-712q-33 0 -56.5 -23.5t-23.5 -56.5v-692z" />
|
||||
<glyph unicode="h" horiz-adv-x="1368" d="M111 0v1577h168v-389h794q102 0 175 -73t73 -175v-940h-168v940q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -57 -23.5t-24 -56.5v-940h-168z" />
|
||||
<glyph unicode="i" horiz-adv-x="425" d="M106 0v1188h168v-1188h-168zM106 1409v168h168v-168h-168z" />
|
||||
<glyph unicode="j" horiz-adv-x="489" d="M-383 -328h502q33 0 56.5 23.5t23.5 56.5v1436h170v-1436q0 -104 -73 -177t-177 -73h-502v170zM199 1409v168h170v-168h-170z" />
|
||||
<glyph unicode="k" horiz-adv-x="1323" d="M111 0v1577h168v-899h327l467 510h221l-538 -594l536 -594h-219l-467 510h-327v-510h-168z" />
|
||||
<glyph unicode="l" horiz-adv-x="618" d="M106 248v1329h168v-1329q0 -33 24 -56.5t56 -23.5h201v-168h-201q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode="m" horiz-adv-x="2002" d="M111 0v1188h1568q104 0 176 -73t72 -175v-940h-166v940q0 33 -24.5 56.5t-57.5 23.5h-493q-33 0 -56.5 -23.5t-23.5 -56.5v-940h-170v940q0 33 -23.5 56.5t-56.5 23.5h-496q-33 0 -56 -23.5t-23 -56.5v-940h-170z" />
|
||||
<glyph unicode="n" horiz-adv-x="1425" d="M111 0v1188h962q102 0 175 -73t73 -175v-940h-168v940q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -57 -23.5t-24 -56.5v-940h-168z" />
|
||||
<glyph unicode="o" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692z" />
|
||||
<glyph unicode="p" horiz-adv-x="1359" d="M111 -471v1659h962q102 0 175 -73t73 -175v-692q0 -102 -72.5 -175t-175.5 -73h-794v-471h-168zM279 248q0 -33 24.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -57 -23.5t-24 -56.5v-692z" />
|
||||
<glyph unicode="q" horiz-adv-x="1359" d="M41 248v692q0 102 72.5 175t177.5 73h960v-1659h-168v471h-792q-104 0 -177 72.5t-73 175.5zM211 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56 23.5t23 56.5v692q0 33 -23.5 56.5t-55.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-692z" />
|
||||
<glyph unicode="r" horiz-adv-x="1048" d="M106 0v940q0 102 73 175t175 73h668v-168h-668q-33 0 -56.5 -23.5t-23.5 -56.5v-940h-168z" />
|
||||
<glyph unicode="s" horiz-adv-x="1404" d="M98 248v16h168v-16q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v182q0 33 -23.5 56.5t-56.5 23.5h-713q-102 0 -175 72.5t-73 175.5v182q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-16h-170v16q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-182q0 -33 23.5 -56.5t56.5 -23.5h713q104 0 177 -73t73 -175v-182q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode="t" horiz-adv-x="839" d="M109 248v1329h167v-389h515v-168h-515v-772q0 -33 24 -56.5t56 -23.5h435v-168h-435q-104 0 -175.5 72.5t-71.5 175.5z" />
|
||||
<glyph unicode="u" horiz-adv-x="1423" d="M109 248v940h167v-940q0 -33 24 -56.5t56 -23.5h713q33 0 57.5 23.5t24.5 56.5v940h168v-940q0 -102 -72.5 -175t-177.5 -73h-713q-102 0 -174.5 72.5t-72.5 175.5z" />
|
||||
<glyph unicode="v" horiz-adv-x="1617" d="M43 1188h197l557 -1024l557 1024h196l-657 -1188h-195z" />
|
||||
<glyph unicode="w" horiz-adv-x="2193" d="M72 1188h180l360 -885l383 885h222l407 -883l336 883h182l-448 -1188h-146l-442 981l-420 -981h-147z" />
|
||||
<glyph unicode="x" horiz-adv-x="1417" d="M94 0l496 604l-496 584h221l385 -451l387 451h220l-496 -584l498 -604h-222l-387 475l-385 -475h-221z" />
|
||||
<glyph unicode="y" horiz-adv-x="1402" d="M86 248v936h168v-936q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56 23.5t23 56.5v936h168v-1405q0 -104 -71.5 -177t-175.5 -73h-742v170h742q33 0 56 23.5t23 56.5v221h-792q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode="z" horiz-adv-x="1429" d="M111 0v229l1026 791h-1026v168h1210v-230l-1026 -790h1026v-168h-1210z" />
|
||||
<glyph unicode="{" horiz-adv-x="591" d="M47 641v197l96 51v336q0 104 73 177t175 73h60v-170h-60q-33 0 -56.5 -24t-23.5 -56v-351l-172 -137l172 -141v-348q0 -33 23.5 -56.5t56.5 -23.5h60v-168h-60q-102 0 -175 72.5t-73 175.5v334q-12 8 -47 29.5t-49 29.5z" />
|
||||
<glyph unicode="|" horiz-adv-x="438" d="M111 -236v1960h168v-1960h-168z" />
|
||||
<glyph unicode="}" horiz-adv-x="591" d="M104 0v168h60q33 0 56.5 23.5t23.5 56.5v346l172 141l-172 135v355q0 33 -23.5 56.5t-56.5 23.5h-60v170h60q102 0 175 -73t73 -177v-336q16 -8 51 -29.5t43 -25.5v-195l-94 -59v-332q0 -102 -73 -175t-175 -73h-60z" />
|
||||
<glyph unicode="~" horiz-adv-x="827" d="M49 631v76q55 18 127 18q82 0 219 -68.5t209 -76.5h4q66 0 135 32v-84q-72 -27 -135 -26q-72 0 -209 72.5t-223 72.5q-80 0 -127 -16z" />
|
||||
<glyph unicode="¡" horiz-adv-x="430" d="M109 0v1059h167v-1059h-167zM109 1321v170h167v-170h-167z" />
|
||||
<glyph unicode="¢" horiz-adv-x="1302" d="M68 248v713q0 104 71.5 176.5t175.5 72.5h273v277h168v-277h516v-170h-516v-872h516v-168h-516v-236h-168v236h-273q-104 0 -175.5 72.5t-71.5 175.5zM236 248q0 -33 23.5 -56.5t55.5 -23.5h273v872h-273q-33 0 -56 -23.5t-23 -55.5v-713z" />
|
||||
<glyph unicode="£" horiz-adv-x="1503" d="M80 0v168h215v494h-215v167h215v396q0 104 72.5 177t177.5 73h620q104 0 177 -73t73 -177v-31h-170v31q0 33 -23.5 56.5t-56.5 23.5h-620q-33 0 -56.5 -24t-23.5 -56v-396h721v-167h-721v-494h950v-168h-1335z" />
|
||||
<glyph unicode="¨" horiz-adv-x="788" d="M111 1786v168h170v-168h-170zM479 1786v168h168v-168h-168z" />
|
||||
<glyph unicode="­" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
|
||||
<glyph unicode="°" horiz-adv-x="899" d="M92 1069v172q0 104 73 177t177 73h193q104 0 176.5 -72.5t72.5 -177.5v-172q0 -102 -72.5 -175t-176.5 -73h-193q-104 0 -177 73t-73 175zM217 1026q0 -33 23.5 -56.5t56.5 -23.5h283q33 0 56 23.5t23 56.5v258q0 33 -23.5 56.5t-55.5 23.5h-283q-33 0 -56.5 -23.5 t-23.5 -56.5v-258z" />
|
||||
<glyph unicode="´" horiz-adv-x="436" d="M68 1786l71 285h162l-70 -285h-163z" />
|
||||
<glyph unicode="¶" horiz-adv-x="1705" d="M115 803v436q0 104 71.5 177t175.5 73h1242v-1489h-168v555h-283v-555h-168v555h-623q-104 0 -175.5 72.5t-71.5 175.5zM283 803q0 -33 23.5 -56.5t55.5 -23.5h623v596h-623q-33 0 -56 -23.5t-23 -56.5v-436zM1153 723h283v596h-283v-596z" />
|
||||
<glyph unicode="¸" horiz-adv-x="436" d="M68 -350l71 284h162l-70 -284h-163z" />
|
||||
<glyph unicode="¿" horiz-adv-x="1382" d="M39 248v397q0 104 71.5 177t176.5 73h559q33 0 56.5 23.5t23.5 56.5v98h168v-98q0 -104 -72 -177t-176 -73h-559q-33 0 -56.5 -23.5t-23.5 -56.5v-397q0 -33 23.5 -56.5t56.5 -23.5h1040q0 -59 4 -105.5t8 -62.5l4 -16l-1056 16q-104 0 -176 72.5t-72 175.5zM926 1321 v170h168v-170h-168z" />
|
||||
<glyph unicode="À" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM705 2056h165l70 -284h-164z" />
|
||||
<glyph unicode="Á" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM705 1769l71 285h162l-70 -285h-163z" />
|
||||
<glyph unicode="Â" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM606 1769l146 240h120l146 -240h-86l-119 175l-123 -175h-84z" />
|
||||
<glyph unicode="Ã" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM496 1911v96q55 18 127 18q82 0 219 -68.5t209 -78.5h4q61 0 135 35v-105 q-78 -29 -135 -28q-72 0 -209 73.5t-223 73.5q-80 0 -127 -16z" />
|
||||
<glyph unicode="Ä" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM571 1751v168h170v-168h-170zM940 1751v168h168v-168h-168z" />
|
||||
<glyph unicode="Å" horiz-adv-x="1712" d="M119 0v1229q0 102 72 174t174 72h983q102 0 173.5 -72t71.5 -174v-1229h-166v539h-1142v-539h-166zM285 705h1142v524q0 33 -23.5 56.5t-55.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524zM688 1790v111q0 45 33 76.5t78 31.5h114q45 0 78 -31.5t33 -76.5v-111 q0 -45 -33 -77t-78 -32h-114q-45 0 -78 32t-33 77zM770 1784q0 -21 18 -21h136q18 0 18 21v123q0 20 -18 20h-136q-18 0 -18 -20v-123z" />
|
||||
<glyph unicode="Æ" horiz-adv-x="2816" d="M111 0v1229q0 102 71.5 174t173.5 72h2409v-166h-1180v-488h948v-168h-948v-487h1180v-166h-1346v539h-1143v-539h-165zM276 705h1143v524q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5v-524z" />
|
||||
<glyph unicode="Ç" horiz-adv-x="1683" d="M115 246v983q0 102 71.5 174t173.5 72h1225v-166h-1225q-33 0 -56 -23.5t-23 -56.5v-983q0 -33 23.5 -56.5t55.5 -23.5h1225v-166h-661l-70 -285h-164l72 285h-402q-102 0 -173.5 71.5t-71.5 174.5z" />
|
||||
<glyph unicode="È" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM633 2056h166l69 -284h-163z" />
|
||||
<glyph unicode="É" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM633 1772l72 284h161l-69 -284h-164z" />
|
||||
<glyph unicode="Ê" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM535 1769l145 240h121l145 -240h-86l-119 175l-123 -175h-83z" />
|
||||
<glyph unicode="Ë" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM500 1772v167h170v-167h-170zM868 1772v167h168v-167h-168z" />
|
||||
<glyph unicode="Ì" horiz-adv-x="450" d="M74 2056h166l69 -284h-164zM117 0v1475h166v-1475h-166z" />
|
||||
<glyph unicode="Í" horiz-adv-x="450" d="M74 1772l71 284h162l-69 -284h-164zM117 0v1475h166v-1475h-166z" />
|
||||
<glyph unicode="Î" horiz-adv-x="450" d="M-25 1769l146 240h121l145 -240h-86l-119 175l-123 -175h-84zM117 0v1475h166v-1475h-166z" />
|
||||
<glyph unicode="Ï" horiz-adv-x="450" d="M-59 1772v167h170v-167h-170zM117 0v1475h166v-1475h-166zM309 1772v167h168v-167h-168z" />
|
||||
<glyph unicode="Ñ" horiz-adv-x="1703" d="M115 0v1475h227l1081 -1287v1287h166v-1475h-227l-1081 1286v-1286h-166zM492 1911v96q55 18 126 18q82 0 219.5 -68.5t209.5 -78.5h4q61 0 135 35v-105q-78 -29 -135 -28q-72 0 -209 73.5t-224 73.5q-80 0 -126 -16z" />
|
||||
<glyph unicode="Ò" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983zM696 2056h166l70 -284h-164z" />
|
||||
<glyph unicode="Ó" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983zM696 1772l72 284h162l-70 -284h-164z" />
|
||||
<glyph unicode="Ô" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983zM598 1769l145 240h121l146 -240h-86l-119 175l-123 -175h-84z" />
|
||||
<glyph unicode="Õ" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983zM487 1911v96q55 18 127 18q82 0 219 -68.5t209 -78.5h5q61 0 135 35v-105q-78 -29 -135 -28q-72 0 -209.5 73.5t-223.5 73.5q-80 0 -127 -16z" />
|
||||
<glyph unicode="Ö" d="M111 246v983q0 102 71.5 174t173.5 72h983q102 0 174 -72t72 -174v-983q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM276 246q0 -33 23.5 -56.5t56.5 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983 q-33 0 -56.5 -23.5t-23.5 -56.5v-983zM563 1772v167h170v-167h-170zM932 1772v167h168v-167h-168z" />
|
||||
<glyph unicode="×" horiz-adv-x="1118" d="M109 1036h221l215 -295l217 295h217l-324 -420l324 -421h-217l-217 294l-215 -294h-219l323 421z" />
|
||||
<glyph unicode="Ù" d="M111 246v1229h165v-1229q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM696 2056h166l70 -284h-164z" />
|
||||
<glyph unicode="Ú" d="M111 246v1229h165v-1229q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM696 1772l72 284h162l-70 -284h-164z" />
|
||||
<glyph unicode="Û" d="M111 246v1229h165v-1229q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM598 1769l145 240h121l146 -240h-86l-119 175l-123 -175h-84z" />
|
||||
<glyph unicode="Ü" d="M111 246v1229h165v-1229q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v1229h166v-1229q0 -102 -71.5 -174t-174.5 -72h-983q-102 0 -173.5 71.5t-71.5 174.5zM563 1772v167h170v-167h-170zM932 1772v167h168v-167h-168z" />
|
||||
<glyph unicode="Ý" horiz-adv-x="1650" d="M35 1475h190l572 -721l565 721h194l-677 -920v-555h-166v555zM674 1772l71 284h162l-69 -284h-164z" />
|
||||
<glyph unicode="ß" horiz-adv-x="1705" d="M117 0v1241q0 104 71.5 177t176.5 73h993q82 0 152.5 -62.5t95.5 -146.5v-350q0 -82 -62 -166q61 -80 62 -164v-354q0 -102 -73 -175t-175 -73h-776v168h776q33 0 56.5 23.5t23.5 56.5v354q0 33 -23.5 56.5t-56.5 23.5h-776v145h776q33 0 56.5 23.5t23.5 56.5v332 q0 33 -23.5 56.5t-56.5 23.5h-993q-33 0 -56.5 -23.5t-23.5 -56.5v-1239h-168z" />
|
||||
<glyph unicode="à" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM590 1847h166l69 -284h-163z" />
|
||||
<glyph unicode="á" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM590 1563l72 284h161l-69 -284h-164z" />
|
||||
<glyph unicode="â" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM492 1563l145 239h121l145 -239h-86l-119 174l-123 -174h-83z" />
|
||||
<glyph unicode="ã" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM381 1700v96q55 18 127 19q82 0 219 -69t209 -79h4q61 0 135 35v-105 q-78 -29 -135 -28q-72 0 -209 73.5t-223 73.5q-80 0 -127 -16z" />
|
||||
<glyph unicode="ä" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM457 1563v168h170v-168h-170zM825 1563v168h168v-168h-168z" />
|
||||
<glyph unicode="å" horiz-adv-x="1484" d="M106 248v430h1041v262q0 33 -23.5 56.5t-56.5 23.5h-961v168h961q104 0 177 -73t73 -175v-940h-963q-102 0 -175 72.5t-73 175.5zM274 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM573 1579v111q0 45 33 76.5t78 31.5h115q45 0 77.5 -31.5t32.5 -76.5v-111 q0 -45 -32.5 -77t-77.5 -32h-115q-45 0 -78 32t-33 77zM655 1573q1 -21 19 -21h135q18 0 18 21v123q0 20 -18 20h-135q-18 0 -19 -20v-123z" />
|
||||
<glyph unicode="æ" horiz-adv-x="2412" d="M109 248v430h1040v262q0 33 -23.5 56.5t-56.5 23.5h-960v168h2000q104 0 176 -73t72 -175v-430h-1040v-270q2 -31 25.5 -51.5t54.5 -20.5h960v-168h-2001q-104 0 -175.5 72.5t-71.5 175.5zM276 248q0 -33 24 -56.5t56 -23.5h793v342h-873v-262zM1317 678h872v262 q0 33 -23.5 56.5t-56.5 23.5h-712q-33 0 -56.5 -23.5t-23.5 -56.5v-262z" />
|
||||
<glyph unicode="ç" horiz-adv-x="1419" d="M104 248v692q0 102 73 175t175 73h959v-168h-959q-33 0 -56.5 -23.5t-23.5 -56.5v-692q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-524l-70 -285h-164l72 285h-277q-102 0 -175 72.5t-73 175.5z" />
|
||||
<glyph unicode="è" horiz-adv-x="1306" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-430h-1043v-262q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5zM272 678h873v262q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-262zM502 1847h166l69 -284 h-164z" />
|
||||
<glyph unicode="é" horiz-adv-x="1306" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-430h-1043v-262q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5zM272 678h873v262q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-262zM502 1565l71 284h162 l-69 -284h-164z" />
|
||||
<glyph unicode="ê" horiz-adv-x="1306" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-430h-1043v-262q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5zM272 678h873v262q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-262zM403 1563l146 239h121 l145 -239h-86l-119 174l-123 -174h-84z" />
|
||||
<glyph unicode="ë" horiz-adv-x="1306" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-430h-1043v-262q0 -33 23.5 -56.5t56.5 -23.5h963v-168h-963q-102 0 -175 72.5t-73 175.5zM272 678h873v262q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5t-23.5 -56.5v-262zM369 1563v168h170v-168 h-170zM737 1563v168h168v-168h-168z" />
|
||||
<glyph unicode="ì" horiz-adv-x="438" d="M33 1849h166l69 -284h-164zM115 0v1188h168v-1188h-168z" />
|
||||
<glyph unicode="í" horiz-adv-x="438" d="M100 1563l72 284h162l-70 -284h-164zM104 0v1188h168v-1188h-168z" />
|
||||
<glyph unicode="î" horiz-adv-x="438" d="M-31 1563l146 239h121l145 -239h-86l-119 174l-123 -174h-84zM104 0v1188h168v-1188h-168z" />
|
||||
<glyph unicode="ï" horiz-adv-x="438" d="M-66 1567v168h170v-168h-170zM113 0v1188h168v-1188h-168zM303 1567v168h168v-168h-168z" />
|
||||
<glyph unicode="ñ" horiz-adv-x="1449" d="M111 0v1188h962q102 0 175 -73t73 -175v-940h-168v940q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -57 -23.5t-24 -56.5v-940h-168zM365 1698v96q55 18 127 18q82 0 219 -68.5t209 -78.5h4q61 0 135 35v-105q-78 -29 -135 -28q-72 0 -209 73.5t-223 73.5q-80 0 -127 -16z " />
|
||||
<glyph unicode="ò" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692zM557 1849h166l70 -284h-164z" />
|
||||
<glyph unicode="ó" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692zM557 1565l72 284h162l-70 -284h-164z" />
|
||||
<glyph unicode="ô" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692zM459 1563l145 239h121l145 -239h-86l-118 174l-123 -174h-84z" />
|
||||
<glyph unicode="õ" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692zM348 1698v96q55 18 127 18q82 0 219 -68.5t209 -78.5h4q61 0 135 35v-105q-78 -29 -135 -28q-72 0 -209 73.5t-223 73.5q-80 0 -127 -16z" />
|
||||
<glyph unicode="ö" horiz-adv-x="1417" d="M104 248v692q0 102 73 175t175 73h713q104 0 177 -73t73 -175v-692q0 -102 -73 -175t-177 -73h-713q-102 0 -175 72.5t-73 175.5zM272 248q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713q-33 0 -56.5 -23.5 t-23.5 -56.5v-692zM424 1567v168h170v-168h-170zM793 1567v168h168v-168h-168z" />
|
||||
<glyph unicode="÷" horiz-adv-x="1040" d="M37 522v168h971v-168h-971zM440 2v168h168v-168h-168zM440 1018v168h168v-168h-168z" />
|
||||
<glyph unicode="ù" horiz-adv-x="1423" d="M109 248v940h167v-940q0 -33 24 -56.5t56 -23.5h713q33 0 57.5 23.5t24.5 56.5v940h168v-940q0 -102 -72.5 -175t-177.5 -73h-713q-102 0 -174.5 72.5t-72.5 175.5zM559 1849h166l70 -284h-164z" />
|
||||
<glyph unicode="ú" horiz-adv-x="1423" d="M109 248v940h167v-940q0 -33 24 -56.5t56 -23.5h713q33 0 57.5 23.5t24.5 56.5v940h168v-940q0 -102 -72.5 -175t-177.5 -73h-713q-102 0 -174.5 72.5t-72.5 175.5zM559 1565l72 284h162l-70 -284h-164z" />
|
||||
<glyph unicode="û" horiz-adv-x="1423" d="M109 248v940h167v-940q0 -33 24 -56.5t56 -23.5h713q33 0 57.5 23.5t24.5 56.5v940h168v-940q0 -102 -72.5 -175t-177.5 -73h-713q-102 0 -174.5 72.5t-72.5 175.5zM461 1565l145 239h121l145 -239h-86l-118 174l-123 -174h-84z" />
|
||||
<glyph unicode="ü" horiz-adv-x="1423" d="M109 248v940h167v-940q0 -33 24 -56.5t56 -23.5h713q33 0 57.5 23.5t24.5 56.5v940h168v-940q0 -102 -72.5 -175t-177.5 -73h-713q-102 0 -174.5 72.5t-72.5 175.5zM426 1563v168h170v-168h-170zM795 1563v168h168v-168h-168z" />
|
||||
<glyph unicode="ý" horiz-adv-x="1409" d="M86 248v936h168v-936q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56 23.5t23 56.5v936h168v-1405q0 -104 -71.5 -177t-175.5 -73h-742v170h742q33 0 56 23.5t23 56.5v221h-792q-102 0 -175 72.5t-73 175.5zM553 1565l72 284h161l-69 -284h-164z" />
|
||||
<glyph unicode="ÿ" horiz-adv-x="1409" d="M86 248v936h168v-936q0 -33 23.5 -56.5t56.5 -23.5h713q33 0 56 23.5t23 56.5v936h168v-1405q0 -104 -71.5 -177t-175.5 -73h-742v170h742q33 0 56 23.5t23 56.5v221h-792q-102 0 -175 72.5t-73 175.5zM420 1567v168h170v-168h-170zM788 1567v168h168v-168h-168z" />
|
||||
<glyph unicode="Œ" horiz-adv-x="2813" d="M109 246v983q0 102 71.5 174t173.5 72h2409v-166h-1180v-488h948v-168h-948v-487h1180v-166h-2409q-102 0 -173.5 71.5t-71.5 174.5zM274 246q0 -33 24 -56.5t56 -23.5h983q33 0 56.5 23.5t23.5 56.5v983q0 33 -23.5 56.5t-56.5 23.5h-983q-33 0 -56.5 -23.5t-23.5 -56.5 v-983z" />
|
||||
<glyph unicode="œ" horiz-adv-x="2410" d="M106 248v692q0 102 72 175t176 73h1753q104 0 176 -73t72 -175v-430h-1040v-262q0 -33 23.5 -56.5t56.5 -23.5h960v-168h-2001q-104 0 -176 72.5t-72 175.5zM274 248q0 -33 24 -56.5t56 -23.5h713q33 0 56.5 23.5t23.5 56.5v692q0 33 -23.5 56.5t-56.5 23.5h-713 q-33 0 -56.5 -23.5t-23.5 -56.5v-692zM1315 678h872v262q0 33 -23.5 56.5t-56.5 23.5h-712q-33 0 -56.5 -23.5t-23.5 -56.5v-262z" />
|
||||
<glyph unicode="Ÿ" horiz-adv-x="1650" d="M35 1475h190l572 -721l565 721h194l-677 -920v-555h-166v555zM541 1772v167h170v-167h-170zM909 1772v167h168v-167h-168z" />
|
||||
<glyph unicode="ˆ" horiz-adv-x="614" d="M57 1784l146 239h121l145 -239h-86l-119 174l-123 -174h-84z" />
|
||||
<glyph unicode="˜" horiz-adv-x="825" d="M47 1925v96q55 18 127 19q82 0 219 -69t209 -79h4q61 0 135 35v-104q-78 -29 -135 -29q-72 0 -209 74t-223 74q-80 0 -127 -17z" />
|
||||
<glyph unicode=" " horiz-adv-x="1035" />
|
||||
<glyph unicode=" " horiz-adv-x="2071" />
|
||||
<glyph unicode=" " horiz-adv-x="1035" />
|
||||
<glyph unicode=" " horiz-adv-x="2071" />
|
||||
<glyph unicode=" " horiz-adv-x="690" />
|
||||
<glyph unicode=" " horiz-adv-x="517" />
|
||||
<glyph unicode=" " horiz-adv-x="345" />
|
||||
<glyph unicode=" " horiz-adv-x="345" />
|
||||
<glyph unicode=" " horiz-adv-x="258" />
|
||||
<glyph unicode=" " horiz-adv-x="414" />
|
||||
<glyph unicode=" " horiz-adv-x="115" />
|
||||
<glyph unicode="‐" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
|
||||
<glyph unicode="‑" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
|
||||
<glyph unicode="‒" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
|
||||
<glyph unicode="–" horiz-adv-x="1449" d="M111 520v168h1230v-168h-1230z" />
|
||||
<glyph unicode="—" horiz-adv-x="1683" d="M111 520v168h1476v-168h-1476z" />
|
||||
<glyph unicode="‘" horiz-adv-x="344" d="M68 1030v201q0 82 47 147.5t123 87.5v-436h-170z" />
|
||||
<glyph unicode="’" horiz-adv-x="339" d="M111 1040v437h168v-201q0 -82 -47.5 -147.5t-120.5 -88.5z" />
|
||||
<glyph unicode="“" horiz-adv-x="743" d="M96 1028v201q0 82 47 147.5t123 87.5v-436h-170zM467 1028v201q0 82 46 147.5t122 87.5v-436h-168z" />
|
||||
<glyph unicode="”" horiz-adv-x="743" d="M111 1040v437h170v-201q0 -82 -47.5 -147.5t-122.5 -88.5zM481 1040v437h168v-201q0 -82 -47 -147.5t-121 -88.5z" />
|
||||
<glyph unicode="•" horiz-adv-x="759" d="M295 723v43q0 59 57 59h51q59 0 60 -59v-43q0 -57 -60 -57h-51q-57 0 -57 57z" />
|
||||
<glyph unicode="…" horiz-adv-x="1175" d="M111 0v168h168v-168h-168zM498 0v168h168v-168h-168zM883 0v168h170v-168h-170z" />
|
||||
<glyph unicode=" " horiz-adv-x="414" />
|
||||
<glyph unicode=" " horiz-adv-x="517" />
|
||||
<glyph unicode="€" horiz-adv-x="1636" d="M72 471v168h215v211h-215v170h215v207q0 104 72.5 177t177.5 73h1022v-170h-1022q-33 0 -56.5 -23.5t-23.5 -56.5v-207h868v-170h-868v-211h868v-168h-868v-223q0 -33 23.5 -56.5t56.5 -23.5h1022v-168h-1022q-104 0 -177 72.5t-73 175.5v223h-215z" />
|
||||
<glyph unicode="◼" horiz-adv-x="1187" d="M0 0v1188h1188v-1188h-1188z" />
|
||||
<hkern u1="?" u2="v" k="2" />
|
||||
<hkern u1="A" u2="Y" k="27" />
|
||||
<hkern u1="A" u2="W" k="63" />
|
||||
<hkern u1="B" u2="Y" k="63" />
|
||||
<hkern u1="B" u2="V" k="100" />
|
||||
<hkern u1="D" u2="Z" k="55" />
|
||||
<hkern u1="D" u2="V" k="59" />
|
||||
<hkern u1="E" u2="O" k="63" />
|
||||
<hkern u1="E" u2="M" k="59" />
|
||||
<hkern u1="F" u2="y" k="41" />
|
||||
<hkern u1="F" u2="T" k="-20" />
|
||||
<hkern u1="F" u2="R" k="-10" />
|
||||
<hkern u1="F" u2="J" k="492" />
|
||||
<hkern u1="G" u2="W" k="55" />
|
||||
<hkern u1="K" u2="H" k="59" />
|
||||
<hkern u1="K" u2="A" k="61" />
|
||||
<hkern u1="L" u2="Y" k="367" />
|
||||
<hkern u1="L" u2="W" k="264" />
|
||||
<hkern u1="L" u2="V" k="473" />
|
||||
<hkern u1="M" u2="c" k="20" />
|
||||
<hkern u1="O" u2="X" k="80" />
|
||||
<hkern u1="O" u2="W" k="55" />
|
||||
<hkern u1="O" u2="V" k="55" />
|
||||
<hkern u1="P" u2="v" k="-2" />
|
||||
<hkern u1="P" u2="d" k="-20" />
|
||||
<hkern u1="P" u2="J" k="383" />
|
||||
<hkern u1="P" u2="A" k="-20" />
|
||||
<hkern u1="R" u2="W" k="39" />
|
||||
<hkern u1="R" u2="V" k="39" />
|
||||
<hkern u1="S" u2="Y" k="20" />
|
||||
<hkern u1="S" u2="W" k="51" />
|
||||
<hkern u1="S" u2="N" k="39" />
|
||||
<hkern u1="T" u2="z" k="211" />
|
||||
<hkern u1="T" u2="y" k="186" />
|
||||
<hkern u1="T" u2="w" k="170" />
|
||||
<hkern u1="T" u2="u" k="207" />
|
||||
<hkern u1="T" u2="s" k="248" />
|
||||
<hkern u1="T" u2="o" k="252" />
|
||||
<hkern u1="V" u2="s" k="82" />
|
||||
<hkern u1="V" u2="o" k="61" />
|
||||
<hkern u1="V" u2="S" k="41" />
|
||||
<hkern u1="V" u2="O" k="68" />
|
||||
<hkern u1="V" u2="A" k="76" />
|
||||
<hkern u1="W" u2="u" k="41" />
|
||||
<hkern u1="W" u2="o" k="51" />
|
||||
<hkern u1="W" u2="i" k="20" />
|
||||
<hkern u1="W" u2="e" k="72" />
|
||||
<hkern u1="W" u2="a" k="31" />
|
||||
<hkern u1="W" u2="O" k="47" />
|
||||
<hkern u1="W" u2="A" k="55" />
|
||||
<hkern u1="X" u2="B" k="72" />
|
||||
<hkern u1="Y" u2="u" k="199" />
|
||||
<hkern u1="Y" u2="s" k="240" />
|
||||
<hkern u1="Y" u2="p" k="203" />
|
||||
<hkern u1="Y" u2="o" k="244" />
|
||||
<hkern u1="Y" u2="i" k="39" />
|
||||
<hkern u1="Y" u2="e" k="244" />
|
||||
<hkern u1="Y" u2="a" k="199" />
|
||||
<hkern u1="Y" u2="S" k="72" />
|
||||
<hkern u1="Z" u2="Y" k="20" />
|
||||
<hkern u1="a" u2="z" k="51" />
|
||||
<hkern u1="a" u2="x" k="31" />
|
||||
<hkern u1="a" u2="w" k="61" />
|
||||
<hkern u1="a" u2="v" k="41" />
|
||||
<hkern u1="a" u2="s" k="41" />
|
||||
<hkern u1="a" u2="r" k="10" />
|
||||
<hkern u1="a" u2="n" k="31" />
|
||||
<hkern u1="a" u2="m" k="41" />
|
||||
<hkern u1="a" u2="l" k="20" />
|
||||
<hkern u1="a" u2="c" k="20" />
|
||||
<hkern u1="a" u2="b" k="51" />
|
||||
<hkern u1="b" u2="d" k="-61" />
|
||||
<hkern u1="c" u2="z" k="41" />
|
||||
<hkern u1="c" u2="u" k="41" />
|
||||
<hkern u1="c" u2="t" k="51" />
|
||||
<hkern u1="c" u2="k" k="41" />
|
||||
<hkern u1="c" u2="h" k="31" />
|
||||
<hkern u1="c" u2="e" k="51" />
|
||||
<hkern u1="d" u2="u" k="47" />
|
||||
<hkern u1="d" u2="o" k="45" />
|
||||
<hkern u1="d" u2="e" k="41" />
|
||||
<hkern u1="e" u2="x" k="35" />
|
||||
<hkern u1="e" u2="w" k="61" />
|
||||
<hkern u1="e" u2="v" k="41" />
|
||||
<hkern u1="e" u2="r" k="10" />
|
||||
<hkern u1="e" u2="l" k="41" />
|
||||
<hkern u1="e" u2="e" k="31" />
|
||||
<hkern u1="e" u2="c" k="41" />
|
||||
<hkern u1="f" u2="u" k="-20" />
|
||||
<hkern u1="f" u2="t" k="-10" />
|
||||
<hkern u1="f" u2="," k="371" />
|
||||
<hkern u1="g" u2="w" k="41" />
|
||||
<hkern u1="g" u2="u" k="51" />
|
||||
<hkern u1="g" u2="s" k="43" />
|
||||
<hkern u1="g" u2="r" k="31" />
|
||||
<hkern u1="g" u2="o" k="41" />
|
||||
<hkern u1="g" u2="e" k="31" />
|
||||
<hkern u1="g" u2="c" k="31" />
|
||||
<hkern u1="g" u2="a" k="31" />
|
||||
<hkern u1="h" u2="i" k="-10" />
|
||||
<hkern u1="h" u2="f" k="-20" />
|
||||
<hkern u1="h" u2="a" k="-10" />
|
||||
<hkern u1="i" u2="x" k="84" />
|
||||
<hkern u1="i" u2="v" k="10" />
|
||||
<hkern u1="i" u2="q" k="31" />
|
||||
<hkern u1="i" u2="p" k="51" />
|
||||
<hkern u1="i" u2="n" k="31" />
|
||||
<hkern u1="i" u2="f" k="96" />
|
||||
<hkern u1="i" u2="c" k="31" />
|
||||
<hkern u1="i" u2="a" k="72" />
|
||||
<hkern u1="j" u2="e" k="41" />
|
||||
<hkern u1="k" u2="e" k="10" />
|
||||
<hkern u1="l" u2="’" k="178" />
|
||||
<hkern u1="l" u2="w" k="133" />
|
||||
<hkern u1="l" u2="v" k="121" />
|
||||
<hkern u1="l" u2="o" k="20" />
|
||||
<hkern u1="l" u2="m" k="20" />
|
||||
<hkern u1="l" u2="e" k="31" />
|
||||
<hkern u1="l" u2="d" k="-10" />
|
||||
<hkern u1="l" u2="a" k="20" />
|
||||
<hkern u1="m" u2="w" k="51" />
|
||||
<hkern u1="m" u2="m" k="27" />
|
||||
<hkern u1="m" u2="k" k="27" />
|
||||
<hkern u1="n" u2="x" k="51" />
|
||||
<hkern u1="n" u2="p" k="20" />
|
||||
<hkern u1="n" u2="o" k="31" />
|
||||
<hkern u1="n" u2="c" k="41" />
|
||||
<hkern u1="n" u2="b" k="41" />
|
||||
<hkern u1="o" u2="x" k="72" />
|
||||
<hkern u1="o" u2="w" k="72" />
|
||||
<hkern u1="o" u2="v" k="27" />
|
||||
<hkern u1="o" u2="u" k="47" />
|
||||
<hkern u1="o" u2="t" k="47" />
|
||||
<hkern u1="o" u2="s" k="41" />
|
||||
<hkern u1="o" u2="r" k="20" />
|
||||
<hkern u1="o" u2="o" k="41" />
|
||||
<hkern u1="o" u2="n" k="31" />
|
||||
<hkern u1="o" u2="l" k="41" />
|
||||
<hkern u1="o" u2="a" k="20" />
|
||||
<hkern u1="p" u2="s" k="-20" />
|
||||
<hkern u1="p" u2="i" k="-31" />
|
||||
<hkern u1="p" u2="d" k="-51" />
|
||||
<hkern u1="q" u2="u" k="51" />
|
||||
<hkern u1="r" u2="o" k="10" />
|
||||
<hkern u1="r" u2="." k="41" />
|
||||
<hkern u1="r" u2="," k="498" />
|
||||
<hkern u1="s" u2="z" k="47" />
|
||||
<hkern u1="s" u2="x" k="76" />
|
||||
<hkern u1="s" u2="v" k="41" />
|
||||
<hkern u1="s" u2="u" k="41" />
|
||||
<hkern u1="s" u2="n" k="47" />
|
||||
<hkern u1="s" u2="k" k="31" />
|
||||
<hkern u1="s" u2="e" k="31" />
|
||||
<hkern u1="s" u2="c" k="39" />
|
||||
<hkern u1="t" u2="z" k="-10" />
|
||||
<hkern u1="t" u2="i" k="-10" />
|
||||
<hkern u1="t" u2="h" k="-10" />
|
||||
<hkern u1="t" u2="d" k="-41" />
|
||||
<hkern u1="t" u2="b" k="-10" />
|
||||
<hkern u1="u" u2="z" k="31" />
|
||||
<hkern u1="u" u2="x" k="31" />
|
||||
<hkern u1="u" u2="t" k="31" />
|
||||
<hkern u1="u" u2="s" k="31" />
|
||||
<hkern u1="u" u2="p" k="31" />
|
||||
<hkern u1="u" u2="n" k="-10" />
|
||||
<hkern u1="u" u2="m" k="41" />
|
||||
<hkern u1="u" u2="f" k="20" />
|
||||
<hkern u1="u" u2="e" k="31" />
|
||||
<hkern u1="u" u2="d" k="-20" />
|
||||
<hkern u1="u" u2="c" k="41" />
|
||||
<hkern u1="u" u2="b" k="31" />
|
||||
<hkern u1="v" u2="s" k="51" />
|
||||
<hkern u1="v" u2="o" k="59" />
|
||||
<hkern u1="v" u2="e" k="61" />
|
||||
<hkern u1="w" u2="s" k="31" />
|
||||
<hkern u1="w" u2="r" k="41" />
|
||||
<hkern u1="w" u2="o" k="41" />
|
||||
<hkern u1="w" u2="e" k="41" />
|
||||
<hkern u1="x" u2="e" k="100" />
|
||||
<hkern u1="y" u2="o" k="47" />
|
||||
<hkern u1="y" u2="n" k="31" />
|
||||
<hkern u1="y" u2="l" k="-20" />
|
||||
<hkern u1="y" u2="e" k="41" />
|
||||
<hkern u1="y" u2="c" k="41" />
|
||||
<hkern u1="y" u2="a" k="47" />
|
||||
<hkern u1="z" u2="z" k="41" />
|
||||
<hkern u1="z" u2="t" k="41" />
|
||||
<hkern u1="z" u2="l" k="41" />
|
||||
<hkern u1="z" u2="e" k="51" />
|
||||
<hkern u1="z" u2="a" k="51" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
Before Width: | Height: | Size: 45 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M4 10v20c0 1.1 0.9 2 2 2h18c1.1 0 2-0.9 2-2v-20h-22zM10 28h-2v-14h2v14zM14 28h-2v-14h2v14zM18 28h-2v-14h2v14zM22 28h-2v-14h2v14z"></path>
|
||||
<path d="M26.5 4h-6.5v-2.5c0-0.825-0.675-1.5-1.5-1.5h-7c-0.825 0-1.5 0.675-1.5 1.5v2.5h-6.5c-0.825 0-1.5 0.675-1.5 1.5v2.5h26v-2.5c0-0.825-0.675-1.5-1.5-1.5zM18 4h-6v-1.975h6v1.975z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 657 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M11.366 22.564l1.291-1.807-1.414-1.414-1.807 1.291c-0.335-0.187-0.694-0.337-1.071-0.444l-0.365-2.19h-2l-0.365 2.19c-0.377 0.107-0.736 0.256-1.071 0.444l-1.807-1.291-1.414 1.414 1.291 1.807c-0.187 0.335-0.337 0.694-0.443 1.071l-2.19 0.365v2l2.19 0.365c0.107 0.377 0.256 0.736 0.444 1.071l-1.291 1.807 1.414 1.414 1.807-1.291c0.335 0.187 0.694 0.337 1.071 0.444l0.365 2.19h2l0.365-2.19c0.377-0.107 0.736-0.256 1.071-0.444l1.807 1.291 1.414-1.414-1.291-1.807c0.187-0.335 0.337-0.694 0.444-1.071l2.19-0.365v-2l-2.19-0.365c-0.107-0.377-0.256-0.736-0.444-1.071zM7 27c-1.105 0-2-0.895-2-2s0.895-2 2-2 2 0.895 2 2-0.895 2-2 2zM32 12v-2l-2.106-0.383c-0.039-0.251-0.088-0.499-0.148-0.743l1.799-1.159-0.765-1.848-2.092 0.452c-0.132-0.216-0.273-0.426-0.422-0.629l1.219-1.761-1.414-1.414-1.761 1.219c-0.203-0.149-0.413-0.29-0.629-0.422l0.452-2.092-1.848-0.765-1.159 1.799c-0.244-0.059-0.492-0.109-0.743-0.148l-0.383-2.106h-2l-0.383 2.106c-0.251 0.039-0.499 0.088-0.743 0.148l-1.159-1.799-1.848 0.765 0.452 2.092c-0.216 0.132-0.426 0.273-0.629 0.422l-1.761-1.219-1.414 1.414 1.219 1.761c-0.149 0.203-0.29 0.413-0.422 0.629l-2.092-0.452-0.765 1.848 1.799 1.159c-0.059 0.244-0.109 0.492-0.148 0.743l-2.106 0.383v2l2.106 0.383c0.039 0.251 0.088 0.499 0.148 0.743l-1.799 1.159 0.765 1.848 2.092-0.452c0.132 0.216 0.273 0.426 0.422 0.629l-1.219 1.761 1.414 1.414 1.761-1.219c0.203 0.149 0.413 0.29 0.629 0.422l-0.452 2.092 1.848 0.765 1.159-1.799c0.244 0.059 0.492 0.109 0.743 0.148l0.383 2.106h2l0.383-2.106c0.251-0.039 0.499-0.088 0.743-0.148l1.159 1.799 1.848-0.765-0.452-2.092c0.216-0.132 0.426-0.273 0.629-0.422l1.761 1.219 1.414-1.414-1.219-1.761c0.149-0.203 0.29-0.413 0.422-0.629l2.092 0.452 0.765-1.848-1.799-1.159c0.059-0.244 0.109-0.492 0.148-0.743l2.106-0.383zM21 15.35c-2.402 0-4.35-1.948-4.35-4.35s1.948-4.35 4.35-4.35 4.35 1.948 4.35 4.35c0 2.402-1.948 4.35-4.35 4.35z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,8 +0,0 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g transform="translate(1,1)">
|
||||
<path stroke="#ff3b00" transform="rotate(45 15 15)" d="m4,4 l 11,-4 l 11,4 l 4,11 l -4,11 l -11,4 l -11,-4 l -4,-11 l 4,-11 l 22,0 l 0,22 l -22,0 z" stroke-width="1" fill="#000000"/>
|
||||
<rect height="3" width="10" y="13.5" x="10" stroke-width="1" stroke="#ff3b00" />
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 404 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M16 18l8-8h-6v-8h-4v8h-6zM23.273 14.727l-2.242 2.242 8.128 3.031-13.158 4.907-13.158-4.907 8.127-3.031-2.242-2.242-8.727 3.273v8l16 6 16-6v-8z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 480 B |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M18 23l3 3 10-10-10-10-3 3 7 7z"></path>
|
||||
<path d="M14 9l-3-3-10 10 10 10 3-3-7-7z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 419 B |
@@ -1,3 +0,0 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="724" height="1024" viewBox="0 0 1024 1024">
|
||||
<path d="M0 1024c128-384 463-1024 1024-1024-263 211-384 704-576 704s-192 0-192 0l-192 320h-64z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 218 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M28 0h-28v32h32v-28l-4-4zM16 4h4v8h-4v-8zM28 28h-24v-24h2v10h18v-10h2.343l1.657 1.657v22.343z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 431 B |
@@ -1,3 +0,0 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zM9.464 26.067c0.347-0.957 0.536-1.99 0.536-3.067 0-3.886-2.463-7.197-5.913-8.456 0.319-2.654 1.508-5.109 3.427-7.029 2.267-2.266 5.28-3.515 8.485-3.515s6.219 1.248 8.485 3.515c1.92 1.92 3.108 4.375 3.428 7.029-3.45 1.26-5.913 4.57-5.913 8.456 0 1.077 0.189 2.11 0.536 3.067-1.928 1.258-4.18 1.933-6.536 1.933s-4.608-0.675-6.536-1.933zM17.242 20.031c0.434 0.109 0.758 0.503 0.758 0.969v2c0 0.55-0.45 1-1 1h-2c-0.55 0-1-0.45-1-1v-2c0-0.466 0.324-0.86 0.758-0.969l0.742-14.031h1l0.742 14.031z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 688 B |
@@ -1,3 +0,0 @@
|
||||
<svg height="1024" width="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M512 0C229.252 0 0 229.25199999999995 0 512c0 226.251 146.688 418.126 350.155 485.813 25.593 4.686 34.937-11.125 34.937-24.626 0-12.188-0.469-52.562-0.718-95.314-128.708 23.46-161.707-31.541-172.469-60.373-5.525-14.809-30.407-60.249-52.398-72.263-17.988-9.828-43.26-33.237-0.917-33.735 40.434-0.476 69.348 37.308 78.471 52.75 45.938 77.749 119.876 55.627 148.999 42.5 4.654-32.999 17.902-55.627 32.501-68.373-113.657-12.939-233.22-56.875-233.22-253.063 0-55.94 19.968-101.561 52.658-137.404-5.22-12.999-22.844-65.095 5.063-135.563 0 0 42.937-13.749 140.811 52.501 40.811-11.406 84.594-17.031 128.124-17.22 43.499 0.188 87.314 5.874 128.188 17.28 97.689-66.311 140.686-52.501 140.686-52.501 28 70.532 10.375 122.564 5.124 135.499 32.811 35.844 52.626 81.468 52.626 137.404 0 196.686-119.751 240-233.813 252.686 18.439 15.876 34.748 47.001 34.748 94.748 0 68.437-0.686 123.627-0.686 140.501 0 13.625 9.312 29.561 35.25 24.562C877.436 929.998 1024 738.126 1024 512 1024 229.25199999999995 794.748 0 512 0z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M31.562 25.905l-9.423-9.423c-0.583-0.583-1.538-0.583-2.121 0l-0.707 0.707-5.75-5.75 9.439-9.439h-10l-4.439 4.439-0.439-0.439h-2.121v2.121l0.439 0.439-6.439 6.439 5 5 6.439-6.439 5.75 5.75-0.707 0.707c-0.583 0.583-0.583 1.538 0 2.121l9.423 9.423c0.583 0.583 1.538 0.583 2.121 0l3.535-3.535c0.583-0.583 0.583-1.538 0-2.121z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 659 B |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M24.5 23.5c-2.003 0-3.887-0.78-5.303-2.197l-3.197-3.196-3.196 3.196c-1.417 1.417-3.3 2.197-5.303 2.197s-3.887-0.78-5.304-2.197c-1.417-1.417-2.197-3.3-2.197-5.303s0.78-3.887 2.197-5.304c1.417-1.417 3.3-2.197 5.304-2.197s3.887 0.78 5.303 2.197l3.196 3.196 3.196-3.196c1.417-1.417 3.3-2.197 5.303-2.197s3.887 0.78 5.303 2.197c1.417 1.417 2.197 3.3 2.197 5.304s-0.78 3.887-2.197 5.303c-1.416 1.417-3.3 2.197-5.303 2.197zM21.304 19.197c0.854 0.853 1.989 1.324 3.196 1.323s2.342-0.47 3.196-1.324c0.854-0.854 1.324-1.989 1.324-3.196s-0.47-2.342-1.324-3.196c-0.854-0.854-1.989-1.324-3.196-1.324s-2.342 0.47-3.196 1.324l-3.196 3.196 3.196 3.197zM7.5 11.48c-1.207 0-2.342 0.47-3.196 1.324s-1.324 1.989-1.324 3.196c0 1.207 0.47 2.342 1.324 3.196s1.989 1.324 3.196 1.324c1.207 0 2.342-0.47 3.196-1.324l3.196-3.196-3.196-3.196c-0.854-0.854-1.989-1.324-3.196-1.324v0z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M14 9.5c0-0.825 0.675-1.5 1.5-1.5h1c0.825 0 1.5 0.675 1.5 1.5v1c0 0.825-0.675 1.5-1.5 1.5h-1c-0.825 0-1.5-0.675-1.5-1.5v-1z"></path>
|
||||
<path d="M20 24h-8v-2h2v-6h-2v-2h6v8h2z"></path>
|
||||
<path d="M16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zM16 29c-7.18 0-13-5.82-13-13s5.82-13 13-13 13 5.82 13 13-5.82 13-13 13z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 675 B |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M13.757 19.868c-0.416 0-0.832-0.159-1.149-0.476-2.973-2.973-2.973-7.81 0-10.783l6-6c1.44-1.44 3.355-2.233 5.392-2.233s3.951 0.793 5.392 2.233c2.973 2.973 2.973 7.81 0 10.783l-2.743 2.743c-0.635 0.635-1.663 0.635-2.298 0s-0.635-1.663 0-2.298l2.743-2.743c1.706-1.706 1.706-4.481 0-6.187-0.826-0.826-1.925-1.281-3.094-1.281s-2.267 0.455-3.094 1.281l-6 6c-1.706 1.706-1.706 4.481 0 6.187 0.635 0.635 0.635 1.663 0 2.298-0.317 0.317-0.733 0.476-1.149 0.476z"></path>
|
||||
<path d="M8 31.625c-2.037 0-3.952-0.793-5.392-2.233-2.973-2.973-2.973-7.81 0-10.783l2.743-2.743c0.635-0.635 1.664-0.635 2.298 0s0.635 1.663 0 2.298l-2.743 2.743c-1.706 1.706-1.706 4.481 0 6.187 0.826 0.826 1.925 1.281 3.094 1.281s2.267-0.455 3.094-1.281l6-6c1.706-1.706 1.706-4.481 0-6.187-0.635-0.635-0.635-1.663 0-2.298s1.663-0.635 2.298 0c2.973 2.973 2.973 7.81 0 10.783l-6 6c-1.44 1.44-3.355 2.233-5.392 2.233z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,7 +0,0 @@
|
||||
<svg width="201" height="201" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle fill-opacity="0" r="70" cy="100" cx="100" stroke-width="5" />
|
||||
<line y2="60" x2="101" y1="0" x1="101" stroke-width="5" />
|
||||
<line y2="101" x2="200" y1="101" x1="140" stroke-width="5" />
|
||||
<line y2="101" x2="60" y1="101" x1="0" stroke-width="5" />
|
||||
<line y2="200" x2="101" y1="140" x1="101" stroke-width="5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 417 B |
@@ -1,4 +0,0 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<ellipse ry="25" rx="95" cy="100" cx="100" fill-opacity="0" stroke-width="5" />
|
||||
<ellipse ry="95" rx="25" cy="100" cx="100" fill-opacity="0" stroke-width="5" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 258 B |
@@ -1,5 +0,0 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<line y2="170" x2="162" y1="170" x1="8" stroke-width="6" />
|
||||
<path d="m13,138l144,0l0,-50l-27,-40l-90,0l-27,40l0,50z" id="svg_12" fill-opacity="0" stroke-width="6" />
|
||||
<line y2="91" x2="200" y1="91" x1="159" stroke-width="6" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 326 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M16 3c-3.472 0-6.737 1.352-9.192 3.808s-3.808 5.72-3.808 9.192c0 3.472 1.352 6.737 3.808 9.192s5.72 3.808 9.192 3.808c3.472 0 6.737-1.352 9.192-3.808s3.808-5.72 3.808-9.192c0-3.472-1.352-6.737-3.808-9.192s-5.72-3.808-9.192-3.808zM16 0v0c8.837 0 16 7.163 16 16s-7.163 16-16 16c-8.837 0-16-7.163-16-16s7.163-16 16-16zM14 22h4v4h-4zM14 6h4v12h-4z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 681 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M14 22h4v4h-4zM22 8c1.105 0 2 0.895 2 2v6l-6 4h-4v-2l6-4v-2h-10v-4h12zM16 3c-3.472 0-6.737 1.352-9.192 3.808s-3.808 5.72-3.808 9.192c0 3.472 1.352 6.737 3.808 9.192s5.72 3.808 9.192 3.808c3.472 0 6.737-1.352 9.192-3.808s3.808-5.72 3.808-9.192c0-3.472-1.352-6.737-3.808-9.192s-5.72-3.808-9.192-3.808zM16 0v0c8.837 0 16 7.163 16 16s-7.163 16-16 16c-8.837 0-16-7.163-16-16s7.163-16 16-16z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 723 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M22 2l-10 10h-6l-6 8c0 0 6.357-1.77 10.065-0.94l-10.065 12.94 13.184-10.255c1.839 4.208-1.184 10.255-1.184 10.255l8-6v-6l10-10 2-10-10 2z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 475 B |
@@ -1,3 +0,0 @@
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="33" height="33" viewBox="0 0 33 33">
|
||||
<path d="M32 12h-12l4.485-4.485c-2.267-2.266-5.28-3.515-8.485-3.515s-6.219 1.248-8.485 3.515c-2.266 2.267-3.515 5.28-3.515 8.485s1.248 6.219 3.515 8.485c2.267 2.266 5.28 3.515 8.485 3.515s6.219-1.248 8.485-3.515c0.189-0.189 0.371-0.384 0.546-0.583l3.010 2.634c-2.933 3.349-7.239 5.464-12.041 5.464-8.837 0-16-7.163-16-16s7.163-16 16-16c4.418 0 8.418 1.791 11.313 4.687l4.687-4.687v12z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 499 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M0 26h32v4h-32zM4 18h4v6h-4zM10 10h4v14h-4zM16 16h4v8h-4zM22 4h4v20h-4z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 409 B |
@@ -1,4 +0,0 @@
|
||||
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="33" height="33" viewBox="0 0 33 33">
|
||||
<path d="M20 4.581v4.249c1.131 0.494 2.172 1.2 3.071 2.099 1.889 1.889 2.929 4.4 2.929 7.071s-1.040 5.182-2.929 7.071c-1.889 1.889-4.4 2.929-7.071 2.929s-5.182-1.040-7.071-2.929c-1.889-1.889-2.929-4.4-2.929-7.071s1.040-5.182 2.929-7.071c0.899-0.899 1.94-1.606 3.071-2.099v-4.249c-5.783 1.721-10 7.077-10 13.419 0 7.732 6.268 14 14 14s14-6.268 14-14c0-6.342-4.217-11.698-10-13.419zM14 0h4v16h-4z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 510 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M14 18h4v-8h6l-8-8-8 8h6zM20 13.5v3.085l9.158 3.415-13.158 4.907-13.158-4.907 9.158-3.415v-3.085l-12 4.5v8l16 6 16-6v-8z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 458 B |
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path d="M16 2.899l13.409 26.726h-26.819l13.409-26.726zM16 0c-0.69 0-1.379 0.465-1.903 1.395l-13.659 27.222c-1.046 1.86-0.156 3.383 1.978 3.383h27.166c2.134 0 3.025-1.522 1.978-3.383h0l-13.659-27.222c-0.523-0.93-1.213-1.395-1.903-1.395v0z"></path>
|
||||
<path d="M18 26c0 1.105-0.895 2-2 2s-2-0.895-2-2c0-1.105 0.895-2 2-2s2 0.895 2 2z"></path>
|
||||
<path d="M16 22c-1.105 0-2-0.895-2-2v-6c0-1.105 0.895-2 2-2s2 0.895 2 2v6c0 1.105-0.895 2-2 2z"></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 762 B |
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="images/logo/mstile-70x70.png"/>
|
||||
<square150x150logo src="images/logo/mstile-150x150.png"/>
|
||||
<square310x310logo src="images/logo/mstile-310x310.png"/>
|
||||
<wide310x150logo src="images/logo/mstile-310x150.png"/>
|
||||
<TileColor>#000000</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="app" ng-strict-di="true" manifest="/coriolis.appcache">
|
||||
<head>
|
||||
<title ng-bind="title">Coriolis</title>
|
||||
<link rel="stylesheet" href="/app.css">
|
||||
|
||||
<!-- Standard headers -->
|
||||
<meta name="description" content="A ship builder, outfitting and comparison tool for Elite Dangerous">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
<link rel="manifest" href="/images/logo/manifest.json">
|
||||
<link rel="icon" sizes="152x152 192x192" type="image/png" href="/images/logo/192x192.png">
|
||||
<link rel="shortcut icon" href="/images/logo/favicon.ico">
|
||||
|
||||
<!-- Apple/iOS headers -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-title" content="Coriolis">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<link rel="apple-touch-icon-precomposed" sizes="180x180" href="/images/logo/apple-touch-icon-precomposed.png">
|
||||
<link rel="apple-touch-icon" href="/images/logo/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/logo/apple-touch-icon-180x180.png">
|
||||
<!-- iPhone, iPod Touch, portrait -->
|
||||
<link href="/images/splash/320x460.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone, iPod Touch, landscape -->
|
||||
<link href="/images/splash/480x320.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 4, 4S, portrait -->
|
||||
<link href="/images/splash/640x920.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 4, 4S, landscape -->
|
||||
<link href="/images/splash/960x640.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 5, 5S, 5C, portrait -->
|
||||
<link href="/images/splash/640x1096.png" media="(device-width: 320px) and (device-height: 568px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 5, 5S, 5C, landscape -->
|
||||
<link href="/images/splash/1136x640.png" media="(device-width: 320px) and (device-height: 568px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 6, portrait -->
|
||||
<link href="/images/splash/750x1294.png" media="(device-width: 375px) and (device-height: 667px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 6, landscape -->
|
||||
<link href="/images/splash/1334x750.png" media="(device-width: 375px) and (device-height: 667px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 6+, portrait -->
|
||||
<link href="/images/splash/1242x2148.png" media="(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image">
|
||||
<!-- iPhone 6+, landscape -->
|
||||
<link href="/images/splash/2208x1242.png" media="(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image">
|
||||
<!-- iPad 1, 2, Mini, portrait -->
|
||||
<link href="/images/splash/768x1004.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
|
||||
<!-- iPad 1, 2, Mini, landscape -->
|
||||
<link href="/images/splash/1024x748.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
|
||||
<!-- iPad 3, 4, Air, Air 2, Mini 2, Mini 3, portrait -->
|
||||
<link href="/images/splash/1536x2008.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
<!-- iPad 3, 4, Air, Air 2, Mini 2, Mini 3, landscape -->
|
||||
<link href="/images/splash/2048x1496.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
|
||||
|
||||
<!-- Microsoft Windows Phone/Tablet headers -->
|
||||
<meta name="msapplication-TileColor" content="#000000">
|
||||
<meta name="msapplication-TileImage" content="/images/logo/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="/images/logo/browserconfig.xml">
|
||||
<meta name="theme-color" content="#000000">
|
||||
</head>
|
||||
<body style="background-color:#000;">
|
||||
<div style="height: 0; width: 0; overflow:hidden"><%= svgContent %></div>
|
||||
<shipyard-header></shipyard-header>
|
||||
<div id="main" ui-view ng-click="bgClicked($event)"></div>
|
||||
|
||||
<div ui-view="modal" ng-click="bgClicked($event)"></div>
|
||||
|
||||
<footer>
|
||||
<div class="right">
|
||||
<a href="https://github.com/cmmcleod/coriolis/releases/" target="_blank" title="Coriolis Github Project">Version <%= version %> - <%= date %></a>
|
||||
</div>
|
||||
<div style="max-width:50%" class="l">
|
||||
Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments and no employee of Frontier Developments was involved in the making of it.
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="/lib.js" type="text/javascript"></script>
|
||||
<script src="/app.js" type="text/javascript"></script>
|
||||
<% if (uaTracking) { %>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '<%= uaTracking %> ', 'auto');
|
||||
var GAPI_KEY = '<%= gapiKey %>';
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
101
app/js/app.js
@@ -1,101 +0,0 @@
|
||||
angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'ui.sortable', 'shipyard', 'ngLodash', 'app.templates'])
|
||||
.run(['$rootScope', '$location', '$window', '$document', '$state', 'commonArray', 'shipSize', 'hardPointClass', 'GroupMap', 'Persist', 'Discounts',
|
||||
function($rootScope, $location, $window, $doc, $state, CArr, sz, hpc, GroupMap, Persist, Discounts) {
|
||||
// App is running as a standalone web app on tablet/mobile
|
||||
var isStandAlone;
|
||||
// This was causing issues on Windows phones ($window.external was causing Angular js to throw an exception). Backup is to try this and set isStandAlone to false if this fails.
|
||||
try {
|
||||
isStandAlone = $window.navigator.standalone || ($window.external && $window.external.msIsSiteMode && $window.external.msIsSiteMode());
|
||||
} catch (ex) {
|
||||
isStandAlone = false;
|
||||
}
|
||||
|
||||
// Redirect any state transition errors to the error controller/state
|
||||
$rootScope.$on('$stateChangeError', function(e, toState, toParams, fromState, fromParams, error) {
|
||||
e.preventDefault();
|
||||
$state.go('error', error, { location: false, reload: true }); // Go to error state, reload the controller, keep the current URL
|
||||
});
|
||||
|
||||
// Track on Google analytics if available
|
||||
$rootScope.$on('$stateChangeSuccess', function(e, to, toParams, from, fromParams) {
|
||||
$rootScope.prevState = { name: from.name, params: fromParams };
|
||||
|
||||
if (to.url) { // Only track states that have a URL
|
||||
|
||||
if ($window.ga) {
|
||||
ga('send', 'pageview', { page: $location.path() });
|
||||
}
|
||||
|
||||
if (isStandAlone) {
|
||||
// Persist the current state
|
||||
Persist.setState({ name: to.name, params: toParams });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Global Reference variables
|
||||
$rootScope.CArr = CArr;
|
||||
$rootScope.SZ = sz;
|
||||
$rootScope.HPC = hpc;
|
||||
$rootScope.GMAP = GroupMap;
|
||||
$rootScope.insurance = { opts: [{ name: 'Standard', pct: 0.05 }, { name: 'Alpha', pct: 0.025 }, { name: 'Beta', pct: 0.0375 }] };
|
||||
$rootScope. discounts = { opts: Discounts };
|
||||
$rootScope.STATUS = ['', 'DISABLED', 'OFF', 'ON'];
|
||||
$rootScope.STATUS_CLASS = ['', 'disabled', 'warning', 'secondary-disabled'];
|
||||
$rootScope.title = 'Coriolis';
|
||||
|
||||
/**
|
||||
* Returns the name of the component mounted in the specified slot
|
||||
* @param {Object} slot The slot object
|
||||
* @return {String} The component name
|
||||
*/
|
||||
$rootScope.cName = function(slot) {
|
||||
return slot.c ? slot.c.name ? slot.c.name : GroupMap[slot.c.grp] : null;
|
||||
};
|
||||
|
||||
// Formatters
|
||||
$rootScope.fCrd = d3.format(',.0f');
|
||||
$rootScope.fPwr = d3.format(',.2f');
|
||||
$rootScope.fRound = function(d) { return d3.round(d, 2); };
|
||||
$rootScope.fRound4 = function(d) { return d3.round(d, 4); };
|
||||
$rootScope.fPct = d3.format('.2%');
|
||||
$rootScope.f1Pct = d3.format('.1%');
|
||||
$rootScope.fRPct = d3.format('%');
|
||||
$rootScope.fTime = function(d) { return Math.floor(d / 60) + ':' + ('00' + Math.floor(d % 60)).substr(-2, 2); };
|
||||
|
||||
if (isStandAlone) {
|
||||
var state = Persist.getState();
|
||||
// If a previous state has been stored, load that state
|
||||
if (state && state.name && state.params) {
|
||||
$state.go(state.name, state.params, { location: 'replace' });
|
||||
} else {
|
||||
$state.go('shipyard', null, { location: 'replace' }); // Default to home page
|
||||
}
|
||||
}
|
||||
|
||||
// Global Event Listeners
|
||||
$doc.bind('keyup', function(e) {
|
||||
if (e.keyCode == 27) { // Escape Key
|
||||
$rootScope.$broadcast('close', e);
|
||||
$rootScope.$apply();
|
||||
} else {
|
||||
$rootScope.$broadcast('keyup', e);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.bgClicked = function(e) {
|
||||
$rootScope.$broadcast('close', e);
|
||||
};
|
||||
|
||||
if ($window.applicationCache) {
|
||||
// Listen for appcache updated event, present refresh to update view
|
||||
$window.applicationCache.addEventListener('updateready', function() {
|
||||
if ($window.applicationCache.status == $window.applicationCache.UPDATEREADY) {
|
||||
// Browser downloaded a new app cache.
|
||||
$rootScope.appCacheUpdate = true;
|
||||
$rootScope.$apply();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
}]);
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Sets up the routes and handlers before the Angular app is kicked off.
|
||||
*/
|
||||
angular.module('app').config(['$provide', '$stateProvider', '$urlRouterProvider', '$locationProvider', 'ShipsDB', function($provide, $stateProvider, $urlRouterProvider, $locationProvider, ships) {
|
||||
// Use HTML5 push and replace state if possible
|
||||
$locationProvider.html5Mode({ enabled: true, requireBase: false });
|
||||
/**
|
||||
* Set up all states and their routes.
|
||||
*/
|
||||
$stateProvider
|
||||
.state('outfit', {
|
||||
url: '/outfit/:shipId/:code?bn',
|
||||
params: {
|
||||
shipId: { value: 'sidewinder', squash: false }, // Allow 'shipId' parameter to default to sidewinder
|
||||
code: { value: null, squash: true } // Allow 'code' parameter to be empty/optional
|
||||
},
|
||||
templateUrl: 'views/page-outfit.html',
|
||||
controller: 'OutfitController',
|
||||
resolve: {
|
||||
shipId: ['$stateParams', function($p) { // Ensure ship exists before loading controller
|
||||
if (!ships[$p.shipId]) {
|
||||
throw { type: 'no-ship', message: $p.shipId };
|
||||
}
|
||||
}]
|
||||
},
|
||||
sticky: true
|
||||
})
|
||||
.state('compare', {
|
||||
url: '/compare/:name',
|
||||
params: {
|
||||
name: { value: null, squash: true }
|
||||
},
|
||||
templateUrl: 'views/page-comparison.html',
|
||||
controller: 'ComparisonController',
|
||||
sticky: true
|
||||
})
|
||||
.state('comparison', {
|
||||
url: '/comparison/:code',
|
||||
templateUrl: 'views/page-comparison.html',
|
||||
controller: 'ComparisonController',
|
||||
sticky: true
|
||||
})
|
||||
.state('shipyard', { url: '/', templateUrl: 'views/page-shipyard.html', controller: 'ShipyardController', sticky: true })
|
||||
.state('error', { params: { type: null, message: null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController', sticky: true })
|
||||
|
||||
// Modal States and views
|
||||
.state('modal', { abstract: true, views: { 'modal': { templateUrl: 'views/_modal.html', controller: 'ModalController' } } })
|
||||
.state('modal.about', { views: { 'modal-content': { templateUrl: 'views/modal-about.html' } } })
|
||||
.state('modal.export', { params: { title: null, data: null, promise: null, description: null }, views: { 'modal-content': { templateUrl: 'views/modal-export.html', controller: 'ExportController' } } })
|
||||
.state('modal.import', { params: { obj: null }, views: { 'modal-content': { templateUrl: 'views/modal-import.html', controller: 'ImportController' } } })
|
||||
.state('modal.link', { params: { url: null }, views: { 'modal-content': { templateUrl: 'views/modal-link.html', controller: 'LinkController' } } })
|
||||
.state('modal.delete', { views: { 'modal-content': { templateUrl: 'views/modal-delete.html', controller: 'DeleteController' } } });
|
||||
|
||||
|
||||
// Redirects
|
||||
$urlRouterProvider.when('/outfit', '/outfit/sidewinder');
|
||||
|
||||
/**
|
||||
* 404 Handler - Keep current URL/ do not redirect, change to error state.
|
||||
*/
|
||||
$urlRouterProvider.otherwise(function($injector, $location) {
|
||||
// Go to error state, reload the controller, keep the current URL
|
||||
$injector.get('$state').go('error', { type: 404, message: null, details: null }, { location: false, reload: true });
|
||||
return $location.path;
|
||||
});
|
||||
|
||||
/**
|
||||
* Global Error Handler. Decorates the existing error handler such that it
|
||||
* redirects uncaught errors to the error page.
|
||||
*
|
||||
*/
|
||||
$provide.decorator('$exceptionHandler', ['$delegate', '$injector', function($delegate, $injector) {
|
||||
return function(err, cause) {
|
||||
// Go to error state, reload the controller, keep the current URL
|
||||
$injector.get('$state').go('error', { type: null, message: err.message, details: err.stack }, { location: false, reload: true });
|
||||
$delegate(err, cause);
|
||||
};
|
||||
}]);
|
||||
|
||||
}]);
|
||||
@@ -1,234 +0,0 @@
|
||||
angular.module('app').controller('ComparisonController', ['lodash', '$rootScope', '$filter', '$scope', '$state', '$stateParams', 'Utils', 'ShipFacets', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function(_, $rootScope, $filter, $scope, $state, $stateParams, Utils, ShipFacets, Ships, Ship, Persist, Serializer) {
|
||||
$rootScope.title = 'Coriolis - Compare';
|
||||
$scope.predicate = 'name'; // Sort by ship name as default
|
||||
$scope.desc = false;
|
||||
$scope.facetSortOpts = { containment: '#facet-container', orderChanged: function() { $scope.saved = false; } };
|
||||
$scope.builds = [];
|
||||
$scope.unusedBuilds = [];
|
||||
$scope.name = $stateParams.name;
|
||||
$scope.compareMode = !$stateParams.code;
|
||||
$scope.importObj = {}; // Used for importing comparison builds (from permalinked comparison)
|
||||
var defaultFacets = [9, 6, 4, 1, 3, 2]; // Reverse order of Armour, Shields, Speed, Jump Range, Cargo Capacity, Cost
|
||||
var facets = $scope.facets = angular.copy(ShipFacets);
|
||||
var shipId, buildName, comparisonData;
|
||||
|
||||
/**
|
||||
* Add an existing build to the comparison. The build must be saved locally.
|
||||
* @param {string} id The unique ship key/id
|
||||
* @param {string} name The build name
|
||||
*/
|
||||
$scope.addBuild = function(id, name, code) {
|
||||
var data = Ships[id]; // Get ship properties
|
||||
code = code ? code : Persist.builds[id][name]; // Retrieve build code if not passed
|
||||
var b = new Ship(id, data.properties, data.slots); // Create a new Ship instance
|
||||
Serializer.toShip(b, code); // Populate components from code
|
||||
// Extend ship instance and add properties below
|
||||
b.buildName = name;
|
||||
b.code = code;
|
||||
b.pctRetracted = b.powerRetracted / b.powerAvailable;
|
||||
b.pctDeployed = b.powerDeployed / b.powerAvailable;
|
||||
$scope.builds.push(b); // Add ship build to comparison
|
||||
$scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc); // Resort
|
||||
_.remove($scope.unusedBuilds, function(o) { // Remove from unused builds
|
||||
return o.id == id && o.buildName == name;
|
||||
});
|
||||
$scope.saved = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a build from the comparison
|
||||
* @param {string} id The unique ship key/id
|
||||
* @param {string} name The build name
|
||||
*/
|
||||
$scope.removeBuild = function(id, name) {
|
||||
_.remove($scope.builds, function(s) {
|
||||
if (s.id == id && s.buildName == name) {
|
||||
$scope.unusedBuilds.push({ id: id, buildName: name, name: s.name }); // Add build back to unused builds
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$scope.saved = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles the selected the set of facets used in the comparison
|
||||
* @param {number} i The index of the facet in facets
|
||||
*/
|
||||
$scope.toggleFacet = function(i) {
|
||||
facets[i].active = !facets[i].active;
|
||||
$scope.tblUpdate = !$scope.tblUpdate; // Simple switch to trigger the table to update
|
||||
$scope.saved = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Click handler for sorting by facets in the table
|
||||
* @param {object} e Event object
|
||||
*/
|
||||
$scope.handleClick = function(e) {
|
||||
var elem = angular.element(e.target);
|
||||
if (elem.attr('prop')) { // Get component ID
|
||||
$scope.sort(elem.attr('prop'));
|
||||
|
||||
} else if (elem.attr('del')) { // Delete index
|
||||
$scope.removeBuild(elem.attr('del'));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort the comparison array based on the selected facet / ship property
|
||||
* @param {string} key Ship property
|
||||
*/
|
||||
$scope.sort = function(key) {
|
||||
$scope.desc = $scope.predicate == key ? !$scope.desc : $scope.desc;
|
||||
$scope.predicate = key;
|
||||
$scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc);
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the current comparison's selected facets and builds
|
||||
*/
|
||||
$scope.save = function() {
|
||||
$scope.name = $scope.name.trim();
|
||||
if ($scope.name == 'all') {
|
||||
return;
|
||||
}
|
||||
var selectedFacets = [];
|
||||
facets.forEach(function(f) {
|
||||
if (f.active) {
|
||||
selectedFacets.unshift(f.index);
|
||||
}
|
||||
});
|
||||
Persist.saveComparison($scope.name, $scope.builds, selectedFacets);
|
||||
$state.go('compare', { name: $scope.name }, { location: 'replace', notify: false });
|
||||
$scope.saved = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Permantently delete the current comparison
|
||||
*/
|
||||
$scope.delete = function() {
|
||||
Persist.deleteComparison($scope.name);
|
||||
$state.go('compare', { name: null }, { location: 'replace', reload: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* Set saved to false when the name of the comparison is changed.
|
||||
*/
|
||||
$scope.nameChange = function() {
|
||||
$scope.saved = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide/Show the select builds menu
|
||||
* @param {boolean} s Show true/false
|
||||
* @param {Event} e Event Object
|
||||
*/
|
||||
$scope.selectBuilds = function(s, e) {
|
||||
e.stopPropagation();
|
||||
$scope.showBuilds = s;
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the permalink modal
|
||||
* @param {Event} e Event object
|
||||
*/
|
||||
$scope.permalink = function(e) {
|
||||
e.stopPropagation();
|
||||
$state.go('modal.link', { url: genPermalink() });
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate the forum embed code for the comparison
|
||||
* and show the export modal.
|
||||
*
|
||||
* @param {Event} e Event object
|
||||
*/
|
||||
$scope.embed = function(e) {
|
||||
e.stopPropagation();
|
||||
// Make a request to goo.gl to shorten the URL, returns a promise
|
||||
var promise = Utils.shortenUrl( genPermalink()).then(
|
||||
function(shortUrl) {
|
||||
return Utils.comparisonBBCode(facets, $scope.builds, shortUrl);
|
||||
},
|
||||
function(err) {
|
||||
return 'Error - ' + err.statusText;
|
||||
}
|
||||
);
|
||||
$state.go('modal.export', { promise: promise, title: 'Forum BBCode' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the long permalink URL
|
||||
* @return {string} The long permalink URL
|
||||
*/
|
||||
function genPermalink() {
|
||||
var selectedFacets = [];
|
||||
facets.forEach(function(f) {
|
||||
if (f.active) {
|
||||
selectedFacets.unshift(f.index);
|
||||
}
|
||||
});
|
||||
var code = Serializer.fromComparison(
|
||||
$scope.name,
|
||||
$scope.builds,
|
||||
selectedFacets,
|
||||
$scope.predicate,
|
||||
$scope.desc
|
||||
);
|
||||
return $state.href('comparison', { code: code }, { absolute: true });
|
||||
}
|
||||
|
||||
/* Event listeners */
|
||||
$scope.$on('close', function() {
|
||||
$scope.showBuilds = false;
|
||||
});
|
||||
|
||||
/* Initialization */
|
||||
if ($scope.compareMode) {
|
||||
if ($scope.name == 'all') {
|
||||
for (shipId in Persist.builds) {
|
||||
for (buildName in Persist.builds[shipId]) {
|
||||
$scope.addBuild(shipId, buildName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (shipId in Persist.builds) {
|
||||
for (buildName in Persist.builds[shipId]) {
|
||||
$scope.unusedBuilds.push({ id: shipId, buildName: buildName, name: Ships[shipId].properties.name });
|
||||
}
|
||||
}
|
||||
comparisonData = Persist.getComparison($scope.name);
|
||||
if (comparisonData) {
|
||||
defaultFacets = comparisonData.facets;
|
||||
comparisonData.builds.forEach(function(b) {
|
||||
$scope.addBuild(b.shipId, b.buildName);
|
||||
});
|
||||
$scope.saved = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
comparisonData = Serializer.toComparison($stateParams.code);
|
||||
defaultFacets = comparisonData.f;
|
||||
$scope.name = comparisonData.n;
|
||||
$scope.predicate = comparisonData.p;
|
||||
$scope.desc = comparisonData.d;
|
||||
comparisonData.b.forEach(function(build) {
|
||||
$scope.addBuild(build.s, build.n, build.c);
|
||||
if (!$scope.importObj[build.s]) {
|
||||
$scope.importObj[build.s] = {};
|
||||
}
|
||||
$scope.importObj[build.s][build.n] = build.c;
|
||||
});
|
||||
} catch (e) {
|
||||
throw { type: 'bad-comparison', message: e.message, details: e };
|
||||
}
|
||||
}
|
||||
// Replace fmt with actual format function as defined in rootScope and retain original index
|
||||
facets.forEach(function(f, i) { f.fmt = $rootScope[f.fmt]; f.index = i; });
|
||||
// Remove default facets, mark as active, and add them back in selected order
|
||||
_.pullAt(facets, defaultFacets).forEach(function(f) { f.active = true; facets.unshift(f); });
|
||||
$scope.builds = $filter('orderBy')($scope.builds, $scope.predicate, $scope.desc);
|
||||
|
||||
}]);
|
||||
@@ -1,7 +0,0 @@
|
||||
angular.module('app').controller('DeleteController', ['$scope', 'Persist', function($scope, Persist) {
|
||||
$scope.deleteAll = function() {
|
||||
Persist.deleteAll();
|
||||
$scope.$parent.dismiss();
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,29 +0,0 @@
|
||||
angular.module('app')
|
||||
.controller('ErrorController', ['$window', '$rootScope', '$scope', '$stateParams', '$location', function($window, $rootScope, $scope, $p, $location) {
|
||||
$rootScope.title = 'Error';
|
||||
$scope.path = $location.path();
|
||||
$scope.type = $p.type || 'unknown';
|
||||
$scope.browser = $window.navigator.userAgent;
|
||||
|
||||
switch ($scope.type) {
|
||||
case 404:
|
||||
$scope.msgPre = 'Page';
|
||||
$scope.msgHighlight = $scope.path;
|
||||
$scope.msgPost = 'Not Found';
|
||||
break;
|
||||
case 'no-ship':
|
||||
$scope.msgPre = 'Ship';
|
||||
$scope.msgHighlight = $p.message;
|
||||
$scope.msgPost = 'does not exist';
|
||||
break;
|
||||
case 'build-fail':
|
||||
$scope.msgPre = 'Build Failure!';
|
||||
$scope.details = $p.details;
|
||||
break;
|
||||
default:
|
||||
$scope.msgPre = 'Uh, Jameson, we have a problem..';
|
||||
$scope.errorMessage = $p.message;
|
||||
$scope.details = $p.details;
|
||||
}
|
||||
|
||||
}]);
|
||||
@@ -1,19 +0,0 @@
|
||||
angular.module('app').controller('ExportController', ['$scope', '$stateParams', function($scope, $stateParams) {
|
||||
|
||||
$scope.title = $stateParams.title || 'Export';
|
||||
$scope.description = $stateParams.description;
|
||||
|
||||
if ($stateParams.promise) {
|
||||
$scope.export = 'Generating...';
|
||||
$stateParams.promise.then(function(data) {
|
||||
$scope.export = (typeof data === 'object') ? angular.toJson(data, true) : data;
|
||||
});
|
||||
} else {
|
||||
$scope.export = angular.toJson($stateParams.data, true);
|
||||
}
|
||||
|
||||
$scope.onTextClick = function($event) {
|
||||
$event.target.select();
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,196 +0,0 @@
|
||||
angular.module('app').controller('ImportController', ['lodash', '$rootScope', '$scope', '$stateParams', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function(_, $rootScope, $scope, $stateParams, Ships, Ship, Persist, Serializer) {
|
||||
$scope.jsonValid = false;
|
||||
$scope.importJSON = null;
|
||||
$scope.errorMsg = null;
|
||||
$scope.canEdit = true;
|
||||
$scope.builds = $stateParams.obj || null;
|
||||
$scope.ships = Ships;
|
||||
|
||||
function validateBuild(shipId, code, name) {
|
||||
var shipData = Ships[shipId];
|
||||
|
||||
if (!shipData) {
|
||||
throw '"' + shipId + '" is not a valid Ship Id!';
|
||||
}
|
||||
if (typeof name != 'string' || name.length < 3) {
|
||||
throw shipData.properties.name + ' build "' + name + '" must be a string at least 3 characters long!';
|
||||
}
|
||||
if (typeof code != 'string' || code.length < 10) {
|
||||
throw shipData.properties.name + ' build "' + name + '" is not valid!';
|
||||
}
|
||||
try {
|
||||
Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), code);
|
||||
} catch (e) {
|
||||
throw shipData.properties.name + ' build "' + name + '" is not valid!';
|
||||
}
|
||||
}
|
||||
|
||||
function detailedJsonToBuild(detailedBuild) {
|
||||
var ship;
|
||||
if (!detailedBuild.name) {
|
||||
throw 'Build Name missing!';
|
||||
}
|
||||
|
||||
try {
|
||||
ship = Serializer.fromDetailedBuild(detailedBuild);
|
||||
} catch (e) {
|
||||
throw detailedBuild.ship + ' Build "' + detailedBuild.name + '": Invalid data';
|
||||
}
|
||||
|
||||
return { shipId: ship.id, name: detailedBuild.name, code: Serializer.fromShip(ship) };
|
||||
}
|
||||
|
||||
function importBackup(importData) {
|
||||
if (importData.builds && typeof importData.builds == 'object') {
|
||||
for (var shipId in importData.builds) {
|
||||
for (var buildName in importData.builds[shipId]) {
|
||||
validateBuild(shipId, importData.builds[shipId][buildName], buildName);
|
||||
}
|
||||
}
|
||||
$scope.builds = importData.builds;
|
||||
} else {
|
||||
throw 'builds must be an object!';
|
||||
}
|
||||
if (importData.comparisons) {
|
||||
// TODO: check ship/builds exist for comparison
|
||||
$scope.comparisons = importData.comparisons;
|
||||
}
|
||||
if (importData.discounts instanceof Array && importData.discounts.length == 2) {
|
||||
$scope.discounts = importData.discounts;
|
||||
}
|
||||
if (typeof importData.insurance == 'string' && importData.insurance.length > 3) {
|
||||
$scope.insurance = importData.insurance;
|
||||
}
|
||||
}
|
||||
|
||||
function importDetailedArray(importArr) {
|
||||
var builds = {};
|
||||
for (var i = 0, l = importArr.length; i < l; i++) {
|
||||
var build = detailedJsonToBuild(importArr[i]);
|
||||
if (!builds[build.shipId]) {
|
||||
builds[build.shipId] = {};
|
||||
}
|
||||
builds[build.shipId][build.name] = build.code;
|
||||
}
|
||||
$scope.builds = builds;
|
||||
}
|
||||
|
||||
$scope.validateJson = function() {
|
||||
var importData = null;
|
||||
$scope.jsonValid = false;
|
||||
$scope.errorMsg = null;
|
||||
$scope.builds = $scope.discounts = $scope.comparisons = $scope.insurance = null;
|
||||
|
||||
if (!$scope.importJSON) { return; }
|
||||
|
||||
try {
|
||||
importData = angular.fromJson($scope.importJSON);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = 'Cannot Parse JSON!';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!importData || typeof importData != 'object') {
|
||||
$scope.errorMsg = 'Must be an object or array!';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (importData instanceof Array) { // Must be detailed export json
|
||||
importDetailedArray(importData);
|
||||
} else if (importData.ship && importData.name) { // Using JSON from a single ship build export
|
||||
importDetailedArray([importData]); // Convert to array with singleobject
|
||||
} else { // Using Backup JSON
|
||||
importBackup(importData);
|
||||
}
|
||||
} catch (e) {
|
||||
$scope.errorMsg = e;
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.jsonValid = true;
|
||||
};
|
||||
|
||||
$scope.hasBuild = function(shipId, name) {
|
||||
return Persist.getBuild(shipId, name) !== null;
|
||||
};
|
||||
|
||||
$scope.hasComparison = function(name) {
|
||||
return Persist.getComparison(name) !== null;
|
||||
};
|
||||
|
||||
$scope.process = function() {
|
||||
if ($scope.builds) {
|
||||
var builds = $scope.builds;
|
||||
for (var shipId in builds) {
|
||||
for (var buildName in builds[shipId]) {
|
||||
var code = builds[shipId][buildName];
|
||||
// Update builds object such that orginal name retained, but can be renamed
|
||||
builds[shipId][buildName] = {
|
||||
code: code,
|
||||
useName: buildName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.comparisons) {
|
||||
var comparisons = $scope.comparisons;
|
||||
for (var name in comparisons) {
|
||||
comparisons[name].useName = name;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.processed = true;
|
||||
};
|
||||
|
||||
$scope.import = function() {
|
||||
|
||||
if ($scope.builds) {
|
||||
var builds = $scope.builds;
|
||||
for (var shipId in builds) {
|
||||
for (var buildName in builds[shipId]) {
|
||||
var build = builds[shipId][buildName];
|
||||
var name = build.useName.trim();
|
||||
if (name) {
|
||||
Persist.saveBuild(shipId, name, build.code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.comparisons) {
|
||||
var comparisons = $scope.comparisons;
|
||||
for (var comp in comparisons) {
|
||||
var comparison = comparisons[comp];
|
||||
var useName = comparison.useName.trim();
|
||||
if (useName) {
|
||||
Persist.saveComparison(useName, comparison.builds, comparison.facets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope.discounts) {
|
||||
$rootScope.discounts.ship = $scope.discounts[0];
|
||||
$rootScope.discounts.components = $scope.discounts[1];
|
||||
$rootScope.$broadcast('discountChange');
|
||||
Persist.setDiscount($scope.discounts);
|
||||
}
|
||||
|
||||
if ($scope.insurance) {
|
||||
$rootScope.insurance.current = $scope.insurance;
|
||||
Persist.setInsurance($scope.insurance);
|
||||
}
|
||||
|
||||
$scope.$parent.dismiss();
|
||||
};
|
||||
|
||||
/* Initialization */
|
||||
|
||||
if ($scope.builds) { // If import is passed an build object
|
||||
$scope.canEdit = false;
|
||||
$scope.process();
|
||||
}
|
||||
|
||||
|
||||
}]);
|
||||
@@ -1,16 +0,0 @@
|
||||
angular.module('app').controller('LinkController', ['$scope', 'Utils', '$stateParams', function($scope, Utils, $stateParams) {
|
||||
$scope.url = $stateParams.url;
|
||||
$scope.shortenedUrl = 'Shortening...';
|
||||
|
||||
$scope.onTextClick = function($event) {
|
||||
$event.target.select();
|
||||
};
|
||||
|
||||
Utils.shortenUrl($scope.url)
|
||||
.then(function(url) {
|
||||
$scope.shortenedUrl = url;
|
||||
}, function(e) {
|
||||
$scope.shortenedUrl = 'Error - ' + e.statusText;
|
||||
});
|
||||
|
||||
}]);
|
||||
@@ -1,14 +0,0 @@
|
||||
angular.module('app').controller('ModalController', ['$rootScope', '$scope', '$state', function($rootScope, $scope, $state) {
|
||||
|
||||
$scope.dismiss = function() {
|
||||
if ($rootScope.prevState) {
|
||||
var state = $rootScope.prevState;
|
||||
$state.go(state.name, state.params, { location: 'replace', reload: false });
|
||||
} else {
|
||||
$state.go('shipyard');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$on('close', $scope.dismiss);
|
||||
|
||||
}]);
|
||||
@@ -1,390 +0,0 @@
|
||||
angular.module('app').controller('OutfitController', ['$window', '$rootScope', '$scope', '$state', '$stateParams', 'ShipsDB', 'Ship', 'Components', 'Serializer', 'Persist', 'calcTotalRange', 'calcSpeed', function($window, $rootScope, $scope, $state, $p, Ships, Ship, Components, Serializer, Persist, calcTotalRange, calcSpeed) {
|
||||
var win = angular.element($window); // Angularized window object for event triggering
|
||||
var data = Ships[$p.shipId]; // Retrieve the basic ship properties, slots and defaults
|
||||
var ship = new Ship($p.shipId, data.properties, data.slots); // Create a new Ship instance
|
||||
var retrofitShip = new Ship($p.shipId, data.properties, data.slots); // Create a new Ship for retrofit comparison
|
||||
|
||||
// Update the ship instance with the code (if provided) or the 'factory' defaults.
|
||||
if ($p.code) {
|
||||
Serializer.toShip(ship, $p.code); // Populate components from 'code' URL param
|
||||
$scope.code = $p.code;
|
||||
} else {
|
||||
ship.buildWith(data.defaults); // Populate with default components
|
||||
}
|
||||
|
||||
$scope.buildName = $p.bn;
|
||||
$rootScope.title = ship.name + ($scope.buildName ? ' - ' + $scope.buildName : '');
|
||||
$scope.ship = ship;
|
||||
$scope.pp = ship.common[0]; // Power Plant
|
||||
$scope.th = ship.common[1]; // Thruster
|
||||
$scope.fsd = ship.common[2]; // Frame Shrift Drive
|
||||
$scope.ls = ship.common[3]; // Life Support
|
||||
$scope.pd = ship.common[4]; // Power Distributor
|
||||
$scope.ss = ship.common[5]; // Sensors
|
||||
$scope.ft = ship.common[6]; // Fuel Tank
|
||||
$scope.hps = ship.hardpoints;
|
||||
$scope.internal = ship.internal;
|
||||
$scope.costList = ship.costList;
|
||||
$scope.powerList = ship.powerList;
|
||||
$scope.priorityBands = ship.priorityBands;
|
||||
$scope.availCS = Components.forShip(ship.id);
|
||||
$scope.selectedSlot = null;
|
||||
$scope.savedCode = Persist.getBuild(ship.id, $scope.buildName);
|
||||
$scope.canSave = Persist.isEnabled();
|
||||
$scope.allBuilds = Persist.builds;
|
||||
$scope.fuel = 0;
|
||||
$scope.pwrDesc = false;
|
||||
$scope.pwrPredicate = 'type';
|
||||
$scope.retroDesc = false;
|
||||
$scope.retroPredicate = 'netCost';
|
||||
$scope.costDesc = true;
|
||||
$scope.costPredicate = 'c.cost';
|
||||
$scope.costTab = Persist.getCostTab() || 'costs';
|
||||
|
||||
if ($scope.savedCode) {
|
||||
Serializer.toShip(retrofitShip, $scope.savedCode); // Populate components from last save
|
||||
$scope.retrofitBuild = $scope.buildName;
|
||||
} else {
|
||||
retrofitShip.buildWith(data.defaults);
|
||||
$scope.retrofitBuild = null;
|
||||
}
|
||||
|
||||
ship.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
|
||||
retrofitShip.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
|
||||
updateRetrofitCosts();
|
||||
|
||||
$scope.jrSeries = {
|
||||
xMin: 0,
|
||||
xMax: ship.cargoCapacity,
|
||||
yMax: ship.unladenRange,
|
||||
yMin: 0,
|
||||
func: function(cargo) { // X Axis is Cargo
|
||||
return ship.jumpRangeWithMass(ship.unladenMass + $scope.fuel + cargo, $scope.fuel);
|
||||
}
|
||||
};
|
||||
$scope.jrChart = {
|
||||
labels: {
|
||||
xAxis: {
|
||||
title: 'Cargo',
|
||||
unit: 'T'
|
||||
},
|
||||
yAxis: {
|
||||
title: 'Jump Range',
|
||||
unit: 'LY'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.trSeries = {
|
||||
xMin: 0,
|
||||
xMax: ship.cargoCapacity,
|
||||
yMax: ship.unladenTotalRange,
|
||||
yMin: 0,
|
||||
func: function(cargo) { // X Axis is Cargo
|
||||
return calcTotalRange(ship.unladenMass + cargo, $scope.fsd.c, $scope.fuel);
|
||||
}
|
||||
};
|
||||
$scope.trChart = {
|
||||
labels: {
|
||||
xAxis: {
|
||||
title: 'Cargo',
|
||||
unit: 'T'
|
||||
},
|
||||
yAxis: {
|
||||
title: 'Total Range',
|
||||
unit: 'LY'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.speedSeries = {
|
||||
xMin: 0,
|
||||
xMax: ship.cargoCapacity,
|
||||
yMax: 500,
|
||||
yMin: 0,
|
||||
series: ['speed', 'boost'],
|
||||
func: function(cargo) { // X Axis is Cargo
|
||||
return calcSpeed(ship.unladenMass + $scope.fuel + cargo, ship.speed, ship.boost, $scope.th.c);
|
||||
}
|
||||
};
|
||||
$scope.speedChart = {
|
||||
labels: {
|
||||
xAxis: {
|
||||
title: 'Cargo',
|
||||
unit: 'T'
|
||||
},
|
||||
yAxis: {
|
||||
title: 'Speed',
|
||||
unit: 'm/s'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 'Opens' a select for component selection.
|
||||
*
|
||||
* @param {[type]} e The event object
|
||||
* @param {[type]} slot The slot that is being 'opened' for selection
|
||||
*/
|
||||
$scope.selectSlot = function(e, slot) {
|
||||
e.stopPropagation();
|
||||
if ($scope.selectedSlot == slot) {
|
||||
$scope.selectedSlot = null;
|
||||
} else {
|
||||
$scope.selectedSlot = slot;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the ships build with the selected component for the
|
||||
* specified slot. Prevents the click event from propagation.
|
||||
*
|
||||
* @param {string} type Shorthand key/string for identifying the slot & component type
|
||||
* @param {[type]} slot The slot object belonging to the ship instance
|
||||
* @param {[type]} e The event object
|
||||
*/
|
||||
$scope.select = function(type, slot, e, id) {
|
||||
e.stopPropagation();
|
||||
id = id || angular.element(e.target).attr('cpid'); // Get component ID
|
||||
|
||||
if (id) {
|
||||
if (id == 'empty') {
|
||||
ship.use(slot, null, null);
|
||||
} else if (type == 'h') {
|
||||
ship.use(slot, id, Components.hardpoints(id));
|
||||
} else if (type == 'c') {
|
||||
ship.use(slot, id, Components.common(ship.common.indexOf(slot), id));
|
||||
} else if (type == 'i') {
|
||||
ship.use(slot, id, Components.internal(id));
|
||||
} else if (type == 'b') {
|
||||
ship.useBulkhead(id);
|
||||
}
|
||||
$scope.selectedSlot = null;
|
||||
updateState(Serializer.fromShip(ship));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reload the build from the last save.
|
||||
*/
|
||||
$scope.reloadBuild = function() {
|
||||
if ($scope.buildName && $scope.savedCode) {
|
||||
Serializer.toShip(ship, $scope.savedCode); // Repopulate with components from last save
|
||||
updateState($scope.savedCode);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Strip ship to D-class and no other components.
|
||||
*/
|
||||
$scope.stripBuild = function() {
|
||||
for (var i = 0, l = ship.common.length - 1; i < l; i++) { // All except Fuel Tank
|
||||
var id = ship.common[i].maxClass + 'D';
|
||||
ship.use(ship.common[i], id, Components.common(i, id));
|
||||
}
|
||||
ship.hardpoints.forEach(function(slot) { ship.use(slot, null, null); });
|
||||
ship.internal.forEach(function(slot) { ship.use(slot, null, null); });
|
||||
ship.useBulkhead(0);
|
||||
updateState(Serializer.fromShip(ship));
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the current build. Will replace the saved build if there is one
|
||||
* for this ship & with the exact name.
|
||||
*/
|
||||
$scope.saveBuild = function() {
|
||||
if (!$scope.buildName) {
|
||||
return;
|
||||
}
|
||||
// No change hav been made, i.e. save ship default build under a name
|
||||
if (!$scope.code) {
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
}
|
||||
// Only save if there a build name and a change has been made or the build has never been saved
|
||||
if ($scope.code != $scope.savedCode) {
|
||||
Persist.saveBuild(ship.id, $scope.buildName, $scope.code);
|
||||
$scope.savedCode = $scope.code;
|
||||
if ($scope.retrofitBuild === $scope.buildName) {
|
||||
Serializer.toShip(retrofitShip, $scope.code);
|
||||
}
|
||||
updateState($scope.code);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the build to detailed JSON
|
||||
*/
|
||||
$scope.exportBuild = function(e) {
|
||||
e.stopPropagation();
|
||||
|
||||
if ($scope.buildName) {
|
||||
$state.go('modal.export', {
|
||||
title: $scope.buildName + ' Export',
|
||||
description: 'A detailed JSON export of your build for use in other sites and tools',
|
||||
data: Serializer.toDetailedBuild($scope.buildName, ship, $scope.code || Serializer.fromShip(ship))
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Permanently delete the current build and redirect/reload this controller
|
||||
* with the 'factory' build of the current ship.
|
||||
*/
|
||||
$scope.deleteBuild = function() {
|
||||
Persist.deleteBuild(ship.id, $scope.buildName);
|
||||
$state.go('outfit', { shipId: ship.id, code: null, bn: null }, { location: 'replace', reload: true });
|
||||
};
|
||||
|
||||
/**
|
||||
* On build name change, retrieve the existing saved code if there is one
|
||||
*/
|
||||
$scope.bnChange = function() {
|
||||
$scope.savedCode = Persist.getBuild(ship.id, $scope.buildName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle cost of the selected component
|
||||
* @param {object} item The component being toggled
|
||||
*/
|
||||
$scope.toggleCost = function(item) {
|
||||
ship.setCostIncluded(item, !item.incCost);
|
||||
};
|
||||
|
||||
/**
|
||||
* [sortCost description]
|
||||
* @param {[type]} key [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
$scope.sortCost = function(key) {
|
||||
$scope.costDesc = $scope.costPredicate == key ? !$scope.costDesc : $scope.costDesc;
|
||||
$scope.costPredicate = key;
|
||||
};
|
||||
|
||||
$scope.sortPwr = function(key) {
|
||||
$scope.pwrDesc = $scope.pwrPredicate == key ? !$scope.pwrDesc : $scope.pwrDesc;
|
||||
$scope.pwrPredicate = key;
|
||||
};
|
||||
|
||||
$scope.sortRetrofit = function(key) {
|
||||
$scope.retroDesc = $scope.retroPredicate == key ? !$scope.retroDesc : $scope.retroDesc;
|
||||
$scope.retroPredicate = key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the power on/off for the selected component
|
||||
* @param {object} item The component being toggled
|
||||
*/
|
||||
$scope.togglePwr = function(c) {
|
||||
ship.setSlotEnabled(c, !c.enabled);
|
||||
updateState(Serializer.fromShip(ship));
|
||||
};
|
||||
|
||||
$scope.incPriority = function(c) {
|
||||
if (ship.changePriority(c, c.priority + 1)) {
|
||||
updateState(Serializer.fromShip(ship));
|
||||
}
|
||||
};
|
||||
|
||||
$scope.decPriority = function(c) {
|
||||
if (ship.changePriority(c, c.priority - 1)) {
|
||||
updateState(Serializer.fromShip(ship));
|
||||
}
|
||||
};
|
||||
|
||||
$scope.fuelChange = function(fuel) {
|
||||
$scope.fuel = fuel;
|
||||
win.triggerHandler('render');
|
||||
};
|
||||
|
||||
$scope.statusRetracted = function(slot) {
|
||||
return ship.getSlotStatus(slot, false);
|
||||
};
|
||||
|
||||
$scope.statusDeployed = function(slot) {
|
||||
return ship.getSlotStatus(slot, true);
|
||||
};
|
||||
|
||||
$scope.setRetrofitBase = function() {
|
||||
if ($scope.retrofitBuild) {
|
||||
Serializer.toShip(retrofitShip, Persist.getBuild(ship.id, $scope.retrofitBuild));
|
||||
} else {
|
||||
retrofitShip.buildWith(data.defaults);
|
||||
}
|
||||
updateRetrofitCosts();
|
||||
};
|
||||
|
||||
// Utilify functions
|
||||
|
||||
function updateState(code) {
|
||||
$scope.code = code;
|
||||
$state.go('outfit', { shipId: ship.id, code: $scope.code, bn: $scope.buildName }, { location: 'replace', notify: false });
|
||||
$scope.speedSeries.xMax = $scope.trSeries.xMax = $scope.jrSeries.xMax = ship.cargoCapacity;
|
||||
$scope.jrSeries.yMax = ship.unladenRange;
|
||||
$scope.trSeries.yMax = ship.unladenTotalRange;
|
||||
updateRetrofitCosts();
|
||||
win.triggerHandler('pwrchange');
|
||||
}
|
||||
|
||||
function updateRetrofitCosts() {
|
||||
var costs = $scope.retrofitList = [];
|
||||
var cName = $rootScope.cName;
|
||||
var total = 0, i, l, item;
|
||||
|
||||
if (ship.bulkheads.id != retrofitShip.bulkheads.id) {
|
||||
item = {
|
||||
buyClassRating: ship.bulkheads.c.class + ship.bulkheads.c.rating,
|
||||
buyName: cName(ship.bulkheads),
|
||||
sellClassRating: retrofitShip.bulkheads.c.class + retrofitShip.bulkheads.c.rating,
|
||||
sellName: cName(retrofitShip.bulkheads),
|
||||
netCost: ship.bulkheads.discountedCost - retrofitShip.bulkheads.discountedCost
|
||||
};
|
||||
costs.push(item);
|
||||
total += item.netCost;
|
||||
}
|
||||
|
||||
for (var g in { common: 1, internal: 1, hardpoints: 1 }) {
|
||||
var retroSlotGroup = retrofitShip[g];
|
||||
var slotGroup = ship[g];
|
||||
for (i = 0, l = slotGroup.length; i < l; i++) {
|
||||
if (slotGroup[i].id != retroSlotGroup[i].id) {
|
||||
item = { netCost: 0 };
|
||||
if (slotGroup[i].id) {
|
||||
item.buyName = cName(slotGroup[i]);
|
||||
item.buyClassRating = slotGroup[i].c.class + slotGroup[i].c.rating;
|
||||
item.netCost = slotGroup[i].discountedCost;
|
||||
}
|
||||
if (retroSlotGroup[i].id) {
|
||||
item.sellName = cName(retroSlotGroup[i]);
|
||||
item.sellClassRating = retroSlotGroup[i].c.class + retroSlotGroup[i].c.rating;
|
||||
item.netCost -= retroSlotGroup[i].discountedCost;
|
||||
}
|
||||
costs.push(item);
|
||||
total += item.netCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
$scope.retrofitTotal = total;
|
||||
}
|
||||
|
||||
$scope.updateCostTab = function(tab) {
|
||||
Persist.setCostTab(tab);
|
||||
$scope.costTab = tab;
|
||||
};
|
||||
|
||||
$scope.pdWarning = function(pd) {
|
||||
return pd.enginecapacity < ship.boostEnergy;
|
||||
};
|
||||
|
||||
// Hide any open menu/slot/etc if the background is clicked
|
||||
$scope.$on('close', function() {
|
||||
$scope.selectedSlot = null;
|
||||
});
|
||||
|
||||
// Hide any open menu/slot/etc if the background is clicked
|
||||
$scope.$on('discountChange', function() {
|
||||
ship.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
|
||||
retrofitShip.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
|
||||
updateRetrofitCosts();
|
||||
});
|
||||
|
||||
}]);
|
||||
@@ -1,4 +0,0 @@
|
||||
angular.module('app').controller('ShipyardController', ['$rootScope', 'ShipsDB', function($rootScope, ships) {
|
||||
$rootScope.title = 'Coriolis';
|
||||
$rootScope.ships = ships;
|
||||
}]);
|
||||
@@ -1,163 +0,0 @@
|
||||
angular.module('app').directive('areaChart', ['$window', function($window) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
config: '=',
|
||||
series: '='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var series = scope.series,
|
||||
config = scope.config,
|
||||
labels = config.labels,
|
||||
margin = { top: 15, right: 15, bottom: 35, left: 60 },
|
||||
fmt = d3.format('.3r'),
|
||||
fmtLong = d3.format('.2f'),
|
||||
func = series.func,
|
||||
drag = d3.behavior.drag(),
|
||||
dragging = false,
|
||||
// Define Axes
|
||||
xAxis = d3.svg.axis().outerTickSize(0).orient('bottom').tickFormat(d3.format('.2r')),
|
||||
yAxis = d3.svg.axis().ticks(6).outerTickSize(0).orient('left').tickFormat(fmt),
|
||||
x = d3.scale.linear(),
|
||||
y = d3.scale.linear(),
|
||||
data = [];
|
||||
|
||||
// Create chart
|
||||
var svg = d3.select(element[0]).append('svg');
|
||||
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
|
||||
// Define Area
|
||||
var area = d3.svg.area();
|
||||
|
||||
var gradient = vis.append('defs')
|
||||
.append('linearGradient')
|
||||
.attr('id', 'gradient')
|
||||
.attr('x1', '0%').attr('y1', '0%')
|
||||
.attr('x2', '100%').attr('y2', '100%')
|
||||
.attr('spreadMethod', 'pad');
|
||||
gradient.append('stop')
|
||||
.attr('offset', '0%')
|
||||
.attr('stop-color', '#ff8c0d')
|
||||
.attr('stop-opacity', 1);
|
||||
gradient.append('stop')
|
||||
.attr('offset', '100%')
|
||||
.attr('stop-color', '#ff3b00')
|
||||
.attr('stop-opacity', 1);
|
||||
|
||||
// Create Y Axis SVG Elements
|
||||
var yTxt = vis.append('g').attr('class', 'y axis')
|
||||
.append('text')
|
||||
.attr('transform', 'rotate(-90)')
|
||||
.attr('y', -50)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.yAxis.title + ' (' + labels.yAxis.unit + ')');
|
||||
// Create X Axis SVG Elements
|
||||
var xLbl = vis.append('g').attr('class', 'x axis');
|
||||
var xTxt = xLbl.append('text')
|
||||
.attr('y', 30)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.xAxis.title + ' (' + labels.xAxis.unit + ')');
|
||||
|
||||
// Create and Add tooltip
|
||||
var tip = vis.append('g').style('display', 'none');
|
||||
tip.append('rect').attr('width', '4.5em').attr('height', '2em').attr('x', '0.5em').attr('y', '-1em').attr('class', 'tip');
|
||||
tip.append('circle')
|
||||
.attr('class', 'marker')
|
||||
.attr('r', 4);
|
||||
tip.append('text').attr('class', 'label x').attr('y', '-0.25em');
|
||||
tip.append('text').attr('class', 'label y').attr('y', '0.85em');
|
||||
|
||||
vis.insert('path', ':first-child') // Area/Path to appear behind everything else
|
||||
.data([data])
|
||||
.attr('class', 'area')
|
||||
.attr('fill', 'url(#gradient)')
|
||||
.attr('d', area)
|
||||
.on('mouseover', showTip)
|
||||
.on('mouseout', hideTip)
|
||||
.on('mousemove', moveTip)
|
||||
.call(drag);
|
||||
|
||||
drag
|
||||
.on('dragstart', function() {
|
||||
dragging = true;
|
||||
moveTip.call(this);
|
||||
showTip();
|
||||
})
|
||||
.on('dragend', function() {
|
||||
dragging = false;
|
||||
hideTip();
|
||||
})
|
||||
.on('drag', moveTip);
|
||||
|
||||
/**
|
||||
* Watch for changes in the series data (mass changes, etc)
|
||||
*/
|
||||
scope.$watchCollection('series', render);
|
||||
angular.element($window).bind('orientationchange resize render', render);
|
||||
|
||||
function render() {
|
||||
var width = element[0].parentElement.offsetWidth,
|
||||
height = width * 0.5,
|
||||
w = width - margin.left - margin.right,
|
||||
h = height - margin.top - margin.bottom;
|
||||
|
||||
data.length = 0; // Reset Data array
|
||||
|
||||
if (series.xMax == series.xMin) {
|
||||
var yVal = func(series.xMin);
|
||||
data.push([ series.xMin, yVal ]);
|
||||
data.push([ series.xMin, yVal ]);
|
||||
area.x(function(d, i) { return i * w; }).y0(h).y1(function(d) { return y(d[1]); });
|
||||
} else {
|
||||
for (var val = series.xMin; val <= series.xMax; val += 1) {
|
||||
data.push([ val, func(val) ]);
|
||||
}
|
||||
area.x(function(d) { return x(d[0]); }).y0(h).y1(function(d) { return y(d[1]); });
|
||||
}
|
||||
|
||||
// Update Chart Size
|
||||
svg.attr('width', width).attr('height', height);
|
||||
// Update domain and scale for axes
|
||||
x.range([0, w]).domain([series.xMin, series.xMax]).clamp(true);
|
||||
xAxis.scale(x);
|
||||
xLbl.attr('transform', 'translate(0,' + h + ')');
|
||||
xTxt.attr('x', w / 2);
|
||||
y.range([h, 0]).domain([series.yMin, series.yMax]);
|
||||
yAxis.scale(y);
|
||||
yTxt.attr('x', -h / 2);
|
||||
vis.selectAll('.y.axis').call(yAxis);
|
||||
vis.selectAll('.x.axis').call(xAxis);
|
||||
|
||||
vis.selectAll('path.area') // Area/Path to appear behind everything else
|
||||
.data([data])
|
||||
.attr('d', area);
|
||||
}
|
||||
|
||||
function showTip() {
|
||||
tip.style('display', null);
|
||||
}
|
||||
|
||||
function hideTip() {
|
||||
if (!dragging) {
|
||||
tip.style('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
function moveTip() {
|
||||
var xPos = d3.mouse(this)[0], x0 = x.invert(xPos), y0 = func(x0), flip = (x0 / x.domain()[1] > 0.65);
|
||||
tip.attr('transform', 'translate(' + x(x0) + ',' + y(y0) + ')');
|
||||
tip.selectAll('rect').attr('x', flip ? '-5.75em' : '0.5em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.selectAll('text.label').attr('x', flip ? '-2em' : '1em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.select('text.label.x').text(fmtLong(x0) + ' ' + labels.xAxis.unit);
|
||||
tip.select('text.label.y').text(fmtLong(y0) + ' ' + labels.yAxis.unit);
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
angular.element($window).unbind('orientationchange resize render', render);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,127 +0,0 @@
|
||||
angular.module('app').directive('barChart', ['$window', function($window) {
|
||||
|
||||
function bName(build) {
|
||||
return build.buildName + '\n' + build.name;
|
||||
}
|
||||
|
||||
function insertLinebreaks(d) {
|
||||
var el = d3.select(this);
|
||||
var words = d.split('\n');
|
||||
el.text('').attr('y', -6);
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var tspan = el.append('tspan').text(words[i]);
|
||||
if (i > 0) {
|
||||
tspan.attr('x', -9).attr('dy', 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
data: '=',
|
||||
facet: '='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var color = d3.scale.ordinal().range([ '#7b6888', '#6b486b', '#3182bd', '#a05d56', '#d0743c']),
|
||||
labels = scope.facet.lbls,
|
||||
fmt = scope.facet.fmt,
|
||||
properties = scope.facet.props,
|
||||
unit = scope.facet.unit,
|
||||
margin = { top: 10, right: 20, bottom: 35, left: 150 },
|
||||
y0 = d3.scale.ordinal(),
|
||||
y1 = d3.scale.ordinal(),
|
||||
x = d3.scale.linear(),
|
||||
yAxis = d3.svg.axis().scale(y0).outerTickSize(0).orient('left'),
|
||||
xAxis = d3.svg.axis().scale(x).ticks(5).outerTickSize(0).orient('bottom').tickFormat(d3.format('.2s'));
|
||||
|
||||
// Create chart
|
||||
var svg = d3.select(element[0]).append('svg');
|
||||
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
|
||||
// Create and Add tooltip
|
||||
var tip = d3.tip()
|
||||
.attr('class', 'd3-tip')
|
||||
.html(function(property, propertyIndex) {
|
||||
return (labels ? (labels[propertyIndex] + ': ') : '') + fmt(property.value) + ' ' + unit;
|
||||
});
|
||||
|
||||
vis.call(tip);
|
||||
|
||||
// Create Y Axis SVG Elements
|
||||
vis.append('g').attr('class', 'y axis');
|
||||
vis.selectAll('g.y.axis g text').each(insertLinebreaks);
|
||||
// Create X Axis SVG Elements
|
||||
var xAxisLbl = vis.append('g')
|
||||
.attr('class', 'x axis')
|
||||
.append('text')
|
||||
.attr('y', 30)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(scope.facet.title + (unit ? (' (' + unit + ')') : ''));
|
||||
|
||||
|
||||
/**
|
||||
* Watch for changes in the comparison array (ships added/removed, sorting)
|
||||
*/
|
||||
scope.$watchCollection('data', render);
|
||||
angular.element($window).bind('orientationchange resize render', render);
|
||||
|
||||
function render() {
|
||||
var data = scope.data,
|
||||
width = element[0].offsetWidth,
|
||||
w = width - margin.left - margin.right,
|
||||
height = 45 + (30 * data.length),
|
||||
h = height - margin.top - margin.bottom,
|
||||
maxVal = d3.max(data, function(d) { return d3.max(properties, function(p) {return d[p]; }); });
|
||||
|
||||
// Update chart size
|
||||
svg.attr('width', width).attr('height', height);
|
||||
|
||||
// Remove existing elements
|
||||
vis.selectAll('.ship').remove();
|
||||
vis.selectAll('rect').remove();
|
||||
|
||||
// Update X & Y Axis
|
||||
x.range([0, w]).domain([0, maxVal]);
|
||||
y0.domain(data.map(bName)).rangeRoundBands([0, h], 0.3);
|
||||
y1.domain(properties).rangeRoundBands([0, y0.rangeBand()]);
|
||||
vis.selectAll('.y.axis').call(yAxis);
|
||||
vis.selectAll('.x.axis').attr('transform', 'translate(0,' + h + ')').call(xAxis);
|
||||
xAxisLbl.attr('x', w / 2);
|
||||
// Update Y-Axis labels
|
||||
vis.selectAll('g.y.axis g text').each(insertLinebreaks);
|
||||
|
||||
var group = vis.selectAll('.ship')
|
||||
.data(scope.data, bName)
|
||||
.enter().append('g')
|
||||
.attr('class', 'g')
|
||||
.attr('transform', function(build) { return 'translate(0,' + y0(bName(build)) + ')'; });
|
||||
|
||||
group.selectAll('rect')
|
||||
.data(function(build) {
|
||||
var o = [];
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
o.push({ name: properties[i], value: build[properties[i]] });
|
||||
}
|
||||
return o;
|
||||
})
|
||||
.enter().append('rect')
|
||||
.attr('height', y1.rangeBand())
|
||||
.attr('x', 0)
|
||||
.attr('y', function(d) {return y1(d.name); })
|
||||
.attr('width', function(d) { return x(d.value); })
|
||||
.on('mouseover', tip.show)
|
||||
.on('mouseout', tip.hide)
|
||||
.style('fill', function(d) { return color(d.name); });
|
||||
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
angular.element($window).unbind('orientationchange resize render', render);
|
||||
tip.destroy(); // Remove the tooltip from the DOM
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,80 +0,0 @@
|
||||
angular.module('app').directive('comparisonTable', ['$state', function($state) {
|
||||
|
||||
function tblHeader(facets) {
|
||||
var r1 = ['<tr class="main"><th rowspan="2" class="prop" prop="name">Ship</th><th rowspan="2" class="prop" prop="buildName">Build</th>'];
|
||||
var r2 = [];
|
||||
for (var i = 0, l = facets.length; i < l; i++) {
|
||||
if (facets[i].active) {
|
||||
var f = facets[i];
|
||||
var p = f.props;
|
||||
var pl = p.length;
|
||||
r1.push('<th rowspan="', f.props.length == 1 ? 2 : 1, '" colspan="', pl, '"');
|
||||
|
||||
if (pl == 1) {
|
||||
r1.push(' prop="', p[0], '" class="prop"');
|
||||
} else {
|
||||
for (var j = 0; j < pl; j++) {
|
||||
r2.push('<th prop="', p[j], '" class="prop ', j === 0 ? 'lft' : '', '">', f.lbls[j], '</th>');
|
||||
}
|
||||
}
|
||||
|
||||
r1.push('>', f.title, '</th>');
|
||||
}
|
||||
}
|
||||
r1.push('</tr><tr>');
|
||||
r1.push(r2.join(''));
|
||||
r1.push('</tr>');
|
||||
return r1.join('');
|
||||
}
|
||||
|
||||
function tblBody(facets, builds) {
|
||||
var body = [];
|
||||
|
||||
if (builds.length === 0) {
|
||||
return '<td colspan="100" class="cen">No builds added to comparison!</td';
|
||||
}
|
||||
|
||||
for (var i = 0, l = builds.length; i < l; i++) {
|
||||
var b = builds[i];
|
||||
body.push('<tr class="tr">');
|
||||
var href = $state.href('outfit', { shipId: b.id, code: b.code, bn: b.buildName });
|
||||
body.push('<td class="tl"><a href="', href, '">', b.name, '</a></td>');
|
||||
body.push('<td class="tl"><a href="', href, '">', b.buildName, '</a></td>');
|
||||
|
||||
for (var j = 0, fl = facets.length; j < fl; j++) {
|
||||
if (facets[j].active) {
|
||||
var f = facets[j];
|
||||
var p = f.props;
|
||||
for (var k = 0, pl = p.length; k < pl; k++) {
|
||||
body.push('<td>', f.fmt(b[p[k]]), '<u> ', f.unit, '</u></td>');
|
||||
}
|
||||
}
|
||||
}
|
||||
body.push('</tr>');
|
||||
}
|
||||
|
||||
return body.join('');
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
|
||||
link: function(scope, element) {
|
||||
var header = angular.element('<thead></thead>');
|
||||
var body = angular.element('<tbody></tbody>');
|
||||
element.append(header);
|
||||
element.append(body);
|
||||
|
||||
var updateAll = function() {
|
||||
header.html(tblHeader(scope.facets));
|
||||
body.html(tblBody(scope.facets, scope.builds));
|
||||
};
|
||||
|
||||
scope.$watchCollection('facets', updateAll);
|
||||
scope.$watch('tblUpdate', updateAll);
|
||||
scope.$watchCollection('builds', function() {
|
||||
body.html(tblBody(scope.facets, scope.builds));
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,90 +0,0 @@
|
||||
angular.module('app').directive('componentSelect', function() {
|
||||
|
||||
// Generting the HTML in this manner is MUCH faster than using an angular template.
|
||||
|
||||
function appendGroup(list, opts, cid, mass, checkWarning) {
|
||||
var prevClass = null, prevRating = null;
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
var o = opts[i];
|
||||
var id = o.id || (o.class + o.rating); // Common components' ID is their class and rating
|
||||
|
||||
if (i > 0 && opts.length > 4 && o.class != prevClass && (o.rating != prevRating || o.mode)) {
|
||||
list.push('<br/>');
|
||||
}
|
||||
|
||||
list.push('<li class="', o.name ? 'lc' : 'c');
|
||||
|
||||
if (cid == id) {
|
||||
list.push(' active');
|
||||
}
|
||||
|
||||
if (checkWarning && checkWarning(opts[i])) {
|
||||
list.push(' warning');
|
||||
}
|
||||
|
||||
list.push((o.maxmass && mass > o.maxmass) ? ' disabled"' : '" cpid="', id, '">');
|
||||
|
||||
if (o.mode) {
|
||||
list.push('<svg cpid="', id, '" class="icon lg"><use cpid="', id, '" xlink:href="#mount-', o.mode, '"></use></svg> ');
|
||||
}
|
||||
|
||||
list.push('<span cpid="', id, '">', o.class, o.rating);
|
||||
|
||||
if (o.missile) {
|
||||
list.push('/' + o.missile);
|
||||
}
|
||||
|
||||
|
||||
if (o.name) {
|
||||
list.push(' ' + o.name);
|
||||
}
|
||||
|
||||
list.push('</span></li>');
|
||||
prevClass = o.class;
|
||||
prevRating = o.rating;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
opts: '=', // Component Options object
|
||||
groups: '=', // Groups of Component Options
|
||||
mass: '=', // Current ship unladen mass
|
||||
s: '=', // Current Slot
|
||||
warning: '=' // Check warning function
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var list = [];
|
||||
var cid = scope.s.id; // Slot's current component id
|
||||
var component = scope.s.c; // Slot's Current Component (may be null/undefined)
|
||||
var opts = scope.opts;
|
||||
var groups = scope.groups;
|
||||
var mass = scope.mass || 0;
|
||||
|
||||
if (groups) {
|
||||
// At present time slots with grouped options (Hardpoints and Internal) can be empty
|
||||
list.push('<div class="empty-c" cpid="empty">EMPTY</div>');
|
||||
for (var g in groups) {
|
||||
var grp = groups[g];
|
||||
var grpCode = grp[Object.keys(grp)[0]].grp; // Nasty operation to get the grp property of the first/any single component
|
||||
list.push('<div id="', grpCode, '" class="select-group">', g, '</div><ul>');
|
||||
appendGroup(list, grp, cid, mass, scope.warning);
|
||||
list.push('</ul>');
|
||||
}
|
||||
} else {
|
||||
list.push('<ul>');
|
||||
appendGroup(list, opts, cid, mass, scope.warning);
|
||||
list.push('</ul>');
|
||||
}
|
||||
|
||||
element.html(list.join(''));
|
||||
// If groups are present and a component is already selectd
|
||||
if (groups && component && component.grp) {
|
||||
var groupElement = angular.element(document.getElementById(component.grp));
|
||||
var parentElem = element[0].parentElement;
|
||||
parentElem.scrollTop = groupElement[0].offsetTop; // Scroll to currently selected group
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
angular.module('app').directive('contextMenu', ['$parse', function($parse) {
|
||||
return function(scope, element, attrs) {
|
||||
var fn = $parse(attrs.contextMenu);
|
||||
|
||||
element.bind('contextmenu', function(e) {
|
||||
if (!e.shiftKey) {
|
||||
scope.$apply(function() {
|
||||
e.preventDefault();
|
||||
fn(scope, { $event: e });
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
@@ -1,87 +0,0 @@
|
||||
angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', '$state', 'Persist', 'Serializer', 'ShipsDB', function(_, $rootScope, $state, Persist, Serializer, ships) {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'views/_header.html',
|
||||
scope: true,
|
||||
link: function(scope) {
|
||||
scope.openedMenu = null;
|
||||
scope.ships = ships;
|
||||
scope.allBuilds = Persist.builds;
|
||||
scope.buildsList = Object.keys(scope.allBuilds).sort();
|
||||
scope.allComparisons = Persist.comparisons;
|
||||
scope.bs = Persist.state;
|
||||
|
||||
var insIndex = _.findIndex($rootScope.insurance.opts, 'name', Persist.getInsurance());
|
||||
var savedDiscounts = Persist.getDiscount() || [1, 1];
|
||||
$rootScope.insurance.current = $rootScope.insurance.opts[insIndex != -1 ? insIndex : 0];
|
||||
$rootScope.discounts.ship = savedDiscounts[0];
|
||||
$rootScope.discounts.components = savedDiscounts[1];
|
||||
|
||||
/**
|
||||
* Save selected insurance option
|
||||
*/
|
||||
scope.updateInsurance = function() {
|
||||
Persist.setInsurance($rootScope.insurance.current.name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save selected discount option
|
||||
*/
|
||||
scope.updateDiscount = function() {
|
||||
Persist.setDiscount([$rootScope.discounts.ship, $rootScope.discounts.components]);
|
||||
$rootScope.$broadcast('discountChange');
|
||||
};
|
||||
|
||||
scope.backup = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
scope.openedMenu = null;
|
||||
$state.go('modal.export', {
|
||||
title: 'Backup',
|
||||
data: Persist.getAll(),
|
||||
description: 'Backup of all Coriolis data to save or transfer to another browser/device'
|
||||
});
|
||||
};
|
||||
|
||||
scope.detailedExport = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
scope.openedMenu = null;
|
||||
$state.go('modal.export', {
|
||||
title: 'Detailed Export',
|
||||
data: Serializer.toDetailedExport(scope.allBuilds),
|
||||
description: 'Detailed export of all builds for use with other tools and sites'
|
||||
});
|
||||
};
|
||||
|
||||
scope.openMenu = function(e, menu) {
|
||||
e.stopPropagation();
|
||||
if (menu == scope.openedMenu) {
|
||||
scope.openedMenu = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((menu == 'comp' || menu == 'b') && !scope.bs.hasBuilds) {
|
||||
scope.openedMenu = null;
|
||||
return;
|
||||
}
|
||||
scope.openedMenu = menu;
|
||||
};
|
||||
|
||||
// Close menus if a navigation change event occurs
|
||||
$rootScope.$on('$stateChangeStart', function() {
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
// Listen to close event to close opened menus or modals
|
||||
$rootScope.$on('close', function() {
|
||||
scope.openedMenu = null;
|
||||
});
|
||||
|
||||
scope.$watchCollection('allBuilds', function() {
|
||||
scope.buildsList = Object.keys(scope.allBuilds).sort();
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,190 +0,0 @@
|
||||
angular.module('app').directive('lineChart', ['$window', function($window) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
config: '=',
|
||||
series: '='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var seriesConfig = scope.series,
|
||||
series = seriesConfig.series,
|
||||
color = d3.scale.ordinal().range([ '#ff8c0d', '#1fb0ff', '#a05d56', '#d0743c']),
|
||||
config = scope.config,
|
||||
labels = config.labels,
|
||||
margin = { top: 15, right: 15, bottom: 35, left: 60 },
|
||||
fmt = d3.format('.3r'),
|
||||
fmtLong = d3.format('.2f'),
|
||||
func = seriesConfig.func,
|
||||
drag = d3.behavior.drag(),
|
||||
dragging = false,
|
||||
// Define Scales
|
||||
x = d3.scale.linear(),
|
||||
y = d3.scale.linear(),
|
||||
// Define Axes
|
||||
xAxis = d3.svg.axis().scale(x).outerTickSize(0).orient('bottom').tickFormat(d3.format('.2r')),
|
||||
yAxis = d3.svg.axis().scale(y).ticks(6).outerTickSize(0).orient('left').tickFormat(fmt),
|
||||
data = [];
|
||||
|
||||
// Create chart
|
||||
var svg = d3.select(element[0]).append('svg');
|
||||
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
var lines = vis.append('g');
|
||||
|
||||
// Define Area
|
||||
var line = d3.svg.line().y(function(d) { return y(d[1]); });
|
||||
|
||||
// Create Y Axis SVG Elements
|
||||
var yTxt = vis.append('g').attr('class', 'y axis')
|
||||
.append('text')
|
||||
.attr('transform', 'rotate(-90)')
|
||||
.attr('y', -50)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.yAxis.title + ' (' + labels.yAxis.unit + ')');
|
||||
// Create X Axis SVG Elements
|
||||
var xLbl = vis.append('g').attr('class', 'x axis');
|
||||
var xTxt = xLbl.append('text')
|
||||
.attr('y', 30)
|
||||
.attr('dy', '.1em')
|
||||
.style('text-anchor', 'middle')
|
||||
.text(labels.xAxis.title + ' (' + labels.xAxis.unit + ')');
|
||||
|
||||
// Create and Add tooltip
|
||||
var tipWidth = (Math.max(labels.yAxis.unit.length, labels.xAxis.unit.length) * 1.25) + 2;
|
||||
var tips = vis.append('g').style('display', 'none');
|
||||
|
||||
var background = vis.append('rect') // Background to capture hover/drag
|
||||
.attr('fill-opacity', 0)
|
||||
.on('mouseover', showTip)
|
||||
.on('mouseout', hideTip)
|
||||
.on('mousemove', moveTip)
|
||||
.call(drag);
|
||||
|
||||
drag
|
||||
.on('dragstart', function() {
|
||||
dragging = true;
|
||||
moveTip.call(this);
|
||||
showTip();
|
||||
})
|
||||
.on('dragend', function() {
|
||||
dragging = false;
|
||||
hideTip();
|
||||
})
|
||||
.on('drag', moveTip);
|
||||
|
||||
/**
|
||||
* Watch for changes in the series data (mass changes, etc)
|
||||
*/
|
||||
scope.$watchCollection('series', render);
|
||||
angular.element($window).bind('orientationchange resize render', render);
|
||||
|
||||
function render() {
|
||||
var width = element[0].parentElement.offsetWidth,
|
||||
height = width * 0.5,
|
||||
xMax = seriesConfig.xMax,
|
||||
xMin = seriesConfig.xMin,
|
||||
yMax = seriesConfig.yMax,
|
||||
yMin = seriesConfig.yMin,
|
||||
w = width - margin.left - margin.right,
|
||||
h = height - margin.top - margin.bottom,
|
||||
s, val, yVal, delta;
|
||||
|
||||
data.length = 0; // Reset Data array
|
||||
|
||||
if (seriesConfig.xMax == seriesConfig.xMin) {
|
||||
line.x(function(d, i) { return i * w; });
|
||||
} else {
|
||||
line.x(function(d) { return x(d[0]); });
|
||||
}
|
||||
|
||||
if (series) {
|
||||
for (s = 0; s < series.length; s++) {
|
||||
data.push([]);
|
||||
}
|
||||
|
||||
if (xMax == xMin) {
|
||||
yVal = func(xMin);
|
||||
for (s = 0; s < series.length; s++) {
|
||||
data[s].push( [ xMin, yVal[ series[s] ] ], [ 1, yVal[ series[s] ] ]);
|
||||
}
|
||||
} else {
|
||||
delta = (xMax - xMin) / 30; // Only render 30 points on the graph
|
||||
for (val = xMin; val <= xMax; val += delta) {
|
||||
yVal = func(val);
|
||||
for (s = 0; s < series.length; s++) {
|
||||
data[s].push([ val, yVal[ series[s] ] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
var seriesData = [];
|
||||
if (xMax == xMin) {
|
||||
yVal = func(xMin);
|
||||
seriesData.push([ xMin, yVal ], [ 1, yVal ]);
|
||||
} else {
|
||||
delta = (xMax - xMin) / 30; // Only render 30 points on the graph
|
||||
for (val = xMin; val <= xMax; val += delta) {
|
||||
seriesData.push([val, func(val) ]);
|
||||
}
|
||||
}
|
||||
|
||||
data.push(seriesData);
|
||||
}
|
||||
|
||||
// Update Chart Size
|
||||
svg.attr('width', width).attr('height', height);
|
||||
background.attr('height', h).attr('width', w);
|
||||
|
||||
// Update domain and scale for axes
|
||||
x.range([0, w]).domain([xMin, xMax]).clamp(true);
|
||||
xLbl.attr('transform', 'translate(0,' + h + ')');
|
||||
xTxt.attr('x', w / 2);
|
||||
y.range([h, 0]).domain([yMin, yMax]);
|
||||
yTxt.attr('x', -h / 2);
|
||||
vis.selectAll('.y.axis').call(yAxis);
|
||||
vis.selectAll('.x.axis').call(xAxis);
|
||||
|
||||
lines.selectAll('path.line')
|
||||
.data(data)
|
||||
.attr('d', line) // Update existing series
|
||||
.enter() // Add new series
|
||||
.append('path')
|
||||
.attr('class', 'line')
|
||||
.attr('stroke', function(d, i) { return color(i); })
|
||||
.attr('stroke-width', 2)
|
||||
.attr('d', line);
|
||||
|
||||
var tip = tips.selectAll('g.tooltip').data(data).enter().append('g').attr('class', 'tooltip');
|
||||
tip.append('rect').attr('width', tipWidth + 'em').attr('height', '2em').attr('x', '0.5em').attr('y', '-1em').attr('class', 'tip');
|
||||
tip.append('circle').attr('class', 'marker').attr('r', 4);
|
||||
tip.append('text').attr('class', 'label x').attr('y', '-0.25em');
|
||||
tip.append('text').attr('class', 'label y').attr('y', '0.85em');
|
||||
}
|
||||
|
||||
function showTip() {
|
||||
tips.style('display', null);
|
||||
}
|
||||
|
||||
function hideTip() {
|
||||
if (!dragging) {
|
||||
tips.style('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
function moveTip() {
|
||||
var xPos = d3.mouse(this)[0], x0 = x.invert(xPos), y0 = func(x0), flip = (x0 / x.domain()[1] > 0.65);
|
||||
var tip = tips.selectAll('g.tooltip').attr('transform', function(d, i) { return 'translate(' + x(x0) + ',' + y(series ? y0[series[i]] : y0) + ')'; });
|
||||
tip.selectAll('rect').attr('x', flip ? (-tipWidth - 0.5) + 'em' : '0.5em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.selectAll('text.label').attr('x', flip ? '-1em' : '1em').style('text-anchor', flip ? 'end' : 'start');
|
||||
tip.selectAll('text.label.x').text(fmtLong(x0) + ' ' + labels.xAxis.unit);
|
||||
tips.selectAll('text.label.y').text(function(d, i) { return fmtLong(series ? y0[series[i]] : y0) + ' ' + labels.yAxis.unit; });
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
angular.element($window).unbind('orientationchange resize render', render);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,159 +0,0 @@
|
||||
angular.module('app').directive('powerBands', ['$window', function($window) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
bands: '=',
|
||||
available: '='
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var margin = { top: 20, right: 130, bottom: 20, left: 40 },
|
||||
barHeight = 20,
|
||||
bands = null,
|
||||
innerHeight = (barHeight * 2) + 3,
|
||||
height = innerHeight + margin.top + margin.bottom + 1,
|
||||
wattScale = d3.scale.linear(),
|
||||
pctScale = d3.scale.linear().domain([0, 1]),
|
||||
wattFmt = d3.format('.2f'),
|
||||
pctFmt = d3.format('.1%'),
|
||||
wattAxis = d3.svg.axis().scale(wattScale).outerTickSize(0).orient('top').tickFormat(d3.format('.2r')),
|
||||
pctAxis = d3.svg.axis().scale(pctScale).outerTickSize(0).orient('bottom').tickFormat(d3.format('%')),
|
||||
// Create chart
|
||||
svg = d3.select(element[0]).append('svg'),
|
||||
vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'),
|
||||
deployed = vis.append('g').attr('class', 'power-band'),
|
||||
retracted = vis.append('g').attr('class', 'power-band');
|
||||
|
||||
svg.on('contextmenu', function() {
|
||||
d3.event.preventDefault();
|
||||
for (var i = 0, l = bands.length; i < l; i++) {
|
||||
bands[i].retSelected = false;
|
||||
bands[i].depSelected = false;
|
||||
}
|
||||
render();
|
||||
});
|
||||
|
||||
// Create Y Axis SVG Elements
|
||||
vis.append('g').attr('class', 'watt axis');
|
||||
vis.append('g').attr('class', 'pct axis');
|
||||
vis.append('text').attr('x', -35).attr('y', 16).attr('class', 'primary').text('RET');
|
||||
vis.append('text').attr('x', -35).attr('y', barHeight + 18).attr('class', 'primary').text('DEP');
|
||||
|
||||
var retLbl = vis.append('text').attr('y', 16);
|
||||
var depLbl = vis.append('text').attr('y', barHeight + 18);
|
||||
|
||||
// Watch for changes to data and events
|
||||
scope.$watchCollection('available', render);
|
||||
angular.element($window).bind('orientationchange resize pwrchange', render);
|
||||
|
||||
function render() {
|
||||
bands = scope.bands;
|
||||
|
||||
var available = scope.available,
|
||||
width = element[0].offsetWidth,
|
||||
w = width - margin.left - margin.right,
|
||||
maxBand = bands[bands.length - 1],
|
||||
deployedSum = 0,
|
||||
retractedSum = 0,
|
||||
retBandsSelected = false,
|
||||
depBandsSelected = false,
|
||||
maxPwr = Math.max(available, maxBand.retractedSum, maxBand.deployedSum);
|
||||
|
||||
// Update chart size
|
||||
svg.attr('width', width).attr('height', height);
|
||||
|
||||
// Remove existing elements
|
||||
retracted.selectAll('rect').remove();
|
||||
retracted.selectAll('text').remove();
|
||||
deployed.selectAll('rect').remove();
|
||||
deployed.selectAll('text').remove();
|
||||
|
||||
// Update X & Y Axis
|
||||
wattScale.range([0, w]).domain([0, maxPwr]).clamp(true);
|
||||
pctScale.range([0, w]).domain([0, maxPwr / available]).clamp(true);
|
||||
vis.selectAll('.watt.axis').call(wattAxis);
|
||||
vis.selectAll('.pct.axis').attr('transform', 'translate(0,' + innerHeight + ')').call(pctAxis);
|
||||
|
||||
for (var b = 0, l = bands.length; b < l; b++) {
|
||||
if (bands[b].retSelected) {
|
||||
retractedSum += bands[b].retracted + bands[b].retOnly;
|
||||
retBandsSelected = true;
|
||||
}
|
||||
if (bands[b].depSelected) {
|
||||
deployedSum += bands[b].deployed + bands[b].retracted;
|
||||
depBandsSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
updateLabel(retLbl, w, retBandsSelected, retBandsSelected ? retractedSum : maxBand.retractedSum, available);
|
||||
updateLabel(depLbl, w, depBandsSelected, depBandsSelected ? deployedSum : maxBand.deployedSum, available);
|
||||
|
||||
retracted.selectAll('rect').data(bands).enter().append('rect')
|
||||
.attr('height', barHeight)
|
||||
.attr('width', function(d) { return Math.max(wattScale(d.retracted + d.retOnly) - 1, 0); })
|
||||
.attr('x', function(d) { return wattScale(d.retractedSum) - wattScale(d.retracted + d.retOnly); })
|
||||
.attr('y', 1)
|
||||
.on('click', function(d) {
|
||||
d.retSelected = !d.retSelected;
|
||||
render();
|
||||
})
|
||||
.attr('class', function(d) { return getClass(d.retSelected, d.retractedSum, available); });
|
||||
|
||||
retracted.selectAll('text').data(bands).enter().append('text')
|
||||
.attr('x', function(d) { return wattScale(d.retractedSum) - (wattScale(d.retracted + d.retOnly) / 2); })
|
||||
.attr('y', 15)
|
||||
.style('text-anchor', 'middle')
|
||||
.attr('class', 'primary-bg')
|
||||
.on('click', function(d) {
|
||||
d.retSelected = !d.retSelected;
|
||||
render();
|
||||
})
|
||||
.text(function(d, i) { return bandText(d.retracted + d.retOnly, i); });
|
||||
|
||||
deployed.selectAll('rect').data(bands).enter().append('rect')
|
||||
.attr('height', barHeight)
|
||||
.attr('width', function(d) { return Math.max(wattScale(d.deployed + d.retracted) - 1, 0); })
|
||||
.attr('x', function(d) { return wattScale(d.deployedSum) - wattScale(d.retracted) - wattScale(d.deployed); })
|
||||
.attr('y', barHeight + 2)
|
||||
.on('click', function(d) {
|
||||
d.depSelected = !d.depSelected;
|
||||
render();
|
||||
})
|
||||
.attr('class', function(d) { return getClass(d.depSelected, d.deployedSum, available); });
|
||||
|
||||
deployed.selectAll('text').data(bands).enter().append('text')
|
||||
.attr('x', function(d) { return wattScale(d.deployedSum) - ((wattScale(d.retracted) + wattScale(d.deployed)) / 2); })
|
||||
.attr('y', barHeight + 17)
|
||||
.style('text-anchor', 'middle')
|
||||
.attr('class', 'primary-bg')
|
||||
.on('click', function(d) {
|
||||
d.depSelected = !d.depSelected;
|
||||
render();
|
||||
})
|
||||
.text(function(d, i) { return bandText(d.deployed + d.retracted, i); });
|
||||
|
||||
}
|
||||
|
||||
function updateLabel(lbl, width, selected, sum, available) {
|
||||
lbl
|
||||
.attr('x', width + 5 )
|
||||
.attr('class', getClass(selected, sum, available))
|
||||
.text(wattFmt(Math.max(0, sum)) + ' (' + pctFmt(Math.max(0, sum / available)) + ')');
|
||||
}
|
||||
|
||||
function getClass(selected, sum, available) {
|
||||
return selected ? 'secondary' : (sum > available) ? 'warning' : 'primary';
|
||||
}
|
||||
|
||||
function bandText(val, index) {
|
||||
if (val > 0 && wattScale(val) > 13) {
|
||||
return index + 1;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
angular.element($window).unbind('orientationchange resize pwrchange', render);
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,80 +0,0 @@
|
||||
angular.module('app').directive('slider', ['$window', function($window) {
|
||||
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
max: '=',
|
||||
unit: '=',
|
||||
change: '&onChange'
|
||||
},
|
||||
link: function(scope, element) {
|
||||
var margin = { top: -10, right: 145, bottom: 0, left: 50 },
|
||||
height = 40, // Height is fixed
|
||||
h = height - margin.top - margin.bottom,
|
||||
fmt = d3.format('.2f'),
|
||||
pct = d3.format('.1%'),
|
||||
unit = scope.unit,
|
||||
val = scope.max,
|
||||
svg = d3.select(element[0]).append('svg'),
|
||||
vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'),
|
||||
xAxis = vis.append('g').attr('class', 'x slider-axis').attr('transform', 'translate(0,' + h / 2 + ')'),
|
||||
x = d3.scale.linear(),
|
||||
slider = vis.append('g').attr('class', 'slider'),
|
||||
filled = slider.append('path').attr('class', 'filled').attr('transform', 'translate(0,' + h / 2 + ')'),
|
||||
brush = d3.svg.brush().x(x).extent([scope.max, scope.max]).on('brush', brushed),
|
||||
handle = slider.append('circle').attr('class', 'handle').attr('r', '0.6em'),
|
||||
lbl = slider.append('g').append('text').attr('y', h / 2);
|
||||
|
||||
slider.call(brush);
|
||||
slider.select('.background').attr('height', h);
|
||||
handle.attr('transform', 'translate(0,' + h / 2 + ')');
|
||||
|
||||
/**
|
||||
* Watch for changes in the max, window size
|
||||
*/
|
||||
scope.$watch('max', function(newMax, oldMax) {
|
||||
val = newMax * (val / oldMax); // Retain percentage filled
|
||||
render();
|
||||
});
|
||||
|
||||
angular.element($window).bind('orientationchange resize', render);
|
||||
|
||||
function render() {
|
||||
var width = element[0].offsetWidth, w = width - margin.left - margin.right;
|
||||
|
||||
svg.attr('width', width).attr('height', height);
|
||||
x.domain([0, scope.max]).range([0, w]).clamp(true);
|
||||
handle.attr('cx', x(val));
|
||||
xAxis
|
||||
.call(d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient('bottom')
|
||||
.tickFormat(function(d) { return d + unit; })
|
||||
.tickValues([0, scope.max / 4, scope.max / 2, (3 * scope.max) / 4, scope.max])
|
||||
.tickSize(0)
|
||||
.tickPadding(12))
|
||||
.select('.domain');
|
||||
lbl.attr('x', w + 20);
|
||||
slider.call(brush.extent([val, val])).call(brush.event);
|
||||
slider.selectAll('.extent,.resize').remove();
|
||||
}
|
||||
|
||||
function brushed() {
|
||||
val = brush.extent()[0];
|
||||
if (d3.event.sourceEvent) { // not a programmatic event
|
||||
val = x.invert(d3.mouse(this)[0]);
|
||||
brush.extent([val, val]);
|
||||
}
|
||||
lbl.text(fmt(val) + ' ' + unit + ' ' + pct(val / scope.max));
|
||||
scope.change({ val: val });
|
||||
handle.attr('cx', x(val));
|
||||
filled.attr('d', 'M0,0V0H' + x(val) + 'V0');
|
||||
}
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
angular.element($window).unbind('orientationchange resize render', render);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,14 +0,0 @@
|
||||
angular.module('app').directive('slotHardpoint', ['$rootScope', function($r) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
hp: '=',
|
||||
size: '=',
|
||||
lbl: '='
|
||||
},
|
||||
templateUrl: 'views/_slot-hardpoint.html',
|
||||
link: function(scope) {
|
||||
scope.$r = $r;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,14 +0,0 @@
|
||||
angular.module('app').directive('slotInternal', ['$rootScope', function($r) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
c: '=slot',
|
||||
lbl: '=',
|
||||
fuel: '='
|
||||
},
|
||||
templateUrl: 'views/_slot-internal.html',
|
||||
link: function(scope) {
|
||||
scope.$r = $r;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
* BBCode Generator functions for embedding in the Elite Dangerous Forums
|
||||
*/
|
||||
angular.module('app').factory('Utils', ['$window', '$state', '$http', '$q', function($window, $state, $http, $q) {
|
||||
|
||||
var shortenAPI = 'https://www.googleapis.com/urlshortener/v1/url?key=';
|
||||
|
||||
function shortenUrl(url) {
|
||||
if ($window.navigator.onLine) {
|
||||
return $http.post(shortenAPI + GAPI_KEY, { longUrl: url }).then(function(response) {
|
||||
return response.data.id;
|
||||
});
|
||||
} else {
|
||||
return $q.reject({ statusText: 'Not Online' });
|
||||
}
|
||||
}
|
||||
|
||||
function comparisonBBCode(facets, builds, link) {
|
||||
var colCount = 2, b, i, j, k, f, fl, p, pl, l = [];
|
||||
|
||||
for (i = 0; i < facets.length; i++) {
|
||||
if (facets[i].active) {
|
||||
f = facets[i];
|
||||
p = f.props;
|
||||
|
||||
if (p.length == 1) {
|
||||
l.push('[th][B][COLOR=#FF8C0D]', f.title, '[/COLOR][/B][/th]');
|
||||
colCount++;
|
||||
} else {
|
||||
for (j = 0; j < p.length; j++) {
|
||||
l.push('[th][B][COLOR=#FF8C0D]', f.title, '\n', f.lbls[j], '[/COLOR][/B][/th]');
|
||||
colCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
l.push('[/tr]\n');
|
||||
|
||||
for (i = 0; i < builds.length; i++) {
|
||||
b = builds[i];
|
||||
//var href = $state.href('outfit',{shipId: b.id, code: b.code, bn: b.buildName}, {absolute: true});
|
||||
l.push('[tr][td]', b.name, '[/td][td]', b.buildName, '[/td]');
|
||||
|
||||
for (j = 0, fl = facets.length; j < fl; j++) {
|
||||
if (facets[j].active) {
|
||||
f = facets[j];
|
||||
p = f.props;
|
||||
for (k = 0, pl = p.length; k < pl; k++) {
|
||||
l.push('[td="align: right"]', f.fmt(b[p[k]]), ' [size=-2]', f.unit, '[/size][/td]');
|
||||
}
|
||||
}
|
||||
}
|
||||
l.push('[/tr]\n');
|
||||
}
|
||||
l.push('[tr][td="align: center, colspan:', colCount, '"][size=-3]\n[url=', link, ']Interactive Comparison at Coriolis.io[/url][/td][/tr]\n[/size][/table]');
|
||||
l.unshift('[table="width:', colCount * 90, ',align: center"]\n[tr][th][B][COLOR=#FF8C0D]Ship[/COLOR][/B][/th][th][B][COLOR="#FF8C0D"]Build[/COLOR][/B][/th]');
|
||||
return l.join('');
|
||||
}
|
||||
|
||||
return {
|
||||
comparisonBBCode: comparisonBBCode,
|
||||
shortenUrl: shortenUrl
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,273 +0,0 @@
|
||||
/**
|
||||
* [description]
|
||||
*/
|
||||
angular.module('app').service('Persist', ['$window', 'lodash', function($window, _) {
|
||||
var LS_KEY_BUILDS = 'builds';
|
||||
var LS_KEY_COMPARISONS = 'comparisons';
|
||||
var LS_KEY_COST_TAB = 'costTab';
|
||||
var LS_KEY_INSURANCE = 'insurance';
|
||||
var LS_KEY_DISCOUNTS = 'discounts';
|
||||
var localStorage = $window.localStorage;
|
||||
var buildJson = null;
|
||||
var comparisonJson = null;
|
||||
|
||||
// Safe check to determine if localStorage is enabled
|
||||
try {
|
||||
localStorage.setItem('s', 1);
|
||||
localStorage.removeItem('s');
|
||||
buildJson = localStorage.getItem(LS_KEY_BUILDS);
|
||||
comparisonJson = localStorage.getItem(LS_KEY_COMPARISONS);
|
||||
this.lsEnabled = true;
|
||||
} catch(e) {
|
||||
this.lsEnabled = false;
|
||||
}
|
||||
|
||||
this.builds = buildJson ? angular.fromJson(buildJson) : {};
|
||||
this.comparisons = comparisonJson ? angular.fromJson(comparisonJson) : {};
|
||||
var buildCount = Object.keys(this.builds).length;
|
||||
|
||||
this.state = {
|
||||
buildCount: buildCount,
|
||||
hasBuilds: buildCount > 0,
|
||||
hasComparisons: Object.keys(this.comparisons).length > 0
|
||||
};
|
||||
/**
|
||||
* Persist a ship build in local storage.
|
||||
*
|
||||
* @param {string} shipId The unique id for a model of ship
|
||||
* @param {string} name The name of the build
|
||||
* @param {string} code The serialized code
|
||||
*/
|
||||
this.saveBuild = function(shipId, name, code) {
|
||||
if (!this.lsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.builds[shipId]) {
|
||||
this.builds[shipId] = {};
|
||||
}
|
||||
|
||||
if (!this.builds[shipId][name]) {
|
||||
this.state.buildCount++;
|
||||
this.state.hasBuilds = true;
|
||||
}
|
||||
|
||||
this.builds[shipId][name] = code;
|
||||
// Persist updated build collection to localStorage
|
||||
localStorage.setItem(LS_KEY_BUILDS, angular.toJson(this.builds));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the serialized code/string for a build. Returns null if a
|
||||
* build is not found.
|
||||
*
|
||||
* @param {string} shipId The unique id for a model of ship
|
||||
* @param {string} name The name of the build
|
||||
* @return {string} The serialized build string.
|
||||
*/
|
||||
this.getBuild = function(shipId, name) {
|
||||
if (this.builds[shipId] && this.builds[shipId][name]) {
|
||||
return this.builds[shipId][name];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a build from local storage. It will also delete the ship build collection if
|
||||
* it becomes empty
|
||||
*
|
||||
* @param {string} shipId The unique id for a model of ship
|
||||
* @param {string} name The name of the build
|
||||
*/
|
||||
this.deleteBuild = function(shipId, name) {
|
||||
if (this.lsEnabled && this.builds[shipId][name]) {
|
||||
delete this.builds[shipId][name];
|
||||
if (Object.keys(this.builds[shipId]).length === 0) {
|
||||
delete this.builds[shipId];
|
||||
this.state.buildCount--;
|
||||
this.state.hasBuilds = this.state.buildCount > 0;
|
||||
}
|
||||
// Persist updated build collection to localStorage
|
||||
localStorage.setItem(LS_KEY_BUILDS, angular.toJson(this.builds));
|
||||
// Check if the build was used in existing comparisons
|
||||
var comps = this.comparisons;
|
||||
for (var c in comps) {
|
||||
for (var i = 0; i < comps[c].builds.length; i++) { // For all builds in the current comparison
|
||||
if (comps[c].builds[i].shipId == shipId && comps[c].builds[i].buildName == name) {
|
||||
comps[c].builds.splice(i, 1);
|
||||
break; // A build is unique ber comparison
|
||||
}
|
||||
}
|
||||
}
|
||||
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist a comparison in localstorage.
|
||||
*
|
||||
* @param {string} name The name of the comparison
|
||||
* @param {array} builds Array of builds
|
||||
* @param {array} facets Array of facet indices
|
||||
*/
|
||||
this.saveComparison = function(name, builds, facets) {
|
||||
if (!this.lsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.comparisons[name]) {
|
||||
this.comparisons[name] = {};
|
||||
}
|
||||
this.comparisons[name] = {
|
||||
facets: facets,
|
||||
builds: _.map(builds, function(b) { return { shipId: b.id || b.shipId, buildName: b.buildName }; })
|
||||
};
|
||||
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
|
||||
this.state.hasComparisons = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* [getComparison description]
|
||||
* @param {string} name [description]
|
||||
* @return {object} Object containing array of facets and ship id + build names
|
||||
*/
|
||||
this.getComparison = function(name) {
|
||||
if (this.comparisons[name]) {
|
||||
return this.comparisons[name];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the comparison from localstorage.
|
||||
* @param {string} name Comparison name
|
||||
*/
|
||||
this.deleteComparison = function(name) {
|
||||
if (this.lsEnabled && this.comparisons[name]) {
|
||||
delete this.comparisons[name];
|
||||
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
|
||||
this.state.hasComparisons = Object.keys(this.comparisons).length > 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete all builds and comparisons from localStorage
|
||||
*/
|
||||
this.deleteAll = function() {
|
||||
angular.copy({}, this.builds); // Empty object but keep original instance
|
||||
angular.copy({}, this.comparisons);
|
||||
this.state.hasBuilds = false;
|
||||
this.state.buildCount = 0;
|
||||
|
||||
if (this.lsEnabled) {
|
||||
localStorage.removeItem(LS_KEY_BUILDS);
|
||||
localStorage.removeItem(LS_KEY_COMPARISONS);
|
||||
}
|
||||
};
|
||||
|
||||
this.getAll = function() {
|
||||
var data = {};
|
||||
data[LS_KEY_BUILDS] = this.builds;
|
||||
data[LS_KEY_COMPARISONS] = this.comparisons;
|
||||
data[LS_KEY_INSURANCE] = this.getInsurance();
|
||||
data[LS_KEY_DISCOUNTS] = this.getDiscount();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the saved insurance type
|
||||
* @return {string} The name of the saved insurance type of null
|
||||
*/
|
||||
this.getInsurance = function() {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.getItem(LS_KEY_INSURANCE);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist selected insurance type
|
||||
* @param {string} name Insurance type name
|
||||
*/
|
||||
this.setInsurance = function(name) {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.setItem(LS_KEY_INSURANCE, name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist selected discount
|
||||
* @param {number} val Discount value/amount
|
||||
*/
|
||||
this.setDiscount = function(val) {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.setItem(LS_KEY_DISCOUNTS, angular.toJson(val));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the saved discount
|
||||
* @return {number} val Discount value/amount
|
||||
*/
|
||||
this.getDiscount = function() {
|
||||
if (this.lsEnabled) {
|
||||
return angular.fromJson(localStorage.getItem(LS_KEY_DISCOUNTS));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist selected cost tab
|
||||
* @param {number} val Discount value/amount
|
||||
*/
|
||||
this.setCostTab = function(tabName) {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.setItem(LS_KEY_COST_TAB, tabName);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the saved discount
|
||||
* @return {number} val Discount value/amount
|
||||
*/
|
||||
this.getCostTab = function() {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.getItem(LS_KEY_COST_TAB);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the last router state from local storage
|
||||
* @param {object} state State object containing state name and params
|
||||
*/
|
||||
this.getState = function() {
|
||||
if (this.lsEnabled) {
|
||||
var state = localStorage.getItem('state');
|
||||
if (state) {
|
||||
return angular.fromJson(state);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the current router state to localstorage
|
||||
* @param {object} state State object containing state name and params
|
||||
*/
|
||||
this.setState = function(state) {
|
||||
if (this.lsEnabled) {
|
||||
localStorage.setItem('state', angular.toJson(state));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if localStorage is enabled/active
|
||||
* @return {Boolean} True if localStorage is enabled
|
||||
*/
|
||||
this.isEnabled = function() {
|
||||
return this.lsEnabled;
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,232 +0,0 @@
|
||||
/**
|
||||
* Service managing seralization and deserialization of models for use in URLs and persistene.
|
||||
*/
|
||||
angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', 'ShipsDB', 'Ship', 'Components', '$state', function(_, GroupMap, MountMap, ShipsDB, Ship, Components, $state) {
|
||||
|
||||
/**
|
||||
* Serializes the ships selected components for all slots to a URL friendly string.
|
||||
* @param {Ship} ship The ship to be serialized.
|
||||
* @return {string} Encoded string of components
|
||||
*/
|
||||
this.fromShip = function(ship) {
|
||||
var power = {
|
||||
enabled: [ship.cargoScoop.enabled ? 1 : 0],
|
||||
priorities: [ship.cargoScoop.priority]
|
||||
};
|
||||
|
||||
var data = [
|
||||
ship.bulkheads.id,
|
||||
_.map(ship.common, mapGroup, power),
|
||||
_.map(ship.hardpoints, mapGroup, power),
|
||||
_.map(ship.internal, mapGroup, power),
|
||||
'.',
|
||||
LZString.compressToBase64(power.enabled.join('')).replace(/\//g, '-'),
|
||||
'.',
|
||||
LZString.compressToBase64(power.priorities.join('')).replace(/\//g, '-')
|
||||
];
|
||||
|
||||
return _.flatten(data).join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates an existing ship instance's slots with components determined by the
|
||||
* code.
|
||||
*
|
||||
* @param {Ship} ship The ship instance to be updated
|
||||
* @param {string} dataString The string to deserialize
|
||||
*/
|
||||
this.toShip = function(ship, dataString) {
|
||||
var common = new Array(ship.common.length),
|
||||
hardpoints = new Array(ship.hardpoints.length),
|
||||
internal = new Array(ship.internal.length),
|
||||
parts = dataString.split('.'),
|
||||
priorities = null,
|
||||
enabled = null,
|
||||
code = parts[0];
|
||||
|
||||
if (parts[1]) {
|
||||
enabled = LZString.decompressFromBase64(parts[1].replace(/-/g, '/')).split('');
|
||||
}
|
||||
|
||||
if (parts[2]) {
|
||||
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split('');
|
||||
}
|
||||
|
||||
decodeToArray(code, internal, decodeToArray(code, hardpoints, decodeToArray(code, common, 1)));
|
||||
|
||||
ship.buildWith(
|
||||
{
|
||||
bulkheads: code.charAt(0) * 1,
|
||||
common: common,
|
||||
hardpoints: hardpoints,
|
||||
internal: internal
|
||||
},
|
||||
priorities,
|
||||
enabled
|
||||
);
|
||||
};
|
||||
|
||||
this.toDetailedBuild = function(buildName, ship, code) {
|
||||
var standard = ship.common,
|
||||
hardpoints = ship.hardpoints,
|
||||
internal = ship.internal;
|
||||
|
||||
var data = {
|
||||
$schema: 'http://cdn.coriolis.io/schemas/ship-loadout/1.json#',
|
||||
name: buildName,
|
||||
ship: ship.name,
|
||||
references: [{
|
||||
name: 'Coriolis.io',
|
||||
url: $state.href('outfit', { shipId: ship.id, code: code, bn: buildName }, { absolute: true }),
|
||||
code: code,
|
||||
shipId: ship.id
|
||||
}],
|
||||
components: {
|
||||
standard: {
|
||||
bulkheads: ship.bulkheads.c.name,
|
||||
powerPlant: { class: standard[0].c.class, rating: standard[0].c.rating },
|
||||
thrusters: { class: standard[1].c.class, rating: standard[1].c.rating },
|
||||
frameShiftDrive: { class: standard[2].c.class, rating: standard[2].c.rating },
|
||||
lifeSupport: { class: standard[3].c.class, rating: standard[3].c.rating },
|
||||
powerDistributor: { class: standard[4].c.class, rating: standard[4].c.rating },
|
||||
sensors: { class: standard[5].c.class, rating: standard[5].c.rating },
|
||||
fuelTank: { class: standard[6].c.class, rating: standard[6].c.rating }
|
||||
},
|
||||
hardpoints: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass > 0; }), slotToSchema),
|
||||
utility: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass === 0; }), slotToSchema),
|
||||
internal: _.map(internal, slotToSchema)
|
||||
},
|
||||
stats: {}
|
||||
};
|
||||
|
||||
for (var stat in ship) {
|
||||
if (!isNaN(ship[stat])) {
|
||||
data.stats[stat] = Math.round(ship[stat] * 100) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
this.fromDetailedBuild = function(detailedBuild) {
|
||||
var shipId = _.findKey(ShipsDB, { properties: { name: detailedBuild.ship } });
|
||||
|
||||
if (!shipId) {
|
||||
throw 'No such ship: ' + detailedBuild.ship;
|
||||
}
|
||||
|
||||
var comps = detailedBuild.components;
|
||||
var shipData = ShipsDB[shipId];
|
||||
var ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
var bulkheads = Components.bulkheadIndex(comps.standard.bulkheads);
|
||||
|
||||
if (bulkheads < 0) {
|
||||
throw 'Invalid bulkheads: ' + comps.standard.bulkheads;
|
||||
}
|
||||
|
||||
var common = _.map(
|
||||
['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank'],
|
||||
function(c) {
|
||||
if (!comps.standard[c].class || !comps.standard[c].rating) {
|
||||
throw 'Invalid value for ' + c;
|
||||
}
|
||||
return comps.standard[c].class + comps.standard[c].rating;
|
||||
}
|
||||
);
|
||||
|
||||
var internal = _.map(comps.internal, function(c) { return c ? Components.findInternalId(c.group, c.class, c.rating, c.name) : 0; });
|
||||
|
||||
var hardpoints = _.map(comps.hardpoints, function(c) {
|
||||
return c ? Components.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount], c.missile) : 0;
|
||||
});
|
||||
hardpoints = hardpoints.concat(_.map(comps.utility, function(c) {
|
||||
return c ? Components.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount]) : 0;
|
||||
}));
|
||||
|
||||
ship.buildWith({ bulkheads: bulkheads, common: common, hardpoints: hardpoints, internal: internal });
|
||||
|
||||
return ship;
|
||||
};
|
||||
|
||||
this.toDetailedExport = function(builds) {
|
||||
var data = [];
|
||||
|
||||
for (var shipId in builds) {
|
||||
for (var buildName in builds[shipId]) {
|
||||
var code = builds[shipId][buildName];
|
||||
var shipData = ShipsDB[shipId];
|
||||
var ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
this.toShip(ship, code);
|
||||
data.push(this.toDetailedBuild(buildName, ship, code));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
this.fromComparison = function(name, builds, facets, predicate, desc) {
|
||||
var shipBuilds = [];
|
||||
|
||||
builds.forEach(function(b) {
|
||||
shipBuilds.push({ s: b.id, n: b.buildName, c: this.fromShip(b) });
|
||||
}.bind(this));
|
||||
|
||||
return LZString.compressToBase64(angular.toJson({
|
||||
n: name,
|
||||
b: shipBuilds,
|
||||
f: facets,
|
||||
p: predicate,
|
||||
d: desc ? 1 : 0
|
||||
})).replace(/\//g, '-');
|
||||
};
|
||||
|
||||
this.toComparison = function(code) {
|
||||
return angular.fromJson(LZString.decompressFromBase64(code.replace(/-/g, '/')));
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility function to retrieve a safe string for selected component for a slot.
|
||||
* Used for serialization to code only.
|
||||
*
|
||||
* @private
|
||||
* @param {object} slot The slot object.
|
||||
* @return {string} The id of the selected component or '-' if none selected
|
||||
*/
|
||||
function mapGroup(slot) {
|
||||
this.enabled.push(slot.enabled ? 1 : 0);
|
||||
this.priorities.push(slot.priority);
|
||||
|
||||
return slot.id === null ? '-' : slot.id;
|
||||
}
|
||||
|
||||
function decodeToArray(code, arr, codePos) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (code.charAt(codePos) == '-') {
|
||||
arr[i] = 0;
|
||||
codePos++;
|
||||
} else {
|
||||
arr[i] = code.substring(codePos, codePos + 2);
|
||||
codePos += 2;
|
||||
}
|
||||
}
|
||||
return codePos;
|
||||
}
|
||||
|
||||
function slotToSchema(slot) {
|
||||
if (slot.c) {
|
||||
var o = { class: slot.c.class, rating: slot.c.rating, group: GroupMap[slot.c.grp] };
|
||||
if (slot.c.name) {
|
||||
o.name = slot.c.name;
|
||||
}
|
||||
if (slot.c.mode) {
|
||||
o.mount = MountMap[slot.c.mode];
|
||||
}
|
||||
if (slot.c.missile) {
|
||||
o.missile = slot.c.missile;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}]);
|
||||
@@ -1,69 +0,0 @@
|
||||
angular.module('shipyard').factory('ComponentSet', ['lodash', function(_) {
|
||||
|
||||
function filter(data, maxClass, minClass, mass) {
|
||||
return _.filter(data, function(c) {
|
||||
return c.class <= maxClass && c.class >= minClass && (c.maxmass === undefined || mass <= c.maxmass);
|
||||
});
|
||||
}
|
||||
|
||||
function ComponentSet(components, mass, maxCommonArr, maxInternal, maxHardPoint) {
|
||||
this.mass = mass;
|
||||
this.common = {};
|
||||
this.internal = {};
|
||||
this.hardpoints = {};
|
||||
this.hpClass = {};
|
||||
this.intClass = {};
|
||||
|
||||
this.common[0] = filter(components.common[0], maxCommonArr[0], 0, mass); // Power Plant
|
||||
this.common[2] = filter(components.common[2], maxCommonArr[2], 0, mass); // FSD
|
||||
this.common[4] = filter(components.common[4], maxCommonArr[4], 0, mass); // Power Distributor
|
||||
this.common[6] = filter(components.common[6], maxCommonArr[6], 0, mass); // Fuel Tank
|
||||
|
||||
// Thrusters, filter components by class only (to show full list of ratings for that class)
|
||||
var minThrusterClass = _.reduce(components.common[1], function(minClass, thruster) {
|
||||
return (thruster.maxmass >= mass && thruster.class < minClass) ? thruster.class : minClass;
|
||||
}, maxCommonArr[1]);
|
||||
this.common[1] = filter(components.common[1], maxCommonArr[1], minThrusterClass, 0); // Thrusters
|
||||
|
||||
// Slots where component class must be equal to slot class
|
||||
this.common[3] = filter(components.common[3], maxCommonArr[3], maxCommonArr[3], 0); // Life Supprt
|
||||
this.common[5] = filter(components.common[5], maxCommonArr[5], maxCommonArr[5], mass); // Sensors
|
||||
|
||||
for (var h in components.hardpoints) {
|
||||
this.hardpoints[h] = filter(components.hardpoints[h], maxHardPoint, 0, mass);
|
||||
}
|
||||
|
||||
for (var g in components.internal) {
|
||||
this.internal[g] = filter(components.internal[g], maxInternal, 0, mass);
|
||||
}
|
||||
}
|
||||
|
||||
ComponentSet.prototype.getHps = function(c) {
|
||||
if (!this.hpClass[c]) {
|
||||
var o = this.hpClass[c] = {};
|
||||
for (var key in this.hardpoints) {
|
||||
var data = filter(this.hardpoints[key], c, c ? 1 : 0, this.mass);
|
||||
if (data.length) { // If group is not empty
|
||||
o[key] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.hpClass[c];
|
||||
};
|
||||
|
||||
ComponentSet.prototype.getInts = function(c) {
|
||||
if (!this.intClass[c]) {
|
||||
var o = this.intClass[c] = {};
|
||||
for (var key in this.internal) {
|
||||
var data = filter(this.internal[key], c, 0, this.mass);
|
||||
if (data.length) { // If group is not empty
|
||||
o[key] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.intClass[c];
|
||||
};
|
||||
|
||||
return ComponentSet;
|
||||
|
||||
}]);
|
||||
@@ -1,431 +0,0 @@
|
||||
angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', 'calcJumpRange', 'calcTotalRange', 'lodash', 'ArmourMultiplier', function(Components, calcShieldStrength, calcJumpRange, calcTotalRange, _, ArmourMultiplier) {
|
||||
|
||||
/**
|
||||
* Returns the power usage type of a slot and it's particular component
|
||||
* @param {object} slot The Slot
|
||||
* @param {object} component The component in the slot
|
||||
* @return {string} The key for the power usage type
|
||||
*/
|
||||
function powerUsageType(slot, component) {
|
||||
if (component) {
|
||||
if (component.retractedOnly) {
|
||||
return 'retOnly';
|
||||
}
|
||||
if (component.passive) {
|
||||
return 'retracted';
|
||||
}
|
||||
}
|
||||
return slot.cat != 1 ? 'retracted' : 'deployed';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ship model used to track all ship components and properties.
|
||||
*
|
||||
* @param {string} id Unique ship Id / Key
|
||||
* @param {object} properties Basic ship properties such as name, manufacturer, mass, etc
|
||||
* @param {object} slots Collection of slot groups (standard/common, internal, hardpoints) with their max class size.
|
||||
*/
|
||||
function Ship(id, properties, slots) {
|
||||
this.id = id;
|
||||
this.cargoScoop = { c: Components.cargoScoop(), type: 'SYS' };
|
||||
this.bulkheads = { incCost: true, maxClass: 8 };
|
||||
|
||||
for (var p in properties) { this[p] = properties[p]; } // Copy all base properties from shipData
|
||||
|
||||
for (var slotType in slots) { // Initialize all slots
|
||||
var slotGroup = slots[slotType];
|
||||
var group = this[slotType] = []; // Initialize Slot group (Common, Hardpoints, Internal)
|
||||
for (var i = 0; i < slotGroup.length; i++) {
|
||||
group.push({ id: null, c: null, incCost: true, maxClass: slotGroup[i] });
|
||||
}
|
||||
}
|
||||
// Make a Ship 'slot'/item similar to other slots
|
||||
this.c = { incCost: true, type: 'SHIP', discountedCost: this.hullCost, c: { name: this.name, cost: this.hullCost } };
|
||||
|
||||
this.costList = _.union(this.internal, this.common, this.hardpoints);
|
||||
this.costList.push(this.bulkheads); // Add The bulkheads
|
||||
this.costList.unshift(this.c); // Add the ship itself to the list
|
||||
|
||||
this.powerList = _.union(this.internal, this.hardpoints);
|
||||
this.powerList.unshift(this.cargoScoop);
|
||||
this.powerList.unshift(this.common[1]); // Add Thrusters
|
||||
this.powerList.unshift(this.common[5]); // Add Sensors
|
||||
this.powerList.unshift(this.common[4]); // Add Power Distributor
|
||||
this.powerList.unshift(this.common[3]); // Add Life Support
|
||||
this.powerList.unshift(this.common[2]); // Add FSD
|
||||
this.powerList.unshift(this.common[0]); // Add Power Plant
|
||||
|
||||
this.shipCostMultiplier = 1;
|
||||
this.componentCostMultiplier = 1;
|
||||
|
||||
this.priorityBands = [
|
||||
{ deployed: 0, retracted: 0, retOnly: 0 },
|
||||
{ deployed: 0, retracted: 0, retOnly: 0 },
|
||||
{ deployed: 0, retracted: 0, retOnly: 0 },
|
||||
{ deployed: 0, retracted: 0, retOnly: 0 },
|
||||
{ deployed: 0, retracted: 0, retOnly: 0 }
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds/Updates the ship instance with the components[comps] passed in.
|
||||
* @param {object} comps Collection of components used to build the ship
|
||||
*/
|
||||
Ship.prototype.buildWith = function(comps, priorities, enabled) {
|
||||
var internal = this.internal,
|
||||
common = this.common,
|
||||
hps = this.hardpoints,
|
||||
bands = this.priorityBands,
|
||||
cl = common.length,
|
||||
i, l;
|
||||
|
||||
// Reset Cumulative stats
|
||||
this.fuelCapacity = 0;
|
||||
this.cargoCapacity = 0;
|
||||
this.ladenMass = 0;
|
||||
this.armourAdded = 0;
|
||||
this.armourMultiplier = 1;
|
||||
this.shieldMultiplier = 1;
|
||||
this.totalCost = this.c.incCost ? this.c.discountedCost : 0;
|
||||
this.unladenMass = this.hullMass;
|
||||
this.totalDps = 0;
|
||||
|
||||
this.bulkheads.c = null;
|
||||
this.useBulkhead(comps.bulkheads || 0, true);
|
||||
this.cargoScoop.priority = priorities ? priorities[0] * 1 : 0;
|
||||
this.cargoScoop.enabled = enabled ? enabled[0] * 1 : true;
|
||||
|
||||
for (i = 0, l = this.priorityBands.length; i < l; i++) {
|
||||
this.priorityBands[i].deployed = 0;
|
||||
this.priorityBands[i].retracted = 0;
|
||||
this.priorityBands[i].retOnly = 0;
|
||||
}
|
||||
|
||||
if (this.cargoScoop.enabled) {
|
||||
bands[this.cargoScoop.priority].retracted += this.cargoScoop.c.power;
|
||||
}
|
||||
|
||||
for (i = 0; i < cl; i++) {
|
||||
common[i].cat = 0;
|
||||
common[i].enabled = enabled ? enabled[i + 1] * 1 : true;
|
||||
common[i].priority = priorities ? priorities[i + 1] * 1 : 0;
|
||||
common[i].type = 'SYS';
|
||||
common[i].c = common[i].id = null; // Resetting 'old' component if there was one
|
||||
common[i].discountedCost = 0;
|
||||
this.use(common[i], comps.common[i], Components.common(i, comps.common[i]), true);
|
||||
}
|
||||
|
||||
common[1].type = 'ENG'; // Thrusters
|
||||
common[2].type = 'ENG'; // FSD
|
||||
cl++; // Increase accounts for Cargo Scoop
|
||||
|
||||
for (i = 0, l = hps.length; i < l; i++) {
|
||||
hps[i].cat = 1;
|
||||
hps[i].enabled = enabled ? enabled[cl + i] * 1 : true;
|
||||
hps[i].priority = priorities ? priorities[cl + i] * 1 : 0;
|
||||
hps[i].type = hps[i].maxClass ? 'WEP' : 'SYS';
|
||||
hps[i].c = hps[i].id = null; // Resetting 'old' component if there was one
|
||||
hps[i].discountedCost = 0;
|
||||
|
||||
if (comps.hardpoints[i] !== 0) {
|
||||
this.use(hps[i], comps.hardpoints[i], Components.hardpoints(comps.hardpoints[i]), true);
|
||||
}
|
||||
}
|
||||
|
||||
cl += hps.length; // Increase accounts for hardpoints
|
||||
|
||||
for (i = 0, l = internal.length; i < l; i++) {
|
||||
internal[i].cat = 2;
|
||||
internal[i].enabled = enabled ? enabled[cl + i] * 1 : true;
|
||||
internal[i].priority = priorities ? priorities[cl + i] * 1 : 0;
|
||||
internal[i].type = 'SYS';
|
||||
internal[i].id = internal[i].c = null; // Resetting 'old' component if there was one
|
||||
internal[i].discountedCost = 0;
|
||||
|
||||
if (comps.internal[i] !== 0) {
|
||||
this.use(internal[i], comps.internal[i], Components.internal(comps.internal[i]), true);
|
||||
}
|
||||
}
|
||||
|
||||
// Update aggragated stats
|
||||
this.updatePower();
|
||||
this.updateJumpStats();
|
||||
this.updateShieldStrength();
|
||||
};
|
||||
|
||||
Ship.prototype.useBulkhead = function(index, preventUpdate) {
|
||||
var oldBulkhead = this.bulkheads.c;
|
||||
this.bulkheads.id = index;
|
||||
this.bulkheads.c = Components.bulkheads(this.id, index);
|
||||
this.bulkheads.discountedCost = this.bulkheads.c.cost * this.componentCostMultiplier;
|
||||
this.armourMultiplier = ArmourMultiplier[index];
|
||||
this.updateStats(this.bulkheads, this.bulkheads.c, oldBulkhead, preventUpdate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update a slot with a the component if the id is different from the current id for this slot.
|
||||
* Has logic handling components that you may only have 1 of (Shield Generator or Refinery).
|
||||
*
|
||||
* @param {object} slot The component slot
|
||||
* @param {string} id Unique ID for the selected component
|
||||
* @param {object} component Properties for the selected component
|
||||
* @param {boolean} preventUpdate If true, do not update aggregated stats
|
||||
*/
|
||||
Ship.prototype.use = function(slot, id, component, preventUpdate) {
|
||||
if (slot.id != id) { // Selecting a different component
|
||||
// Slot is an internal slot, is not being emptied, and the selected component group/type must be of unique
|
||||
if (slot.cat == 2 && component && _.includes(['psg', 'sg', 'rf', 'fs'], component.grp)) {
|
||||
// Find another internal slot that already has this type/group installed
|
||||
var similarSlot = this.findInternalByGroup(component.grp);
|
||||
// If another slot has an installed component with of the same type
|
||||
if (!preventUpdate && similarSlot && similarSlot !== slot) {
|
||||
this.updateStats(similarSlot, null, similarSlot.c, true); // Update stats but don't trigger a global update
|
||||
similarSlot.id = similarSlot.c = null; // Empty the slot
|
||||
similarSlot.discountedCost = 0;
|
||||
}
|
||||
}
|
||||
var oldComponent = slot.c;
|
||||
slot.id = id;
|
||||
slot.c = component;
|
||||
slot.discountedCost = (component && component.cost) ? component.cost * this.componentCostMultiplier : 0;
|
||||
this.updateStats(slot, component, oldComponent, preventUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate jump range using the installed FSD and the
|
||||
* specified mass which can be more or less than ships actual mass
|
||||
* @param {number} mass Mass in tons
|
||||
* @param {number} fuel Fuel available in tons
|
||||
* @return {number} Jump range in Light Years
|
||||
*/
|
||||
Ship.prototype.jumpRangeWithMass = function(mass, fuel) {
|
||||
return calcJumpRange(mass, this.common[2].c, fuel);
|
||||
};
|
||||
|
||||
/**
|
||||
* Find an internal slot that has an installed component of the specific group.
|
||||
*
|
||||
* @param {string} group Component group/type
|
||||
* @return {number} The index of the slot in ship.internal
|
||||
*/
|
||||
Ship.prototype.findInternalByGroup = function(group) {
|
||||
var index;
|
||||
if (group == 'sg' || group == 'psg') {
|
||||
index = _.findIndex(this.internal, function(slot) {
|
||||
return slot.c && (slot.c.grp == 'sg' || slot.c.grp == 'psg');
|
||||
});
|
||||
} else {
|
||||
index = _.findIndex(this.internal, function(slot) {
|
||||
return slot.c && slot.c.grp == group;
|
||||
});
|
||||
}
|
||||
|
||||
if (index !== -1) {
|
||||
return this.internal[index];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Will change the priority of the specified slot if the new priority is valid
|
||||
* @param {object} slot The slot to be updated
|
||||
* @param {number} newPriority The new priority to be set
|
||||
* @return {boolean} Returns true if the priority was changed (within range)
|
||||
*/
|
||||
Ship.prototype.changePriority = function(slot, newPriority) {
|
||||
if (newPriority >= 0 && newPriority < this.priorityBands.length) {
|
||||
var oldPriority = slot.priority;
|
||||
slot.priority = newPriority;
|
||||
|
||||
if (slot.enabled) { // Only update power if the slot is enabled
|
||||
var usage = powerUsageType(slot, slot.c);
|
||||
this.priorityBands[oldPriority][usage] -= slot.c.power;
|
||||
this.priorityBands[newPriority][usage] += slot.c.power;
|
||||
this.updatePower();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Ship.prototype.setCostIncluded = function(item, included) {
|
||||
if (item.incCost != included && item.c) {
|
||||
this.totalCost += included ? item.discountedCost : -item.discountedCost;
|
||||
}
|
||||
item.incCost = included;
|
||||
};
|
||||
|
||||
Ship.prototype.setSlotEnabled = function(slot, enabled) {
|
||||
if (slot.enabled != enabled) { // Enabled state is changing
|
||||
slot.enabled = enabled;
|
||||
if (slot.c) {
|
||||
this.priorityBands[slot.priority][powerUsageType(slot, slot.c)] += enabled ? slot.c.power : -slot.c.power;
|
||||
|
||||
if (slot.c.grp == 'sg' || slot.c.grp == 'psg') {
|
||||
this.updateShieldStrength();
|
||||
} else if (slot.c.grp == 'sb') {
|
||||
this.shieldMultiplier += slot.c.shieldmul * (enabled ? 1 : -1);
|
||||
this.updateShieldStrength();
|
||||
} else if (slot.c.dps) {
|
||||
this.totalDps += slot.c.dps * (enabled ? 1 : -1);
|
||||
}
|
||||
|
||||
this.updatePower();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ship.prototype.getSlotStatus = function(slot, deployed) {
|
||||
if (!slot.c) { // Empty Slot
|
||||
return 0; // No Status (Not possible)
|
||||
} else if (!slot.enabled) {
|
||||
return 1; // Disabled
|
||||
} else if (deployed && !slot.c.retractedOnly) { // Certain component (e.g. Detaild Surface scanner) are power only while retracted
|
||||
return this.priorityBands[slot.priority].deployedSum > this.powerAvailable ? 2 : 3; // Offline : Online
|
||||
// Active hardpoints have no retracted status
|
||||
} else if ((deployed && slot.c.retractedOnly) || (slot.cat === 1 && !slot.c.passive)) {
|
||||
return 0; // No Status (Not possible)
|
||||
}
|
||||
return this.priorityBands[slot.priority].retractedSum > this.powerAvailable ? 2 : 3; // Offline : Online
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the ship's cumulative and aggregated stats based on the component change.
|
||||
*/
|
||||
Ship.prototype.updateStats = function(slot, n, old, preventUpdate) {
|
||||
var powerChange = slot == this.common[0];
|
||||
|
||||
if (old) { // Old component now being removed
|
||||
switch (old.grp) {
|
||||
case 'ft':
|
||||
this.fuelCapacity -= old.capacity;
|
||||
break;
|
||||
case 'cr':
|
||||
this.cargoCapacity -= old.capacity;
|
||||
break;
|
||||
case 'hr':
|
||||
this.armourAdded -= old.armouradd;
|
||||
break;
|
||||
case 'sb':
|
||||
this.shieldMultiplier -= slot.enabled ? old.shieldmul : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot.incCost && old.cost) {
|
||||
this.totalCost -= old.cost * this.componentCostMultiplier;
|
||||
}
|
||||
|
||||
if (old.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][powerUsageType(slot, old)] -= old.power;
|
||||
powerChange = true;
|
||||
|
||||
if (old.dps) {
|
||||
this.totalDps -= old.dps;
|
||||
}
|
||||
}
|
||||
this.unladenMass -= old.mass || 0;
|
||||
}
|
||||
|
||||
if (n) {
|
||||
switch (n.grp) {
|
||||
case 'ft':
|
||||
this.fuelCapacity += n.capacity;
|
||||
break;
|
||||
case 'cr':
|
||||
this.cargoCapacity += n.capacity;
|
||||
break;
|
||||
case 'hr':
|
||||
this.armourAdded += n.armouradd;
|
||||
break;
|
||||
case 'sb':
|
||||
this.shieldMultiplier += slot.enabled ? n.shieldmul : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot.incCost && n.cost) {
|
||||
this.totalCost += n.cost * this.componentCostMultiplier;
|
||||
}
|
||||
|
||||
if (n.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][powerUsageType(slot, n)] += n.power;
|
||||
powerChange = true;
|
||||
|
||||
if (n.dps) {
|
||||
this.totalDps += n.dps;
|
||||
}
|
||||
}
|
||||
this.unladenMass += n.mass || 0;
|
||||
}
|
||||
|
||||
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
|
||||
this.armour = this.armourAdded + Math.round(this.baseArmour * this.armourMultiplier);
|
||||
|
||||
if (!preventUpdate) {
|
||||
if (powerChange) {
|
||||
this.updatePower();
|
||||
}
|
||||
this.updateJumpStats();
|
||||
this.updateShieldStrength();
|
||||
}
|
||||
};
|
||||
|
||||
Ship.prototype.updatePower = function() {
|
||||
var bands = this.priorityBands;
|
||||
var prevRetracted = 0, prevDeployed = 0;
|
||||
|
||||
for (var i = 0, l = bands.length; i < l; i++) {
|
||||
var band = bands[i];
|
||||
prevRetracted = band.retractedSum = prevRetracted + band.retracted + band.retOnly;
|
||||
prevDeployed = band.deployedSum = prevDeployed + band.deployed + band.retracted;
|
||||
}
|
||||
|
||||
this.powerAvailable = this.common[0].c.pGen;
|
||||
this.powerRetracted = prevRetracted;
|
||||
this.powerDeployed = prevDeployed;
|
||||
};
|
||||
|
||||
Ship.prototype.updateShieldStrength = function() {
|
||||
var sgSlot = this.findInternalByGroup('sg'); // Find Shield Generator slot Index if any
|
||||
this.shieldStrength = sgSlot && sgSlot.enabled ? calcShieldStrength(this.hullMass, this.baseShieldStrength, sgSlot.c, this.shieldMultiplier) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Jump Range and total range calculations
|
||||
*/
|
||||
Ship.prototype.updateJumpStats = function() {
|
||||
var fsd = this.common[2].c; // Frame Shift Drive;
|
||||
this.unladenRange = calcJumpRange(this.unladenMass + fsd.maxfuel, fsd, this.fuelCapacity); // Include fuel weight for jump
|
||||
this.fullTankRange = calcJumpRange(this.unladenMass + this.fuelCapacity, fsd, this.fuelCapacity); // Full Tanke
|
||||
this.ladenRange = calcJumpRange(this.ladenMass, fsd, this.fuelCapacity);
|
||||
this.unladenTotalRange = calcTotalRange(this.unladenMass, fsd, this.fuelCapacity);
|
||||
this.ladenTotalRange = calcTotalRange(this.unladenMass + this.cargoCapacity, fsd, this.fuelCapacity);
|
||||
this.maxJumpCount = Math.ceil(this.fuelCapacity / fsd.maxfuel);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recalculate all item costs and total based on discounts.
|
||||
* @param {number} shipCostMultiplier Ship cost multiplier discount (e.g. 0.9 === 10% discount)
|
||||
* @param {number} componentCostMultiplier Component cost multiplier discount (e.g. 0.75 === 25% discount)
|
||||
*/
|
||||
Ship.prototype.applyDiscounts = function(shipCostMultiplier, componentCostMultiplier) {
|
||||
var total = 0;
|
||||
var costList = this.costList;
|
||||
|
||||
for (var i = 0, l = costList.length; i < l; i++) {
|
||||
var item = costList[i];
|
||||
if (item.c && item.c.cost) {
|
||||
item.discountedCost = item.c.cost * (item.type == 'SHIP' ? shipCostMultiplier : componentCostMultiplier);
|
||||
if (item.incCost) {
|
||||
total += item.discountedCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.shipCostMultiplier = shipCostMultiplier;
|
||||
this.componentCostMultiplier = componentCostMultiplier;
|
||||
this.totalCost = total;
|
||||
};
|
||||
|
||||
return Ship;
|
||||
}]);
|
||||
@@ -1,266 +0,0 @@
|
||||
/**
|
||||
* This module contains all of the logic and models corresponding to
|
||||
* information or behavoir in Elite Dangerous.
|
||||
*
|
||||
* This file contains values and functions that can be reused across the app.
|
||||
*
|
||||
* @requires ngLodash
|
||||
*/
|
||||
angular.module('shipyard', ['ngLodash'])
|
||||
// Create 'angularized' references to DB.This will aid testing
|
||||
.constant('ShipsDB', DB.ships)
|
||||
.constant('ComponentsDB', DB.components)
|
||||
.value('ArmourMultiplier', [
|
||||
1, // Lightweight
|
||||
1.4, // Reinforced
|
||||
1.945, // Military
|
||||
1.945, // Mirrored
|
||||
1.945 // Reactive
|
||||
])
|
||||
.value('commonArray', [
|
||||
'Power Plant',
|
||||
'Thrusters',
|
||||
'Frame Shift Drive',
|
||||
'Life Support',
|
||||
'Power Distributor',
|
||||
'Sensors',
|
||||
'Fuel Tank'
|
||||
])
|
||||
// Map to lookup group labels/names for component grp
|
||||
.value('GroupMap', {
|
||||
// Common
|
||||
pp: 'Power Plant',
|
||||
t: 'Thrusters',
|
||||
fsd: 'Frame Shift Drive',
|
||||
ls: 'Life Support',
|
||||
pd: 'Power Distributor',
|
||||
s: 'Sensors',
|
||||
ft: 'Fuel Tank',
|
||||
|
||||
// Internal
|
||||
fs: 'Fuel Scoop',
|
||||
sc: 'Scanner',
|
||||
am: 'Auto Field-Maintenance Unit',
|
||||
cr: 'Cargo Rack',
|
||||
fi: 'FSD Interdictor',
|
||||
hb: 'Hatch Breaker Limpet Controller',
|
||||
hr: 'Hull Reinforcement Package',
|
||||
rf: 'Refinery',
|
||||
scb: 'Shield Cell Bank',
|
||||
sg: 'Shield Generator',
|
||||
psg: 'Prismatic Shield Generator',
|
||||
dc: 'Docking Computer',
|
||||
fx: 'Fuel Transfer Limpet Controller',
|
||||
pc: 'Prospector Limpet Controller',
|
||||
cc: 'Collector Limpet Controller',
|
||||
|
||||
// Hard Points
|
||||
bl: 'Beam Laser',
|
||||
ul: 'Burst Laser',
|
||||
c: 'Cannon',
|
||||
cs: 'Cargo Scanner',
|
||||
cm: 'Countermeasure',
|
||||
fc: 'Fragment Cannon',
|
||||
ws: 'Frame Shift Wake Scanner',
|
||||
kw: 'Kill Warrant Scanner',
|
||||
nl: 'Mine Launcher',
|
||||
ml: 'Mining Laser',
|
||||
mr: 'Missile Rack',
|
||||
pa: 'Plasma Accelerator',
|
||||
mc: 'Multi-cannon',
|
||||
pl: 'Pulse Laser',
|
||||
rg: 'Rail Gun',
|
||||
sb: 'Shield Booster',
|
||||
tp: 'Torpedo Pylon'
|
||||
})
|
||||
.value('MountMap', {
|
||||
'F': 'Fixed',
|
||||
'G': 'Gimballed',
|
||||
'T': 'Turret',
|
||||
'Fixed': 'F',
|
||||
'Gimballed': 'G',
|
||||
'Turret': 'T'
|
||||
})
|
||||
.value('shipSize', [
|
||||
'N/A',
|
||||
'Small',
|
||||
'Medium',
|
||||
'Large',
|
||||
'Capital'
|
||||
])
|
||||
.value('hardPointClass', [
|
||||
'Utility',
|
||||
'Small',
|
||||
'Medium',
|
||||
'Large',
|
||||
'Huge'
|
||||
])
|
||||
/**
|
||||
* Array of all Ship properties (facets) organized into groups
|
||||
* used for ship comparisons.
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
.value('ShipFacets', [
|
||||
{ // 0
|
||||
title: 'Agility',
|
||||
props: ['agility'],
|
||||
unit: '',
|
||||
fmt: 'fCrd'
|
||||
},
|
||||
{ // 1
|
||||
title: 'Speed',
|
||||
props: ['speed', 'boost'],
|
||||
lbls: ['Thrusters', 'Boost'],
|
||||
unit: 'm/s',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 2
|
||||
title: 'Armour',
|
||||
props: ['armour'],
|
||||
unit: '',
|
||||
fmt: 'fCrd'
|
||||
},
|
||||
{ // 3
|
||||
title: 'Shields',
|
||||
props: ['shieldStrength'],
|
||||
unit: 'MJ',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 4
|
||||
title: 'Jump Range',
|
||||
props: ['unladenRange', 'fullTankRange', 'ladenRange'],
|
||||
lbls: ['Max', 'Full Tank', 'Laden'],
|
||||
unit: 'LY',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 5
|
||||
title: 'Mass',
|
||||
props: ['unladenMass', 'ladenMass'],
|
||||
lbls: ['Unladen', 'Laden'],
|
||||
unit: 'T',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 6
|
||||
title: 'Cargo',
|
||||
props: ['cargoCapacity'],
|
||||
unit: 'T',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 7
|
||||
title: 'Fuel',
|
||||
props: ['fuelCapacity'],
|
||||
unit: 'T',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 8
|
||||
title: 'Power',
|
||||
props: ['powerRetracted', 'powerDeployed', 'powerAvailable'],
|
||||
lbls: ['Retracted', 'Deployed', 'Available'],
|
||||
unit: 'MW',
|
||||
fmt: 'fPwr'
|
||||
},
|
||||
{ // 9
|
||||
title: 'Cost',
|
||||
props: ['totalCost'],
|
||||
unit: 'CR',
|
||||
fmt: 'fCrd'
|
||||
},
|
||||
{ // 10
|
||||
title: 'Total Range',
|
||||
props: ['unladenTotalRange', 'ladenTotalRange'],
|
||||
lbls: ['Unladen', 'Laden'],
|
||||
unit: 'LY',
|
||||
fmt: 'fRound'
|
||||
},
|
||||
{ // 11
|
||||
title: 'DPS',
|
||||
props: ['totalDps'],
|
||||
lbls: ['Dps'],
|
||||
unit: '',
|
||||
fmt: 'fRound'
|
||||
}
|
||||
])
|
||||
/**
|
||||
* Set of all available / theoretical discounts
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
.value('Discounts', {
|
||||
'None': 1,
|
||||
'5%': 0.95,
|
||||
'10%': 0.90,
|
||||
'15%': 0.85,
|
||||
'20%': 0.80,
|
||||
'25%': 0.75
|
||||
})
|
||||
/**
|
||||
* Calculate the maximum single jump range based on mass and a specific FSD
|
||||
*
|
||||
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
|
||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||
* @param {number} fuel Optional - The fuel consumed during the jump (must be less than the drives max fuel per jump)
|
||||
* @return {number} Distance in Light Years
|
||||
*/
|
||||
.value('calcJumpRange', function(mass, fsd, fuel) {
|
||||
return Math.pow(Math.min(fuel === undefined ? fsd.maxfuel : fuel, fsd.maxfuel) / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass;
|
||||
})
|
||||
/**
|
||||
* Calculate the total range based on mass and a specific FSD, and all fuel available
|
||||
*
|
||||
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
|
||||
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
|
||||
* @param {number} fuel The total fuel available
|
||||
* @return {number} Distance in Light Years
|
||||
*/
|
||||
.value('calcTotalRange', function(mass, fsd, fuel) {
|
||||
var fuelRemaining = fuel % fsd.maxfuel; // Fuel left after making N max jumps
|
||||
var jumps = Math.floor(fuel / fsd.maxfuel);
|
||||
mass += fuelRemaining;
|
||||
// Going backwards, start with the last jump using the remaining fuel
|
||||
var totalRange = fuelRemaining > 0 ? Math.pow(fuelRemaining / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass : 0;
|
||||
// For each max fuel jump, calculate the max jump range based on fuel mass left in the tank
|
||||
for (var j = 0; j < jumps; j++) {
|
||||
mass += fsd.maxfuel;
|
||||
totalRange += Math.pow(fsd.maxfuel / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass;
|
||||
}
|
||||
return totalRange;
|
||||
})
|
||||
/**
|
||||
* Calculate the a ships shield strength based on mass, shield generator and shield boosters used.
|
||||
*
|
||||
* @private
|
||||
* @param {number} mass Current mass of the ship
|
||||
* @param {number} shields Base Shield strength MJ for ship
|
||||
* @param {object} sg The shield generator used
|
||||
* @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any)
|
||||
* @return {number} Approximate shield strengh in MJ
|
||||
*/
|
||||
.value('calcShieldStrength', function(mass, shields, sg, multiplier) {
|
||||
if (mass <= sg.minmass) {
|
||||
return shields * multiplier * sg.minmul;
|
||||
}
|
||||
if (mass < sg.optmass) {
|
||||
return shields * multiplier * (sg.minmul + (mass - sg.minmass) / (sg.optmass - sg.minmass) * (sg.optmul - sg.minmul));
|
||||
}
|
||||
if (mass < sg.maxmass) {
|
||||
return shields * multiplier * (sg.optmul + (mass - sg.optmass) / (sg.maxmass - sg.optmass) * (sg.maxmul - sg.optmul));
|
||||
}
|
||||
return shields * multiplier * sg.maxmul;
|
||||
})
|
||||
/**
|
||||
* Calculate the a ships speed based on mass, and thrusters. Currently Innacurate / Incomplete :(
|
||||
*
|
||||
* @private
|
||||
* @param {number} mass Current mass of the ship
|
||||
* @param {number} baseSpeed Base speed m/s for ship
|
||||
* @param {number} baseBoost Base boost m/s for ship
|
||||
* @param {object} thrusters The shield generator used
|
||||
* @return {object} Approximate speed and boost speed in m/s
|
||||
*/
|
||||
.value('calcSpeed', function(mass, baseSpeed, baseBoost) { //, thrusters) {
|
||||
//var speed = baseSpeed * (1 + ((thrusters.optmass / mass) * 0.1 ) ); // TODO: find thruser coefficient(s)
|
||||
//var boost = baseBoost * (1 + ((thrusters.optmass / mass) * 0.1 ) );
|
||||
|
||||
return { boost: baseSpeed, speed: baseBoost };
|
||||
});
|
||||
@@ -1,96 +0,0 @@
|
||||
angular.module('shipyard').service('Components', ['lodash', 'ComponentsDB', 'ShipsDB', 'ComponentSet', function(_, C, Ships, ComponentSet) {
|
||||
|
||||
this.cargoScoop = function() {
|
||||
return { name: 'Cargo Hatch', class: 1, rating: 'H', power: 0.6 };
|
||||
};
|
||||
|
||||
this.common = function(typeIndex, componentId) {
|
||||
return C.common[typeIndex][componentId];
|
||||
};
|
||||
|
||||
this.hardpoints = function(id) {
|
||||
for (var n in C.hardpoints) {
|
||||
var group = C.hardpoints[n];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
if (group[i].id == id) {
|
||||
return group[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.internal = function(id) {
|
||||
for (var n in C.internal) {
|
||||
var group = C.internal[n];
|
||||
for (var i = 0; i < group.length; i++) {
|
||||
if (group[i].id == id) {
|
||||
return group[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.findInternalId = function(groupName, clss, rating, name) {
|
||||
var group = C.internal[groupName];
|
||||
|
||||
if (!group) {
|
||||
throw 'Invalid internal group: ' + groupName;
|
||||
}
|
||||
|
||||
for (var i = 0, l = group.length; i < l; i++) {
|
||||
if (group[i].class == clss && group[i].rating == rating && ((!name && !group[i].name) || group[i].name == name)) {
|
||||
return group[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.findHardpointId = function(groupName, clss, rating, name, mode, missile) {
|
||||
var group = C.hardpoints[groupName];
|
||||
|
||||
if (!group) {
|
||||
throw 'Invalid hardpoint group: ' + groupName;
|
||||
}
|
||||
|
||||
for (var i = 0, l = group.length; i < l; i++) {
|
||||
if (group[i].class == clss && group[i].rating == rating && group[i].mode == mode
|
||||
&& ((!name && !group[i].name) || group[i].name == name)
|
||||
&& ((!missile && !group[i].missile) || group[i].missile == missile)
|
||||
) {
|
||||
return group[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Looks up the bulkhead component for a specific ship and bulkhead
|
||||
* @param {string} shipId Unique ship Id/Key
|
||||
* @param {number} bulkheadsId Id/Index for the specified bulkhead
|
||||
* @return {object} The bulkhead component object
|
||||
*/
|
||||
this.bulkheads = function(shipId, bulkheadsId) {
|
||||
return C.bulkheads[shipId][bulkheadsId];
|
||||
};
|
||||
|
||||
this.bulkheadIndex = function(bulkheadName) {
|
||||
return ['Lightweight Alloy', 'Reinforced Alloy', 'Military Grade Composite', 'Mirrored Surface Composite', 'Reactive Surface Composite'].indexOf(bulkheadName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new ComponentSet that contains all available components
|
||||
* that the specified ship is eligible to use.
|
||||
*
|
||||
* @param {string} shipId Unique ship Id/Key
|
||||
* @return {ComponentSet} The set of components the ship can install
|
||||
*/
|
||||
this.forShip = function(shipId) {
|
||||
var ship = Ships[shipId];
|
||||
return new ComponentSet(C, ship.minMassFilter || ship.properties.hullMass + 5, ship.slots.common, ship.slots.internal[0], ship.slots.hardpoints[0]);
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
.deep-space {
|
||||
background-image: url(images/deep-space-1920x1080.jpg);
|
||||
}
|
||||
|
||||
.docking-bay {
|
||||
background-image: url(images/bay-1920x1080.jpg);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
.d3-tip {
|
||||
font-size: 0.8em;
|
||||
padding: 0.25em 0.5em;
|
||||
background: @primary-disabled;
|
||||
|
||||
color: @primary-bg;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Creates a small triangle extender for the tooltip */
|
||||
.d3-tip:after {
|
||||
box-sizing: border-box;
|
||||
display: inline;
|
||||
font-size: 10px;
|
||||
width: 100%;
|
||||
line-height: 1;
|
||||
color: @primary-disabled;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Northward tooltips */
|
||||
.d3-tip.n {
|
||||
margin-top: -7px;
|
||||
&:after {
|
||||
content: "\25BC";
|
||||
margin: -1px 0 0 0;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Eastward tooltips */
|
||||
.d3-tip.e {
|
||||
margin-left: 8px;
|
||||
&:after {
|
||||
content: "\25C0";
|
||||
margin: -4px 0 0 0;
|
||||
top: 50%;
|
||||
left: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Southward tooltips */
|
||||
.d3-tip.s {
|
||||
margin-top: 8px;
|
||||
&:after {
|
||||
content: "\25B2";
|
||||
margin: 0 0 1px 0;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Westward tooltips */
|
||||
.d3-tip.w:after {
|
||||
content: "\25B6";
|
||||
margin: -4px 0 0 -1px;
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'Orbitron-Regular';
|
||||
src: url('fonts/orbitron-regular-webfont.eot');
|
||||
src: url('fonts/orbitron-regular-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('fonts/orbitron-regular-webfont.woff2') format('woff2'),
|
||||
url('fonts/orbitron-regular-webfont.woff') format('woff'),
|
||||
url('fonts/orbitron-regular-webfont.ttf') format('truetype'),
|
||||
url('fonts/orbitron-regular-webfont.svg#orbitronregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Eurostile';
|
||||
src: url('fonts/eurostile.eot');
|
||||
src: url('fonts/eurostile.eot?#iefix') format('embedded-opentype'),
|
||||
url('fonts/eurostile.woff2') format('woff2'),
|
||||
url('fonts/eurostile.woff') format('woff'),
|
||||
url('fonts/eurostile.ttf') format('truetype'),
|
||||
url('fonts/eurostile.svg#euro_capsregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@fStandard: 'Eurostile', Helvetica, sans-serif;
|
||||
@fTitle: 'Orbitron-Regular', Arial, sans-serif;
|
||||
@@ -1,43 +0,0 @@
|
||||
|
||||
.slider-axis {
|
||||
line, path {
|
||||
fill: none;
|
||||
stroke: @primary-disabled;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 0.7em;
|
||||
fill: @primary-disabled;
|
||||
}
|
||||
|
||||
|
||||
.domain {
|
||||
fill: none;
|
||||
stroke: @primary;
|
||||
stroke-opacity: .3;
|
||||
stroke-width: 0.7em;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.slider {
|
||||
|
||||
text {
|
||||
dominant-baseline: central;
|
||||
fill: @primary;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.filled {
|
||||
stroke-width: 0.3em;
|
||||
stroke-linecap: round;
|
||||
stroke: @primary-disabled;
|
||||
}
|
||||
|
||||
.handle {
|
||||
fill: @primary;
|
||||
stroke-opacity: .5;
|
||||
cursor: crosshair;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
.sortable {
|
||||
.user-select-none();
|
||||
}
|
||||
|
||||
.as-sortable-item, .as-sortable-placeholder {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.as-sortable-item {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.as-sortable-item-handle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.as-sortable-drag {
|
||||
margin: 0;
|
||||
padding:0;
|
||||
opacity: .8;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.as-sortable-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<div id="app-update" ng-show="appCacheUpdate">
|
||||
<a href="#" onclick="window.location.reload()">Update Available! Click to Refresh</a>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<a class="l" ui-sref="shipyard" style="margin-right: 1em;" title="Ships"><svg class="icon xl"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#coriolis"></use></svg></a>
|
||||
|
||||
<div class="l menu">
|
||||
<div class="menu-header" ng-class="{selected: openedMenu=='s'}" ng-click="openMenu($event,'s')">
|
||||
<svg class="icon warning"><use xlink:href="#rocket"></use></svg><span class="menu-item-label"> Ships</span>
|
||||
</div>
|
||||
<div class="menu-list dbl no-wrap" ng-if="openedMenu=='s'">
|
||||
<a class="block" ng-repeat="(shipId,ship) in ships" ui-sref-active="active" ui-sref="outfit({shipId:shipId, code:null, bn:null})">{{::ship.properties.name}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="l menu">
|
||||
<div class="menu-header" ng-class="{selected: openedMenu=='b', disabled: !bs.hasBuilds}" ng-click="openMenu($event,'b')">
|
||||
<svg class="icon warning" ng-class="{'warning-disabled': !bs.hasBuilds}"><use xlink:href="#hammer"></use></svg><span class="menu-item-label"> Builds</span>
|
||||
</div>
|
||||
<div class="menu-list" ng-if="openedMenu=='b'" ng-click="$event.stopPropagation();">
|
||||
<div class="dbl" >
|
||||
<div><ul ng-repeat="shipId in buildsList">
|
||||
{{ships[shipId].properties.name}}
|
||||
<li ng-repeat="(name, build) in allBuilds[shipId]">
|
||||
<a ui-sref-active="active" class="name" ui-sref="outfit({shipId:shipId, code:build, bn:name})" ng-bind="name"></a>
|
||||
</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="l menu">
|
||||
<div class="menu-header" ng-class="{selected: openedMenu=='comp', disabled: !bs.hasBuilds}" ng-click="openMenu($event,'comp')">
|
||||
<svg class="icon warning" ng-class="{'warning-disabled': !bs.hasBuilds}"><use xlink:href="#stats-bars"></use></svg><span class="menu-item-label"> Compare</span>
|
||||
</div>
|
||||
<div class="menu-list" ng-if="openedMenu=='comp'" ng-click="$event.stopPropagation();" style="white-space: nowrap;">
|
||||
<span ng-if="!bs.hasComparisons">None Created</span>
|
||||
<a ng-repeat="(name, comp) in allComparisons" ui-sref-active="active" class="block name" ui-sref="compare({name:name})" ng-bind="name"></a>
|
||||
<hr />
|
||||
<a ui-sref="compare({name: 'all'})" class="block">Compare All</a>
|
||||
<a ui-sref="compare({name: null})" class="block">Create New</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="r menu">
|
||||
<div class="menu-header" ng-class="{selected: openedMenu=='settings'}" ng-click="openMenu($event,'settings')">
|
||||
<svg class="icon xl warning"><use xlink:href="#cogs"></use></svg><span class="menu-item-label"> Settings</span>
|
||||
</div>
|
||||
<div class="menu-list no-wrap" ng-if="openedMenu=='settings'" ng-click="$event.stopPropagation();">
|
||||
<ul>
|
||||
Insurance
|
||||
<li><select ng-model="insurance.current" ng-options="ins.name for (i,ins) in insurance.opts" ng-change="updateInsurance()"></select></li>
|
||||
</ul><br>
|
||||
<ul>
|
||||
Ship Discount
|
||||
<li><select ng-model="discounts.ship" ng-options="i for (i,d) in discounts.opts" ng-change="updateDiscount()"></select></li>
|
||||
</ul><br>
|
||||
<ul>
|
||||
Component Discount
|
||||
<li><select ng-model="discounts.components" ng-options="i for (i,d) in discounts.opts" ng-change="updateDiscount()"></select></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul>
|
||||
Builds & Comparisons
|
||||
<li><a href="#" class="block" ng-click="backup($event)">Backup</a></li>
|
||||
<li><a href="#" class="block" ng-click="detailedExport($event)">Detailed Export</a></li>
|
||||
<li><a href="#" class="block" ui-sref="modal.import">Import</a></li>
|
||||
<li><a href="#" class="block" ui-sref="modal.delete">Delete All</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<a href="#" ui-sref="modal.about" class="block">About</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
@@ -1,3 +0,0 @@
|
||||
<div class="modal-bg">
|
||||
<div class="modal" ui-view="modal-content" ng-click="$event.stopPropagation()"></div>
|
||||
</div>
|
||||
@@ -1,17 +0,0 @@
|
||||
<div class="sz">{{::['U','S','M','L','H'][hp.maxClass]}}</div>
|
||||
<div class="empty" ng-if="!hp.c">EMPTY</div>
|
||||
<div ng-if="hp.c">
|
||||
{{hp.c.class}}{{hp.c.rating}}<span ng-if="hp.c.mode">/{{hp.c.mode}}{{hp.c.missile}}</span> {{hp.c.name || lbl}}
|
||||
<div class="r">{{hp.c.mass}} <u>T</u></div>
|
||||
<div class="cb">
|
||||
<div class="l" ng-if="hp.c.damage">Damage: {{hp.c.damage}} <span ng-if="hp.c.ssdam">({{$r.fCrd(hp.c.ssdam)}} <u>Mj</u>)</span></div>
|
||||
<div class="l" ng-if="hp.c.dps">DPS: {{hp.c.dps}} <span ng-if="hp.c.mjdps">({{$r.fCrd(hp.c.mjdps)}} <u>Mj</u>)</span></div>
|
||||
<div class="l" ng-if="hp.c.thermload">T-Load: {{hp.c.thermload}}</div>
|
||||
<div class="l" ng-if="hp.c.type">Type: {{hp.c.type}}</div>
|
||||
<div class="l" ng-if="hp.c.rof">ROF: {{hp.c.rof}}<u>/s</u></div>
|
||||
<div class="l" ng-if="hp.c.armourpen">Pen: {{hp.c.armourpen}}</div>
|
||||
<div class="l" ng-if="hp.c.shieldmul">+{{$r.fRPct(hp.c.shieldmul)}}</div>
|
||||
<div class="l" ng-if="hp.c.range">{{hp.c.range}} <u>KM</u></div>
|
||||
<div class="l" ng-if="hp.c.ammo">Ammo: {{$r.fCrd(hp.c.clip)}}/{{$r.fCrd(hp.c.ammo)}}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,22 +0,0 @@
|
||||
<div class="sz" ng-bind="c.maxClass"></div>
|
||||
<div class="empty" ng-if="!c.c">EMPTY</div>
|
||||
<div ng-if="c.c">
|
||||
<div class="l name">{{c.c.class}}{{c.c.rating}} {{c.c.name || lbl}}</div>
|
||||
<div class="r">{{c.c.mass || c.c.capacity || '0'}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l" ng-if="c.c.optmass">Optimal Mass: {{c.c.optmass}} <u>T</u></div>
|
||||
<div class="l" ng-if="c.c.maxmass">Max Mass: {{c.c.maxmass}} <u>T</u></div>
|
||||
<div class="l" ng-if="c.c.bins">{{c.c.bins}} <u>Bins</u></div>
|
||||
<div class="l" ng-if="c.c.rate">Rate: {{c.c.rate}} <u>Kg/s</u> Refuel Time: {{$r.fTime(fuel * 1000 / c.c.rate)}}</div>
|
||||
<div class="l" ng-if="c.c.ammo">Ammo: {{c.c.ammo}}</div>
|
||||
<div class="l" ng-if="c.c.cells">Cells: {{c.c.cells}}</div>
|
||||
<div class="l" ng-if="c.c.recharge">Recharge: {{c.c.recharge}} <u>MJ</u></div>
|
||||
<div class="l" ng-if="c.c.repair">Repair: {{c.c.repair}}</div>
|
||||
<div class="l" ng-if="c.c.range">Range {{c.c.range}} <u>km</u></div>
|
||||
<div class="l" ng-if="c.c.time">Time: {{$r.fTime(c.c.time)}}</div>
|
||||
<div class="l" ng-if="c.c.maximum">Max: {{(c.c.maximum)}}</div>
|
||||
<div class="l" ng-if="c.c.rangeLS">{{c.c.rangeLS}} <u>LS</u></div>
|
||||
<div class="l" ng-if="c.c.rangeLS === null"><svg class="icon"><use xlink:href="#infinite"></use></svg> <u>LS</u></div>
|
||||
<div class="l" ng-if="c.c.rangeRating">Range: {{c.c.rangeRating}}</div>
|
||||
<div class="l" ng-if="c.c.armouradd">+{{c.c.armouradd}} <u>Armour</u></div>
|
||||
</div>
|
||||
@@ -1,29 +0,0 @@
|
||||
<h1><svg class="icon xl"><use xlink:href="#coriolis"></use></svg> <span class="warning">Coriolis</span></h1>
|
||||
<p>The Coriolis project was inspired by <a href="http://www.edshipyard.com/" target="_blank">E:D Shipyard</a> and, of course,
|
||||
<a href="http://www.elitedangerous.com" target="_blank">Elite Dangerous</a>. The ultimate goal of Coriolis is to provide rich features to support in-game play and planning while engaging the E:D community to support its development.</p>
|
||||
|
||||
<p>Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments.</p>
|
||||
|
||||
<div>
|
||||
<a class="l" style="margin: 0.4em" href="https://github.com/cmmcleod/coriolis" target="_blank" title="Coriolis Github Project">
|
||||
<svg class="icon fg xl"><use xlink:href="#github-mark"></use></svg>
|
||||
</a>
|
||||
<h2>Github</h2>
|
||||
<a href="https://github.com/cmmcleod/coriolis" target="_blank" title="Coriolis Github Project">github.com/cmmcleod/coriolis</a>
|
||||
</div>
|
||||
<p>
|
||||
Coriolis is an open source project. Checkout the list of upcoming features and to-do list on github.
|
||||
Any and all contributions and feedback are welcome. If you encounter any bugs please report them and provide as much detail as possible.
|
||||
</p>
|
||||
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHLwYJKoZIhvcNAQcEoIIHIDCCBxwCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCjl3XoqQ3Q+x/qS7Va1lwvF0IgUs8gBbrwj1/uEv/xFyPSB2G0kgWqiB2c/8vvfcjjyMr4nlzLUlmQ0yl1zZaeTXFciN5a+JsvaBISThIlN9UP7PXP61TVHCECtt/hBNtlOmg8/gG8khJCj8+qi81XsNAz5bEDpdahKW3fwGHD4jELMAkGBSsOAwIaBQAwgawGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQI4EVkn3RE+9qAgYhg2sTmY1Gul2yJyLYJZPRMO/PwgzEogb2NlIcshJSO+KvBea5NjjTXN2EJNqJa24h4lGA1mdrSgzTGDrVbdcnuti9+7ggn5R5s5IwEEQnN4JQx3IAqsp3UmJbti5t776Ns50nQbjA8NzxI+gwUmIvUQaVs6wC4HYXG6q8QtqUIWeVDhvbnt+H8oIIDhzCCA4MwggLsoAMCAQICAQAwDQYJKoZIhvcNAQEFBQAwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0MDIxMzEwMTMxNVoXDTM1MDIxMzEwMTMxNVowgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBR07d/ETMS1ycjtkpkvjXZe9k+6CieLuLsPumsJ7QC1odNz3sJiCbs2wC0nLE0uLGaEtXynIgRqIddYCHx88pb5HTXv4SZeuv0Rqq4+axW9PLAAATU8w04qqjaSXgbGLP3NmohqM6bV9kZZwZLR/klDaQGo1u9uDb9lr4Yn+rBQIDAQABo4HuMIHrMB0GA1UdDgQWBBSWn3y7xm8XvVk/UtcKG+wQ1mSUazCBuwYDVR0jBIGzMIGwgBSWn3y7xm8XvVk/UtcKG+wQ1mSUa6GBlKSBkTCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb22CAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCBXzpWmoBa5e9fo6ujionW1hUhPkOBakTr3YCDjbYfvJEiv/2P+IobhOGJr85+XHhN0v4gUkEDI8r2/rNk1m0GA8HKddvTjyGw/XqXa+LSTlDYkqI8OwR8GEYj4efEtcRpRYBxV8KxAW93YDWzFGvruKnnLbDAF6VR5w/cCMn5hzGCAZowggGWAgEBMIGUMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbQIBADAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTUwNjA1MjEwNDQzWjAjBgkqhkiG9w0BCQQxFgQUx6Bs50H7tbYJln13pP5J7J1KiSUwDQYJKoZIhvcNAQEBBQAEgYBiOr1RX38uvwghuIZxKpjXX4LG/GoyYM6citfsBD5vjUGj0udmsamjlur+dwxJNs9dULnJO6huoTvxqxTui0Mh3n21YKoMqVE/erfNk2XygrJw9bEtW+HXjU3F+OGKR7dfD9STp2ZlvTEvZR9JRV5A/udC9/9U9eD5iLKRRwkIBg==-----END PKCS7-----
|
||||
">
|
||||
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" name="submit" alt="PayPal - Donate to Coriolis.io" style="border:none;">
|
||||
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
|
||||
</form>
|
||||
|
||||
<p>Help keep the lights on! Donations will be used to cover costs of running and maintaining Coriolis. Thanks for helping!</p>
|
||||
|
||||
<button class="r dismiss" ng-click="dismiss()">Close</button>
|
||||
@@ -1,4 +0,0 @@
|
||||
<h2>Delete All</h2>
|
||||
<p style="text-align:center;">Are you sure?</p>
|
||||
<button class="l" ng-click="deleteAll()">Yes</button>
|
||||
<button class="r" ng-click="dismiss()">No</button>
|
||||
@@ -1,6 +0,0 @@
|
||||
<h2 ng-bind="title"></h2>
|
||||
<div ng-if="description" ng-bind="description"></div>
|
||||
<div>
|
||||
<textarea class="cb json" ng-click="onTextClick($event)" ng-bind="export"></textarea>
|
||||
</div>
|
||||
<button class="r dismiss" ng-click="dismiss()">Close</button>
|
||||
@@ -1,40 +0,0 @@
|
||||
<h2>Import</h2>
|
||||
<div ng-show="!processed">
|
||||
<textarea class="cb json" ng-model="importJSON" ng-change="validateJson()" placeholder="Paste JSON Here"></textarea>
|
||||
<button class="l" ng-click="process()" ng-disabled="!jsonValid">Proceed</button>
|
||||
<div class="l warning" style="margin-left:3em;">{{errorMsg}}</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="processed">
|
||||
<table class="l" style="overflow:hidden;margin: 1em 0; width: 100%;">
|
||||
<thead><tr><th style="text-align:left">Ship</th><th style="text-align:left">Build Name</th><th>Action</th></tr></thead>
|
||||
<tbody ng-repeat="(shipId,shipBuilds) in builds">
|
||||
<tr class="cb" ng-repeat="(buildName, b) in shipBuilds">
|
||||
<td>{{ships[shipId].properties.name}}</td>
|
||||
<td><input type="text" ng-model="b.useName"/></td>
|
||||
<td style="text-align:center" ng-class="{warning: hasBuild(shipId, b.useName) == true, disabled: b.useName == ''}">
|
||||
<span ng-show="b.useName">{{ hasBuild(shipId, b.useName)? 'Overwrite' : 'Create' }}</span>
|
||||
<span ng-show="b.useName == ''">Skip</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="l" style="overflow:hidden;margin: 1em 0; width: 100%;" ng-if="comparisons">
|
||||
<thead><tr><th style="text-align:left">Comparison</th><th>Action</th></tr></thead>
|
||||
<tbody>
|
||||
<tr class="cb" ng-repeat="(name, comparison) in comparisons">
|
||||
<td><input type="text" ng-model="comparison.useName"/></td>
|
||||
<td style="text-align:center" ng-class="{warning: hasComparison(comparison.useName) == true, disabled: comparison.useName == ''}">
|
||||
<span ng-show="comparison.useName">{{ hasComparison(comparison.useName)? 'Overwrite' : 'Create' }}</span>
|
||||
<span ng-show="comparison.useName == ''">Skip</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button class="cl l" ng-click="import()"><svg class="icon"><use xlink:href="#download"></use></svg> Import</button>
|
||||
<button class="l" style="margin-left: 2em;" ng-click="processed = false" ng-show="canEdit">Edit JSON</button>
|
||||
</div>
|
||||
|
||||
<button class="r dismiss" ng-click="dismiss()">Cancel</button>
|
||||
@@ -1,9 +0,0 @@
|
||||
<h2>Permalink</h2>
|
||||
<br>
|
||||
<h3>URL</h3>
|
||||
<input ng-model="url" size="40" ng-click="onTextClick($event)">
|
||||
<br><br>
|
||||
<h3>Shortened</h3>
|
||||
<input ng-model="shortenedUrl" size="25" ng-click="onTextClick($event)">
|
||||
<br><br>
|
||||
<button class="r dismiss" ng-click="dismiss()">Close</button>
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
<table id="comparison">
|
||||
<tr ng-show="compareMode">
|
||||
<td class="head">Comparison</td>
|
||||
<td>
|
||||
<input ng-model="name" ng-change="nameChange()" placeholder="Enter Comparison Name" maxlength="50" />
|
||||
<button ng-click="save()" ng-disabled="!name || name == 'all' || saved">
|
||||
<svg class="icon lg "><use xlink:href="#floppy-disk"></use></svg><span class="button-lbl"> Save</span>
|
||||
</button>
|
||||
<button ng-click="delete()" ng-disabled="name == 'all' || !saved"><svg class="icon lg warning "><use xlink:href="#bin"></use></svg></button>
|
||||
<button ng-click="selectBuilds(true, $event)">
|
||||
<svg class="icon lg "><use xlink:href="#rocket"></use></svg><span class="button-lbl"> Builds</span>
|
||||
</button>
|
||||
<button class="r" ng-click="permalink($event)" ng-disabled="builds.length == 0">
|
||||
<svg class="icon lg "><use xlink:href="#link"></use></svg><span class="button-lbl"> Permalink</span>
|
||||
</button>
|
||||
<button class="r" ng-click="embed($event)" ng-disabled="builds.length == 0">
|
||||
<svg class="icon lg "><use xlink:href="#embed"></use></svg><span class="button-lbl"> Forum</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="!compareMode">
|
||||
<td class="head">Comparison</td>
|
||||
<td>
|
||||
<h3 ng-bind="name"></h3>
|
||||
<button class="r" ui-sref="modal.import({obj:importObj})"><svg class="icon lg "><use xlink:href="#download"></use></svg> Import Builds</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="head">Compare</td>
|
||||
<td>
|
||||
<ul id="facet-container" as-sortable="facetSortOpts" ng-model="facets" class="sortable" update="tblUpdate">
|
||||
<li ng-repeat="(i,f) in facets" as-sortable-item class="facet" ng-class="{active: f.active}" ng-click="toggleFacet(i)">
|
||||
<div as-sortable-item-handle>↔ <span ng-bind="f.title"></span></div>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="scroll-x">
|
||||
<table id="comp-tbl" comparison-table ng-click="handleClick($event)"></table>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="f in facets | filter:{active:true}" ng-if="builds.length > 0" class="chart" bar-chart facet="f" data="builds">
|
||||
<h3 ng-click="sort(f.props[0])" >{{f.title}}</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-bg" ng-show="showBuilds" ng-click="selectBuilds(false, $event)">
|
||||
<div class="modal" ui-view="modal-content" ng-click="$event.stopPropagation()">
|
||||
<h3>Select Builds to Compare</h3>
|
||||
<div id="build-select">
|
||||
<table>
|
||||
<thead><tr><th colspan="2">Available</th></tr></thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="b in unusedBuilds | orderBy:'name'" ng-click="addBuild(b.id, b.buildName)">
|
||||
<td class="tl" ng-bind="b.name"></td><td class="tl" ng-bind="b.buildName"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h1>⇆</h1>
|
||||
<table>
|
||||
<thead><tr><th colspan="2">Added</th></tr></thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="b in builds | orderBy:'name'" ng-click="removeBuild(b.id, b.buildName)">
|
||||
<td class="tl" ng-bind="b.name"></td><td class="tl" ng-bind="b.buildName"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<br>
|
||||
<button class="r dismiss" ng-click="selectBuilds(false, $event)">Done</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,21 +0,0 @@
|
||||
<div class="error">
|
||||
<h1>
|
||||
<span ng-if="msgPre">{{msgPre}}</span>
|
||||
<small ng-if="msgHighlight">{{msgHighlight}}</small>
|
||||
<span ng-if="msgPost">{{msgPost}}</span>
|
||||
</h1>
|
||||
|
||||
<div style="text-align:left; font-size:0.8em; width: 43em; margin:0 auto;" >
|
||||
<div class="cen">
|
||||
<a href="https://github.com/cmmcleod/ed-shipyard" target="_blank" title="Coriolis Github Project">Create an issue on Github</a>
|
||||
if this keeps happening. <a href="#" ng-click="showDetails = !showDetails">Add these details</a>
|
||||
</div>
|
||||
<div style="margin-top: 2em;" ng-show="showDetails">
|
||||
<div>Browser:<br>{{browser}}</div>
|
||||
<div ng-if="path" >Path:<br>{{path}}</div>
|
||||
<div ng-if="type">Error:<br>{{type}}</div>
|
||||
<div ng-if="errorMessage">Message:<pre>{{errorMessage}}</pre></div>
|
||||
<div ng-if="details">Details:<br><pre>{{details}}<pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,365 +0,0 @@
|
||||
<div id="outfit">
|
||||
|
||||
<div id="overview">
|
||||
<h1 ng-bind="ship.name"></h1>
|
||||
<div id="build">
|
||||
<input ng-model="buildName" ng-change="bnChange()" placeholder="Enter Build Name" maxsize="50" />
|
||||
<button ng-click="saveBuild()" ng-disabled="!buildName || savedCode && code == savedCode || !canSave">
|
||||
<svg class="icon lg "><use xlink:href="#floppy-disk"></use></svg><span class="button-lbl">Save</span>
|
||||
</button>
|
||||
<button ng-click="reloadBuild()" ng-disabled="!savedCode || code == savedCode">
|
||||
<svg class="icon lg"><use xlink:href="#spinner11"></use></svg><span class="button-lbl">Reload</span>
|
||||
</button>
|
||||
<button class="danger" ng-click="deleteBuild()" ng-disabled="!savedCode">
|
||||
<svg class="icon lg"><use xlink:href="#bin"></use></svg>
|
||||
</button>
|
||||
<button ui-sref="outfit({shipId: ship.id,code:null, bn: buildName})" ng-disabled="!code">
|
||||
<svg class="icon lg"><use xlink:href="#switch"></use></svg><span class="button-lbl">Reset</span>
|
||||
</button>
|
||||
<button ng-click="stripBuild()">
|
||||
<svg class="icon lg"><use xlink:href="#feather"></use></svg><span class="button-lbl">Low-Weight</span>
|
||||
</button>
|
||||
<button ng-click="exportBuild($event)" ng-disabled="!buildName">
|
||||
<svg class="icon lg"><use xlink:href="#download"></use></svg><span class="button-lbl">Export</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="summary">
|
||||
<table id="summaryTable">
|
||||
<thead>
|
||||
<tr class="main">
|
||||
<th rowspan="2">Size</th>
|
||||
<th rowspan="2">Agility</th>
|
||||
<th rowspan="2">Speed</th>
|
||||
<th rowspan="2" ng-class="{'bg-warning-disabled': pd.c.enginecapacity < ship.boostEnergy}">Boost</th>
|
||||
<th rowspan="2">DPS</th>
|
||||
<th rowspan="2">Armour</th>
|
||||
<th rowspan="2">Shields</th>
|
||||
<th colspan="3">Mass</th>
|
||||
<th rowspan="2">Cargo</th>
|
||||
<th rowspan="2">Fuel</th>
|
||||
<th colspan="3">Jump Range</th>
|
||||
<th colspan="3">Total Range</th>
|
||||
<th rowspan="2">Lock<br>Factor</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="lft">Hull</th>
|
||||
<th>Unladen</th>
|
||||
<th>Laden</th>
|
||||
<th class="lft">Max</th>
|
||||
<th>Full Tank</th>
|
||||
<th>Laden</th>
|
||||
<th class="lft">Jumps</th>
|
||||
<th>Unladen</th>
|
||||
<th>Laden</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td ng-bind="SZ[ship.class]"></td>
|
||||
<td>{{ship.agility}}/10</td>
|
||||
<td>{{fRound(ship.speed)}} <u>m/s</u></td>
|
||||
<td>
|
||||
<span ng-if="pd.c.enginecapacity >= ship.boostEnergy">{{fRound(ship.boost)}} <u>m/s</u></span>
|
||||
<span class="warning" ng-if="pd.c.enginecapacity < ship.boostEnergy">0 <svg class="icon"><use xlink:href="#warning"></use></svg></span>
|
||||
</td>
|
||||
<td>{{fRound(ship.totalDps)}}</td>
|
||||
<td>
|
||||
{{ship.armour}}
|
||||
<span ng-if="ship.armourAdded || ship.armourMultiplier > 1">(<span ng-if="ship.armourMultiplier > 1">{{fRPct(ship.armourMultiplier)}}</span>
|
||||
<span ng-if="ship.armourAdded">+ {{ship.armourAdded}}</span>)</span>
|
||||
</td>
|
||||
<td>{{fRound(ship.shieldStrength)}} <u>MJ</u> <span ng-if="ship.shieldMultiplier > 1 && ship.shieldStrength > 0">({{fRPct(ship.shieldMultiplier)}})</span></td>
|
||||
<td>{{ship.hullMass}} <u>T</u></td>
|
||||
<td>{{fRound(ship.unladenMass)}} <u>T</u></td>
|
||||
<td>{{fRound(ship.ladenMass)}} <u>T</u></td>
|
||||
<td>{{fRound(ship.cargoCapacity)}} <u>T</u></td>
|
||||
<td>{{fRound(ship.fuelCapacity)}} <u>T</u></td>
|
||||
<td>{{fRound(ship.unladenRange)}} <u>LY</u></td>
|
||||
<td>{{fRound(ship.fullTankRange)}} <u>LY</u></td>
|
||||
<td>{{fRound(ship.ladenRange)}} <u>LY</u></td>
|
||||
<td>{{fRound(ship.maxJumpCount)}}</td>
|
||||
<td>{{fRound(ship.unladenTotalRange)}} <u>LY</u></td>
|
||||
<td>{{fRound(ship.ladenTotalRange)}} <u>LY</u></td>
|
||||
<td ng-bind="ship.masslock"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="standard" class="group">
|
||||
<h1>Standard</h1>
|
||||
<div class="slot" ng-click="selectSlot($event, ship.bulkheads)" ng-class="{selected: selectedSlot==ship.bulkheads}">
|
||||
<div class="details">
|
||||
<div class="sz"><span>8</span></div>
|
||||
<div class="l">Bulkheads</div>
|
||||
<div class="r">{{ship.bulkheads.c.mass}} <u>T</u></div>
|
||||
<div class="cl l">{{ship.bulkheads.c.name}}</div>
|
||||
</div>
|
||||
<div class="select" ng-if="selectedSlot==ship.bulkheads" ng-click="select('b',ship.bulkheads,$event)">
|
||||
<ul>
|
||||
<li class="lc" ng-class="{active: ship.bulkheads.id=='0'}" cpid="0">Lightweight Alloy</li>
|
||||
<li class="lc" ng-class="{active: ship.bulkheads.id=='1'}" cpid="1">Reinforced Alloy</li>
|
||||
<li class="lc" ng-class="{active: ship.bulkheads.id=='2'}" cpid="2">Military Grade Composite</li>
|
||||
<li class="lc" ng-class="{active: ship.bulkheads.id=='3'}" cpid="3">Mirrored Surface Composite</li>
|
||||
<li class="lc" ng-class="{active: ship.bulkheads.id=='4'}" cpid="4">Reactive Surface Composite</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, pp)" ng-class="{selected: selectedSlot==pp}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::pp.maxClass}}</div>
|
||||
<div class="l">{{pp.id}} Power Plant</div>
|
||||
<div class="r">{{pp.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">Efficiency: {{pp.c.eff}}</div>
|
||||
<div class="l">Power: {{pp.c.pGen}} <u>MW</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="pp" opts="availCS.common[0]" ng-if="selectedSlot==pp" ng-click="select('c',pp,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, th)" ng-class="{selected: selectedSlot==th}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::th.maxClass}}</div>
|
||||
<div class="l">{{th.id}} Thrusters</div>
|
||||
<div class="r">{{th.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">Optimal Mass: {{th.c.optmass}} <u>T</u></div>
|
||||
<div class="l">Max Mass: {{th.c.maxmass}} <u>T</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="th" mass="ship.ladenMass" opts="availCS.common[1]" ng-if="selectedSlot==th" ng-click="select('c',th,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, fsd)" ng-class="{selected: selectedSlot==fsd}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::fsd.maxClass}}</div>
|
||||
<div class="l">{{fsd.id}} Frame Shift Drive</div>
|
||||
<div class="r cr">{{fsd.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">Optimal Mass: {{fsd.c.optmass}} <u>T</u></div>
|
||||
<div class="l">Max Fuel: {{fsd.c.maxfuel}} <u>T</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="fsd" opts="availCS.common[2]" ng-if="selectedSlot==fsd" ng-click="select('c',fsd,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, ls)" ng-class="{selected: selectedSlot==ls}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::ls.maxClass}}</div>
|
||||
<div class="l">{{ls.id}} Life Support</div>
|
||||
<div class="r">{{ls.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">Time: {{fTime(ls.c.time)}}</div>
|
||||
</div>
|
||||
<div component-select class="select" s="ls" opts="availCS.common[3]" ng-if="selectedSlot==ls" ng-click="select('c',ls,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, pd)" ng-class="{selected: selectedSlot==pd}">
|
||||
<div class="details" ng-class="{warning: pd.c.enginecapacity < ship.boostEnergy}">
|
||||
<div class="sz">{{::pd.maxClass}}</div>
|
||||
<div class="l">{{pd.id}} Power Distributor</div>
|
||||
<div class="r">{{pd.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">WEP: {{pd.c.weaponcapacity}} <u>MJ</u> / {{pd.c.weaponrecharge}} <u>MW</u></div>
|
||||
<div class="l">SYS: {{pd.c.systemcapacity}} <u>MJ</u> / {{pd.c.systemrecharge}} <u>MW</u></div>
|
||||
<div class="l">ENG: {{pd.c.enginecapacity}} <u>MJ</u> / {{pd.c.enginerecharge}} <u>MW</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="pd" warning="pdWarning" opts="availCS.common[4]" ng-if="selectedSlot==pd" ng-click="select('c',pd,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, ss)" ng-class="{selected: selectedSlot==ss}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::ss.maxClass}}</div>
|
||||
<div class="l">{{ss.id}} Sensors</div>
|
||||
<div class="r">{{ss.c.mass}} <u>T</u></div>
|
||||
<div class="cb"></div>
|
||||
<div class="l">Range: {{ss.c.range}} <u>km</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="ss" opts="availCS.common[5]" ng-if="selectedSlot==ss" ng-click="select('c',ss,$event)"></div>
|
||||
</div>
|
||||
<div class="slot" ng-click="selectSlot($event, ft)" ng-class="{selected: selectedSlot==ft}">
|
||||
<div class="details">
|
||||
<div class="sz">{{::ft.maxClass}}</div>
|
||||
<div class="l">{{ft.id}} Fuel Tank</div>
|
||||
<div class="r">{{ft.c.capacity}} <u>T</u></div>
|
||||
</div>
|
||||
<div component-select class="select" s="ft" opts="availCS.common[6]" ng-if="selectedSlot==ft" ng-click="select('c',ft,$event)"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="internal" class="group">
|
||||
<h1>Internal Compartments</h1>
|
||||
<div class="slot" ng-repeat="i in ship.internal" ng-click="selectSlot($event, i)" context-menu="select('i', i, $event, 'empty')" ng-class="{selected: selectedSlot==i}">
|
||||
<div slot-internal class="details" slot="i" lbl="GMAP[i.c.grp]" fuel="ship.fuelCapacity"></div>
|
||||
<div class="select" ng-if="selectedSlot==i" ng-click="select('i',i,$event)">
|
||||
<div component-select s="i" groups="availCS.getInts(i.maxClass)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="hardpoints" class="group">
|
||||
<h1>HardPoints</h1>
|
||||
<div class="slot" ng-repeat="h in ship.hardpoints | filter:{maxClass: '!0'}" ng-click="selectSlot($event, h)" context-menu="select('h', h, $event, 'empty')" ng-class="{selected: selectedSlot==h}">
|
||||
<div slot-hardpoint class="details" hp="h" size="HPC[h.maxClass]" lbl="GMAP[h.c.grp]"></div>
|
||||
<div class="select" ng-class="{hardpoint: h.maxClass > 0}" ng-if="selectedSlot==h" ng-click="select('h',h,$event)">
|
||||
<div component-select s="h" groups="availCS.getHps(h.maxClass)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="utility" class="group">
|
||||
<h1>Utility Mounts</h1>
|
||||
<div class="slot" ng-repeat="h in ship.hardpoints | filter:{maxClass: '0'}" ng-click="selectSlot($event, h)" context-menu="select('h', h, $event, 'empty')" ng-class="{selected: selectedSlot==h}">
|
||||
<div slot-hardpoint class="details" hp="h" size="HPC[h.maxClass]" lbl="GMAP[h.c.grp]"></div>
|
||||
<div class="select" ng-class="{hardpoint: h.maxClass > 0}" ng-if="selectedSlot==h" ng-click="select('h',h,$event)">
|
||||
<div component-select s="h" groups="availCS.getHps(h.maxClass)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group half" id="componentPriority">
|
||||
<table style="width:100%">
|
||||
<thead>
|
||||
<tr class="main">
|
||||
<th colspan="2" class="sortable le" ng-click="sortPwr(cName)">Component</th>
|
||||
<th style="width:3em;" class="sortable" ng-click="sortPwr('type')">Type</th>
|
||||
<th style="width:4em;" class="sortable" ng-click="sortPwr('priority')">Pri</th>
|
||||
<th colspan="2" class="sortable" ng-click="sortPwr('c.power')">Pwr</th>
|
||||
<th style="width:3em;" class="sortable" ng-click="sortPwr(statusRetracted)">Ret</th>
|
||||
<th style="width:3em;" class="sortable" ng-click="sortPwr(statusDeployed)">Dep</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{pp.c.class}}{{pp.c.rating}}</td>
|
||||
<td class="le shorten">Power Plant</td>
|
||||
<td><u>SYS</u></td>
|
||||
<td>1</td>
|
||||
<td class="ri">{{fPwr(pp.c.pGen)}}</td>
|
||||
<td class="ri"><u>100%</u></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr><td style="line-height:0;" colspan="8"><hr style="margin: 0 0 3px;background: #ff8c0d;border: 0;height: 1px;" /></td></tr>
|
||||
<tr class="highlight" ng-repeat="c in powerList | orderBy:pwrPredicate:pwrDesc" ng-if="c.c.power" ng-class="{disabled:!c.enabled}">
|
||||
<td style="width:1em;" ng-click="togglePwr(c)">{{c.c.class}}{{c.c.rating}}</td>
|
||||
<td class="le shorten" ng-click="togglePwr(c)" ng-bind="cName(c)"></td>
|
||||
<td ng-click="togglePwr(c)"><u ng-bind="c.type"></u></td>
|
||||
<td><span ng-click="decPriority(c)" class="flip">►</span> {{c.priority + 1}} <span ng-click="incPriority(c)">►</span></td>
|
||||
<td class="ri" style="width:3.25em;">{{fPwr(c.c.power)}}</td>
|
||||
<td class="ri" style="width:3em;"><u>{{f1Pct(c.c.power/ship.powerAvailable)}}</u></td>
|
||||
<td ng-if="!c.enabled" class="disabled" colspan="2">DISABLED</td>
|
||||
<td ng-if="c.enabled" ng-class="STATUS_CLASS[statusRetracted(c)]">{{STATUS[statusRetracted(c)]}}</td>
|
||||
<td ng-if="c.enabled" ng-class="STATUS_CLASS[statusDeployed(c)]">{{STATUS[statusDeployed(c)]}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-top: 1em" power-bands bands="priorityBands" available="ship.powerAvailable"></div>
|
||||
</div>
|
||||
|
||||
<div class="group half">
|
||||
<table class="tabs">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:50%" ng-class="{active: costTab == 'retrofit'}" ng-click="updateCostTab('retrofit')">Retrofit Costs</th>
|
||||
<th style="width:50%" ng-class="{active: costTab == 'costs'}" ng-click="updateCostTab('costs')">Costs</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<div ng-if="costTab == 'costs'">
|
||||
<table style="width:100%">
|
||||
<thead>
|
||||
<tr class="main">
|
||||
<th colspan="2" class="sortable le" ng-click="sortCost(cName)">
|
||||
Component
|
||||
<u class="optional-hide" ng-if="discounts.ship < 1">[Ship {{fRPct(1 - discounts.ship)}} off]</u>
|
||||
<u class="optional-hide" ng-if="discounts.components < 1">[Components {{fRPct(1 - discounts.components)}} off]</u>
|
||||
</th>
|
||||
<th class="sortable le" ng-click="sortCost('discountedCost')">Credits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="highlight" ng-repeat="item in costList | orderBy:costPredicate:costDesc" ng-if="item.c.cost > 0" ng-class="{disabled:!item.incCost}">
|
||||
<td class="toggleable" style="width:1em;" ng-click="toggleCost(item)">{{item.c.class}}{{item.c.rating}}</td>
|
||||
<td class="le toggleable shorten" ng-click="toggleCost(item)">{{cName(item)}}</td>
|
||||
<td class="ri toggleable" ng-click="toggleCost(item)">{{fCrd(item.discountedCost)}} <u>CR</u></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="total">
|
||||
<tr class="ri">
|
||||
<td class="lbl">Total</td>
|
||||
<td>{{fCrd(ship.totalCost)}} <u>CR</u></td>
|
||||
</tr>
|
||||
<tr class="ri">
|
||||
<td class="lbl">Insurance</td>
|
||||
<td>{{fCrd(ship.totalCost * insurance.current.pct)}} <u>CR</u></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-if="costTab == 'retrofit'">
|
||||
<div class="scroll-x">
|
||||
<table style="width:100%">
|
||||
<thead>
|
||||
<tr class="main">
|
||||
<th colspan="2" class="sortable le" ng-click="sortRetrofit('sellName')">Sell</th>
|
||||
<th colspan="2" class="sortable le" ng-click="sortRetrofit('buyName')">Buy</th>
|
||||
<th class="sortable le" ng-click="sortRetrofit('netCost')">
|
||||
Net Cost <u class="optional-hide" ng-if="discounts.components < 1">[{{fRPct(1 - discounts.components)}} off]</u>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-if="!retrofitList || retrofitList.length == 0">
|
||||
<td colspan="5" style="padding: 3em 0;">No Retrofitting changes</td>
|
||||
</tr>
|
||||
<tr class="highlight" ng-repeat="item in retrofitList | orderBy:retroPredicate:retroDesc">
|
||||
<td style="width:1em;">{{item.sellClassRating}}</td>
|
||||
<td class="le shorten">{{item.sellName}}</td>
|
||||
<td style="width:1em;">{{item.buyClassRating}}</td>
|
||||
<td class="le shorten">{{item.buyName}}</td>
|
||||
<td class="ri" ng-class="item.netCost > 0 ? 'warning' : 'secondary-disabled'">{{ fCrd(item.netCost)}} <u>CR</u></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<table class="total">
|
||||
<tr class="ri">
|
||||
<td class="lbl">Cost</td>
|
||||
<td colspan="2" ng-class="retrofitTotal > 0 ? 'warning' : 'secondary-disabled'">{{fCrd(retrofitTotal)}} <u>CR</u></td>
|
||||
</tr>
|
||||
<tr class="ri">
|
||||
<td class="lbl">Retrofit from</td>
|
||||
<td class="cen" style="border-right:none;width: 1em;"><u class="primary-disabled">▾</u></td>
|
||||
<td style="border-left:none;padding:0;">
|
||||
<select style="width: 100%;padding: 0" ng-model="$parent.retrofitBuild" ng-change="setRetrofitBase()" ng-options="name as name for (name, build) in allBuilds[ship.id]">
|
||||
<option value="">Stock / Standard</option>
|
||||
</select>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group half">
|
||||
<h1>Jump Range</h1>
|
||||
<div line-chart config="jrChart" series="jrSeries"></div>
|
||||
</div>
|
||||
|
||||
<div class="group half">
|
||||
<h1>Total Range</h1>
|
||||
<div line-chart config="trChart" series="trSeries"></div>
|
||||
</div>
|
||||
|
||||
<!-- TODO: Add back in once calcSpeed is dynamic and accurate
|
||||
<div class="group third">
|
||||
<h1>Thruster Speed</h1>
|
||||
<div line-chart config="speedChart" series="speedSeries"></div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="group half">
|
||||
<div slider max="ship.fuelCapacity" unit="'T'" on-change="::fuelChange(val)" style="position:relative; margin: 0 auto;">
|
||||
<svg class="icon xl primary-disabled" style="position:absolute;height: 100%;"><use xlink:href="#fuel"></use></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,9 +0,0 @@
|
||||
<div id="shipyard">
|
||||
<a ui-sref="outfit({shipId:id})" class="ship" ng-repeat="(id,s) in ships">
|
||||
<h2 ng-bind="s.properties.name"></h2>
|
||||
<div class="subtitle">
|
||||
<small ng-bind="s.properties.manufacturer"></small>
|
||||
</div>
|
||||
{{fCrd(s.retailCost)}} <u>CR</u>
|
||||
</a>
|
||||
</div>
|
||||
57
bower.json
@@ -1,57 +0,0 @@
|
||||
{
|
||||
"name": "coriolis_shipyard",
|
||||
"authors": [
|
||||
"Colin McLeod <colin@mcleod.eu>"
|
||||
],
|
||||
"description": "Coriolis Shipyard for Elite Dangerous",
|
||||
"main": "app/app.js",
|
||||
"keywords": [
|
||||
"elite",
|
||||
"shipyard"
|
||||
],
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"d3": "~3.5.5",
|
||||
"ng-lodash": "~0.2.0",
|
||||
"ui-router-extras": "0.0.13",
|
||||
"angular-ui-router": "^0.2.15",
|
||||
"d3-tip": "~0.6.7",
|
||||
"ng-sortable": "~1.2.1",
|
||||
"lz-string": "~1.4.3",
|
||||
"angular": "~1.4.0"
|
||||
},
|
||||
"overrides": {
|
||||
"angular": {
|
||||
"main": "angular.min.js"
|
||||
},
|
||||
"angular-ui-router": {
|
||||
"main": "release/angular-ui-router.min.js"
|
||||
},
|
||||
"d3": {
|
||||
"main": "d3.min.js"
|
||||
},
|
||||
"ng-lodash": {
|
||||
"main": "build/ng-lodash.min.js"
|
||||
},
|
||||
"ui-router-extras": {
|
||||
"main": [
|
||||
"release/modular/ct-ui-router-extras.core.min.js",
|
||||
"release/modular/ct-ui-router-extras.sticky.min.js"
|
||||
]
|
||||
},
|
||||
"ng-sortable": {
|
||||
"main": "dist/ng-sortable.min.js"
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"angular": "~1.4.0"
|
||||
}
|
||||
}
|
||||
@@ -1,742 +0,0 @@
|
||||
{
|
||||
"sidewinder": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 25600,
|
||||
"mass": 2
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 80320,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 132064,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 139424,
|
||||
"mass": 4
|
||||
}
|
||||
],
|
||||
"diamondback": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 225700,
|
||||
"mass": 13
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 507900,
|
||||
"mass": 26
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 1185100,
|
||||
"mass": 26
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 1330100,
|
||||
"mass": 26
|
||||
}
|
||||
],
|
||||
"diamondback_explorer": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 800000,
|
||||
"mass": 23
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 1800000,
|
||||
"mass": 47
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 4200000,
|
||||
"mass": 26
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 4714000,
|
||||
"mass": 47
|
||||
}
|
||||
],
|
||||
"imperial_courier": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 1017200,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 2288600,
|
||||
"mass": 8
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 5408800,
|
||||
"mass": 8
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 5993700,
|
||||
"mass": 8
|
||||
}
|
||||
],
|
||||
"cobra_mk_iii": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 151887,
|
||||
"mass": 14
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 341746,
|
||||
"mass": 27
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 797407,
|
||||
"mass": 27
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 894995,
|
||||
"mass": 27
|
||||
}
|
||||
],
|
||||
"imperial_clipper": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 8918344,
|
||||
"mass": 30
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 20066274,
|
||||
"mass": 60
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 47423294,
|
||||
"mass": 60
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 52551342,
|
||||
"mass": 60
|
||||
}
|
||||
],
|
||||
"federal_dropship": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 7925682,
|
||||
"mass": 44
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 17832784,
|
||||
"mass": 87
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 42144814,
|
||||
"mass": 87
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 46702081,
|
||||
"mass": 87
|
||||
}
|
||||
],
|
||||
"python": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 22791271,
|
||||
"mass": 26
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 51280361,
|
||||
"mass": 53
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 121192586,
|
||||
"mass": 53
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 134297567,
|
||||
"mass": 53
|
||||
}
|
||||
],
|
||||
"anaconda": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 58787780,
|
||||
"mass": 30
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 132272505,
|
||||
"mass": 60
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 312604021,
|
||||
"mass": 60
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 346406995,
|
||||
"mass": 60
|
||||
}
|
||||
],
|
||||
"eagle": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 26880,
|
||||
"mass": 4
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 90048,
|
||||
"mass": 8
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 140089,
|
||||
"mass": 8
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 150393,
|
||||
"mass": 8
|
||||
}
|
||||
],
|
||||
"viper": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 57172,
|
||||
"mass": 5
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 128637,
|
||||
"mass": 9
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 304014,
|
||||
"mass": 9
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 336888,
|
||||
"mass": 9
|
||||
}
|
||||
],
|
||||
"vulture": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 1970246,
|
||||
"mass": 17
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 4433054,
|
||||
"mass": 35
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 10476783,
|
||||
"mass": 35
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 11609675,
|
||||
"mass": 35
|
||||
}
|
||||
],
|
||||
"fer_de_lance": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 20626816,
|
||||
"mass": 19
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 46410336,
|
||||
"mass": 38
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 109683094,
|
||||
"mass": 38
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 121543513,
|
||||
"mass": 38
|
||||
}
|
||||
],
|
||||
"hauler": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 42176,
|
||||
"mass": 1
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 185047,
|
||||
"mass": 2
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 270295,
|
||||
"mass": 2
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 282421,
|
||||
"mass": 2
|
||||
}
|
||||
],
|
||||
"type_6_transporter": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 418378,
|
||||
"mass": 12
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 941350,
|
||||
"mass": 23
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 2224725,
|
||||
"mass": 23
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 2465292,
|
||||
"mass": 23
|
||||
}
|
||||
],
|
||||
"type_7_transport": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 6988901,
|
||||
"mass": 32
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 15725027,
|
||||
"mass": 63
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 37163481,
|
||||
"mass": 63
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 41182099,
|
||||
"mass": 63
|
||||
}
|
||||
],
|
||||
"type_9_heavy": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 30622336,
|
||||
"mass": 75
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 68900257,
|
||||
"mass": 150
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 162834275,
|
||||
"mass": 150
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 180442119,
|
||||
"mass": 150
|
||||
}
|
||||
],
|
||||
"adder": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 35123,
|
||||
"mass": 3
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 79027,
|
||||
"mass": 5
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 186767,
|
||||
"mass": 5
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 206963,
|
||||
"mass": 5
|
||||
}
|
||||
],
|
||||
"asp": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 2664461,
|
||||
"mass": 21
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 5995038,
|
||||
"mass": 42
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 14168273,
|
||||
"mass": 42
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 15700338,
|
||||
"mass": 42
|
||||
}
|
||||
],
|
||||
"orca": [
|
||||
{
|
||||
"name": "Lightweight Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 0,
|
||||
"mass": 0
|
||||
},
|
||||
{
|
||||
"name": "Reinforced Alloy",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 19415954,
|
||||
"mass": 21
|
||||
},
|
||||
{
|
||||
"name": "Military Grade Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 43685898,
|
||||
"mass": 87
|
||||
},
|
||||
{
|
||||
"name": "Mirrored Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 103244339,
|
||||
"mass": 87
|
||||
},
|
||||
{
|
||||
"name": "Reactive Surface Composite",
|
||||
"class": 1,
|
||||
"rating": "I",
|
||||
"cost": 114408513,
|
||||
"mass": 87
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
{
|
||||
"6E": {
|
||||
"grp": "fsd",
|
||||
"class": 6,
|
||||
"rating": "E",
|
||||
"cost": 199747,
|
||||
"mass": 40,
|
||||
"power": 0.4,
|
||||
"optmass": 960,
|
||||
"maxfuel": 5.3,
|
||||
"fuelmul": 0.011,
|
||||
"fuelpower": 2.6
|
||||
},
|
||||
"6D": {
|
||||
"grp": "fsd",
|
||||
"class": 6,
|
||||
"rating": "D",
|
||||
"cost": 599242,
|
||||
"mass": 16,
|
||||
"power": 0.45,
|
||||
"optmass": 1080,
|
||||
"maxfuel": 5.3,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.6
|
||||
},
|
||||
"6C": {
|
||||
"grp": "fsd",
|
||||
"class": 6,
|
||||
"rating": "C",
|
||||
"cost": 1797726,
|
||||
"mass": 40,
|
||||
"power": 0.5,
|
||||
"optmass": 1200,
|
||||
"maxfuel": 5.3,
|
||||
"fuelmul": 0.008,
|
||||
"fuelpower": 2.6
|
||||
},
|
||||
"6B": {
|
||||
"grp": "fsd",
|
||||
"class": 6,
|
||||
"rating": "B",
|
||||
"cost": 5393177,
|
||||
"mass": 64,
|
||||
"power": 0.63,
|
||||
"optmass": 1500,
|
||||
"maxfuel": 6.6,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.6
|
||||
},
|
||||
"6A": {
|
||||
"grp": "fsd",
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"cost": 16179531,
|
||||
"mass": 40,
|
||||
"power": 0.75,
|
||||
"optmass": 1800,
|
||||
"maxfuel": 8,
|
||||
"fuelmul": 0.012,
|
||||
"fuelpower": 2.6
|
||||
},
|
||||
"5E": {
|
||||
"grp": "fsd",
|
||||
"class": 5,
|
||||
"rating": "E",
|
||||
"cost": 63013,
|
||||
"mass": 20,
|
||||
"power": 0.32,
|
||||
"optmass": 560,
|
||||
"maxfuel": 3.3,
|
||||
"fuelmul": 0.011,
|
||||
"fuelpower": 2.45
|
||||
},
|
||||
"5D": {
|
||||
"grp": "fsd",
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"cost": 189036,
|
||||
"mass": 8,
|
||||
"power": 0.36,
|
||||
"optmass": 630,
|
||||
"maxfuel": 3.3,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.45
|
||||
},
|
||||
"5C": {
|
||||
"grp": "fsd",
|
||||
"class": 5,
|
||||
"rating": "C",
|
||||
"cost": 567106,
|
||||
"mass": 20,
|
||||
"power": 0.4,
|
||||
"optmass": 700,
|
||||
"maxfuel": 3.3,
|
||||
"fuelmul": 0.008,
|
||||
"fuelpower": 2.45
|
||||
},
|
||||
"5B": {
|
||||
"grp": "fsd",
|
||||
"class": 5,
|
||||
"rating": "B",
|
||||
"cost": 1701318,
|
||||
"mass": 32,
|
||||
"power": 0.5,
|
||||
"optmass": 875,
|
||||
"maxfuel": 4.1,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.45
|
||||
},
|
||||
"5A": {
|
||||
"grp": "fsd",
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"cost": 5103953,
|
||||
"mass": 20,
|
||||
"power": 0.6,
|
||||
"optmass": 1050,
|
||||
"maxfuel": 5,
|
||||
"fuelmul": 0.012,
|
||||
"fuelpower": 2.45
|
||||
},
|
||||
"4E": {
|
||||
"grp": "fsd",
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"cost": 19878,
|
||||
"mass": 10,
|
||||
"power": 0.24,
|
||||
"optmass": 280,
|
||||
"maxfuel": 2,
|
||||
"fuelmul": 0.011,
|
||||
"fuelpower": 2.3
|
||||
},
|
||||
"4D": {
|
||||
"grp": "fsd",
|
||||
"class": 4,
|
||||
"rating": "D",
|
||||
"cost": 59633,
|
||||
"mass": 4,
|
||||
"power": 0.27,
|
||||
"optmass": 315,
|
||||
"maxfuel": 2,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.3
|
||||
},
|
||||
"4C": {
|
||||
"grp": "fsd",
|
||||
"class": 4,
|
||||
"rating": "C",
|
||||
"cost": 178898,
|
||||
"mass": 10,
|
||||
"power": 0.3,
|
||||
"optmass": 350,
|
||||
"maxfuel": 2,
|
||||
"fuelmul": 0.008,
|
||||
"fuelpower": 2.3
|
||||
},
|
||||
"4B": {
|
||||
"grp": "fsd",
|
||||
"class": 4,
|
||||
"rating": "B",
|
||||
"cost": 536693,
|
||||
"mass": 16,
|
||||
"power": 0.38,
|
||||
"optmass": 438,
|
||||
"maxfuel": 2.5,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.3
|
||||
},
|
||||
"4A": {
|
||||
"grp": "fsd",
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"cost": 1610080,
|
||||
"mass": 10,
|
||||
"power": 0.45,
|
||||
"optmass": 525,
|
||||
"maxfuel": 3,
|
||||
"fuelmul": 0.012,
|
||||
"fuelpower": 2.3
|
||||
},
|
||||
"3E": {
|
||||
"grp": "fsd",
|
||||
"class": 3,
|
||||
"rating": "E",
|
||||
"cost": 6271,
|
||||
"mass": 5,
|
||||
"power": 0.24,
|
||||
"optmass": 80,
|
||||
"maxfuel": 1.2,
|
||||
"fuelmul": 0.011,
|
||||
"fuelpower": 2.15
|
||||
},
|
||||
"3D": {
|
||||
"grp": "fsd",
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"cost": 18812,
|
||||
"mass": 2,
|
||||
"power": 0.27,
|
||||
"optmass": 90,
|
||||
"maxfuel": 1.2,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.15
|
||||
},
|
||||
"3C": {
|
||||
"grp": "fsd",
|
||||
"class": 3,
|
||||
"rating": "C",
|
||||
"cost": 56435,
|
||||
"mass": 5,
|
||||
"power": 0.3,
|
||||
"optmass": 100,
|
||||
"maxfuel": 1.2,
|
||||
"fuelmul": 0.008,
|
||||
"fuelpower": 2.15
|
||||
},
|
||||
"3B": {
|
||||
"grp": "fsd",
|
||||
"class": 3,
|
||||
"rating": "B",
|
||||
"cost": 169304,
|
||||
"mass": 8,
|
||||
"power": 0.38,
|
||||
"optmass": 125,
|
||||
"maxfuel": 1.5,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2.15
|
||||
},
|
||||
"3A": {
|
||||
"grp": "fsd",
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"cost": 507912,
|
||||
"mass": 5,
|
||||
"power": 0.45,
|
||||
"optmass": 150,
|
||||
"maxfuel": 1.8,
|
||||
"fuelmul": 0.012,
|
||||
"fuelpower": 2.15
|
||||
},
|
||||
"2E": {
|
||||
"grp": "fsd",
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"cost": 1978,
|
||||
"mass": 2.5,
|
||||
"power": 0.16,
|
||||
"optmass": 48,
|
||||
"maxfuel": 0.6,
|
||||
"fuelmul": 0.011,
|
||||
"fuelpower": 2
|
||||
},
|
||||
"2D": {
|
||||
"grp": "fsd",
|
||||
"class": 2,
|
||||
"rating": "D",
|
||||
"cost": 5934,
|
||||
"mass": 1,
|
||||
"power": 0.18,
|
||||
"optmass": 54,
|
||||
"maxfuel": 0.6,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2
|
||||
},
|
||||
"2C": {
|
||||
"grp": "fsd",
|
||||
"class": 2,
|
||||
"rating": "C",
|
||||
"cost": 17803,
|
||||
"mass": 2.5,
|
||||
"power": 0.2,
|
||||
"optmass": 60,
|
||||
"maxfuel": 0.6,
|
||||
"fuelmul": 0.008,
|
||||
"fuelpower": 2
|
||||
},
|
||||
"2B": {
|
||||
"grp": "fsd",
|
||||
"class": 2,
|
||||
"rating": "B",
|
||||
"cost": 53408,
|
||||
"mass": 4,
|
||||
"power": 0.25,
|
||||
"optmass": 75,
|
||||
"maxfuel": 0.8,
|
||||
"fuelmul": 0.01,
|
||||
"fuelpower": 2
|
||||
},
|
||||
"2A": {
|
||||
"grp": "fsd",
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"cost": 160224,
|
||||
"mass": 2.5,
|
||||
"power": 0.3,
|
||||
"optmass": 90,
|
||||
"maxfuel": 0.9,
|
||||
"fuelmul": 0.012,
|
||||
"fuelpower": 2
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"1C": {
|
||||
"grp": "ft",
|
||||
"class": 1,
|
||||
"rating": "C",
|
||||
"cost": 1000,
|
||||
"capacity": 2
|
||||
},
|
||||
"2C": {
|
||||
"grp": "ft",
|
||||
"class": 2,
|
||||
"rating": "C",
|
||||
"cost": 3750,
|
||||
"capacity": 4
|
||||
},
|
||||
"3C": {
|
||||
"grp": "ft",
|
||||
"class": 3,
|
||||
"rating": "C",
|
||||
"cost": 7063,
|
||||
"capacity": 8
|
||||
},
|
||||
"4C": {
|
||||
"grp": "ft",
|
||||
"class": 4,
|
||||
"rating": "C",
|
||||
"cost": 24734,
|
||||
"capacity": 16
|
||||
},
|
||||
"5C": {
|
||||
"grp": "ft",
|
||||
"class": 5,
|
||||
"rating": "C",
|
||||
"cost": 97754,
|
||||
"capacity": 32
|
||||
},
|
||||
"6C": {
|
||||
"grp": "ft",
|
||||
"class": 6,
|
||||
"rating": "C",
|
||||
"cost": 341577,
|
||||
"capacity": 64
|
||||
}
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
{
|
||||
"6E": {
|
||||
"grp": "ls",
|
||||
"class": 6,
|
||||
"rating": "E",
|
||||
"cost": 88978,
|
||||
"mass": 40,
|
||||
"power": 0.64,
|
||||
"time": 300
|
||||
},
|
||||
"6D": {
|
||||
"grp": "ls",
|
||||
"class": 6,
|
||||
"rating": "D",
|
||||
"cost": 222444,
|
||||
"mass": 16,
|
||||
"power": 0.72,
|
||||
"time": 450
|
||||
},
|
||||
"6C": {
|
||||
"grp": "ls",
|
||||
"class": 6,
|
||||
"rating": "C",
|
||||
"cost": 556110,
|
||||
"mass": 40,
|
||||
"power": 0.8,
|
||||
"time": 600
|
||||
},
|
||||
"6B": {
|
||||
"grp": "ls",
|
||||
"class": 6,
|
||||
"rating": "B",
|
||||
"cost": 1390275,
|
||||
"mass": 64,
|
||||
"power": 0.88,
|
||||
"time": 900
|
||||
},
|
||||
"6A": {
|
||||
"grp": "ls",
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"cost": 3475688,
|
||||
"mass": 40,
|
||||
"power": 0.96,
|
||||
"time": 1500
|
||||
},
|
||||
"5E": {
|
||||
"grp": "ls",
|
||||
"class": 5,
|
||||
"rating": "E",
|
||||
"cost": 31778,
|
||||
"mass": 20,
|
||||
"power": 0.57,
|
||||
"time": 300
|
||||
},
|
||||
"5D": {
|
||||
"grp": "ls",
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"cost": 79444,
|
||||
"mass": 8,
|
||||
"power": 0.64,
|
||||
"time": 450
|
||||
},
|
||||
"5C": {
|
||||
"grp": "ls",
|
||||
"class": 5,
|
||||
"rating": "C",
|
||||
"cost": 198611,
|
||||
"mass": 20,
|
||||
"power": 0.71,
|
||||
"time": 600
|
||||
},
|
||||
"5B": {
|
||||
"grp": "ls",
|
||||
"class": 5,
|
||||
"rating": "B",
|
||||
"cost": 496527,
|
||||
"mass": 32,
|
||||
"power": 0.78,
|
||||
"time": 900
|
||||
},
|
||||
"5A": {
|
||||
"grp": "ls",
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"cost": 1241317,
|
||||
"mass": 20,
|
||||
"power": 0.85,
|
||||
"time": 1500
|
||||
},
|
||||
"4E": {
|
||||
"grp": "ls",
|
||||
"class": 4,
|
||||
"rating": "E",
|
||||
"cost": 11349,
|
||||
"mass": 10,
|
||||
"power": 0.5,
|
||||
"time": 300
|
||||
},
|
||||
"4D": {
|
||||
"grp": "ls",
|
||||
"class": 4,
|
||||
"rating": "D",
|
||||
"cost": 28373,
|
||||
"mass": 4,
|
||||
"power": 0.56,
|
||||
"time": 450
|
||||
},
|
||||
"4C": {
|
||||
"grp": "ls",
|
||||
"class": 4,
|
||||
"rating": "C",
|
||||
"cost": 70932,
|
||||
"mass": 10,
|
||||
"power": 0.62,
|
||||
"time": 600
|
||||
},
|
||||
"4B": {
|
||||
"grp": "ls",
|
||||
"class": 4,
|
||||
"rating": "B",
|
||||
"cost": 177331,
|
||||
"mass": 16,
|
||||
"power": 0.68,
|
||||
"time": 900
|
||||
},
|
||||
"4A": {
|
||||
"grp": "ls",
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"cost": 443328,
|
||||
"mass": 10,
|
||||
"power": 0.74,
|
||||
"time": 1500
|
||||
},
|
||||
"3E": {
|
||||
"grp": "ls",
|
||||
"class": 3,
|
||||
"rating": "E",
|
||||
"cost": 4053,
|
||||
"mass": 5,
|
||||
"power": 0.42,
|
||||
"time": 300
|
||||
},
|
||||
"3D": {
|
||||
"grp": "ls",
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"cost": 10133,
|
||||
"mass": 2,
|
||||
"power": 0.48,
|
||||
"time": 450
|
||||
},
|
||||
"3C": {
|
||||
"grp": "ls",
|
||||
"class": 3,
|
||||
"rating": "C",
|
||||
"cost": 25333,
|
||||
"mass": 5,
|
||||
"power": 0.53,
|
||||
"time": 600
|
||||
},
|
||||
"3B": {
|
||||
"grp": "ls",
|
||||
"class": 3,
|
||||
"rating": "B",
|
||||
"cost": 63333,
|
||||
"mass": 8,
|
||||
"power": 0.58,
|
||||
"time": 900
|
||||
},
|
||||
"3A": {
|
||||
"grp": "ls",
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"cost": 158331,
|
||||
"mass": 5,
|
||||
"power": 0.64,
|
||||
"time": 1500
|
||||
},
|
||||
"2E": {
|
||||
"grp": "ls",
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"cost": 1448,
|
||||
"mass": 2.5,
|
||||
"power": 0.37,
|
||||
"time": 300
|
||||
},
|
||||
"2D": {
|
||||
"grp": "ls",
|
||||
"class": 2,
|
||||
"rating": "D",
|
||||
"cost": 3619,
|
||||
"mass": 1,
|
||||
"power": 0.41,
|
||||
"time": 450
|
||||
},
|
||||
"2C": {
|
||||
"grp": "ls",
|
||||
"class": 2,
|
||||
"rating": "C",
|
||||
"cost": 9048,
|
||||
"mass": 2.5,
|
||||
"power": 0.46,
|
||||
"time": 600
|
||||
},
|
||||
"2B": {
|
||||
"grp": "ls",
|
||||
"class": 2,
|
||||
"rating": "B",
|
||||
"cost": 22619,
|
||||
"mass": 4,
|
||||
"power": 0.51,
|
||||
"time": 900
|
||||
},
|
||||
"2A": {
|
||||
"grp": "ls",
|
||||
"class": 2,
|
||||
"rating": "A",
|
||||
"cost": 56547,
|
||||
"mass": 2.5,
|
||||
"power": 0.55,
|
||||
"time": 1500
|
||||
},
|
||||
"1E": {
|
||||
"grp": "ls",
|
||||
"class": 1,
|
||||
"rating": "E",
|
||||
"cost": 517,
|
||||
"mass": 1.3,
|
||||
"power": 0.32,
|
||||
"time": 300
|
||||
},
|
||||
"1D": {
|
||||
"grp": "ls",
|
||||
"class": 1,
|
||||
"rating": "D",
|
||||
"cost": 1293,
|
||||
"mass": 0.5,
|
||||
"power": 0.36,
|
||||
"time": 450
|
||||
},
|
||||
"1C": {
|
||||
"grp": "ls",
|
||||
"class": 1,
|
||||
"rating": "C",
|
||||
"cost": 3231,
|
||||
"mass": 1.3,
|
||||
"power": 0.4,
|
||||
"time": 600
|
||||
},
|
||||
"1B": {
|
||||
"grp": "ls",
|
||||
"class": 1,
|
||||
"rating": "B",
|
||||
"cost": 8078,
|
||||
"mass": 2,
|
||||
"power": 0.44,
|
||||
"time": 900
|
||||
},
|
||||
"1A": {
|
||||
"grp": "ls",
|
||||
"class": 1,
|
||||
"rating": "A",
|
||||
"cost": 20195,
|
||||
"mass": 1.3,
|
||||
"power": 0.48,
|
||||
"time": 1500
|
||||
}
|
||||
}
|
||||