Compare commits
1080 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0870b90443 | ||
|
|
70375f94c8 | ||
|
|
2d4336116a | ||
|
|
f52880765e | ||
|
|
dbfe68decb | ||
|
|
659f337de9 | ||
|
|
1d36d41da1 | ||
|
|
0f90efaa54 | ||
|
|
48ccab152b | ||
|
|
4442930a82 | ||
|
|
912a775088 | ||
|
|
24a229d818 | ||
|
|
66afb61494 | ||
|
|
e7511cc05b | ||
|
|
926f19a936 | ||
|
|
9e6f86b963 | ||
|
|
059de43a9a | ||
|
|
e246b737b2 | ||
|
|
f3bc900f16 | ||
|
|
38842417b0 | ||
|
|
82d485a98e | ||
|
|
fac71feea7 | ||
|
|
ec148847a9 | ||
|
|
445c63878b | ||
|
|
0474af912a | ||
|
|
7df5953824 | ||
|
|
e391b563fb | ||
|
|
53f62f96d0 | ||
|
|
18745979a0 | ||
|
|
c1966a38ff | ||
|
|
d86973f3b1 | ||
|
|
56b8d19649 | ||
|
|
7cb037e0bc | ||
|
|
56e1b3f9e9 | ||
|
|
c792323a8a | ||
|
|
4d2865de13 | ||
|
|
0d360bc367 | ||
|
|
91c9b46b91 | ||
|
|
7e67bd80dd | ||
|
|
2f775ea09b | ||
|
|
0603c55089 | ||
|
|
41f25a44e9 | ||
|
|
35440b7273 | ||
|
|
7d68b91018 | ||
|
|
deaa61b848 | ||
|
|
2d00cbc41b | ||
|
|
57c1e83c67 | ||
|
|
b7079dbd4e | ||
|
|
be642a5373 | ||
|
|
ffc691c1a2 | ||
|
|
6122d99369 | ||
|
|
b73a8bcdab | ||
|
|
dd624537b7 | ||
|
|
50a67f73fd | ||
|
|
2262a980d4 | ||
|
|
84964ceb5f | ||
|
|
c4bdb7a66e | ||
|
|
21309e129f | ||
|
|
928e02c718 | ||
|
|
7f494dd200 | ||
|
|
f38e743e59 | ||
|
|
58b55eb3da | ||
|
|
8375ad95b3 | ||
|
|
506d027a2d | ||
|
|
fbeb6237cf | ||
|
|
bd95e2c5a5 | ||
|
|
f3276e557a | ||
|
|
8b813e0e7f | ||
|
|
d660d2959f | ||
|
|
014ebda7d2 | ||
|
|
607398d364 | ||
|
|
97d141ce2b | ||
|
|
9f492db9c6 | ||
|
|
6ed82b366c | ||
|
|
a7ca037f48 | ||
|
|
6e21d0e74a | ||
|
|
e6c75bf2af | ||
|
|
270c2f386e | ||
|
|
83f7880c58 | ||
|
|
51d29aee38 | ||
|
|
c7754c0365 | ||
|
|
94037cea38 | ||
|
|
5c1a9d9eea | ||
|
|
3835c73ffd | ||
|
|
b8c1effecb | ||
|
|
dd07241dd9 | ||
|
|
5ad828a613 | ||
|
|
9856df5527 | ||
|
|
7b249900ec | ||
|
|
e3b9267c3f | ||
|
|
a996b8135a | ||
|
|
5e1237390b | ||
|
|
83571b4bef | ||
|
|
c2a0dad9a8 | ||
|
|
f6f057689c | ||
|
|
4378f0020e | ||
|
|
2e9e7c4fc6 | ||
|
|
b7b8ee5580 | ||
|
|
c630dbbed0 | ||
|
|
fa6703a3b8 | ||
|
|
bdcb64c9d1 | ||
|
|
a1afc869a7 | ||
|
|
d8ce26c7cf | ||
|
|
95c474dc05 | ||
|
|
56ca73b4ad | ||
|
|
d82cd6a89e | ||
|
|
bf20d32364 | ||
|
|
e968e62fca | ||
|
|
b9c9ca9fa1 | ||
|
|
6e965e2e98 | ||
|
|
7d569f9036 | ||
|
|
df5a77199d | ||
|
|
3c8dfebfdc | ||
|
|
3cc422596f | ||
|
|
4ed167de22 | ||
|
|
b420647501 | ||
|
|
0c318b5e68 | ||
|
|
1c627297b8 | ||
|
|
f41e2d0552 | ||
|
|
1a1d539c60 | ||
|
|
ba2e46f88f | ||
|
|
c2f1fa81af | ||
|
|
752e03fa0f | ||
|
|
1da69664d7 | ||
|
|
9aa986a133 | ||
|
|
bdbfb28c4a | ||
|
|
162156bb2b | ||
|
|
64c5d542e9 | ||
|
|
31dc789f6e | ||
|
|
b0e2cfd7db | ||
|
|
54ddb0d014 | ||
|
|
e19688e96f | ||
|
|
4f53d75999 | ||
|
|
7277460060 | ||
|
|
93c4f6f3c0 | ||
|
|
c6919a7518 | ||
|
|
ca428e67dc | ||
|
|
c6726cf020 | ||
|
|
56ae1378da | ||
|
|
e982ab1a3b | ||
|
|
0d6aa87e89 | ||
|
|
94d06e4025 | ||
|
|
cee5b297ac | ||
|
|
c549213ce0 | ||
|
|
f3f9112767 | ||
|
|
fb325ea3e2 | ||
|
|
3773f6f7ec | ||
|
|
b90ab6fe48 | ||
|
|
cc2e56dc8a | ||
|
|
ae65af7bbf | ||
|
|
c8fb513cd1 | ||
|
|
7fc3855af4 | ||
|
|
bcebb26d4a | ||
|
|
1f23e4cfcc | ||
|
|
65998778fe | ||
|
|
e53c04a07f | ||
|
|
e5a8e106c1 | ||
|
|
11d1d80a53 | ||
|
|
c8a3d86a45 | ||
|
|
4484ca226a | ||
|
|
496c9ba35c | ||
|
|
dae2fc9192 | ||
|
|
07b00e6230 | ||
|
|
36526f0824 | ||
|
|
f4691939ba | ||
|
|
534f735b63 | ||
|
|
bc2c8406a2 | ||
|
|
032c44f39a | ||
|
|
2b43c8e91a | ||
|
|
e91b3df31a | ||
|
|
3e0597023a | ||
|
|
1dd2edf742 | ||
|
|
97f3bece33 | ||
|
|
be02444487 | ||
|
|
fc012fe68a | ||
|
|
7ac16d6d22 | ||
|
|
4ee92b1f3e | ||
|
|
d82128690b | ||
|
|
9e57eb4262 | ||
|
|
6e0d45f419 | ||
|
|
645e86714e | ||
|
|
00afd1cd6a | ||
|
|
77ae126a51 | ||
|
|
9c82c7caed | ||
|
|
d9a92e7a78 | ||
|
|
d8a87029a6 | ||
|
|
f407d0f92a | ||
|
|
4ac42e62e6 | ||
|
|
748c63fa0b | ||
|
|
78ca756cef | ||
|
|
a8554b51c2 | ||
|
|
e54e4da289 | ||
|
|
f97cb5f5a7 | ||
|
|
318e8077d0 | ||
|
|
c8355a532d | ||
|
|
3686ccd4ed | ||
|
|
f02db0120a | ||
|
|
d9ad93d3cd | ||
|
|
77018cc1ad | ||
|
|
30a8a29ce3 | ||
|
|
7b1aa646ac | ||
|
|
49e4409862 | ||
|
|
ab87ddc649 | ||
|
|
57784329ac | ||
|
|
1db613c56d | ||
|
|
464cd4165f | ||
|
|
420ebe4cc7 | ||
|
|
15ead440d6 | ||
|
|
ef0614a62f | ||
|
|
2fd2af3e31 | ||
|
|
f30a904a02 | ||
|
|
e00680113f | ||
|
|
93e6a29057 | ||
|
|
1fbba6a5f3 | ||
|
|
d1c0b635b3 | ||
|
|
060cf75ec4 | ||
|
|
62e3b70581 | ||
|
|
4accb901af | ||
|
|
82725e1c5a | ||
|
|
4dc8ab928c | ||
|
|
7db76ecba0 | ||
|
|
16a5b2a72a | ||
|
|
59a5ba0227 | ||
|
|
c130b52b7c | ||
|
|
03f32097e9 | ||
|
|
8660dcbd2b | ||
|
|
95f358f9d8 | ||
|
|
8f944bc4c8 | ||
|
|
e9cbe0d952 | ||
|
|
684ecfcafd | ||
|
|
1516bd4fc0 | ||
|
|
4ea0bbfb93 | ||
|
|
9b6df8ea4f | ||
|
|
9c6f5fb44e | ||
|
|
c0a732a76b | ||
|
|
9551b8b5de | ||
|
|
22f83b79af | ||
|
|
0a26f76fb4 | ||
|
|
077f432daf | ||
|
|
e846b4508b | ||
|
|
3be78885b8 | ||
|
|
e29a4b263d | ||
|
|
061ab77de1 | ||
|
|
c6a8e48fda | ||
|
|
f48af272c3 | ||
|
|
2b1402d099 | ||
|
|
1ad0afa0d7 | ||
|
|
93d6c1b871 | ||
|
|
243f1123ba | ||
|
|
2fa2625a8f | ||
|
|
42c43d3f2d | ||
|
|
1237833c7a | ||
|
|
171a84dd33 | ||
|
|
79dac7b38f | ||
|
|
0e86ae79c1 | ||
|
|
7d7ea18447 | ||
|
|
2a6da36aeb | ||
|
|
db1a976e20 | ||
|
|
3b058bda7f | ||
|
|
da274f1b75 | ||
|
|
d624663278 | ||
|
|
d8ac185b4d | ||
|
|
b66baef998 | ||
|
|
8a115f8323 | ||
|
|
442da6f05b | ||
|
|
f536c037b1 | ||
|
|
33a678a200 | ||
|
|
b0dc4d7864 | ||
|
|
8b0e822ea9 | ||
|
|
006811f5a9 | ||
|
|
873935c1d4 | ||
|
|
94d876e934 | ||
|
|
b055963fe0 | ||
|
|
8ad9472d56 | ||
|
|
d15e49f315 | ||
|
|
c7ea1eb95a | ||
|
|
82ce86a374 | ||
|
|
a1a17bc836 | ||
|
|
75a4e54453 | ||
|
|
32fb66139a | ||
|
|
3f18987007 | ||
|
|
eb042b2778 | ||
|
|
85f108556a | ||
|
|
73a75c69a3 | ||
|
|
2f5d123f02 | ||
|
|
e278babee8 | ||
|
|
86df6f20f6 | ||
|
|
117028875f | ||
|
|
cadd699bdf | ||
|
|
6afd80002c | ||
|
|
2736e1df79 | ||
|
|
0ff95ed1f1 | ||
|
|
fcb8980a38 | ||
|
|
49a076fd9e | ||
|
|
eb83969015 | ||
|
|
369d882354 | ||
|
|
23c4da55de | ||
|
|
7259a666eb | ||
|
|
91cab5a4f1 | ||
|
|
d60a8f2625 | ||
|
|
69489aa267 | ||
|
|
750d23b10a | ||
|
|
cd753af48e | ||
|
|
365810a610 | ||
|
|
73d609610a | ||
|
|
a3c03266bf | ||
|
|
7b3ad555a1 | ||
|
|
1605e80884 | ||
|
|
0729fc29fa | ||
|
|
964cdd2b9a | ||
|
|
49c3e395db | ||
|
|
bdd2299335 | ||
|
|
f782adb21d | ||
|
|
950c0c61f9 | ||
|
|
f6ebaf7445 | ||
|
|
3b35d5030e | ||
|
|
067b69f449 | ||
|
|
6f67267fec | ||
|
|
ec0cd37896 | ||
|
|
84719c997f | ||
|
|
2731ec3b90 | ||
|
|
340121c6bd | ||
|
|
ec4e70326a | ||
|
|
3a271e4b7b | ||
|
|
02db800c7b | ||
|
|
3a55c8cc0a | ||
|
|
e00b07c2f6 | ||
|
|
fbfd0deb6c | ||
|
|
dc11cc182f | ||
|
|
597344353a | ||
|
|
9aef1ff8a6 | ||
|
|
70f218f833 | ||
|
|
5937843be8 | ||
|
|
d4b384eded | ||
|
|
2b5a42d4e2 | ||
|
|
afd8ad7678 | ||
|
|
cdc5c29458 | ||
|
|
5a351d4c0d | ||
|
|
fac279d9dd | ||
|
|
f4e5254832 | ||
|
|
2fb3ee8cd8 | ||
|
|
cc2f3fd1fe | ||
|
|
87146b2cf3 | ||
|
|
bec3ae3f89 | ||
|
|
af2e0cbed3 | ||
|
|
4bf30c0cd5 | ||
|
|
a9fdf73d86 | ||
|
|
fe691d12c7 | ||
|
|
a5df542aa2 | ||
|
|
069959dabb | ||
|
|
a0e8f19683 | ||
|
|
342ca7af05 | ||
|
|
d00c0c3904 | ||
|
|
8e0f1ca977 | ||
|
|
33360fd6cf | ||
|
|
78ad34b082 | ||
|
|
ba98fe49a9 | ||
|
|
11f5c04efa | ||
|
|
ee9f65052a | ||
|
|
a25dde8d2d | ||
|
|
8d813688f7 | ||
|
|
99fc55ba6c | ||
|
|
402a4c1939 | ||
|
|
d1e16470b8 | ||
|
|
76027b8537 | ||
|
|
fd5ff3b6a8 | ||
|
|
d2d8f084d2 | ||
|
|
ea3d57399c | ||
|
|
77d3053ff8 | ||
|
|
aea3e43e1c | ||
|
|
a949bd6738 | ||
|
|
4981ffb908 | ||
|
|
4859138053 | ||
|
|
1f3c66d9ba | ||
|
|
f2af463d00 | ||
|
|
3858712613 | ||
|
|
d7941e0a8a | ||
|
|
178d38f28d | ||
|
|
e42a0d1210 | ||
|
|
ddb89c47e7 | ||
|
|
8b9aae342b | ||
|
|
ab1d73a6ea | ||
|
|
d73a3cc2b4 | ||
|
|
230351b959 | ||
|
|
4ee5c03cd1 | ||
|
|
d8e9733170 | ||
|
|
aba2abe507 | ||
|
|
45e6b71ec9 | ||
|
|
15a14dc280 | ||
|
|
cbac650b9e | ||
|
|
f011f1f4d5 | ||
|
|
d467ad5f7c | ||
|
|
b56ac177d9 | ||
|
|
5b13d64a1d | ||
|
|
2620935745 | ||
|
|
45852db507 | ||
|
|
7fbcbb75ed | ||
|
|
abf65ee436 | ||
|
|
24849cee08 | ||
|
|
9e5efe50dc | ||
|
|
39e9a38068 | ||
|
|
73d5915b3a | ||
|
|
b06d2d1f72 | ||
|
|
6e71f5e6db | ||
|
|
588cfc3990 | ||
|
|
191e31ff18 | ||
|
|
c655b65779 | ||
|
|
3e168a3e5f | ||
|
|
ee52a4b716 | ||
|
|
a14974fef4 | ||
|
|
2c0959d68b | ||
|
|
0221d05b04 | ||
|
|
975432b45a | ||
|
|
e78551f5d9 | ||
|
|
b1daf6f799 | ||
|
|
bc31be5884 | ||
|
|
df03102c35 | ||
|
|
55e4c51d77 | ||
|
|
e7d1a0df63 | ||
|
|
ca0c9675b3 | ||
|
|
491899fe49 | ||
|
|
cc22a89ad6 | ||
|
|
d389114189 | ||
|
|
9d0f7a166b | ||
|
|
c344d56d48 | ||
|
|
eb5d0e868c | ||
|
|
c28f22a78b | ||
|
|
e2b22dd4ca | ||
|
|
f5ecccec48 | ||
|
|
7c8eee4707 | ||
|
|
99e251fd4b | ||
|
|
c1ddecfd3e | ||
|
|
0ae59c5e48 | ||
|
|
eb76040b08 | ||
|
|
7698cb75e9 | ||
|
|
bd7139c703 | ||
|
|
c9b9404ba1 | ||
|
|
84ff013a9e | ||
|
|
d2bcf6cd71 | ||
|
|
e52c6730f4 | ||
|
|
e448b3cb0a | ||
|
|
705f3158aa | ||
|
|
f4789717fe | ||
|
|
93e69f215b | ||
|
|
d04e662de4 | ||
|
|
a9f9285278 | ||
|
|
c5e27d43aa | ||
|
|
db376829f5 | ||
|
|
79a31fd992 | ||
|
|
094f3aa3e2 | ||
|
|
41d51743d3 | ||
|
|
cf741d18ed | ||
|
|
c02f674530 | ||
|
|
89f2273b5d | ||
|
|
351b084ce9 | ||
|
|
dd48d2d007 | ||
|
|
63e850b5aa | ||
|
|
46775879f7 | ||
|
|
c9ba4e3fcb | ||
|
|
8b855b62a1 | ||
|
|
d6a687300c | ||
|
|
ddc968129d | ||
|
|
e364560ca7 | ||
|
|
baf6f8130a | ||
|
|
f8f5cd2581 | ||
|
|
8019453d0d | ||
|
|
6ad17595dc | ||
|
|
50e1f7d4df | ||
|
|
fdb931fe00 | ||
|
|
86efb59237 | ||
|
|
f05aa66e53 | ||
|
|
f4e95cd150 | ||
|
|
5798c0e8a6 | ||
|
|
22f98fa8a7 | ||
|
|
897668c0d4 | ||
|
|
99c0bfcee1 | ||
|
|
37bfc700e9 | ||
|
|
8fcebf59f6 | ||
|
|
486c055631 | ||
|
|
92246302b9 | ||
|
|
0d646c6193 | ||
|
|
217ea3c5ac | ||
|
|
fcf0494df6 | ||
|
|
20ba6eb822 | ||
|
|
0e2c0349e0 | ||
|
|
c49e2cff03 | ||
|
|
d79313bfbe | ||
|
|
fd404b5155 | ||
|
|
49e72146b4 | ||
|
|
9b534b62c8 | ||
|
|
0be59af9b0 | ||
|
|
5d87a6cd56 | ||
|
|
c61c17d465 | ||
|
|
029ba63aa5 | ||
|
|
99e9e0c76f | ||
|
|
5bbc6e1cbe | ||
|
|
1e5f66e528 | ||
|
|
cdb837a25a | ||
|
|
dd1175abf4 | ||
|
|
619976230d | ||
|
|
2cb0d5209b | ||
|
|
ad06e23afa | ||
|
|
3def84e435 | ||
|
|
7f377d6345 | ||
|
|
53137e0ae1 | ||
|
|
792eda2572 | ||
|
|
550c94fa94 | ||
|
|
2a841281d4 | ||
|
|
260f29834a | ||
|
|
ddb35d321c | ||
|
|
6017c1ecff | ||
|
|
05e06f30f5 | ||
|
|
fb5ba6a0b2 | ||
|
|
80656a7a78 | ||
|
|
ce980cf091 | ||
|
|
a4656e223a | ||
|
|
66d4b5ac4c | ||
|
|
6961469ae5 | ||
|
|
06f4abdf8b | ||
|
|
7855d0e171 | ||
|
|
40f213c883 | ||
|
|
be1bfeb6f3 | ||
|
|
b40a2e96e0 | ||
|
|
5f036c586c | ||
|
|
091789c819 | ||
|
|
0ce8bfac79 | ||
|
|
e53ffd0273 | ||
|
|
bb7db144d6 | ||
|
|
2e42a328e0 | ||
|
|
f82122f29f | ||
|
|
5bf907809d | ||
|
|
51d7b6c9aa | ||
|
|
b8cff0c2fc | ||
|
|
6ac69a6388 | ||
|
|
32282141cf | ||
|
|
059c2badf4 | ||
|
|
fb090618da | ||
|
|
9ed0e30538 | ||
|
|
af82b8ca1e | ||
|
|
6e18793d82 | ||
|
|
22e74164c5 | ||
|
|
93ba1bf67a | ||
|
|
46ed9003dd | ||
|
|
5603315bf0 | ||
|
|
5bbc6be3d8 | ||
|
|
203e9c7b46 | ||
|
|
2a6850ded0 | ||
|
|
041f873f97 | ||
|
|
b944035541 | ||
|
|
7c6a4fc5f8 | ||
|
|
5426b55637 | ||
|
|
a6a10df39c | ||
|
|
0dc58bad7e | ||
|
|
794faacbd4 | ||
|
|
0a37b36ec2 | ||
|
|
85e6796e88 | ||
|
|
fa1ef47b71 | ||
|
|
f31e3c09f4 | ||
|
|
e6ab536601 | ||
|
|
5bced9fe56 | ||
|
|
67742060d3 | ||
|
|
ca2136544c | ||
|
|
ee19e9af50 | ||
|
|
f457fd0bff | ||
|
|
c1ce07e039 | ||
|
|
c8d1536f77 | ||
|
|
231ad4af59 | ||
|
|
d5f61d7ae8 | ||
|
|
8a5d4a36bf | ||
|
|
2c9237626d | ||
|
|
37f889e317 | ||
|
|
f86ba48295 | ||
|
|
aac35633a3 | ||
|
|
e73e0a305d | ||
|
|
4b2b0efe37 | ||
|
|
8fe20f6f65 | ||
|
|
11af7f567a | ||
|
|
3b8444482f | ||
|
|
c09e1b1b3e | ||
|
|
5770cf8d39 | ||
|
|
6da09f2e5d | ||
|
|
294fadf7cd | ||
|
|
2a97678574 | ||
|
|
76b3bd34f5 | ||
|
|
02bfecb92d | ||
|
|
719759ad56 | ||
|
|
fd446b29ba | ||
|
|
e5552d3e10 | ||
|
|
50946eeeb8 | ||
|
|
faab41117c | ||
|
|
0ab59c1f9a | ||
|
|
1067dceaa3 | ||
|
|
9042de422a | ||
|
|
f0547feb93 | ||
|
|
f863daa347 | ||
|
|
fdb202e7d6 | ||
|
|
c6bde19052 | ||
|
|
f6aff3d3bb | ||
|
|
2f4a2ebe03 | ||
|
|
ca20e94b93 | ||
|
|
40a87dceeb | ||
|
|
95b7d60be4 | ||
|
|
24abd6583f | ||
|
|
8857aba53f | ||
|
|
e4830811b0 | ||
|
|
143380ac58 | ||
|
|
a2f6fb6ac0 | ||
|
|
0d3c128059 | ||
|
|
930a555425 | ||
|
|
d6f213fbe7 | ||
|
|
0571e8e099 | ||
|
|
54c61ecb7d | ||
|
|
030867c4f8 | ||
|
|
33a7c71fec | ||
|
|
4e0f682ad6 | ||
|
|
4486aa2e2b | ||
|
|
0c94c81746 | ||
|
|
5b037e3a00 | ||
|
|
42a2b907ce | ||
|
|
a65dae1631 | ||
|
|
7d4c534956 | ||
|
|
8397d3505b | ||
|
|
9556f28ba4 | ||
|
|
f489257f86 | ||
|
|
c96693c439 | ||
|
|
3d4f6d7861 | ||
|
|
606eabfec7 | ||
|
|
782603727a | ||
|
|
ad570534a0 | ||
|
|
87e903e473 | ||
|
|
cf6d32ea04 | ||
|
|
5b81a0b25f | ||
|
|
0688faac93 | ||
|
|
3719bb9696 | ||
|
|
21582d1598 | ||
|
|
9a9607fcfb | ||
|
|
8602c5667b | ||
|
|
f13a987388 | ||
|
|
38eaebefc0 | ||
|
|
c1bc514e6b | ||
|
|
42e98fd015 | ||
|
|
5f0b851de7 | ||
|
|
616ed0bf10 | ||
|
|
108ab3b1ee | ||
|
|
04caef9613 | ||
|
|
cae7edbe01 | ||
|
|
2fa96fc1a5 | ||
|
|
6b8a4d1f85 | ||
|
|
07df44a907 | ||
|
|
be45637435 | ||
|
|
87ab684ba3 | ||
|
|
916a6d5e48 | ||
|
|
b99fbf07f5 | ||
|
|
6d6ef2a93e | ||
|
|
d08e5e2858 | ||
|
|
c1f4a8d416 | ||
|
|
c17c7125e3 | ||
|
|
97fc4ce45d | ||
|
|
abfc338240 | ||
|
|
3d129946ce | ||
|
|
2aab31d317 | ||
|
|
f8ff9a6a87 | ||
|
|
6727c2fc13 | ||
|
|
ba1f11a88b | ||
|
|
c88e4369c8 | ||
|
|
c490f97c22 | ||
|
|
7c71555384 | ||
|
|
35538f971a | ||
|
|
b3c82ac2de | ||
|
|
ff0d8dccea | ||
|
|
06841b1485 | ||
|
|
f55448c0a8 | ||
|
|
258701c377 | ||
|
|
1a0f05511b | ||
|
|
3ec9679893 | ||
|
|
e5cc3e269e | ||
|
|
4b14f617ec | ||
|
|
0df051e40f | ||
|
|
2b464f34e5 | ||
|
|
7a33bd64f8 | ||
|
|
3656c7a18f | ||
|
|
3114852c63 | ||
|
|
45337913ba | ||
|
|
adc5d1c039 | ||
|
|
183f22c223 | ||
|
|
43eb4935e6 | ||
|
|
2c45011664 | ||
|
|
f29f3f4f8f | ||
|
|
c347336055 | ||
|
|
cd87184169 | ||
|
|
09895852c3 | ||
|
|
32759d3e0e | ||
|
|
965134fc02 | ||
|
|
7da5360349 | ||
|
|
bf0701340c | ||
|
|
a3a490f442 | ||
|
|
33b22b8280 | ||
|
|
e6278858b9 | ||
|
|
ed7a9ef037 | ||
|
|
9c42179617 | ||
|
|
5634fbd568 | ||
|
|
7d99d59790 | ||
|
|
5f75c9d32b | ||
|
|
fe1d16415e | ||
|
|
ed8cbb403e | ||
|
|
58182bddce | ||
|
|
771ba7e692 | ||
|
|
ed0d4ddc48 | ||
|
|
266c63bc0c | ||
|
|
ebcc92f7d4 | ||
|
|
a1f280cf62 | ||
|
|
0306167e6e | ||
|
|
162136194a | ||
|
|
3600a4862f | ||
|
|
65fdad64b2 | ||
|
|
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 | ||
|
|
f0bdcd5557 | ||
|
|
b1ee0e44f3 | ||
|
|
c96e6afbd7 | ||
|
|
77334341ea | ||
|
|
5f22743778 | ||
|
|
03986cb88a | ||
|
|
c796adf40d | ||
|
|
2890ff5537 | ||
|
|
a6ba61a2bf | ||
|
|
db5e080992 | ||
|
|
63d7f98e2c | ||
|
|
7997ff6ae9 | ||
|
|
b3126cf6b6 | ||
|
|
ab1ea53ce3 | ||
|
|
82a87cb653 | ||
|
|
d2fc526039 | ||
|
|
88587c6487 | ||
|
|
4578dbf906 | ||
|
|
cd48ef6f86 | ||
|
|
0f0e67ec9c | ||
|
|
bbb2a223af | ||
|
|
5278e52e2f | ||
|
|
e6290abef7 | ||
|
|
346fee1208 | ||
|
|
1b9f5f870e | ||
|
|
26b624d1dd | ||
|
|
7cbd9732b7 | ||
|
|
44152116b4 | ||
|
|
3ad35992fc | ||
|
|
e963eb24a0 | ||
|
|
827e2b403c | ||
|
|
0fd4712021 | ||
|
|
ae0af05e78 | ||
|
|
dd00f283e6 | ||
|
|
eddf968629 | ||
|
|
7fdd83ba84 | ||
|
|
1bb4f6850e | ||
|
|
f47b931380 | ||
|
|
d9f686f0d6 | ||
|
|
73cef20073 | ||
|
|
fd68565d8e | ||
|
|
a45d165d33 | ||
|
|
904f828d83 | ||
|
|
f00420c92f | ||
|
|
457705014c | ||
|
|
6faf3765e0 | ||
|
|
4abdce2b70 | ||
|
|
3b44f5fe27 | ||
|
|
7332dc69ed | ||
|
|
381387c04f | ||
|
|
e0db9fdfb0 | ||
|
|
a8d66b22af | ||
|
|
bdc1e622f9 | ||
|
|
ad8130ae9b | ||
|
|
394a3bb9f1 | ||
|
|
54907b462c | ||
|
|
1350de1910 | ||
|
|
89d3fd69e1 | ||
|
|
7325081ec9 | ||
|
|
680872a302 | ||
|
|
a3c65d6c69 | ||
|
|
a189265326 | ||
|
|
b447e913ff | ||
|
|
b5a249fb4b | ||
|
|
ae081c147e | ||
|
|
3ce0d0bdd8 | ||
|
|
a71abd9fe3 | ||
|
|
f1d804e3a1 | ||
|
|
aa7479d111 | ||
|
|
7c23fb3884 | ||
|
|
b707015d9c | ||
|
|
10d5611dcd | ||
|
|
9009a2a434 | ||
|
|
8b98a98faf | ||
|
|
44de3e4bbc | ||
|
|
ba2e9a12b0 | ||
|
|
57304f55c1 | ||
|
|
1eea358c35 | ||
|
|
f671b7c34f | ||
|
|
211028d80d | ||
|
|
c79359ea2f | ||
|
|
93f92da1df | ||
|
|
25020293ec | ||
|
|
4e7f1d3e8b | ||
|
|
e6ba0a14e8 | ||
|
|
b285a433b2 | ||
|
|
f19c786f64 | ||
|
|
6fb2247dd7 |
21
.editorconfig
Normal file
@@ -0,0 +1,21 @@
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
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
|
||||
}
|
||||
}
|
||||
9
.gitignore
vendored
@@ -1,10 +1,9 @@
|
||||
node_modules
|
||||
bower_components
|
||||
bower_components/*
|
||||
build
|
||||
.DS_Store
|
||||
*.log
|
||||
app/js/db.js
|
||||
app/db.json
|
||||
nginx.pid
|
||||
template_cache.js
|
||||
.idea
|
||||
/bin
|
||||
env
|
||||
*.swp
|
||||
|
||||
12
.travis.yml
@@ -3,17 +3,13 @@ notifications:
|
||||
email: false
|
||||
sudo: false
|
||||
node_js:
|
||||
- "0.12"
|
||||
- "4.8.1"
|
||||
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
|
||||
|
||||
349
ChangeLog.md
Normal file
@@ -0,0 +1,349 @@
|
||||
#2.5.1
|
||||
* Passenger count on main page
|
||||
* AX Modules
|
||||
* Engineering fixes
|
||||
* Use coriolis-data 2.5.1
|
||||
|
||||
#2.5.0
|
||||
* willyb321 and myself have conquered engineering. Mainly him though...
|
||||
* Use coriolis-data 2.5.0
|
||||
|
||||
#2.4.2
|
||||
Lots of kind people have helped out for this release! Check out the PR history!
|
||||
* Uses coriolis-data update:
|
||||
* Fixes issues with repair limpets
|
||||
* Adds requirement data
|
||||
* Adds requirements panel
|
||||
* Adds comma formatting to tooltip numbers
|
||||
|
||||
#2.4.1
|
||||
* Small patches and changes
|
||||
|
||||
#2.4.0
|
||||
* Changed compression library to Pako
|
||||
* Use coriolis-data 2.4.0
|
||||
* Repair Limpets added
|
||||
|
||||
#2.3.7
|
||||
* Fixed Travis test issues
|
||||
* Bumped NodeJS version to provide better compatability and support
|
||||
* Added updated German Translation
|
||||
* Fixed issues with Safari
|
||||
* Use coriolis-data 2.3.7
|
||||
* Fixed Orca mass-lock
|
||||
|
||||
#2.3.6
|
||||
* Update miner role to provide better defaults
|
||||
* Fix issue where torpedo special effects were not showing
|
||||
* Fix typo causing long range blueprint to not modify shot speed in some circumstances
|
||||
* Fix for Spanish translation of Chaff Launcher (thanks to DamonFstr)
|
||||
* Update for Russian translation (thanks to LeeNTien)
|
||||
* Use coriolis-data 2.3.6:
|
||||
* Add shotspeed modifier to cannon/multi-cannon/fragment cannon
|
||||
|
||||
#2.3.5
|
||||
* Ensure that hidden blueprint effects are applied when a blueprint is selected
|
||||
* Handle display when summary values show thrusters disabled but current mass keeps them enabled
|
||||
* Added updated German translations (thanks to @sweisgerber-dev)
|
||||
* Power state (enabled and priority) now follows modules when they are swapped or copied
|
||||
* Grey out modules that are powered off to provide a clearer visual indication
|
||||
* Use coriolis-data 2.3.5:
|
||||
* Fix list of available blueprints for Point Defence
|
||||
* Fix integrity values for class 6 power plants
|
||||
* Add shot speed for long range weapon
|
||||
* Fix components for dirty drive grade 3
|
||||
* Update values for Cytoscrambler
|
||||
|
||||
#2.3.4
|
||||
* Fix crash when removing the special effect from a module
|
||||
* Ensure comparisons with saved stock ships work correctly
|
||||
* Add 'Racer' role
|
||||
* Tidy up shipyard page; remove units from data columns and re-order for legibility
|
||||
* Allow basic drag/drop functionality in Edge/Internet Explorer 11 browser
|
||||
* Provide separate special effects for dumbfire and seeker missiles
|
||||
* Include special effect modifiers in blueprint tooltip
|
||||
* Use coriolis-data 2.3.4:
|
||||
* Add missing Long Range blueprint to multi-cannon
|
||||
* Fix values for thermal load of focused weapon grade 4
|
||||
* Fix internal module information for power plant blueprints
|
||||
* Add 'FSD Interrupt' special to dumbfire missile racks; this module now has `specials_S` and `specials_D` keys for specials to differentiate
|
||||
|
||||
#2.3.3
|
||||
* Remove unused blueprint when hitting reset
|
||||
* Add 'purchase module' external link to EDDB for refit items
|
||||
* Use coriolis-data 2.3.3:
|
||||
* Add Felicity Farseer to list of engineers that supply sensor and detailed surface scanner modifications
|
||||
|
||||
#2.3.2
|
||||
* Use scan range for DSS rather than scan time
|
||||
* Fix companion API import of Dolphin
|
||||
* Use coriolis-data 2.3.2:
|
||||
* Separate scan time and scan range
|
||||
* Add Frontier IDs for new items in 2.3
|
||||
* Update ownership of module blueprints for sensors and scanners
|
||||
* Update railgun penetration
|
||||
|
||||
#2.3.0
|
||||
* Make scan time visible on scanners where available
|
||||
* Update power distributor able-to-boost calculation to take fractional MJ values in to account
|
||||
* Revert to floating header due to issues on iOS
|
||||
* Fix issue where new module added to a slot did not reset its enabled status
|
||||
* Show integrity value for relevant modules
|
||||
* Reset old modification values when a new roll is applied
|
||||
* Fix issue with miner role where refinery would not be present in ships with class 5 slots but no class 4
|
||||
* Ensure that boost value is set correctly when modifications to power distributor enable/disable boost
|
||||
* Ensure that hull reinforcement modifications take the inherent resistance in to account when calculating modification percentages
|
||||
* Add tooltip for blueprints providing details of the features they alter, the components required for the blueprint and the engineer(s) who cam craft them
|
||||
* Use opponent's saved pips if available
|
||||
* Ignore rounds per shot for EPS and HPS calculations; it's already factored in to the numbers
|
||||
* Ensure that clip size modification imports result in whole numbers
|
||||
* Rework of separate offence/defence/movement sections to a unified interface
|
||||
* Use cargo hatch information on import if available
|
||||
* Additional information of power distributor pips, boost, cargo and fuel loads added to build
|
||||
* Additional information of opponent and engagement range added to build
|
||||
* Reworking of offence, defence and movement information in to separate tabs as part of the outfitting screen:
|
||||
* Power and costs section provides the existing 'Power' and 'Costs' sections
|
||||
* Profiles section provides a number of graphs that show how various components of the build (top speed, sustained DPS against opponent's shields and armour etc) are affected by mass, range, etc.
|
||||
* Offence section provides details of your build's damage distribution and per-weapon effectiveness. It also gives summary information for how long it will take for your build to wear down your opponent's shields and armour
|
||||
* Defence section provides details of your build's defences against your selected opponent. It provides details of the effectiveness of your resistances of both shields and armour, and effective strength of each as a result. It also provides key metrics around shield longevity and recovery times, as well as module protection
|
||||
* Fix power band marker to show safe power limit at 40% rather than 50%
|
||||
* Restyle blueprint list to improve consistency with similar menus
|
||||
* Use coriolis-data 2.3.0:
|
||||
* Add Dolphin
|
||||
* Add turreted mining lasers
|
||||
* Add long range / wide angle / fast scan scanner blueprints
|
||||
* Fix EDDB IDs for class 5 and 7 fighter hangars for correct shopping list
|
||||
* Fix cost for rocket-propelled FSD disruptor
|
||||
* Add module names for blueprints
|
||||
* Fix erroneous value for grade 5 kinetic shield booster
|
||||
* Add missing integrity values for some modules
|
||||
* Update module reinforcement package integrity
|
||||
* Update specs of Beluga as per 2.3
|
||||
* Update specs of Asp Scout as per 2.3
|
||||
* Update specs of Diamondback Explorer as per 2.3
|
||||
* Add ED ID for Rocket Propelled FSD Disruptor
|
||||
* Fix ED name for target lock breaker special
|
||||
* Update scan range and angle information for sensors
|
||||
* Tidy up shield cell bank information to allow for accurate calculations with modifications
|
||||
* Update mine launcher stats
|
||||
* Add appropriate engineers to per-module blueprint information
|
||||
|
||||
#2.2.19
|
||||
* Power management panel now displays modules in descending order of power usage by default
|
||||
* Shot speed can no longer be modified directly. Its value is derived from the range modifier for Long Range and Focused modifications
|
||||
* Ensure that jump range chart updates when fuel slider is changed
|
||||
* Add 'Engine profile' and 'FSD profile' charts. These show how your maximum speed/jump range will alter as you alter the mass of your build
|
||||
* Use coriolis-data 2.2.19:
|
||||
* Remove shot speed modification - it is directly tied to range
|
||||
* Fix incorrect minimal mass for 3C bi-weave shield generator
|
||||
|
||||
#2.2.18
|
||||
* Change methodology for calculating explorer role; can result in lighter builds
|
||||
* Tidy up layout for module selection and lay everything out in a consistent best-to-worst for both class and grade
|
||||
* Make integrity for module reinforcement packages visible
|
||||
* Clean up breakpoints for modules in available modules list; stops 7- or 8- module long lines
|
||||
* Add damager/range graphs to damage dealt
|
||||
* Reorder panels
|
||||
* Use coriolis-data 2.2.18:
|
||||
* Correct lower efficiency value to be better, not worse
|
||||
|
||||
#2.2.17
|
||||
* Use in-game terminology for shield generator optmul and optmass items
|
||||
* Add crew to shipyard and outfitting page information
|
||||
* Use coriolis-data 2.2.17:
|
||||
* Add mass as potential SCB modification
|
||||
* Fix mining laser statistics
|
||||
* Remove non-existent grade 4 and 5 wake scanner modifications
|
||||
* Add number of crew for each ship
|
||||
|
||||
#2.2.16
|
||||
* Fix 'Extreme' blueprint roll where some incorrect ranges were chosen
|
||||
* Use coriolis-data 2.2.16:
|
||||
* Fix incorrect thermal load modifiers for dirty drives
|
||||
* Provide explicit information about if values are higher numeric value == better or not
|
||||
|
||||
#2.2.15
|
||||
* Ensure that standard slots are repainted when any component changes
|
||||
* Reload page if Safari throws a security error
|
||||
* Handle import of ships with incorrectly-sized slots
|
||||
* Add 'Extreme' blueprint roll: best beneficial and worst detrimental outcome (in place of 'Average' roll)
|
||||
* Display information about Microsoft browser issues when an import fails
|
||||
* Add 'purchase this build' icon link to EDDB
|
||||
* Add 'miner' and 'shielded miner' ship roles
|
||||
* Use coriolis-data 2.2.15:
|
||||
* Fix location of initial cargo rack for Vulture
|
||||
* Fix broken regeneration rate for 6B shield generators
|
||||
* Tidy up breach damage values
|
||||
|
||||
#2.2.14
|
||||
* Ensure that jitter is shown correctly when the result of a special effect
|
||||
* Use restyled blueprint information
|
||||
* Use the ship name (if available) rather than the ship model for the window title
|
||||
* Use coriolis-data 2.2.14:
|
||||
* Alter blueprint structure to combine components and features
|
||||
* Make hidden value of modifications its own attribute
|
||||
* Fix incorrect ED ID for class 6 passenger cabins
|
||||
|
||||
#2.2.13
|
||||
* Add 'time to drain' summary value. This is the time to drain the WEP capacitor if firing all enabled weapons
|
||||
* Do not include utility slot DPS/EPS/HPS in summary information
|
||||
* Ensure that auto loader special shows in the tooltip
|
||||
* Ensure that ship mass is recalculated when appropriate
|
||||
* Use coriolis-data 2.2.13:
|
||||
* Add plasma slug special effect for plasma accelerator
|
||||
* Tweak hull costs of ships
|
||||
|
||||
#2.2.12
|
||||
* Tidy up old references to coriolis.io
|
||||
* Add ability to add and remove special effects to weapon modifications
|
||||
* Add weapon engineering information to Damage Dealt section
|
||||
* Change shortcut for link from ctrl-l to ctrl-o to avoid clash with location bar
|
||||
* Only show one of power generation or draw in tooltips, according to module
|
||||
* Use coriolis-data 2.2.12:
|
||||
* Add special effects for each blueprint
|
||||
* Add IDs for most Powerplay modules
|
||||
|
||||
#2.2.11
|
||||
* Add help system and initial help file
|
||||
* Make absolute damage visible
|
||||
* Add 'average' roll for blueprints
|
||||
* Update spacing for movement summary to make it more readable
|
||||
* Provide damage dealt statistics for both shields and hull
|
||||
* Damage dealt panel only shows enabled weapons
|
||||
* Add engagement range to damage received panel
|
||||
* Handle burst rate of fire as an absolute number rather than a perentage modification
|
||||
* Ensure that clip values are always rounded up
|
||||
* Ensure that focused weapon mod uses range modifier to increase falloff as well
|
||||
* Use coriolis-data 2.2.11:
|
||||
* Remove non-existent chaff launcher capacity blueprint grades
|
||||
* Fix incorrect values for charge enhanced power distributor
|
||||
* Remove incorrect AFMU blueprints
|
||||
* Correct fragment cannon Double Shot blueprint information
|
||||
* Correct Focused weapon blueprint information
|
||||
|
||||
#2.2.10
|
||||
* Fix detailed export of module reinforcement packages
|
||||
* Use damagedist for exact breakdown of weapons that have more than one type of damage
|
||||
* Use new-style modification validity data
|
||||
* Provide ability to select engineering blueprint and roll sample values for them
|
||||
* Use coriolis-data 2.2.10:
|
||||
* Fix incorrect base shield values for Cutter and Corvette
|
||||
* Update weapons to have %-based damage distributions
|
||||
* Remove power draw for detailed surface scanner - although shown in outfitting it is not part of active power
|
||||
* Fix incorrect names for lightweight and kinetic armour
|
||||
* Add engineering blueprints
|
||||
|
||||
#2.2.9
|
||||
* Use SSL-enabled server for shortlinks
|
||||
* Add falloff for weapons
|
||||
* Use falloff when calculating weapon effectiveness in damage dealt
|
||||
* Add engagement range slider to 'Damage Dealt' section to allow user to see change in weapon effectiveness with range
|
||||
* Use better DPE calculation methodology
|
||||
* Add total DPS and effectiveness information to 'Damage Dealt' section
|
||||
* Use coriolis-data 2.2.9:
|
||||
* Add falloff metric for weapons
|
||||
* Add falloff from range modification
|
||||
|
||||
#2.2.8
|
||||
* Fix issue where filling all internals with cargo racks would include restricted slots
|
||||
* Use coriolis-data 2.2.8:
|
||||
* Set military slot of Viper Mk IV to class 3; was incorrectly set as class 2
|
||||
* Update base regeneration rate of prismatic shield generators to values in 2.2.03
|
||||
* Update specials with information in 2.2.03
|
||||
|
||||
#2.2.7
|
||||
* Fix resistance diminishing return calculations
|
||||
* Do not allow -100% to be entered as a modification value
|
||||
|
||||
#2.2.6
|
||||
* Add pitch/roll/yaw information
|
||||
* Use combination of pitch, roll and yaw to provide a more useful agility metric
|
||||
* Add movement summary to outfitting page
|
||||
* Add standard internal class sizes to shipyard page
|
||||
* Fix issue when importing Viper Mk IV
|
||||
* Ensure ordering of all types of modules (standard, internal, utilities) is consistent
|
||||
* Add rebuilds per bay information for fighter hangars
|
||||
* Add ability to show military compartments
|
||||
* Show module reinforcement package results in defence summary
|
||||
* Use separate speed/rotation/acceleration multipliers for thrusters if available
|
||||
* Obey restricted slot rules when adding all for internal slots
|
||||
* Version URLs to handle changes to ship specifications over time
|
||||
* Do not include disabled shield boosters in calculations
|
||||
* Add 'Damage dealt' section
|
||||
* Add 'Damage received' section
|
||||
* Add 'Piercing' information to hardpoints
|
||||
* Add 'Hardness' information to ship summary
|
||||
* Add module copy functionality - drag module whilst holding 'alt' to copy
|
||||
* Add base resistances to defence summary tooltip
|
||||
* Update shield recovery/regeneration calculations
|
||||
* Pin menu to top of page
|
||||
* Switch to custom shortlink method to avoid google length limitations
|
||||
* Ensure that information is not lost on narrow screens
|
||||
* Do not lose ship selector selection on narrow screens
|
||||
* Reinstate jump range graph
|
||||
* Use coriolis-data 2.2.6:
|
||||
* Update weapons with changed values for 2.2.03
|
||||
* Add individual pitch/roll/yaw statistics for each ship
|
||||
* Remove old and meaningless agility stat
|
||||
* Use sane order for multi-module JSON - coriolis can re-order as it sees fit when displaying modules
|
||||
* Fix cost of fighter hangars
|
||||
* Update Powerplay weapons with current statistics
|
||||
* Add separate min/opt/max multipliers for enhanced thrusters for speed, acceleration and rotation
|
||||
* Add module reinforcement packages
|
||||
* Add military compartments
|
||||
* Fix missing damage value for 2B dumbfires
|
||||
* Update shield recharge rates
|
||||
* Reduce hull mass of Viper to 50T
|
||||
* Fix incorrect optimal mass value for 8A thrusters
|
||||
* Add power draw for detailed surface scanner
|
||||
|
||||
#2.2.5
|
||||
* Calculate rate of fire for multi-burst weapons
|
||||
* Add note to disable ghostery in error situation
|
||||
* Use coriolis-data 2.2.5:
|
||||
* Fix incorrect ID for emissive munitions special
|
||||
* Fix rate of fire for burst lasers
|
||||
* Add fragment cannon modifications
|
||||
* Fix internal name of dazzle shell
|
||||
|
||||
#2.2.4
|
||||
* Add shortlink for outfitting page
|
||||
* Use coriolis-data 2.2.4:
|
||||
* Fix incorrect ID for class 5 luxury passenger cabin
|
||||
* Add damage type modifier
|
||||
* Change modifications from simple strings to objects, to allow more data-driven behaviour
|
||||
* Add special effects
|
||||
* Modification tooltip now shows special effect
|
||||
|
||||
#2.2.3
|
||||
* Fix hull boost calculation - now shows correct % modifier and total armour
|
||||
* Fix import of DiamondBack - can now be imported
|
||||
* Fix import of Beluga - can now be imported
|
||||
* Use coriolis-data 2.2.3:
|
||||
* Fix mismatch between class 5 and class 7 fighter hangars - now shows correct module
|
||||
* Add details for concordant sequence special effect - now shows correct damage
|
||||
* Fix details for thermal shock special effect - now shows correct damage
|
||||
* Add engineer blueprints
|
||||
* Modification tooltip now shows name and grade of modifications for imported builds
|
||||
* Retain import URL unless user changes the build - allows future updates of Coriolis to take advantage of additional build information
|
||||
|
||||
#2.2.2
|
||||
* Update DPS/HPS/EPS in real-time as modifiers change
|
||||
* Use coriolis-data 2.2.2:
|
||||
* Add distributor draw modifier to shield generators
|
||||
* Remove modifiers for sensors
|
||||
* Add initial loadout passenger cabins for Beluga
|
||||
* Add initial loadout passenger cabins for Orca
|
||||
* Update costs and initial loadouts for Keelback and Type-7
|
||||
* Add resistances for hull reinforcement packages
|
||||
* Added modifier actions to create modifications from raw data
|
||||
* Show modification icon for modified modules
|
||||
* Take modifications in to account when deciding whether to issue a warning on a standard module
|
||||
* Fix hardpoint comparison DPS number when selecting an alternate module
|
||||
* Ensure that retrofit tab only shows changed modules
|
||||
* Fix import and export of ships with modifications, bump schema version to 4
|
||||
* Enable boost display even if power distributor is disabled
|
||||
* Calculate breakdown of ship offensive and defensive stats
|
||||
* Add 'Offence summary' and 'Defence summary' components
|
||||
* Add ability to import from companion API output through import feature
|
||||
* Add ability to import from companion API output through URL
|
||||
26
README.md
@@ -1,37 +1,41 @@
|
||||
[](https://travis-ci.org/cmmcleod/coriolis) [](https://waffle.io/cmmcleod/coriolis) [](http://waffle.io/cmmcleod/coriolis)
|
||||
|
||||
|
||||
 [](https://travis-ci.org/EDCD/coriolis) [](https://discord.gg/0uwCh6R62aPRjk9w)
|
||||
|
||||
## 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. It is not endorsed by nor reflects the views or opinions of Frontier Developments.
|
||||
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
|
||||
|
||||
Please [submit issues](https://github.com/cmmcleod/coriolis/issues), or better yet [pull requests](http://www.elitedangerous.com) for any corrections or additions to the database or the code.
|
||||
Please [submit issues](https://github.com/EDCD/coriolis/issues), or better yet [pull requests](https://github.com/EDCD/coriolis/pulls) for any corrections or additions to the database or the code.
|
||||
|
||||
### Translations
|
||||
|
||||
Please use the OneSky translation site to suggest new translations: http://edcd-coriolis.oneskyapp.com
|
||||
These will be merged regularly by the project manager.
|
||||
|
||||
### Feature Requests, Suggestions & Bugs
|
||||
|
||||
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).
|
||||
Chat to us on [Discord](https://discord.gg/0uwCh6R62aPRjk9w)!
|
||||
|
||||
## Development
|
||||
|
||||
See the [Developer's Guide](https://github.com/cmmcleod/coriolis/wiki/Developer's-Guide) in the wiki.
|
||||
See the [Developer's Guide](https://github.com/EDCD/coriolis/wiki/Developing-for-Coriolis) 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/EDCD/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 specificially for Coriolis.io is released under the MIT License.
|
||||
The code (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.
|
||||
|
||||
Copyright (c) 2015 Coriolis.io, Colin McLeod
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
||||
30
__tests__/fixtures/agility-data.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"adder": {
|
||||
"t3": {"speed": 205, "boost": 298, "pitch": 35.37, "roll": 93.09, "yaw": 13.03},
|
||||
"t2": {"speed": 209, "boost": 304, "pitch": 36.06, "roll": 94.90, "yaw": 13.29},
|
||||
"t1": {"speed": 213, "boost": 310, "pitch": 36.80, "roll": 96.84, "yaw": 13.56},
|
||||
"t0": {"speed": 218, "boost": 317, "pitch": 37.70, "roll": 99.20, "yaw": 13.89},
|
||||
"t9": {"speed": 220, "boost": 321, "pitch": 38.08, "roll": 100.21, "yaw": 14.03},
|
||||
"t8": {"speed": 225, "boost": 327, "pitch": 38.86, "roll": 102.26, "yaw": 14.32},
|
||||
"t7": {"speed": 230, "boost": 334, "pitch": 39.69, "roll": 104.44, "yaw": 14.62},
|
||||
"t6": {"speed": 234, "boost": 340, "pitch": 40.41, "roll": 106.34, "yaw": 14.89},
|
||||
"t5": {"speed": 242, "boost": 351, "pitch": 41.71, "roll": 109.78, "yaw": 15.37}
|
||||
},
|
||||
"eagle": {
|
||||
"t2": {"speed": 223, "boost": 325, "pitch": 46.45, "roll": 111.48, "yaw": 16.72},
|
||||
"t1": {"speed": 229, "boost": 334, "pitch": 47.69, "roll": 114.46, "yaw": 17.17},
|
||||
"t0": {"speed": 235, "boost": 343, "pitch": 49.00, "roll": 117.60, "yaw": 17.64},
|
||||
"t9": {"speed": 239, "boost": 349, "pitch": 49.80, "roll": 119.53, "yaw": 17.93},
|
||||
"t8": {"speed": 243, "boost": 355, "pitch": 50.70, "roll": 121.69, "yaw": 18.25},
|
||||
"t7": {"speed": 248, "boost": 361, "pitch": 51.62, "roll": 123.89, "yaw": 18.58},
|
||||
"t6": {"speed": 252, "boost": 367, "pitch": 52.46, "roll": 125.91, "yaw": 18.89},
|
||||
"t5": {"speed": 259, "boost": 378, "pitch": 53.99, "roll": 129.56, "yaw": 19.43}
|
||||
},
|
||||
"hauler": {
|
||||
"t4": {"speed": 203, "boost": 305, "pitch": 36.61, "roll": 101.71, "yaw": 14.24},
|
||||
"t3": {"speed": 209, "boost": 314, "pitch": 37.63, "roll": 104.54, "yaw": 14.64},
|
||||
"t2": {"speed": 216, "boost": 324, "pitch": 38.89, "roll": 108.03, "yaw": 15.12},
|
||||
"t1": {"speed": 222, "boost": 333, "pitch": 39.97, "roll": 111.02, "yaw": 15.54},
|
||||
"t0": {"speed": 232, "boost": 348, "pitch": 41.76, "roll": 116.00, "yaw": 16.24}
|
||||
}
|
||||
}
|
||||
289
__tests__/fixtures/anaconda-test-detailed-export-v3.json
Normal file
@@ -0,0 +1,289 @@
|
||||
{
|
||||
"$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.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",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 3
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 8,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"sensors": {
|
||||
"class": 8,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 5,
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"utility": [
|
||||
{
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"internal": [
|
||||
{
|
||||
"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,
|
||||
null,
|
||||
{
|
||||
"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",
|
||||
"enabled": true,
|
||||
"priority": 3,
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 3,
|
||||
"hullCost": 141889930,
|
||||
"speed": 180,
|
||||
"topSpeed": 186.5,
|
||||
"boost": 240,
|
||||
"boostEnergy": 29,
|
||||
"topBoost": 248.66,
|
||||
"agility": 2,
|
||||
"baseShieldStrength": 350,
|
||||
"baseArmour": 945,
|
||||
"hullMass": 400,
|
||||
"masslock": 23,
|
||||
"pipSpeed": 0.14,
|
||||
"moduleCostMultiplier": 1,
|
||||
"fuelCapacity": 32,
|
||||
"cargoCapacity": 128,
|
||||
"ladenMass": 1339.2,
|
||||
"armour": 2228,
|
||||
"armourAdded": 390,
|
||||
"armourMultiplier": 1.95,
|
||||
"shieldMultiplier": 1.4,
|
||||
"totalCost": 882362060,
|
||||
"unladenMass": 1179.2,
|
||||
"totalDps": 29,
|
||||
"powerAvailable": 36,
|
||||
"powerRetracted": 23.33,
|
||||
"powerDeployed": 34.76,
|
||||
"unladenRange": 18.49,
|
||||
"fullTankRange": 18.12,
|
||||
"ladenRange": 16.39,
|
||||
"unladenFastestRange": 73.21,
|
||||
"ladenFastestRange": 66.15,
|
||||
"maxJumpCount": 4,
|
||||
"shieldStrength": 833
|
||||
}
|
||||
}
|
||||
325
__tests__/fixtures/anaconda-test-detailed-export-v4.json
Normal file
@@ -0,0 +1,325 @@
|
||||
{
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#",
|
||||
"name": "Test My Ship",
|
||||
"ship": "Anaconda",
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA==?bn=Test%20My%20Ship",
|
||||
"old-code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA==",
|
||||
"code": "4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.AwRj4zNKqA==.CwBhCYzBGW9qCTSqs5xA.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA==",
|
||||
"shipId": "anaconda"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"standard": {
|
||||
"bulkheads": "Reactive Surface Composite",
|
||||
"cargoHatch": {
|
||||
"enabled": false,
|
||||
"priority": 5
|
||||
},
|
||||
"powerPlant": {
|
||||
"class": 8,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"modifications": {
|
||||
"pgen": 1000
|
||||
}
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 3
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 8,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"sensors": {
|
||||
"class": 8,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 5,
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"utility": [
|
||||
{
|
||||
"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": "Electronic Countermeasure",
|
||||
"name": "Electronic Countermeasure"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Chaff Launcher",
|
||||
"name": "Chaff Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Point Defence",
|
||||
"name": "Point Defence"
|
||||
}
|
||||
],
|
||||
"internal": [
|
||||
{
|
||||
"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,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"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",
|
||||
"enabled": true,
|
||||
"priority": 3,
|
||||
"group": "Frame Shift Drive Interdictor"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 3,
|
||||
"fighterHangars": 1,
|
||||
"hullCost": 141889930,
|
||||
"speed": 180,
|
||||
"topSpeed": 186.5,
|
||||
"boost": 240,
|
||||
"boostEnergy": 27,
|
||||
"topBoost": 249.34,
|
||||
"topPitch": 25.97,
|
||||
"topRoll": 62.34,
|
||||
"topYaw": 10.39,
|
||||
"topSpeed": 187.01,
|
||||
"totalCost": 882362058,
|
||||
"totalDpe": 142.68,
|
||||
"totalDps": 101.13,
|
||||
"totalEps": 18.71,
|
||||
"totalExplDpe": 0,
|
||||
"totalExplDps": 0,
|
||||
"totalExplSDps": 0,
|
||||
"totalAbsDpe": 3.57,
|
||||
"totalAbsDps": 18.78,
|
||||
"totalAbsSDps": 14.45,
|
||||
"totalHps": 28.28,
|
||||
"totalKinDpe": 117.48,
|
||||
"totalKinDps": 22.27,
|
||||
"totalKinSDps": 16.91,
|
||||
"totalSDps": 89.99,
|
||||
"totalThermDpe": 21.63,
|
||||
"totalThermDps": 60.08,
|
||||
"totalThermSDps": 58.64,
|
||||
"baseShieldStrength": 350,
|
||||
"baseArmour": 945,
|
||||
"hullExplRes": 0.22,
|
||||
"hullKinRes": 0.27,
|
||||
"hullMass": 400,
|
||||
"hullThermRes": -0.36,
|
||||
"masslock": 23,
|
||||
"pipSpeed": 0.14,
|
||||
"pitch": 25,
|
||||
"moduleCostMultiplier": 1,
|
||||
"modulearmour": 0,
|
||||
"moduleprotection": 0,
|
||||
"fuelCapacity": 32,
|
||||
"cargoCapacity": 128,
|
||||
"ladenMass": 1323.2,
|
||||
"armour": 2227.5,
|
||||
"baseArmour": 525,
|
||||
"unladenMass": 1163.2,
|
||||
"powerAvailable": 39.6,
|
||||
"powerRetracted": 23.33,
|
||||
"powerDeployed": 34.13,
|
||||
"roll": 60,
|
||||
"unladenRange": 18.74,
|
||||
"yaw": 10,
|
||||
"fullTankRange": 18.36,
|
||||
"hardness": 65,
|
||||
"ladenRange": 16.59,
|
||||
"unladenFastestRange": 74.2,
|
||||
"ladenFastestRange": 66.96,
|
||||
"maxJumpCount": 4,
|
||||
"shield": 833,
|
||||
"shieldCells": 1840,
|
||||
"shieldExplRes": 0.5,
|
||||
"shieldKinRes": 0.4,
|
||||
"shieldThermRes": -0.2,
|
||||
"crew": 3
|
||||
}
|
||||
}
|
||||
255
__tests__/fixtures/asp-test-detailed-export-v4.json
Normal file
@@ -0,0 +1,255 @@
|
||||
{
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#",
|
||||
"name": "Multi-purpose Asp Explorer",
|
||||
"ship": "Asp Explorer",
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "https://coriolis.edcd.io/outfit/asp?code=0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FAwDFxwtofAAAAA%3D%3D&bn=Multi-purpose%20Asp%20Explorer",
|
||||
"code": "0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx/78YG5AltB7I/8/0TwImJboDSPJ/+/f/v/KlX///i3AwMTBIfARK/Gf+JwVSxArStVAYqOjvz///JVo5GRhE2IBc4SKQSSz/DGEmCa398P8//2+gTf//AwDFxwtofAAAAA==",
|
||||
"shipId": "asp"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"standard": {
|
||||
"bulkheads": "Lightweight Alloy",
|
||||
"cargoHatch": {
|
||||
"enabled": false,
|
||||
"priority": 5
|
||||
},
|
||||
"powerPlant": {
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"modifications": {
|
||||
"eff": -1850,
|
||||
"pgen": 6,
|
||||
"mass": 431
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 64,
|
||||
"name": "Low emissions",
|
||||
"grade": 1
|
||||
}
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"modifications": {
|
||||
"optmul": 440,
|
||||
"integrity": -266,
|
||||
"thermload": -1326,
|
||||
"optmass": 520,
|
||||
"power": 241
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 24,
|
||||
"name": "Clean",
|
||||
"grade": 1
|
||||
}
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 5,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"modifications": {
|
||||
"mass": 5025,
|
||||
"integrity": -1539,
|
||||
"power": 2437,
|
||||
"optmass": 4870,
|
||||
"maxfuel": 370
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 26,
|
||||
"name": "Increased range",
|
||||
"grade": 5
|
||||
}
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"modifications": {
|
||||
"mass": -3923,
|
||||
"integrity": -1797
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 49,
|
||||
"name": "Lightweight",
|
||||
"grade": 1
|
||||
}
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 3,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"sensors": {
|
||||
"class": 5,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 5,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
}
|
||||
},
|
||||
"hardpoints": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"utility": [
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Heat Sink Launcher",
|
||||
"name": "Heat Sink Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Heat Sink Launcher",
|
||||
"name": "Heat Sink Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Heat Sink Launcher",
|
||||
"name": "Heat Sink Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Point Defence",
|
||||
"name": "Point Defence"
|
||||
}
|
||||
],
|
||||
"internal": [
|
||||
{
|
||||
"class": 6,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Fuel Scoop"
|
||||
},
|
||||
{
|
||||
"class": 5,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Generator"
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "G",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Planetary Vehicle Hangar"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Scanner",
|
||||
"name": "Advanced Discovery Scanner"
|
||||
},
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Scanner",
|
||||
"name": "Detailed Surface Scanner"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 2,
|
||||
"hullCost": 6135660,
|
||||
"speed": 250,
|
||||
"boost": 340,
|
||||
"boostEnergy": 13,
|
||||
"agility": 6,
|
||||
"baseShieldStrength": 140,
|
||||
"baseArmour": 210,
|
||||
"hullMass": 280,
|
||||
"masslock": 11,
|
||||
"pipSpeed": 0.13,
|
||||
"moduleCostMultiplier": 1,
|
||||
"fuelCapacity": 32,
|
||||
"cargoCapacity": 40,
|
||||
"ladenMass": 435.26,
|
||||
"armour": 378,
|
||||
"shield": 113.43,
|
||||
"shieldCells": 0,
|
||||
"totalCost": 48402550,
|
||||
"unladenMass": 363.26,
|
||||
"totalDpe": 0,
|
||||
"totalExplDpe": 0,
|
||||
"totalKinDpe": 0,
|
||||
"totalThermDpe": 0,
|
||||
"totalDps": 0,
|
||||
"totalExplDps": 0,
|
||||
"totalKinDps": 0,
|
||||
"totalThermDps": 0,
|
||||
"totalSDps": 0,
|
||||
"totalExplSDps": 0,
|
||||
"totalKinSDps": 0,
|
||||
"totalThermSDps": 0,
|
||||
"totalEps": 1.2,
|
||||
"totalHps": 1,
|
||||
"shieldExplRes": 0.5,
|
||||
"shieldKinRes": 0.6,
|
||||
"shieldThermRes": 1.2,
|
||||
"hullExplRes": 1.4,
|
||||
"hullKinRes": 1.2,
|
||||
"hullThermRes": 1,
|
||||
"powerAvailable": 20.41,
|
||||
"powerRetracted": 11.91,
|
||||
"powerDeployed": 11.91,
|
||||
"unladenRange": 50.45,
|
||||
"fullTankRange": 47.03,
|
||||
"ladenRange": 42.71,
|
||||
"unladenFastestRange": 317.24,
|
||||
"ladenFastestRange": 287.02,
|
||||
"maxJumpCount": 7,
|
||||
"topSpeed": 274.01,
|
||||
"topBoost": 372.65
|
||||
}
|
||||
}
|
||||
1288
__tests__/fixtures/companion-api-import-1.json
Normal file
552
__tests__/fixtures/companion-api-import-2.json
Normal file
@@ -0,0 +1,552 @@
|
||||
{
|
||||
"cargo": {
|
||||
"capacity": 32
|
||||
},
|
||||
"free": false,
|
||||
"fuel": {
|
||||
"main": {
|
||||
"capacity": 128
|
||||
},
|
||||
"reserve": {
|
||||
"capacity": 0.81
|
||||
}
|
||||
},
|
||||
"id": 31,
|
||||
"modules": {
|
||||
"Armour": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049346,
|
||||
"name": "BelugaLiner_Armour_Grade1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Bobble01": [],
|
||||
"Bobble02": [],
|
||||
"Bobble03": [],
|
||||
"Bobble04": [],
|
||||
"Bobble05": [],
|
||||
"Bobble06": [],
|
||||
"Bobble07": [],
|
||||
"Bobble08": [],
|
||||
"Bobble09": [],
|
||||
"Bobble10": [],
|
||||
"Decal1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667757,
|
||||
"name": "Decal_Explorer_Ranger",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667742,
|
||||
"name": "Decal_Combat_Deadly",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667750,
|
||||
"name": "Decal_Trade_Tycoon",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"EngineColour": [],
|
||||
"FrameShiftDrive": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064132,
|
||||
"modifiers": {
|
||||
"engineerID": 300100,
|
||||
"id": 175,
|
||||
"modifiers": [
|
||||
{
|
||||
"name": "mod_mass",
|
||||
"type": 1,
|
||||
"value": 0.4457540512085
|
||||
},
|
||||
{
|
||||
"name": "mod_health",
|
||||
"type": 1,
|
||||
"value": -0.24584779143333
|
||||
},
|
||||
{
|
||||
"name": "mod_passive_power",
|
||||
"type": 1,
|
||||
"value": 0.24457727372646
|
||||
},
|
||||
{
|
||||
"name": "mod_fsd_optimised_mass",
|
||||
"type": 1,
|
||||
"value": 0.49257898330688
|
||||
},
|
||||
{
|
||||
"name": "mod_fsd_max_fuel_per_jump",
|
||||
"type": 2,
|
||||
"value": 0.028505677357316
|
||||
},
|
||||
{
|
||||
"name": "mod_fsd_heat_rate",
|
||||
"type": 2,
|
||||
"value": -0.079360365867615
|
||||
}
|
||||
],
|
||||
"moduleTags": [
|
||||
16
|
||||
],
|
||||
"recipeID": 128673694,
|
||||
"slotIndex": 53
|
||||
},
|
||||
"name": "Int_Hyperdrive_Size7_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"recipeLevel": 5,
|
||||
"recipeName": "FSD_LongRange",
|
||||
"recipeValue": 0,
|
||||
"unloaned": 0,
|
||||
"value": 46160201
|
||||
}
|
||||
},
|
||||
"FuelTank": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064352,
|
||||
"name": "Int_FuelTank_Size7_Class3",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 1602822,
|
||||
"value": 1602822
|
||||
}
|
||||
},
|
||||
"LifeSupport": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064174,
|
||||
"name": "Int_LifeSupport_Size8_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 1569565
|
||||
}
|
||||
},
|
||||
"MainEngines": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064094,
|
||||
"modifiers": {
|
||||
"engineerID": 300100,
|
||||
"id": 253,
|
||||
"modifiers": [
|
||||
{
|
||||
"name": "mod_engine_mass_curve_multiplier",
|
||||
"type": 1,
|
||||
"value": 0.098235413432121
|
||||
},
|
||||
{
|
||||
"name": "mod_engine_heat",
|
||||
"type": 1,
|
||||
"value": 0.18069696426392
|
||||
},
|
||||
{
|
||||
"name": "mod_passive_power",
|
||||
"type": 1,
|
||||
"value": 0.033788848668337
|
||||
},
|
||||
{
|
||||
"name": "mod_health",
|
||||
"type": 1,
|
||||
"value": -0.056404989212751
|
||||
},
|
||||
{
|
||||
"name": "mod_engine_mass_curve",
|
||||
"type": 1,
|
||||
"value": -0.027384582906961
|
||||
},
|
||||
{
|
||||
"name": "mod_engine_heat",
|
||||
"type": 2,
|
||||
"value": -0.072683908045292
|
||||
}
|
||||
],
|
||||
"moduleTags": [
|
||||
17
|
||||
],
|
||||
"recipeID": 128673655,
|
||||
"slotIndex": 52
|
||||
},
|
||||
"name": "Int_Engine_Size7_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"recipeLevel": 1,
|
||||
"recipeName": "Engine_Dirty",
|
||||
"recipeValue": 0,
|
||||
"unloaned": 0,
|
||||
"value": 1709638
|
||||
}
|
||||
},
|
||||
"MediumHardpoint1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049436,
|
||||
"name": "Hpt_BeamLaser_Turret_Medium",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 1889910
|
||||
}
|
||||
},
|
||||
"MediumHardpoint2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049436,
|
||||
"name": "Hpt_BeamLaser_Turret_Medium",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 1889910
|
||||
}
|
||||
},
|
||||
"MediumHardpoint3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049460,
|
||||
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 51300
|
||||
}
|
||||
},
|
||||
"MediumHardpoint4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049460,
|
||||
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 51300
|
||||
}
|
||||
},
|
||||
"MediumHardpoint5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049460,
|
||||
"name": "Hpt_MultiCannon_Gimbal_Medium",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 51300
|
||||
}
|
||||
},
|
||||
"PaintJob": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128732290,
|
||||
"name": "PaintJob_BelugaLiner_Tactical_White",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"PlanetaryApproachSuite": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128672317,
|
||||
"name": "Int_PlanetApproachSuite",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 450,
|
||||
"value": 450
|
||||
}
|
||||
},
|
||||
"PowerDistributor": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064207,
|
||||
"name": "Int_PowerDistributor_Size6_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 3128120
|
||||
}
|
||||
},
|
||||
"PowerPlant": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064057,
|
||||
"modifiers": {
|
||||
"engineerID": 300100,
|
||||
"id": 277,
|
||||
"modifiers": [
|
||||
{
|
||||
"name": "mod_powerplant_power",
|
||||
"type": 1,
|
||||
"value": 0.054692290723324
|
||||
},
|
||||
{
|
||||
"name": "mod_health",
|
||||
"type": 1,
|
||||
"value": -0.033690698444843
|
||||
},
|
||||
{
|
||||
"name": "mod_powerplant_heat",
|
||||
"type": 1,
|
||||
"value": 0.027470717206597
|
||||
},
|
||||
{
|
||||
"name": "mod_powerplant_heat",
|
||||
"type": 2,
|
||||
"value": -0.056317910552025
|
||||
}
|
||||
],
|
||||
"moduleTags": [
|
||||
18
|
||||
],
|
||||
"recipeID": 128673765,
|
||||
"slotIndex": 51
|
||||
},
|
||||
"name": "Int_Powerplant_Size6_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"recipeLevel": 1,
|
||||
"recipeName": "PowerPlant_Boosted",
|
||||
"recipeValue": 0,
|
||||
"unloaned": 0,
|
||||
"value": 14561578
|
||||
}
|
||||
},
|
||||
"Radar": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064239,
|
||||
"name": "Int_Sensors_Size5_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 71500
|
||||
}
|
||||
},
|
||||
"Slot01_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128666681,
|
||||
"name": "Int_FuelScoop_Size6_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 25887249
|
||||
}
|
||||
},
|
||||
"Slot02_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064287,
|
||||
"name": "Int_ShieldGenerator_Size6_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 14561578
|
||||
}
|
||||
},
|
||||
"Slot03_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128727927,
|
||||
"name": "Int_PassengerCabin_Size6_Class2",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 165808,
|
||||
"value": 165808
|
||||
}
|
||||
},
|
||||
"Slot04_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128727928,
|
||||
"name": "Int_PassengerCabin_Size6_Class3",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 497429
|
||||
}
|
||||
},
|
||||
"Slot05_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128727925,
|
||||
"name": "Int_PassengerCabin_Size5_Class4",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 1492286
|
||||
}
|
||||
},
|
||||
"Slot06_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064342,
|
||||
"name": "Int_CargoRack_Size5_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 100409,
|
||||
"value": 100409
|
||||
}
|
||||
},
|
||||
"Slot07_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128727922,
|
||||
"name": "Int_PassengerCabin_Size4_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 17059
|
||||
}
|
||||
},
|
||||
"Slot08_Size3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667632,
|
||||
"name": "Int_Repairer_Size3_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 2361960
|
||||
}
|
||||
},
|
||||
"Slot09_Size3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128672289,
|
||||
"name": "Int_BuggyBay_Size2_Class2",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 19440
|
||||
}
|
||||
},
|
||||
"Slot10_Size3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128666634,
|
||||
"name": "Int_DetailedSurfaceScanner_Tiny",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 225000
|
||||
}
|
||||
},
|
||||
"Slot11_Size3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128663561,
|
||||
"name": "Int_StellarBodyDiscoveryScanner_Advanced",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 1390500
|
||||
}
|
||||
},
|
||||
"TinyHardpoint1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049513,
|
||||
"name": "Hpt_ChaffLauncher_Tiny",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 7650
|
||||
}
|
||||
},
|
||||
"TinyHardpoint2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 252900
|
||||
}
|
||||
},
|
||||
"TinyHardpoint3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 252900
|
||||
}
|
||||
},
|
||||
"TinyHardpoint4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"WeaponColour": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128732194,
|
||||
"name": "WeaponCustomisation_Purple",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "BelugaLiner",
|
||||
"value": {
|
||||
"hull": 71688743,
|
||||
"modules": 120812762,
|
||||
"unloaned": 1869489
|
||||
}
|
||||
}
|
||||
314
__tests__/fixtures/companion-api-import-3.json
Normal file
@@ -0,0 +1,314 @@
|
||||
{
|
||||
"cargo": {
|
||||
"capacity": 264
|
||||
},
|
||||
"free": false,
|
||||
"fuel": {
|
||||
"main": {
|
||||
"capacity": 32
|
||||
},
|
||||
"reserve": {
|
||||
"capacity": 0.52
|
||||
}
|
||||
},
|
||||
"id": 4,
|
||||
"modules": {
|
||||
"Armour": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049298,
|
||||
"name": "Type7_Armour_Grade1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Bobble01": [],
|
||||
"Bobble02": [],
|
||||
"Bobble03": [],
|
||||
"Bobble04": [],
|
||||
"Bobble05": [],
|
||||
"Bobble06": [],
|
||||
"Bobble07": [],
|
||||
"Bobble08": [],
|
||||
"Bobble09": [],
|
||||
"Bobble10": [],
|
||||
"Decal1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667746,
|
||||
"name": "Decal_Trade_Dealer",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667738,
|
||||
"name": "Decal_Combat_Competent",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Decal3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128667753,
|
||||
"name": "Decal_Explorer_Scout",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"EngineColour": [],
|
||||
"FrameShiftDrive": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064122,
|
||||
"name": "Int_Hyperdrive_Size5_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 5103953
|
||||
}
|
||||
},
|
||||
"FuelTank": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064350,
|
||||
"name": "Int_FuelTank_Size5_Class3",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 97754,
|
||||
"value": 97754
|
||||
}
|
||||
},
|
||||
"LifeSupport": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064154,
|
||||
"name": "Int_LifeSupport_Size4_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 28373
|
||||
}
|
||||
},
|
||||
"MainEngines": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064087,
|
||||
"name": "Int_Engine_Size5_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 5103953
|
||||
}
|
||||
},
|
||||
"PaintJob": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128671422,
|
||||
"name": "PaintJob_Type7_Tactical_White",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"PlanetaryApproachSuite": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128672317,
|
||||
"name": "Int_PlanetApproachSuite",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 500,
|
||||
"value": 500
|
||||
}
|
||||
},
|
||||
"PowerDistributor": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064192,
|
||||
"name": "Int_PowerDistributor_Size3_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 158331
|
||||
}
|
||||
},
|
||||
"PowerPlant": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064047,
|
||||
"name": "Int_Powerplant_Size4_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 1610080
|
||||
}
|
||||
},
|
||||
"Radar": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064229,
|
||||
"name": "Int_Sensors_Size3_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 10133
|
||||
}
|
||||
},
|
||||
"Slot01_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot02_Size6": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot03_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064343,
|
||||
"name": "Int_CargoRack_Size6_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 362591
|
||||
}
|
||||
},
|
||||
"Slot04_Size5": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064342,
|
||||
"name": "Int_CargoRack_Size5_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 111566,
|
||||
"value": 111566
|
||||
}
|
||||
},
|
||||
"Slot05_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064342,
|
||||
"name": "Int_CargoRack_Size5_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 111566,
|
||||
"value": 111566
|
||||
}
|
||||
},
|
||||
"Slot06_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064279,
|
||||
"name": "Int_ShieldGenerator_Size5_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 189035
|
||||
}
|
||||
},
|
||||
"Slot07_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049549,
|
||||
"name": "Int_DockingComputer_Standard",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 4500
|
||||
}
|
||||
},
|
||||
"Slot08_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064340,
|
||||
"name": "Int_CargoRack_Size3_Class1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"unloaned": 0,
|
||||
"value": 10563
|
||||
}
|
||||
},
|
||||
"SmallHardpoint1": [],
|
||||
"SmallHardpoint2": [],
|
||||
"SmallHardpoint3": [],
|
||||
"SmallHardpoint4": [],
|
||||
"TinyHardpoint1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint3": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128668536,
|
||||
"name": "Hpt_ShieldBooster_Size0_Class5",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 281000
|
||||
}
|
||||
},
|
||||
"TinyHardpoint4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049513,
|
||||
"name": "Hpt_ChaffLauncher_Tiny",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"unloaned": 0,
|
||||
"value": 8500
|
||||
}
|
||||
},
|
||||
"WeaponColour": []
|
||||
},
|
||||
"name": "Type7",
|
||||
"value": {
|
||||
"hull": 16780009,
|
||||
"modules": 14479580,
|
||||
"unloaned": 321386
|
||||
}
|
||||
}
|
||||
225
__tests__/fixtures/companion-api-import-4.json
Normal file
@@ -0,0 +1,225 @@
|
||||
{
|
||||
"free": false,
|
||||
"id": 2,
|
||||
"modules": {
|
||||
"Armour": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128049280,
|
||||
"name": "CobraMkIII_Armour_Grade1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"FrameShiftDrive": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064117,
|
||||
"name": "Int_Hyperdrive_Size4_Class5",
|
||||
"on": true,
|
||||
"priority": 4,
|
||||
"value": 1610080
|
||||
}
|
||||
},
|
||||
"FuelTank": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064349,
|
||||
"name": "Int_FuelTank_Size4_Class3",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 24734
|
||||
}
|
||||
},
|
||||
"LifeSupport": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064149,
|
||||
"name": "Int_LifeSupport_Size3_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"value": 10133
|
||||
}
|
||||
},
|
||||
"MainEngines": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064079,
|
||||
"name": "Int_Engine_Size4_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"value": 59633
|
||||
}
|
||||
},
|
||||
"PaintJob": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128741033,
|
||||
"name": "PaintJob_CobraMKIII_Corrosive_05",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"PlanetaryApproachSuite": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128672317,
|
||||
"name": "Int_PlanetApproachSuite",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 500
|
||||
}
|
||||
},
|
||||
"PowerDistributor": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064179,
|
||||
"name": "Int_PowerDistributor_Size1_Class2",
|
||||
"on": true,
|
||||
"priority": 2,
|
||||
"value": 1293
|
||||
}
|
||||
},
|
||||
"PowerPlant": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064037,
|
||||
"name": "Int_Powerplant_Size2_Class5",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 160224
|
||||
}
|
||||
},
|
||||
"Radar": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128064229,
|
||||
"name": "Int_Sensors_Size3_Class2",
|
||||
"on": true,
|
||||
"priority": 0,
|
||||
"value": 10133
|
||||
}
|
||||
},
|
||||
"ShipID0": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128758976,
|
||||
"name": "Nameplate_ShipID_Black",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipID1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128758976,
|
||||
"name": "Nameplate_ShipID_Black",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipKitBumper": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128740698,
|
||||
"name": "CobraMkIII_ShipkitRaider1_Bumper1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipKitSpoiler": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128740701,
|
||||
"name": "CobraMkIII_ShipkitRaider1_Spoiler1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipKitTail": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128740705,
|
||||
"name": "CobraMkIII_ShipkitRaider1_Tail2",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipKitWings": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128740707,
|
||||
"name": "CobraMkIII_ShipkitRaider1_Wings1",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipName0": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128758944,
|
||||
"name": "Nameplate_Explorer01_Black",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"ShipName1": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128758944,
|
||||
"name": "Nameplate_Explorer01_Black",
|
||||
"on": true,
|
||||
"priority": 1,
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
"Slot01_Size4": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128666663,
|
||||
"name": "Int_FuelScoop_Size4_Class3",
|
||||
"on": true,
|
||||
"priority": 2,
|
||||
"value": 178898
|
||||
}
|
||||
},
|
||||
"Slot02_Size4": [],
|
||||
"Slot03_Size4": [],
|
||||
"Slot04_Size2": [],
|
||||
"Slot05_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128663561,
|
||||
"name": "Int_StellarBodyDiscoveryScanner_Advanced",
|
||||
"on": true,
|
||||
"priority": 2,
|
||||
"value": 1545000
|
||||
}
|
||||
},
|
||||
"Slot06_Size2": {
|
||||
"module": {
|
||||
"free": false,
|
||||
"id": 128666634,
|
||||
"name": "Int_DetailedSurfaceScanner_Tiny",
|
||||
"on": true,
|
||||
"priority": 2,
|
||||
"value": 250000
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "CobraMkIII",
|
||||
"value": {
|
||||
"hull": 205287,
|
||||
"modules": 3850628,
|
||||
"unloaned": 1751109
|
||||
}
|
||||
}
|
||||
327
__tests__/fixtures/courier-test-detailed-export-v4.json
Normal file
@@ -0,0 +1,327 @@
|
||||
{
|
||||
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/4.json#",
|
||||
"name": "Multi-purpose Imperial Courier",
|
||||
"ship": "Imperial Courier",
|
||||
"references": [
|
||||
{
|
||||
"name": "Coriolis.io",
|
||||
"url": "https://coriolis.edcd.io/outfit/imperial_courier?code=0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s%2FkIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA%2B%2Fz%2Bz3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ%2BLgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ%2F0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g%2F6v0TTdbxJ2KhdEIaCw15MF%2FNB0L%2BS2hwEwyFM8KgP%2BqEpWWA3Qu9Z3z9kPWHzakt7Dt%2BAeD7ghSTgEAAA%3D%3D&bn=Multi-purpose%20Imperial%20Courier",
|
||||
"code": "0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ=.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s/kIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA+/z+z3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ+LgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ/0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g/6v0TTdbxJ2KhdEIaCw15MF/NB0L+S2hwEwyFM8KgP+qEpWWA3Qu9Z3z9kPWHzakt7Dt+AeD7ghSTgEAAA==",
|
||||
"shipId": "imperial_courier"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"standard": {
|
||||
"bulkheads": "Lightweight Alloy",
|
||||
"cargoHatch": {
|
||||
"enabled": false,
|
||||
"priority": 5
|
||||
},
|
||||
"powerPlant": {
|
||||
"class": 4,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"modifications": {
|
||||
"pgen": 1052,
|
||||
"integrity": -482,
|
||||
"eff": 974
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 63,
|
||||
"name": "Overcharged",
|
||||
"grade": 1
|
||||
}
|
||||
},
|
||||
"thrusters": {
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"name": "Enhanced Performance",
|
||||
"modifications": {
|
||||
"optmul": 2476,
|
||||
"thermload": 7023,
|
||||
"power": 1763,
|
||||
"integrity": 165,
|
||||
"optmass": -667
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 22,
|
||||
"name": "Dirty",
|
||||
"grade": 4
|
||||
}
|
||||
},
|
||||
"frameShiftDrive": {
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"modifications": {
|
||||
"mass": 4082,
|
||||
"integrity": -2422,
|
||||
"power": 1782,
|
||||
"optmass": 4927
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 26,
|
||||
"name": "Increased range",
|
||||
"grade": 5
|
||||
}
|
||||
},
|
||||
"lifeSupport": {
|
||||
"class": 1,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"powerDistributor": {
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"sensors": {
|
||||
"class": 2,
|
||||
"rating": "D",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
},
|
||||
"fuelTank": {
|
||||
"class": 3,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 1
|
||||
}
|
||||
},
|
||||
"hardpoints": [
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "F",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Pulse Laser",
|
||||
"mount": "Fixed",
|
||||
"modifications": {
|
||||
"rof": 5931,
|
||||
"damage": -184,
|
||||
"jitter": 50,
|
||||
"distdraw": -4689,
|
||||
"piercing": 3328
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 89,
|
||||
"name": "Rapid fire",
|
||||
"grade": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "F",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Pulse Laser",
|
||||
"mount": "Fixed",
|
||||
"modifications": {
|
||||
"rof": 4715,
|
||||
"damage": -97,
|
||||
"jitter": 30,
|
||||
"distdraw": -4548,
|
||||
"piercing": 1057,
|
||||
"integrity": 319
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 89,
|
||||
"name": "Rapid fire",
|
||||
"grade": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "F",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Multi-cannon",
|
||||
"mount": "Gimballed",
|
||||
"modifications": {
|
||||
"damage": 2437,
|
||||
"distdraw": 5487,
|
||||
"rof": 1120,
|
||||
"jitter": 58,
|
||||
"thermload": 1346,
|
||||
"power": 1009,
|
||||
"integrity": -202,
|
||||
"ammo": -2000
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 88,
|
||||
"name": "Overcharged",
|
||||
"grade": 3,
|
||||
"special": {
|
||||
"id": 3,
|
||||
"name": "Corrosive shell"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"utility": [
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Heat Sink Launcher",
|
||||
"name": "Heat Sink Launcher",
|
||||
"modifications": {
|
||||
"ammo": 5000,
|
||||
"mass": 17684,
|
||||
"reload": 9707
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 37,
|
||||
"name": "Ammo capacity",
|
||||
"grade": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Heat Sink Launcher",
|
||||
"name": "Heat Sink Launcher",
|
||||
"modifications": {
|
||||
"ammo": 5000,
|
||||
"mass": 18520,
|
||||
"reload": 8715
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 37,
|
||||
"name": "Ammo capacity",
|
||||
"grade": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "I",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Chaff Launcher",
|
||||
"name": "Chaff Launcher"
|
||||
},
|
||||
{
|
||||
"class": 0,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Frame Shift Wake Scanner"
|
||||
}
|
||||
],
|
||||
"internal": [
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Shield Generator",
|
||||
"modifications": {
|
||||
"optmul": 1888,
|
||||
"explres": 455,
|
||||
"kinres": 546,
|
||||
"thermres": 1092,
|
||||
"brokenregen": -2614,
|
||||
"regen": -876,
|
||||
"distdraw": 463
|
||||
},
|
||||
"blueprint": {
|
||||
"id": 77,
|
||||
"name": "Reinforced",
|
||||
"grade": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"class": 3,
|
||||
"rating": "A",
|
||||
"enabled": true,
|
||||
"priority": 1,
|
||||
"group": "Fuel Scoop"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
{
|
||||
"class": 2,
|
||||
"rating": "E",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Cargo Rack"
|
||||
},
|
||||
null,
|
||||
{
|
||||
"class": 1,
|
||||
"rating": "C",
|
||||
"enabled": true,
|
||||
"priority": 2,
|
||||
"group": "Scanner",
|
||||
"name": "Advanced Discovery Scanner"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"class": 1,
|
||||
"hullCost": 2481550,
|
||||
"speed": 280,
|
||||
"boost": 380,
|
||||
"boostEnergy": 10,
|
||||
"agility": 6,
|
||||
"baseShieldStrength": 200,
|
||||
"baseArmour": 80,
|
||||
"hullMass": 35,
|
||||
"masslock": 7,
|
||||
"pipSpeed": 0.05,
|
||||
"moduleCostMultiplier": 1,
|
||||
"fuelCapacity": 8,
|
||||
"cargoCapacity": 8,
|
||||
"ladenMass": 104.25,
|
||||
"armour": 144,
|
||||
"shield": 404.19,
|
||||
"shieldCells": 0,
|
||||
"totalCost": 14059860,
|
||||
"unladenMass": 88.25,
|
||||
"totalDpe": 32.25,
|
||||
"totalExplDpe": 0,
|
||||
"totalKinDpe": 9.41,
|
||||
"totalThermDpe": 22.84,
|
||||
"totalDps": 53.8,
|
||||
"totalExplDps": 0,
|
||||
"totalKinDps": 17.44,
|
||||
"totalThermDps": 36.35,
|
||||
"totalSDps": 48.99,
|
||||
"totalExplSDps": 0,
|
||||
"totalKinSDps": 12.64,
|
||||
"totalThermSDps": 36.35,
|
||||
"totalEps": 9.84,
|
||||
"totalHps": 12.28,
|
||||
"shieldExplRes": 0.48,
|
||||
"shieldKinRes": 0.55,
|
||||
"shieldThermRes": 1.09,
|
||||
"hullExplRes": 1.4,
|
||||
"hullKinRes": 1.2,
|
||||
"hullThermRes": 1,
|
||||
"powerAvailable": 17.24,
|
||||
"powerRetracted": 11.3,
|
||||
"powerDeployed": 16.41,
|
||||
"unladenRange": 25.57,
|
||||
"fullTankRange": 23.92,
|
||||
"ladenRange": 22.09,
|
||||
"unladenFastestRange": 116.23,
|
||||
"ladenFastestRange": 107,
|
||||
"maxJumpCount": 5,
|
||||
"topSpeed": 386.56,
|
||||
"topBoost": 524.62
|
||||
}
|
||||
}
|
||||
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": "A0p0tdFal8d8s8f4-----04040303430101.Iw1/kA==.Aw1/kA==.",
|
||||
"Miner": "A0p5tdFal8d8s8f42l2l---040403451q0101.Iw1/kA==.Aw1/kA==.",
|
||||
"Hopper": "A0p0tdFal8d0s8f41717---030302024300-.Iw1/kA==.Aw1/kA==."
|
||||
},
|
||||
"type_7_transport": {
|
||||
"Cargo": "A0p0tiFfliddsdf5--------0505040403480101.Iw18aQ==.Aw18aQ==.",
|
||||
"Miner": "A0pdtiFflid8sdf5--2l2l----0505041v03450000.Iw18aQ==.Aw18aQ==."
|
||||
},
|
||||
"federal_dropship": {
|
||||
"Cargo": "A0pdtiFflnddsif4-1717------05040448--020201.Iw18eQ==.Aw18eQ==."
|
||||
},
|
||||
"asp": {
|
||||
"Miner": "A2pftfFflidfskf50s0s24242l2l---04054a1q02022o27.Iw18WQ==.Aw18WQ==."
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "A0p5tiFflndisnf4--0s0s----0605450302020101.Iw18aQ==.Aw18aQ==.",
|
||||
"Dream": "A2pktkFflndpskf40v0v0s0s0404040n4k5n5d2b29292o-.AwRj4yWU1I==.CwBhCYy6YRigzLIA.",
|
||||
"Current": "A0patkFflndfskf4----------------.AwRj4yWU1I==.CwBhCYy6YRigzLIA."
|
||||
},
|
||||
"type_9_heavy": {
|
||||
"Current": "A0patsFklndnsif6---------0706054a0303020224.AwRj4yoo.EwBhEYy6dsg=."
|
||||
},
|
||||
"python": {
|
||||
"Cargo": "A0patnFflidsssf5---------050505040448020201.Iw18eQ==.Aw18eQ==.",
|
||||
"Miner": "A0pktkFflidpspf50v0v0v2m2m0404--050505Ce4a1v02022o.Iw18eQ==.IwBhBYy6dkCYg===.",
|
||||
"Dream": "A2pptkFfliduspf50v0v0v27270404040m5n5n4f2d2d032t0201.Iw1+gDBxA===.EwBhEYy6e0WEA===.",
|
||||
"Missile": "A0pttoFjljdystf52f2g2d2ePh----04044j03---002h.Iw18eQ==.Aw18eQ==."
|
||||
},
|
||||
"anaconda": {
|
||||
"Dream": "A4putpFklndzsuf52c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d04-0303326b.AwRj4yo5dyg=.MwBhCYy6duvARiA=.",
|
||||
"Cargo": "A0patnFklndnsxf5----------------06050505040404-45030301.Iw18ZVA=.Aw18ZVA=.",
|
||||
"Current": "A0patnFklndksxf5----------------06050505040404-03034524.Iw18ZVA=.Aw18ZVA=.",
|
||||
"Explorer": "A0patnFklndksxf5--------0202------f7050505040s37-2f2i4524.AwRj4yVKJ9hA.AwhMIyumQRhEA===.",
|
||||
"Test": "A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.Iw18ZVA=.Aw18ZVA=."
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Explorer": "A0p0tdFfldddsdf5---0202--320p432i2f-.AwRj4zTYg===.AwiMIyoo."
|
||||
},
|
||||
"vulture": {
|
||||
"Bounty Hunter": "A3patcFalddksff31e1e0404-0l4a-5d27662j.AwRj4z2I.MwBhBYy6oJmAjLIA."
|
||||
},
|
||||
"fer_de_lance": {
|
||||
"Attack": "A2pfthFalidpsff31r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.CwBhrSu8EZyA."
|
||||
},
|
||||
"eagle": {
|
||||
"Figther": "A4p0t5F5l3d5s5f20p0p24-4053-2j-.Iw18kA==.Aw18kA==."
|
||||
}
|
||||
}
|
||||
50
__tests__/fixtures/old-valid-export.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"builds": {
|
||||
"type_6_transporter": {
|
||||
"Cargo": "02A4D4A2D2D2D4C-----04040303430101",
|
||||
"Miner": "03A4D4A2D2D2D4C2l2l---040403451q0101",
|
||||
"Hopper": "02A4D4A2D1A2D4C1717---030302024300-"
|
||||
},
|
||||
"type_7_transport": {
|
||||
"Cargo": "02A5D5A4D3D3D5C--------0505040403480101",
|
||||
"Miner": "04D5D5A4D2D3D5C--2l2l----0505041v03450000"
|
||||
},
|
||||
"federal_dropship": {
|
||||
"Cargo": "04D5D5A5D3D4D4C-1717------05040448020201"
|
||||
},
|
||||
"asp": {
|
||||
"Miner": "25A5A5A4D4A5A5C0s0s24242l2l---04054a1q02022o27"
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "03A5D5A5D4D5D4C--0s0s----0605450302020101",
|
||||
"Dream": "26A6A5A5D6A5A4C0v0v0s0s0404040n4k5n5d2b29292o-.AwRj4yWU1I==.CwBhCYy6YRigzLIA",
|
||||
"Current": "04A6A5A5D4A5A4C----------------.AwRj4yWU1I==.CwBhCYy6YRigzLIA"
|
||||
},
|
||||
"type_9_heavy": {
|
||||
"Current": "04A7D6A5D5D4D6C---------0706054a0303020224.AwRj4yoo.EwBhEYy6dsg="
|
||||
},
|
||||
"python": {
|
||||
"Cargo": "04A6D5A4D6D6D5C---------050505040448020201.Iw18eQ==.Aw18eQ==",
|
||||
"Miner": "06A6A5A4D6A6A5C0v0v0v2m2m0404--050505Ce4a1v02022o.Iw18eQ==.IwBhBYy6dkCYg===",
|
||||
"Dream": "27A6A5A4D7A6A5C0v0v0v27270404040m5n5n4f2d2d032t0201.Iw1+gDBxA===.EwBhEYy6e0WEA==="
|
||||
},
|
||||
"anaconda": {
|
||||
"Dream": "48A7A6A5D8A8A5C2c0o0o0o1m1m0q0q0404040l0b0100004k5n5n112d2d040303326b.AwRj4yo5dig=.MwBhCYy6du3ARiA=",
|
||||
"Cargo": "04A6D6A5D5D8D5C----------------0605050504040445030301.Iw18ZlA=.Aw18ZlA=",
|
||||
"Current": "04A6D6A5D5A8D5C----------------0605050504040403034524.Iw18ZlA=.Aw18ZlA=",
|
||||
"Explorer": "04A6D6A5D5A8D5C--------0202------f7050505040s372f2i4524.AwRj4yVKJthA.AwhMIyungRhEA==="
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Explorer": "02A4D5A3D3D3D5C---0202--320p432i2f.AwRj4zTI.AwiMIypI"
|
||||
},
|
||||
"vulture": {
|
||||
"Bounty Hunter": "34A4C4A3D5A4A3C1e1e0404-0l4a5d27662j.AwRj4y2I.MwBhBYy6wJmAjLIA"
|
||||
},
|
||||
"fer_de_lance": {
|
||||
"Attack": "25A5C4A4D6A4A3C1r0s0s0s0s000404-04-4a-5d27-.Iw18aQ==.CwBhrSu8EZyA"
|
||||
},
|
||||
"eagle": {
|
||||
"Figther": "42A3A3A1D2A2A2C0p0p24-40532j.AwRj49iA.AwgsIkEZigmIA==="
|
||||
}
|
||||
}
|
||||
}
|
||||
67
__tests__/fixtures/valid-backup.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"builds": {
|
||||
"type_6_transporter": {
|
||||
"Cargo": "02A4D4A2D2D2D4C-----04040303430101",
|
||||
"Miner": "03A4D4A2D2D2D4C2l2l---040403451q0101",
|
||||
"Hopper": "02A4D4A2D1A2D4C1717---030302024300-"
|
||||
},
|
||||
"type_7_transport": {
|
||||
"Cargo": "02A5D5A4D3D3D5C--------0505040403480101",
|
||||
"Miner": "04D5D5A4D2D3D5C--2l2l----0505041v03450000"
|
||||
},
|
||||
"federal_dropship": {
|
||||
"Cargo": "04D5D5A5D3D4D4C-1717------05040448020201"
|
||||
},
|
||||
"asp": {
|
||||
"Miner": "25A5A5A4D4A5A5C0s0s24242l2l---04054a1q02022o27"
|
||||
},
|
||||
"cobra_mk_iii": {
|
||||
"Example": "24A4A4A3D3A3A4C0s0s2d2d0m0445032b2o2753.AwRj4yKA.CwBhEYyrKhmMQ==="
|
||||
},
|
||||
"imperial_clipper": {
|
||||
"Cargo": "03A5D5A5D4D5D4C--0s0s----0605450302020101",
|
||||
"Multi-purpose": "26A4A5A5D6A5A4C0v0v272704090j0h064f2c0302020101",
|
||||
"Current": "05A6D5A5D6A5A4C0v0v27270404050n4m05035d29292o01.AwRj4yrI.AwhMIyuBGNiA",
|
||||
"Dream": "26A6A5A5D6A5A4C0v0v0s0s04040c0n064f5d2b02022o0d.AwRj49UlmI==.AwiMIyuo"
|
||||
},
|
||||
"type_9_heavy": {
|
||||
"Cargo": "04A6D6A5D4D4D5C---------07064f040303010201.AwRj4yoo.EwBhEYy6dsg="
|
||||
},
|
||||
"python": {
|
||||
"Cargo": "04A6D5A4D6D6D5C---------050505044a03020201",
|
||||
"Miner": "04A6D5A4D6D6D5C---2m2m----050505044d1v02022o"
|
||||
},
|
||||
"anaconda": {
|
||||
"Dream": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404040l0b0100034k5n05050404040303326b.AwRj4yo5dig=.MwBhEYy6duwEziA=",
|
||||
"Cargo": "03A7D6A5D4D8D5C----------------060505054d040403030301.AwRj4yuqg===.Aw18ZlA=",
|
||||
"Modified": "0pyttFolodDsyf5------1717--------05044j-03----2h00.Iw18ZlA=.Aw18ZlA=.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA=="
|
||||
},
|
||||
"diamondback_explorer": {
|
||||
"Explorer": "02A4D5A3D3D3D5C-------320p432i2f.AwRj4zTI.AwiMIypI"
|
||||
}
|
||||
},
|
||||
"comparisons": {
|
||||
"Test": {
|
||||
"facets": [ 9, 6, 4, 1, 3, 2 ],
|
||||
"builds": [
|
||||
{
|
||||
"shipId": "anaconda",
|
||||
"buildName": "Dream"
|
||||
},
|
||||
{
|
||||
"shipId": "asp",
|
||||
"buildName": "Miner"
|
||||
},
|
||||
{
|
||||
"shipId": "diamondback_explorer",
|
||||
"buildName": "Explorer"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"insurance": "Beta",
|
||||
"discounts": [
|
||||
1,
|
||||
1
|
||||
]
|
||||
}
|
||||
3621
__tests__/fixtures/valid-detailed-export.json
Normal file
90
__tests__/test-agility.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import Ship from '../src/app/shipyard/Ship';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
|
||||
|
||||
describe("Agility", function() {
|
||||
|
||||
it("correctly calculates speed", function() {
|
||||
let agilityData = require('./fixtures/agility-data');
|
||||
|
||||
for (let shipId in agilityData) {
|
||||
for (let thrusterId in agilityData[shipId]) {
|
||||
const thrusterData = agilityData[shipId][thrusterId];
|
||||
let shipData = Ships[shipId];
|
||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
ship.buildWith(shipData.defaults);
|
||||
ship.use(ship.standard[1], ModuleUtils.findModule('t', thrusterId));
|
||||
|
||||
expect(Math.round(ship.topSpeed)).toBe(thrusterData.speed);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("correctly calculates boost", function() {
|
||||
let agilityData = require('./fixtures/agility-data');
|
||||
|
||||
for (let shipId in agilityData) {
|
||||
for (let thrusterId in agilityData[shipId]) {
|
||||
const thrusterData = agilityData[shipId][thrusterId];
|
||||
let shipData = Ships[shipId];
|
||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
ship.buildWith(shipData.defaults);
|
||||
// Turn off internals to ensure we have enough power to boost
|
||||
for (let internal in ship.internal) {
|
||||
ship.internal[internal].enabled = 0;
|
||||
}
|
||||
ship.use(ship.standard[1], ModuleUtils.findModule('t', thrusterId));
|
||||
|
||||
expect(Math.round(ship.topBoost)).toBe(thrusterData.boost);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("correctly calculates pitch", function() {
|
||||
let agilityData = require('./fixtures/agility-data');
|
||||
|
||||
for (let shipId in agilityData) {
|
||||
for (let thrusterId in agilityData[shipId]) {
|
||||
const thrusterData = agilityData[shipId][thrusterId];
|
||||
let shipData = Ships[shipId];
|
||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
ship.buildWith(shipData.defaults);
|
||||
ship.use(ship.standard[1], ModuleUtils.findModule('t', thrusterId));
|
||||
|
||||
expect(Math.round(ship.pitches[4] * 100) / 100).toBeCloseTo(thrusterData.pitch, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("correctly calculates roll", function() {
|
||||
let agilityData = require('./fixtures/agility-data');
|
||||
|
||||
for (let shipId in agilityData) {
|
||||
for (let thrusterId in agilityData[shipId]) {
|
||||
const thrusterData = agilityData[shipId][thrusterId];
|
||||
let shipData = Ships[shipId];
|
||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
ship.buildWith(shipData.defaults);
|
||||
ship.use(ship.standard[1], ModuleUtils.findModule('t', thrusterId));
|
||||
|
||||
expect(Math.round(ship.rolls[4] * 100) / 100).toBeCloseTo(thrusterData.roll, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("correctly calculates yaw", function() {
|
||||
let agilityData = require('./fixtures/agility-data');
|
||||
|
||||
for (let shipId in agilityData) {
|
||||
for (let thrusterId in agilityData[shipId]) {
|
||||
const thrusterData = agilityData[shipId][thrusterId];
|
||||
let shipData = Ships[shipId];
|
||||
let ship = new Ship(shipId, shipData.properties, shipData.slots);
|
||||
ship.buildWith(shipData.defaults);
|
||||
ship.use(ship.standard[1], ModuleUtils.findModule('t', thrusterId));
|
||||
|
||||
expect(Math.round(ship.yaws[4] * 100) / 100).toBeCloseTo(thrusterData.yaw, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
327
__tests__/test-import.js
Normal file
@@ -0,0 +1,327 @@
|
||||
jest.unmock('../src/app/stores/Persist');
|
||||
jest.unmock('../src/app/components/TranslatedComponent');
|
||||
jest.unmock('../src/app/components/ModalImport');
|
||||
jest.unmock('prop-types');
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
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
|
||||
delete(invalidImportData.builds.asp);
|
||||
|
||||
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 V3 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?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.&bn=Test%20My%20Ship');
|
||||
});
|
||||
|
||||
it('catches an invalid build', function() {
|
||||
const importData = require('./fixtures/anaconda-test-detailed-export-v3');
|
||||
pasteText(JSON.stringify(importData).replace('references', 'refs'));
|
||||
|
||||
expect(modal.state.importValid).toBeFalsy();
|
||||
expect(modal.state.errorMsg).toEqual('Anaconda Build "Test My Ship": Invalid data');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Detailed V4 Build', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid v4 build', function() {
|
||||
const importData = require('./fixtures/anaconda-test-detailed-export-v4');
|
||||
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?code=A4putkFklkdzsuf52c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04---0303326b.AwRj4zNLaA%3D%3D.CwBhCYzBGW9qCTSqq5xA.H4sIAAAAAAAAA2MUe8HMwPD%2FPwMAAGvB0AkAAAA%3D&bn=Test%20My%20Ship');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import Detailed Engineered V4 Build', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid v4 build', function() {
|
||||
const importData = require('./fixtures/asp-test-detailed-export-v4');
|
||||
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/asp?code=A0pftiFflfddsnf5------020202033c044002v62f2i.AwRj4yvI.CwRgDBldHnJA.H4sIAAAAAAAAA2P858DAwPCXEUhwHPvx%2F78YG5AltB7I%2F8%2F0TwImJboDSPJ%2F%2B%2Ff%2Fv%2FKlX%2F%2F%2Fi3AwMTBIfARK%2FGf%2BJwVSxArStVAYqOjvz%2F%2F%2FJVo5GRhE2IBc4SKQSSz%2FDGEmCa398P8%2F%2F2%2BgTf%2F%2FA7kMAExxqlSAAAAA&bn=Multi-purpose%20Asp%20Explorer');
|
||||
});
|
||||
|
||||
it('imports a valid v4 build with modifications', function() {
|
||||
const importData = require('./fixtures/courier-test-detailed-export-v4');
|
||||
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/imperial_courier?code=A0patzF5l0das8f31a1a270202000e402t0101-2f.AwRj4zKA.CwRgDBldLiQ%3D.H4sIAAAAAAAAA12OPUvDYBSFT1OTfkRJjUkbbC3Yj8mlODgUISAtdOlety5ODv0Vgji7O7kJ%2FgzBQX%2BEY7Gg0NKhfY%2FnHQLFDBdynufe9%2BRMCmCb06g29oCgacjiRx6gY6oWKUT8UgLaszqQfHmSnpVFN1uSeXNsJVcj%2FA2EHlZkspIUpUc6UjTXGT85qwHuSEuVc%2F16r99kDQeSSjvSbSjpyUpNK10uJJ3aYqk6smwm1lQ9bOxw71TMm8VanEqq9JW1r3Qo%2BREOLnQHvbWmb7rZIu5VLIyGQGOukPv%2F0WQk5LeEAjPOUDwtAP6bShy2HKAz0HPO%2B5KsP25I79O2I7LvD%2Bz4Il1XAQAA&bn=Multi-purpose%20Imperial%20Courier');
|
||||
});
|
||||
});
|
||||
|
||||
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 Companion API Build', function() {
|
||||
|
||||
beforeEach(reset);
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-1');
|
||||
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/federal_corvette?code=A2putsFklndzsxf50x0x7l28281919040404040402020l06p05sf63c5ifr--v66g2f.AwRj4zNaqA%3D%3D.CwRgDBldUExuBiIlUA%3D%3D.H4sIAAAAAAAAA12STy8DURTFb1szU53Ga8dg2qqqDmJDIoKFxJImumYjVrVqfAALC4lNbcUnkLCoDbEQu0bSlQVhI8JHsJBIQ73rXMkwMYuT9%2Bb87nl%2F7ovoRSL6ikD6TYNINZg5XsWUo7pfrBikr2USlRyXyDuLAhr6ZHanNLOzD5tjOiskysk5dOBvfTB7bjeRW0MNG3ohSBq1bKKxKwyLLUAjmwjpPu4wJx4xVbNI57heDfbUKUAy2xaRUQZpllHoHMHxKqjhhF4LgjtJiFHDmqbrEeVnUJOax7%2FSdRfRwBNotv9wo5kAuZMD2egKyDYcdYl1OBki6z%2BZQjaFnBPyFCM1LefF%2BcgrY0es9FKwbW8ZYj9gmBbxRVRdglMh6BNqnwsk4ouoO4HSIehNoBuBRHwR1QOmsBvHmk6IfMbd2fdCEka%2BjNSexPWGoEkcyX6CnxbxRZQtd%2BPpym%2B31xFtn0iSFPkf%2BBkttZlzB9KDFyBuFRfAGV0Ogoff8SSsCfjjD5hGWtLIwZB%2FgX5Zt%2BLHMI9My7sp6nzgZzekswTxVvCOkq%2FSXqb%2F3zfLxh6HrwIAAA%3D%3D&bn=Imported%20Federal%20Corvette');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-2');
|
||||
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/beluga?code=A0pktsFplCdpsnf70t0t2727270004040404043c4fmimlmm04mc0iv62i2f.AwRj4yukg%3D%3D%3D.CwRgDBldHi8IUA%3D%3D.H4sIAAAAAAAAA2P8Z8%2FAwPCXEUiIKTMxMPCv%2F%2Ff%2FP8cFIPGf6Z8YTEr0GjMDg%2FJWICERBOTzn%2Fn7%2F7%2FIO5Ai5n9SIEWsQEIoSxAolfbt%2F3%2BJPk4GBhE7YQYGYVmgcuVnf4Aq%2FwOVAAAyiFctbgAAAA%3D%3D&bn=Imported%20Beluga%20Liner');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-3');
|
||||
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/type_7_transport?code=A0patfFflidasdf5----0404040005050504044d2402.AwRj4yrI.CwRgDBlVK7EiA%3D%3D%3D.&bn=Imported%20Type-7%20Transporter');
|
||||
});
|
||||
|
||||
it('imports a valid companion API build', function() {
|
||||
const importData = require('./fixtures/companion-api-import-4');
|
||||
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/cobra_mk_iii?code=A0p0tdFaldd3sdf4------34---2f2i.AwRj4yKA.CwRgDMYExrezBUg%3D.&bn=Imported%20Cobra%20Mk%20III');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Import E:D Shipyard Builds', function() {
|
||||
|
||||
// it('imports a valid build', 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 + '?code=' + encodeURIComponent(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.unmock('../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-v4');
|
||||
const code = anacondaTestExport.references[0].code;
|
||||
const anaconda = Ships.anaconda;
|
||||
const validate = jsen(require('../src/schemas/ship-loadout/4'));
|
||||
|
||||
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 v4 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 v4 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');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
156
__tests__/test-ship.js
Normal file
@@ -0,0 +1,156 @@
|
||||
import Ship from '../src/app/shipyard/Ship';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
|
||||
|
||||
describe("Ship", function() {
|
||||
|
||||
it("can build all ships", function() {
|
||||
for (let s in Ships) {
|
||||
let shipData = Ships[s];
|
||||
let ship = new Ship(s, shipData.properties, shipData.slots);
|
||||
|
||||
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.cargoCapacity).toBeDefined();
|
||||
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.unladenFastestRange).toBeGreaterThan(0, s + ' unladenFastestRange');
|
||||
expect(ship.ladenFastestRange).toBeGreaterThan(0, s + ' ladenFastestRange');
|
||||
expect(ship.shield).toBeGreaterThan(0, s + ' shield');
|
||||
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 = 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 = {
|
||||
standard:['4A', '4A', '4A', '3D', '3A', '3A', '4C'],
|
||||
hardpoints: ['0s', '0s', '2d', '2d', 0, '04'],
|
||||
internal: ['45', '03', '2b', '2o', '27', '53']
|
||||
};
|
||||
|
||||
shipA.buildWith(buildA); // Build A
|
||||
shipB.buildWith(buildB);// Build B
|
||||
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 = 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.1;
|
||||
|
||||
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.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(0, 0); // No discount, 100% of cost
|
||||
|
||||
expect(testShip.m.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
|
||||
expect(testShip.totalCost).toEqual(originalTotalCost, 'Total cost does not match');
|
||||
|
||||
testShip.applyDiscounts(discount, 0); // Only discount hull
|
||||
|
||||
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 = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
expect(anaconda.internal[2].m.grp).toEqual('sg', 'Anaconda default shield generator slot');
|
||||
|
||||
anaconda.use(anaconda.internal[1], ModuleUtils.internal('4j')); // 6E Shield Generator
|
||||
|
||||
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 = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
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], ModuleUtils.internal('32'));
|
||||
|
||||
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 = Ships[id];
|
||||
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
|
||||
anaconda.buildWith(anacondaData.defaults);
|
||||
|
||||
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], ModuleUtils.internal('23'));
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
});
|
||||
25
__tests__/testUtils.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const TestUtils = {
|
||||
createContextProvider: function(context) {
|
||||
var _contextTypes = {};
|
||||
|
||||
Object.keys(context).forEach(function(key) {
|
||||
_contextTypes[key] = 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 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">
|
||||
<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 Shipyard was created for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments.
|
||||
</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>
|
||||
@@ -1,91 +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', 'shipPurpose', 'shipSize', 'hardPointClass', 'GroupMap', 'Persist',
|
||||
function($rootScope, $location, $window, $doc, $state, CArr, shipPurpose, sz, hpc, GroupMap, Persist) {
|
||||
// App is running as a standalone web app on tablet/mobile
|
||||
var isStandAlone = $window.navigator.standalone || ($window.external && $window.external.msIsSiteMode && $window.external.msIsSiteMode());
|
||||
|
||||
// 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.SP = shipPurpose;
|
||||
$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.035 }] };
|
||||
$rootScope.discounts = { opts: [{ name: 'None', pct: 1 }, { name: 'Founders World - 10%', pct: 0.90 }] };
|
||||
$rootScope.STATUS = ['', 'DISABLED', 'OFF', 'ON'];
|
||||
$rootScope.STATUS_CLASS = ['', 'disabled', 'warning', 'secondary-disabled'];
|
||||
$rootScope.title = 'Coriolis';
|
||||
|
||||
$rootScope.cName = function(c) {
|
||||
return c.c ? c.c.name ? c.c.name : GroupMap[c.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 }, 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,18 +0,0 @@
|
||||
angular.module('app').controller('ExportController', ['$scope', '$stateParams', function($scope, $stateParams) {
|
||||
|
||||
$scope.title = $stateParams.title || 'Export';
|
||||
|
||||
if ($stateParams.promise) {
|
||||
$scope.export = 'Generating...';
|
||||
$stateParams.promise.then(function(data) {
|
||||
$scope.export = data;
|
||||
});
|
||||
} else {
|
||||
$scope.export = angular.toJson($stateParams.data, true);
|
||||
}
|
||||
|
||||
$scope.onTextClick = function($event) {
|
||||
$event.target.select();
|
||||
};
|
||||
|
||||
}]);
|
||||
@@ -1,101 +0,0 @@
|
||||
angular.module('app').controller('ImportController', ['$scope', '$stateParams', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function($scope, $stateParams, Ships, Ship, Persist, Serializer) {
|
||||
$scope.jsonValid = false;
|
||||
$scope.importData = null;
|
||||
$scope.errorMsg = null;
|
||||
$scope.canEdit = true;
|
||||
$scope.builds = $stateParams.obj || null;
|
||||
$scope.ships = Ships;
|
||||
|
||||
$scope.validateJson = function() {
|
||||
var importObj = null;
|
||||
$scope.jsonValid = false;
|
||||
$scope.errorMsg = null;
|
||||
$scope.builds = null;
|
||||
|
||||
if (!$scope.importData) { return; }
|
||||
|
||||
try {
|
||||
importObj = angular.fromJson($scope.importData);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = 'Cannot Parse JSON!';
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof importObj != 'object') {
|
||||
$scope.errorMsg = 'Must be an object!';
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!importObj.builds || !Object.keys(importObj.builds).length)) {
|
||||
$scope.errorMsg = 'No builds in data';
|
||||
return;
|
||||
}
|
||||
|
||||
for (var shipId in importObj.builds) {
|
||||
var shipData = Ships[shipId];
|
||||
if (shipData) {
|
||||
for (var buildName in importObj.builds[shipId]) {
|
||||
if (typeof importObj.builds[shipId][buildName] != 'string') {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" must be a string!';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Actually build the ship with the code to ensure it's valid
|
||||
Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), importObj.builds[shipId][buildName]);
|
||||
} catch (e) {
|
||||
$scope.errorMsg = shipData.properties.name + ' build "' + buildName + '" is not valid!';
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$scope.errorMsg = '"' + shipId + '"" is not a valid Ship Id!';
|
||||
return;
|
||||
}
|
||||
$scope.builds = importObj.builds;
|
||||
}
|
||||
|
||||
$scope.jsonValid = true;
|
||||
};
|
||||
|
||||
$scope.hasBuild = function(shipId, name) {
|
||||
return Persist.getBuild(shipId, name) !== null;
|
||||
};
|
||||
|
||||
$scope.process = function() {
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
$scope.processed = true;
|
||||
};
|
||||
|
||||
$scope.import = function() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
$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,267 +0,0 @@
|
||||
angular.module('app').controller('OutfitController', ['$window', '$rootScope', '$scope', '$state', '$stateParams', 'ShipsDB', 'Ship', 'Components', 'Serializer', 'Persist', 'calcTotalRange', function($window, $rootScope, $scope, $state, $p, Ships, Ship, Components, Serializer, Persist, calcTotalRange) {
|
||||
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 win = angular.element($window); // Angularized window object for event triggering
|
||||
|
||||
// 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.fuel = 0;
|
||||
$scope.pwrDesc = false;
|
||||
$scope.pwrPredicate = 'type';
|
||||
$scope.costDesc = true;
|
||||
$scope.costPredicate = 'c.cost';
|
||||
|
||||
$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'
|
||||
}
|
||||
},
|
||||
watch: $scope.fsd
|
||||
};
|
||||
|
||||
$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'
|
||||
}
|
||||
},
|
||||
watch: $scope.fsd
|
||||
};
|
||||
|
||||
/**
|
||||
* '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;
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
$scope.code = $scope.savedCode;
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
updateState();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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);
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
updateState();
|
||||
};
|
||||
|
||||
$scope.incPriority = function(c) {
|
||||
if (ship.changePriority(c, c.priority + 1)) {
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.decPriority = function(c) {
|
||||
if (ship.changePriority(c, c.priority - 1)) {
|
||||
$scope.code = Serializer.fromShip(ship);
|
||||
updateState();
|
||||
}
|
||||
};
|
||||
|
||||
$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);
|
||||
};
|
||||
|
||||
// Utilify functions
|
||||
|
||||
function updateState() {
|
||||
$state.go('outfit', { shipId: ship.id, code: $scope.code, bn: $scope.buildName }, { location: 'replace', notify: false });
|
||||
$scope.trSeries.xMax = $scope.jrSeries.xMax = ship.cargoCapacity;
|
||||
$scope.jrSeries.yMax = ship.unladenRange;
|
||||
$scope.trSeries.yMax = ship.unladenTotalRange;
|
||||
win.triggerHandler('pwrchange');
|
||||
}
|
||||
|
||||
// Hide any open menu/slot/etc if the background is clicked
|
||||
$scope.$on('close', function() {
|
||||
$scope.selectedSlot = null;
|
||||
});
|
||||
|
||||
}]);
|
||||
@@ -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,85 +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) {
|
||||
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 > 3 && o.class != prevClass && (!o.grp || o.rating != prevRating || o.mode)) {
|
||||
list.push('<br/>');
|
||||
}
|
||||
|
||||
list.push('<li class="', o.name ? 'lc' : 'c');
|
||||
|
||||
if (cid == id) {
|
||||
list.push(' active');
|
||||
}
|
||||
|
||||
list.push((o.maxmass && mass > o.maxmass) ? ' disabled"' : '" cpid="', id, '">');
|
||||
|
||||
if (o.mode) {
|
||||
list.push('<svg cpid="', id, '" class="icon lg"><use xlink:href="#mount-', o.mode, '"></use></svg> ');
|
||||
}
|
||||
|
||||
list.push(o.class, o.rating);
|
||||
|
||||
if (o.missile) {
|
||||
list.push('/' + o.missile);
|
||||
}
|
||||
|
||||
|
||||
if (o.name) {
|
||||
list.push(' ' + o.name);
|
||||
}
|
||||
|
||||
list.push('</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
|
||||
},
|
||||
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);
|
||||
list.push('</ul>');
|
||||
}
|
||||
} else {
|
||||
list.push('<ul>');
|
||||
appendGroup(list, opts, cid, mass);
|
||||
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,12 +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) {
|
||||
scope.$apply(function() {
|
||||
e.preventDefault();
|
||||
fn(scope, { $event: e });
|
||||
});
|
||||
});
|
||||
};
|
||||
}]);
|
||||
@@ -1,74 +0,0 @@
|
||||
angular.module('app').directive('shipyardHeader', ['lodash', '$rootScope', 'Persist', 'ShipsDB', function(_, $rootScope, Persist, 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());
|
||||
$rootScope.insurance.current = $rootScope.insurance.opts[insIndex != -1 ? insIndex : 0];
|
||||
$rootScope.discounts.current = $rootScope.discounts.opts[Persist.getDiscount() || 0];
|
||||
|
||||
// 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;
|
||||
$rootScope.showAbout = false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Save selected insurance option
|
||||
*/
|
||||
scope.updateInsurance = function() {
|
||||
Persist.setInsurance($rootScope.insurance.current.name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save selected discount option
|
||||
*/
|
||||
scope.updateDiscount = function() {
|
||||
Persist.setDiscount($rootScope.discounts.opts.indexOf($rootScope.discounts.current));
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
scope.about = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
scope.openedMenu = null;
|
||||
$rootScope.showAbout = true;
|
||||
};
|
||||
|
||||
$rootScope.hideAbout = function() {
|
||||
$rootScope.showAbout = false;
|
||||
};
|
||||
|
||||
scope.$watchCollection('allBuilds', function() {
|
||||
scope.buildsList = Object.keys(scope.allBuilds).sort();
|
||||
});
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -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,239 +0,0 @@
|
||||
/**
|
||||
* [description]
|
||||
*/
|
||||
angular.module('app').service('Persist', ['$window', 'lodash', function($window, _) {
|
||||
var LS_KEY_BUILDS = 'builds';
|
||||
var LS_KEY_COMPARISONS = 'comparisons';
|
||||
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, 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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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('insurance');
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist selected insurance type
|
||||
* @param {string} name Insurance type name
|
||||
*/
|
||||
this.setInsurance = function(name) {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.setItem('insurance', name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Persist selected discount
|
||||
* @param {number} val Discount value/amount
|
||||
*/
|
||||
this.setDiscount = function(val) {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.setItem('discount', val);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the saved discount
|
||||
* @return {number} val Discount value/amount
|
||||
*/
|
||||
this.getDiscount = function() {
|
||||
if (this.lsEnabled) {
|
||||
return localStorage.getItem('discount');
|
||||
}
|
||||
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,121 +0,0 @@
|
||||
/**
|
||||
* Service managing seralization and deserialization of models for use in URLs and persistene.
|
||||
*/
|
||||
angular.module('app').service('Serializer', ['lodash', function(_) {
|
||||
|
||||
/**
|
||||
* 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} code 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)));
|
||||
|
||||
// get the remaining substring / split into parts for
|
||||
// - priorities
|
||||
// - enabled/disabled
|
||||
|
||||
ship.buildWith(
|
||||
{
|
||||
bulkheads: code.charAt(0) * 1,
|
||||
common: common,
|
||||
hardpoints: hardpoints,
|
||||
internal: internal
|
||||
},
|
||||
priorities,
|
||||
enabled
|
||||
);
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}]);
|
||||
@@ -1,68 +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 = {};
|
||||
|
||||
for (var i = 0; i < components.common.length; i++) {
|
||||
var max = maxCommonArr[i];
|
||||
switch (i) {
|
||||
// Slots where component class must be equal to slot class
|
||||
case 3: // Life Support
|
||||
case 5: // Sensors
|
||||
this.common[i] = filter(components.common[i], max, max, this.mass);
|
||||
break;
|
||||
// Other slots can have a component of class lower than the slot class
|
||||
default:
|
||||
this.common[i] = filter(components.common[i], max, 0, this.mass);
|
||||
}
|
||||
}
|
||||
|
||||
for (var h in components.hardpoints) {
|
||||
this.hardpoints[h] = filter(components.hardpoints[h], maxHardPoint, 0, this.mass);
|
||||
}
|
||||
|
||||
for (var g in components.internal) {
|
||||
this.internal[g] = filter(components.internal[g], maxInternal, 0, this.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,381 +0,0 @@
|
||||
angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', 'calcJumpRange', 'calcTotalRange', 'lodash', function(Components, calcShieldStrength, calcJumpRange, calcTotalRange, _) {
|
||||
|
||||
/**
|
||||
* 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, discount: 1 };
|
||||
|
||||
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], discount: 1 });
|
||||
}
|
||||
}
|
||||
this.c = { incCost: true, discount: 1, c: { name: this.name, cost: this.cost } }; // Make a 'Ship' component similar to other components
|
||||
|
||||
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.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.shieldMultiplier = 1;
|
||||
this.totalCost = this.cost;
|
||||
this.unladenMass = this.mass;
|
||||
this.armourTotal = this.armour;
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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.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(['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 (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
|
||||
}
|
||||
}
|
||||
var oldComponent = slot.c;
|
||||
slot.id = id;
|
||||
slot.c = component;
|
||||
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 = _.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.c.cost : -item.c.cost;
|
||||
}
|
||||
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') {
|
||||
this.updateShieldStrength();
|
||||
} else if (slot.c.grp == 'sb') {
|
||||
this.shieldMultiplier += slot.c.shieldmul * (enabled ? 1 : -1);
|
||||
this.updateShieldStrength();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (old.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][powerUsageType(slot, old)] -= old.power;
|
||||
powerChange = true;
|
||||
}
|
||||
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 't':
|
||||
this.maxMass = n.maxmass;
|
||||
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;
|
||||
}
|
||||
|
||||
if (n.power && slot.enabled) {
|
||||
this.priorityBands[slot.priority][powerUsageType(slot, n)] += n.power;
|
||||
powerChange = true;
|
||||
}
|
||||
this.unladenMass += n.mass || 0;
|
||||
}
|
||||
|
||||
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
|
||||
this.armourTotal = this.armourAdded + this.armour;
|
||||
|
||||
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.mass, this.shields, 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);
|
||||
};
|
||||
|
||||
return Ship;
|
||||
}]);
|
||||
@@ -1,224 +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('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: 'Scanners',
|
||||
am: 'Auto Field-Maint. Unit',
|
||||
cr: 'Cargo Racks',
|
||||
fi: 'FSD Interdictor',
|
||||
hb: 'Hatch Breaker Limpet Ctrl',
|
||||
hr: 'Hull Reinforcement Package',
|
||||
rf: 'Refinery',
|
||||
scb: 'Shield Cell Bank',
|
||||
sg: 'Shield Generator',
|
||||
dc: 'Docking Computer',
|
||||
fx: 'Fuel Transfer Limpet Ctrl',
|
||||
pc: 'Prospector Limpet Ctrl',
|
||||
cc: 'Collector Limpet Ctrl',
|
||||
|
||||
// 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('shipPurpose', {
|
||||
mp: 'Multi Purpose',
|
||||
fr: 'Freighter',
|
||||
ex: 'Explorer',
|
||||
co: 'Combat',
|
||||
pa: 'Passenger Transport'
|
||||
})
|
||||
.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: ['armourTotal'],
|
||||
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'
|
||||
}
|
||||
])
|
||||
/**
|
||||
* 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 = 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 left in the tank
|
||||
for (var j = 0, l = Math.floor(jumps); j < l; j++) {
|
||||
fuelRemaining += 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 (!sg) {
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
});
|
||||
@@ -1,57 +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;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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];
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.properties.mass + 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,38 +0,0 @@
|
||||
button {
|
||||
.border-radius(0);
|
||||
color: @primary;
|
||||
svg {
|
||||
fill: @primary;
|
||||
}
|
||||
border: none;
|
||||
font-family: @fStandard;
|
||||
vertical-align: middle;
|
||||
padding: 0.5em;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
outline: none;
|
||||
|
||||
&.danger {
|
||||
color: red;
|
||||
svg {
|
||||
fill: red;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
color: @disabled;
|
||||
svg {
|
||||
fill: @disabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-lbl {
|
||||
margin-left: 0.5em;
|
||||
|
||||
.smallTablet({
|
||||
display: none;
|
||||
});
|
||||
}
|
||||
@@ -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,27 +0,0 @@
|
||||
|
||||
.icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 1.1em;
|
||||
height: 1em;
|
||||
|
||||
&.sm {
|
||||
width: 0.8em;
|
||||
height: 0.75em;
|
||||
}
|
||||
|
||||
&.tn {
|
||||
width: 0.6em;
|
||||
height: 0.5em;
|
||||
}
|
||||
|
||||
&.lg {
|
||||
width: 1.6em;
|
||||
height: 1.5em;
|
||||
}
|
||||
|
||||
&.xl {
|
||||
width: 2.1em;
|
||||
height: 2em;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
.select {
|
||||
color: @primary-disabled;
|
||||
position: absolute;
|
||||
left: -1px;
|
||||
padding: 0.5em 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
z-index: 0;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
background-color: @bg;
|
||||
border: 1px solid @primary;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
|
||||
.select-group {
|
||||
line-height: 1.5em;
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
padding-left: 5px;
|
||||
border-top: 1px solid @primary-disabled;
|
||||
border-bottom: 1px solid @primary-disabled;
|
||||
}
|
||||
|
||||
.empty-c, .c, .lc {
|
||||
cursor: pointer;
|
||||
|
||||
color: @primary-disabled;
|
||||
stroke-width: 1em;
|
||||
stroke: @primary-disabled;
|
||||
|
||||
&:hover {
|
||||
color: @warning;
|
||||
stroke: @warning;
|
||||
}
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: @disabled;
|
||||
stroke: @disabled;
|
||||
}
|
||||
&.active {
|
||||
color: @secondary;
|
||||
stroke: @secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@optionSpacing: 2em;
|
||||
|
||||
.lc {
|
||||
line-height:@optionSpacing;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.empty-c {
|
||||
line-height:@optionSpacing;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.c {
|
||||
border:1px solid @primary-disabled;
|
||||
display: inline-block;
|
||||
padding: 0.1em;
|
||||
margin: 0.3em;
|
||||
width: 2em;
|
||||
line-height: @optionSpacing;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
border:1px solid @warning;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border:1px solid @disabled;
|
||||
}
|
||||
&.active {
|
||||
border:1px solid @secondary;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
min-width: 15em;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
&.hardpoint {
|
||||
.c {
|
||||
width: 4.4em;
|
||||
padding: 0.1em 0.2em;
|
||||
}
|
||||
ul {
|
||||
width: 17em;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,69 +0,0 @@
|
||||
|
||||
.slot {
|
||||
float: left;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
margin-top: 0.25em;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
padding-right: 0.4em;
|
||||
padding-left: 1.65em;
|
||||
box-sizing: border-box;
|
||||
background-color: @primary-bg;
|
||||
border: 1px solid @primary-disabled;
|
||||
color: @fg;
|
||||
fill: @fg;
|
||||
|
||||
.details {
|
||||
min-height: 2.7em;
|
||||
padding: 0.25em 0;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.cb {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.l {
|
||||
margin-right: 0.8em;
|
||||
}
|
||||
|
||||
.sz {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
font-size: 1.2em;
|
||||
width: 1.2em;
|
||||
color: @primary-disabled;
|
||||
border-right: 1px solid @primary-disabled;
|
||||
box-sizing: border-box;
|
||||
padding-top: 0.2em;
|
||||
}
|
||||
|
||||
.empty {
|
||||
font-size: 1.3em;
|
||||
color: lighten(@primary-bg, 12%);
|
||||
text-align: center;
|
||||
letter-spacing: 0.1em;
|
||||
line-height: 1.7em;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: @primary-bg;
|
||||
fill: @primary-bg;
|
||||
background-color: @primary;
|
||||
border: 1px solid @primary;
|
||||
z-index: 1;
|
||||
.sz {
|
||||
color: @primary;
|
||||
background-color: @primary-bg;
|
||||
border-right: 1px solid @primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,71 +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>
|
||||
Discount
|
||||
<li><select ng-model="discounts.current" ng-options="d.name for (i,d) in discounts.opts" ng-change="updateDiscount()"></select></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<ul>
|
||||
Builds & Comparisons
|
||||
<li><a href="#" class="block" ui-sref="modal.export({data: {builds: allBuilds}})">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">
|
||||
{{c.c.class}}{{c.c.rating}} {{c.c.name || lbl}}
|
||||
<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">Opt: {{c.c.optmass}} <u>T</u></div>
|
||||
<div class="l" ng-if="c.c.maxmass">Max: {{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>
|
||||