Compare commits

...

438 Commits

Author SHA1 Message Date
Cmdr McDonald
99c0bfcee1 Merge branch 'hotfix/2.2.10b' 2017-01-23 14:17:50 +00:00
Cmdr McDonald
37bfc700e9 Fix for direct entering of modifications 2017-01-23 14:17:42 +00:00
Cmdr McDonald
fcf0494df6 Merge branch 'release/2.10' 2017-01-23 13:05:21 +00:00
Cmdr McDonald
20ba6eb822 Tidy-ups prior to release 2017-01-23 13:05:14 +00:00
Cmdr McDonald
0e2c0349e0 Merge branch 'feature/blueprints' into develop 2017-01-22 17:16:40 +00:00
Cmdr McDonald
c49e2cff03 Lint and test fixes 2017-01-22 17:12:48 +00:00
Cmdr McDonald
d79313bfbe Fix shield boost values; add tooltips 2017-01-22 14:15:33 +00:00
Cmdr McDonald
fd404b5155 Handle heavy duty shield booster special modification value 2017-01-22 10:59:36 +00:00
Cmdr McDonald
49e72146b4 Only update relevant modification parameters 2017-01-22 09:02:32 +00:00
Cmdr McDonald
9b534b62c8 Add modification functionality 2017-01-21 10:34:08 +00:00
Cmdr McDonald
0be59af9b0 Allow selection of blueprints type and grade 2017-01-20 17:53:49 +00:00
Cmdr McDonald
029ba63aa5 Use new-style modification information 2017-01-19 22:25:13 +00:00
Cmdr McDonald
99e9e0c76f Merge branch 'feature/fixes' into develop 2017-01-15 23:06:13 +00:00
Cmdr McDonald
5bbc6e1cbe Use damage distribution numbers 2017-01-15 17:10:46 +00:00
Cmdr McDonald
1e5f66e528 Fix detailed export of module reinforcement packages 2017-01-15 17:07:12 +00:00
Cmdr McDonald
cdb837a25a Merge branch 'release/2.2.9' into develop 2017-01-14 16:24:18 +00:00
Cmdr McDonald
dd1175abf4 Merge branch 'release/2.2.9' 2017-01-14 16:24:09 +00:00
Cmdr McDonald
619976230d Bump version 2017-01-14 16:24:04 +00:00
Cmdr McDonald
2cb0d5209b Merge branch 'feature/falloff' into develop 2017-01-14 16:23:12 +00:00
Cmdr McDonald
ad06e23afa Add total DPS and effectiveness information to 'Damage Dealt' section 2017-01-14 16:20:48 +00:00
Cmdr McDonald
3def84e435 Use better DPE calculation methodology 2017-01-14 13:15:15 +00:00
Cmdr McDonald
7f377d6345 Add and use range when calculating weapon effectiveness for damage dealt 2017-01-14 13:10:09 +00:00
Cmdr McDonald
53137e0ae1 Add falloff for weapons 2017-01-14 09:52:31 +00:00
Cmdr McDonald
792eda2572 Use SSL-enabled server for shortlinks 2017-01-13 20:05:45 +00:00
Cmdr McDonald
550c94fa94 Merge branch 'release/2.2.8' into develop 2017-01-13 11:42:36 +00:00
Cmdr McDonald
2a841281d4 Merge branch 'release/2.2.8' 2017-01-13 11:42:31 +00:00
Cmdr McDonald
260f29834a Update release notes 2017-01-13 11:35:01 +00:00
Cmdr McDonald
ddb35d321c Fix issue where filling all internals with cargo racks would include restricted slots 2017-01-13 11:34:18 +00:00
Cmdr McDonald
6017c1ecff Merge branch 'release/2.2.7' into develop 2017-01-11 21:59:09 +00:00
Cmdr McDonald
05e06f30f5 Merge branch 'release/2.2.7' 2017-01-11 21:59:01 +00:00
Cmdr McDonald
fb5ba6a0b2 Update damage dealt to use actual resistances 2017-01-11 21:57:49 +00:00
Cmdr McDonald
80656a7a78 Fix resistance diminishing return calculations 2017-01-11 21:33:31 +00:00
Cmdr McDonald
ce980cf091 Merge branch 'release/2.2.6' into develop 2017-01-10 19:34:18 +00:00
Cmdr McDonald
a4656e223a Merge branch 'release/2.2.6' 2017-01-10 19:34:10 +00:00
Cmdr McDonald
66d4b5ac4c Fix tests due to new module values 2017-01-10 19:30:43 +00:00
Cmdr McDonald
6961469ae5 Merge branch 'feature/changes' into develop 2017-01-10 19:15:56 +00:00
Cmdr McDonald
06f4abdf8b Import builds with military slots 2017-01-10 19:12:19 +00:00
Cmdr McDonald
7855d0e171 Reinstate jump range graph 2017-01-02 12:06:44 +00:00
Cmdr McDonald
40f213c883 Do not lose ship selector selection on narrow screens 2017-01-02 12:05:55 +00:00
Cmdr McDonald
be1bfeb6f3 Ensure that information is not lost on narrow screens. Fix for #48 2017-01-02 12:05:22 +00:00
Cmdr McDonald
b40a2e96e0 Fix for change to military slots 2016-12-24 23:49:33 +00:00
Cmdr McDonald
5f036c586c Use own URL shortener 2016-12-24 21:57:11 +00:00
Cmdr McDonald
091789c819 Revert overloading of 'reload' translation key 2016-12-24 20:57:51 +00:00
Cmdr McDonald
0ce8bfac79 Fixes for #46 2016-12-24 20:56:37 +00:00
Cmdr McDonald
e53ffd0273 Update shield recovery/regeneration calculations 2016-12-20 13:58:00 +00:00
Cmdr McDonald
bb7db144d6 Allow collapse/expand of damage sections 2016-12-19 21:50:53 +00:00
Cmdr McDonald
2e42a328e0 Add base resistances to defence summary tooltip 2016-12-19 17:56:54 +00:00
Cmdr McDonald
f82122f29f Add module copy functionality - drag module whilst holding 'alt' to copy 2016-12-18 21:37:21 +00:00
Cmdr McDonald
5bf907809d Make weapons real modules to benefits from standard DPS etc. calculations 2016-12-18 21:26:30 +00:00
Cmdr McDonald
51d7b6c9aa Add 'Piercing' information to hardpoints; add 'Hardness' information to ship summary 2016-12-18 09:36:33 +00:00
Cmdr McDonald
b8cff0c2fc Add 'Damage received' section 2016-12-17 10:46:52 +00:00
Cmdr McDonald
6ac69a6388 Add translation 2016-12-16 21:16:17 +00:00
Cmdr McDonald
32282141cf Use ship rather than ship ID 2016-12-16 21:09:11 +00:00
Cmdr McDonald
059c2badf4 Lint 2016-12-16 20:38:58 +00:00
Cmdr McDonald
fb090618da Add 'Damage dealt' section 2016-12-16 20:37:06 +00:00
Cmdr McDonald
9ed0e30538 Add hardness to shipyard 2016-12-16 16:25:57 +00:00
Cmdr McDonald
af82b8ca1e Fix up tests 2016-12-15 16:46:38 +00:00
Cmdr McDonald
6e18793d82 Lint fix 2016-12-14 22:41:10 +00:00
Cmdr McDonald
22e74164c5 Alternate (embedded) code versioning scheme; start to fix up tests 2016-12-14 22:38:21 +00:00
Cmdr McDonald
93ba1bf67a Do not include disabled shield boosters in calculations 2016-12-14 17:39:01 +00:00
Cmdr McDonald
46ed9003dd Tidy-ups 2016-12-14 13:31:20 +00:00
Cmdr McDonald
5603315bf0 Version URLs to handle changes to ship specifications over time 2016-12-14 13:23:54 +00:00
Cmdr McDonald
5bbc6be3d8 Obey restricted slot rules when adding all for internal slots 2016-12-14 13:23:19 +00:00
Cmdr McDonald
203e9c7b46 Fix for importing definitions with missing slots 2016-12-14 08:49:23 +00:00
Cmdr McDonald
2a6850ded0 Set initial shield boost correctly 2016-12-13 22:08:49 +00:00
Cmdr McDonald
041f873f97 Updates 2016-12-13 18:56:59 +00:00
Cmdr McDonald
b944035541 Use separate speed/rotation/acceleration multipliers for thrusters if available 2016-12-12 13:37:36 +00:00
Cmdr McDonald
7c6a4fc5f8 Do not rely on coriolis-data' internal ordering of modules for display purposes 2016-12-12 10:38:50 +00:00
Cmdr McDonald
5426b55637 Ensure module ordering is consistent 2016-12-12 10:28:54 +00:00
Cmdr McDonald
a6a10df39c Add movement summary; add standard internal class sizes to shipyard page; fix issue when importing Viper Mk IV 2016-12-11 21:52:49 +00:00
Cmdr McDonald
0dc58bad7e Beta version 2016-12-03 15:52:17 +00:00
Cmdr McDonald
794faacbd4 Merge branch 'release/2.2.5' into develop 2016-12-03 15:48:50 +00:00
Cmdr McDonald
0a37b36ec2 Merge branch 'release/2.2.5' 2016-12-03 15:48:45 +00:00
Cmdr McDonald
85e6796e88 Bump version 2016-12-03 15:48:39 +00:00
Cmdr McDonald
fa1ef47b71 Add note to disable ghostery in error situations 2016-12-01 13:26:33 +00:00
Cmdr McDonald
f31e3c09f4 Merge branch 'feature/rebalance' into develop 2016-12-01 10:28:21 +00:00
Cmdr McDonald
e6ab536601 Merge branch 'feature/rebalance' of https://github.com/EDCD/coriolis into feature/rebalance 2016-12-01 10:28:08 +00:00
Cmdr McDonald
5bced9fe56 Bump version number 2016-11-30 15:09:25 +00:00
Cmdr McDonald
67742060d3 Merge branch 'feature/burst' into develop 2016-11-30 15:09:04 +00:00
Cmdr McDonald
ca2136544c Handle unmodifiable values 2016-11-30 15:08:32 +00:00
Cmdr McDonald
ee19e9af50 Lint 2016-11-30 14:56:33 +00:00
Cmdr McDonald
f457fd0bff Fixes for burst calculations 2016-11-30 14:51:19 +00:00
Cmdr McDonald
c1ce07e039 Calculate rate of fire for multi-burst weapons 2016-11-30 12:19:40 +00:00
Cmdr McDonald
c8d1536f77 Bump version number 2016-11-29 13:53:23 +00:00
Cmdr McDonald
231ad4af59 Merge branch 'release/2.2.4' into develop 2016-11-28 16:54:35 +00:00
Cmdr McDonald
d5f61d7ae8 Merge branch 'release/2.2.4' 2016-11-28 16:54:32 +00:00
Cmdr McDonald
8a5d4a36bf Bumped revision 2016-11-28 16:51:24 +00:00
Cmdr McDonald
2c9237626d Show specials; handle import of specials 2016-11-27 19:43:43 +00:00
Cmdr McDonald
37f889e317 Merge branch 'feature/incendiary' into develop 2016-11-26 23:24:37 +00:00
Cmdr McDonald
f86ba48295 Fix tests 2016-11-26 18:58:29 +00:00
Cmdr McDonald
aac35633a3 Merge branch 'feature/incendiary' of https://github.com/EDCD/coriolis into feature/incendiary 2016-11-26 18:56:57 +00:00
Cmdr McDonald
e73e0a305d Use new-style modification data 2016-11-26 18:54:22 +00:00
Cmdr McDonald
4b2b0efe37 Allow non-numeric modifiers 2016-11-26 18:54:22 +00:00
Cmdr McDonald
8fe20f6f65 Checkpoint - handle non-numeric modifiers 2016-11-26 18:54:22 +00:00
Cmdr McDonald
11af7f567a Move to method for damage type to allow for modifications 2016-11-26 18:54:22 +00:00
Cmdr McDonald
3b8444482f Add URL shortlink for outfitting page 2016-11-26 18:53:47 +00:00
Cmdr McDonald
c09e1b1b3e Merge branch 'feature/incendiary' of https://github.com/EDCD/coriolis into feature/incendiary 2016-11-26 13:16:38 +00:00
Cmdr McDonald
5770cf8d39 Use new-style modification data 2016-11-26 13:15:43 +00:00
Cmdr McDonald
6da09f2e5d Allow non-numeric modifiers 2016-11-26 13:15:43 +00:00
Cmdr McDonald
294fadf7cd Checkpoint - handle non-numeric modifiers 2016-11-26 13:15:43 +00:00
Cmdr McDonald
2a97678574 Move to method for damage type to allow for modifications 2016-11-26 13:15:43 +00:00
Cmdr McDonald
76b3bd34f5 Use new-style modification data 2016-11-26 12:54:22 +00:00
Cmdr McDonald
02bfecb92d Allow non-numeric modifiers 2016-11-24 22:23:14 +00:00
Cmdr McDonald
719759ad56 Merge branch 'release/2.2.3' into develop 2016-11-24 14:37:43 +00:00
Cmdr McDonald
fd446b29ba Merge branch 'release/2.2.3' 2016-11-24 14:37:39 +00:00
Cmdr McDonald
e5552d3e10 Updates ready for release 2016-11-24 13:49:37 +00:00
Cmdr McDonald
50946eeeb8 Fix misnamed diamondbacks - issue #36 2016-11-24 13:19:14 +00:00
Cmdr McDonald
faab41117c Checkpoint - handle non-numeric modifiers 2016-11-24 12:50:33 +00:00
Cmdr McDonald
0ab59c1f9a Handle import of restricted slots - fix for #35 2016-11-24 11:10:41 +00:00
Cmdr McDonald
1067dceaa3 Move to method for damage type to allow for modifications 2016-11-23 13:02:23 +00:00
Cmdr McDonald
9042de422a patch 2016-11-23 01:05:13 +00:00
Cmdr McDonald
f0547feb93 Merge branch 'feature/blueprints' into develop 2016-11-23 00:56:19 +00:00
Cmdr McDonald
f863daa347 Fix hull boost calculation. Partial fix for #29 2016-11-23 00:54:42 +00:00
Cmdr McDonald
fdb202e7d6 Add blueprints 2016-11-22 15:52:31 +00:00
Cmdr McDonald
c6bde19052 Merge branch 'release/2.2.2' into develop 2016-11-21 16:44:19 +00:00
Cmdr McDonald
f6aff3d3bb Merge branch 'release/2.2.2' 2016-11-21 16:44:15 +00:00
Cmdr McDonald
2f4a2ebe03 Bumped release 2016-11-21 16:42:17 +00:00
Cmdr McDonald
ca20e94b93 Merge branch 'feature/res' into develop 2016-11-21 16:39:25 +00:00
Cmdr McDonald
40a87dceeb Update tooltip to match reality 2016-11-21 11:34:45 +00:00
Cmdr McDonald
95b7d60be4 Fix URL strings for query parameter method 2016-11-21 11:33:34 +00:00
Cmdr McDonald
24abd6583f Remove requirement for double encoding 2016-11-21 10:14:16 +00:00
Cmdr McDonald
8857aba53f Use query parameters rather than long path 2016-11-21 10:06:14 +00:00
Cmdr McDonald
e4830811b0 Fix up jitter 2016-11-17 14:23:40 +00:00
Cmdr McDonald
143380ac58 Tidy-ups 2016-11-16 20:58:35 +00:00
Cmdr McDonald
a2f6fb6ac0 Added help tooltip for modifications 2016-11-16 20:49:22 +00:00
Cmdr McDonald
0d3c128059 Lints and tests 2016-11-15 13:38:02 +00:00
Cmdr McDonald
930a555425 Update costs for reload 2016-11-15 13:33:59 +00:00
Cmdr McDonald
d6f213fbe7 Remove logging 2016-11-14 23:02:56 +00:00
Cmdr McDonald
0571e8e099 Added jitter for hardpoints 2016-11-14 22:58:09 +00:00
Cmdr McDonald
54c61ecb7d Fix base armour 2016-11-14 22:18:16 +00:00
Cmdr McDonald
030867c4f8 Update test results 2016-11-14 16:47:28 +00:00
Cmdr McDonald
33a7c71fec Tweaks for restoring data from previous builds 2016-11-14 16:39:58 +00:00
Cmdr McDonald
4e0f682ad6 Use forrked browserify-zlib as it has bug fixes 2016-11-14 12:17:30 +00:00
Cmdr McDonald
4486aa2e2b Handle saved builds and old URLs 2016-11-14 11:57:39 +00:00
Cmdr McDonald
0c94c81746 Remove explicit bulkheads name from slot 2016-11-13 21:02:39 +00:00
Cmdr McDonald
5b037e3a00 Additional info if import fails 2016-11-13 17:04:57 +00:00
Cmdr McDonald
42a2b907ce Linting 2016-11-13 16:51:07 +00:00
Cmdr McDonald
a65dae1631 Various fixes; allow direct import from URL 2016-11-13 16:42:59 +00:00
Cmdr McDonald
7d4c534956 Re-enable shields for comparison 2016-11-13 13:44:00 +00:00
Cmdr McDonald
8397d3505b Rework per-module resistance calculations 2016-11-13 13:13:57 +00:00
Cmdr McDonald
9556f28ba4 Add ability to import directly from companion API output 2016-11-12 12:02:52 +00:00
Cmdr McDonald
f489257f86 Update shield cell numbers when appropriate 2016-11-11 12:30:32 +00:00
Cmdr McDonald
c96693c439 Tidy up descriptions; allow total cost to be non-integer 2016-11-11 12:19:08 +00:00
Cmdr McDonald
3d4f6d7861 Slightly friendlier modifications 2016-11-11 12:04:30 +00:00
Cmdr McDonald
606eabfec7 Fix issues with losing precision due to using decimal modification values. Validate modification information 2016-11-11 11:15:56 +00:00
Cmdr McDonald
782603727a Re-add recovery/recharge times and tweak styling 2016-11-11 00:39:14 +00:00
Cmdr McDonald
ad570534a0 Update test outputs 2016-11-11 00:21:53 +00:00
Cmdr McDonald
87e903e473 Add 'Offence summary' and 'Defence summary' components 2016-11-11 00:15:49 +00:00
Cmdr McDonald
cf6d32ea04 Enable boost display even if power distributor is disabled 2016-11-10 22:15:42 +00:00
Cmdr McDonald
5b81a0b25f Fix modification value for additive modifications 2016-11-10 15:18:05 +00:00
Cmdr McDonald
0688faac93 Added offence and defence summary 2016-11-10 00:13:56 +00:00
Cmdr McDonald
3719bb9696 Merge branch 'feature/fixes' into develop 2016-11-09 19:05:43 +00:00
Cmdr McDonald
21582d1598 Handle potentially null modifications object 2016-11-09 18:57:45 +00:00
Cmdr McDonald
9a9607fcfb Merge branch 'gienkov-pl-language' into feature/fixes 2016-11-09 16:41:19 +00:00
Cmdr McDonald
8602c5667b Merge branch 'pl-language' of https://github.com/gienkov/coriolis into gienkov-pl-language 2016-11-09 16:40:43 +00:00
Cmdr McDonald
f13a987388 Lint tidy-ups 2016-11-09 16:40:22 +00:00
Cmdr McDonald
38eaebefc0 Fix import and export of ships with modifications, bump schema version to 4 2016-11-09 16:32:11 +00:00
Cmdr McDonald
c1bc514e6b Remove swapfile 2016-11-08 09:29:32 +00:00
Cmdr McDonald
42e98fd015 Fix tooltip DPS 2016-11-08 09:25:01 +00:00
Cmdr McDonald
5f0b851de7 Take modifications in to account when deciding whether to issue a
warning on a standard module.
Fix for #16.
2016-11-08 09:05:54 +00:00
Cmdr McDonald
616ed0bf10 Show modification icon for modified modules
Fix for #14
2016-11-07 17:11:39 +00:00
Cmdr McDonald
108ab3b1ee Update DPS/HPS/EPS in real-time as modifiers change 2016-11-07 10:15:20 +00:00
Cmdr McDonald
04caef9613 Merge branch 'release/2.2.1' into develop 2016-11-05 14:39:28 +00:00
Cmdr McDonald
cae7edbe01 Merge branch 'release/2.2.1' 2016-11-05 14:39:21 +00:00
Cmdr McDonald
2fa96fc1a5 Bump version 2016-11-05 14:37:37 +00:00
Cmdr McDonald
6b8a4d1f85 Merge branch 'feature/mods' into develop 2016-11-05 14:03:24 +00:00
Cmdr McDonald
07df44a907 Allow 3dp for ship and module discounts 2016-11-05 13:59:23 +00:00
Cmdr McDonald
be45637435 Use GZIP to decrease length of modifications URL string 2016-11-05 13:43:57 +00:00
Cmdr McDonald
87ab684ba3 Use degree symbol for jitter 2016-11-04 23:58:03 +00:00
Cmdr McDonald
916a6d5e48 Show shield boost decimal place 2016-11-04 23:00:19 +00:00
Cmdr McDonald
b99fbf07f5 Fix up name of shield boost 2016-11-04 22:34:08 +00:00
Cmdr McDonald
6d6ef2a93e Provide weights to 2dp 2016-11-04 20:53:05 +00:00
Cmdr McDonald
d08e5e2858 Fixes for serialization 2016-11-04 17:13:28 +00:00
Cmdr McDonald
c1f4a8d416 Add tooltips for icons; fix import of old-style modification strings 2016-11-04 13:12:44 +00:00
Cmdr McDonald
c17c7125e3 Tidy-ups 2016-11-04 11:34:39 +00:00
Cmdr McDonald
97fc4ce45d Fixes and tidy-ups 2016-11-04 11:31:48 +00:00
Cmdr McDonald
abfc338240 Tidy-ups 2016-11-03 16:19:13 +00:00
Cmdr McDonald
3d129946ce Updates module diff details 2016-11-03 12:23:25 +00:00
Cmdr McDonald
2aab31d317 Fix typo 2016-11-03 11:33:00 +00:00
Cmdr McDonald
f8ff9a6a87 Add more fillouts 2016-11-03 11:29:41 +00:00
Cmdr McDonald
6727c2fc13 Move to pure damage/distdraw/thermload numbers 2016-11-03 10:52:54 +00:00
Cmdr McDonald
ba1f11a88b Updates for shield strength 2016-11-02 14:14:15 +00:00
Cmdr McDonald
c88e4369c8 Update to handle armour 2016-11-02 13:32:49 +00:00
Cmdr McDonald
c490f97c22 Use modifiers when calculating regen rates 2016-11-02 11:11:45 +00:00
Cmdr McDonald
7c71555384 Added facing limit and range for fsdi 2016-11-02 11:03:29 +00:00
Cmdr McDonald
35538f971a Tidy-ups 2016-11-02 10:47:10 +00:00
Cmdr McDonald
b3c82ac2de Added (non-functional) resistances 2016-11-02 10:35:55 +00:00
Cmdr McDonald
ff0d8dccea Handle bulkheads 2016-11-02 09:54:52 +00:00
Cmdr McDonald
06841b1485 Change arc to facinglimit 2016-11-01 12:22:03 +00:00
Cmdr McDonald
f55448c0a8 Ensure that fuel tank mass is displayed 2016-11-01 07:24:38 +00:00
Cmdr McDonald
258701c377 Separate modification slider in to its own component 2016-10-31 23:19:22 +00:00
Cmdr McDonald
1a0f05511b Various bug fixes 2016-10-31 21:08:15 +00:00
Cmdr McDonald
3ec9679893 Tidy up diff 2016-10-31 12:13:03 +00:00
Cmdr McDonald
e5cc3e269e Updates for modifications 2016-10-31 11:22:36 +00:00
Cmdr McDonald
4b14f617ec Changes for mods 2016-10-30 20:54:36 +00:00
Cmdr McDonald
0df051e40f Move more values to functions over direct variable access 2016-10-29 23:32:52 +01:00
Cmdr McDonald
2b464f34e5 Use react-number-editor for modifications 2016-10-29 14:14:57 +01:00
Cmdr McDonald
7a33bd64f8 Updates to modifications menu 2016-10-28 01:46:21 +01:00
Cmdr McDonald
3656c7a18f Update naming to match Elite names 2016-10-27 15:11:23 +01:00
Cmdr McDonald
3114852c63 Updates for mods UI 2016-10-27 13:26:09 +01:00
Cmdr McDonald
45337913ba Make modifications icon clickable 2016-10-25 13:36:46 +01:00
Cmdr McDonald
adc5d1c039 Only show modifications icon if the module has valid modifications. Use no more than two decimal places for modification values. 2016-10-24 18:40:12 +01:00
Cmdr McDonald
183f22c223 Updates to internal representation of modification information. Temporary power usage slider with standard modules for testing 2016-10-24 00:38:12 +01:00
Cmdr McDonald
43eb4935e6 Merge branch 'master' into develop 2016-10-22 21:03:35 +01:00
Cmdr McDonald
2c45011664 Rework modules to be individual objects rather than references to templates 2016-10-22 09:47:43 +01:00
Cmdr McDonald
f29f3f4f8f Merge branch 'release/2.2.0' into develop 2016-10-22 09:31:08 +01:00
Cmdr McDonald
c347336055 Merge branch 'release/2.2.0' 2016-10-22 09:31:05 +01:00
Cmdr McDonald
cd87184169 Apply discounts when ship updates 2016-10-17 19:30:58 +01:00
Cmdr McDonald
09895852c3 Fixes for tests 2016-10-17 15:12:05 +01:00
Cmdr McDonald
32759d3e0e Fix lint issues 2016-10-17 14:33:24 +01:00
Cmdr McDonald
965134fc02 Fix serializer for named standard modules - #2 2016-10-17 14:33:12 +01:00
Cmdr McDonald
7da5360349 Bumped release number 2016-10-16 13:50:45 +01:00
Cmdr McDonald
bf0701340c Use UTF-8 glyph for infinity rather than custom SVG 2016-10-15 09:10:40 +01:00
Cmdr McDonald
a3a490f442 Merge branch 'feature/cabins' into develop 2016-10-14 17:12:57 +01:00
Cmdr McDonald
33b22b8280 Use correct i18n formatting methods. Update note to 2.2 2016-10-14 14:53:20 +01:00
Cmdr McDonald
e6278858b9 Added drag and drop logic for special compartments 2016-10-14 12:09:54 +01:00
Cmdr McDonald
ed7a9ef037 Display new-style hardpoint information 2016-10-14 01:04:05 +01:00
Cmdr McDonald
9c42179617 Handle fighter bays and luxury passenger cabins 2016-10-12 11:48:42 +01:00
Grzegorz
5634fbd568 pl language 2016-10-10 17:47:37 +02:00
Grzegorz
7d99d59790 pl option in menu 2016-10-10 17:39:17 +02:00
Paul Heisig
5f75c9d32b final changes before coriolis.edcd.io launch 2016-10-09 20:49:29 +02:00
Jonathan Harris
fe1d16415e Update links 2016-10-09 11:35:59 +01:00
Jonathan Harris
ed8cbb403e Point badges to this fork 2016-10-09 11:24:17 +01:00
Jonathan Harris
58182bddce Pass lint 2016-10-09 11:21:06 +01:00
Jonathan Harris
771ba7e692 Remove debugging statement 2016-10-09 11:18:36 +01:00
Paul Heisig
ed0d4ddc48 making coriolis enhanced deploy ready... 2016-10-07 21:26:27 +02:00
Paul Heisig
266c63bc0c test commit 2016-10-07 19:21:01 +02:00
Colin McLeod
ebcc92f7d4 Allow external webpack hotloading 2016-06-18 19:59:29 -07:00
Colin McLeod
a1f280cf62 Allow middle click, Fixes #173 2016-06-18 19:59:09 -07:00
Colin McLeod
0306167e6e Cleanup wepback devserver output 2016-06-18 19:47:20 -07:00
Colin McLeod
162136194a Add build name to title, Fixes #171 2016-06-18 19:46:20 -07:00
Colin McLeod
3600a4862f Merge pull request #172 from w0rm49/translation-fixes
fix some typos and errors in russian translation
2016-06-15 20:19:50 -07:00
w0rm49
65fdad64b2 fix some typos and errors in russian translation 2016-06-08 16:23:10 +03:00
Colin McLeod
b49eb06101 Use IDs for standard components instead of [class][rating]. Update tests accordingly 2016-06-06 00:07:21 -07:00
Colin McLeod
eeb4a86a13 Allow 'named' standard module (special case for bulkheads) 2016-06-05 00:56:09 -07:00
Colin McLeod
3a265b2804 Update version to 2.0.0. Update react to v15 2016-06-05 00:54:35 -07:00
Colin McLeod
5ebabd6e6e Tweak string interpolation based on React v15 changes 2016-06-05 00:54:02 -07:00
Colin McLeod
6e6c337bbb Use table to align settings. Fixes #163 2016-06-05 00:52:23 -07:00
Colin McLeod
31b56354e0 Update French translations 2016-06-05 00:51:41 -07:00
Colin McLeod
fd1adbe55c Update German translations 2016-06-05 00:51:19 -07:00
Colin McLeod
3d0259c304 Fix lint issues 2016-04-04 13:02:26 -07:00
Colin McLeod
6f1b86118e Bump beta version 2016-04-04 12:52:31 -07:00
Colin McLeod
b3fcfa7808 Improve scrolling overview of shipyard page 2016-04-04 12:52:05 -07:00
Colin McLeod
4ead80a37c Improve touch detection 2016-04-04 12:51:46 -07:00
Colin McLeod
72dc73e090 Include discounts on comparison page 2016-04-04 12:31:54 -07:00
Colin McLeod
bb19dc25c0 Autofill sensor bug fix 2016-04-04 12:31:27 -07:00
Colin McLeod
1729636657 Make boost speed 0 when unable to boost 2016-04-04 12:30:18 -07:00
Colin McLeod
92809d1d24 Fix scrolling and hover issues on tablet 2016-04-04 12:29:59 -07:00
Colin McLeod
4e81c828df Fix JEST mock issue 2016-03-20 00:36:21 -07:00
Colin McLeod
f5bd7d2ecb Lint fix 2016-03-20 00:35:40 -07:00
Colin McLeod
a989bd5b5d Include migrate.html with prod build 2016-03-19 23:28:02 -07:00
Colin McLeod
1bedbb1909 Take discount into consideration for module tool tip 2016-03-19 23:27:43 -07:00
Colin McLeod
9775e1c742 Refactor footer, UI tweaks 2016-03-19 23:27:26 -07:00
Colin McLeod
19228a9c56 Change hold alt messaging 2016-03-19 23:25:42 -07:00
Colin McLeod
363bf7fd2a Shipyard page changes - in progress 2016-03-10 12:29:19 -08:00
Colin McLeod
15748066c9 Bulkhead refactoring 2016-03-10 12:29:02 -08:00
Colin McLeod
c3fe0a0cef UI Tweaks 2016-03-10 12:28:35 -08:00
Colin McLeod
1544deb350 Update tests for eagle changes 2016-03-07 09:14:48 -08:00
Colin McLeod
f060eb1b62 Fix standalone router bugs 2016-03-06 22:39:33 -08:00
Colin McLeod
32795ea678 Hide ALT text for mobile 2016-03-06 22:39:17 -08:00
Colin McLeod
d744d15132 Tweak touch module select tooltip 2016-03-06 21:33:25 -08:00
Colin McLeod
bfcef18c02 Fix Cost section discount label 2016-03-06 20:24:48 -08:00
Colin McLeod
b04c2ed2f5 Fix thruster warning bug 2016-03-06 20:24:33 -08:00
Colin McLeod
f51998b1c2 Update German, French, and Russian translations 2016-03-06 17:22:42 -08:00
Colin McLeod
d7000bfebf Update test to work with Jest 0.9.0 2016-03-06 17:22:26 -08:00
Colin McLeod
3e2b3e33fb Add localstorage migration for iframe 2016-03-04 11:15:51 -08:00
Colin McLeod
87dd52c043 Tweak and refactor build/role preset functions 2016-03-03 19:58:47 -08:00
Colin McLeod
05bc8ebb93 Fix find lightest shield generator min mass bug 2016-03-03 19:58:08 -08:00
Colin McLeod
09b945d29e tweak comments 2016-03-03 19:57:41 -08:00
Colin McLeod
67b5d749df Add can mount 2016-03-03 19:55:52 -08:00
Colin McLeod
a19fd69d0b Tweak internal slot labels 2016-03-03 19:55:04 -08:00
Colin McLeod
cfb65396ab fix max speed/boost, use lightest FSD and fuel tank 2016-03-02 10:08:16 -08:00
Colin McLeod
a4a0f96502 Add fuel tank to optimize 2016-03-02 10:07:49 -08:00
Colin McLeod
1390339024 Hull reinforcement will always clobber, fix 2016-03-02 10:07:05 -08:00
Colin McLeod
43d19f1dbb Fix phrase case 2016-03-02 10:06:41 -08:00
Colin McLeod
c20439264a Tweak GA tracking 2016-03-02 10:06:28 -08:00
Colin McLeod
61c3941618 Tweak reload on update message positioning 2016-02-29 09:35:55 -08:00
Colin McLeod
da277e4eaa Bump Beta version 2 2016-02-29 09:28:50 -08:00
Colin McLeod
51d24a1105 Fix Planetary Vehicle Hangar typo. Fixes #153 2016-02-26 09:04:47 -08:00
Colin McLeod
138931c0cf fix deploy script 2016-02-24 13:23:30 -08:00
Colin McLeod
7b3c3a1236 Correct test data 2016-02-24 12:30:35 -08:00
Colin McLeod
524b05159e Merge branch 'react' 2016-02-24 12:21:58 -08:00
Colin McLeod
e2170c9d2f Update tests and correct beta version 2016-02-24 12:13:51 -08:00
Colin McLeod
34b4690e1a Tweak module diff tooltip 2016-02-24 12:13:32 -08:00
Colin McLeod
f25152f378 Support new discounts import 2016-02-24 12:13:17 -08:00
Colin McLeod
3491d62b99 Language corrections 2016-02-24 12:13:04 -08:00
Colin McLeod
36bffe1758 Add variable discount support 2016-02-24 12:11:46 -08:00
Colin McLeod
33fd30a377 Shipyard page now scales based on font size 2016-02-24 12:10:09 -08:00
Colin McLeod
78ff84630e Facet drag improvements 2016-02-19 15:17:52 -08:00
Colin McLeod
b357573add Linting improvements 2016-02-19 15:17:40 -08:00
Colin McLeod
05e160f702 Tweaks supporting standard modules schema changes 2016-02-17 17:52:58 -08:00
Colin McLeod
9175fb60af 2.0.1 Beta 2016-02-13 22:48:48 -08:00
Colin McLeod
d783a38588 Continued porting to react 2016-02-02 09:13:59 -08:00
Colin McLeod
b42a812a45 React port nearing completetion. Adding tests 2016-01-27 00:52:57 -08:00
Colin McLeod
9af87ae88e Bump version to 1.10.4 2016-01-24 12:15:02 -08:00
Colin McLeod
a2f91cf620 Fix 146. Fix #143 2016-01-24 12:14:19 -08:00
Colin McLeod
8227a4e361 Continued porting to react, approaching beta 2016-01-21 22:06:05 -08:00
Colin McLeod
653cb30dd9 Continued porting to React 2016-01-11 18:04:38 -08:00
Colin McLeod
8e28408a8d Bumping version to 1.10.3 2015-12-26 17:42:50 -08:00
Colin McLeod
eb70eb417a Use latest data, rename vehicles to bays 2015-12-26 17:40:39 -08:00
Colin McLeod
126e8ca59b Update serialization json schema to support rating G, H 2015-12-26 17:34:26 -08:00
Colin McLeod
c81d7bf302 Bumping version to 1.10.2 2015-12-19 22:28:00 -08:00
Colin McLeod
78e85f2c6a Update data. Closes #131 2015-12-19 21:49:37 -08:00
Colin McLeod
973af84b73 Update imperial cutter boost pwoer 2015-12-18 01:20:27 -08:00
Colin McLeod
3c8b1f7d6a Adding 2.5% discount 2015-12-18 01:05:49 -08:00
Colin McLeod
62d9749660 Adding agility/maneuverability to shipyard overview 2015-12-13 12:31:06 -08:00
Colin McLeod
7db185e635 Bumping version to 1.10.0 2015-12-13 12:20:56 -08:00
Colin McLeod
e69bdac75c Add Cobra MK IV, FdL power plant update, PV Hangar 2015-12-13 12:19:22 -08:00
Colin McLeod
231f7e9267 Add planetary vechile hanger support 2015-12-13 12:19:22 -08:00
Colin McLeod
ab0019424f More refactoring and porting to React 2015-12-13 11:51:58 -08:00
Colin McLeod
2ef44e38b3 Merge pull request #123 from fawick/master
Fix typo in languages.js
2015-12-07 10:31:23 -08:00
Fabian Wickborn
d051829f98 Fix typo in languages.js 2015-12-07 19:16:00 +01:00
Colin McLeod
01e8e71b28 Updating data reference, bumping version to 1.9.4 2015-11-30 23:38:06 -08:00
Colin McLeod
14681aa9fa Update tests to include bulkheads 2015-11-30 22:56:28 -08:00
Colin McLeod
035f6b3efa More react changes 2015-11-30 22:55:53 -08:00
Colin McLeod
79224f4f9a more react changes, incomplete 2015-11-29 18:44:59 -08:00
Colin McLeod
b93572b18d Merge pull request #120 from sf302/master
Heat Sink Launcher utility auto-fill
2015-11-19 16:28:51 -08:00
Kevin Chang
41c4b4243a Remove arg overloading in useUtility 2015-11-16 16:36:15 -08:00
Kevin Chang
f5127c2475 Typo fix 2015-11-16 15:37:55 -08:00
Kevin Chang
db4303d3c8 Add Heat Sink auto-fill given new SCB heat output 2015-11-16 15:35:36 -08:00
Colin McLeod
8bc100714f Fix Viper Mk4 data. Bumping version to 1.9.3 2015-11-14 12:04:55 -08:00
Colin McLeod
fabd370f4a Update serializer test fixtures 2015-11-14 10:59:15 -08:00
Colin McLeod
769c20154d Updating Hull Reinforcement packages. Bumping to 1.9.2 2015-11-14 10:48:47 -08:00
Colin McLeod
2b5edd75cb Fix keelback boost/speed. Bump to 1.9.1 2015-11-14 10:37:38 -08:00
Colin McLeod
1b56d39356 Update tests to support latest data changes 2015-11-14 00:15:59 -08:00
Colin McLeod
8d1d6d63ad Merge pull request #119 from sf302/master
Handle new Bi-Weave Shield Generator
2015-11-13 22:38:26 -08:00
Colin McLeod
ed637addb8 Initial Commit for React 2015-11-13 17:43:45 -08:00
Kevin Chang
a713105878 Handle new Bi-Weave Shield Generator 2015-11-13 16:54:00 -08:00
Colin McLeod
c527a62ce6 Tweak loader 2015-11-12 11:27:56 -08:00
Colin McLeod
16c76b2598 Added EDDB IDs to data. Updating submodule 2015-10-27 12:00:25 -07:00
Colin McLeod
ad134330c4 Fix common -> standard for outfitting page 2015-10-27 12:00:25 -07:00
Colin McLeod
05438daf48 Merge pull request #113 from richardbuckle/fix-112
#112 lower-case 'k' in 'kg/s'
2015-10-25 18:45:33 -08:00
Richard Buckle
afebf68cae #112 lower-case 'k' in 'kg/s' 2015-10-26 01:51:52 +00:00
Colin McLeod
ab4bdf355c Fix submodule reference 2015-10-23 09:44:42 -07:00
Colin McLeod
0f4abd6ace Updating data submodule reference 2015-10-23 09:18:53 -07:00
Colin McLeod
2901c978dc Use HTTPS instead of SSH for submodule 2015-10-23 09:10:01 -07:00
Colin McLeod
21e9dbc381 Adding data through submodule 2015-10-22 20:38:28 -07:00
Colin McLeod
b2ceafa89e removing data folder 2015-10-22 20:37:14 -07:00
Colin McLeod
d8633a8411 Rename common to standard for consistency 2015-10-22 20:19:56 -07:00
Colin McLeod
f4bf09eaab fix discount minus sign placement 2015-10-22 20:19:56 -07:00
Colin McLeod
f0c40aae34 Handle erroneous data better 2015-10-22 20:19:55 -07:00
Colin McLeod
90ed8ed198 error page fix 2015-10-22 20:19:55 -07:00
Colin McLeod
9af6a529dd Adding station icons 2015-10-22 20:19:55 -07:00
Colin McLeod
269dfbdc1d Merge pull request #107 from sf302/master
Reload costs refinements
2015-10-14 00:15:43 -07:00
Kevin Chang
d01cd24b0d Updated comment to reflect changes to fuel logic 2015-10-13 15:58:44 -07:00
Kevin Chang
93ac3b217f Clean up unnecessary fuel costs logic 2015-10-13 15:56:17 -07:00
Colin McLeod
a38d6cf839 Merge pull request #109 from Toxicat/patch-1
Correct bad translation
2015-10-13 13:32:29 -07:00
PanzerKadaver
bd656b46ef Correct bad translation
Correct error reported in #108
2015-10-13 22:29:48 +02:00
Kevin Chang
20cce4dcda More logical limpet ammo display, fuel tied to slider 2015-10-12 20:54:47 -07:00
Kevin Chang
d286dda07f Refinements, limpet ammo display added to reloads 2015-10-12 19:38:33 -07:00
Colin McLeod
45b6dabcd2 Bumping version to 1.8.3 2015-10-10 11:47:46 -07:00
Colin McLeod
d476c58a9c Workaround for UI-router bug for build with slash in the name. Fixes #105 2015-10-09 18:29:04 -07:00
Colin McLeod
e837bb68fb Bumping version to 1.8.2 2015-10-09 15:48:54 -07:00
Colin McLeod
e2adc7bdc4 Tweak AFMU for explorer build 2015-10-09 15:44:10 -07:00
Colin McLeod
22716517c5 Remove A-rated build type, now redundant 2015-10-09 15:23:59 -07:00
Colin McLeod
8b82965c12 Fix section quick-fit menu z-index / overlap 2015-10-09 15:23:43 -07:00
Colin McLeod
65cf975a35 Merge pull request #104 from sf302/master
Hull reinforcement auto-fill, hardpoint clobber behavior tweak
2015-10-09 15:09:10 -07:00
Kevin Chang
1c78fea48f Fix behavior for hull reinforcement max at 5D 2015-10-08 22:51:00 -07:00
Kevin Chang
08f49c8339 Fix SCB internal clobber 2015-10-08 19:29:46 -07:00
Kevin Chang
bed81d26b2 Alter auto-fill clobbering behavior for hardpoints 2015-10-08 19:20:17 -07:00
Kevin Chang
38b13fca27 Add armor autofill, prevent internal fill clobber 2015-10-08 18:06:01 -07:00
Colin McLeod
0869230b13 Fix to standard fit all class B. Closes #103 2015-10-08 15:32:01 -07:00
Colin McLeod
80d4b6b431 fix power bug when swapping disabled components 2015-10-07 20:34:52 -07:00
Colin McLeod
fb7e9136d4 Merge pull request #102 from sf302/master
Additional auto-fill for SCB and other weapons
2015-10-07 20:25:38 -07:00
Colin McLeod
059ff367ff Price changes for 1.4 2015-10-07 20:13:21 -07:00
Kevin Chang
d322e062ad Trimming back down to just laser/MC/cannon fills 2015-10-07 20:09:51 -07:00
Kevin Chang
f807f4222f Less hacks to get the same thing done 2015-10-07 20:06:04 -07:00
Kevin Chang
1d4b046723 Tweaked to reenable slot if previously disabled 2015-10-07 19:51:36 -07:00
Kevin Chang
b9fc114e02 Additional auto-fill for SCB and other weapons 2015-10-07 19:43:39 -07:00
Colin McLeod
50047411c3 Correct Viper boost speed 2015-10-07 17:57:22 -07:00
Colin McLeod
610ded2f83 Fix ammo sorting by qty and unit price 2015-10-07 11:35:36 -07:00
Colin McLeod
2a644e787a Merge pull request #100 from sf302/master
Added new 'Reload Costs' tab for ammo, digit display cleanup
2015-10-07 11:33:05 -07:00
Colin McLeod
90b339e5c3 Correct 50% warning on power band 2015-10-07 11:32:52 -07:00
Colin McLeod
a213ad12d0 lint fix 2015-10-07 02:17:49 -07:00
Colin McLeod
a4b8b942a1 Show warning when Power priority group 1 exceeds 50%. 2015-10-07 02:16:00 -07:00
Colin McLeod
df7ef0fbdb Adding more outiftting sub section menu options 2015-10-07 02:14:45 -07:00
Colin McLeod
f42dc481df Added Outfitting section sub-menu 2015-10-06 22:49:09 -07:00
Colin McLeod
623be748c0 New and improved shipyard/home page 2015-10-06 20:06:13 -07:00
Colin McLeod
35c84ee0f0 Handle rounding erros on priority bands 2015-10-06 20:06:13 -07:00
Colin McLeod
4d84f271be Update tests for ignore auto generated property 2015-10-06 20:06:13 -07:00
Colin McLeod
5458c548fb Detailed discover scanner does not use any power 2015-10-06 20:06:12 -07:00
Colin McLeod
a9be057fe8 Readbility changes for fsd, fuel tank, and ls data 2015-10-06 20:06:12 -07:00
Colin McLeod
564c228d41 Massive refactoring to Ship class 2015-10-06 20:06:12 -07:00
Colin McLeod
3f6875abb6 Add find lightest shield generator 2015-10-06 20:06:12 -07:00
Colin McLeod
a2aa829b45 Add/impromve find compoonent functions 2015-10-06 20:06:12 -07:00
Colin McLeod
08b6ec9e31 Add size map 2015-10-06 20:06:12 -07:00
Colin McLeod
ee99d33275 Bumping version to 1.8.0 2015-10-06 20:06:12 -07:00
Colin McLeod
7b9e8dbc7d Sort ships by actual name not file name 2015-10-06 20:06:12 -07:00
Colin McLeod
44f45e7e93 Handle comparison when build is missing. Closes #96 2015-10-06 20:06:12 -07:00
Colin McLeod
a49f7ec594 Handle special characters in build or comparison name. Closes #101 2015-10-06 20:06:12 -07:00
Colin McLeod
9ee12e4167 Rename DBS file 2015-10-06 20:06:11 -07:00
Kevin Chang
33ad7d909a Fix torpedo ammo cost data 2015-10-05 20:27:22 -07:00
Kevin Chang
e5e29dc6cb Cleaned up lint errors 2015-10-05 20:15:46 -07:00
Kevin Chang
34dd40bcbf Added new 'Reload Costs' tab for ammo, digit display cleanup 2015-10-05 20:08:36 -07:00
Colin McLeod
0e8e9f5cbc Merge pull request #97 from SmokyBird/patch-1
Update fr.js
2015-10-05 16:30:00 -07:00
SmokyBird
d39cbb3ef5 Update fr.js
Finally found the full French translation for the Hull Reinforcement.
2015-10-06 00:47:07 +02:00
Colin McLeod
5470b241f6 Merge pull request #94 from koreldan/master
Minor corrections
2015-09-28 09:24:49 -07:00
enrico
6507c22355 minor corrections 2015-09-27 15:36:11 +02:00
Enrico
96c2f4b3b6 Merge pull request #1 from cmmcleod/master
updating
2015-09-27 15:26:35 +02:00
Colin McLeod
b0c521246e Bumping version to 1.7.3 2015-09-22 11:53:08 -07:00
Colin McLeod
5c0616ad47 Display clip + ammo reserve more intelligently 2015-09-22 11:52:44 -07:00
Colin McLeod
523f37ccc1 Correct Torpedo Pylon ammo reserve 2015-09-22 11:52:13 -07:00
Colin McLeod
5e2768bbf6 Correct Pack-Hound cost 2015-09-22 11:51:56 -07:00
Colin McLeod
61b3e7d47d Corrected Federal Gunship hull cost 2015-09-22 11:51:25 -07:00
Colin McLeod
ed6fc32d76 Correct Shield Cell Bank recharge values 2015-09-22 11:50:00 -07:00
Colin McLeod
4c74675edd Bumping version to 1.7.2 2015-09-22 09:27:39 -07:00
Colin McLeod
d43ee25e71 Use full name for Advanced Plasma Accelerator 2015-09-22 09:27:19 -07:00
Colin McLeod
46f00e0bc7 Lint fixes 2015-09-22 09:14:47 -07:00
Colin McLeod
d3cea71e50 Bumping version to 1.7.1 2015-09-22 09:13:43 -07:00
Colin McLeod
0516a6f54d Use calculated boost speed in comparisons. Fixes #91 2015-09-22 09:13:21 -07:00
Colin McLeod
eb8373f8b4 Line chart UI tweaks 2015-09-22 01:43:54 -07:00
Colin McLeod
202bbbd357 Use power icons for power management 2015-09-22 00:43:55 -07:00
Colin McLeod
b9e404c4da Adding italian number format support 2015-09-21 23:44:24 -07:00
Colin McLeod
e16ce83c03 Adding Spanish support 2015-09-21 23:44:05 -07:00
Colin McLeod
83c266d083 Bumping version to 1.7.0 2015-09-21 21:43:56 -07:00
Colin McLeod
349b8f436c Import/export fixture fixes for FSD Interdictor 2015-09-21 21:43:17 -07:00
Colin McLeod
e9a0a01e14 Lint fixes 2015-09-21 21:42:48 -07:00
Colin McLeod
457b8920f2 Partial Italian translation 2015-09-21 21:00:29 -07:00
Colin McLeod
31b63e9a87 en.js formatting 2015-09-21 21:00:17 -07:00
Colin McLeod
8dc3725b47 Chart UI Tweaks 2015-09-21 20:58:13 -07:00
Colin McLeod
e2096ba9f4 Display calculate boost speed 2015-09-21 20:47:59 -07:00
Colin McLeod
231fcbb3bc Calculate top boost speed 2015-09-21 20:47:31 -07:00
Colin McLeod
75c22de166 Use true base boost speeds 2015-09-21 20:45:44 -07:00
Colin McLeod
d196127392 Improve Shield Cell bank readability 2015-09-20 10:56:39 -07:00
Colin McLeod
fb4dc906aa Empty Spanish translations for now 2015-09-20 10:56:18 -07:00
Colin McLeod
9937ba8039 Merge pull request #93 from koreldan/master
added italian language
2015-09-19 22:10:06 -07:00
enrico
d92722f1c2 added italian language 2015-09-20 01:13:07 +02:00
Colin McLeod
69096d7816 Merge pull request #92 from SmokyBird/patch-1
Update fr.js
2015-09-19 14:48:55 -07:00
SmokyBird
2846827959 Update fr.js
Changed a few translations to keep the real ones, coming from the game.
2015-09-19 14:50:53 +02:00
Colin McLeod
67bd56e692 Top speed display and test tweaks 2015-09-17 22:09:30 -07:00
Colin McLeod
95f5e8e5ae Bumping version to 1.6.0 2015-09-17 01:00:38 -07:00
Colin McLeod
eb52a7548c Improve multi series tooltips for line chart 2015-09-17 01:00:10 -07:00
Colin McLeod
b479b61926 Minor bar chart UI tweak 2015-09-17 00:59:29 -07:00
Colin McLeod
726a08b05b Calculate speed based on Thrusters. Closes #16 2015-09-17 00:59:09 -07:00
Colin McLeod
fc2f76c31c Updating ships and thrusters for speed calculation support 2015-09-17 00:57:31 -07:00
Colin McLeod
839e1a5cbd Removing unused icon 2015-09-17 00:55:26 -07:00
Colin McLeod
12beeffae0 Hack to component select. Closes #89 2015-09-14 10:45:06 -07:00
Colin McLeod
83ad7d9f6c Correct price of Federal Gunship 2015-09-07 12:43:52 -07:00
332 changed files with 22303 additions and 15054 deletions

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["es2015", "react", "stage-0"]
}

61
.eslintrc Normal file
View 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
}
}

8
.gitignore vendored
View File

@@ -1,10 +1,8 @@
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

View File

@@ -3,17 +3,13 @@ notifications:
email: false
sudo: false
node_js:
- "0.12"
- "4.2.6"
cache:
directories:
- node_modules
- bower_components
before_script:
- npm install -g gulp
- npm install -g bower
- bower install
script:
- gulp lint
- gulp build-prod
- gulp test
- npm run lint
- npm test

126
ChangeLog.md Normal file
View File

@@ -0,0 +1,126 @@
#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

View File

@@ -1,6 +1,4 @@
[![Build Status](https://travis-ci.org/cmmcleod/coriolis.svg?branch=master)](https://travis-ci.org/cmmcleod/coriolis) [![Tasks in Ready](https://badge.waffle.io/cmmcleod/coriolis.png?label=ready&title=Ready)](https://waffle.io/cmmcleod/coriolis) [![Tasks in Progress](https://badge.waffle.io/cmmcleod/coriolis.svg?label=in%20progress&title=In%20Progress)](http://waffle.io/cmmcleod/coriolis)
![Latest Release](https://img.shields.io/github/release/EDCD/coriolis.svg) [![Build Status](https://travis-ci.org/EDCD/coriolis.svg?branch=master)](https://travis-ci.org/EDCD/coriolis) [![Chat to us on Discord](https://img.shields.io/badge/Discord-EDCD%20%23coriolis-blue.svg?style=social)](https://discord.gg/0uwCh6R62aPRjk9w)
## About
@@ -10,25 +8,25 @@ Coriolis was created using assets and imagery from Elite: Dangerous, with the pe
## Contributing
Please [submit issues](https://github.com/cmmcleod/coriolis/issues), or better yet [pull requests](https://github.com/cmmcleod/coriolis/pulls) 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.
### 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.
### 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 (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.

View 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}
}
}

View File

@@ -1,12 +1,13 @@
{
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/2.json#",
"name": "Test",
"$schema": "http://cdn.coriolis.io/schemas/ship-loadout/3.json#",
"name": "Test My Ship",
"ship": "Anaconda",
"references": [
{
"name": "Coriolis.io",
"url": "http://localhost:3300/outfit/anaconda/48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA%3D%3D%3D.AwhMJBGaei%2BJCyyiA%3D%3D%3D?bn=Test",
"code": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404-0l0b0100034k5n052d04--0303326b.Iw18QDBNA===.AwhMJBGaei+JCyyiA===",
"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"
}
],
@@ -245,31 +246,33 @@
"rating": "A",
"enabled": true,
"priority": 3,
"group": "FSD Interdictor"
"group": "Frame Shift Drive Interdictor"
}
]
},
"stats": {
"class": 3,
"hullCost": 141889932,
"hullCost": 141889930,
"speed": 180,
"topSpeed": 186.5,
"boost": 240,
"boostEnergy": 29,
"topBoost": 248.66,
"agility": 2,
"baseShieldStrength": 350,
"baseArmour": 945,
"hullMass": 400,
"masslock": 23,
"shipCostMultiplier": 1,
"componentCostMultiplier": 1,
"pipSpeed": 0.14,
"moduleCostMultiplier": 1,
"fuelCapacity": 32,
"cargoCapacity": 128,
"ladenMass": 1339.2,
"armour": 2078,
"armourAdded": 240,
"armour": 2228,
"armourAdded": 390,
"armourMultiplier": 1.95,
"shieldMultiplier": 1.4,
"totalCost": 882362049,
"totalCost": 882362060,
"unladenMass": 1179.2,
"totalDps": 29,
"powerAvailable": 36,
@@ -278,8 +281,8 @@
"unladenRange": 18.49,
"fullTankRange": 18.12,
"ladenRange": 16.39,
"unladenTotalRange": 73.21,
"ladenTotalRange": 66.15,
"unladenFastestRange": 73.21,
"ladenFastestRange": 66.15,
"maxJumpCount": 4,
"shieldStrength": 833
}

View File

@@ -0,0 +1,322 @@
{
"$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": 103.8,
"totalEps": 22.71,
"totalHps": 677.29,
"totalExplDpe": 0,
"totalExplDps": 0,
"totalExplSDps": 0,
"totalHps": 33.62,
"totalKinDpe": 117.48,
"totalKinDps": 24.94,
"totalKinSDps": 18.76,
"totalSDps": 91.84,
"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
}
}

View 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
}
}

File diff suppressed because it is too large Load Diff

View 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
}
}

View 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
}
}

View File

@@ -2,31 +2,31 @@
{
"shipId": "anaconda",
"buildName": "Imported Anaconda",
"buildCode": "08E7E6E5E8E8E5C------1717--------05044j-03--2h--00.Iw18ZlA=.Aw18ZlA=",
"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": "08E7E6E5E8E8E5C------1717--------05044j-03--2h--00.Iw18ZlA=.Aw18ZlA=",
"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": "04A4C4E3D2A3D4C1712222503040202490f242h.Iw1-kA==.Aw1-kA==",
"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": "35A7D6A5A4D4D5C7e2k2f2h110001020306054j03022f01242i.Iw18eQ==.Aw18eQ==",
"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": "44A5A4A3D5A4D3C1e1e0e0j04044a0n532jf1.Iw19kA==.Aw19kA==",
"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)"
}
]
]

View 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.AwRj4zTI.AwiMIypI."
},
"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==."
}
}

View File

@@ -16,7 +16,7 @@
"Miner": "25A5A5A4D4A5A5C0s0s24242l2l---04054a1q02022o27"
},
"cobra_mk_iii": {
"Example": "24A4A4A3D3A3A4C0s0s2d2d0m0445032b2o2753.AwRj4yKA.CwBhEYyrKhmMQ===",
"Example": "24A4A4A3D3A3A4C0s0s2d2d0m0445032b2o2753.AwRj4yKA.CwBhEYyrKhmMQ==="
},
"imperial_clipper": {
"Cargo": "03A5D5A5D4D5D4C--0s0s----0605450302020101",
@@ -33,7 +33,8 @@
},
"anaconda": {
"Dream": "48A6A6A5A8A8A5C2c0o0o0o1m1m0q0q0404040l0b0100034k5n05050404040303326b.AwRj4yo5dig=.MwBhEYy6duwEziA=",
"Cargo": "03A7D6A5D4D8D5C----------------060505054d040403030301.AwRj4yuqg===.Aw18ZlA="
"Cargo": "03A7D6A5D4D8D5C----------------060505054d040403030301.AwRj4yuqg===.Aw18ZlA=",
"Modified": "0pyttFolodDsyf5------1717--------05044j-03----2h00.Iw18ZlA=.Aw18ZlA=.H4sIAAAAAAAAA2MUe8HMwPD-PwDDhxeuCAAAAA=="
},
"diamondback_explorer": {
"Explorer": "02A4D5A3D3D3D5C-------320p432i2f.AwRj4zTI.AwiMIypI"
@@ -63,4 +64,4 @@
1,
1
]
}
}

View File

@@ -117,8 +117,8 @@
"unladenRange": 32.48,
"fullTankRange": 30.27,
"ladenRange": 19.61,
"unladenTotalRange": 176.71,
"ladenTotalRange": 112.92,
"unladenFastestRange": 176.71,
"ladenFastestRange": 112.92,
"maxJumpCount": 6,
"shieldStrength": 86.49
}
@@ -251,8 +251,8 @@
"unladenRange": 30.24,
"fullTankRange": 28.32,
"ladenRange": 19.8,
"unladenTotalRange": 164.89,
"ladenTotalRange": 114.03,
"unladenFastestRange": 164.89,
"ladenFastestRange": 114.03,
"maxJumpCount": 6,
"shieldStrength": 149.2
}
@@ -381,8 +381,8 @@
"unladenRange": 31.71,
"fullTankRange": 29.61,
"ladenRange": 23.58,
"unladenTotalRange": 172.68,
"ladenTotalRange": 136.46,
"unladenFastestRange": 172.68,
"ladenFastestRange": 136.46,
"maxJumpCount": 6,
"shieldStrength": 86.49
}
@@ -513,8 +513,8 @@
"unladenRange": 26.41,
"fullTankRange": 24.97,
"ladenRange": 17.36,
"unladenTotalRange": 172.04,
"ladenTotalRange": 118.55,
"unladenFastestRange": 172.04,
"ladenFastestRange": 118.55,
"maxJumpCount": 7,
"shieldStrength": 89.07
}
@@ -655,8 +655,8 @@
"unladenRange": 25.77,
"fullTankRange": 24.39,
"ladenRange": 17.98,
"unladenTotalRange": 167.93,
"ladenTotalRange": 122.84,
"unladenFastestRange": 167.93,
"ladenFastestRange": 122.84,
"maxJumpCount": 7,
"shieldStrength": 125.07
}
@@ -793,8 +793,8 @@
"unladenRange": 19.27,
"fullTankRange": 18.95,
"ladenRange": 15.43,
"unladenTotalRange": 67.34,
"ladenTotalRange": 54.75,
"unladenFastestRange": 67.34,
"ladenFastestRange": 54.75,
"maxJumpCount": 4,
"shieldStrength": 111.07
}
@@ -956,8 +956,8 @@
"unladenRange": 27.1,
"fullTankRange": 25.58,
"ladenRange": 21.94,
"unladenTotalRange": 176.39,
"ladenTotalRange": 150.58,
"unladenFastestRange": 176.39,
"ladenFastestRange": 150.58,
"maxJumpCount": 7,
"shieldStrength": 253.58
}
@@ -1098,8 +1098,8 @@
"unladenRange": 26.01,
"fullTankRange": 25.42,
"ladenRange": 17.19,
"unladenTotalRange": 90.67,
"ladenTotalRange": 61.04,
"unladenFastestRange": 90.67,
"ladenFastestRange": 61.04,
"maxJumpCount": 4,
"shieldStrength": 191.82
}
@@ -1262,8 +1262,8 @@
"unladenRange": 15.19,
"fullTankRange": 14.99,
"ladenRange": 14.99,
"unladenTotalRange": 53.15,
"ladenTotalRange": 53.15,
"unladenFastestRange": 53.15,
"ladenFastestRange": 53.15,
"maxJumpCount": 4,
"shieldStrength": 489.6
}
@@ -1362,8 +1362,8 @@
"unladenRange": 24.25,
"fullTankRange": 23.73,
"ladenRange": 23.73,
"unladenTotalRange": 84.56,
"ladenTotalRange": 84.56,
"unladenFastestRange": 84.56,
"ladenFastestRange": 84.56,
"maxJumpCount": 4,
"shieldStrength": 0
}
@@ -1501,8 +1501,8 @@
"unladenRange": 19.51,
"fullTankRange": 18.58,
"ladenRange": 13.09,
"unladenTotalRange": 152.32,
"ladenTotalRange": 106.49,
"unladenFastestRange": 152.32,
"ladenFastestRange": 106.49,
"maxJumpCount": 8,
"shieldStrength": 170.57
}
@@ -1639,8 +1639,8 @@
"unladenRange": 28.25,
"fullTankRange": 26.6,
"ladenRange": 16.67,
"unladenTotalRange": 183.67,
"ladenTotalRange": 113.69,
"unladenFastestRange": 183.67,
"ladenFastestRange": 113.69,
"maxJumpCount": 7,
"shieldStrength": 214.26
}
@@ -1810,8 +1810,8 @@
"unladenRange": 20.32,
"fullTankRange": 19.46,
"ladenRange": 14.65,
"unladenTotalRange": 133.17,
"ladenTotalRange": 99.65,
"unladenFastestRange": 133.17,
"ladenFastestRange": 99.65,
"maxJumpCount": 7,
"shieldStrength": 486.35
}
@@ -1989,8 +1989,8 @@
"unladenRange": 14.32,
"fullTankRange": 13.89,
"ladenRange": 13.46,
"unladenTotalRange": 94.42,
"ladenTotalRange": 91.49,
"unladenFastestRange": 94.42,
"ladenFastestRange": 91.49,
"maxJumpCount": 7,
"shieldStrength": 645.57
}
@@ -2188,7 +2188,7 @@
{
"class": 2,
"rating": "A",
"group": "FSD Interdictor"
"group": "Frame Shift Drive Interdictor"
}
]
},
@@ -2219,8 +2219,8 @@
"unladenRange": 16.99,
"fullTankRange": 16.68,
"ladenRange": 15.91,
"unladenTotalRange": 67.35,
"ladenTotalRange": 64.2,
"unladenFastestRange": 67.35,
"ladenFastestRange": 64.2,
"maxJumpCount": 4,
"shieldStrength": 952
}
@@ -2374,8 +2374,8 @@
"unladenRange": 39.26,
"fullTankRange": 37.65,
"ladenRange": 21.21,
"unladenTotalRange": 153.79,
"ladenTotalRange": 85.82,
"unladenFastestRange": 153.79,
"ladenFastestRange": 85.82,
"maxJumpCount": 4,
"shieldStrength": 372.98
}
@@ -2530,8 +2530,8 @@
"unladenRange": 38.44,
"fullTankRange": 36.89,
"ladenRange": 21.04,
"unladenTotalRange": 150.62,
"ladenTotalRange": 85.16,
"unladenFastestRange": 150.62,
"ladenFastestRange": 85.16,
"maxJumpCount": 4,
"shieldStrength": 372.98
}
@@ -2698,8 +2698,8 @@
"unladenRange": 38.04,
"fullTankRange": 30.11,
"ladenRange": 23.03,
"unladenTotalRange": 675.7,
"ladenTotalRange": 501.97,
"unladenFastestRange": 675.7,
"ladenFastestRange": 501.97,
"maxJumpCount": 20,
"shieldStrength": 372.98
}
@@ -2885,7 +2885,7 @@
{
"class": 2,
"rating": "A",
"group": "FSD Interdictor"
"group": "Frame Shift Drive Interdictor"
}
]
},
@@ -2916,8 +2916,8 @@
"unladenRange": 18.49,
"fullTankRange": 18.12,
"ladenRange": 16.39,
"unladenTotalRange": 73.21,
"ladenTotalRange": 66.15,
"unladenFastestRange": 73.21,
"ladenFastestRange": 66.15,
"maxJumpCount": 4,
"shieldStrength": 833
}
@@ -3044,8 +3044,8 @@
"unladenRange": 35.99,
"fullTankRange": 33.36,
"ladenRange": 33.36,
"unladenTotalRange": 232.28,
"ladenTotalRange": 232.28,
"unladenFastestRange": 232.28,
"ladenFastestRange": 232.28,
"maxJumpCount": 7,
"shieldStrength": 92.25
}
@@ -3145,7 +3145,7 @@
{
"class": 1,
"rating": "A",
"group": "FSD Interdictor"
"group": "Frame Shift Drive Interdictor"
},
{
"class": 1,
@@ -3181,8 +3181,8 @@
"unladenRange": 15.06,
"fullTankRange": 14.86,
"ladenRange": 14.86,
"unladenTotalRange": 42.5,
"ladenTotalRange": 42.5,
"unladenFastestRange": 42.5,
"ladenFastestRange": 42.5,
"maxJumpCount": 3,
"shieldStrength": 548.74
}
@@ -3335,8 +3335,8 @@
"unladenRange": 12.51,
"fullTankRange": 12.38,
"ladenRange": 12.38,
"unladenTotalRange": 35.35,
"ladenTotalRange": 35.35,
"unladenFastestRange": 35.35,
"ladenFastestRange": 35.35,
"maxJumpCount": 3,
"shieldStrength": 760.16
}
@@ -3348,8 +3348,8 @@
"references": [
{
"name": "Coriolis.io",
"url": "http://localhost:3300/outfit/eagle/42A3A3A1D2A2A2C0p0p24-40532j.AwRj49iA.AwgsIkEZigmIA%3D%3D%3D?bn=Figther",
"code": "42A3A3A1D2A2A2C0p0p24-40532j.AwRj49iA.AwgsIkEZigmIA===",
"url": "http://localhost:3300/outfit/eagle/42A3A3A1D2A2A2C0p0p24-40532j-.Iw1-EA==.Aw1-EA==?bn=Figther",
"code": "42A3A3A1D2A2A2C0p0p24-40532j-.Iw1-EA==.Aw1-EA==",
"shipId": "eagle"
}
],
@@ -3423,7 +3423,8 @@
"class": 1,
"rating": "A",
"group": "Fuel Scoop"
}
},
null
]
},
"stats": {
@@ -3453,8 +3454,8 @@
"unladenRange": 17.12,
"fullTankRange": 16.71,
"ladenRange": 16.71,
"unladenTotalRange": 42.4,
"ladenTotalRange": 42.4,
"unladenFastestRange": 42.4,
"ladenFastestRange": 42.4,
"maxJumpCount": 3,
"shieldStrength": 102
}
@@ -3611,8 +3612,8 @@
"unladenRange": 8.43,
"fullTankRange": 8.09,
"ladenRange": 7.25,
"unladenTotalRange": 81.5,
"ladenTotalRange": 72.9,
"unladenFastestRange": 81.5,
"ladenFastestRange": 72.9,
"maxJumpCount": 10,
"shieldStrength": 299.48
}

90
__tests__/test-agility.js Normal file
View 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);
}
}
});
});

301
__tests__/test-import.js Normal file
View File

@@ -0,0 +1,301 @@
jest.dontMock('../src/app/stores/Persist');
jest.dontMock('../src/app/components/TranslatedComponent');
jest.dontMock('../src/app/components/ModalImport');
import React from 'react';
import ReactDOM from 'react-dom';
import TU from 'react-testutils-additions';
import Utils from './testUtils';
import { getLanguage } from '../src/app/i18n/Language';
describe('Import Modal', function() {
let MockRouter = require('../src/app/Router').default;
const Persist = require('../src/app/stores/Persist').default;
const ModalImport = require('../src/app/components/ModalImport').default;
const mockContext = {
language: getLanguage('en'),
sizeRatio: 1,
openMenu: jest.genMockFunction(),
closeMenu: jest.genMockFunction(),
showModal: jest.genMockFunction(),
hideModal: jest.genMockFunction(),
tooltip: jest.genMockFunction(),
termtip: jest.genMockFunction(),
onWindowResize: jest.genMockFunction()
};
let modal, render, ContextProvider = Utils.createContextProvider(mockContext);
/**
* Clear saved builds, and reset React DOM
*/
function reset() {
MockRouter.go.mockClear();
Persist.deleteAll();
render = TU.renderIntoDocument(<ContextProvider><ModalImport /></ContextProvider>);
modal = TU.findRenderedComponentWithType(render, ModalImport);
}
/**
* Simulate user import text entry / paste
* @param {string} text Import text / raw data
*/
function pasteText(text) {
let textarea = TU.findRenderedDOMComponentWithTag(render, 'textarea');
TU.Simulate.change(textarea, { target: { value: text } });
}
/**
* Simulate click on Proceed button
*/
function clickProceed() {
let proceedButton = TU.findRenderedDOMComponentWithId(render, 'proceed');
TU.Simulate.click(proceedButton);
}
/**
* Simulate click on Import button
*/
function clickImport() {
let importButton = TU.findRenderedDOMComponentWithId(render, 'import');
TU.Simulate.click(importButton);
}
describe('Import Backup', function() {
beforeEach(reset);
it('imports a valid backup', function() {
let importData = require('./fixtures/valid-backup');
let importString = JSON.stringify(importData);
expect(modal.state.importValid).toEqual(false);
expect(modal.state.errorMsg).toEqual(null);
pasteText(importString);
expect(modal.state.importValid).toBe(true);
expect(modal.state.errorMsg).toEqual(null);
expect(modal.state.builds).toEqual(importData.builds);
expect(modal.state.comparisons).toEqual(importData.comparisons);
expect(modal.state.shipDiscount).toEqual(importData.discounts[0]);
expect(modal.state.moduleDiscount).toEqual(importData.discounts[1]);
expect(modal.state.insurance).toBe(importData.insurance.toLowerCase());
clickProceed();
expect(modal.state.processed).toBe(true);
expect(modal.state.errorMsg).toEqual(null);
clickImport();
expect(Persist.getBuilds()).toEqual(importData.builds);
expect(Persist.getComparisons()).toEqual(importData.comparisons);
expect(Persist.getInsurance()).toEqual(importData.insurance.toLowerCase());
expect(Persist.getShipDiscount()).toEqual(importData.discounts[0]);
expect(Persist.getModuleDiscount()).toEqual(importData.discounts[1]);
});
it('imports an old valid backup', function() {
const importData = require('./fixtures/old-valid-export');
const importStr = JSON.stringify(importData);
pasteText(importStr);
expect(modal.state.builds).toEqual(importData.builds);
expect(modal.state.importValid).toBe(true);
expect(modal.state.errorMsg).toEqual(null);
clickProceed();
expect(modal.state.processed).toBeTruthy();
clickImport();
expect(Persist.getBuilds()).toEqual(importData.builds);
});
it('catches an invalid backup', function() {
const importData = require('./fixtures/valid-backup');
let invalidImportData = Object.assign({}, importData);
//invalidImportData.builds.asp = null; // Remove Asp Miner build used in comparison
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%2FPwMcAABTINwTEgAAAA%3D%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%2FAwDFxwtofAAAAA%3D%3D&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.H4sIAAAAAAAAA12OP0tCYRjFj9fuVbvF1du9ekkT8s%2FkIg4NElyIBBd321yaGvwUQTS3N7UFfYygIT9EoyQUJA36ns47XJCWA%2B%2Fz%2Bz3Pe3ImBbDNKaqNPSBoGrL4ngfomKpFGiJ%2BLgHteR1IPjxJT5pF11uSeXNsJVcRfgdC92syWUuK0iMdKZqrjJ%2F0aoA71lJ5oKf38knWcCiptCPdhJIerdS00vlK0qktlqoj983UmqqHjQ33VsW8eazFmaTyULP2hQ4lX8LBme6g%2F6v0TTdbxJ2KhdEIaCw15MF%2FNB0L%2BS2hwEwyFM8KgP%2BqEpWWA3Qu9Z3z9kPWHzakt7Dt%2BAeD7ghSTgEAAA%3D%3D&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 v4 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.H4sIAAAAAAAAA02Svy9DURTHT1vvtfoat32eekVV9fm1kBgwSIw0YWYgBqmpMZkMBomFVfwFEoZKhBjE1qWTgegiDX%2BCQdKI1j2%2BR%2FJ4yzfnvu%2FnfO%2B979yQXiCi7xAkbRpEqsLMsRKWHNZpsSKQnppJVLAdIvc6DGiwxexMaWb7GDZHdJ%2BQaCf71Ia%2F88XsOp1EThk9bOh5P2kkahGN3qPM1wANbyOk87zNHH%2FBUs0gnWN61T9TOwfJ7EWJjMcms1lEo30Gx11BD8f1mh%2FcTkCMMvY0HZcoe4Wk5By%2BFcrrRL0N0OOlrd0Ntv57jGoc%2BH4%2F8EqHj3%2FCUXc4FicC5NFvsJBVIWeFvESlpuXSuCS5RRyLlV70z%2B4uQaw6ypSIJ6KOJDgZgFpQ60YgEU9EPQmUCkAfAj0IJOKJqC4wuYMY9rQD5CuubT0LSag8qdShxHUHoElcyWrAT4l4IsoCw65e%2BRv5BqKtC0mSJu8LH8OFT%2Bb%2BE8SZb0CcEn4AZ3TRDx5q4l1EJ%2BCP1bEM1WSaAwH%2FFkOLPoofwTo0LY8nr7O%2B37cp4yWIu4zHlHiXGfMPmat5gqMCAAA%3D&bn=Imported%20Federal%20Corvette');
});
it('imports a valid v4 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%2FwMAIrEcGGsAAAA%3D&bn=Imported%20Beluga%20Liner');
});
});
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
View File

@@ -0,0 +1,143 @@
jest.dontMock('../src/app/stores/Persist');
import React from 'react';
import ReactDOM from 'react-dom';
import TU from 'react-testutils-additions';
let origAddEventListener = window.addEventListener;
let storageListener;
let ls = {};
// Implment mock localStorage
let localStorage = {
getItem: function(key) {
return ls[key];
},
setItem: function(key, value) {
ls[key] = value;
},
removeItem: function(key) {
delete ls[key];
},
clear: function() {
ls = {};
}
}
window.addEventListener = function(eventName, listener) {
if(eventName == 'storage') {
storageListener = listener; // Keep track of latest storage listener
} else {
origAddEventListener.apply(arguments);
}
}
describe('Persist', function() {
const Persist = require('../src/app/stores/Persist').Persist;
describe('Multi tab/window', function() {
it("syncs builds", function() {
window.localStorage = localStorage;
ls = {};
let p = new Persist();
let newBuilds = {
anaconda: { test: '1234' }
};
storageListener({ key: 'builds', newValue: JSON.stringify(newBuilds) });
expect(p.getBuild('anaconda', 'test')).toBe('1234');
});
});
describe('General and Settings', function() {
it("has defaults", function() {
window.localStorage = localStorage;
ls = {};
let p = new Persist();
expect(p.getLangCode()).toBe('en');
expect(p.showTooltips()).toBe(true);
expect(p.getInsurance()).toBe('standard');
expect(p.getShipDiscount()).toBe(0);
expect(p.getModuleDiscount()).toBe(0);
expect(p.getSizeRatio()).toBe(1);
});
it("loads from localStorage correctly", function() {
window.localStorage = localStorage;
let savedData = require('./fixtures/valid-backup');
ls = {};
ls.builds = JSON.stringify(savedData.builds);
ls.NG_TRANSLATE_LANG_KEY = 'de';
ls.insurance = 'Standard';
ls.shipDiscount = 0.25;
ls.moduleDiscount = 0.15;
let p = new Persist();
expect(p.getInsurance()).toBe('standard');
expect(p.getShipDiscount()).toBe(0.25);
expect(p.getModuleDiscount()).toBe(0.15);
expect(p.getLangCode()).toEqual('de');
expect(p.getBuilds('anaconda')).toEqual(savedData.builds.anaconda);
expect(p.getBuilds('python')).toEqual(savedData.builds.python);
expect(p.getBuildsNamesFor('imperial_clipper')).toEqual(['Cargo', 'Current', 'Dream', 'Multi-purpose']);
expect(p.getBuild('type_7_transport', 'Cargo')).toEqual('02A5D5A4D3D3D5C--------0505040403480101');
});
it("uses defaults from a corrupted localStorage", function() {
window.localStorage = localStorage;
ls = {};
ls.builds = "not valid json";
ls.comparisons = "1, 3, 4";
ls.insurance = 'this insurance does not exist';
ls.shipDiscount = 'this is not a number';
ls.moduleDiscount = 10; // Way to big
let p = new Persist();
expect(p.getLangCode()).toBe('en');
expect(p.showTooltips()).toBe(true);
expect(p.getInsurance()).toBe('standard');
expect(p.getShipDiscount()).toBe(0);
expect(p.getModuleDiscount()).toBe(0);
expect(p.getBuilds()).toEqual({});
expect(p.getComparisons()).toEqual({});
});
it("works without localStorage", function() {
window.localStorage = null;
let p = new Persist();
expect(p.getLangCode()).toBe('en');
expect(p.showTooltips()).toBe(true);
expect(p.getInsurance()).toBe('standard');
expect(p.getShipDiscount()).toBe(0);
expect(p.getModuleDiscount()).toBe(0);
expect(p.getSizeRatio()).toBe(1);
p.saveBuild('anaconda', 'test', '12345');
expect(p.getBuild('anaconda', 'test')).toBe('12345');
p.deleteBuild('anaconda', 'test');
expect(p.hasBuilds()).toBe(false);
});
it("generates the backup", function() {
window.localStorage = localStorage;
let savedData = require('./fixtures/valid-backup');
ls = {};
ls.builds = JSON.stringify(savedData.builds);
ls.insurance = 'Beta';
ls.shipDiscount = 0.25;
ls.moduleDiscount = 0.15;
let p = new Persist();
let backup = p.getAll();
expect(backup.insurance).toBe('beta');
expect(backup.shipDiscount).toBe(0.25);
expect(backup.moduleDiscount).toBe(0.15);
expect(backup.builds).toEqual(savedData.builds);
expect(backup.comparisons).toEqual({});
});
});
})

View 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');
}
});
});
});

View File

@@ -1,48 +1,45 @@
describe("Ship Factory", function() {
import Ship from '../src/app/shipyard/Ship';
import { Ships } from 'coriolis-data/dist';
import * as ModuleUtils from '../src/app/shipyard/ModuleUtils';
var Ship;
var Components;
beforeEach(module('shipyard'));
beforeEach(inject(['Ship', 'Components', function (_Ship_, _Components_) {
Ship = _Ship_;
Components = _Components_;
}]));
describe("Ship", function() {
it("can build all ships", function() {
for (var s in DB.ships) {
var shipData = DB.ships[s];
var ship = new Ship(s, shipData.properties, shipData.slots);
for (let s in Ships) {
let shipData = Ships[s];
let ship = new Ship(s, shipData.properties, shipData.slots);
for (p in shipData.properties) {
for (let p in shipData.properties) {
expect(ship[p]).toEqual(shipData.properties[p], s + ' property [' + p + '] does not match when built');
}
ship.buildWith(shipData.defaults);
expect(ship.totalCost).toEqual(shipData.retailCost, s + ' retail cost does not match default build cost');
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' cargo');
expect(ship.cargoCapacity).toBeDefined();
expect(ship.priorityBands[0].retracted).toBeGreaterThan(0, s + ' priorityBands');
expect(ship.powerAvailable).toBeGreaterThan(0, s + ' powerAvailable');
expect(ship.unladenRange).toBeGreaterThan(0, s + ' unladenRange');
expect(ship.ladenRange).toBeGreaterThan(0, s + ' ladenRange');
expect(ship.fuelCapacity).toBeGreaterThan(0, s + ' fuelCapacity');
expect(ship.unladenTotalRange).toBeGreaterThan(0, s + ' unladenTotalRange');
expect(ship.ladenTotalRange).toBeGreaterThan(0, s + ' ladenTotalRange');
expect(ship.shieldStrength).toBeGreaterThan(0, s + ' shieldStrength');
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 = DB.ships[id];
var cobra = Ships[id];
var shipA = new Ship(id, cobra.properties, cobra.slots);
var shipB = new Ship(id, cobra.properties, cobra.slots);
var testShip = new Ship(id, cobra.properties, cobra.slots);
var buildA = cobra.defaults;
var buildB = {
common:['4A', '4A', '4A', '3D', '3A', '3A', '4C'],
standard:['4A', '4A', '4A', '3D', '3A', '3A', '4C'],
hardpoints: ['0s', '0s', '2d', '2d', 0, '04'],
internal: ['45', '03', '2b', '2o', '27', '53']
};
@@ -52,102 +49,108 @@ describe("Ship Factory", function() {
testShip.buildWith(buildA);
for(var p in testShip) {
if (p == 'availCS') {
continue;
}
expect(testShip[p]).toEqual(shipA[p], p + ' does not match');
}
testShip.buildWith(buildB);
for(var p in testShip) {
if (p == 'availCS') {
continue;
}
expect(testShip[p]).toEqual(shipB[p], p + ' does not match');
}
testShip.buildWith(buildA);
for(var p in testShip) {
if (p == 'availCS') {
continue;
}
expect(testShip[p]).toEqual(shipA[p], p + ' does not match');
}
});
it("discounts hull and components properly", function() {
var id = 'cobra_mk_iii';
var cobra = DB.ships[id];
var cobra = Ships[id];
var testShip = new Ship(id, cobra.properties, cobra.slots);
testShip.buildWith(cobra.defaults);
var originalHullCost = testShip.hullCost;
var originalTotalCost = testShip.totalCost;
var discount = 0.9;
var discount = 0.1;
expect(testShip.c.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
expect(testShip.m.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
testShip.applyDiscounts(discount, discount);
// Floating point errors cause miniscule decimal places which are handled in the app by rounding/formatting
expect(Math.floor(testShip.c.discountedCost)).toEqual(Math.floor(originalHullCost * discount), 'Discounted Hull cost does not match');
expect(Math.floor(testShip.totalCost)).toEqual(Math.floor(originalTotalCost * discount), 'Discounted Total cost does not match');
expect(Math.floor(testShip.m.discountedCost)).toEqual(Math.floor(originalHullCost * (1 - discount)), 'Discounted Hull cost does not match');
expect(Math.floor(testShip.totalCost)).toEqual(Math.floor(originalTotalCost * (1 - discount)), 'Discounted Total cost does not match');
testShip.applyDiscounts(1, 1); // No discount, 100% of cost
testShip.applyDiscounts(0, 0); // No discount, 100% of cost
expect(testShip.c.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
expect(testShip.m.discountedCost).toEqual(originalHullCost, 'Hull cost does not match');
expect(testShip.totalCost).toEqual(originalTotalCost, 'Total cost does not match');
testShip.applyDiscounts(discount, 1); // Only discount hull
testShip.applyDiscounts(discount, 0); // Only discount hull
expect(Math.floor(testShip.c.discountedCost)).toEqual(Math.round(originalHullCost * discount), 'Discounted Hull cost does not match');
expect(testShip.totalCost).toEqual(originalTotalCost - originalHullCost + testShip.c.discountedCost, 'Total cost does not match');
expect(Math.floor(testShip.m.discountedCost)).toEqual(Math.round(originalHullCost * (1 - discount)), 'Discounted Hull cost does not match');
expect(testShip.totalCost).toEqual(originalTotalCost - originalHullCost + testShip.m.discountedCost, 'Total cost does not match');
});
it("enforces a single shield generator", function() {
var id = 'anaconda';
var anacondaData = DB.ships[id];
var anacondaData = Ships[id];
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
anaconda.buildWith(anacondaData.defaults);
expect(anaconda.internal[2].c.grp).toEqual('sg', 'Anaconda default shield generator slot');
expect(anaconda.internal[2].m.grp).toEqual('sg', 'Anaconda default shield generator slot');
anaconda.use(anaconda.internal[1], '4j', Components.internal('4j')); // 6E Shield Generator
anaconda.use(anaconda.internal[1], ModuleUtils.internal('4j')); // 6E Shield Generator
expect(anaconda.internal[2].c).toEqual(null, 'Anaconda default shield generator slot is empty');
expect(anaconda.internal[2].id).toEqual(null, 'Anaconda default shield generator slot id is null');
expect(anaconda.internal[1].id).toEqual('4j', 'Slot 1 should have SG 4j in it');
expect(anaconda.internal[1].c.grp).toEqual('sg','Slot 1 should have SG 4j in it');
expect(anaconda.internal[2].m).toEqual(null, 'Anaconda default shield generator slot is empty');
expect(anaconda.internal[1].m.id).toEqual('4j', 'Slot 1 should have SG 4j in it');
expect(anaconda.internal[1].m.grp).toEqual('sg','Slot 1 should have SG 4j in it');
});
it("enforces a single shield fuel scoop", function() {
var id = 'anaconda';
var anacondaData = DB.ships[id];
var anacondaData = Ships[id];
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
anaconda.buildWith(anacondaData.defaults);
anaconda.use(anaconda.internal[4], '32', Components.internal('32')); // 4A Fuel Scoop
expect(anaconda.internal[4].c.grp).toEqual('fs', 'Anaconda fuel scoop slot');
anaconda.use(anaconda.internal[4], ModuleUtils.internal('32')); // 4A Fuel Scoop
expect(anaconda.internal[4].m.grp).toEqual('fs', 'Anaconda fuel scoop slot');
anaconda.use(anaconda.internal[3], '32', Components.internal('32'));
anaconda.use(anaconda.internal[3], ModuleUtils.internal('32'));
expect(anaconda.internal[4].c).toEqual(null, 'Anaconda original fuel scoop slot is empty');
expect(anaconda.internal[4].id).toEqual(null, 'Anaconda original fuel scoop slot id is null');
expect(anaconda.internal[3].id).toEqual('32', 'Slot 1 should have FS 32 in it');
expect(anaconda.internal[3].c.grp).toEqual('fs','Slot 1 should have FS 32 in it');
expect(anaconda.internal[4].m).toEqual(null, 'Anaconda original fuel scoop slot is empty');
expect(anaconda.internal[3].m.id).toEqual('32', 'Slot 1 should have FS 32 in it');
expect(anaconda.internal[3].m.grp).toEqual('fs','Slot 1 should have FS 32 in it');
});
it("enforces a single refinery", function() {
var id = 'anaconda';
var anacondaData = DB.ships[id];
var anacondaData = Ships[id];
var anaconda = new Ship(id, anacondaData.properties, anacondaData.slots);
anaconda.buildWith(anacondaData.defaults);
anaconda.use(anaconda.internal[4], '23', Components.internal('23')); // 4E Refinery
expect(anaconda.internal[4].c.grp).toEqual('rf', 'Anaconda refinery slot');
anaconda.use(anaconda.internal[4], ModuleUtils.internal('23')); // 4E Refinery
expect(anaconda.internal[4].m.grp).toEqual('rf', 'Anaconda refinery slot');
anaconda.use(anaconda.internal[3], '23', Components.internal('23'));
anaconda.use(anaconda.internal[3], ModuleUtils.internal('23'));
expect(anaconda.internal[4].c).toEqual(null, 'Anaconda original refinery slot is empty');
expect(anaconda.internal[4].id).toEqual(null, 'Anaconda original refinery slot id is null');
expect(anaconda.internal[3].id).toEqual('23', 'Slot 1 should have RF 23 in it');
expect(anaconda.internal[3].c.grp).toEqual('rf','Slot 1 should have RF 23 in it');
expect(anaconda.internal[4].m).toEqual(null, 'Anaconda original refinery slot is empty');
expect(anaconda.internal[3].m.id).toEqual('23', 'Slot 1 should have RF 23 in it');
expect(anaconda.internal[3].m.grp).toEqual('rf','Slot 1 should have RF 23 in it');
});
});

24
__tests__/testUtils.js Normal file
View File

@@ -0,0 +1,24 @@
import React from 'react';
const TestUtils = {
createContextProvider: function(context) {
var _contextTypes = {};
Object.keys(context).forEach(function(key) {
_contextTypes[key] = React.PropTypes.any;
});
return React.createClass({
displayName: 'ContextProvider',
childContextTypes: _contextTypes,
getChildContext() { return context; },
render() {
return React.Children.only(this.props.children);
}
});
}
};
export default TestUtils;

View File

@@ -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="&#xd;" horiz-adv-x="681" />
<glyph unicode=" " horiz-adv-x="557" />
<glyph unicode="&#x09;" horiz-adv-x="557" />
<glyph unicode="&#xa0;" horiz-adv-x="557" />
<glyph unicode="!" horiz-adv-x="450" d="M119 0v168h168v-168h-168zM119 416v1059h168v-1059h-168z" />
<glyph unicode="&#x22;" 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="&#x26;" 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="&#x3c;" 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="&#x3e;" 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="&#xa1;" horiz-adv-x="430" d="M109 0v1059h167v-1059h-167zM109 1321v170h167v-170h-167z" />
<glyph unicode="&#xa2;" 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="&#xa3;" 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="&#xa8;" horiz-adv-x="788" d="M111 1786v168h170v-168h-170zM479 1786v168h168v-168h-168z" />
<glyph unicode="&#xad;" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
<glyph unicode="&#xb0;" 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="&#xb4;" horiz-adv-x="436" d="M68 1786l71 285h162l-70 -285h-163z" />
<glyph unicode="&#xb6;" 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="&#xb8;" horiz-adv-x="436" d="M68 -350l71 284h162l-70 -284h-163z" />
<glyph unicode="&#xbf;" 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="&#xc0;" 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="&#xc1;" 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="&#xc2;" 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="&#xc3;" 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="&#xc4;" 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="&#xc5;" 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="&#xc6;" 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="&#xc7;" 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="&#xc8;" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM633 2056h166l69 -284h-163z" />
<glyph unicode="&#xc9;" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM633 1772l72 284h161l-69 -284h-164z" />
<glyph unicode="&#xca;" 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="&#xcb;" horiz-adv-x="1568" d="M119 0v1475h1345v-166h-1179v-488h948v-168h-948v-487h1179v-166h-1345zM500 1772v167h170v-167h-170zM868 1772v167h168v-167h-168z" />
<glyph unicode="&#xcc;" horiz-adv-x="450" d="M74 2056h166l69 -284h-164zM117 0v1475h166v-1475h-166z" />
<glyph unicode="&#xcd;" horiz-adv-x="450" d="M74 1772l71 284h162l-69 -284h-164zM117 0v1475h166v-1475h-166z" />
<glyph unicode="&#xce;" horiz-adv-x="450" d="M-25 1769l146 240h121l145 -240h-86l-119 175l-123 -175h-84zM117 0v1475h166v-1475h-166z" />
<glyph unicode="&#xcf;" horiz-adv-x="450" d="M-59 1772v167h170v-167h-170zM117 0v1475h166v-1475h-166zM309 1772v167h168v-167h-168z" />
<glyph unicode="&#xd1;" 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="&#xd2;" 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="&#xd3;" 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="&#xd4;" 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="&#xd5;" 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="&#xd6;" 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="&#xd7;" horiz-adv-x="1118" d="M109 1036h221l215 -295l217 295h217l-324 -420l324 -421h-217l-217 294l-215 -294h-219l323 421z" />
<glyph unicode="&#xd9;" 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="&#xda;" 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="&#xdb;" 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="&#xdc;" 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="&#xdd;" horiz-adv-x="1650" d="M35 1475h190l572 -721l565 721h194l-677 -920v-555h-166v555zM674 1772l71 284h162l-69 -284h-164z" />
<glyph unicode="&#xdf;" 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="&#xe0;" 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="&#xe1;" 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="&#xe2;" 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="&#xe3;" 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="&#xe4;" 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="&#xe5;" 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="&#xe6;" 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="&#xe7;" 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="&#xe8;" 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="&#xe9;" 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="&#xea;" 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="&#xeb;" 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="&#xec;" horiz-adv-x="438" d="M33 1849h166l69 -284h-164zM115 0v1188h168v-1188h-168z" />
<glyph unicode="&#xed;" horiz-adv-x="438" d="M100 1563l72 284h162l-70 -284h-164zM104 0v1188h168v-1188h-168z" />
<glyph unicode="&#xee;" horiz-adv-x="438" d="M-31 1563l146 239h121l145 -239h-86l-119 174l-123 -174h-84zM104 0v1188h168v-1188h-168z" />
<glyph unicode="&#xef;" horiz-adv-x="438" d="M-66 1567v168h170v-168h-170zM113 0v1188h168v-1188h-168zM303 1567v168h168v-168h-168z" />
<glyph unicode="&#xf1;" 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="&#xf2;" 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="&#xf3;" 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="&#xf4;" 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="&#xf5;" 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="&#xf6;" 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="&#xf7;" horiz-adv-x="1040" d="M37 522v168h971v-168h-971zM440 2v168h168v-168h-168zM440 1018v168h168v-168h-168z" />
<glyph unicode="&#xf9;" 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="&#xfa;" 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="&#xfb;" 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="&#xfc;" 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="&#xfd;" 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="&#xff;" 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="&#x152;" 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="&#x153;" 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="&#x178;" horiz-adv-x="1650" d="M35 1475h190l572 -721l565 721h194l-677 -920v-555h-166v555zM541 1772v167h170v-167h-170zM909 1772v167h168v-167h-168z" />
<glyph unicode="&#x2c6;" horiz-adv-x="614" d="M57 1784l146 239h121l145 -239h-86l-119 174l-123 -174h-84z" />
<glyph unicode="&#x2dc;" 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="&#x2000;" horiz-adv-x="1035" />
<glyph unicode="&#x2001;" horiz-adv-x="2071" />
<glyph unicode="&#x2002;" horiz-adv-x="1035" />
<glyph unicode="&#x2003;" horiz-adv-x="2071" />
<glyph unicode="&#x2004;" horiz-adv-x="690" />
<glyph unicode="&#x2005;" horiz-adv-x="517" />
<glyph unicode="&#x2006;" horiz-adv-x="345" />
<glyph unicode="&#x2007;" horiz-adv-x="345" />
<glyph unicode="&#x2008;" horiz-adv-x="258" />
<glyph unicode="&#x2009;" horiz-adv-x="414" />
<glyph unicode="&#x200a;" horiz-adv-x="115" />
<glyph unicode="&#x2010;" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
<glyph unicode="&#x2011;" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
<glyph unicode="&#x2012;" horiz-adv-x="1058" d="M121 522v168h799v-168h-799z" />
<glyph unicode="&#x2013;" horiz-adv-x="1449" d="M111 520v168h1230v-168h-1230z" />
<glyph unicode="&#x2014;" horiz-adv-x="1683" d="M111 520v168h1476v-168h-1476z" />
<glyph unicode="&#x2018;" horiz-adv-x="344" d="M68 1030v201q0 82 47 147.5t123 87.5v-436h-170z" />
<glyph unicode="&#x2019;" horiz-adv-x="339" d="M111 1040v437h168v-201q0 -82 -47.5 -147.5t-120.5 -88.5z" />
<glyph unicode="&#x201c;" 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="&#x201d;" 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="&#x2022;" horiz-adv-x="759" d="M295 723v43q0 59 57 59h51q59 0 60 -59v-43q0 -57 -60 -57h-51q-57 0 -57 57z" />
<glyph unicode="&#x2026;" horiz-adv-x="1175" d="M111 0v168h168v-168h-168zM498 0v168h168v-168h-168zM883 0v168h170v-168h-170z" />
<glyph unicode="&#x202f;" horiz-adv-x="414" />
<glyph unicode="&#x205f;" horiz-adv-x="517" />
<glyph unicode="&#x20ac;" 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="&#x25fc;" horiz-adv-x="1187" d="M0 0v1188h1188v-1188h-1188z" />
<hkern u1="&#x3f;" 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="&#x2c;" 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="&#x2019;" 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="&#x2e;" k="41" />
<hkern u1="r" u2="&#x2c;" 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

View File

@@ -1,3 +0,0 @@
<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="M10.063 26l1.8-6h8.274l1.8 6h3.551l-6-20h-6.976l-6 20h3.551zM14.863 10h2.274l1.8 6h-5.874l1.8-6z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 265 B

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -1,88 +0,0 @@
<!DOCTYPE html>
<html ng-app="app" ng-strict-di="true" manifest="/coriolis.appcache">
<head>
<title ng-bind="title">Coriolis</title>
<link rel="stylesheet" href="/app.css">
<!-- Standard headers -->
<meta name="description" content="A ship builder, outfitting and comparison tool for Elite Dangerous">
<meta name="mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="manifest" href="/images/logo/manifest.json">
<link rel="icon" sizes="152x152 192x192" type="image/png" href="/images/logo/192x192.png">
<link rel="shortcut icon" href="/images/logo/favicon.ico">
<!-- Apple/iOS headers -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="Coriolis">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="180x180" href="/images/logo/apple-touch-icon-precomposed.png">
<link rel="apple-touch-icon" href="/images/logo/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="180x180" href="/images/logo/apple-touch-icon-180x180.png">
<!-- iPhone, iPod Touch, portrait -->
<link href="/images/splash/320x460.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
<!-- iPhone, iPod Touch, landscape -->
<link href="/images/splash/480x320.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
<!-- iPhone 4, 4S, portrait -->
<link href="/images/splash/640x920.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 4, 4S, landscape -->
<link href="/images/splash/960x640.png" media="(device-width: 320px) and (device-height: 480px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 5, 5S, 5C, portrait -->
<link href="/images/splash/640x1096.png" media="(device-width: 320px) and (device-height: 568px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 5, 5S, 5C, landscape -->
<link href="/images/splash/1136x640.png" media="(device-width: 320px) and (device-height: 568px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 6, portrait -->
<link href="/images/splash/750x1294.png" media="(device-width: 375px) and (device-height: 667px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 6, landscape -->
<link href="/images/splash/1334x750.png" media="(device-width: 375px) and (device-height: 667px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPhone 6+, portrait -->
<link href="/images/splash/1242x2148.png" media="(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image">
<!-- iPhone 6+, landscape -->
<link href="/images/splash/2208x1242.png" media="(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)" rel="apple-touch-startup-image">
<!-- iPad 1, 2, Mini, portrait -->
<link href="/images/splash/768x1004.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
<!-- iPad 1, 2, Mini, landscape -->
<link href="/images/splash/1024x748.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)" rel="apple-touch-startup-image">
<!-- iPad 3, 4, Air, Air 2, Mini 2, Mini 3, portrait -->
<link href="/images/splash/1536x2008.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- iPad 3, 4, Air, Air 2, Mini 2, Mini 3, landscape -->
<link href="/images/splash/2048x1496.png" media="(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)" rel="apple-touch-startup-image">
<!-- Microsoft Windows Phone/Tablet headers -->
<meta name="msapplication-TileColor" content="#000000">
<meta name="msapplication-TileImage" content="/images/logo/mstile-144x144.png">
<meta name="msapplication-config" content="/images/logo/browserconfig.xml">
<meta name="theme-color" content="#000000">
</head>
<body style="background-color:#000;">
<div style="height: 0; width: 0; overflow:hidden"><%= svgContent %></div>
<shipyard-header></shipyard-header>
<div id="main" ui-view ng-click="bgClicked($event)" ng-style="{'font-size': sizeRatio + 'em'}"></div>
<div ui-view="modal" ng-click="bgClicked($event)"></div>
<footer>
<div class="right cap">
<a href="https://github.com/cmmcleod/coriolis/releases/" target="_blank" title="Coriolis Github Project"><span translate="version"></span> <%= version %> - <%= date %></a>
</div>
<div style="max-width:50%" class="l">
Coriolis was created using assets and imagery from Elite: Dangerous, with the permission of Frontier Developments plc, for non-commercial purposes. It is not endorsed by nor reflects the views or opinions of Frontier Developments and no employee of Frontier Developments was involved in the making of it.
</div>
</footer>
<script src="/lib.js" type="text/javascript"></script>
<script src="/app.js" type="text/javascript"></script>
<% if (uaTracking) { %>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '<%= uaTracking %> ', 'auto');
var GAPI_KEY = '<%= gapiKey %>';
</script>
<% } %>
</body>
</html>

View File

@@ -1,115 +0,0 @@
angular.module('app', ['ui.router', 'ct.ui.router.extras.sticky', 'ui.sortable', 'shipyard', 'ngLodash', 'app.templates', 'pascalprecht.translate'])
.run(['$rootScope', '$location', '$window', '$document', '$state', '$translate', 'localeFormat', 'Persist', 'Discounts', 'Languages',
function($rootScope, $location, $window, $doc, $state, $translate, localeFormat, Persist, Discounts, Languages) {
// App is running as a standalone web app on tablet/mobile
var isStandAlone;
// This was causing issues on Windows phones ($window.external was causing Angular js to throw an exception). Backup is to try this and set isStandAlone to false if this fails.
try {
isStandAlone = $window.navigator.standalone || ($window.external && $window.external.msIsSiteMode && $window.external.msIsSiteMode());
} catch (ex) {
isStandAlone = false;
}
// Redirect any state transition errors to the error controller/state
$rootScope.$on('$stateChangeError', function(e, toState, toParams, fromState, fromParams, error) {
e.preventDefault();
$state.go('error', error, { location: false, reload: true }); // Go to error state, reload the controller, keep the current URL
});
// Track on Google analytics if available
$rootScope.$on('$stateChangeSuccess', function(e, to, toParams, from, fromParams) {
$rootScope.prevState = { name: from.name, params: fromParams };
if (to.url) { // Only track states that have a URL
if ($window.ga) {
ga('send', 'pageview', { page: $location.path() });
}
if (isStandAlone) {
// Persist the current state
Persist.setState({ name: to.name, params: toParams });
}
}
});
$rootScope.language = {
opts: Languages,
current: Languages[Persist.getLangCode()] ? Persist.getLangCode() : 'en'
};
$rootScope.localeFormat = d3.locale(localeFormat.get($rootScope.language.current));
updateNumberFormat();
// Global Reference variables
$rootScope.insurance = { opts: [{ name: 'standard', pct: 0.05 }, { name: 'alpha', pct: 0.025 }, { name: 'beta', pct: 0.0375 }] };
$rootScope.discounts = { opts: Discounts };
$rootScope.STATUS = ['', 'disabled', 'off', 'on'];
$rootScope.STATUS_CLASS = ['', 'disabled', 'warning', 'secondary-disabled'];
$rootScope.sizeRatio = Persist.getSizeRatio();
$rootScope.title = 'Coriolis';
$rootScope.changeLanguage = function() {
$translate.use($rootScope.language.current);
$rootScope.localeFormat = d3.locale(localeFormat.get($rootScope.language.current));
updateNumberFormat();
$rootScope.$broadcast('languageChanged', $rootScope.language.current);
};
// Formatters
$rootScope.fRPct = d3.format('%');
$rootScope.fTime = function(d) { return Math.floor(d / 60) + ':' + ('00' + Math.floor(d % 60)).substr(-2, 2); };
function updateNumberFormat() {
var locale = $rootScope.localeFormat;
var fGen = $rootScope.fGen = locale.numberFormat('n');
$rootScope.fCrd = locale.numberFormat(',.0f');
$rootScope.fPwr = locale.numberFormat(',.2f');
$rootScope.fRound = function(d) { return fGen(d3.round(d, 2)); };
$rootScope.fPct = locale.numberFormat('.2%');
$rootScope.f1Pct = locale.numberFormat('.1%');
}
/**
* Returns the name of the component mounted in the specified slot
* @param {Object} slot The slot object
* @return {String} The component name
*/
$rootScope.cName = function(slot) {
return $translate.instant(slot.c ? slot.c.name ? slot.c.name : slot.c.grp : null);
};
// 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);
}
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
}
}
}]);

View File

@@ -1,81 +0,0 @@
/**
* Sets up the routes and handlers before the Angular app is kicked off.
*/
angular.module('app').config(['$provide', '$stateProvider', '$urlRouterProvider', '$locationProvider', 'ShipsDB', function($provide, $stateProvider, $urlRouterProvider, $locationProvider, ships) {
// Use HTML5 push and replace state if possible
$locationProvider.html5Mode({ enabled: true, requireBase: false });
/**
* Set up all states and their routes.
*/
$stateProvider
.state('outfit', {
url: '/outfit/:shipId/:code?bn',
params: {
shipId: { value: 'sidewinder', squash: false }, // Allow 'shipId' parameter to default to sidewinder
code: { value: null, squash: true } // Allow 'code' parameter to be empty/optional
},
templateUrl: 'views/page-outfit.html',
controller: 'OutfitController',
resolve: {
shipId: ['$stateParams', function($p) { // Ensure ship exists before loading controller
if (!ships[$p.shipId]) {
throw { type: 'no-ship', message: $p.shipId };
}
}]
},
sticky: true
})
.state('compare', {
url: '/compare/:name',
params: {
name: { value: null, squash: true }
},
templateUrl: 'views/page-comparison.html',
controller: 'ComparisonController',
sticky: true
})
.state('comparison', {
url: '/comparison/:code',
templateUrl: 'views/page-comparison.html',
controller: 'ComparisonController',
sticky: true
})
.state('shipyard', { url: '/', templateUrl: 'views/page-shipyard.html', controller: 'ShipyardController', sticky: true })
.state('error', { params: { type: null, message: null, details: null }, templateUrl: 'views/page-error.html', controller: 'ErrorController', sticky: true })
// Modal States and views
.state('modal', { abstract: true, views: { 'modal': { templateUrl: 'views/_modal.html', controller: 'ModalController' } } })
.state('modal.about', { views: { 'modal-content': { templateUrl: 'views/modal-about.html' } } })
.state('modal.export', { params: { title: null, data: null, promise: null, description: null }, views: { 'modal-content': { templateUrl: 'views/modal-export.html', controller: 'ExportController' } } })
.state('modal.import', { params: { obj: null }, views: { 'modal-content': { templateUrl: 'views/modal-import.html', controller: 'ImportController' } } })
.state('modal.link', { params: { url: null }, views: { 'modal-content': { templateUrl: 'views/modal-link.html', controller: 'LinkController' } } })
.state('modal.delete', { views: { 'modal-content': { templateUrl: 'views/modal-delete.html', controller: 'DeleteController' } } });
// Redirects
$urlRouterProvider.when('/outfit', '/outfit/sidewinder');
/**
* 404 Handler - Keep current URL/ do not redirect, change to error state.
*/
$urlRouterProvider.otherwise(function($injector, $location) {
// Go to error state, reload the controller, keep the current URL
$injector.get('$state').go('error', { type: 404, message: null, details: null }, { location: false, reload: true });
return $location.path;
});
/**
* Global Error Handler. Decorates the existing error handler such that it
* redirects uncaught errors to the error page.
*
*/
$provide.decorator('$exceptionHandler', ['$delegate', '$injector', function($delegate, $injector) {
return function(err, cause) {
// Go to error state, reload the controller, keep the current URL
$injector.get('$state').go('error', { type: null, message: err.message, details: err.stack }, { location: false, reload: true });
$delegate(err, cause);
};
}]);
}]);

View File

@@ -1,238 +0,0 @@
angular.module('app').controller('ComparisonController', ['lodash', '$rootScope', '$filter', '$scope', '$state', '$stateParams', '$translate', 'Utils', 'ShipFacets', 'ShipsDB', 'Ship', 'Persist', 'Serializer', function(_, $rootScope, $filter, $scope, $state, $stateParams, $translate, 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: $translate.instant('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;
});
$scope.$on('languageChanged', function() {
$scope.tblUpdate = !$scope.tblUpdate; // Simple switch to trigger the table to update
});
/* 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.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);
}]);

View File

@@ -1,7 +0,0 @@
angular.module('app').controller('DeleteController', ['$scope', 'Persist', function($scope, Persist) {
$scope.deleteAll = function() {
Persist.deleteAll();
$scope.$parent.dismiss();
};
}]);

View File

@@ -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;
}
}]);

View File

@@ -1,19 +0,0 @@
angular.module('app').controller('ExportController', ['$scope', '$stateParams', function($scope, $stateParams) {
$scope.title = $stateParams.title || 'Export';
$scope.description = $stateParams.description;
if ($stateParams.promise) {
$scope.export = 'Generating...';
$stateParams.promise.then(function(data) {
$scope.export = (typeof data === 'object') ? angular.toJson(data, true) : data;
});
} else {
$scope.export = angular.toJson($stateParams.data, true);
}
$scope.onTextClick = function($event) {
$event.target.select();
};
}]);

View File

@@ -1,312 +0,0 @@
angular.module('app').controller('ImportController', ['lodash', '$rootScope', '$scope', '$stateParams', 'ShipsDB', 'Ship', 'Components', 'GroupMap', 'Persist', 'Serializer', function(_, $rootScope, $scope, $stateParams, Ships, Ship, Components, GroupMap, Persist, Serializer) {
$scope.importValid = false;
$scope.importString = null;
$scope.errorMsg = null;
$scope.canEdit = true;
$scope.builds = $stateParams.obj || null;
$scope.ships = Ships;
var textBuildRegex = new RegExp('^\\[([\\w \\-]+)\\]\n');
var lineRegex = new RegExp('^([\\dA-Z]{1,2}): (\\d)([A-I])[/]?([FGT])?([SD])? ([\\w\\- ]+)');
var mountMap = { 'H': 4, 'L': 3, 'M': 2, 'S': 1, 'U': 0 };
var commonMap = { 'RB': 0, 'TM': 1, 'FH': 2, 'EC': 3, 'PC': 4, 'SS': 5, 'FS': 6 };
var bhMap = { 'lightweight alloy': 0, 'reinforced alloy': 1, 'military grade composite': 2, 'mirrored surface composite': 3, 'reactive surface composite': 4 };
function isEmptySlot(slot) {
return slot.maxClass == this && slot.c === null;
}
function equalsIgnoreCase(str) {
return str.toLowerCase() == this.toLowerCase();
}
function validateBuild(shipId, code, name) {
var shipData = Ships[shipId];
if (!shipData) {
throw '"' + shipId + '" is not a valid Ship Id!';
}
if (typeof name != 'string' || name.length < 3) {
throw shipData.properties.name + ' build "' + name + '" must be a string at least 3 characters long!';
}
if (typeof code != 'string' || code.length < 10) {
throw shipData.properties.name + ' build "' + name + '" is not valid!';
}
try {
Serializer.toShip(new Ship(shipId, shipData.properties, shipData.slots), code);
} catch (e) {
throw shipData.properties.name + ' build "' + name + '" is not valid!';
}
}
function detailedJsonToBuild(detailedBuild) {
var ship;
if (!detailedBuild.name) {
throw 'Build Name missing!';
}
try {
ship = Serializer.fromDetailedBuild(detailedBuild);
} catch (e) {
throw detailedBuild.ship + ' Build "' + detailedBuild.name + '": Invalid data';
}
return { shipId: ship.id, name: detailedBuild.name, code: Serializer.fromShip(ship) };
}
function importBackup(importData) {
if (importData.builds && typeof importData.builds == 'object') {
for (var shipId in importData.builds) {
for (var buildName in importData.builds[shipId]) {
validateBuild(shipId, importData.builds[shipId][buildName], buildName);
}
}
$scope.builds = importData.builds;
} else {
throw 'builds must be an object!';
}
if (importData.comparisons) {
for (var compName in importData.comparisons) {
var comparison = importData.comparisons[compName];
for (var i = 0, l = comparison.builds.length; i < l; i++) {
var build = comparison.builds[i];
if (!importData.builds[build.shipId] || !importData.builds[build.shipId][build.buildName]) {
throw build.shipId + ' build "' + build.buildName + '" data is missing!';
}
}
}
$scope.comparisons = importData.comparisons;
}
if (importData.discounts instanceof Array && importData.discounts.length == 2) {
$scope.discounts = importData.discounts;
}
if (typeof importData.insurance == 'string' && importData.insurance.length > 3) {
$scope.insurance = importData.insurance;
}
}
function importDetailedArray(importArr) {
var builds = {};
for (var i = 0, l = importArr.length; i < l; i++) {
var build = detailedJsonToBuild(importArr[i]);
if (!builds[build.shipId]) {
builds[build.shipId] = {};
}
builds[build.shipId][build.name] = build.code;
}
$scope.builds = builds;
}
function importTextBuild(buildStr) {
var buildName = textBuildRegex.exec(buildStr)[1].trim();
var shipName = buildName.toLowerCase();
var shipId = null;
for (var sId in Ships) {
if (Ships[sId].properties.name.toLowerCase() == shipName) {
shipId = sId;
break;
}
}
if (!shipId) { throw 'No such ship found: "' + buildName + '"'; }
var lines = buildStr.split('\n');
var ship = new Ship(shipId, Ships[shipId].properties, Ships[shipId].slots);
ship.buildWith(null);
for (var i = 1; i < lines.length; i++) {
var line = lines[i].trim();
if (!line) { continue; }
if (line.substring(0, 3) == '---') { break; }
var parts = lineRegex.exec(line);
if (!parts) { throw 'Error parsing: "' + line + '"'; }
var typeSize = parts[1];
var cl = parts[2];
var rating = parts[3];
var mount = parts[4];
var missile = parts[5];
var name = parts[6].trim();
var slot, group;
if (isNaN(typeSize)) { // Common or Hardpoint
if (typeSize.length == 1) { // Hardpoint
var slotClass = mountMap[typeSize];
if (cl > slotClass) { throw cl + rating + ' ' + name + ' exceeds slot size: "' + line + '"'; }
slot = _.find(ship.hardpoints, isEmptySlot, slotClass);
if (!slot) { throw 'No hardpoint slot available for: "' + line + '"'; }
group = _.find(GroupMap, equalsIgnoreCase, name);
var hpid = Components.findHardpointId(group, cl, rating, group ? null : name, mount, missile);
if (!hpid) { throw 'Unknown component: "' + line + '"'; }
ship.use(slot, hpid, Components.hardpoints(hpid), true);
} else if (typeSize == 'BH') {
var bhId = bhMap[name.toLowerCase()];
if (bhId === undefined) { throw 'Unknown bulkhead: "' + line + '"'; }
ship.useBulkhead(bhId, true);
} else if (commonMap[typeSize] != undefined) {
var commonIndex = commonMap[typeSize];
if (ship.common[commonIndex].maxClass < cl) { throw name + ' exceeds max class for the ' + ship.name; }
ship.use(ship.common[commonIndex], cl + rating, Components.common(commonIndex, cl + rating), true);
} else {
throw 'Unknown component: "' + line + '"';
}
} else {
if (cl > typeSize) { throw cl + rating + ' ' + name + ' exceeds slot size: "' + line + '"'; }
slot = _.find(ship.internal, isEmptySlot, typeSize);
if (!slot) { throw 'No internal slot available for: "' + line + '"'; }
group = _.find(GroupMap, equalsIgnoreCase, name);
var intId = Components.findInternalId(group, cl, rating, group ? null : name);
if (!intId) { throw 'Unknown component: "' + line + '"'; }
ship.use(slot, intId, Components.internal(intId));
}
}
var builds = {};
builds[shipId] = {};
builds[shipId]['Imported ' + buildName] = Serializer.fromShip(ship);
$scope.builds = builds;
}
$scope.validateImport = function() {
var importData = null;
var importString = $scope.importString.trim();
$scope.importValid = false;
$scope.errorMsg = null;
$scope.builds = $scope.discounts = $scope.comparisons = $scope.insurance = null;
if (!importString) { return; }
try {
if (textBuildRegex.test(importString)) { // E:D Shipyard build text
importTextBuild(importString);
} else { // JSON Build data
importData = angular.fromJson($scope.importString);
if (!importData || typeof importData != 'object') {
throw 'Must be an object or array!';
}
if (importData instanceof Array) { // Must be detailed export json
importDetailedArray(importData);
} else if (importData.ship && importData.name) { // Using JSON from a single ship build export
importDetailedArray([importData]); // Convert to array with singleobject
} else { // Using Backup JSON
importBackup(importData);
}
}
} catch (e) {
$scope.errorMsg = (typeof e == 'string') ? e : 'Cannot Parse the data!';
return;
}
$scope.importValid = true;
};
$scope.hasBuild = function(shipId, name) {
return Persist.getBuild(shipId, name) !== null;
};
$scope.hasComparison = function(name) {
return Persist.getComparison(name) !== null;
};
$scope.process = function() {
if ($scope.builds) {
var builds = $scope.builds;
for (var shipId in builds) {
for (var buildName in builds[shipId]) {
var code = builds[shipId][buildName];
// Update builds object such that orginal name retained, but can be renamed
builds[shipId][buildName] = {
code: code,
useName: buildName
};
}
}
}
if ($scope.comparisons) {
var comparisons = $scope.comparisons;
for (var name in comparisons) {
comparisons[name].useName = name;
}
}
$scope.processed = true;
};
$scope.import = function() {
if ($scope.builds) {
var builds = $scope.builds;
for (var shipId in builds) {
for (var buildName in builds[shipId]) {
var build = builds[shipId][buildName];
var name = build.useName.trim();
if (name) {
Persist.saveBuild(shipId, name, build.code);
}
}
}
}
if ($scope.comparisons) {
var comparisons = $scope.comparisons;
for (var comp in comparisons) {
var comparison = comparisons[comp];
var useName = comparison.useName.trim();
if (useName) {
Persist.saveComparison(useName, comparison.builds, comparison.facets);
}
}
}
if ($scope.discounts) {
$rootScope.discounts.ship = $scope.discounts[0];
$rootScope.discounts.components = $scope.discounts[1];
$rootScope.$broadcast('discountChange');
Persist.setDiscount($scope.discounts);
}
if ($scope.insurance) {
$rootScope.insurance.current = $scope.insurance;
Persist.setInsurance($scope.insurance);
}
$scope.$parent.dismiss();
};
/* Initialization */
if ($scope.builds) { // If import is passed an build object
$scope.canEdit = false;
$scope.process();
}
}]);

View File

@@ -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;
});
}]);

View File

@@ -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);
}]);

View File

@@ -1,437 +0,0 @@
angular.module('app').controller('OutfitController', ['$window', '$rootScope', '$scope', '$state', '$stateParams', '$translate', 'ShipsDB', 'Ship', 'Components', 'Serializer', 'Persist', 'calcTotalRange', 'calcSpeed', function($window, $rootScope, $scope, $state, $p, $translate, Ships, Ship, Components, Serializer, Persist, calcTotalRange, calcSpeed) {
var win = angular.element($window); // Angularized window object for event triggering
var data = Ships[$p.shipId]; // Retrieve the basic ship properties, slots and defaults
var ship = new Ship($p.shipId, data.properties, data.slots); // Create a new Ship instance
var retrofitShip = new Ship($p.shipId, data.properties, data.slots); // Create a new Ship for retrofit comparison
// Update the ship instance with the code (if provided) or the 'factory' defaults.
if ($p.code) {
Serializer.toShip(ship, $p.code); // Populate components from 'code' URL param
$scope.code = $p.code;
} else {
ship.buildWith(data.defaults); // Populate with default components
}
$scope.buildName = $p.bn;
$rootScope.title = ship.name + ($scope.buildName ? ' - ' + $scope.buildName : '');
$scope.ship = ship;
$scope.pp = ship.common[0]; // Power Plant
$scope.th = ship.common[1]; // Thruster
$scope.fsd = ship.common[2]; // Frame Shrift Drive
$scope.ls = ship.common[3]; // Life Support
$scope.pd = ship.common[4]; // Power Distributor
$scope.ss = ship.common[5]; // Sensors
$scope.ft = ship.common[6]; // Fuel Tank
$scope.hps = ship.hardpoints;
$scope.internal = ship.internal;
$scope.costList = ship.costList;
$scope.powerList = ship.powerList;
$scope.priorityBands = ship.priorityBands;
$scope.availCS = Components.forShip(ship.id);
$scope.selectedSlot = null;
$scope.savedCode = Persist.getBuild(ship.id, $scope.buildName);
$scope.canSave = Persist.isEnabled();
$scope.allBuilds = Persist.builds;
$scope.fuel = 0;
$scope.pwrDesc = false;
$scope.pwrPredicate = 'type';
$scope.retroDesc = false;
$scope.retroPredicate = 'netCost';
$scope.costDesc = true;
$scope.costPredicate = 'c.cost';
$scope.costTab = Persist.getCostTab() || 'costs';
if ($scope.savedCode) {
Serializer.toShip(retrofitShip, $scope.savedCode); // Populate components from last save
$scope.retrofitBuild = $scope.buildName;
} else {
retrofitShip.buildWith(data.defaults);
$scope.retrofitBuild = null;
}
ship.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
retrofitShip.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
updateRetrofitCosts();
$scope.jrSeries = {
xMin: 0,
xMax: ship.cargoCapacity,
yMax: ship.unladenRange,
yMin: 0,
func: function(cargo) { // X Axis is Cargo
return ship.jumpRangeWithMass(ship.unladenMass + $scope.fuel + cargo, $scope.fuel);
}
};
$scope.jrChart = {
labels: {
xAxis: {
title: 'cargo',
unit: 'T'
},
yAxis: {
title: 'jump range',
unit: 'LY'
}
}
};
$scope.trSeries = {
xMin: 0,
xMax: ship.cargoCapacity,
yMax: ship.unladenTotalRange,
yMin: 0,
func: function(cargo) { // X Axis is Cargo
return calcTotalRange(ship.unladenMass + cargo, $scope.fsd.c, $scope.fuel);
}
};
$scope.trChart = {
labels: {
xAxis: {
title: 'cargo',
unit: 'T'
},
yAxis: {
title: 'total range',
unit: 'LY'
}
}
};
$scope.speedSeries = {
xMin: 0,
xMax: ship.cargoCapacity,
yMax: 500,
yMin: 0,
series: ['speed', 'boost'],
func: function(cargo) { // X Axis is Cargo
return calcSpeed(ship.unladenMass + $scope.fuel + cargo, ship.speed, ship.boost, $scope.th.c);
}
};
$scope.speedChart = {
labels: {
xAxis: {
title: 'cargo',
unit: 'T'
},
yAxis: {
title: 'speed',
unit: 'm/s'
}
}
};
/**
* 'Opens' a select for component selection.
*
* @param {[type]} e The event object
* @param {[type]} slot The slot that is being 'opened' for selection
*/
$scope.selectSlot = function(e, slot) {
e.stopPropagation();
if ($scope.selectedSlot == slot) {
$scope.selectedSlot = null;
} else {
$scope.selectedSlot = slot;
}
};
/**
* Updates the ships build with the selected component for the
* specified slot. Prevents the click event from propagation.
*
* @param {string} type Shorthand key/string for identifying the slot & component type
* @param {[type]} slot The slot object belonging to the ship instance
* @param {[type]} e The event object
*/
$scope.select = function(type, slot, e, id) {
e.stopPropagation();
if (!id) { // Find component id if not passed
var elem = e.target;
while (elem && elem !== e.currentTarget && !elem.getAttribute('cpid')) {
elem = elem.parentElement;
}
if (elem) {
id = elem.getAttribute('cpid');
}
}
if (id) {
if (id == 'empty') {
ship.use(slot, null, null);
} else if (type == 'h') {
ship.use(slot, id, Components.hardpoints(id));
} else if (type == 'c') {
ship.use(slot, id, Components.common(ship.common.indexOf(slot), id));
} else if (type == 'i') {
ship.use(slot, id, Components.internal(id));
} else if (type == 'b') {
ship.useBulkhead(id);
}
$scope.selectedSlot = null;
updateState(Serializer.fromShip(ship));
}
};
/**
* Reload the build from the last save.
*/
$scope.reloadBuild = function() {
if ($scope.buildName && $scope.savedCode) {
Serializer.toShip(ship, $scope.savedCode); // Repopulate with components from last save
updateState($scope.savedCode);
}
};
/**
* Strip ship to A-class and biggest A-class shield generator with military bulkheads
*/
$scope.aRatedBuild = function() {
for (var i = 0, l = ship.common.length - 1; i < l; i++) { // All except Fuel Tank
var id = ship.common[i].maxClass + 'A';
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.internal.some(function(slot) {
if (typeof slot.eligible === 'undefined') { // Assuming largest slot can hold an eligible shield
id = Components.findInternalId('Shield Generator', slot.maxClass, 'A');
ship.use(slot, id, Components.internal(id));
return true;
}
});
ship.useBulkhead(2);
updateState(Serializer.fromShip(ship));
};
/**
* Optimize for the lower mass build that can still boost and power the ship
* without power management.
*/
$scope.optimizeMassBuild = function() {
var common = ship.common;
ship.hardpoints.forEach(function(slot) { ship.use(slot, null, null); });
ship.internal.forEach(function(slot) { ship.use(slot, null, null); });
ship.useBulkhead(0);
ship.use(common[2], common[2].maxClass + 'A', Components.common(2, common[2].maxClass + 'A')); // FSD
ship.use(common[3], common[3].maxClass + 'D', Components.common(3, common[3].maxClass + 'D')); // Life Support
ship.use(common[5], common[5].maxClass + 'D', Components.common(5, common[5].maxClass + 'D')); // Sensors
var pd = $scope.availCS.lightestPowerDist(ship.boostEnergy); // Find lightest Power Distributor that can still boost
ship.use(ship.common[4], pd, Components.common(4, pd));
var th = $scope.availCS.lightestThruster(ship.ladenMass); // Find lightest Thruster that still works for the ship at max mass
ship.use(ship.common[1], th, Components.common(1, th));
var pp = $scope.availCS.lightestPowerPlant(ship.powerRetracted); // Find lightest Power plant that can power the ship
ship.use(ship.common[0], pp, Components.common(0, pp));
updateState(Serializer.fromShip(ship));
};
/**
* Save the current build. Will replace the saved build if there is one
* for this ship & with the exact name.
*/
$scope.saveBuild = function() {
if (!$scope.buildName) {
return;
}
// No change hav been made, i.e. save ship default build under a name
if (!$scope.code) {
$scope.code = Serializer.fromShip(ship);
}
// Only save if there a build name and a change has been made or the build has never been saved
if ($scope.code != $scope.savedCode) {
Persist.saveBuild(ship.id, $scope.buildName, $scope.code);
$scope.savedCode = $scope.code;
if ($scope.retrofitBuild === $scope.buildName) {
Serializer.toShip(retrofitShip, $scope.code);
}
updateState($scope.code);
}
};
/**
* Export the build to detailed JSON
*/
$scope.exportBuild = function(e) {
e.stopPropagation();
if ($scope.buildName) {
$state.go('modal.export', {
title: $scope.buildName + ' ' + $translate.instant('export'),
description: $translate.instant('PHRASE_EXPORT_DESC'),
data: Serializer.toDetailedBuild($scope.buildName, ship, $scope.code || Serializer.fromShip(ship))
});
}
};
/**
* Permanently delete the current build and redirect/reload this controller
* with the 'factory' build of the current ship.
*/
$scope.deleteBuild = function() {
Persist.deleteBuild(ship.id, $scope.buildName);
$state.go('outfit', { shipId: ship.id, code: null, bn: null }, { location: 'replace', reload: true });
};
/**
* On build name change, retrieve the existing saved code if there is one
*/
$scope.bnChange = function() {
$scope.savedCode = Persist.getBuild(ship.id, $scope.buildName);
};
/**
* Toggle cost of the selected component
* @param {object} item The component being toggled
*/
$scope.toggleCost = function(item) {
ship.setCostIncluded(item, !item.incCost);
};
/**
* [sortCost description]
* @param {[type]} key [description]
* @return {[type]} [description]
*/
$scope.sortCost = function(key) {
$scope.costDesc = $scope.costPredicate == key ? !$scope.costDesc : $scope.costDesc;
$scope.costPredicate = key;
};
$scope.sortPwr = function(key) {
$scope.pwrDesc = $scope.pwrPredicate == key ? !$scope.pwrDesc : $scope.pwrDesc;
$scope.pwrPredicate = key;
};
$scope.sortRetrofit = function(key) {
$scope.retroDesc = $scope.retroPredicate == key ? !$scope.retroDesc : $scope.retroDesc;
$scope.retroPredicate = key;
};
/**
* Toggle the power on/off for the selected component
* @param {object} item The component being toggled
*/
$scope.togglePwr = function(c) {
ship.setSlotEnabled(c, !c.enabled);
updateState(Serializer.fromShip(ship));
};
$scope.incPriority = function(c) {
if (ship.changePriority(c, c.priority + 1)) {
updateState(Serializer.fromShip(ship));
}
};
$scope.decPriority = function(c) {
if (ship.changePriority(c, c.priority - 1)) {
updateState(Serializer.fromShip(ship));
}
};
$scope.fuelChange = function(fuel) {
$scope.fuel = fuel;
win.triggerHandler('render');
};
$scope.statusRetracted = function(slot) {
return ship.getSlotStatus(slot, false);
};
$scope.statusDeployed = function(slot) {
return ship.getSlotStatus(slot, true);
};
$scope.setRetrofitBase = function() {
if ($scope.retrofitBuild) {
Serializer.toShip(retrofitShip, Persist.getBuild(ship.id, $scope.retrofitBuild));
} else {
retrofitShip.buildWith(data.defaults);
}
updateRetrofitCosts();
};
// Utilify functions
function updateState(code) {
$scope.code = code;
$state.go('outfit', { shipId: ship.id, code: $scope.code, bn: $scope.buildName }, { location: 'replace', notify: false });
$scope.speedSeries.xMax = $scope.trSeries.xMax = $scope.jrSeries.xMax = ship.cargoCapacity;
$scope.jrSeries.yMax = ship.unladenRange;
$scope.trSeries.yMax = ship.unladenTotalRange;
updateRetrofitCosts();
win.triggerHandler('pwrchange');
}
function updateRetrofitCosts() {
var costs = $scope.retrofitList = [];
var total = 0, i, l, item;
if (ship.bulkheads.id != retrofitShip.bulkheads.id) {
item = {
buyClassRating: ship.bulkheads.c.class + ship.bulkheads.c.rating,
buyName: ship.bulkheads.c.name,
sellClassRating: retrofitShip.bulkheads.c.class + retrofitShip.bulkheads.c.rating,
sellName: retrofitShip.bulkheads.c.name,
netCost: ship.bulkheads.discountedCost - retrofitShip.bulkheads.discountedCost
};
costs.push(item);
total += item.netCost;
}
for (var g in { common: 1, internal: 1, hardpoints: 1 }) {
var retroSlotGroup = retrofitShip[g];
var slotGroup = ship[g];
for (i = 0, l = slotGroup.length; i < l; i++) {
if (slotGroup[i].id != retroSlotGroup[i].id) {
item = { netCost: 0 };
if (slotGroup[i].id) {
item.buyName = slotGroup[i].c.name || slotGroup[i].c.grp;
item.buyClassRating = slotGroup[i].c.class + slotGroup[i].c.rating;
item.netCost = slotGroup[i].discountedCost;
}
if (retroSlotGroup[i].id) {
item.sellName = retroSlotGroup[i].c.name || retroSlotGroup[i].c.grp;
item.sellClassRating = retroSlotGroup[i].c.class + retroSlotGroup[i].c.rating;
item.netCost -= retroSlotGroup[i].discountedCost;
}
costs.push(item);
total += item.netCost;
}
}
}
$scope.retrofitTotal = total;
}
$scope.updateCostTab = function(tab) {
Persist.setCostTab(tab);
$scope.costTab = tab;
};
$scope.ppWarning = function(pp) {
return pp.pGen < ship.powerRetracted;
};
$scope.pdWarning = function(pd) {
return pd.enginecapacity < ship.boostEnergy;
};
// Hide any open menu/slot/etc if the background is clicked
$scope.$on('close', function() {
$scope.selectedSlot = null;
});
// Hide any open menu/slot/etc if the background is clicked
$scope.$on('languageChanged', function() {
$scope.selectedSlot = null;
});
// Hide any open menu/slot/etc if the background is clicked
$scope.$on('discountChange', function() {
ship.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
retrofitShip.applyDiscounts($rootScope.discounts.ship, $rootScope.discounts.components);
updateRetrofitCosts();
});
}]);

View File

@@ -1,4 +0,0 @@
angular.module('app').controller('ShipyardController', ['$rootScope', 'ShipsDB', function($rootScope, ships) {
$rootScope.title = 'Coriolis';
$rootScope.ships = ships;
}]);

View File

@@ -1,164 +0,0 @@
angular.module('app').directive('areaChart', ['$window', '$translate', function($window, $translate) {
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('class', 'cap')
.attr('transform', 'rotate(-90)')
.attr('y', -50)
.attr('dy', '.1em')
.style('text-anchor', 'middle')
.text($translate.instant(labels.yAxis.title) + ' (' + $translate.instant(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($translate.instant(labels.xAxis.title) + ' (' + $translate.instant(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) + ' ' + $translate.instant(labels.xAxis.unit));
tip.select('text.label.y').text(fmtLong(y0) + ' ' + $translate.instant(labels.yAxis.unit));
}
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize render', render);
});
}
};
}]);

View File

@@ -1,132 +0,0 @@
angular.module('app').directive('barChart', ['$window', '$translate', '$rootScope', function($window, $translate, $rootScope) {
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', '1em');
}
}
}
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 = null,
unit = null,
properties = scope.facet.props,
margin = { top: 10, right: 20, bottom: 40, 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');
// 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 ? ($translate.instant(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 cap')
.append('text')
.attr('y', 33)
.attr('dy', '.1em')
.style('text-anchor', 'middle');
updateFormats();
function render() {
var data = scope.data,
width = element[0].offsetWidth,
w = width - margin.left - margin.right,
height = 45 + (30 * data.length * $rootScope.sizeRatio),
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); });
}
function updateFormats() {
fmt = $rootScope[scope.facet.fmt];
unit = $translate.instant(scope.facet.unit);
xAxisLbl.text($translate.instant(scope.facet.title) + (unit ? (' (' + $translate.instant(unit) + ')') : ''));
xAxis.tickFormat($rootScope.localeFormat.numberFormat('.2s'));
render();
}
angular.element($window).bind('orientationchange resize render', render);
scope.$watchCollection('data', render); // Watch for changes in the comparison array
scope.$on('languageChanged', updateFormats);
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize render', render);
tip.destroy(); // Remove the tooltip from the DOM
});
}
};
}]);

View File

@@ -1,80 +0,0 @@
angular.module('app').directive('comparisonTable', ['$state', '$translate', '$rootScope', function($state, $translate, $rootScope) {
function tblHeader(facets) {
var r1 = ['<tr class="main"><th rowspan="2" class="prop" prop="name">', $translate.instant('SHIP'), '</th><th rowspan="2" class="prop" prop="buildName">', $translate.instant('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' : '', '">', $translate.instant(f.lbls[j]), '</th>');
}
}
r1.push('>', $translate.instant(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>', $rootScope[f.fmt](b[p[k]]), '<u> ', $translate.instant(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));
});
}
};
}]);

View File

@@ -1,90 +0,0 @@
angular.module('app').directive('componentSelect', ['$translate', function($translate) {
// Generting the HTML in this manner is MUCH faster than using an angular template.
function appendGroup(list, opts, cid, mass, checkWarning) {
var prevClass = null, prevRating = null;
for (var i = 0; i < opts.length; i++) {
var o = opts[i];
var id = o.id || (o.class + o.rating); // Common components' ID is their class and rating
if (i > 0 && opts.length > 4 && o.class != prevClass && (o.rating != prevRating || o.mode)) {
list.push('<br/>');
}
list.push('<li class="', o.name ? 'lc' : 'c');
if (cid == id) {
list.push(' active');
}
if (checkWarning && checkWarning(opts[i])) {
list.push(' warning');
}
list.push(((o.maxmass && (mass + (o.mass ? o.mass : 0)) > o.maxmass) ? ' disabled"' : '" cpid="' + id + '"'), '>');
if (o.mode) {
list.push('<svg class="icon lg"><use xlink:href="#mount-', o.mode, '"></use></svg> ');
}
list.push('<span>', o.class, o.rating);
if (o.missile) {
list.push('/' + o.missile);
}
if (o.name) {
list.push(' ' + $translate.instant(o.name));
}
list.push('</span></li>');
prevClass = o.class;
prevRating = o.rating;
}
}
return {
restrict: 'A',
scope: {
opts: '=', // Component Options object
groups: '=', // Groups of Component Options
mass: '=', // Current ship mass
s: '=', // Current Slot
warning: '=' // Check warning function
},
link: function(scope, element) {
var list = [];
var cid = scope.s.id; // Slot's current component id
var component = scope.s.c; // Slot's Current Component (may be null/undefined)
var opts = scope.opts;
var groups = scope.groups;
var mass = (scope.mass ? scope.mass : 0) - (component && component.mass ? component.mass : 0); // Mass minus the currently selected component
if (groups) {
// At present time slots with grouped options (Hardpoints and Internal) can be empty
list.push('<div class="empty-c upp" cpid="empty">', $translate.instant('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 cap">', $translate.instant(g), '</div><ul>');
appendGroup(list, grp, cid, mass, scope.warning);
list.push('</ul>');
}
} else {
list.push('<ul>');
appendGroup(list, opts, cid, mass, scope.warning);
list.push('</ul>');
}
element.html(list.join(''));
// If groups are present and a component is already selectd
if (groups && component && component.grp) {
var groupElement = angular.element(document.getElementById(component.grp));
var parentElem = element[0].parentElement;
parentElem.scrollTop = groupElement[0].offsetTop; // Scroll to currently selected group
}
}
};
}]);

View File

@@ -1,14 +0,0 @@
angular.module('app').directive('contextMenu', ['$parse', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.contextMenu);
element.bind('contextmenu', function(e) {
if (!e.shiftKey) {
scope.$apply(function() {
e.preventDefault();
fn(scope, { $event: e });
});
}
});
};
}]);

View File

@@ -1,105 +0,0 @@
angular.module('app').directive('shipyardHeader', ['lodash', '$window', '$rootScope', '$state', 'Persist', 'Serializer', 'ShipsDB', function(_, $window, $rootScope, $state, Persist, Serializer, ships) {
return {
restrict: 'E',
templateUrl: 'views/_header.html',
scope: true,
link: function(scope) {
scope.openedMenu = null;
scope.ships = ships;
scope.allBuilds = Persist.builds;
scope.buildsList = Object.keys(scope.allBuilds).sort();
scope.allComparisons = Persist.comparisons;
scope.bs = Persist.state;
var win = angular.element($window); // Angularized window object for event triggering
var insIndex = _.findIndex($rootScope.insurance.opts, 'name', Persist.getInsurance());
var savedDiscounts = Persist.getDiscount() || [1, 1];
$rootScope.insurance.current = $rootScope.insurance.opts[insIndex != -1 ? insIndex : 0];
$rootScope.discounts.ship = savedDiscounts[0];
$rootScope.discounts.components = savedDiscounts[1];
/**
* Save selected insurance option
*/
scope.updateInsurance = function() {
Persist.setInsurance($rootScope.insurance.current.name);
};
/**
* Save selected discount option
*/
scope.updateDiscount = function() {
Persist.setDiscount([$rootScope.discounts.ship, $rootScope.discounts.components]);
$rootScope.$broadcast('discountChange');
};
scope.backup = function(e) {
e.preventDefault();
e.stopPropagation();
scope.openedMenu = null;
$state.go('modal.export', {
title: 'backup',
data: Persist.getAll(),
description: 'PHRASE_BACKUP_DESC'
});
};
scope.detailedExport = function(e) {
e.preventDefault();
e.stopPropagation();
scope.openedMenu = null;
$state.go('modal.export', {
title: 'detailed export',
data: Serializer.toDetailedExport(scope.allBuilds),
description: 'PHRASE_EXPORT_DESC'
});
};
scope.openMenu = function(e, menu) {
e.stopPropagation();
if (menu == scope.openedMenu) {
scope.openedMenu = null;
return;
}
if ((menu == 'comp' || menu == 'b') && !scope.bs.hasBuilds) {
scope.openedMenu = null;
return;
}
scope.openedMenu = menu;
};
// Close menus if a navigation change event occurs
$rootScope.$on('$stateChangeStart', function() {
scope.openedMenu = null;
});
// Listen to close event to close opened menus or modals
$rootScope.$on('close', function() {
scope.openedMenu = null;
});
scope.textSizeChange = function(size) {
if (size != $rootScope.sizeRatio) {
$rootScope.sizeRatio = size;
document.getElementById('main').style.fontSize = size + 'em';
Persist.setSizeRatio(size);
win.triggerHandler('resize');
}
};
scope.resetTextSize = function() {
if ($rootScope.sizeRatio != 1) {
scope.textSizeChange(1);
scope.$broadcast('reset', 1);
}
};
scope.$watchCollection('allBuilds', function() {
scope.buildsList = Object.keys(scope.allBuilds).sort();
});
}
};
}]);

View File

@@ -1,199 +0,0 @@
angular.module('app').directive('lineChart', ['$window', '$translate', '$rootScope', function($window, $translate, $rootScope) {
return {
restrict: 'A',
scope: {
config: '=',
series: '='
},
link: function(scope, element) {
var seriesConfig = scope.series,
series = seriesConfig.series,
color = d3.scale.ordinal().range([ '#ff8c0d', '#1fb0ff', '#a05d56', '#d0743c']),
config = scope.config,
labels = config.labels,
margin = { top: 15, right: 15, bottom: 35, left: 60 },
fmtLong = null,
func = seriesConfig.func,
drag = d3.behavior.drag(),
dragging = false,
// Define Scales
x = d3.scale.linear(),
y = d3.scale.linear(),
// Define Axes
xAxis = d3.svg.axis().scale(x).outerTickSize(0).orient('bottom'),
yAxis = d3.svg.axis().scale(y).ticks(6).outerTickSize(0).orient('left'),
data = [];
// Create chart
var svg = d3.select(element[0]).append('svg');
var vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var lines = vis.append('g');
// Define Area
var line = d3.svg.line().y(function(d) { return y(d[1]); });
// Create Y Axis SVG Elements
var yTxt = vis.append('g').attr('class', 'y axis')
.append('text')
.attr('class', 'cap')
.attr('transform', 'rotate(-90)')
.attr('y', -50)
.attr('dy', '.1em')
.style('text-anchor', 'middle')
.text($translate.instant(labels.yAxis.title) + ' (' + $translate.instant(labels.yAxis.unit) + ')');
// Create X Axis SVG Elements
var xLbl = vis.append('g').attr('class', 'x axis');
var xTxt = xLbl.append('text')
.attr('class', 'cap')
.attr('y', 30)
.attr('dy', '.1em')
.style('text-anchor', 'middle')
.text($translate.instant(labels.xAxis.title) + ' (' + $translate.instant(labels.xAxis.unit) + ')');
// Create and Add tooltip
var tipWidth = (Math.max(labels.yAxis.unit.length, labels.xAxis.unit.length) * 1.25) + 2.5;
var tips = vis.append('g').style('display', 'none');
var background = vis.append('rect') // Background to capture hover/drag
.attr('fill-opacity', 0)
.on('mouseover', showTip)
.on('mouseout', hideTip)
.on('mousemove', moveTip)
.call(drag);
drag
.on('dragstart', function() {
dragging = true;
moveTip.call(this);
showTip();
})
.on('dragend', function() {
dragging = false;
hideTip();
})
.on('drag', moveTip);
updateFormats();
function render() {
var width = element[0].parentElement.offsetWidth,
height = width * 0.5 * $rootScope.sizeRatio,
xMax = seriesConfig.xMax,
xMin = seriesConfig.xMin,
yMax = seriesConfig.yMax,
yMin = seriesConfig.yMin,
w = width - margin.left - margin.right,
h = height - margin.top - margin.bottom,
s, val, yVal, delta;
data.length = 0; // Reset Data array
if (seriesConfig.xMax == seriesConfig.xMin) {
line.x(function(d, i) { return i * w; });
} else {
line.x(function(d) { return x(d[0]); });
}
if (series) {
for (s = 0; s < series.length; s++) {
data.push([]);
}
if (xMax == xMin) {
yVal = func(xMin);
for (s = 0; s < series.length; s++) {
data[s].push( [ xMin, yVal[ series[s] ] ], [ 1, yVal[ series[s] ] ]);
}
} else {
delta = (xMax - xMin) / 30; // Only render 30 points on the graph
for (val = xMin; val <= xMax; val += delta) {
yVal = func(val);
for (s = 0; s < series.length; s++) {
data[s].push([ val, yVal[ series[s] ] ]);
}
}
}
} else {
var seriesData = [];
if (xMax == xMin) {
yVal = func(xMin);
seriesData.push([ xMin, yVal ], [ 1, yVal ]);
} else {
delta = (xMax - xMin) / 30; // Only render 30 points on the graph
for (val = xMin; val <= xMax; val += delta) {
seriesData.push([val, func(val) ]);
}
}
data.push(seriesData);
}
// Update Chart Size
svg.attr('width', width).attr('height', height);
background.attr('height', h).attr('width', w);
// Update domain and scale for axes
x.range([0, w]).domain([xMin, xMax]).clamp(true);
xLbl.attr('transform', 'translate(0,' + h + ')');
xTxt.attr('x', w / 2);
y.range([h, 0]).domain([yMin, yMax]);
yTxt.attr('x', -h / 2);
vis.selectAll('.y.axis').call(yAxis);
vis.selectAll('.x.axis').call(xAxis);
lines.selectAll('path.line')
.data(data)
.attr('d', line) // Update existing series
.enter() // Add new series
.append('path')
.attr('class', 'line')
.attr('stroke', function(d, i) { return color(i); })
.attr('stroke-width', 2)
.attr('d', line);
var tip = tips.selectAll('g.tooltip').data(data).enter().append('g').attr('class', 'tooltip');
tip.append('rect').attr('width', tipWidth + 'em').attr('height', '2em').attr('x', '0.5em').attr('y', '-1em').attr('class', 'tip');
tip.append('circle').attr('class', 'marker').attr('r', 4);
tip.append('text').attr('class', 'label x').attr('y', '-0.25em');
tip.append('text').attr('class', 'label y').attr('y', '0.85em');
}
function showTip() {
tips.style('display', null);
}
function hideTip() {
if (!dragging) {
tips.style('display', 'none');
}
}
function moveTip() {
var xPos = d3.mouse(this)[0], x0 = x.invert(xPos), y0 = func(x0), flip = (x0 / x.domain()[1] > 0.65);
var tip = tips.selectAll('g.tooltip').attr('transform', function(d, i) { return 'translate(' + x(x0) + ',' + y(series ? y0[series[i]] : y0) + ')'; });
tip.selectAll('rect').attr('x', flip ? (-tipWidth - 0.5) + 'em' : '0.5em').style('text-anchor', flip ? 'end' : 'start');
tip.selectAll('text.label').attr('x', flip ? '-1em' : '1em').style('text-anchor', flip ? 'end' : 'start');
tip.selectAll('text.label.x').text(fmtLong(x0) + ' ' + $translate.instant(labels.xAxis.unit));
tips.selectAll('text.label.y').text(function(d, i) { return fmtLong(series ? y0[series[i]] : y0) + ' ' + $translate.instant(labels.yAxis.unit); });
}
function updateFormats() {
xTxt.text($translate.instant(labels.xAxis.title) + ' (' + $translate.instant(labels.xAxis.unit) + ')');
yTxt.text($translate.instant(labels.yAxis.title) + ' (' + $translate.instant(labels.yAxis.unit) + ')');
fmtLong = $rootScope.localeFormat.numberFormat('.2f');
xAxis.tickFormat($rootScope.localeFormat.numberFormat('.2r'));
yAxis.tickFormat($rootScope.localeFormat.numberFormat('.3r'));
render();
}
angular.element($window).bind('orientationchange resize render', render);
scope.$watchCollection('series', render); // Watch for changes in the series data
scope.$on('languageChanged', updateFormats);
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize render', render);
});
}
};
}]);

View File

@@ -1,9 +0,0 @@
angular.module('app').directive('loader', function() {
return {
restrict: 'A',
link: function(scope, element) {
element.addClass('loader');
element.html('<svg viewbox="0 0 40 40" width="100%" height="100%"><path d="m5,8l5,8l5,-8z" class="l1 d1" /><path d="m5,8l5,-8l5,8z" class="l1 d2" /><path d="m10,0l5,8l5,-8z" class="l1 d3" /><path d="m15,8l5,-8l5,8z" class="l1 d4" /><path d="m20,0l5,8l5,-8z" class="l1 d5" /><path d="m25,8l5,-8l5,8z" class="l1 d6" /><path d="m25,8l5,8l5,-8z" class="l1 d7" /><path d="m30,16l5,-8l5,8z" class="l1 d8" /><path d="m30,16l5,8l5,-8z" class="l1 d9" /><path d="m25,24l5,-8l5,8z" class="l1 d10" /><path d="m25,24l5,8l5,-8z" class="l1 d11" /><path d="m20,32l5,-8l5,8z" class="l1 d13" /><path d="m15,24l5,8l5,-8z" class="l1 d14" /><path d="m10,32l5,-8l5,8z" class="l1 d15" /><path d="m5,24l5,8l5,-8z" class="l1 d16" /><path d="m5,24l5,-8l5,8z" class="l1 d17" /><path d="m0,16l5,8l5,-8z" class="l1 d18" /><path d="m0,16l5,-8l5,8z" class="l1 d20" /><path d="m10,16l5,-8l5,8z" class="l2 d0" /><path d="m15,8l5,8l5,-8z" class="l2 d3" /><path d="m20,16l5,-8l5,8z" class="l2 d6" /><path d="m20,16l5,8l5,-8z" class="l2 d9" /><path d="m15,24l5,-8l5,8z" class="l2 d12" /><path d="m10,16l5,8l5,-8z" class="l2 d15" /></svg>');
}
};
});

View File

@@ -1,197 +0,0 @@
angular.module('app').directive('powerBands', ['$window', '$translate', '$rootScope', function($window, $translate, $rootScope) {
return {
restrict: 'A',
scope: {
bands: '=',
available: '='
},
link: function(scope, element) {
var bands = null,
available = 0,
maxBand,
maxPwr,
deployedSum = 0,
retractedSum = 0,
retBandsSelected = false,
depBandsSelected = false,
wattScale = d3.scale.linear(),
pctScale = d3.scale.linear().domain([0, 1]),
wattFmt,
pctFmt,
wattAxis = d3.svg.axis().scale(wattScale).outerTickSize(0).orient('top'),
pctAxis = d3.svg.axis().scale(pctScale).outerTickSize(0).orient('bottom'),
// Create chart
svg = d3.select(element[0]).append('svg'),
vis = svg.append('g'),
deployed = vis.append('g').attr('class', 'power-band'),
retracted = vis.append('g').attr('class', 'power-band');
svg.on('contextmenu', function() {
if (!d3.event.shiftKey) {
d3.event.preventDefault();
for (var i = 0, l = bands.length; i < l; i++) {
bands[i].retSelected = false;
bands[i].depSelected = false;
}
dataChange();
}
});
// Create Y Axis SVG Elements
vis.append('g').attr('class', 'watt axis');
vis.append('g').attr('class', 'pct axis');
var retText = vis.append('text').attr('x', -3).style('text-anchor', 'end').attr('dy', '0.5em').attr('class', 'primary upp');
var depText = vis.append('text').attr('x', -3).style('text-anchor', 'end').attr('dy', '0.5em').attr('class', 'primary upp');
var retLbl = vis.append('text').attr('dy', '0.5em');
var depLbl = vis.append('text').attr('dy', '0.5em');
updateFormats(true);
function dataChange() {
bands = scope.bands;
available = scope.available;
maxBand = bands[bands.length - 1];
deployedSum = 0;
retractedSum = 0;
retBandsSelected = false;
depBandsSelected = false;
maxPwr = Math.max(available, maxBand.retractedSum, maxBand.deployedSum);
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;
}
}
render();
}
function render() {
var size = $rootScope.sizeRatio,
mTop = Math.round(25 * size),
mRight = Math.round(130 * size),
mBottom = Math.round(25 * size),
mLeft = Math.round(45 * size),
barHeight = Math.round(20 * size),
width = element[0].offsetWidth,
innerHeight = (barHeight * 2) + 2,
height = innerHeight + mTop + mBottom,
w = width - mLeft - mRight,
repY = (barHeight / 2),
depY = (barHeight * 1.5) - 1;
// Update chart size
svg.attr('width', width).attr('height', height);
vis.attr('transform', 'translate(' + mLeft + ',' + mTop + ')');
// 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);
retText.attr('y', repY);
depText.attr('y', depY);
updateLabel(retLbl, w, repY, retBandsSelected, retBandsSelected ? retractedSum : maxBand.retractedSum, available);
updateLabel(depLbl, w, depY, depBandsSelected, depBandsSelected ? deployedSum : maxBand.deployedSum, available);
retracted.selectAll('rect').data(bands).enter().append('rect')
.attr('height', barHeight)
.attr('width', function(d) { return Math.ceil(Math.max(wattScale(d.retracted + d.retOnly), 0)); })
.attr('x', function(d) { return Math.floor(Math.max(wattScale(d.retractedSum) - wattScale(d.retracted + d.retOnly), 0)); })
.attr('y', 1)
.on('click', function(d) {
d.retSelected = !d.retSelected;
dataChange();
})
.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', repY)
.attr('dy', '0.5em')
.style('text-anchor', 'middle')
.attr('class', 'primary-bg')
.on('click', function(d) {
d.retSelected = !d.retSelected;
dataChange();
})
.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.ceil(Math.max(wattScale(d.deployed + d.retracted), 0)); })
.attr('x', function(d) { return Math.floor(Math.max(wattScale(d.deployedSum) - wattScale(d.retracted) - wattScale(d.deployed), 0)); })
.attr('y', barHeight + 1)
.on('click', function(d) {
d.depSelected = !d.depSelected;
dataChange();
})
.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', depY)
.attr('dy', '0.5em')
.style('text-anchor', 'middle')
.attr('class', 'primary-bg')
.on('click', function(d) {
d.depSelected = !d.depSelected;
dataChange();
})
.text(function(d, i) { return bandText(d.deployed + d.retracted, i); });
}
function updateLabel(lbl, width, y, selected, sum, avail) {
lbl
.attr('x', width + 5 )
.attr('y', y)
.attr('class', getClass(selected, sum, avail))
.text(wattFmt(Math.max(0, sum)) + ' (' + pctFmt(Math.max(0, sum / avail)) + ')');
}
function getClass(selected, sum, avail) {
return selected ? 'secondary' : (sum >= avail) ? 'warning' : 'primary';
}
function bandText(val, index) {
if (val > 0 && wattScale(val) > 13) {
return index + 1;
}
return '';
}
function updateFormats(preventRender) {
retText.text($translate.instant('ret'));
depText.text($translate.instant('dep'));
wattFmt = $rootScope.localeFormat.numberFormat('.2f');
pctFmt = $rootScope.localeFormat.numberFormat('.1%');
wattAxis.tickFormat($rootScope.localeFormat.numberFormat('.2r'));
pctAxis.tickFormat($rootScope.localeFormat.numberFormat('%'));
if (!preventRender) {
render();
}
}
// Watch for changes to data and events
angular.element($window).bind('pwrchange', dataChange);
angular.element($window).bind('orientationchange resize', render);
scope.$watchCollection('available', dataChange);
scope.$on('languageChanged', updateFormats);
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize pwrchange', render);
});
}
};
}]);

View File

@@ -1,90 +0,0 @@
angular.module('app').directive('slider', ['$window', function($window) {
return {
restrict: 'A',
scope: {
min: '=',
def: '=',
max: '=',
unit: '=',
change: '&onChange',
ignoreResize: '='
},
link: function(scope, element) {
var unit = scope.unit,
margin = unit ? { top: -10, right: 145, left: 50 } : { top: 0, right: 10, left: 10 },
height = unit ? 40 : 20, // Height is fixed
h = height - margin.top,
fmt = d3.format('.2f'),
pct = d3.format('.1%'),
def = scope.def !== undefined ? scope.def : scope.max,
val = def,
svg = d3.select(element[0]).append('svg'),
vis = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'),
xAxisContainer = vis.append('g').attr('class', 'x slider-axis').attr('transform', 'translate(0,' + h / 2 + ')'),
x = d3.scale.linear(),
xAxis = d3.svg.axis().scale(x).orient('bottom').tickFormat(function(d) { return d + unit; }).tickSize(0).tickPadding(12),
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 = unit ? slider.append('g').append('text').attr('y', h / 2) : null;
slider.call(brush);
slider.select('.background').attr('height', h);
handle.attr('transform', 'translate(0,' + h / 2 + ')');
function render() {
var width = element[0].offsetWidth, w = width - margin.left - margin.right;
svg.attr('width', width).attr('height', height);
x.domain([scope.min || 0, scope.max]).range([0, w]).clamp(true);
handle.attr('cx', x(val));
if (unit) {
xAxisContainer.call(xAxis.tickValues([0, scope.max / 4, scope.max / 2, (3 * scope.max) / 4, scope.max]));
lbl.attr('x', w + 20);
}
slider.call(brush.extent([val, val]));
drawBrush();
slider.selectAll('.extent,.resize').remove();
}
function brushed() {
val = x.invert(d3.mouse(this)[0]);
brush.extent([val, val]);
scope.change({ val: val });
drawBrush();
}
function drawBrush() {
if (unit) {
lbl.text(fmt(val) + ' ' + unit + ' ' + pct(val / scope.max));
}
handle.attr('cx', x(val));
filled.attr('d', 'M0,0V0H' + x(val) + 'V0');
}
/**
* Watch for changes in the max, window size
*/
scope.$watch('max', function(newMax, oldMax) {
val = newMax * (val / oldMax); // Retain percentage filled
scope.change({ val: val });
render();
});
if (!scope.ignoreResize) {
angular.element($window).bind('orientationchange resize', render);
}
scope.$on('reset', function(e, resetVal) {
val = resetVal;
drawBrush();
});
scope.$on('$destroy', function() {
angular.element($window).unbind('orientationchange resize render', render);
});
}
};
}]);

View File

@@ -1,13 +0,0 @@
angular.module('app').directive('slotHardpoint', ['$rootScope', function($r) {
return {
restrict: 'A',
scope: {
hp: '=',
size: '='
},
templateUrl: 'views/_slot-hardpoint.html',
link: function(scope) {
scope.$r = $r;
}
};
}]);

View File

@@ -1,13 +0,0 @@
angular.module('app').directive('slotInternal', ['$rootScope', function($r) {
return {
restrict: 'A',
scope: {
c: '=slot',
fuel: '='
},
templateUrl: 'views/_slot-internal.html',
link: function(scope) {
scope.$r = $r;
}
};
}]);

View File

@@ -1,65 +0,0 @@
/**
* BBCode Generator functions for embedding in the Elite Dangerous Forums
*/
angular.module('app').factory('Utils', ['$window', '$state', '$http', '$q', '$translate', '$rootScope', function($window, $state, $http, $q, $translate, $rootScope) {
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]', $translate.instant(f.title).toUpperCase(), '[/COLOR][/B][/th]');
colCount++;
} else {
for (j = 0; j < p.length; j++) {
l.push('[th][B][COLOR=#FF8C0D]', $translate.instant(f.title).toUpperCase(), '\n', $translate.instant(f.lbls[j]).toUpperCase(), '[/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"]', $rootScope[f.fmt](b[p[k]]), ' [size=-2]', $translate.instant(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
};
}]);

View File

@@ -1,219 +0,0 @@
angular.module('app').config(['$translateProvider', 'localeFormatProvider', function($translateProvider, localeFormatProvider) {
// Declare number format settings
localeFormatProvider.addFormat('de', {
decimal: ',',
thousands: '.',
grouping: [3],
currency: ['', ' €'],
dateTime: '%A, der %e. %B %Y, %X',
date: '%d.%m.%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'], // unused
days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
shortDays: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
shortMonths: ['Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
});
$translateProvider.translations('de', {
PHRASE_EXPORT_DESC: 'Ein detaillierter JSON-Export Ihrer Konfiguration für die Verwendung in anderen Websites und Tools',
'A-Rated': 'A-Klasse',
about: 'Über',
action: 'Aktion',
added: 'Hinzugefügt',
Advanced: 'Verbessert',
'Advanced Discovery Scanner': 'Fortgeschrittener Aufklärungsscanner',
agility: 'Manövrierbarkeit',
ammo: 'Munition',
PHRASE_CONFIRMATION: 'Sind Sie sicher?',
armour: 'Panzerung',
am: 'Automatische Feldwartungs-Einheit',
available: 'Verfügbar',
backup: 'Sicherungsdatei',
'Basic Discovery Scanner': 'Einfacher Aufklärungsscanner',
bl: 'Strahlenlaser',
beta: 'Beta',
bins: 'Behälter',
boost: 'Boost',
build: 'Ausstattung',
'build name': 'Ausstattungsname',
builds: 'Ausstattungen',
bh: 'Rumpfhüllenverstärkung',
ul: 'Salvenlaser',
buy: 'Kaufen',
cancel: 'Abbrechen',
c: 'Kanone',
capital: 'Kapital',
cargo: 'Fracht',
'Cargo Hatch': 'Frachtluke',
cr: 'Frachtgestell',
cs: 'Frachtscanner',
cells: 'Zellen',
'Chaff Launcher': 'Düppel-Werfer',
close: 'Schließen',
cc: 'Krallensteuerung: Sammler',
compare: 'Vergleichen',
'compare all': 'Alles Vergleichen',
comparison: 'Vergleich',
comparisons: 'Vergleiche',
component: 'Komponente',
cost: 'Preis',
costs: 'Kosten',
cm: 'Gegenmaßnahme',
create: 'Erstellen',
'create new': 'Neu Erstellen',
Cytoscrambler: 'Zytostreuer',
damage: 'Schaden',
delete: 'Löschen',
'delete all': 'Alles Löschen',
dep: 'Ausg',
deployed: 'Ausgefahren',
'detailed export': 'Detailierter Export',
'Detailed Surface Scanner': 'Detailoberflächenscanner',
disabled: 'Deaktiviert',
discount: 'Rabatt',
Distruptor: 'Disruptor',
dc: 'Standard-Landecomputer',
done: 'Fertig',
'edit data': 'Bearbeiten',
efficiency: 'Effizienz',
'Electronic Countermeasure': 'Elektronische Gegenmaßnahme',
empty: 'leer',
Enforcer: 'Vollstrecker',
ENG: 'ANT',
'enter name': 'Namen eingeben',
export: 'Export',
fixed: 'Fixiert',
forum: 'Forum',
fc: 'Splitterkanone',
fd: 'Frameshiftantrieb',
ws: 'Frameshift-Sogwolkenscanner',
FSD: 'FSA',
fi: 'FSA-Unterbrecher',
fuel: 'Treibstoff',
fs: 'Treibstoffsammler',
ft: 'Treibstofftank',
fx: 'Krallensteuerung Treibstoffstransfer',
'full tank': 'Tank voll',
Gimballed: 'Kardanisch',
H: 'R',
hardpoints: 'Waffenaufhängungen',
hb: 'Krallen-Steuereinheit (Ladelukenöffner)',
'Heat Sink Launcher': 'Kühlkörperwerfer',
huge: 'Riesig',
hull: 'Hülle',
hr: 'Rumpfhüllenverstärkung (Paket)',
'Imperial Hammer': 'Imperialer Hammer',
import: 'Importieren',
'import all': 'Alles Importieren',
insurance: 'Versicherung',
'Intermediate Discovery Scanner': 'Mittlerer Aufklärungsscanner',
'internal compartments': 'Innenbereichskabine',
'jump range': 'Sprungreichweite',
jumps: 'Sprünge',
kw: 'Tötungsbefehl-Scanner',
L: 'G',
laden: 'Beladen',
language: 'Sprache',
large: 'Groß',
ls: 'Lebenserhaltung',
'Lightweight Alloy': 'Leichte Legierung',
'lock factor': 'Massensperrefaktor',
LS: 'Ls',
LY: 'Lj',
mass: 'Masse',
'max mass': 'maximale Masse',
medium: 'Mittel',
'Military Grade Composite': 'Militär-Komposit',
nl: 'Minenwerfer',
'Mining Lance': 'Lanzenabbaulaser',
ml: 'Abbaulaser',
'Mirrored Surface Composite': 'Gespiegelte-Oberfläche-Komposit',
mr: 'Raketenbatterie',
mc: 'Mehrfachgeschütz',
'net cost': 'Nettokosten',
no: 'Nein',
PHRASE_NO_BUILDS: 'Keine Konfigurationen zum Vergleich ausgewählt!',
PHRASE_NO_RETROCH: 'Keine Umrüständerungen',
none: 'Nichts',
'none created': 'Leer',
off: 'Aus',
on: 'An',
'optimal mass': 'optimale Masse',
'optimize mass': 'Masse optimieren',
overwrite: 'Überschreiben',
Pacifier: 'Friedensstifter',
'Pack-Hound': 'Schwarmwerfer',
PHRASE_IMPORT: 'JSON hier einfügen oder importieren',
pen: 'Durchdr.',
penetration: 'Durchdringung',
permalink: 'Permalink',
pa: 'Plasmabeschleuniger',
'Point Defence': 'Punktverteidigung',
power: 'Energie',
pd: 'Energieverteiler',
pp: 'Kraftwerk',
pri: 'Prio',
priority: 'Priorität',
psg: 'Prismaschildgenerator',
proceed: 'Fortfahren',
pc: 'Krallensteuerung: Erzsucher',
pl: 'Impulslaser',
PWR: 'En',
rg: 'Schienenkanone',
range: 'Reichweite',
rate: 'Rate',
'Reactive Surface Composite': 'Reaktive-Oberfläche-Komposit',
recharge: 'Aufladen',
rf: 'Raffinerie',
'refuel time': 'Auftankzeit',
'Reinforced Alloy': 'Verstärkte Legierung',
reload: 'Aktualisieren',
rename: 'Umbenennen',
repair: 'Reparieren',
reset: 'Zurücksetzen',
ret: 'Eing',
retracted: 'Eingefahren',
'retrofit costs': 'Änderungskosten',
'retrofit from': 'Nachrüsten von',
ROF: 'Kad',
S: 'K',
save: 'Speichern',
sc: 'Scanner',
PHRASE_SELECT_BUILDS: 'Ausstattung zum Vergleich auswählen',
sell: 'Verkaufen',
s: 'Sensoren',
settings: 'Einstellungen',
sb: 'Schild-Booster',
scb: 'Schildzellenbank',
sg: 'Schildgenerator',
shields: 'Schilde',
ship: 'Schiff',
ships: 'Schiffe',
shortened: 'Gekürzt',
size: 'Größe',
skip: 'Überspringen',
small: 'Klein',
speed: 'Geschwindigkeit',
standard: 'Standard',
'Standard Docking Computer': 'Standard-Landecomputer',
Stock: 'Standard',
T: 't',
T_LOAD: 'T-Lad',
'The Retributor': 'Retributor',
t: 'Schubdüsen',
time: 'Dauer',
tp: 'Torpedoaufhängung',
total: 'Gesamt',
'total range': 'Maximale Reichweite',
turret: 'Geschützturm',
type: 'Typ',
U: 'W',
unladen: 'Unbeladen',
PHRASE_UPDATE_RDY: 'Update verfügbar! Klicken zum Aktualisieren',
utility: 'Werkzeug',
'utility mounts': 'Werkzeug-Steckplätze',
WEP: 'WAF',
yes: 'Ja',
PHRASE_BACKUP_DESC: 'Export aller Coriolis-Daten, um sie zu sichern oder oder um sie zu einem anderen Browser/Gerät zu übertragen.'
});
}]);

View File

@@ -1,218 +0,0 @@
angular.module('app').config(['$translateProvider', function($translateProvider) {
$translateProvider
.translations('en', {
PHRASE_EXPORT_DESC: 'A detailed JSON export of your build for use in other sites and tools',
'A-Rated': 'A-Rated',
about: 'about',
action: 'action',
added: 'added',
Advanced: 'Advanced',
'Advanced Discovery Scanner': 'Advanced Discovery Scanner',
agility: 'agility',
alpha: 'alpha',
ammo: 'ammo',
PHRASE_CONFIRMATION: 'Are You Sure?',
armour: 'armour',
am: 'Auto Field-Maintenance Unit',
available: 'available',
backup: 'backup',
'Basic Discovery Scanner': 'Basic Discovery Scanner',
bl: 'Beam Laser',
beta: 'beta',
bins: 'bins',
boost: 'boost',
build: 'build',
'build name': 'Build Name',
builds: 'builds',
bh: 'bulkheads',
ul: 'Burst Laser',
buy: 'buy',
cancel: 'cancel',
c: 'Cannon',
capital: 'capital',
cargo: 'cargo',
'Cargo Hatch': 'Cargo Hatch',
cr: 'Cargo Rack',
cs: 'Cargo Scanner',
cells: 'cells',
'Chaff Launcher': 'Chaff Launcher',
close: 'close',
cc: 'Collector Limpet Controller',
compare: 'compare',
'compare all': 'compare all',
comparison: 'comparison',
comparisons: 'comparisons',
component: 'component',
cost: 'cost',
costs: 'costs',
cm: 'Countermeasure',
CR: 'CR',
create: 'create',
'create new': 'create new',
credits: 'credits',
Cytoscrambler: 'Cytoscrambler',
damage: 'damage',
delete: 'delete',
'delete all': 'delete all',
dep: 'dep',
deployed: 'deployed',
'detailed export': 'detailed export',
'Detailed Surface Scanner': 'Detailed Surface Scanner',
disabled: 'disabled',
discount: 'discount',
Distruptor: 'Distruptor',
dc: 'Docking Computer',
done: 'done',
DPS: 'DPS',
'edit data': 'edit data',
efficiency: 'efficiency',
'Electronic Countermeasure': 'Electronic Countermeasure',
empty: 'empty',
Enforcer: 'Enforcer',
ENG: 'ENG',
'enter name': 'Enter Name',
EPS: 'EPS',
export: 'export',
fixed: 'fixed',
forum: 'forum',
fc: 'Fragment Cannon',
fd: 'Frame Shift Drive',
ws: 'Frame Shift Wake Scanner',
FSD: 'FSD',
fi: 'FSD Interdictor',
fuel: 'fuel',
fs: 'Fuel Scoop',
ft: 'Fuel Tank',
fx: 'Fuel Transfer Limpet Controller',
'full tank': 'full tank',
Gimballed: 'Gimballed',
H: 'H',
hardpoints: 'hardpoints',
hb: 'Hatch Breaker Limpet Controller',
'Heat Sink Launcher': 'Heat Sink Launcher',
huge: 'huge',
hull: 'hull',
hr: 'Hull Reinforcement Package',
'Imperial Hammer': 'Imperial Hammer',
import: 'import',
'import all': 'import all',
insurance: 'insurance',
'Intermediate Discovery Scanner': 'Intermediate Discovery Scanner',
'internal compartments': 'internal compartments',
'jump range': 'jump range',
jumps: 'jumps',
kw: 'Kill Warrant Scanner',
L: 'L',
laden: 'laden',
language: 'language',
large: 'large',
ls: 'life support',
'Lightweight Alloy': 'Lightweight Alloy',
'lock factor': 'lock factor',
LS: 'Ls',
LY: 'LY',
M: 'M',
'm/s': 'm/s',
mass: 'mass',
max: 'max',
'max mass': 'max mass',
medium: 'medium',
'Military Grade Composite': 'Military Grade Composite',
nl: 'Mine Launcher',
'Mining Lance': 'Mining Lance',
ml: 'Mining Laser',
'Mirrored Surface Composite': 'Mirrored Surface Composite',
mr: 'Missile Rack',
mc: 'Multi-cannon',
'net cost': 'net cost',
no: 'no',
PHRASE_NO_BUILDS: 'No builds added to comparison!',
PHRASE_NO_RETROCH: 'No Retrofitting changes',
none: 'none',
'none created': 'none created',
off: 'off',
on: 'on',
optimal: 'optimal',
'optimal mass': 'optimal mass',
'optimize mass': 'optimize mass',
overwrite: 'overwrite',
Pacifier: 'Pacifier',
'Pack-Hound': 'Pack-Hound',
PHRASE_IMPORT: 'Paste JSON or import here',
pen: 'pen',
penetration: 'penetration',
permalink: 'permalink',
pa: 'Plasma Accelerator',
'Point Defence': 'Point Defence',
power: 'power',
pd: 'power distributor',
pp: 'power plant',
pri: 'pri',
priority: 'priority',
psg: 'Prismatic Shield Generator',
proceed: 'proceed',
pc: 'Prospector Limpet Controller',
pl: 'Pulse Laser',
PWR: 'PWR',
rg: 'Rail Gun',
range: 'range',
rate: 'rate',
'Reactive Surface Composite': 'Reactive Surface Composite',
recharge: 'recharge',
rf: 'Refinery',
'refuel time': 'refuel time',
'Reinforced Alloy': 'Reinforced Alloy',
reload: 'reload',
rename: 'rename',
repair: 'repair',
reset: 'reset',
ret: 'ret',
retracted: 'retracted',
'retrofit costs': 'retrofit costs',
'retrofit from': 'retrofit from',
ROF: 'ROF',
S: 'S',
save: 'save',
sc: 'scanner',
PHRASE_SELECT_BUILDS: 'Select Builds to Compare',
sell: 'sell',
s: 'sensors',
settings: 'settings',
sb: 'Shield Booster',
scb: 'Shield Cell Bank',
sg: 'Shield Generator',
shields: 'shields',
ship: 'ship',
ships: 'ships',
shortened: 'shortened',
size: 'size',
skip: 'skip',
small: 'small',
speed: 'speed',
standard: 'standard',
'Standard Docking Computer': 'Standard Docking Computer',
Stock: 'Stock',
SYS: 'SYS',
T: 'T',
T_LOAD: 't-load',
'The Retributor': 'The Retributor',
t: 'thrusters',
time: 'time',
tp: 'Torpedo Pylon',
total: 'total',
'total range': 'total range',
turret: 'turret',
type: 'type',
U: 'U',
unladen: 'unladen',
PHRASE_UPDATE_RDY: 'Update Available! Click to Refresh',
URL: 'URL',
utility: 'utility',
'utility mounts': 'utility mounts',
version: 'version',
WEP: 'WEP',
yes: 'yes',
PHRASE_BACKUP_DESC: 'Backup of all Coriolis data to save or transfer to another browser/device'
});
}]);

View File

@@ -1,263 +0,0 @@
angular.module('app').config(['$translateProvider', 'localeFormatProvider', function($translateProvider, localeFormatProvider) {
// Declare number format settings
localeFormatProvider.addFormat('es', {
decimal: ',',
thousands: '.',
grouping: [3],
currency: ['', ' €'],
dateTime: '%A, %e de %B de %Y, %X',
date: '%d/%m/%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['domingo', 'lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado'],
shortDays: ['dom', 'lun', 'mar', 'mié', 'jue', 'vie', 'sáb'],
months: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio', 'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'],
shortMonths: ['ene', 'feb', 'mar', 'abr', 'may', 'jun', 'jul', 'ago', 'sep', 'oct', 'nov', 'dic']
});
$translateProvider.translations('es', {
PHRASE_EXPORT_DESC: 'Ein detaillierter JSON-Export Ihrer Konfiguration für die Verwendung in anderen Websites und Tools',
A_RATED: 'A-Klasse',
ABOUT: 'Über',
ACTION: 'Aktion',
ADDED: 'Hinzugefügt',
ADDER: 'Adder',
ADVANCED: 'Fortgeschritten',
'Advanced Discovery Scanner': 'Fortgeschrittener Aufklärungsscanner',
'Advanced Plasma Laser': 'Fortgeschrittener Plasma-Laser',
AGILITY: 'Beweglichkeit',
ALPHA: 'Alpha',
AMMO: 'Munition',
ANACONDA: 'Anaconda',
PHRASE_CONFIRMATION: 'Sind Sie sicher?',
ARMOUR: 'Panzerung',
ASP_EXPLORER: 'Asp Explorer',
am: 'Automatische Feldwartungseinheit',
AVAILABLE: 'Verfügbar',
BACKUP: 'Sicherungsdatei',
'Basic Discovery Scanner': 'Einfacher Aufklärungsscanner',
bl: 'Strahlenlaser',
BELUGA_LINER: 'Beluga Liner',
BETA: 'beta',
BINS: 'Behälter',
BOOST: 'Boost',
BUILD: 'Konfiguration',
BUILD_NAME: 'Konfigurationsname',
BUILDS: 'Konfigurationen',
BULKHEADS: 'Rumpfhüllenverstärkung',
ul: 'Salvenlaser',
BUY: 'Kaufen',
CANCEL: 'Abbrechen',
c: 'Kanone',
CAPITAL: 'kapital',
CARGO: 'Fracht',
CARGO_HATCH: 'Frachtluke',
cr: 'Frachtgestell',
cs: 'Frachtscanner',
CELLS: 'Zellen',
CHAFF_LAUNCHER: 'Düppel-Werfer',
CLOSE: 'Schließen',
COBRA_MK_III: 'Cobra MK III',
COBRA_MK_IV: 'Cobra MK IV',
cc: 'Krallensteuerung: Sammler',
COMPARE: 'Vergleichen',
COMPARE_ALL: 'Alles Vergleichen',
COMPARISON: 'Vergleich',
COMPARISONS: 'Vergleiche',
COMPONENT: 'Komponente',
COST: 'Kostet',
COSTS: 'Kosten',
cm: 'Gegenmaßnahme',
CR: 'CR',
CREATE: 'Erstellen',
CREATE_NEW: 'Neu Erstellen',
CREDITS: 'Credits',
Cytoscrambler: 'Zytostreuer',
DAMAGE: 'Schaden',
DELETE: 'Löschen',
DELETE_ALL: 'Alles Löschen',
DEP: 'Ausg',
DEPLOYED: 'Ausgefahren',
DETAILED_EXPORT: 'Detailiertes Exportieren',
'Detailed Surface Scanner': 'Detailoberflächenscanner',
DIAMONDBACK_EXPLORER: 'Diamondback-Erkunder',
DIAMONDBACK_SCOUT: 'Diamondback-Aufklärer',
DISABLED: 'Deaktiviert',
DISCOUNT: 'Rabatt',
Distruptor: 'Disruptor',
dc: 'Standard-Landecomputer',
DOLPHIN: 'Dolphin',
DONE: 'Fertig',
DPS: 'DPS',
EAGLE: 'Eagle',
EDIT_DATA: 'Bearbeiten',
EFFICIENCY: 'Effizienz',
'Electronic Countermeasure': 'Elektronische Gegenmaßnahme',
EMPTY: 'leer',
ENFORCER: 'Vollstrecker',
ENG: 'FAH',
PHRASE_ENTER_BUILD_NAME: '',
EPS: 'en/s',
EXPORT: 'Exportieren',
FEDERAL_CORVETTE: 'Föderale Korvette',
FEDERAL_DROPSHIP: 'Föderales Abwurfschiff',
FEDERAL_DROPSHIP_MK_II: 'Föderales Abwurfschiff Mk II',
FEDERAL_GUNSHIP: 'Föderales Kanonenschiff',
FER_DE_LANCE: 'Fer-de-Lance',
FIXED: '',
FORUM: 'Forum',
fc: 'Splitterkanone',
fd: 'Frameshift-Antrieb',
ws: 'Sogwolkenscanner',
FSD: 'FSA',
fi: 'FSA-Unterbrecher',
FUEL: 'Treibstoff',
fs: 'Treibstoffsammler',
ft: 'Treibstofftank',
fx: 'Krallensteuerung Treibstoffstransfer',
FULL_TANK: 'Tank voll',
GIMBALLED: 'Kardianisch',
H: 'H',
HARDPOINTS: 'Waffenaufhängungen',
hb: 'Krallen-Steuereinheit (Ladelukenöffner)',
HAULER: 'Hauler',
'Heat Sink Launcher': 'Kühlkörperwerfer',
HUGE: 'Riesig',
HULL: 'Hülle',
hr: 'Rumpfhüllenverstärkung (Paket)',
IMPERIAL_CLIPPER: 'Imperialer Clipper',
IMPERIAL_COURIER: 'Imperialer Kurier',
IMPERIAL_CUTTER: 'Imperialer Cutter',
IMPERIAL_EAGLE: 'Imperialer Eagle',
IMPERIAL_HAMMER: 'Imperialer Hammer',
IMPORT: 'Importieren',
IMPORT_ALL: 'Alles Importieren',
INSURANCE: 'Versicherung',
'Intermediate Discover Scanner': 'Mittlerer Aufklärungsscanner',
INTERNAL_COMPARTMENTS: 'Innenbereichkabine',
JUMP_RANGE: 'Sprungreichweite',
JUMPS: 'Sprünge',
kw: 'Tötungsbefehlscanner',
KRAIT: 'Krait',
L: 'L',
LADEN: 'Beladen',
LANGUAGE: 'Sprache',
LARGE: 'Groß',
ls: 'Lebenserhaltung',
'Lightweight Alloy': 'Leichte Legierung',
LOCK_FACTOR: 'Massensperrefaktor',
LS: 'LS',
LY: 'LJ',
M: 'M',
'm/s': 'M/Sec.',
MASS: 'Masse',
MAX: 'max',
MAX_MASS: 'maximale Masse',
MEDIUM: 'Mittel',
'Military Grade Composite': 'Militär-Komposit',
nl: 'Minenwerfer',
'Mining Lance': 'Lanzenabbaulaser',
ml: 'Abbaulaser',
'Mirrored Surface Composite': 'Gespiegelte-Oberfläche-Komposit',
mr: 'Raketenbatterie',
mc: 'Mehrfachgeschütz',
NET_COST: 'Nettokosten',
NO: 'Nein',
NO_RETROFITTING_CHANGES: 'Keine Umrüständerungen',
NONE: 'Nichts',
NONE_CREATED: 'Nichts erstellt',
OFF: 'Aus',
ON: 'An',
OPTIMAL: 'optimal',
OPTIMAL_MASS: 'optimale Masse',
OPTIMIZE_MASS: 'Masse optimieren',
ORCA: 'Orca',
OVERWRITE: 'Überschreiben',
Pacifier: 'Friedensstifter',
'Pack-Hound': 'Schwarmwerfer',
PANTHER_CLIPPER: 'Panter Clipper',
PHRASE_IMPORT: 'JSON hier einfügen oder hier importieren',
PEN: 'Durchdr',
PENETRATION: 'Durchdringung',
PERMALINK: 'Permalink',
pa: 'Plasmabeschleuniger',
POINT_DEFENCE: 'Punktverteidigung',
POWER: 'Energie',
pd: 'Energieverteiler',
pp: 'Kraftwerk',
PRI: 'Prio',
PRIORITY: 'Priorität',
psg: 'Prismaschildgenerator',
PROCEED: 'Fortfahren',
pc: 'Krallensteuerung: Erzsucher',
pl: 'Impulslaser',
PWR: 'En',
PYTHON: 'Python',
rg: 'Schienenkanone',
RANGE: 'Reichweite',
RATE: 'Rate',
'Reactive Surface Composite': 'Reaktive-Oberfläche-Komposit',
RECHARGE: 'Aufladen',
rf: 'Raffinerie',
REFUEL_TIME: 'Auftankzeit',
'Reinforced Alloy': 'Verstärkte Legierungen',
RELOAD: 'Aktualisieren',
RENAME: 'Umbenennen',
REPAIR: 'Reparieren',
RESET: 'Zurücksetzen',
RET: 'eing',
RETRACTED: 'Eingefahren',
RETROFIT_COSTS: 'Nachrüstkosten',
RETROFIT_FROM: 'Nachrüsten von',
ROF: 'Kad',
S: 'S',
SAVE: 'Speichern',
sc: 'Scanner',
PHRASE_SELECT_BUILDS: 'Wähle Konfigurationen zum Vergleichen',
SELL: 'Verkaufen',
s: 'Sensoren',
SETTINGS: 'Konfiguration',
sb: 'Schildverstärker',
scb: 'Schildzellenbank',
sg: 'Schildgenerator',
SHIELDS: 'Schilde',
SHIP: 'Schiff',
SHIPS: 'Schiffe',
SHORTENED: 'Gekürzt',
SIDEWINDER: 'Sidewinder',
SIZE: 'Größe',
SKIP: 'Überspringen',
SMALL: 'S',
SPEED: 'Geschwindigkeit',
STANDARD: 'Standard',
STANDARD_DOCKING_COMPUTER: 'Landecomputer',
STOCK: 'Standard',
SYS: 'SYS',
T: 'T',
T_LOAD: 'T-Lad',
THE_HUNTER: 'The Hunter',
'The Retributor': 'Retributor',
t: 'Schubdüsen',
TIME: 'Dauer',
tp: 'Torpedoaufhängung',
TOTAL: 'Gesamt',
TOTAL_RANGE: 'Maximale Reichweite',
TURRET: 'Geschützturm',
TYPE: 'Typ',
TYPE_6_TRANSPORTER: 'Typ-6 Transporter',
TYPE_7_TRANSPORTER: 'Typ-7 Transporter',
TYPE_9_HEAVY: 'Typ-9 Transporter (schwer)',
U: 'U',
UNLADEN: 'Unbeladen',
UPDATE_NOTIFICATION: 'Update verfügbar! Klicken zum Aktualisieren',
URL: 'URL',
UTILITY: 'Werkzeug',
UTILITY_MOUNTS: 'Werkzeug-Steckplatz',
VERSION: 'Version',
VIPER: 'Viper',
VULTURE: 'Vulture',
WEP: 'WAF',
YES: 'Ja'
});
}]);

View File

@@ -1,199 +0,0 @@
angular.module('app').config(['$translateProvider', 'localeFormatProvider', function($translateProvider, localeFormatProvider) {
// Declare number format settings
localeFormatProvider.addFormat('fr', {
decimal: ',',
thousands: '.',
grouping: [3],
currency: ['', ' €'],
dateTime: '%A, le %e %B %Y, %X',
date: '%d/%m/%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'], // unused
days: ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi'],
shortDays: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
months: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'],
shortMonths: ['janv.', 'févr.', 'mars', 'avr.', 'mai', 'juin', 'juil.', 'août', 'sept.', 'oct.', 'nov.', 'déc.']
});
$translateProvider.translations('fr', {
PHRASE_EXPORT_DESC: 'Export détaillé en JSON de votre configuration pour utilisation sur d\'autres sites et outils',
'A-Rated': 'Classe-A ',
about: 'à propos',
added: 'ajouté',
Advanced: 'Avancé',
'Advanced Discovery Scanner': 'Scanner de découverte avancé',
agility: 'manœuvrabilité',
ammo: 'munitions',
PHRASE_CONFIRMATION: 'Êtes-vous sûr ?',
armour: 'Armure',
am: 'Unité de réparation automatique',
available: 'Disponibilité',
backup: 'sauvegarde',
'Basic Discovery Scanner': 'Scanner de découverte simple',
bl: 'Rayon Laser',
bins: 'bacs',
build: 'Configuration',
'build name': 'Nom de la configuration',
builds: 'Configurations',
bh: 'Coque',
ul: 'Laser à rafale',
buy: 'Acheter',
cancel: 'Annuler',
c: 'Canon',
cargo: 'Soute',
'Cargo Hatch': 'Ecoutille de soute',
cr: 'Compartiment de soute',
cs: 'Scanner de soute',
cells: 'Cellules',
'Chaff Launcher': 'Lanceur de paillettes',
close: 'fermer',
cc: 'Contrôleur de prospecteur',
compare: 'comparer',
'compare all': 'tout comparer',
comparison: 'comparaison',
comparisons: 'comparaisons',
component: 'composant',
cost: 'coût',
costs: 'coûts',
cm: 'Contre-mesure',
create: 'Créer',
'create new': 'Créer nouveau',
credits: 'crédits',
damage: 'Dégâts',
delete: 'supprimer',
'delete all': 'tout supprimer',
dep: 'depl',
deployed: 'déployé',
'detailed export': 'export détaillé',
'Detailed Surface Scanner': 'Scanner de surface détaillé',
disabled: 'désactivé',
discount: 'réduction',
Distruptor: 'Disrupteur',
dc: 'Ordinateur d\'appontage',
done: 'Valider',
'edit data': 'Editer donnée',
efficiency: 'efficience',
'Electronic Countermeasure': 'Contre mesure électronique',
empty: 'Vide',
'enter name': 'Entrer un nom',
fixed: 'fixé',
fc: 'Canon à fragmentation',
fd: 'Réacteur FSD',
ws: 'Détecteur de sillage FSD',
fi: 'Intercepteur de réacteur FSD',
fuel: 'carburant',
fs: 'Récupérateur de carburant',
ft: 'Réservoir de carburant',
fx: 'Drone de ravitaillement',
'full tank': 'Réservoir plein',
Gimballed: 'Point',
hardpoints: 'Points d\'emport',
hb: 'Contrôle de patelle perce-soute',
'Heat Sink Launcher': 'Ejecteur de dissipateur thermique',
huge: 'Très grand',
hull: 'Coque',
hr: 'Renfort de soute',
'Imperial Hammer': 'Marteau impérial',
import: 'Importer',
'import all': 'Importer tout',
insurance: 'Assurance',
'Intermediate Discovery Scanner': 'Scanner de découverte intermédiaire',
'internal compartments': 'compartiments internes',
'jump range': 'Distance de saut',
jumps: 'Sauts',
kw: 'Détecteur d\'avis de recherche',
laden: 'chargé',
language: 'Langage',
large: 'large',
ls: 'Support vital',
'Lightweight Alloy': 'alliage léger',
'lock factor': 'facteur inhibition de masse',
LS: 'SL',
LY: 'AL',
mass: 'Masse',
'max mass': 'masse max',
'Military Grade Composite': 'Composite militaire',
nl: 'Lance-mines',
'Mining Lance': 'Lance de minage',
ml: 'Laser minier',
'Mirrored Surface Composite': 'Composite à surface mirroir',
mr: 'Lance missiles',
mc: 'Canon multiple',
'net cost': 'coûts nets',
no: 'non',
PHRASE_NO_BUILDS: 'Aucune configuration ajoutée pour comparaison',
PHRASE_NO_RETROCH: 'Configuration non modifiée',
none: 'aucun',
'none created': 'Rien de créé',
off: 'éteint',
on: 'allumé',
'optimal mass': 'masse optimale',
'optimize mass': 'optimiser masse',
overwrite: 'remplacer',
Pacifier: 'Pacificateur',
PHRASE_IMPORT: 'Coller ici votre JSON à importer',
pen: 'pén.',
penetration: 'pénétration',
permalink: 'lien durable',
pa: 'accélérateur plasma',
'Point Defence': 'Défense ponctuelle',
power: 'énergie',
pd: 'distributeur d\'énérgie',
pp: 'centrale d\'énergie',
priority: 'priorité',
psg: 'générateur de bouclier prisme',
proceed: 'continuer',
pc: 'Drône de minage',
pl: 'Laser à impulsion',
PWR: 'P',
rg: 'Canon électromagnétique',
range: 'portée',
rate: 'cadence',
'Reactive Surface Composite': 'Composite à surface réactive',
recharge: 'recharger',
rf: 'Raffinerie',
'refuel time': 'Temps de remplissage',
'Reinforced Alloy': 'alliage renforcé',
reload: 'recharger',
rename: 'renommer',
repair: 'réparer',
reset: 'Réinitialisation',
ret: 'esc',
retracted: 'escamoté',
'retrofit costs': 'Valeur de rachat',
'retrofit from': 'Racheter de',
ROF: 'cadence',
save: 'sauvegarder',
sc: 'scanner',
PHRASE_SELECT_BUILDS: 'Sélectionner les configurations à comparer',
sell: 'vendre',
s: 'détecteurs',
settings: 'paramètres',
sb: 'Survolteur de bouclier',
scb: 'Réserve de cellules d\'énergie',
sg: 'Générateur de bouclier',
shields: 'boucliers',
ship: 'vaisseau',
ships: 'vaisseaux',
shortened: 'raccourci',
size: 'taille',
skip: 'Suivant',
small: 'petit',
speed: 'vitesse',
'Standard Docking Computer': 'ordinateur amarrage standard',
Stock: 'de base',
T_LOAD: 'degrés',
'The Retributor': 'Le Rétributeur',
t: 'propulseurs',
time: 'temps',
tp: 'Tube lance-torpille',
'total range': 'Distance maximale',
turret: 'tourelle',
unladen: 'Non chargé',
PHRASE_UPDATE_RDY: 'Mise à jour disponible ! Cliquez pour rafraichir',
utility: 'utilitaire',
'utility mounts': 'Support utilitaire',
WEP: 'ARM',
yes: 'oui',
PHRASE_BACKUP_DESC: 'Exportation détaillée des données de Coriolis pour l\'utilisation dans d\'autres sites et outils'
});
}]);

View File

@@ -1,21 +0,0 @@
angular.module('app').config(['$translateProvider', function($translateProvider) {
$translateProvider
.useSanitizeValueStrategy('escapeParameters')
.useStorage('Persist')
.fallbackLanguage('en') // Use English as default/fallback language
.registerAvailableLanguageKeys(['en', 'de', 'fr', 'ru'], { // TODO: add 'es' to the array when ready
'en*': 'en',
'de*': 'de',
//'es*': 'es',
'fr*': 'fr',
'ru*': 'ru'
})
.determinePreferredLanguage();
}])
.value('Languages', {
en: 'English',
de: 'Deutsh',
//es: 'Español',
fr: 'Français',
ru: 'ру́сский'
});

View File

@@ -1,233 +0,0 @@
angular.module('app').config(['$translateProvider', 'localeFormatProvider', function($translateProvider, localeFormatProvider) {
// Declare number format settings
localeFormatProvider.addFormat('ru', {
decimal: ',',
thousands: '\xa0',
grouping: [3],
currency: ['', ' руб.'],
dateTime: '%A, %e %B %Y г. %X',
date: '%d.%m.%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота'],
shortDays: ['вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб'],
months: ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'],
shortMonths: ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
});
$translateProvider.translations('ru', {
PHRASE_EXPORT_DESC: 'Подробный экспорта JSON вашего телосложения для использования в других местах и инструментов',
'A-Rated': 'А-Класса',
about: 'О сайте',
action: 'Действие',
added: 'Добавлено',
Advanced: 'Продвинутый',
'Advanced Discovery Scanner': 'Продвинутый астросканер',
agility: 'Маневренность',
alpha: 'Альфа',
ammo: 'Боекомплект',
PHRASE_CONFIRMATION: 'Вы уверены?',
armour: 'Броня',
am: 'Ремонтный модуль',
available: 'доступно',
backup: 'Резервная копия',
'Basic Discovery Scanner': 'Стандартный исследовательский сканер',
bl: 'Лучевой лазер',
beta: 'Бета',
bins: 'контейнеры',
boost: 'форсаж',
build: 'cборка',
'build name': 'название сборки',
builds: 'cборки',
bh: 'Корпус',
ul: 'Мультиимпульсный лазер',
buy: 'купить',
cancel: 'отменить',
c: 'Пушка',
capital: 'Крупный',
cargo: 'Груз',
'Cargo Hatch': 'Грузовой люк',
cr: 'Грузовой отсек',
cs: 'Сканер груза',
cells: 'Ячейки',
'Chaff Launcher': 'Постановщик помех',
close: 'закрыть',
cc: 'Контроллер "дрон-сборщик"',
compare: 'сравнить ',
'compare all': 'сравнить все',
comparison: 'сравнение',
comparisons: 'сравнения',
component: 'Компонент',
cost: 'Стоимость',
costs: 'Расходы',
cm: 'Контрмеры',
CR: 'кр.',
create: 'создать',
'create new': 'Создать новый',
credits: 'Кредиты',
Cytoscrambler: 'сайтоскрамблер',
damage: 'Урон',
delete: 'Удалить',
'delete all': 'Удалить все',
dep: 'Вып',
deployed: 'Открыты',
'detailed export': 'Подробный экспорт',
'Detailed Surface Scanner': 'Подробный сканер поверхности',
disabled: 'Отключено',
discount: 'Скидка',
Distruptor: 'Дисраптор',
dc: 'Стыковочный компьютер',
done: 'готово',
DPS: 'УВС',
'edit data': 'Редактирование',
efficiency: 'Эффективность',
'Electronic Countermeasure': 'Электронная противомера',
empty: 'пусто',
Enforcer: 'Энфорсер',
ENG: 'ДВГ',
'enter name': 'Введите имя',
EPS: 'ЭВС',
export: 'Экспорт',
fixed: 'Фиксированое',
forum: 'Форум',
fc: 'Осколочное Орудие',
fd: 'Двигатель FSD',
ws: 'FSD Сканнер',
fi: 'Перехватчик FSD',
fuel: 'Топливо',
fs: 'Топливосборщик',
ft: 'Топливный бак',
fx: 'Контроллер Дрона-заправщика',
'full tank': 'Полный бак',
Gimballed: 'Шарнирное',
H: 'O',
hardpoints: 'Орудийные порты',
hb: 'Контроллер "дрон-взломщик"',
'Heat Sink Launcher': 'Теплоотводная ПУ',
huge: 'огромный',
hull: 'Корпус',
hr: 'Набор усиления корпуса',
'Imperial Hammer': 'Имперский Молот',
import: 'импортировать ',
'import all': 'импортировать все',
insurance: 'Страховка',
'Intermediate Discovery Scanner': 'Средний исследовательский сканер',
'internal compartments': 'внутренние отсеки',
'jump range': 'Дальность прыжка',
jumps: 'Прыжков',
kw: 'Полицейский сканер',
L: 'б',
laden: 'Груженый',
language: 'Язык',
large: 'большой',
ls: 'Система жизнеобеспечения',
'Lightweight Alloy': 'Легкий сплав',
'lock factor': 'Масс. блок',
LS: 'Св.сек',
LY: 'Св.лет',
M: 'С',
'm/s': 'м/с',
mass: 'Масса',
max: 'Макс',
'max mass': 'Максимальная масса',
medium: 'Средний',
'Military Grade Composite': 'Военный композит',
nl: 'Минноукладчик',
'Mining Lance': 'Бурильная сулица',
ml: 'Бурильный лазер',
'Mirrored Surface Composite': 'Зеркальный композит',
mr: 'Ракетная установка',
mc: 'Многоствольное орудие',
'net cost': 'разница в цене',
no: 'Нет',
PHRASE_NO_BUILDS: 'Нечего сравнивать',
PHRASE_NO_RETROCH: 'нет ранних версий сборки\конфигурации',
none: 'ни один',
'none created': 'не создано',
off: 'выкл',
on: 'вкл',
optimal: 'Оптимальный',
'optimal mass': 'Оптимальная масса',
'optimize mass': 'Оптимизировать массу',
overwrite: 'перезаписать',
Pacifier: 'Миротворец',
'Pack-Hound': 'Ракета "Гончая"',
PHRASE_IMPORT: 'Для импорта вставьте код в эту форму',
pen: 'ПБ',
penetration: 'Пробитие',
permalink: 'Постоянная ссылка',
pa: 'Ускоритель плазмы',
'Point Defence': 'Противоракетная защита',
power: 'Мощность',
pd: 'Распределитель энергии',
pp: 'Реактор',
pri: 'Осн',
priority: 'Приоритет',
psg: 'Генератор призматического щита',
proceed: 'продолжить',
pc: 'Контроллер "Дрон-исследователь"',
pl: 'Импульсный лазер',
PWR: 'Эн',
rg: 'Рельсотрон',
range: 'Дальность',
rate: 'скорость',
'Reactive Surface Composite': 'Динамическая защита',
recharge: 'Перезарядка',
rf: 'Переработка',
'refuel time': 'Время дозаправки',
'Reinforced Alloy': 'Усиленный сплав',
reload: 'Перезарядить',
rename: 'Переименовать',
repair: 'Починка',
reset: 'Сброс',
ret: 'Убр.',
retracted: 'Убрано',
'retrofit costs': 'цена модификации',
'retrofit from': 'модификация от',
ROF: 'В/сек',
S: 'М',
save: 'Сохранить',
sc: 'Сканер',
PHRASE_SELECT_BUILDS: 'Выберите конфигурацию для сравнения',
sell: 'Продать',
s: 'Сенсоры',
settings: 'Настройки',
sb: 'Усилитель щита',
scb: 'Батареи перезарядки щита',
sg: 'Генератор щита',
shields: 'Щиты',
ship: 'Корабль',
ships: 'Корабли',
shortened: 'Укороченный',
size: 'размер',
skip: 'пропустить',
small: 'Малый',
speed: 'скорость',
standard: 'Стандартный',
'Standard Docking Computer': 'Стандартный стыковочный компьютер',
Stock: 'Стандартная комплектация',
SYS: 'СИС',
T: 'Т',
T_LOAD: 'Тепл.',
'The Retributor': '"Возмездие"',
t: 'Двигатели',
time: 'Время',
tp: 'Торпедный аппарат',
total: 'Всего',
'total range': 'Общий радиус',
turret: 'Туррель',
type: 'Тип',
U: 'В',
unladen: 'Пустой',
PHRASE_UPDATE_RDY: 'Доступно обновление. Нажмите для обновления.',
URL: 'Ссылка',
utility: 'Вспомогательное',
'utility mounts': 'Вспомогательное оборудование',
version: 'Версия',
WEP: 'ОРУ',
yes: 'Да',
PHRASE_BACKUP_DESC: 'Сохраните все данные перед переносом в другой браузер или устройство'
});
}]);

View File

@@ -1,36 +0,0 @@
angular.module('app').provider('localeFormat', function localeFormatProvider() {
var formats = {
en: {
decimal: '.',
thousands: ',',
grouping: [3],
currency: ['$', ''],
dateTime: '%a %b %e %X %Y',
date: '%m/%d/%Y',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
}
};
function LocaleFormat(formatMap) {
this.formatMap = formatMap;
this.get = function(lang) {
return this.formatMap[lang] ? this.formatMap[lang] : this.formatMap.en;
};
}
this.addFormat = function(langCode, formatDetails) {
formats[langCode] = formatDetails;
};
this.$get = [function() {
return new LocaleFormat(formats);
}];
});

View File

@@ -1,314 +0,0 @@
/**
* [description]
*/
angular.module('app').service('Persist', ['$window', 'lodash', function($window, _) {
var LS_KEY_BUILDS = 'builds';
var LS_KEY_COMPARISONS = 'comparisons';
var LS_KEY_LANG = 'NG_TRANSLATE_LANG_KEY';
var LS_KEY_COST_TAB = 'costTab';
var LS_KEY_INSURANCE = 'insurance';
var LS_KEY_DISCOUNTS = 'discounts';
var localStorage = $window.localStorage;
var buildJson = null;
var comparisonJson = null;
// Safe check to determine if localStorage is enabled
try {
localStorage.setItem('s', 1);
localStorage.removeItem('s');
buildJson = localStorage.getItem(LS_KEY_BUILDS);
comparisonJson = localStorage.getItem(LS_KEY_COMPARISONS);
this.lsEnabled = true;
} catch(e) {
this.lsEnabled = false;
}
this.builds = buildJson ? angular.fromJson(buildJson) : {};
this.comparisons = comparisonJson ? angular.fromJson(comparisonJson) : {};
var buildCount = Object.keys(this.builds).length;
this.state = {
buildCount: buildCount,
hasBuilds: buildCount > 0,
hasComparisons: Object.keys(this.comparisons).length > 0
};
this.put = function(name, value) {
if (!this.lsEnabled) {
return;
}
localStorage.setItem(name, value);
};
this.get = function(name) {
return this.lsEnabled ? localStorage.getItem(name) : null;
};
this.getLangCode = function() {
return this.lsEnabled ? localStorage.getItem(LS_KEY_LANG) : null;
};
/**
* Persist a ship build in local storage.
*
* @param {string} shipId The unique id for a model of ship
* @param {string} name The name of the build
* @param {string} code The serialized code
*/
this.saveBuild = function(shipId, name, code) {
if (!this.lsEnabled) {
return;
}
if (!this.builds[shipId]) {
this.builds[shipId] = {};
}
if (!this.builds[shipId][name]) {
this.state.buildCount++;
this.state.hasBuilds = true;
}
this.builds[shipId][name] = code;
// Persist updated build collection to localStorage
localStorage.setItem(LS_KEY_BUILDS, angular.toJson(this.builds));
};
/**
* Get the serialized code/string for a build. Returns null if a
* build is not found.
*
* @param {string} shipId The unique id for a model of ship
* @param {string} name The name of the build
* @return {string} The serialized build string.
*/
this.getBuild = function(shipId, name) {
if (this.builds[shipId] && this.builds[shipId][name]) {
return this.builds[shipId][name];
}
return null;
};
/**
* Delete a build from local storage. It will also delete the ship build collection if
* it becomes empty
*
* @param {string} shipId The unique id for a model of ship
* @param {string} name The name of the build
*/
this.deleteBuild = function(shipId, name) {
if (this.lsEnabled && this.builds[shipId][name]) {
delete this.builds[shipId][name];
if (Object.keys(this.builds[shipId]).length === 0) {
delete this.builds[shipId];
this.state.buildCount--;
this.state.hasBuilds = this.state.buildCount > 0;
}
// Persist updated build collection to localStorage
localStorage.setItem(LS_KEY_BUILDS, angular.toJson(this.builds));
// Check if the build was used in existing comparisons
var comps = this.comparisons;
for (var c in comps) {
for (var i = 0; i < comps[c].builds.length; i++) { // For all builds in the current comparison
if (comps[c].builds[i].shipId == shipId && comps[c].builds[i].buildName == name) {
comps[c].builds.splice(i, 1);
break; // A build is unique ber comparison
}
}
}
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
}
};
/**
* Persist a comparison in localstorage.
*
* @param {string} name The name of the comparison
* @param {array} builds Array of builds
* @param {array} facets Array of facet indices
*/
this.saveComparison = function(name, builds, facets) {
if (!this.lsEnabled) {
return;
}
if (!this.comparisons[name]) {
this.comparisons[name] = {};
}
this.comparisons[name] = {
facets: facets,
builds: _.map(builds, function(b) { return { shipId: b.id || b.shipId, buildName: b.buildName }; })
};
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
this.state.hasComparisons = true;
};
/**
* [getComparison description]
* @param {string} name [description]
* @return {object} Object containing array of facets and ship id + build names
*/
this.getComparison = function(name) {
if (this.comparisons[name]) {
return this.comparisons[name];
}
return null;
};
/**
* Removes the comparison from localstorage.
* @param {string} name Comparison name
*/
this.deleteComparison = function(name) {
if (this.lsEnabled && this.comparisons[name]) {
delete this.comparisons[name];
localStorage.setItem(LS_KEY_COMPARISONS, angular.toJson(this.comparisons));
this.state.hasComparisons = Object.keys(this.comparisons).length > 0;
}
};
/**
* Delete all builds and comparisons from localStorage
*/
this.deleteAll = function() {
angular.copy({}, this.builds); // Empty object but keep original instance
angular.copy({}, this.comparisons);
this.state.hasBuilds = false;
this.state.buildCount = 0;
if (this.lsEnabled) {
localStorage.removeItem(LS_KEY_BUILDS);
localStorage.removeItem(LS_KEY_COMPARISONS);
}
};
this.getAll = function() {
var data = {};
data[LS_KEY_BUILDS] = this.builds;
data[LS_KEY_COMPARISONS] = this.comparisons;
data[LS_KEY_INSURANCE] = this.getInsurance();
data[LS_KEY_DISCOUNTS] = this.getDiscount();
return data;
};
/**
* Get the saved insurance type
* @return {string} The name of the saved insurance type of null
*/
this.getInsurance = function() {
if (this.lsEnabled) {
return localStorage.getItem(LS_KEY_INSURANCE);
}
return null;
};
/**
* Persist selected insurance type
* @param {string} name Insurance type name
*/
this.setInsurance = function(name) {
if (this.lsEnabled) {
return localStorage.setItem(LS_KEY_INSURANCE, name);
}
};
/**
* Persist selected discount
* @param {number} val Discount value/amount
*/
this.setDiscount = function(val) {
if (this.lsEnabled) {
return localStorage.setItem(LS_KEY_DISCOUNTS, angular.toJson(val));
}
};
/**
* Get the saved discount
* @return {number} val Discount value/amount
*/
this.getDiscount = function() {
if (this.lsEnabled) {
return angular.fromJson(localStorage.getItem(LS_KEY_DISCOUNTS));
}
return null;
};
/**
* Persist selected cost tab
* @param {number} val Discount value/amount
*/
this.setCostTab = function(tabName) {
if (this.lsEnabled) {
return localStorage.setItem(LS_KEY_COST_TAB, tabName);
}
};
/**
* Get the saved discount
* @return {number} val Discount value/amount
*/
this.getCostTab = function() {
if (this.lsEnabled) {
return localStorage.getItem(LS_KEY_COST_TAB);
}
return null;
};
/**
* Retrieve the last router state from local storage
* @return {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));
}
};
/**
* Retrieve the last router state from local storage
* @return {number} size Ratio
*/
this.getSizeRatio = function() {
if (this.lsEnabled) {
var ratio = localStorage.getItem('sizeRatio');
if (!isNaN(ratio) && ratio > 0.6) {
return ratio;
}
}
return 1;
};
/**
* Save the current size ratio to localstorage
* @param {number} sizeRatio
*/
this.setSizeRatio = function(sizeRatio) {
if (this.lsEnabled) {
localStorage.setItem('sizeRatio', sizeRatio);
}
};
/**
* Check if localStorage is enabled/active
* @return {Boolean} True if localStorage is enabled
*/
this.isEnabled = function() {
return this.lsEnabled;
};
}]);

View File

@@ -1,246 +0,0 @@
/**
* Service managing seralization and deserialization of models for use in URLs and persistene.
*/
angular.module('app').service('Serializer', ['lodash', 'GroupMap', 'MountMap', 'ShipsDB', 'Ship', 'Components', '$state', function(_, GroupMap, MountMap, ShipsDB, Ship, Components, $state) {
/**
* Serializes the ships selected components for all slots to a URL friendly string.
* @param {Ship} ship The ship to be serialized.
* @return {string} Encoded string of components
*/
this.fromShip = function(ship) {
var power = {
enabled: [ship.cargoHatch.enabled ? 1 : 0],
priorities: [ship.cargoHatch.priority]
};
var data = [
ship.bulkheads.id,
_.map(ship.common, mapGroup, power),
_.map(ship.hardpoints, mapGroup, power),
_.map(ship.internal, mapGroup, power),
'.',
LZString.compressToBase64(power.enabled.join('')).replace(/\//g, '-'),
'.',
LZString.compressToBase64(power.priorities.join('')).replace(/\//g, '-')
];
return _.flatten(data).join('');
};
/**
* Updates an existing ship instance's slots with components determined by the
* code.
*
* @param {Ship} ship The ship instance to be updated
* @param {string} dataString The string to deserialize
*/
this.toShip = function(ship, dataString) {
var common = new Array(ship.common.length),
hardpoints = new Array(ship.hardpoints.length),
internal = new Array(ship.internal.length),
parts = dataString.split('.'),
priorities = null,
enabled = null,
code = parts[0];
if (parts[1]) {
enabled = LZString.decompressFromBase64(parts[1].replace(/-/g, '/')).split('');
}
if (parts[2]) {
priorities = LZString.decompressFromBase64(parts[2].replace(/-/g, '/')).split('');
}
decodeToArray(code, internal, decodeToArray(code, hardpoints, decodeToArray(code, common, 1)));
ship.buildWith(
{
bulkheads: code.charAt(0) * 1,
common: common,
hardpoints: hardpoints,
internal: internal
},
priorities,
enabled
);
};
this.toDetailedBuild = function(buildName, ship, code) {
var standard = ship.common,
hardpoints = ship.hardpoints,
internal = ship.internal;
var data = {
$schema: 'http://cdn.coriolis.io/schemas/ship-loadout/2.json#',
name: buildName,
ship: ship.name,
references: [{
name: 'Coriolis.io',
url: $state.href('outfit', { shipId: ship.id, code: code, bn: buildName }, { absolute: true }),
code: code,
shipId: ship.id
}],
components: {
standard: {
bulkheads: ship.bulkheads.c.name,
cargoHatch: { enabled: Boolean(ship.cargoHatch.enabled), priority: ship.cargoHatch.priority + 1 },
powerPlant: { class: standard[0].c.class, rating: standard[0].c.rating, enabled: Boolean(standard[0].enabled), priority: standard[0].priority + 1 },
thrusters: { class: standard[1].c.class, rating: standard[1].c.rating, enabled: Boolean(standard[1].enabled), priority: standard[1].priority + 1 },
frameShiftDrive: { class: standard[2].c.class, rating: standard[2].c.rating, enabled: Boolean(standard[2].enabled), priority: standard[2].priority + 1 },
lifeSupport: { class: standard[3].c.class, rating: standard[3].c.rating, enabled: Boolean(standard[3].enabled), priority: standard[3].priority + 1 },
powerDistributor: { class: standard[4].c.class, rating: standard[4].c.rating, enabled: Boolean(standard[4].enabled), priority: standard[4].priority + 1 },
sensors: { class: standard[5].c.class, rating: standard[5].c.rating, enabled: Boolean(standard[5].enabled), priority: standard[5].priority + 1 },
fuelTank: { class: standard[6].c.class, rating: standard[6].c.rating, enabled: Boolean(standard[6].enabled), priority: standard[6].priority + 1 }
},
hardpoints: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass > 0; }), slotToSchema),
utility: _.map(_.filter(hardpoints, function(slot) { return slot.maxClass === 0; }), slotToSchema),
internal: _.map(internal, slotToSchema)
},
stats: {}
};
for (var stat in ship) {
if (!isNaN(ship[stat])) {
data.stats[stat] = Math.round(ship[stat] * 100) / 100;
}
}
return data;
};
this.fromDetailedBuild = function(detailedBuild) {
var shipId = _.findKey(ShipsDB, { properties: { name: detailedBuild.ship } });
if (!shipId) {
throw 'No such ship: ' + detailedBuild.ship;
}
var comps = detailedBuild.components;
var standard = comps.standard;
var priorities = [ standard.cargoHatch && standard.cargoHatch.priority !== undefined ? standard.cargoHatch.priority - 1 : 0 ];
var enabled = [ standard.cargoHatch && standard.cargoHatch.enabled !== undefined ? standard.cargoHatch.enabled : true ];
var shipData = ShipsDB[shipId];
var ship = new Ship(shipId, shipData.properties, shipData.slots);
var bulkheads = Components.bulkheadIndex(standard.bulkheads);
if (bulkheads < 0) {
throw 'Invalid bulkheads: ' + standard.bulkheads;
}
var common = _.map(
['powerPlant', 'thrusters', 'frameShiftDrive', 'lifeSupport', 'powerDistributor', 'sensors', 'fuelTank'],
function(c) {
if (!standard[c].class || !standard[c].rating) {
throw 'Invalid value for ' + c;
}
priorities.push(standard[c].priority === undefined ? 0 : standard[c].priority - 1);
enabled.push(standard[c].enabled === undefined ? true : standard[c].enabled);
return standard[c].class + standard[c].rating;
}
);
var internal = _.map(comps.internal, function(c) { return c ? Components.findInternalId(c.group, c.class, c.rating, c.name) : 0; });
var hardpoints = _.map(comps.hardpoints, function(c) {
return c ? Components.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount], c.missile) : 0;
});
hardpoints = hardpoints.concat(_.map(comps.utility, function(c) {
return c ? Components.findHardpointId(c.group, c.class, c.rating, c.name, MountMap[c.mount]) : 0;
}));
// The ordering of these arrays must match the order in which they are read in Ship.buildWith
priorities = priorities.concat(_.map(comps.hardpoints, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; }),
_.map(comps.utility, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; }),
_.map(comps.internal, function(c) { return (!c || c.priority === undefined) ? 0 : c.priority - 1; }));
enabled = enabled.concat(_.map(comps.hardpoints, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; }),
_.map(comps.utility, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; }),
_.map(comps.internal, function(c) { return (!c || c.enabled === undefined) ? true : c.enabled * 1; }));
ship.buildWith({ bulkheads: bulkheads, common: common, hardpoints: hardpoints, internal: internal }, priorities, enabled);
return ship;
};
this.toDetailedExport = function(builds) {
var data = [];
for (var shipId in builds) {
for (var buildName in builds[shipId]) {
var code = builds[shipId][buildName];
var shipData = ShipsDB[shipId];
var ship = new Ship(shipId, shipData.properties, shipData.slots);
this.toShip(ship, code);
data.push(this.toDetailedBuild(buildName, ship, code));
}
}
return data;
};
this.fromComparison = function(name, builds, facets, predicate, desc) {
var shipBuilds = [];
builds.forEach(function(b) {
shipBuilds.push({ s: b.id, n: b.buildName, c: this.fromShip(b) });
}.bind(this));
return LZString.compressToBase64(angular.toJson({
n: name,
b: shipBuilds,
f: facets,
p: predicate,
d: desc ? 1 : 0
})).replace(/\//g, '-');
};
this.toComparison = function(code) {
return angular.fromJson(LZString.decompressFromBase64(code.replace(/-/g, '/')));
};
/**
* Utility function to retrieve a safe string for selected component for a slot.
* Used for serialization to code only.
*
* @private
* @param {object} slot The slot object.
* @return {string} The id of the selected component or '-' if none selected
*/
function mapGroup(slot) {
this.enabled.push(slot.enabled ? 1 : 0);
this.priorities.push(slot.priority);
return slot.id === null ? '-' : slot.id;
}
function decodeToArray(code, arr, codePos) {
for (var i = 0; i < arr.length; i++) {
if (code.charAt(codePos) == '-') {
arr[i] = 0;
codePos++;
} else {
arr[i] = code.substring(codePos, codePos + 2);
codePos += 2;
}
}
return codePos;
}
function slotToSchema(slot) {
if (slot.c) {
var o = { class: slot.c.class, rating: slot.c.rating, enabled: Boolean(slot.enabled), priority: slot.priority + 1, group: GroupMap[slot.c.grp] };
if (slot.c.name) {
o.name = slot.c.name;
}
if (slot.c.mode) {
o.mount = MountMap[slot.c.mode];
}
if (slot.c.missile) {
o.missile = slot.c.missile;
}
return o;
}
return null;
}
}]);

View File

@@ -1,134 +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 getKey(maxClass, eligible) {
if (eligible) {
return maxClass + Object.keys(eligible).join('-');
}
return maxClass;
}
function ComponentSet(components, mass, maxCommonArr, maxInternal, maxHardPoint) {
this.mass = mass;
this.common = {};
this.internal = {};
this.hardpoints = {};
this.hpClass = {};
this.intClass = {};
this.common[0] = filter(components.common[0], maxCommonArr[0], 0, mass); // Power Plant
this.common[2] = filter(components.common[2], maxCommonArr[2], 0, mass); // FSD
this.common[4] = filter(components.common[4], maxCommonArr[4], 0, mass); // Power Distributor
this.common[6] = filter(components.common[6], maxCommonArr[6], 0, mass); // Fuel Tank
// Thrusters, filter components by class only (to show full list of ratings for that class)
var minThrusterClass = _.reduce(components.common[1], function(minClass, thruster) {
return (thruster.maxmass >= mass && thruster.class < minClass) ? thruster.class : minClass;
}, maxCommonArr[1]);
this.common[1] = filter(components.common[1], maxCommonArr[1], minThrusterClass, 0); // Thrusters
// Slots where component class must be equal to slot class
this.common[3] = filter(components.common[3], maxCommonArr[3], maxCommonArr[3], 0); // Life Supprt
this.common[5] = filter(components.common[5], maxCommonArr[5], maxCommonArr[5], mass); // Sensors
for (var h in components.hardpoints) {
this.hardpoints[h] = filter(components.hardpoints[h], maxHardPoint, 0, mass);
}
for (var g in components.internal) {
this.internal[g] = filter(components.internal[g], maxInternal, 0, mass);
}
/**
* Create a memoized function for determining the components that are
* eligible for an internal slot
* @param {integer} c The max class component that can be mounted in the slot
* @param {Object} eligible) The map of eligible internal groups
* @return {object} A map of all eligible components by group
*/
this.getInts = _.memoize(
function(c, eligible) {
var o = {};
for (var key in this.internal) {
if (eligible && !eligible[key]) {
continue;
}
var data = filter(this.internal[key], c, 0, this.mass);
if (data.length) { // If group is not empty
o[key] = data;
}
}
return o;
},
getKey
);
/**
* Create a memoized function for determining the components that are
* eligible for an hardpoint slot
* @param {integer} c The max class component that can be mounted in the slot
* @param {Object} eligible) The map of eligible hardpoint groups
* @return {object} A map of all eligible components by group
*/
this.getHps = _.memoize(
function(c, eligible) {
var o = {};
for (var key in this.hardpoints) {
if (eligible && !eligible[key]) {
continue;
}
var data = filter(this.hardpoints[key], c, c ? 1 : 0, this.mass);
if (data.length) { // If group is not empty
o[key] = data;
}
}
return o;
},
getKey
);
}
ComponentSet.prototype.lightestPowerDist = function(boostEnergy) {
var pds = this.common[4];
var pd = pds[0];
for (var i = 1; i < pds.length; i++) {
if (pds[i].mass < pd.mass && pds[i].enginecapacity >= boostEnergy) {
pd = pds[i];
}
}
return pd.class + pd.rating;
};
ComponentSet.prototype.lightestThruster = function(ladenMass) {
var ths = this.common[1];
var th = ths[0];
for (var i = 1; i < ths.length; i++) {
if (ths[i].mass < th.mass && ths[i].maxmass >= ladenMass) {
th = ths[i];
}
}
return th.class + th.rating;
};
ComponentSet.prototype.lightestPowerPlant = function(powerUsed) {
var pps = this.common[0];
var pp = null;
for (var i = 0; i < pps.length; i++) {
if (pp == null || (pps[i].mass < pp.mass && pps[i].pGen >= powerUsed)) {
pp = pps[i];
}
}
return pp.class + (pp.rating != 'D' ? 'A' : 'D'); // Use A rated if C,E
};
return ComponentSet;
}]);

View File

@@ -1,440 +0,0 @@
angular.module('shipyard').factory('Ship', ['Components', 'calcShieldStrength', 'calcJumpRange', 'calcTotalRange', 'lodash', 'ArmourMultiplier', function(Components, calcShieldStrength, calcJumpRange, calcTotalRange, _, ArmourMultiplier) {
/**
* Returns the power usage type of a slot and it's particular component
* @param {object} slot The Slot
* @param {object} component The component in the slot
* @return {string} The key for the power usage type
*/
function powerUsageType(slot, component) {
if (component) {
if (component.retractedOnly) {
return 'retOnly';
}
if (component.passive) {
return 'retracted';
}
}
return slot.cat != 1 ? 'retracted' : 'deployed';
}
/**
* Ship model used to track all ship components and properties.
*
* @param {string} id Unique ship Id / Key
* @param {object} properties Basic ship properties such as name, manufacturer, mass, etc
* @param {object} slots Collection of slot groups (standard/common, internal, hardpoints) with their max class size.
*/
function Ship(id, properties, slots) {
this.id = id;
this.cargoHatch = { c: Components.cargoHatch(), type: 'SYS' };
this.bulkheads = { incCost: true, maxClass: 8 };
for (var p in properties) { this[p] = properties[p]; } // Copy all base properties from shipData
for (var slotType in slots) { // Initialize all slots
var slotGroup = slots[slotType];
var group = this[slotType] = []; // Initialize Slot group (Common, Hardpoints, Internal)
for (var i = 0; i < slotGroup.length; i++) {
if (typeof slotGroup[i] == 'object') {
group.push({ id: null, c: null, incCost: true, maxClass: slotGroup[i].class, eligible: slotGroup[i].eligible });
} else {
group.push({ id: null, c: null, incCost: true, maxClass: slotGroup[i] });
}
}
}
// Make a Ship 'slot'/item similar to other slots
this.c = { incCost: true, type: 'SHIP', discountedCost: this.hullCost, c: { name: this.name, cost: this.hullCost } };
this.costList = _.union(this.internal, this.common, this.hardpoints);
this.costList.push(this.bulkheads); // Add The bulkheads
this.costList.unshift(this.c); // Add the ship itself to the list
this.powerList = _.union(this.internal, this.hardpoints);
this.powerList.unshift(this.cargoHatch);
this.powerList.unshift(this.common[1]); // Add Thrusters
this.powerList.unshift(this.common[5]); // Add Sensors
this.powerList.unshift(this.common[4]); // Add Power Distributor
this.powerList.unshift(this.common[3]); // Add Life Support
this.powerList.unshift(this.common[2]); // Add FSD
this.powerList.unshift(this.common[0]); // Add Power Plant
this.shipCostMultiplier = 1;
this.componentCostMultiplier = 1;
this.priorityBands = [
{ deployed: 0, retracted: 0, retOnly: 0 },
{ deployed: 0, retracted: 0, retOnly: 0 },
{ deployed: 0, retracted: 0, retOnly: 0 },
{ deployed: 0, retracted: 0, retOnly: 0 },
{ deployed: 0, retracted: 0, retOnly: 0 }
];
}
/**
* Builds/Updates the ship instance with the components[comps] passed in.
* @param {object} comps Collection of components used to build the ship
*/
Ship.prototype.buildWith = function(comps, priorities, enabled) {
var internal = this.internal,
common = this.common,
hps = this.hardpoints,
bands = this.priorityBands,
cl = common.length,
i, l;
// Reset Cumulative stats
this.fuelCapacity = 0;
this.cargoCapacity = 0;
this.ladenMass = 0;
this.armourAdded = 0;
this.armourMultiplier = 1;
this.shieldMultiplier = 1;
this.totalCost = this.c.incCost ? this.c.discountedCost : 0;
this.unladenMass = this.hullMass;
this.totalDps = 0;
this.bulkheads.c = null;
this.useBulkhead(comps && comps.bulkheads ? comps.bulkheads : 0, true);
this.cargoHatch.priority = priorities ? priorities[0] * 1 : 0;
this.cargoHatch.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.cargoHatch.enabled) {
bands[this.cargoHatch.priority].retracted += this.cargoHatch.c.power;
}
for (i = 0; i < cl; i++) {
common[i].cat = 0;
common[i].enabled = enabled ? enabled[i + 1] * 1 : true;
common[i].priority = priorities ? priorities[i + 1] * 1 : 0;
common[i].type = 'SYS';
common[i].c = common[i].id = null; // Resetting 'old' component if there was one
common[i].discountedCost = 0;
if (comps) {
this.use(common[i], comps.common[i], Components.common(i, comps.common[i]), true);
}
}
common[1].type = 'ENG'; // Thrusters
common[2].type = 'ENG'; // FSD
cl++; // Increase accounts for Cargo Scoop
for (i = 0, l = hps.length; i < l; i++) {
hps[i].cat = 1;
hps[i].enabled = enabled ? enabled[cl + i] * 1 : true;
hps[i].priority = priorities ? priorities[cl + i] * 1 : 0;
hps[i].type = hps[i].maxClass ? 'WEP' : 'SYS';
hps[i].c = hps[i].id = null; // Resetting 'old' component if there was one
hps[i].discountedCost = 0;
if (comps && comps.hardpoints[i] !== 0) {
this.use(hps[i], comps.hardpoints[i], Components.hardpoints(comps.hardpoints[i]), true);
}
}
cl += hps.length; // Increase accounts for hardpoints
for (i = 0, l = internal.length; i < l; i++) {
internal[i].cat = 2;
internal[i].enabled = enabled ? enabled[cl + i] * 1 : true;
internal[i].priority = priorities ? priorities[cl + i] * 1 : 0;
internal[i].type = 'SYS';
internal[i].id = internal[i].c = null; // Resetting 'old' component if there was one
internal[i].discountedCost = 0;
if (comps && comps.internal[i] !== 0) {
this.use(internal[i], comps.internal[i], Components.internal(comps.internal[i]), true);
}
}
// Update aggragated stats
if (comps) {
this.updatePower();
this.updateJumpStats();
this.updateShieldStrength();
}
};
Ship.prototype.useBulkhead = function(index, preventUpdate) {
var oldBulkhead = this.bulkheads.c;
this.bulkheads.id = index;
this.bulkheads.c = Components.bulkheads(this.id, index);
this.bulkheads.discountedCost = this.bulkheads.c.cost * this.componentCostMultiplier;
this.armourMultiplier = ArmourMultiplier[index];
this.updateStats(this.bulkheads, this.bulkheads.c, oldBulkhead, preventUpdate);
};
/**
* Update a slot with a the component if the id is different from the current id for this slot.
* Has logic handling components that you may only have 1 of (Shield Generator or Refinery).
*
* @param {object} slot The component slot
* @param {string} id Unique ID for the selected component
* @param {object} component Properties for the selected component
* @param {boolean} preventUpdate If true, do not update aggregated stats
*/
Ship.prototype.use = function(slot, id, component, preventUpdate) {
if (slot.id != id) { // Selecting a different component
// Slot is an internal slot, is not being emptied, and the selected component group/type must be of unique
if (slot.cat == 2 && component && _.includes(['psg', 'sg', 'rf', 'fs'], component.grp)) {
// Find another internal slot that already has this type/group installed
var similarSlot = this.findInternalByGroup(component.grp);
// If another slot has an installed component with of the same type
if (!preventUpdate && similarSlot && similarSlot !== slot) {
this.updateStats(similarSlot, null, similarSlot.c, true); // Update stats but don't trigger a global update
similarSlot.id = similarSlot.c = null; // Empty the slot
similarSlot.discountedCost = 0;
}
}
var oldComponent = slot.c;
slot.id = id;
slot.c = component;
slot.discountedCost = (component && component.cost) ? component.cost * this.componentCostMultiplier : 0;
this.updateStats(slot, component, oldComponent, preventUpdate);
}
};
/**
* Calculate jump range using the installed FSD and the
* specified mass which can be more or less than ships actual mass
* @param {number} mass Mass in tons
* @param {number} fuel Fuel available in tons
* @return {number} Jump range in Light Years
*/
Ship.prototype.jumpRangeWithMass = function(mass, fuel) {
return calcJumpRange(mass, this.common[2].c, fuel);
};
/**
* Find an internal slot that has an installed component of the specific group.
*
* @param {string} group Component group/type
* @return {number} The index of the slot in ship.internal
*/
Ship.prototype.findInternalByGroup = function(group) {
var index;
if (group == 'sg' || group == 'psg') {
index = _.findIndex(this.internal, function(slot) {
return slot.c && (slot.c.grp == 'sg' || slot.c.grp == 'psg');
});
} else {
index = _.findIndex(this.internal, function(slot) {
return slot.c && slot.c.grp == group;
});
}
if (index !== -1) {
return this.internal[index];
}
return null;
};
/**
* Will change the priority of the specified slot if the new priority is valid
* @param {object} slot The slot to be updated
* @param {number} newPriority The new priority to be set
* @return {boolean} Returns true if the priority was changed (within range)
*/
Ship.prototype.changePriority = function(slot, newPriority) {
if (newPriority >= 0 && newPriority < this.priorityBands.length) {
var oldPriority = slot.priority;
slot.priority = newPriority;
if (slot.enabled) { // Only update power if the slot is enabled
var usage = powerUsageType(slot, slot.c);
this.priorityBands[oldPriority][usage] -= slot.c.power;
this.priorityBands[newPriority][usage] += slot.c.power;
this.updatePower();
}
return true;
}
return false;
};
Ship.prototype.setCostIncluded = function(item, included) {
if (item.incCost != included && item.c) {
this.totalCost += included ? item.discountedCost : -item.discountedCost;
}
item.incCost = included;
};
Ship.prototype.setSlotEnabled = function(slot, enabled) {
if (slot.enabled != enabled) { // Enabled state is changing
slot.enabled = enabled;
if (slot.c) {
this.priorityBands[slot.priority][powerUsageType(slot, slot.c)] += enabled ? slot.c.power : -slot.c.power;
if (slot.c.grp == 'sg' || slot.c.grp == 'psg') {
this.updateShieldStrength();
} else if (slot.c.grp == 'sb') {
this.shieldMultiplier += slot.c.shieldmul * (enabled ? 1 : -1);
this.updateShieldStrength();
} else if (slot.c.dps) {
this.totalDps += slot.c.dps * (enabled ? 1 : -1);
}
this.updatePower();
}
}
};
Ship.prototype.getSlotStatus = function(slot, deployed) {
if (!slot.c) { // Empty Slot
return 0; // No Status (Not possible)
} else if (!slot.enabled) {
return 1; // Disabled
} else if (deployed && !slot.c.retractedOnly) { // Certain component (e.g. Detaild Surface scanner) are power only while retracted
return this.priorityBands[slot.priority].deployedSum >= this.powerAvailable ? 2 : 3; // Offline : Online
// Active hardpoints have no retracted status
} else if ((deployed && slot.c.retractedOnly) || (slot.cat === 1 && !slot.c.passive)) {
return 0; // No Status (Not possible)
}
return this.priorityBands[slot.priority].retractedSum >= this.powerAvailable ? 2 : 3; // Offline : Online
};
/**
* Updates the ship's cumulative and aggregated stats based on the component change.
*/
Ship.prototype.updateStats = function(slot, n, old, preventUpdate) {
var powerChange = slot == this.common[0];
if (old) { // Old component now being removed
switch (old.grp) {
case 'ft':
this.fuelCapacity -= old.capacity;
break;
case 'cr':
this.cargoCapacity -= old.capacity;
break;
case 'hr':
this.armourAdded -= old.armouradd;
break;
case 'sb':
this.shieldMultiplier -= slot.enabled ? old.shieldmul : 0;
break;
}
if (slot.incCost && old.cost) {
this.totalCost -= old.cost * this.componentCostMultiplier;
}
if (old.power && slot.enabled) {
this.priorityBands[slot.priority][powerUsageType(slot, old)] -= old.power;
powerChange = true;
if (old.dps) {
this.totalDps -= old.dps;
}
}
this.unladenMass -= old.mass || 0;
}
if (n) {
switch (n.grp) {
case 'ft':
this.fuelCapacity += n.capacity;
break;
case 'cr':
this.cargoCapacity += n.capacity;
break;
case 'hr':
this.armourAdded += n.armouradd;
break;
case 'sb':
this.shieldMultiplier += slot.enabled ? n.shieldmul : 0;
break;
}
if (slot.incCost && n.cost) {
this.totalCost += n.cost * this.componentCostMultiplier;
}
if (n.power && slot.enabled) {
this.priorityBands[slot.priority][powerUsageType(slot, n)] += n.power;
powerChange = true;
if (n.dps) {
this.totalDps += n.dps;
}
}
this.unladenMass += n.mass || 0;
}
this.ladenMass = this.unladenMass + this.cargoCapacity + this.fuelCapacity;
this.armour = this.armourAdded + Math.round(this.baseArmour * this.armourMultiplier);
if (!preventUpdate) {
if (powerChange) {
this.updatePower();
}
this.updateJumpStats();
this.updateShieldStrength();
}
};
Ship.prototype.updatePower = function() {
var bands = this.priorityBands;
var prevRetracted = 0, prevDeployed = 0;
for (var i = 0, l = bands.length; i < l; i++) {
var band = bands[i];
prevRetracted = band.retractedSum = prevRetracted + band.retracted + band.retOnly;
prevDeployed = band.deployedSum = prevDeployed + band.deployed + band.retracted;
}
this.powerAvailable = this.common[0].c.pGen;
this.powerRetracted = prevRetracted;
this.powerDeployed = prevDeployed;
};
Ship.prototype.updateShieldStrength = function() {
var sgSlot = this.findInternalByGroup('sg'); // Find Shield Generator slot Index if any
this.shieldStrength = sgSlot && sgSlot.enabled ? calcShieldStrength(this.hullMass, this.baseShieldStrength, sgSlot.c, this.shieldMultiplier) : 0;
};
/**
* Jump Range and total range calculations
*/
Ship.prototype.updateJumpStats = function() {
var fsd = this.common[2].c; // Frame Shift Drive;
this.unladenRange = calcJumpRange(this.unladenMass + fsd.maxfuel, fsd, this.fuelCapacity); // Include fuel weight for jump
this.fullTankRange = calcJumpRange(this.unladenMass + this.fuelCapacity, fsd, this.fuelCapacity); // Full Tanke
this.ladenRange = calcJumpRange(this.ladenMass, fsd, this.fuelCapacity);
this.unladenTotalRange = calcTotalRange(this.unladenMass, fsd, this.fuelCapacity);
this.ladenTotalRange = calcTotalRange(this.unladenMass + this.cargoCapacity, fsd, this.fuelCapacity);
this.maxJumpCount = Math.ceil(this.fuelCapacity / fsd.maxfuel);
};
/**
* Recalculate all item costs and total based on discounts.
* @param {number} shipCostMultiplier Ship cost multiplier discount (e.g. 0.9 === 10% discount)
* @param {number} componentCostMultiplier Component cost multiplier discount (e.g. 0.75 === 25% discount)
*/
Ship.prototype.applyDiscounts = function(shipCostMultiplier, componentCostMultiplier) {
var total = 0;
var costList = this.costList;
for (var i = 0, l = costList.length; i < l; i++) {
var item = costList[i];
if (item.c && item.c.cost) {
item.discountedCost = item.c.cost * (item.type == 'SHIP' ? shipCostMultiplier : componentCostMultiplier);
if (item.incCost) {
total += item.discountedCost;
}
}
}
this.shipCostMultiplier = shipCostMultiplier;
this.componentCostMultiplier = componentCostMultiplier;
this.totalCost = total;
};
return Ship;
}]);

View File

@@ -1,247 +0,0 @@
/**
* This module contains all of the logic and models corresponding to
* information or behavoir in Elite Dangerous.
*
* This file contains values and functions that can be reused across the app.
*
* @requires ngLodash
*/
angular.module('shipyard', ['ngLodash'])
// Create 'angularized' references to DB. This will aid testing
.constant('ShipsDB', DB.ships)
.constant('ComponentsDB', DB.components)
.value('ArmourMultiplier', [
1, // Lightweight
1.4, // Reinforced
1.945, // Military
1.945, // Mirrored
1.945 // Reactive
])
// Map to lookup group labels/names for component grp, used for JSON Serialization
.value('GroupMap', {
// Common
pp: 'Power Plant',
t: 'Thrusters',
fsd: 'Frame Shift Drive',
ls: 'Life Support',
pd: 'Power Distributor',
s: 'Sensors',
ft: 'Fuel Tank',
// Internal
fs: 'Fuel Scoop',
sc: 'Scanner',
am: 'Auto Field-Maintenance Unit',
cr: 'Cargo Rack',
fi: 'FSD Interdictor',
hb: 'Hatch Breaker Limpet Controller',
hr: 'Hull Reinforcement Package',
rf: 'Refinery',
scb: 'Shield Cell Bank',
sg: 'Shield Generator',
psg: 'Prismatic Shield Generator',
dc: 'Docking Computer',
fx: 'Fuel Transfer Limpet Controller',
pc: 'Prospector Limpet Controller',
cc: 'Collector Limpet Controller',
// Hard Points
bl: 'Beam Laser',
ul: 'Burst Laser',
c: 'Cannon',
cs: 'Cargo Scanner',
cm: 'Countermeasure',
fc: 'Fragment Cannon',
ws: 'Frame Shift Wake Scanner',
kw: 'Kill Warrant Scanner',
nl: 'Mine Launcher',
ml: 'Mining Laser',
mr: 'Missile Rack',
pa: 'Plasma Accelerator',
mc: 'Multi-cannon',
pl: 'Pulse Laser',
rg: 'Rail Gun',
sb: 'Shield Booster',
tp: 'Torpedo Pylon'
})
.value('MountMap', {
'F': 'Fixed',
'G': 'Gimballed',
'T': 'Turret',
'Fixed': 'F',
'Gimballed': 'G',
'Turret': 'T'
})
/**
* Array of all Ship properties (facets) organized into groups
* used for ship comparisons.
*
* @type {Array}
*/
.value('ShipFacets', [
{ // 0
title: 'agility',
props: ['agility'],
unit: '',
fmt: 'fCrd'
},
{ // 1
title: 'speed',
props: ['speed', 'boost'],
lbls: ['thrusters', 'boost'],
unit: 'm/s',
fmt: 'fRound'
},
{ // 2
title: 'armour',
props: ['armour'],
unit: '',
fmt: 'fCrd'
},
{ // 3
title: 'shields',
props: ['shieldStrength'],
unit: 'MJ',
fmt: 'fRound'
},
{ // 4
title: 'jump range',
props: ['unladenRange', 'fullTankRange', 'ladenRange'],
lbls: ['max', 'full tank', 'laden'],
unit: 'LY',
fmt: 'fRound'
},
{ // 5
title: 'mass',
props: ['unladenMass', 'ladenMass'],
lbls: ['unladen', 'laden'],
unit: 'T',
fmt: 'fRound'
},
{ // 6
title: 'cargo',
props: ['cargoCapacity'],
unit: 'T',
fmt: 'fRound'
},
{ // 7
title: 'fuel',
props: ['fuelCapacity'],
unit: 'T',
fmt: 'fRound'
},
{ // 8
title: 'power',
props: ['powerRetracted', 'powerDeployed', 'powerAvailable'],
lbls: ['retracted', 'deployed', 'available'],
unit: 'MW',
fmt: 'fPwr'
},
{ // 9
title: 'cost',
props: ['totalCost'],
unit: 'CR',
fmt: 'fCrd'
},
{ // 10
title: 'total range',
props: ['unladenTotalRange', 'ladenTotalRange'],
lbls: ['unladen', 'laden'],
unit: 'LY',
fmt: 'fRound'
},
{ // 11
title: 'DPS',
props: ['totalDps'],
lbls: ['DPS'],
unit: '',
fmt: 'fRound'
}
])
/**
* Set of all available / theoretical discounts
*/
.value('Discounts', {
'0%': 1,
'5%': 0.95,
'10%': 0.90,
'15%': 0.85,
'20%': 0.80,
'25%': 0.75
})
/**
* Calculate the maximum single jump range based on mass and a specific FSD
*
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
* @param {number} fuel Optional - The fuel consumed during the jump (must be less than the drives max fuel per jump)
* @return {number} Distance in Light Years
*/
.value('calcJumpRange', function(mass, fsd, fuel) {
return Math.pow(Math.min(fuel === undefined ? fsd.maxfuel : fuel, fsd.maxfuel) / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass;
})
/**
* Calculate the total range based on mass and a specific FSD, and all fuel available
*
* @param {number} mass Mass of a ship: laden, unlanden, partially laden, etc
* @param {object} fsd The FDS object/component with maxfuel, fuelmul, fuelpower, optmass
* @param {number} fuel The total fuel available
* @return {number} Distance in Light Years
*/
.value('calcTotalRange', function(mass, fsd, fuel) {
var fuelRemaining = fuel % fsd.maxfuel; // Fuel left after making N max jumps
var jumps = Math.floor(fuel / fsd.maxfuel);
mass += fuelRemaining;
// Going backwards, start with the last jump using the remaining fuel
var totalRange = fuelRemaining > 0 ? Math.pow(fuelRemaining / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass : 0;
// For each max fuel jump, calculate the max jump range based on fuel mass left in the tank
for (var j = 0; j < jumps; j++) {
mass += fsd.maxfuel;
totalRange += Math.pow(fsd.maxfuel / fsd.fuelmul, 1 / fsd.fuelpower ) * fsd.optmass / mass;
}
return totalRange;
})
/**
* Calculate the a ships shield strength based on mass, shield generator and shield boosters used.
*
* @private
* @param {number} mass Current mass of the ship
* @param {number} shields Base Shield strength MJ for ship
* @param {object} sg The shield generator used
* @param {number} multiplier Shield multiplier for ship (1 + shield boosters if any)
* @return {number} Approximate shield strengh in MJ
*/
.value('calcShieldStrength', function(mass, shields, sg, multiplier) {
var opt;
if (mass < sg.minmass) {
return shields * multiplier * sg.minmul;
}
if (mass > sg.maxmass) {
return shields * multiplier * sg.maxmul;
}
if (mass < sg.optmass) {
opt = (sg.optmass - mass) / (sg.optmass - sg.minmass);
opt = 1 - Math.pow(1 - opt, 0.87);
return shields * multiplier * ((opt * sg.minmul) + ((1 - opt) * sg.optmul));
} else {
opt = (sg.optmass - mass) / (sg.maxmass - sg.optmass);
opt = -1 + Math.pow(1 + opt, 2.425);
return shields * multiplier * ( (-1 * opt * sg.maxmul) + ((1 + opt) * sg.optmul) );
}
})
/**
* Calculate the a ships speed based on mass, and thrusters. Currently Innacurate / Incomplete :(
*
* @private
* @param {number} mass Current mass of the ship
* @param {number} baseSpeed Base speed m/s for ship
* @param {number} baseBoost Base boost m/s for ship
* @param {object} thrusters The shield generator used
* @return {object} Approximate speed and boost speed in m/s
*/
.value('calcSpeed', function(mass, baseSpeed, baseBoost) { //, thrusters) {
//var speed = baseSpeed * (1 + ((thrusters.optmass / mass) * 0.1 ) ); // TODO: find thruser coefficient(s)
//var boost = baseBoost * (1 + ((thrusters.optmass / mass) * 0.1 ) );
return { boost: baseSpeed, speed: baseBoost };
});

View File

@@ -1,125 +0,0 @@
angular.module('shipyard').service('Components', ['lodash', 'ComponentsDB', 'ShipsDB', 'ComponentSet', 'GroupMap', function(_, C, Ships, ComponentSet, GroupMap) {
var GrpNameToCodeMap = {};
for (var grp in GroupMap) {
GrpNameToCodeMap[GroupMap[grp]] = grp;
}
this.cargoHatch = function() {
return { name: 'Cargo Hatch', class: 1, rating: 'H', power: 0.6 };
};
this.common = function(typeIndex, componentId) {
return C.common[typeIndex][componentId];
};
this.hardpoints = function(id) {
for (var n in C.hardpoints) {
var group = C.hardpoints[n];
for (var i = 0; i < group.length; i++) {
if (group[i].id == id) {
return group[i];
}
}
}
return null;
};
this.internal = function(id) {
for (var n in C.internal) {
var group = C.internal[n];
for (var i = 0; i < group.length; i++) {
if (group[i].id == id) {
return group[i];
}
}
}
return null;
};
this.findInternalId = function(groupName, clss, rating, name) {
var groups = {};
if (groupName) {
var grpCode = GrpNameToCodeMap[groupName];
if (grpCode && !C.internal[grpCode]) {
throw 'Invalid internal group: ' + groupName;
}
groups[grpCode] = C.internal[grpCode];
} else if (name) {
groups = C.internal;
} else {
throw 'Invalid group or name not provided';
}
for (var g in groups) {
var group = groups[g];
for (var i = 0, l = group.length; i < l; i++) {
if (group[i].class == clss && group[i].rating == rating && ((!name && !group[i].name) || group[i].name == name)) {
return group[i].id;
}
}
}
return 0;
};
this.findHardpointId = function(groupName, clss, rating, name, mode, missile) {
var groups = {};
if (groupName) {
var grpCode = GrpNameToCodeMap[groupName];
if (grpCode && !C.hardpoints[grpCode]) {
throw 'Invalid internal group: ' + groupName;
}
groups[grpCode] = C.hardpoints[grpCode];
} else if (name) {
groups = C.hardpoints;
} else {
throw 'Invalid group or name not provided';
}
for (var g in groups) {
var group = groups[g];
for (var i = 0, l = group.length; i < l; i++) {
if (group[i].class == clss && group[i].rating == rating && group[i].mode == mode
&& ((!name && !group[i].name) || group[i].name == name)
&& ((!missile && !group[i].missile) || group[i].missile == missile)
) {
return group[i].id;
}
}
}
return 0;
};
/**
* Looks up the bulkhead component for a specific ship and bulkhead
* @param {string} shipId Unique ship Id/Key
* @param {number} bulkheadsId Id/Index for the specified bulkhead
* @return {object} The bulkhead component object
*/
this.bulkheads = function(shipId, bulkheadsId) {
return C.bulkheads[shipId][bulkheadsId];
};
this.bulkheadIndex = function(bulkheadName) {
return ['Lightweight Alloy', 'Reinforced Alloy', 'Military Grade Composite', 'Mirrored Surface Composite', 'Reactive Surface Composite'].indexOf(bulkheadName);
};
/**
* Creates a new ComponentSet that contains all available components
* that the specified ship is eligible to use.
*
* @param {string} shipId Unique ship Id/Key
* @return {ComponentSet} The set of components the ship can install
*/
this.forShip = function(shipId) {
var ship = Ships[shipId];
var maxInternal = isNaN(ship.slots.internal[0]) ? ship.slots.internal[0].class : ship.slots.internal[0];
return new ComponentSet(C, ship.minMassFilter || ship.properties.hullMass + 5, ship.slots.common, maxInternal, ship.slots.hardpoints[0]);
};
}]);

View File

@@ -1,8 +0,0 @@
.deep-space {
background-image: url(images/deep-space-1920x1080.jpg);
}
.docking-bay {
background-image: url(images/bay-1920x1080.jpg);
}

View File

@@ -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%;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -1,98 +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;
}
}
input[type=range] {
-webkit-appearance: none;
border: 1px solid @bgBlack;
/*required for proper track sizing in FF*/
width: 300px;
&::-moz-range-track, &::-webkit-slider-runnable-track {
width: 300px;
height: 5px;
background: @primary;
border: none;
border-radius: 3px;
}
&::-moz-range-thumb, &::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 1em;
width: 1em;
border-radius: 50%;
background: @primary;
}
&:focus {
outline: none;
}
/*hide the outline behind the border*/
&:-moz-focusring{
outline: 1px solid @bgBlack;
outline-offset: -1px;
}
&::-ms-track {
width: 300px;
height: 5px;
background: transparent;
border-color: transparent;
border-width: 6px 0;
color: transparent;
}
&::-ms-fill-lower {
background: @primary;
border-radius: 10px;
}
&::-ms-fill-upper {
background: @primary;
border-radius: 10px;
}
&::-ms-thumb {
border: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: goldenrod;
}
}

View File

@@ -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;
}

Some files were not shown because too many files have changed in this diff Show More