Compare commits
1273 Commits
v1.12.0
...
preview_ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d8c76209d | ||
|
|
c2038a6cf2 | ||
|
|
082ac233ad | ||
|
|
5d46fe7e4d | ||
|
|
6049c9837c | ||
|
|
a76eef01de | ||
|
|
b3eb4f35cd | ||
|
|
6b6dacf94c | ||
|
|
f010f2fef2 | ||
|
|
a952f80ea4 | ||
|
|
6d34ae2960 | ||
|
|
d17ff000c7 | ||
|
|
6b3d3ecd93 | ||
|
|
32dc28f48d | ||
|
|
a210724312 | ||
|
|
1d69ed7584 | ||
|
|
43e864e47b | ||
|
|
fb538027f7 | ||
|
|
cbf7f7d320 | ||
|
|
4111d670a7 | ||
|
|
397084a9ff | ||
|
|
968d633d46 | ||
|
|
96c3363edc | ||
|
|
a853ed9960 | ||
|
|
323a7060ec | ||
|
|
d0fa2510e5 | ||
|
|
8d57f641f7 | ||
|
|
055957567f | ||
|
|
5aff3f007e | ||
|
|
c34d86ba80 | ||
|
|
2038f36254 | ||
|
|
b1fc07a4cf | ||
|
|
a366420d65 | ||
|
|
8095b4852b | ||
|
|
cc3274f245 | ||
|
|
fbde9ce7bf | ||
|
|
130fc189ad | ||
|
|
a50e4fcc46 | ||
|
|
ae96ff244e | ||
|
|
1b0cdeedce | ||
|
|
992820ac42 | ||
|
|
c0ecc6a329 | ||
|
|
85131e6166 | ||
|
|
330983d9dd | ||
|
|
1bb7c4e825 | ||
|
|
450e1427a1 | ||
|
|
5614cec19d | ||
|
|
3f24a4b2c5 | ||
|
|
4e9e5735dc | ||
|
|
b1a6189c55 | ||
|
|
836504ee01 | ||
|
|
269565e959 | ||
|
|
e45027a66c | ||
|
|
2d3310d8e0 | ||
|
|
77066f0389 | ||
|
|
5e0567ef4d | ||
|
|
b49de4b0fa | ||
|
|
372495a83a | ||
|
|
468a4644d6 | ||
|
|
29d0f102fd | ||
|
|
ebc7173c50 | ||
|
|
43f1ac78a6 | ||
|
|
d489fdd700 | ||
|
|
d6b1e4465e | ||
|
|
5cbffcf3ac | ||
|
|
c91723516e | ||
|
|
a68f45d15a | ||
|
|
152a708ee8 | ||
|
|
a0ec13d2ed | ||
|
|
3313b7421f | ||
|
|
a76ee6b2fc | ||
|
|
0056b704d4 | ||
|
|
c1ead5fe27 | ||
|
|
85a89339a7 | ||
|
|
55f82c48bc | ||
|
|
f4761e099b | ||
|
|
be3696deba | ||
|
|
cd41e9e9be | ||
|
|
d6db30b7fc | ||
|
|
fd066c2150 | ||
|
|
f9ba95b3de | ||
|
|
7ee4d1d588 | ||
|
|
cef5842344 | ||
|
|
a7b6647135 | ||
|
|
bef17e53c6 | ||
|
|
d4b6099d6e | ||
|
|
ff60538e21 | ||
|
|
50c6133046 | ||
|
|
b7d7b80544 | ||
|
|
2b9342692d | ||
|
|
a24e247f1b | ||
|
|
3396056dae | ||
|
|
366d6c8971 | ||
|
|
14bf7ddf7a | ||
|
|
30cce09063 | ||
|
|
9a50ebfc47 | ||
|
|
0f05b60c20 | ||
|
|
4f8493d1bb | ||
|
|
58dd629956 | ||
|
|
936b746954 | ||
|
|
ef14bfac58 | ||
|
|
291f73b661 | ||
|
|
3d9dae0d52 | ||
|
|
017c37c4af | ||
|
|
ee0c852ddb | ||
|
|
d63627a37b | ||
|
|
b1c9e70f95 | ||
|
|
3ac2fd870f | ||
|
|
af7272cd10 | ||
|
|
d7c71f5d47 | ||
|
|
c858fc2859 | ||
|
|
f76f44e9f3 | ||
|
|
4fb07cc1d0 | ||
|
|
658a87cbc0 | ||
|
|
956fa7a8b7 | ||
|
|
0ebb992354 | ||
|
|
37f8253836 | ||
|
|
200ff5a1a4 | ||
|
|
0d44cbf74a | ||
|
|
bb216aa6ed | ||
|
|
eccf405ba8 | ||
|
|
9df87f61cd | ||
|
|
4186e19c65 | ||
|
|
57edc32a4b | ||
|
|
9cfa0748ac | ||
|
|
df859a2132 | ||
|
|
52257d60ac | ||
|
|
96ddb0bbff | ||
|
|
b529a28715 | ||
|
|
ea3a374ced | ||
|
|
2eacadf08f | ||
|
|
1a127bb1a6 | ||
|
|
edfa130939 | ||
|
|
7fbd89392a | ||
|
|
9f4b31979c | ||
|
|
9ecfc475e3 | ||
|
|
84dc93ac54 | ||
|
|
7532bcda08 | ||
|
|
08b5abc7ad | ||
|
|
38bf143704 | ||
|
|
a440ed3b37 | ||
|
|
39b7d9fdeb | ||
|
|
dfa728a486 | ||
|
|
7bd8ca5a55 | ||
|
|
627977ab51 | ||
|
|
e3b592977a | ||
|
|
622a734405 | ||
|
|
28404cd8bb | ||
|
|
be53dedb18 | ||
|
|
8ab6e26def | ||
|
|
b2a5a20650 | ||
|
|
57f930c83e | ||
|
|
b4dd65cf3e | ||
|
|
4a9b1df9b4 | ||
|
|
874bfb3305 | ||
|
|
ab9c925c47 | ||
|
|
d3b6bc1c93 | ||
|
|
cd7d25e4e1 | ||
|
|
1e5e9122ae | ||
|
|
506c7d31ca | ||
|
|
54cc5abf21 | ||
|
|
18e913d9ba | ||
|
|
180de97893 | ||
|
|
f198ff1773 | ||
|
|
55c13d1ad0 | ||
|
|
16505b30bf | ||
|
|
95b3f0a21c | ||
|
|
6adcfc52cd | ||
|
|
0a28fb60df | ||
|
|
2bab1464ee | ||
|
|
7875c2acaa | ||
|
|
49bf40484d | ||
|
|
07148f1e7f | ||
|
|
8a6ef788b3 | ||
|
|
d3e360b7c0 | ||
|
|
b1bba74c5a | ||
|
|
a954759012 | ||
|
|
90c1033437 | ||
|
|
191a065de1 | ||
|
|
cf91ae7627 | ||
|
|
0ba88d081a | ||
|
|
b6420b9a4b | ||
|
|
4f77dff6dd | ||
|
|
2b3e646213 | ||
|
|
e0e7478857 | ||
|
|
828d722be8 | ||
|
|
1ae55b34ee | ||
|
|
c9bc2341d1 | ||
|
|
eba98fec33 | ||
|
|
70af2b0df7 | ||
|
|
753b5c5339 | ||
|
|
9bb86b4ee4 | ||
|
|
2702193337 | ||
|
|
907196018b | ||
|
|
5eb2fef89c | ||
|
|
9403a1fce9 | ||
|
|
fd224d6781 | ||
|
|
f5776a0cb2 | ||
|
|
5b62419520 | ||
|
|
b9e5a47924 | ||
|
|
545c48266c | ||
|
|
61d1878494 | ||
|
|
4a95156e35 | ||
|
|
ab5f3488e7 | ||
|
|
510492e5e9 | ||
|
|
b375d3cb6c | ||
|
|
6ef57e735e | ||
|
|
f160aede3e | ||
|
|
ea8a4c01cb | ||
|
|
d963327ed4 | ||
|
|
bb96b0af1a | ||
|
|
34e3aa20ba | ||
|
|
5a846c36ab | ||
|
|
7bd6344359 | ||
|
|
b76e8df1bf | ||
|
|
5a0165282f | ||
|
|
597d9f2612 | ||
|
|
4d9c2898bf | ||
|
|
1854a21a50 | ||
|
|
0e4e7525e1 | ||
|
|
5259df2828 | ||
|
|
a5b5da6d27 | ||
|
|
b2cf4b8aa5 | ||
|
|
0d874f9ad1 | ||
|
|
019b8e93b4 | ||
|
|
b29fa2467a | ||
|
|
8b17cbfbc8 | ||
|
|
a445509d75 | ||
|
|
5a8eac21a3 | ||
|
|
45480a0216 | ||
|
|
97f72f6df5 | ||
|
|
466b2ac706 | ||
|
|
0d4f24ade9 | ||
|
|
459d55c31a | ||
|
|
7e98d29de0 | ||
|
|
6bd51ff0d5 | ||
|
|
6500e6d467 | ||
|
|
abcce8879f | ||
|
|
e30040c9fd | ||
|
|
6bbfb8e837 | ||
|
|
2ec203a3a2 | ||
|
|
4df22d2063 | ||
|
|
bf16246825 | ||
|
|
0eed01811c | ||
|
|
96b3d5637a | ||
|
|
4a09cbcec9 | ||
|
|
964493d701 | ||
|
|
f1b9c788f3 | ||
|
|
a50f89db67 | ||
|
|
0d94ffe27a | ||
|
|
dc4c4c7353 | ||
|
|
8d4e0a259e | ||
|
|
91f87b02cc | ||
|
|
870e333605 | ||
|
|
7ea3103c25 | ||
|
|
3aa60ac669 | ||
|
|
81612cc32a | ||
|
|
d3caee328f | ||
|
|
d5af6127e5 | ||
|
|
5eb5fb3310 | ||
|
|
8605bab4d4 | ||
|
|
1540c9463a | ||
|
|
130105ca9f | ||
|
|
cb225eabb3 | ||
|
|
72245d8ebe | ||
|
|
96505e4421 | ||
|
|
fbb1750528 | ||
|
|
dad63b6d77 | ||
|
|
14e69b1e59 | ||
|
|
883917d5d6 | ||
|
|
deeccc85a3 | ||
|
|
cfa57a70dc | ||
|
|
e6dfb1e90a | ||
|
|
e03d3278a0 | ||
|
|
eae4bb75e5 | ||
|
|
e6dead2e27 | ||
|
|
59b854b00d | ||
|
|
675533a732 | ||
|
|
7751a2e072 | ||
|
|
b4bbc82ba1 | ||
|
|
a0a0ec9b1f | ||
|
|
26285cfc95 | ||
|
|
6799e71f1a | ||
|
|
8806c941a8 | ||
|
|
78cbed516a | ||
|
|
2281fae615 | ||
|
|
1192a0658a | ||
|
|
7f2ac25455 | ||
|
|
62a696cc4b | ||
|
|
11716f7f94 | ||
|
|
180166156a | ||
|
|
3c8bab92b5 | ||
|
|
cf361593a4 | ||
|
|
8ad639a122 | ||
|
|
a7cd445cef | ||
|
|
380d74b333 | ||
|
|
eade4f0ebd | ||
|
|
08be50caf2 | ||
|
|
6a5c86b84f | ||
|
|
1fb5bbc36e | ||
|
|
d6edb57a10 | ||
|
|
d3fdf9854d | ||
|
|
3217980ada | ||
|
|
29b5a7433d | ||
|
|
5bca2d723e | ||
|
|
d2a52e26b2 | ||
|
|
8a4fe1627e | ||
|
|
a9fb55fedd | ||
|
|
04c30e70af | ||
|
|
c0210895e9 | ||
|
|
fe9917e620 | ||
|
|
a3dfa3b5ba | ||
|
|
34243b7b71 | ||
|
|
9fd81e8acd | ||
|
|
bbc4ef8146 | ||
|
|
7fe7056c12 | ||
|
|
ab32a3afb0 | ||
|
|
ea3e5e273f | ||
|
|
6849478226 | ||
|
|
b6c5183d40 | ||
|
|
e5d65b97ce | ||
|
|
6cda47be9f | ||
|
|
a0ef1a3d9b | ||
|
|
ba47420577 | ||
|
|
806f17545f | ||
|
|
f0f5b4c04c | ||
|
|
ad76104033 | ||
|
|
c6e481efcf | ||
|
|
2ad0c00c17 | ||
|
|
26ab7d5e6f | ||
|
|
832e7e6637 | ||
|
|
8c7972ed78 | ||
|
|
05bbc14965 | ||
|
|
e7feee6878 | ||
|
|
791ddcb9a1 | ||
|
|
12d5a21982 | ||
|
|
7493b92d83 | ||
|
|
e7c79e58b4 | ||
|
|
0dbdbf7cfe | ||
|
|
f39ca66dbf | ||
|
|
8d80494b8d | ||
|
|
058768baab | ||
|
|
cfee6fdcd0 | ||
|
|
34c95bea5d | ||
|
|
50911c7fc8 | ||
|
|
4e1f0f9cc6 | ||
|
|
2b1abfc9b2 | ||
|
|
595c139ca8 | ||
|
|
6637feb3a6 | ||
|
|
928246a8ca | ||
|
|
fd3e0bbebf | ||
|
|
2a0a572b76 | ||
|
|
a314cd7cfd | ||
|
|
cd28375019 | ||
|
|
7cf4134a73 | ||
|
|
44c76f0b98 | ||
|
|
69a122a271 | ||
|
|
0c0eb327f7 | ||
|
|
74ce79ba8f | ||
|
|
1dc15936ed | ||
|
|
126fa7be29 | ||
|
|
d61251e9b3 | ||
|
|
f9f53a13c0 | ||
|
|
b4360d44f1 | ||
|
|
574d575cad | ||
|
|
5e10339c20 | ||
|
|
feb83cf737 | ||
|
|
0ff4aec400 | ||
|
|
e2944f6be7 | ||
|
|
3e842f30f1 | ||
|
|
481619101b | ||
|
|
2ac66d87af | ||
|
|
e818ce62c8 | ||
|
|
49851d1131 | ||
|
|
a8061c9276 | ||
|
|
4036ac8cd2 | ||
|
|
57bbbfcc3b | ||
|
|
68f769aac2 | ||
|
|
ef9bd3edc8 | ||
|
|
45f88a92dc | ||
|
|
02c8b46b74 | ||
|
|
32068e8d8e | ||
|
|
ccd8ee87f3 | ||
|
|
c73b446482 | ||
|
|
699276ca58 | ||
|
|
3187bab90a | ||
|
|
c1dfd676e1 | ||
|
|
c7554ec400 | ||
|
|
f1771a61d0 | ||
|
|
d3cb968c19 | ||
|
|
9c685263bb | ||
|
|
d43db40469 | ||
|
|
a50471c0a6 | ||
|
|
8d215f7d7f | ||
|
|
eb9b034d65 | ||
|
|
c52fecead3 | ||
|
|
5b09cf7c4d | ||
|
|
9be9a21b22 | ||
|
|
3e4b748952 | ||
|
|
9fe91472cf | ||
|
|
a06810c7c8 | ||
|
|
160de64135 | ||
|
|
2b5535c5d1 | ||
|
|
1e9f911385 | ||
|
|
2a9a4fbdff | ||
|
|
7331c158b6 | ||
|
|
ddcbbb7fcf | ||
|
|
e7ac1597bb | ||
|
|
11e8ea4fe8 | ||
|
|
1853500729 | ||
|
|
a349626923 | ||
|
|
f466f9cc49 | ||
|
|
13b452223d | ||
|
|
c166fa6bf5 | ||
|
|
3a7e343f1c | ||
|
|
02557701f0 | ||
|
|
30755fbb73 | ||
|
|
c1b3491933 | ||
|
|
5467a58b04 | ||
|
|
75f07afcb7 | ||
|
|
c64838f7f5 | ||
|
|
a0359b8bd9 | ||
|
|
e2434619b5 | ||
|
|
becb3d4bb6 | ||
|
|
44fb4a558c | ||
|
|
9a574cb31b | ||
|
|
4fa4640991 | ||
|
|
35b5002eca | ||
|
|
b5574ca535 | ||
|
|
8fec03bcbf | ||
|
|
7de90cc2d8 | ||
|
|
c700d9b661 | ||
|
|
48f264851d | ||
|
|
467d244bea | ||
|
|
840c041f8c | ||
|
|
c30190f63e | ||
|
|
6e54d6788c | ||
|
|
68f45706ab | ||
|
|
43ee031121 | ||
|
|
533c86de16 | ||
|
|
ba3c9b87b5 | ||
|
|
8338b6adb3 | ||
|
|
54c950f951 | ||
|
|
d1c18d9642 | ||
|
|
19090e7353 | ||
|
|
1d52382460 | ||
|
|
a074199219 | ||
|
|
c1179ddb40 | ||
|
|
ef06a1ccb1 | ||
|
|
e31f3cb46e | ||
|
|
9f9cd29a7f | ||
|
|
ed24ef2615 | ||
|
|
c5b78c20e5 | ||
|
|
f98f6a120b | ||
|
|
6192343add | ||
|
|
6728aba0a5 | ||
|
|
64b75303af | ||
|
|
0eef1ee480 | ||
|
|
fef087ae46 | ||
|
|
0e15adecf2 | ||
|
|
be6addf4d0 | ||
|
|
052e9b68b5 | ||
|
|
fd91f56e55 | ||
|
|
a0a35d60ec | ||
|
|
639f3d27b4 | ||
|
|
e3040854d8 | ||
|
|
4597fd27da | ||
|
|
88bceae6b0 | ||
|
|
9ace9815b6 | ||
|
|
bfda7014db | ||
|
|
5107d383e0 | ||
|
|
32ba3fa516 | ||
|
|
69723d1bd0 | ||
|
|
5a5ab846c2 | ||
|
|
394381c736 | ||
|
|
fea1a28760 | ||
|
|
f895e82c69 | ||
|
|
710d15a66c | ||
|
|
d81a51bd8c | ||
|
|
3ac733a30c | ||
|
|
7a715fc471 | ||
|
|
b9b72ebf40 | ||
|
|
071dfaf656 | ||
|
|
88384a2fd8 | ||
|
|
a2c0049488 | ||
|
|
60288204fc | ||
|
|
7d0f65c1f3 | ||
|
|
a35b9b5d3f | ||
|
|
2a2842100a | ||
|
|
faed0ce159 | ||
|
|
23a6849fe3 | ||
|
|
91c6e91023 | ||
|
|
8f64c91677 | ||
|
|
842ee3d426 | ||
|
|
45d338ba3d | ||
|
|
f141fac3a2 | ||
|
|
7b2a89d66b | ||
|
|
4d158d99fd | ||
|
|
c3983a26c5 | ||
|
|
016854a292 | ||
|
|
5d7252cbec | ||
|
|
0e0bcf51fc | ||
|
|
f396077cd6 | ||
|
|
1c194b67f3 | ||
|
|
72e77d2264 | ||
|
|
10c79ac812 | ||
|
|
fe8c3a4957 | ||
|
|
3734be21d6 | ||
|
|
8ae6ad879e | ||
|
|
92b2a35888 | ||
|
|
fb2e6e5c17 | ||
|
|
2212311a44 | ||
|
|
ef3791f845 | ||
|
|
6e2878194c | ||
|
|
e7780485f1 | ||
|
|
7831999563 | ||
|
|
7020f4bda9 | ||
|
|
dcd21bd165 | ||
|
|
4a70028762 | ||
|
|
9255a9e638 | ||
|
|
02736ac92d | ||
|
|
2df01c7157 | ||
|
|
01a0745b9b | ||
|
|
c7573ad4c3 | ||
|
|
06f402bb9d | ||
|
|
b9f0812b38 | ||
|
|
cdca8fe236 | ||
|
|
c8175d1191 | ||
|
|
7a7a0f1eff | ||
|
|
5176fe0366 | ||
|
|
b4bd6e7acd | ||
|
|
bd4dbf45af | ||
|
|
d9fc3d436b | ||
|
|
67143cbc0e | ||
|
|
ed3b2eb1bf | ||
|
|
7a5e4291a5 | ||
|
|
d1c6810e1e | ||
|
|
faa9c0a2b9 | ||
|
|
0456973093 | ||
|
|
4a79a4e4d9 | ||
|
|
ac46d33a60 | ||
|
|
0f958bef81 | ||
|
|
b79009517e | ||
|
|
12ccc96f46 | ||
|
|
47828c38d2 | ||
|
|
afdae6a3d6 | ||
|
|
03d1d8f5a4 | ||
|
|
cc4e4c0f13 | ||
|
|
2f6f14fef2 | ||
|
|
fb590ddfdd | ||
|
|
a5e674cdc4 | ||
|
|
e28883dd47 | ||
|
|
b4694dcf03 | ||
|
|
4c05d9a687 | ||
|
|
53da2f9bb2 | ||
|
|
ea106b6064 | ||
|
|
32f671b4f2 | ||
|
|
25e298ff69 | ||
|
|
45006fe043 | ||
|
|
3e1c561752 | ||
|
|
be4b78ee1c | ||
|
|
5a2989cae4 | ||
|
|
15519fd783 | ||
|
|
a357a5b845 | ||
|
|
806b8f135b | ||
|
|
f2b636bd44 | ||
|
|
0d25eca6e5 | ||
|
|
e5dcac43dc | ||
|
|
8629710223 | ||
|
|
111e2cc0de | ||
|
|
8eb0b942c8 | ||
|
|
4c55827aa4 | ||
|
|
0a1be7d966 | ||
|
|
8f3370307a | ||
|
|
dd1545c7e1 | ||
|
|
8ea9bee810 | ||
|
|
6141356754 | ||
|
|
e70ea67fec | ||
|
|
62be4c5bce | ||
|
|
394a9540b0 | ||
|
|
62d22f0e74 | ||
|
|
1cd7b9a250 | ||
|
|
7044534765 | ||
|
|
9c3b50d622 | ||
|
|
fd62c254a4 | ||
|
|
90e54c6334 | ||
|
|
f423c67979 | ||
|
|
4607dd788c | ||
|
|
f9c595473f | ||
|
|
de6c843e1c | ||
|
|
b45924aa52 | ||
|
|
d04ea5b061 | ||
|
|
7406210c4a | ||
|
|
c24986fba3 | ||
|
|
30c1c00b9b | ||
|
|
655d658a52 | ||
|
|
a089c4cbc2 | ||
|
|
62fd545d24 | ||
|
|
4041ecddc4 | ||
|
|
10f51b41b7 | ||
|
|
7cf0a35a7a | ||
|
|
523f7793b5 | ||
|
|
9891aecf19 | ||
|
|
fd700f73e5 | ||
|
|
d71b05095d | ||
|
|
d061a13b58 | ||
|
|
5176cc3b06 | ||
|
|
1e364913cd | ||
|
|
1adc7c77ac | ||
|
|
51fbcce803 | ||
|
|
80dab63119 | ||
|
|
8c769f152b | ||
|
|
3673391f5a | ||
|
|
f96a2e72f7 | ||
|
|
19929ef3ba | ||
|
|
e3a3d287bf | ||
|
|
b2b92b00f3 | ||
|
|
6bd2c19b21 | ||
|
|
eb8e5c5135 | ||
|
|
5a07be40f1 | ||
|
|
13a15a38c5 | ||
|
|
caa10614d9 | ||
|
|
0943b4b097 | ||
|
|
8823baaef4 | ||
|
|
5a5e77414a | ||
|
|
f524591327 | ||
|
|
55ae7c39a4 | ||
|
|
d4e5f8d165 | ||
|
|
b9dad60b61 | ||
|
|
57b9b916ed | ||
|
|
854476db76 | ||
|
|
941c57b4a8 | ||
|
|
fb1c5a760f | ||
|
|
e5367127ea | ||
|
|
ffebd3f311 | ||
|
|
d8fcbd4032 | ||
|
|
583f416373 | ||
|
|
f605b37a1e | ||
|
|
a1d64acff4 | ||
|
|
1fe42f6a79 | ||
|
|
3ce5f69225 | ||
|
|
985107c601 | ||
|
|
d416124081 | ||
|
|
3a62a6c40d | ||
|
|
8f6f55b001 | ||
|
|
6d1ae39bc6 | ||
|
|
850197faa1 | ||
|
|
1aa206bc82 | ||
|
|
5a9cdb67f9 | ||
|
|
c9810cd019 | ||
|
|
8bf75e38ad | ||
|
|
fe9139ae93 | ||
|
|
87a354a314 | ||
|
|
270ac99a1e | ||
|
|
dc5d6a4ef8 | ||
|
|
4cdb36de09 | ||
|
|
7fce1d00d7 | ||
|
|
26c27153f0 | ||
|
|
b5420e9c6a | ||
|
|
cfd82a6ad4 | ||
|
|
7a352b49a0 | ||
|
|
8a4f3b7642 | ||
|
|
a09d4139d5 | ||
|
|
a257ac87f7 | ||
|
|
1669a5434c | ||
|
|
2fc83aa61c | ||
|
|
ed6f00a893 | ||
|
|
b15f9766c1 | ||
|
|
0ad4f07591 | ||
|
|
4704c5a1b0 | ||
|
|
034a9bc3c3 | ||
|
|
e7dc9db75a | ||
|
|
4a2d1b7997 | ||
|
|
a5e2a32fb8 | ||
|
|
43f69bb184 | ||
|
|
71482c2359 | ||
|
|
84a27a60a5 | ||
|
|
87f865ce1f | ||
|
|
12c78b41af | ||
|
|
c3db808b7c | ||
|
|
af9a9c5698 | ||
|
|
a7e6d3e969 | ||
|
|
708425c67a | ||
|
|
021de1af80 | ||
|
|
b66e98f697 | ||
|
|
28ad32aad5 | ||
|
|
94dc3117bc | ||
|
|
803ada4b27 | ||
|
|
e7118f637c | ||
|
|
e11e368c4b | ||
|
|
27a9051822 | ||
|
|
54caece5b3 | ||
|
|
b1fade5d3b | ||
|
|
8ed485df0e | ||
|
|
9c33947a45 | ||
|
|
33dc06055c | ||
|
|
8ff4a99cf3 | ||
|
|
d38abec819 | ||
|
|
0ba48aa230 | ||
|
|
acf47ad7a6 | ||
|
|
c948c62cac | ||
|
|
eee4dbf66c | ||
|
|
653b995774 | ||
|
|
a78151c5aa | ||
|
|
3177713447 | ||
|
|
0769df1e55 | ||
|
|
0cfa7cb28f | ||
|
|
1e621ee133 | ||
|
|
a203799bd2 | ||
|
|
8fc9724204 | ||
|
|
0d41cb96ab | ||
|
|
39b2f87194 | ||
|
|
1161037092 | ||
|
|
a3d9d5cca8 | ||
|
|
4b67411ca6 | ||
|
|
126b807dc7 | ||
|
|
ca81d2d602 | ||
|
|
015c195c9f | ||
|
|
5fd170d480 | ||
|
|
4b167ba9de | ||
|
|
38ac41bccb | ||
|
|
3315d27d45 | ||
|
|
c3dcdb0686 | ||
|
|
ca91f6bd92 | ||
|
|
65483309ab | ||
|
|
71d33f3429 | ||
|
|
9b1c543eb7 | ||
|
|
24bb0ff39a | ||
|
|
3ae312db37 | ||
|
|
94f73241ea | ||
|
|
d4632b9059 | ||
|
|
dd15d52130 | ||
|
|
145f252ca6 | ||
|
|
731b54a1f7 | ||
|
|
f8d7b68289 | ||
|
|
80e47d5157 | ||
|
|
c1653c5f2e | ||
|
|
36ad31ab25 | ||
|
|
6f1872fb94 | ||
|
|
ff56e70b81 | ||
|
|
201263237f | ||
|
|
1ddd37f381 | ||
|
|
f9d2a78c5e | ||
|
|
443c917c6b | ||
|
|
7c787cd13b | ||
|
|
dc8aff6b6c | ||
|
|
397040549f | ||
|
|
0b858d6e94 | ||
|
|
6c8efcda12 | ||
|
|
3fa0aa9242 | ||
|
|
18775286c0 | ||
|
|
57433efe80 | ||
|
|
c42748a5dd | ||
|
|
b5cf835959 | ||
|
|
48b45b5f51 | ||
|
|
7d658c3f3d | ||
|
|
91980c9f2c | ||
|
|
db1c80c7e3 | ||
|
|
e53bd70c2c | ||
|
|
fe64e2e24c | ||
|
|
a020ca9a71 | ||
|
|
7a9fde822c | ||
|
|
152af02336 | ||
|
|
be7d3a921a | ||
|
|
78acb205d3 | ||
|
|
627dac692c | ||
|
|
68a6a828d8 | ||
|
|
e8604788df | ||
|
|
d36bf41ecf | ||
|
|
821d9ea330 | ||
|
|
65eb0fac3d | ||
|
|
e9a0c5456e | ||
|
|
e2d33beb34 | ||
|
|
b44c8461d4 | ||
|
|
38cc13ff2c | ||
|
|
53a46dcec6 | ||
|
|
c01e506eb1 | ||
|
|
ad61795e80 | ||
|
|
bd802ab926 | ||
|
|
a25a1c0415 | ||
|
|
969952cccc | ||
|
|
d85f8c0744 | ||
|
|
cf60bbc904 | ||
|
|
9c67e7dd93 | ||
|
|
df81a146d2 | ||
|
|
9bfb697f1e | ||
|
|
2e227cdbd5 | ||
|
|
fb7c227a10 | ||
|
|
e3742c0420 | ||
|
|
373ccbcee5 | ||
|
|
785060f12b | ||
|
|
4e509bbaee | ||
|
|
02d4ac81dd | ||
|
|
7e305aab67 | ||
|
|
55eed0d029 | ||
|
|
c7d5f2533a | ||
|
|
a6cfbcb331 | ||
|
|
45074952fd | ||
|
|
a73d9abc60 | ||
|
|
9fc31d6a55 | ||
|
|
9cb99a1170 | ||
|
|
f3f1d022ef | ||
|
|
253ebdc4e1 | ||
|
|
5d45f1d3f3 | ||
|
|
e253af9763 | ||
|
|
a355a82f8a | ||
|
|
ceb7eb15c3 | ||
|
|
115b154f0b | ||
|
|
2d1344b785 | ||
|
|
bdf793072c | ||
|
|
2f879d39f3 | ||
|
|
f0775af439 | ||
|
|
96048b5133 | ||
|
|
36ab224853 | ||
|
|
52d19b8de4 | ||
|
|
7be5ec844f | ||
|
|
3d26a31ee2 | ||
|
|
343d605a84 | ||
|
|
ef1228eb32 | ||
|
|
ad738f7e7c | ||
|
|
4a66fa0138 | ||
|
|
331338e7b9 | ||
|
|
8e28925336 | ||
|
|
df0e829dbe | ||
|
|
0c278b668c | ||
|
|
6e7ba714a8 | ||
|
|
d8e2e3ace1 | ||
|
|
69c3dd188e | ||
|
|
57da36f1cf | ||
|
|
753ba00ac0 | ||
|
|
290f7d116f | ||
|
|
81fa88a36d | ||
|
|
0dd98330aa | ||
|
|
ae55a2c1d2 | ||
|
|
43ae593568 | ||
|
|
81963a6a7d | ||
|
|
fbf67c134b | ||
|
|
a0cfe05eb5 | ||
|
|
ba6e8d7ad1 | ||
|
|
cbd2ed603f | ||
|
|
a2f1623b00 | ||
|
|
87ebcf0818 | ||
|
|
f329c9956e | ||
|
|
2ac62ece06 | ||
|
|
f9db5eb201 | ||
|
|
0a10f2d72a | ||
|
|
4325ccab8a | ||
|
|
04c6fad531 | ||
|
|
ca92285ff3 | ||
|
|
96eee3a173 | ||
|
|
a74c3c9b3d | ||
|
|
b4373cb0c5 | ||
|
|
9029c04ce6 | ||
|
|
c7c0c49218 | ||
|
|
191dd1c71b | ||
|
|
3b64373393 | ||
|
|
0f6c67e852 | ||
|
|
209297769f | ||
|
|
2d4e3a6ddf | ||
|
|
350f4c9f89 | ||
|
|
9c9a6b69fe | ||
|
|
2b9d85a4bc | ||
|
|
f053e45671 | ||
|
|
4d701f561e | ||
|
|
3cb6d03487 | ||
|
|
7dbe6dbe2d | ||
|
|
81f122467a | ||
|
|
20759d205c | ||
|
|
b37aea40a7 | ||
|
|
f95e864119 | ||
|
|
7a9de8cd99 | ||
|
|
dde8b1f802 | ||
|
|
ca34d7cced | ||
|
|
938e2a871d | ||
|
|
89b756d760 | ||
|
|
3b1edd3283 | ||
|
|
5369b17ebf | ||
|
|
2fadaa890b | ||
|
|
31bdb75c51 | ||
|
|
0124f63d9a | ||
|
|
95dba166eb | ||
|
|
83adadd71f | ||
|
|
4baf65c0c7 | ||
|
|
72cdd3e104 | ||
|
|
febc2eee09 | ||
|
|
b302a0a6e5 | ||
|
|
1f6a14ee36 | ||
|
|
99a15af26e | ||
|
|
dff7a4d6ac | ||
|
|
3c8e6a61f2 | ||
|
|
fb997ab16d | ||
|
|
8fe5f43875 | ||
|
|
c8cfee3511 | ||
|
|
bf0b89f3b5 | ||
|
|
1d295c04e3 | ||
|
|
11ebde87c9 | ||
|
|
88c4de9820 | ||
|
|
09e0a0576c | ||
|
|
fc84c5dc94 | ||
|
|
687ebbc41b | ||
|
|
0abe953a70 | ||
|
|
2a8f3e4855 | ||
|
|
8cd36f3cbf | ||
|
|
5577e1976b | ||
|
|
4b27becb5f | ||
|
|
3c055b78d3 | ||
|
|
eb5ce91cb2 | ||
|
|
ef36dc5ba3 | ||
|
|
d9c710c5a1 | ||
|
|
c436e0e669 | ||
|
|
e80917e3d1 | ||
|
|
0d0ec42daf | ||
|
|
0e4cca6138 | ||
|
|
b701acb275 | ||
|
|
4eb61051c6 | ||
|
|
56aba37758 | ||
|
|
f432b08149 | ||
|
|
3e0b2fd09c | ||
|
|
c7b8d94e4f | ||
|
|
31a9b03436 | ||
|
|
f33f558006 | ||
|
|
bb4fe63a7c | ||
|
|
ccb9e085b2 | ||
|
|
702d249bad | ||
|
|
cc2835a341 | ||
|
|
d73c53cb10 | ||
|
|
73409a3324 | ||
|
|
24f770aa7b | ||
|
|
649b99d7bd | ||
|
|
a8b50032c4 | ||
|
|
d1d276ae68 | ||
|
|
6eafbb0a25 | ||
|
|
aedd7ce2de | ||
|
|
b0511ed856 | ||
|
|
d60b288e0e | ||
|
|
f7d5287087 | ||
|
|
7032baa7ef | ||
|
|
b52cbef26f | ||
|
|
34f699b96a | ||
|
|
5b341dfc06 | ||
|
|
cb0003b942 | ||
|
|
6ee6186280 | ||
|
|
781abeea53 | ||
|
|
6496164d95 | ||
|
|
1ce2921eb7 | ||
|
|
6eb6925606 | ||
|
|
9d7a3605dc | ||
|
|
056e961ccc | ||
|
|
8f08f8efb8 | ||
|
|
167eb60fe3 | ||
|
|
c04b7e0552 | ||
|
|
ff87d5e456 | ||
|
|
c81774a3aa | ||
|
|
a5920a9c9c | ||
|
|
c103e563a9 | ||
|
|
08382db011 | ||
|
|
9929510e53 | ||
|
|
f6cddcc86d | ||
|
|
953a70327a | ||
|
|
6e04c64ffb | ||
|
|
e0f99ee133 | ||
|
|
6ed81e9bae | ||
|
|
69a4e42ab0 | ||
|
|
8151debfe1 | ||
|
|
972df6cad3 | ||
|
|
b1729095a0 | ||
|
|
23dbb59f3f | ||
|
|
9269c54434 | ||
|
|
c4246c0d50 | ||
|
|
d013a41079 | ||
|
|
94995685e9 | ||
|
|
11c3859270 | ||
|
|
1415de9573 | ||
|
|
73de795082 | ||
|
|
bb9760f79c | ||
|
|
53b8ca3940 | ||
|
|
8a9107c798 | ||
|
|
52f06bbd43 | ||
|
|
5246432420 | ||
|
|
8ccdbcc51d | ||
|
|
81c2895c9e | ||
|
|
cbb31c1217 | ||
|
|
6c80d15f1d | ||
|
|
4baa6e9e9f | ||
|
|
2e998bd5a4 | ||
|
|
a33ec89e87 | ||
|
|
ba9232e514 | ||
|
|
f090cafa5c | ||
|
|
a67b46bb9a | ||
|
|
f17fb82ce7 | ||
|
|
3f6c484c99 | ||
|
|
11cf4b356c | ||
|
|
231cdb8399 | ||
|
|
30f077027b | ||
|
|
8a2c4671bf | ||
|
|
35f56b9c32 | ||
|
|
ae3bd9d9d4 | ||
|
|
9465aceddb | ||
|
|
8e353b08ae | ||
|
|
a5f1370eec | ||
|
|
b454ac003b | ||
|
|
17d353e09b | ||
|
|
365cacac66 | ||
|
|
30fef3039c | ||
|
|
6f161b495f | ||
|
|
582e54e758 | ||
|
|
072fac4259 | ||
|
|
4e890e1e1d | ||
|
|
473b70944f | ||
|
|
37b158439d | ||
|
|
2617143330 | ||
|
|
a3b108382e | ||
|
|
e07c162453 | ||
|
|
0f8992432b | ||
|
|
dc55dbdf36 | ||
|
|
d0ec17feba | ||
|
|
5b5fdd97d6 | ||
|
|
c751544560 | ||
|
|
1d51e86c1c | ||
|
|
05b9d1e607 | ||
|
|
2a88e3114b | ||
|
|
a0f9fb6ad6 | ||
|
|
b844bdf986 | ||
|
|
61614553a2 | ||
|
|
ae870f9535 | ||
|
|
30a8437515 | ||
|
|
8647fa245f | ||
|
|
23bb763c51 | ||
|
|
c158cb076f | ||
|
|
b1ebf8562a | ||
|
|
e9d02ce4c8 | ||
|
|
ec6914d4aa | ||
|
|
474f270b26 | ||
|
|
fb7574e476 | ||
|
|
760b5f3d74 | ||
|
|
51c481206c | ||
|
|
7b6b922c57 | ||
|
|
a08bb2494b | ||
|
|
4affc24ec7 | ||
|
|
d7cb0d536f | ||
|
|
bf9a4b4919 | ||
|
|
3ea4439b8d | ||
|
|
bd53785667 | ||
|
|
f2b4400834 | ||
|
|
b8d01d5ecb | ||
|
|
9ae5cfbab2 | ||
|
|
045031e8ae | ||
|
|
2c7bfd14b6 | ||
|
|
1584586fd2 | ||
|
|
1402ceec63 | ||
|
|
4663270067 | ||
|
|
0b9cdaa944 | ||
|
|
89c011d37e | ||
|
|
c72f049ccd | ||
|
|
ca34217f3b | ||
|
|
3521b3887d | ||
|
|
492776c5a8 | ||
|
|
51a8076d30 | ||
|
|
decf7ff028 | ||
|
|
31b1c94c0f | ||
|
|
a9fc457510 | ||
|
|
7c3c8182a7 | ||
|
|
b162927f79 | ||
|
|
6dbed1403a | ||
|
|
aa5eb7ac92 | ||
|
|
e0fbcc91f1 | ||
|
|
b2dce223b0 | ||
|
|
4b7b22025c | ||
|
|
8e37dab37e | ||
|
|
6e95f69565 | ||
|
|
31331b1e34 | ||
|
|
05b3777ad2 | ||
|
|
cda8dd4c8b | ||
|
|
e7542fec44 | ||
|
|
e7fcdd86ac | ||
|
|
d909e8adc4 | ||
|
|
def20311a8 | ||
|
|
503907e2d8 | ||
|
|
88dc1edfb4 | ||
|
|
cbedf03026 | ||
|
|
a69589dd23 | ||
|
|
2904ab6afa | ||
|
|
c763595cc4 | ||
|
|
8fe97180ed | ||
|
|
6a4b2ffe69 | ||
|
|
7f100353e2 | ||
|
|
97ac0804c5 | ||
|
|
48f96a7a32 | ||
|
|
598512a904 | ||
|
|
121a81ce70 | ||
|
|
a2e031cf27 | ||
|
|
f18ba6160a | ||
|
|
c2ca5dffe8 | ||
|
|
ab7bbcb6ef | ||
|
|
e5e7311748 | ||
|
|
9ba3ca3f5f | ||
|
|
cc59612fa4 | ||
|
|
01db1efdf7 | ||
|
|
e74e2615ad | ||
|
|
2f246d0897 | ||
|
|
505b0ce38f | ||
|
|
8c19a956e0 | ||
|
|
9de3600d7f | ||
|
|
5a4f526b2b | ||
|
|
cd0b0eada0 | ||
|
|
17733d5951 | ||
|
|
0a1f324053 | ||
|
|
e12b3f3054 | ||
|
|
b32f76cfde | ||
|
|
182104a010 | ||
|
|
90c883da67 | ||
|
|
ac08b1b264 | ||
|
|
f17d015ebe | ||
|
|
d496637614 | ||
|
|
4596c526a2 | ||
|
|
9941b6c74b | ||
|
|
b06ce24d4a | ||
|
|
2f8c201ab3 | ||
|
|
d184820728 | ||
|
|
40aeb1ed4a | ||
|
|
71b258a8f5 | ||
|
|
cd7579a4bf | ||
|
|
d6199a58c2 | ||
|
|
3ad5aaac89 | ||
|
|
3bed268d81 | ||
|
|
9a1b0f07c0 | ||
|
|
f591ecba10 | ||
|
|
c571fdc5e6 | ||
|
|
6f944fc7db | ||
|
|
63fce4be17 | ||
|
|
86ee5292d8 | ||
|
|
0060f58e3d | ||
|
|
23b458534f | ||
|
|
2256efacb0 | ||
|
|
28a5318e3b | ||
|
|
609ee13cd6 | ||
|
|
4216904736 | ||
|
|
496e9b56b5 | ||
|
|
b8f73a7c94 | ||
|
|
b4604f8207 | ||
|
|
68dddf2810 | ||
|
|
4c17f38b1a | ||
|
|
221a3fde14 | ||
|
|
c17e03d8d0 | ||
|
|
af9f64db5f | ||
|
|
1f82465a65 | ||
|
|
d885bd4636 | ||
|
|
c17bce55bb | ||
|
|
4137a7cda9 | ||
|
|
c92911b79a | ||
|
|
adc9fb6d00 | ||
|
|
5baf70694a | ||
|
|
f08dc97576 | ||
|
|
35094ae1ce | ||
|
|
5ac31920ee | ||
|
|
e63c3541c4 | ||
|
|
4976516d4d | ||
|
|
e042a21d32 | ||
|
|
8a22907940 | ||
|
|
a97847e644 | ||
|
|
23309a5da6 | ||
|
|
06e4a7e80f | ||
|
|
b95a10d284 | ||
|
|
2bca3ddcc8 | ||
|
|
9ef182aa99 | ||
|
|
5e56107582 | ||
|
|
972c08e7e4 | ||
|
|
091832af21 | ||
|
|
16d1891e16 | ||
|
|
40ee68e2cf | ||
|
|
bfe3b4a26d | ||
|
|
9aa1332b15 | ||
|
|
0521d242eb | ||
|
|
2b3f3773e5 | ||
|
|
4041407878 | ||
|
|
1b5e0467fc | ||
|
|
a7c346f78e | ||
|
|
3cc51aaf89 | ||
|
|
a339ae1c55 | ||
|
|
3773d1c28e | ||
|
|
41b8db346f | ||
|
|
7959593c6c | ||
|
|
aaa60cbc14 | ||
|
|
8ae5a96047 | ||
|
|
8c90b3132b | ||
|
|
1326e21f6b | ||
|
|
bfdc2161e0 | ||
|
|
9ab79af70c | ||
|
|
f0de2000bf | ||
|
|
5991d19b3e | ||
|
|
51fed996f1 | ||
|
|
f6bbc6c410 | ||
|
|
3de6b63325 | ||
|
|
dd48815f30 | ||
|
|
5608676dc8 | ||
|
|
86ab1f7444 | ||
|
|
8f51642f70 | ||
|
|
de71123a48 | ||
|
|
874cf4ef0a | ||
|
|
87e5929cb1 | ||
|
|
84b1e0ac41 | ||
|
|
539360d5f6 | ||
|
|
ca08f8d8da | ||
|
|
e1ce672569 | ||
|
|
717080b58c | ||
|
|
51696c509f | ||
|
|
4a5ae9f6f1 | ||
|
|
fa9f324f78 | ||
|
|
bcc77f11cd | ||
|
|
f737f292e3 | ||
|
|
1c18a5207c | ||
|
|
fa2b1e3821 | ||
|
|
6184753822 | ||
|
|
91a9c860ea | ||
|
|
0730ac369f | ||
|
|
aaa5a6ae18 | ||
|
|
5372f31be8 | ||
|
|
6d01877d78 | ||
|
|
646f3afd27 | ||
|
|
030f22b66f | ||
|
|
98815f2b85 | ||
|
|
a4fe3fe142 | ||
|
|
5b0857e169 | ||
|
|
975a414c5f | ||
|
|
95eb5a6117 | ||
|
|
8a7e69b902 | ||
|
|
dc035469ed | ||
|
|
ec4a00cdfc | ||
|
|
21937c02ff | ||
|
|
edfd446e46 | ||
|
|
7ec78b941e | ||
|
|
95bf1039c0 | ||
|
|
e6def6f5f9 | ||
|
|
de0b03630a | ||
|
|
90a2a79d5b | ||
|
|
21efd6d06a | ||
|
|
ea288a6133 | ||
|
|
da16f6cee7 | ||
|
|
f285395e0f | ||
|
|
b54e3aeaf9 | ||
|
|
23baaa7dba | ||
|
|
8008c986d3 | ||
|
|
b9efc919ea | ||
|
|
6cc6fd9468 | ||
|
|
53c9169043 | ||
|
|
eb2f4991ee | ||
|
|
16017a3c31 | ||
|
|
98d9adef8a | ||
|
|
9e96aac04d | ||
|
|
3395f8ebe6 | ||
|
|
e7264108dd | ||
|
|
2bcbb03c10 | ||
|
|
9cf20942f1 | ||
|
|
dbb98e981a | ||
|
|
3ae39b2e7c | ||
|
|
7b43b516c9 | ||
|
|
12d6a2c5de | ||
|
|
26bba49193 | ||
|
|
4e69a2656c | ||
|
|
68d504c79d | ||
|
|
2180b1ac3b | ||
|
|
32712a8798 | ||
|
|
73c7ad55b6 | ||
|
|
a34c5ace5c | ||
|
|
fd77661f41 | ||
|
|
ad07cf25d8 | ||
|
|
4daf1b1ba3 | ||
|
|
4b189ab146 | ||
|
|
64a69e3910 | ||
|
|
9482404ca7 | ||
|
|
124d4fab9b | ||
|
|
722406f636 | ||
|
|
6d4957b148 |
26
.codecov.yml
Normal file
26
.codecov.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
codecov:
|
||||
notify:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "70...100"
|
||||
|
||||
status:
|
||||
project: yes
|
||||
patch: yes
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
layout: "header, diff"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
40
.gitattributes
vendored
Normal file
40
.gitattributes
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
# *.c text
|
||||
# *.h text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
# Source files
|
||||
# ============
|
||||
*.pxd text eol=crlf
|
||||
*.py text eol=crlf
|
||||
*.py3 text eol=crlf
|
||||
*.pyw text eol=crlf
|
||||
*.pyx text eol=crlf
|
||||
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
# Binary files
|
||||
# ============
|
||||
*.db binary
|
||||
*.p binary
|
||||
*.pkl binary
|
||||
*.pyc binary
|
||||
*.pyd binary
|
||||
*.pyo binary
|
||||
|
||||
# Note: .db, .p, and .pkl files are associated
|
||||
# with the python modules ``pickle``, ``dbm.*``,
|
||||
# ``shelve``, ``marshal``, ``anydbm``, & ``bsddb``
|
||||
# (among others).
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
# Image files
|
||||
# ============
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.icns binary
|
||||
*.ico binary
|
||||
116
.gitignore
vendored
116
.gitignore
vendored
@@ -4,19 +4,117 @@
|
||||
#Kwrite/Gedit/Other crapapps making backups
|
||||
*~
|
||||
|
||||
#Eclipse
|
||||
.project
|
||||
.pydevproject
|
||||
.settings
|
||||
|
||||
#Patch files
|
||||
*.patch
|
||||
|
||||
#Personal
|
||||
saveddata/
|
||||
|
||||
#PyCharm
|
||||
.idea/
|
||||
/saveddata/
|
||||
|
||||
#Pyfa file
|
||||
pyfaFits.html
|
||||
|
||||
#Temporary files
|
||||
*.py__jb_tmp__
|
||||
|
||||
# Based on https://github.com/github/gitignore
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
Pyfa.egg-info/
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
.venv/
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# Eclipse project settings
|
||||
.project
|
||||
.pydevproject
|
||||
.settings
|
||||
|
||||
# Pycharm project settings
|
||||
.idea
|
||||
eos.iml
|
||||
|
||||
25
.travis.yml
Normal file
25
.travis.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
language: python
|
||||
python:
|
||||
- '2.7'
|
||||
env:
|
||||
- TOXENV=pep8
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# for wxPython:
|
||||
- python-wxgtk2.8
|
||||
- python-wxtools
|
||||
- wx2.8-doc
|
||||
- wx2.8-examples
|
||||
- wx2.8-headers
|
||||
- wx2.8-i18n
|
||||
before_install:
|
||||
- pip install -U tox
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements_test.txt
|
||||
script:
|
||||
- tox
|
||||
- py.test --cov=./
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
68
README.md
68
README.md
@@ -1,15 +1,67 @@
|
||||
# Pyfa
|
||||
# pyfa
|
||||
|
||||
Pyfa is a cross-platform desktop fitting application for EVE online that can be used natively on any platform where python and wxwidgets are available.
|
||||
[](https://pyfainvite.azurewebsites.net/)
|
||||
|
||||
It provides many advanced features such as graphs and full calculations of any possible combination of modules, fits, etc.
|
||||

|
||||
|
||||
Please see the [FAQ](https://github.com/DarkFenX/Pyfa/wiki/FAQ) for answers to common questions / concerns
|
||||
## What is it?
|
||||
|
||||
#### Links
|
||||
* [Development repository: http://github.com/DarkFenX/Pyfa](http://github.com/DarkFenX/Pyfa)
|
||||
* [XMPP conference:
|
||||
pyfa@conference.jabber.org](pyfa@conference.jabber.org)
|
||||
pyfa, short for **py**thon **f**itting **a**ssistant, allows you to create, experiment with, and save ship fittings without being in game. Open source and written in Python, it is available on any platform where Python 2.x and wxWidgets are available, including Windows, Mac OS X, and Linux.
|
||||
|
||||
## Latest Version and Changelogs
|
||||
The latest version along with release notes can always be found on the project's [Releases](https://github.com/DarkFenX/Pyfa/releases) page. pyfa will notify you if you are running an outdated version.
|
||||
|
||||
## Installation
|
||||
Windows and OS X users are supplied self-contained builds of pyfa on the [latest releases](https://github.com/pyfa-org/Pyfa/releases/latest) page. An `.exe` installer is also available for Windows builds. Linux users can run pyfa using their distribution's Python interpreter. There is no official self-contained package for Linux, however, there are a number of third-party packages available through distribution-specific repositories.
|
||||
|
||||
#### OS X
|
||||
There are two different distributives for OS X: `-mac` and `-mac-deprecated`.
|
||||
|
||||
* `-mac`: based on wxPython 3.0.2.0 and has updated libraries. This is the recommended build.
|
||||
* `-mac-deprecated`: utilizes older binaries running on wxPython 2.8; because of this, some features are not available (currently CREST support and Attribute Overrides). Additionally, as development happens primarily on wxPython 3.0, a few GUI bugs may pop up as `-mac-deprecated` is not actively tested. However, due to some general issues with wxPython 3.0, especially on some newer OS X versions, `-mac-deprecated` is still offered for those that need it.
|
||||
|
||||
There is also a [Homebrew](http://brew.sh) option for installing pyfa on OS X. Please note this is maintained by a third-party and is not tested by pyfa developers. Simply fire up in terminal:
|
||||
```
|
||||
$ brew install Caskroom/cask/pyfa
|
||||
```
|
||||
|
||||
### Linux Distro-specific Packages
|
||||
The following is a list of pyfa packages available for certain distributions. Please note that these packages are maintained by third-parties and are not evaluated by the pyfa developers.
|
||||
|
||||
* Debian/Ubuntu/derivitives: https://github.com/AdamMajer/Pyfa/releases
|
||||
* Arch: https://aur.archlinux.org/packages/pyfa/
|
||||
* openSUSE: https://build.opensuse.org/package/show/home:rmk2/pyfa
|
||||
* FreeBSD: http://www.freshports.org/games/pyfa/ (see [#484](https://github.com/pyfa-org/Pyfa/issues/484) for instructions)
|
||||
|
||||
### Dependencies
|
||||
If you wish to help with development or simply need to run pyfa through a Python interpreter, the following software is required:
|
||||
|
||||
* Python 2.7
|
||||
* `wxPython` 2.8/3.0
|
||||
* `sqlalchemy` >= 1.0.5
|
||||
* `dateutil`
|
||||
* `matplotlib` (for some Linux distributions you may need to install separate wxPython bindings such as `python-matplotlib-wx`)
|
||||
* `requests`
|
||||
|
||||
## Bug Reporting
|
||||
The preferred method of reporting bugs is through the project's [GitHub Issues interface](https://github.com/pyfa-org/Pyfa/issues). Alternatively, posting a report in the [pyfa thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609) on the official EVE Online forums is acceptable. Guidelines for bug reporting can be found on [this wiki page](https://github.com/DarkFenX/Pyfa/wiki/Bug-Reporting).
|
||||
|
||||
## License
|
||||
pyfa is licensed under the GNU GPL v3.0, see LICENSE
|
||||
|
||||
## Resources
|
||||
* Development repository: [https://github.com/pyfa-org/Pyfa](https://github.com/pyfa-org/Pyfa)
|
||||
* XMPP conference: [pyfa@conference.jabber.org](pyfa@conference.jabber.org)
|
||||
* [EVE forum thread](http://forums.eveonline.com/default.aspx?g=posts&t=247609)
|
||||
* [EVE University guide using pyfa](http://wiki.eveuniversity.org/Guide_to_using_PYFA)
|
||||
* [EVE Online website](http://www.eveonline.com/)
|
||||
|
||||
## Contacts:
|
||||
* Sable Blitzmann
|
||||
* GitHub: @blitzmann
|
||||
* [TweetFleet Slack](https://www.fuzzwork.co.uk/tweetfleet-slack-invites/): @blitzmann
|
||||
* [Gitter chat](https://gitter.im/pyfa-org/Pyfa): @ blitzmann
|
||||
* Email: sable.blitzmann@gmail.com
|
||||
|
||||
## CCP Copyright Notice
|
||||
EVE Online, the EVE logo, EVE and all associated logos and designs are the intellectual property of CCP hf. All artwork, screenshots, characters, vehicles, storylines, world facts or other recognizable features of the intellectual property relating to these trademarks are likewise the intellectual property of CCP hf. EVE Online and the EVE logo are the registered trademarks of CCP hf. All rights are reserved worldwide. All other trademarks are the property of their respective owners. CCP hf. has granted permission to pyfa to use EVE Online and all associated logos and designs for promotional and information purposes on its website but does not endorse, and is not in any way affiliated with, pyfa. CCP is in no way responsible for the content on or functioning of this program, nor can it be liable for any damage arising from the use of this program.
|
||||
|
||||
155
config.py
155
config.py
@@ -1,6 +1,11 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# TODO: move all logging back to pyfa.py main loop
|
||||
# We moved it here just to avoid rebuilding windows skeleton for now (any change to pyfa.py needs it)
|
||||
import logging
|
||||
import logging.handlers
|
||||
|
||||
# Load variable overrides specific to distribution type
|
||||
try:
|
||||
import configforced
|
||||
@@ -13,83 +18,155 @@ debug = False
|
||||
saveInRoot = False
|
||||
|
||||
# Version data
|
||||
version = "1.12.0"
|
||||
tag = "Stable"
|
||||
expansionName = "Carnyx"
|
||||
expansionVersion = "1.0"
|
||||
version = "1.26.1"
|
||||
tag = "git"
|
||||
expansionName = "YC118.10"
|
||||
expansionVersion = "1.2"
|
||||
evemonMinVersion = "4081"
|
||||
|
||||
# Database version (int ONLY)
|
||||
# Increment every time we need to flag for user database upgrade/modification
|
||||
dbversion = 7
|
||||
|
||||
pyfaPath = None
|
||||
savePath = None
|
||||
staticPath = None
|
||||
saveDB = None
|
||||
gameDB = None
|
||||
|
||||
# TODO: move back to pyfa.py main loop
|
||||
# We moved it here just to avoid rebuilding windows skeleton for now (any change to pyfa.py needs it)
|
||||
import logging
|
||||
logging.basicConfig()
|
||||
|
||||
def defPaths():
|
||||
class StreamToLogger(object):
|
||||
"""
|
||||
Fake file-like stream object that redirects writes to a logger instance.
|
||||
From: http://www.electricmonk.nl/log/2011/08/14/redirect-stdout-and-stderr-to-a-logger-in-python/
|
||||
"""
|
||||
|
||||
def __init__(self, logger, log_level=logging.INFO):
|
||||
self.logger = logger
|
||||
self.log_level = log_level
|
||||
self.linebuf = ''
|
||||
|
||||
def write(self, buf):
|
||||
for line in buf.rstrip().splitlines():
|
||||
self.logger.log(self.log_level, line.rstrip())
|
||||
|
||||
|
||||
def isFrozen():
|
||||
if hasattr(sys, 'frozen'):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def __createDirs(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def defPaths(customSavePath):
|
||||
global debug
|
||||
global pyfaPath
|
||||
global savePath
|
||||
global staticPath
|
||||
global saveDB
|
||||
global gameDB
|
||||
global saveInRoot
|
||||
|
||||
if debug:
|
||||
logLevel = logging.DEBUG
|
||||
else:
|
||||
logLevel = logging.WARN
|
||||
|
||||
# The main pyfa directory which contains run.py
|
||||
# Python 2.X uses ANSI by default, so we need to convert the character encoding
|
||||
pyfaPath = getattr(configforced, "pyfaPath", pyfaPath)
|
||||
if pyfaPath is None:
|
||||
pyfaPath = unicode(os.path.dirname(os.path.realpath(os.path.abspath(
|
||||
sys.modules['__main__'].__file__))), sys.getfilesystemencoding())
|
||||
pyfaPath = getPyfaPath()
|
||||
|
||||
# Where we store the saved fits etc, default is the current users home directory
|
||||
if saveInRoot is True:
|
||||
savePath = getattr(configforced, "savePath", None)
|
||||
if savePath is None:
|
||||
savePath = os.path.join(pyfaPath, "saveddata")
|
||||
savePath = getPyfaPath("saveddata")
|
||||
else:
|
||||
savePath = getattr(configforced, "savePath", None)
|
||||
if savePath is None:
|
||||
savePath = unicode(os.path.expanduser(os.path.join("~", ".pyfa")),
|
||||
sys.getfilesystemencoding())
|
||||
if customSavePath is None: # customSavePath is not overriden
|
||||
savePath = os.path.expanduser(os.path.join("~", ".pyfa"))
|
||||
else:
|
||||
savePath = customSavePath
|
||||
|
||||
# Redirect stderr to file if we're requested to do so
|
||||
stderrToFile = getattr(configforced, "stderrToFile", None)
|
||||
if stderrToFile is True:
|
||||
if not os.path.exists(savePath):
|
||||
os.mkdir(savePath)
|
||||
sys.stderr = open(os.path.join(savePath, "error_log.txt"), "w")
|
||||
__createDirs(savePath)
|
||||
|
||||
# Same for stdout
|
||||
stdoutToFile = getattr(configforced, "stdoutToFile", None)
|
||||
if stdoutToFile is True:
|
||||
if not os.path.exists(savePath):
|
||||
os.mkdir(savePath)
|
||||
sys.stdout = open(os.path.join(savePath, "output_log.txt"), "w")
|
||||
if isFrozen():
|
||||
certName = "cacert.pem"
|
||||
os.environ["REQUESTS_CA_BUNDLE"] = getPyfaPath(certName).encode('utf8')
|
||||
os.environ["SSL_CERT_FILE"] = getPyfaPath(certName).encode('utf8')
|
||||
|
||||
# Static EVE Data from the staticdata repository, should be in the staticdata
|
||||
# directory in our pyfa directory
|
||||
staticPath = os.path.join(pyfaPath, "staticdata")
|
||||
loggingFormat = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
|
||||
logging.basicConfig(format=loggingFormat, level=logLevel)
|
||||
handler = logging.handlers.RotatingFileHandler(getSavePath("log.txt"), maxBytes=1000000, backupCount=3)
|
||||
formatter = logging.Formatter(loggingFormat)
|
||||
handler.setFormatter(formatter)
|
||||
logging.getLogger('').addHandler(handler)
|
||||
|
||||
logging.info("Starting pyfa")
|
||||
|
||||
if hasattr(sys, 'frozen'):
|
||||
stdout_logger = logging.getLogger('STDOUT')
|
||||
sl = StreamToLogger(stdout_logger, logging.INFO)
|
||||
sys.stdout = sl
|
||||
|
||||
# This interferes with cx_Freeze's own handling of exceptions. Find a way to fix this.
|
||||
# stderr_logger = logging.getLogger('STDERR')
|
||||
# sl = StreamToLogger(stderr_logger, logging.ERROR)
|
||||
# sys.stderr = sl
|
||||
|
||||
# The database where we store all the fits etc
|
||||
saveDB = os.path.join(savePath, "saveddata.db")
|
||||
saveDB = getSavePath("saveddata.db")
|
||||
|
||||
# The database where the static EVE data from the datadump is kept.
|
||||
# This is not the standard sqlite datadump but a modified version created by eos
|
||||
# maintenance script
|
||||
gameDB = os.path.join(staticPath, "eve.db")
|
||||
gameDB = getPyfaPath("eve.db")
|
||||
|
||||
## DON'T MODIFY ANYTHING BELOW ##
|
||||
# DON'T MODIFY ANYTHING BELOW!
|
||||
import eos.config
|
||||
|
||||
#Caching modifiers, disable all gamedata caching, its unneeded.
|
||||
# Caching modifiers, disable all gamedata caching, its unneeded.
|
||||
eos.config.gamedataCache = False
|
||||
# saveddata db location modifier, shouldn't ever need to touch this
|
||||
eos.config.saveddata_connectionstring = "sqlite:///" + saveDB + "?check_same_thread=False"
|
||||
eos.config.gamedata_connectionstring = "sqlite:///" + gameDB + "?check_same_thread=False"
|
||||
|
||||
|
||||
def getPyfaPath(Append=None):
|
||||
base = getattr(sys.modules['__main__'], "__file__", sys.executable) if isFrozen() else sys.argv[0]
|
||||
root = os.path.dirname(os.path.realpath(os.path.abspath(base)))
|
||||
|
||||
if Append:
|
||||
path = parsePath(root, Append)
|
||||
else:
|
||||
path = parsePath(root)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def getSavePath(Append=None):
|
||||
root = savePath
|
||||
|
||||
if Append:
|
||||
path = parsePath(root, Append)
|
||||
else:
|
||||
path = parsePath(root)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def parsePath(root, Append=None):
|
||||
if Append:
|
||||
path = os.path.join(root, Append)
|
||||
else:
|
||||
path = root
|
||||
|
||||
if type(path) == str: # leave unicode ones alone
|
||||
try:
|
||||
path = path.decode('utf8')
|
||||
except UnicodeDecodeError:
|
||||
path = path.decode('windows-1252')
|
||||
|
||||
return path
|
||||
|
||||
BIN
dist_assets/mac/pyfa.icns
Normal file
BIN
dist_assets/mac/pyfa.icns
Normal file
Binary file not shown.
BIN
dist_assets/win/pyfa.ico
Normal file
BIN
dist_assets/win/pyfa.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
@@ -1,6 +1,7 @@
|
||||
version = "0.2.3"
|
||||
tag = "git"
|
||||
|
||||
|
||||
def test():
|
||||
import tests.runTests
|
||||
import unittest
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import heapq
|
||||
from math import sqrt, exp
|
||||
import time
|
||||
|
||||
from math import sqrt, exp
|
||||
|
||||
DAY = 24 * 60 * 60 * 1000
|
||||
|
||||
def lcm(a,b):
|
||||
n = a*b
|
||||
|
||||
def lcm(a, b):
|
||||
n = a * b
|
||||
while b:
|
||||
a, b = b, a % b
|
||||
return n / a
|
||||
@@ -40,45 +40,38 @@ class CapSimulator(object):
|
||||
# relevant decimal digits of capacitor for LCM period optimization
|
||||
self.stability_precision = 1
|
||||
|
||||
|
||||
def scale_activation(self, duration, capNeed):
|
||||
for res in self.scale_resolutions:
|
||||
mod = duration % res
|
||||
if mod:
|
||||
if mod > res/2.0:
|
||||
mod = res-mod
|
||||
if mod > res / 2.0:
|
||||
mod = res - mod
|
||||
else:
|
||||
mod = -mod
|
||||
|
||||
if abs(mod) <= duration/100.0:
|
||||
if abs(mod) <= duration / 100.0:
|
||||
# only adjust if the adjustment is less than 1%
|
||||
duration += mod
|
||||
capNeed += float(mod)/duration * capNeed
|
||||
capNeed += float(mod) / duration * capNeed
|
||||
break
|
||||
|
||||
return duration, capNeed
|
||||
|
||||
def init(self, modules):
|
||||
"""prepare modules. a list of (duration, capNeed, clipSize) tuples is
|
||||
"""prepare modules. a list of (duration, capNeed, clipSize, disableStagger) tuples is
|
||||
expected, with clipSize 0 if the module has infinite ammo.
|
||||
"""
|
||||
mods = {}
|
||||
for module in modules:
|
||||
if module in mods:
|
||||
mods[module] += 1
|
||||
else:
|
||||
mods[module] = 1
|
||||
|
||||
self.modules = mods
|
||||
|
||||
self.modules = modules
|
||||
|
||||
def reset(self):
|
||||
"""Reset the simulator state"""
|
||||
self.state = []
|
||||
mods = {}
|
||||
period = 1
|
||||
disable_period = False
|
||||
|
||||
for (duration, capNeed, clipSize), amount in self.modules.iteritems():
|
||||
# Loop over modules, clearing clipSize if applicable, and group modules based on attributes
|
||||
for (duration, capNeed, clipSize, disableStagger) in self.modules:
|
||||
if self.scale:
|
||||
duration, capNeed = self.scale_activation(duration, capNeed)
|
||||
|
||||
@@ -87,14 +80,22 @@ class CapSimulator(object):
|
||||
if not self.reload and capNeed > 0:
|
||||
clipSize = 0
|
||||
|
||||
if self.stagger:
|
||||
# Group modules based on their properties
|
||||
if (duration, capNeed, clipSize, disableStagger) in mods:
|
||||
mods[(duration, capNeed, clipSize, disableStagger)] += 1
|
||||
else:
|
||||
mods[(duration, capNeed, clipSize, disableStagger)] = 1
|
||||
|
||||
# Loop over grouped modules, configure staggering and push to the simulation state
|
||||
for (duration, capNeed, clipSize, disableStagger), amount in mods.iteritems():
|
||||
if self.stagger and not disableStagger:
|
||||
if clipSize == 0:
|
||||
duration = int(duration/amount)
|
||||
duration = int(duration / amount)
|
||||
else:
|
||||
stagger_amount = (duration*clipSize+10000)/(amount*clipSize)
|
||||
stagger_amount = (duration * clipSize + 10000) / (amount * clipSize)
|
||||
for i in range(1, amount):
|
||||
heapq.heappush(self.state,
|
||||
[i*stagger_amount, duration,
|
||||
[i * stagger_amount, duration,
|
||||
capNeed, 0, clipSize])
|
||||
else:
|
||||
capNeed *= amount
|
||||
@@ -107,13 +108,11 @@ class CapSimulator(object):
|
||||
|
||||
heapq.heappush(self.state, [0, duration, capNeed, 0, clipSize])
|
||||
|
||||
|
||||
if disable_period:
|
||||
self.period = self.t_max
|
||||
else:
|
||||
self.period = period
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the simulation"""
|
||||
|
||||
@@ -133,13 +132,13 @@ class CapSimulator(object):
|
||||
capCapacity = self.capacitorCapacity
|
||||
tau = self.capacitorRecharge / 5.0
|
||||
|
||||
cap_wrap = capCapacity # cap value at last period
|
||||
cap_lowest = capCapacity # lowest cap value encountered
|
||||
cap_lowest_pre = capCapacity # lowest cap value before activations
|
||||
cap = capCapacity # current cap value
|
||||
t_wrap = self.period # point in time of next period
|
||||
cap_wrap = capCapacity # cap value at last period
|
||||
cap_lowest = capCapacity # lowest cap value encountered
|
||||
cap_lowest_pre = capCapacity # lowest cap value before activations
|
||||
cap = capCapacity # current cap value
|
||||
t_wrap = self.period # point in time of next period
|
||||
|
||||
t_now = t_last = 0
|
||||
t_last = 0
|
||||
t_max = self.t_max
|
||||
|
||||
while 1:
|
||||
@@ -148,7 +147,7 @@ class CapSimulator(object):
|
||||
if t_now >= t_max:
|
||||
break
|
||||
|
||||
cap = ((1.0+(sqrt(cap/capCapacity)-1.0)*exp((t_last-t_now)/tau))**2)*capCapacity
|
||||
cap = ((1.0 + (sqrt(cap / capCapacity) - 1.0) * exp((t_last - t_now) / tau)) ** 2) * capCapacity
|
||||
|
||||
if t_now != t_last:
|
||||
if cap < cap_lowest_pre:
|
||||
@@ -167,20 +166,20 @@ class CapSimulator(object):
|
||||
|
||||
iterations += 1
|
||||
|
||||
t_last = t_now
|
||||
|
||||
if cap < cap_lowest:
|
||||
if cap < 0.0:
|
||||
break
|
||||
cap_lowest = cap
|
||||
|
||||
t_last = t_now
|
||||
|
||||
# queue the next activation of this module
|
||||
t_now += duration
|
||||
shot += 1
|
||||
if clipSize:
|
||||
if shot % clipSize == 0:
|
||||
shot = 0
|
||||
t_now += 10000 # include reload time
|
||||
t_now += 10000 # include reload time
|
||||
activation[0] = t_now
|
||||
activation[3] = shot
|
||||
|
||||
@@ -193,19 +192,17 @@ class CapSimulator(object):
|
||||
|
||||
# calculate EVE's stability value
|
||||
try:
|
||||
avgDrain = reduce(float.__add__, map(lambda x: x[2]/x[1], self.state), 0.0)
|
||||
self.cap_stable_eve = 0.25 * (1.0 + sqrt(-(2.0 * avgDrain * tau - capCapacity)/capCapacity)) ** 2
|
||||
avgDrain = reduce(float.__add__, map(lambda x: x[2] / x[1], self.state), 0.0)
|
||||
self.cap_stable_eve = 0.25 * (1.0 + sqrt(-(2.0 * avgDrain * tau - capCapacity) / capCapacity)) ** 2
|
||||
except ValueError:
|
||||
self.cap_stable_eve = 0.0
|
||||
|
||||
|
||||
if cap > 0.0:
|
||||
# capacitor low/high water marks
|
||||
self.cap_stable_low = cap_lowest
|
||||
self.cap_stable_high = cap_lowest_pre
|
||||
else:
|
||||
self.cap_stable_low =\
|
||||
self.cap_stable_high = 0.0
|
||||
self.cap_stable_low = \
|
||||
self.cap_stable_high = 0.0
|
||||
|
||||
|
||||
self.runtime = time.time()-start
|
||||
self.runtime = time.time() - start
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
from os.path import realpath, join, dirname, abspath
|
||||
import sys
|
||||
from os.path import realpath, join, dirname, abspath
|
||||
|
||||
debug = False
|
||||
gamedataCache = True
|
||||
saveddataCache = True
|
||||
gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "staticdata", "eve.db")), sys.getfilesystemencoding())
|
||||
saveddata_connectionstring = 'sqlite:///:memory:'
|
||||
gamedata_version = ""
|
||||
gamedata_connectionstring = 'sqlite:///' + unicode(realpath(join(dirname(abspath(__file__)), "..", "eve.db")),
|
||||
sys.getfilesystemencoding())
|
||||
saveddata_connectionstring = 'sqlite:///' + unicode(
|
||||
realpath(join(dirname(abspath(__file__)), "..", "saveddata", "saveddata.db")), sys.getfilesystemencoding())
|
||||
|
||||
#Autodetect path, only change if the autodetection bugs out.
|
||||
|
||||
# Autodetect path, only change if the autodetection bugs out.
|
||||
path = dirname(unicode(__file__, sys.getfilesystemencoding()))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
import threading
|
||||
|
||||
@@ -24,17 +24,20 @@ from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import pool
|
||||
|
||||
from eos import config
|
||||
|
||||
import migration
|
||||
from eos import config
|
||||
|
||||
|
||||
class ReadOnlyException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
gamedata_connectionstring = config.gamedata_connectionstring
|
||||
if callable(gamedata_connectionstring):
|
||||
gamedata_engine = create_engine("sqlite://", creator=gamedata_connectionstring, echo = config.debug)
|
||||
gamedata_engine = create_engine("sqlite://", creator=gamedata_connectionstring, echo=config.debug)
|
||||
else:
|
||||
gamedata_engine = create_engine(gamedata_connectionstring, echo = config.debug)
|
||||
gamedata_engine = create_engine(gamedata_connectionstring, echo=config.debug)
|
||||
|
||||
gamedata_meta = MetaData()
|
||||
gamedata_meta.bind = gamedata_engine
|
||||
@@ -44,8 +47,8 @@ gamedata_session = sessionmaker(bind=gamedata_engine, autoflush=False, expire_on
|
||||
# game db because we haven't reached gamedata_meta.create_all()
|
||||
try:
|
||||
config.gamedata_version = gamedata_session.execute(
|
||||
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'"
|
||||
).fetchone()[0]
|
||||
"SELECT `field_value` FROM `metadata` WHERE `field_name` LIKE 'client_build'"
|
||||
).fetchone()[0]
|
||||
except:
|
||||
config.gamedata_version = None
|
||||
|
||||
@@ -63,25 +66,19 @@ if saveddata_connectionstring is not None:
|
||||
# Lock controlling any changes introduced to session
|
||||
sd_lock = threading.Lock()
|
||||
|
||||
#Import all the definitions for all our database stuff
|
||||
# Import all the definitions for all our database stuff
|
||||
from eos.db.gamedata import *
|
||||
from eos.db.saveddata import *
|
||||
|
||||
#Import queries
|
||||
from eos.db.gamedata.queries import getItem, searchItems, getVariations, getItemsByCategory, directAttributeRequest, \
|
||||
getMarketGroup, getGroup, getCategory, getAttributeInfo, getMetaData, getMetaGroup
|
||||
from eos.db.saveddata.queries import getUser, getCharacter, getFit, getFitsWithShip, countFitsWithShip, searchFits, \
|
||||
getCharacterList, getPrice, getDamagePatternList, getDamagePattern, \
|
||||
getFitList, getFleetList, getFleet, save, remove, commit, add, \
|
||||
getCharactersForUser, getMiscData, getSquadsIDsWithFitID, getWing, \
|
||||
getSquad, getBoosterFits, getProjectedFits, getTargetResistsList, getTargetResists,\
|
||||
clearPrices, countAllFits
|
||||
# Import queries
|
||||
from eos.db.gamedata.queries import *
|
||||
from eos.db.saveddata.queries import *
|
||||
|
||||
#If using in memory saveddata, you'll want to reflect it so the data structure is good.
|
||||
# If using in memory saveddata, you'll want to reflect it so the data structure is good.
|
||||
if config.saveddata_connectionstring == "sqlite:///:memory:":
|
||||
saveddata_meta.create_all()
|
||||
|
||||
|
||||
def rollback():
|
||||
with sd_lock:
|
||||
saveddata_session.rollback()
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
__all__ = ["attribute", "category", "effect", "group", "metaData",
|
||||
"icon", "item", "marketGroup", "metaGroup", "unit"]
|
||||
"icon", "item", "marketGroup", "metaGroup", "unit", "alphaClones"]
|
||||
|
||||
46
eos/db/gamedata/alphaClones.py
Normal file
46
eos/db/gamedata/alphaClones.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Table, ForeignKey
|
||||
from sqlalchemy.orm import relation, mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import AlphaClone, AlphaCloneSkill
|
||||
|
||||
alphaclones_table = Table("alphaClones", gamedata_meta,
|
||||
Column("alphaCloneID", Integer, primary_key=True),
|
||||
Column("alphaCloneName", String),
|
||||
)
|
||||
|
||||
alphacloneskskills_table = Table("alphaCloneSkills", gamedata_meta,
|
||||
Column("alphaCloneID", Integer, ForeignKey("alphaClones.alphaCloneID"), primary_key=True),
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("level", Integer),
|
||||
)
|
||||
|
||||
mapper(AlphaClone, alphaclones_table,
|
||||
properties={
|
||||
"ID": synonym("alphaCloneID"),
|
||||
"skills": relation(
|
||||
AlphaCloneSkill,
|
||||
cascade="all,delete-orphan",
|
||||
backref="clone")
|
||||
})
|
||||
|
||||
mapper(AlphaCloneSkill, alphacloneskskills_table)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,20 +15,22 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, Unicode, ForeignKey, String, Boolean
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from eos.types import Attribute, Icon, AttributeInfo, Unit
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Attribute, Icon, AttributeInfo, Unit
|
||||
|
||||
typeattributes_table = Table("dgmtypeattribs", gamedata_meta,
|
||||
Column("value", Float),
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
Column("attributeID", ForeignKey("dgmattribs.attributeID"), primary_key=True))
|
||||
Column("value", Float),
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
Column("attributeID", ForeignKey("dgmattribs.attributeID"), primary_key=True))
|
||||
|
||||
attributes_table = Table("dgmattribs", gamedata_meta,
|
||||
Column("attributeID", Integer, primary_key = True),
|
||||
Column("attributeID", Integer, primary_key=True),
|
||||
Column("attributeName", String),
|
||||
Column("defaultValue", Float),
|
||||
Column("maxAttributeID", Integer, ForeignKey("dgmattribs.attributeID")),
|
||||
@@ -40,14 +42,14 @@ attributes_table = Table("dgmattribs", gamedata_meta,
|
||||
Column("unitID", Integer, ForeignKey("dgmunits.unitID")))
|
||||
|
||||
mapper(Attribute, typeattributes_table,
|
||||
properties = {"info": relation(AttributeInfo, lazy=False)})
|
||||
properties={"info": relation(AttributeInfo, lazy=False)})
|
||||
|
||||
mapper(AttributeInfo, attributes_table,
|
||||
properties = {"icon" : relation(Icon),
|
||||
"unit": relation(Unit),
|
||||
"ID": synonym("attributeID"),
|
||||
"name": synonym("attributeName"),
|
||||
"description" : deferred(attributes_table.c.description)})
|
||||
properties={"icon": relation(Icon),
|
||||
"unit": relation(Unit),
|
||||
"ID": synonym("attributeID"),
|
||||
"name": synonym("attributeName"),
|
||||
"description": deferred(attributes_table.c.description)})
|
||||
|
||||
Attribute.ID = association_proxy("info", "attributeID")
|
||||
Attribute.name = association_proxy("info", "attributeName")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, ForeignKey, Boolean, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
@@ -24,14 +24,14 @@ from eos.db import gamedata_meta
|
||||
from eos.types import Category, Icon
|
||||
|
||||
categories_table = Table("invcategories", gamedata_meta,
|
||||
Column("categoryID", Integer, primary_key = True),
|
||||
Column("categoryID", Integer, primary_key=True),
|
||||
Column("categoryName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(Category, categories_table,
|
||||
properties = {"icon" : relation(Icon),
|
||||
"ID" : synonym("categoryID"),
|
||||
"name" : synonym("categoryName"),
|
||||
"description" : deferred(categories_table.c.description)})
|
||||
properties={"icon": relation(Icon),
|
||||
"ID": synonym("categoryID"),
|
||||
"name": synonym("categoryName"),
|
||||
"description": deferred(categories_table.c.description)})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,35 +15,35 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, Table, ForeignKey
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import mapper, synonym, relation, deferred
|
||||
from eos.types import Effect, EffectInfo
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Effect, EffectInfo
|
||||
|
||||
typeeffects_table = Table("dgmtypeeffects", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True, index=True),
|
||||
Column("effectID", Integer, ForeignKey("dgmeffects.effectID"), primary_key=True))
|
||||
|
||||
effects_table = Table("dgmeffects", gamedata_meta,
|
||||
Column("effectID", Integer, primary_key = True),
|
||||
Column("effectID", Integer, primary_key=True),
|
||||
Column("effectName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
Column("isAssistance", Boolean),
|
||||
Column("isOffensive", Boolean))
|
||||
|
||||
|
||||
mapper(EffectInfo, effects_table,
|
||||
properties = {"ID" : synonym("effectID"),
|
||||
"name" : synonym("effectName"),
|
||||
"description" : deferred(effects_table.c.description)})
|
||||
properties={"ID": synonym("effectID"),
|
||||
"name": synonym("effectName"),
|
||||
"description": deferred(effects_table.c.description)})
|
||||
|
||||
mapper(Effect, typeeffects_table,
|
||||
properties = {"ID": synonym("effectID"),
|
||||
"info": relation(EffectInfo, lazy=False)})
|
||||
properties={"ID": synonym("effectID"),
|
||||
"info": relation(EffectInfo, lazy=False)})
|
||||
|
||||
Effect.name = association_proxy("info", "name")
|
||||
Effect.description = association_proxy("info", "description")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
@@ -24,7 +24,7 @@ from eos.db import gamedata_meta
|
||||
from eos.types import Group, Icon, Category
|
||||
|
||||
groups_table = Table("invgroups", gamedata_meta,
|
||||
Column("groupID", Integer, primary_key = True),
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("groupName", String),
|
||||
Column("description", String),
|
||||
Column("published", Boolean),
|
||||
@@ -32,8 +32,8 @@ groups_table = Table("invgroups", gamedata_meta,
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(Group, groups_table,
|
||||
properties = {"category" : relation(Category, backref = "groups"),
|
||||
"icon" : relation(Icon),
|
||||
"ID" : synonym("groupID"),
|
||||
"name" : synonym("groupName"),
|
||||
"description" : deferred(groups_table.c.description)})
|
||||
properties={"category": relation(Category, backref="groups"),
|
||||
"icon": relation(Icon),
|
||||
"ID": synonym("groupID"),
|
||||
"name": synonym("groupName"),
|
||||
"description": deferred(groups_table.c.description)})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Table
|
||||
from sqlalchemy.orm import mapper, synonym, deferred
|
||||
@@ -24,10 +24,10 @@ from eos.db import gamedata_meta
|
||||
from eos.types import Icon
|
||||
|
||||
icons_table = Table("icons", gamedata_meta,
|
||||
Column("iconID", Integer, primary_key = True),
|
||||
Column("iconID", Integer, primary_key=True),
|
||||
Column("description", String),
|
||||
Column("iconFile", String))
|
||||
|
||||
mapper(Icon, icons_table,
|
||||
properties = {"ID" : synonym("iconID"),
|
||||
"description" : deferred(icons_table.c.description)})
|
||||
properties={"ID": synonym("iconID"),
|
||||
"description": deferred(icons_table.c.description)})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,18 +15,18 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table, Float
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Icon, Attribute, Item, Effect, MetaType, Group, Traits
|
||||
|
||||
items_table = Table("invtypes", gamedata_meta,
|
||||
Column("typeID", Integer, primary_key = True),
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("typeName", String, index=True),
|
||||
Column("description", String),
|
||||
Column("raceID", Integer),
|
||||
@@ -39,23 +39,23 @@ items_table = Table("invtypes", gamedata_meta,
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")),
|
||||
Column("groupID", Integer, ForeignKey("invgroups.groupID"), index=True))
|
||||
|
||||
from .metaGroup import metatypes_table
|
||||
from .traits import traits_table
|
||||
from .metaGroup import metatypes_table # noqa
|
||||
from .traits import traits_table # noqa
|
||||
|
||||
mapper(Item, items_table,
|
||||
properties = {"group" : relation(Group, backref = "items"),
|
||||
"icon" : relation(Icon),
|
||||
"_Item__attributes" : relation(Attribute, collection_class = attribute_mapped_collection('name')),
|
||||
"effects" : relation(Effect, collection_class = attribute_mapped_collection('name')),
|
||||
"metaGroup" : relation(MetaType,
|
||||
primaryjoin = metatypes_table.c.typeID == items_table.c.typeID,
|
||||
uselist = False),
|
||||
"ID" : synonym("typeID"),
|
||||
"name" : synonym("typeName"),
|
||||
"description" : deferred(items_table.c.description),
|
||||
"traits" : relation(Traits,
|
||||
primaryjoin = traits_table.c.typeID == items_table.c.typeID,
|
||||
uselist = False)
|
||||
})
|
||||
properties={"group": relation(Group, backref="items"),
|
||||
"icon": relation(Icon),
|
||||
"_Item__attributes": relation(Attribute, collection_class=attribute_mapped_collection('name')),
|
||||
"effects": relation(Effect, collection_class=attribute_mapped_collection('name')),
|
||||
"metaGroup": relation(MetaType,
|
||||
primaryjoin=metatypes_table.c.typeID == items_table.c.typeID,
|
||||
uselist=False),
|
||||
"ID": synonym("typeID"),
|
||||
"name": synonym("typeName"),
|
||||
"description": deferred(items_table.c.description),
|
||||
"traits": relation(Traits,
|
||||
primaryjoin=traits_table.c.typeID == items_table.c.typeID,
|
||||
uselist=False)
|
||||
})
|
||||
|
||||
Item.category = association_proxy("group", "category")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey, Table
|
||||
from sqlalchemy.orm import relation, mapper, synonym, deferred
|
||||
@@ -24,17 +24,19 @@ from eos.db import gamedata_meta
|
||||
from eos.types import Item, MarketGroup, Icon
|
||||
|
||||
marketgroups_table = Table("invmarketgroups", gamedata_meta,
|
||||
Column("marketGroupID", Integer, primary_key = True),
|
||||
Column("marketGroupID", Integer, primary_key=True),
|
||||
Column("marketGroupName", String),
|
||||
Column("description", String),
|
||||
Column("hasTypes", Boolean),
|
||||
Column("parentGroupID", Integer, ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
|
||||
Column("parentGroupID", Integer,
|
||||
ForeignKey("invmarketgroups.marketGroupID", initially="DEFERRED", deferrable=True)),
|
||||
Column("iconID", Integer, ForeignKey("icons.iconID")))
|
||||
|
||||
mapper(MarketGroup, marketgroups_table,
|
||||
properties = {"items" : relation(Item, backref = "marketGroup"),
|
||||
"parent" : relation(MarketGroup, backref = "children", remote_side = [marketgroups_table.c.marketGroupID]),
|
||||
"icon" : relation(Icon),
|
||||
"ID" : synonym("marketGroupID"),
|
||||
"name" : synonym("marketGroupName"),
|
||||
"description" : deferred(marketgroups_table.c.description)})
|
||||
properties={"items": relation(Item, backref="marketGroup"),
|
||||
"parent": relation(MarketGroup, backref="children",
|
||||
remote_side=[marketgroups_table.c.marketGroupID]),
|
||||
"icon": relation(Icon),
|
||||
"ID": synonym("marketGroupID"),
|
||||
"name": synonym("marketGroupName"),
|
||||
"description": deferred(marketgroups_table.c.description)})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,15 +15,16 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.types import MetaData
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import MetaData
|
||||
|
||||
metadata_table = Table("metadata", gamedata_meta,
|
||||
Column("field_name", String, primary_key=True),
|
||||
Column("field_value", String))
|
||||
Column("field_name", String, primary_key=True),
|
||||
Column("field_value", String))
|
||||
|
||||
mapper(MetaData, metadata_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,33 +15,33 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import relation, mapper, synonym
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.db.gamedata.item import items_table
|
||||
from eos.types import MetaGroup, Item, MetaType
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
|
||||
metagroups_table = Table("invmetagroups", gamedata_meta,
|
||||
Column("metaGroupID", Integer, primary_key = True),
|
||||
Column("metaGroupID", Integer, primary_key=True),
|
||||
Column("metaGroupName", String))
|
||||
|
||||
metatypes_table = Table("invmetatypes", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key = True),
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
|
||||
Column("parentTypeID", Integer, ForeignKey("invtypes.typeID")),
|
||||
Column("metaGroupID", Integer, ForeignKey("invmetagroups.metaGroupID")))
|
||||
|
||||
mapper(MetaGroup, metagroups_table,
|
||||
properties = {"ID" : synonym("metaGroupID"),
|
||||
"name" : synonym("metaGroupName")})
|
||||
properties={"ID": synonym("metaGroupID"),
|
||||
"name": synonym("metaGroupName")})
|
||||
|
||||
mapper(MetaType, metatypes_table,
|
||||
properties = {"ID" : synonym("metaGroupID"),
|
||||
"parent" : relation(Item, primaryjoin = metatypes_table.c.parentTypeID == items_table.c.typeID),
|
||||
"items" : relation(Item, primaryjoin = metatypes_table.c.typeID == items_table.c.typeID),
|
||||
"info": relation(MetaGroup, lazy=False)})
|
||||
properties={"ID": synonym("metaGroupID"),
|
||||
"parent": relation(Item, primaryjoin=metatypes_table.c.parentTypeID == items_table.c.typeID),
|
||||
"items": relation(Item, primaryjoin=metatypes_table.c.typeID == items_table.c.typeID),
|
||||
"info": relation(MetaGroup, lazy=False)})
|
||||
|
||||
MetaType.name = association_proxy("info", "name")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,21 +15,26 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy.orm import join, exc
|
||||
from sqlalchemy.sql import and_, or_, select
|
||||
|
||||
import eos.config
|
||||
# TODO: Unsure which item the code below needs :(
|
||||
# from eos.gamedata import Item
|
||||
from eos.gamedata import Attribute
|
||||
from eos.db import gamedata_session
|
||||
from eos.db.gamedata.metaGroup import metatypes_table, items_table
|
||||
from sqlalchemy.sql import and_, or_, select, func
|
||||
from sqlalchemy.orm import join, exc
|
||||
from eos.types import Item, Category, Group, MarketGroup, AttributeInfo, MetaData, MetaGroup
|
||||
from eos.db.util import processEager, processWhere
|
||||
import eos.config
|
||||
from eos.types import Item, Category, Group, MarketGroup, AttributeInfo, MetaData, MetaGroup, AlphaClone
|
||||
|
||||
configVal = getattr(eos.config, "gamedataCache", None)
|
||||
if configVal is True:
|
||||
def cachedQuery(amount, *keywords):
|
||||
def deco(function):
|
||||
cache = {}
|
||||
|
||||
def checkAndReturn(*args, **kwargs):
|
||||
useCache = kwargs.pop("useCache", True)
|
||||
cacheKey = []
|
||||
@@ -45,6 +50,7 @@ if configVal is True:
|
||||
return handler
|
||||
|
||||
return checkAndReturn
|
||||
|
||||
return deco
|
||||
|
||||
elif callable(configVal):
|
||||
@@ -56,8 +62,10 @@ else:
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return checkAndReturn
|
||||
|
||||
return deco
|
||||
|
||||
|
||||
def sqlizeString(line):
|
||||
# Escape backslashes first, as they will be as escape symbol in queries
|
||||
# Then escape percent and underscore signs
|
||||
@@ -65,7 +73,10 @@ def sqlizeString(line):
|
||||
line = line.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_").replace("*", "%")
|
||||
return line
|
||||
|
||||
|
||||
itemNameMap = {}
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getItem(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -88,7 +99,28 @@ def getItem(lookfor, eager=None):
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return item
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getAlphaClone(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
item = gamedata_session.query(AlphaClone).get(lookfor)
|
||||
else:
|
||||
item = gamedata_session.query(AlphaClone).options(*processEager(eager)).filter(AlphaClone.ID == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return item
|
||||
|
||||
|
||||
def getAlphaCloneList(eager=None):
|
||||
eager = processEager(eager)
|
||||
clones = gamedata_session.query(AlphaClone).options(*eager).all()
|
||||
return clones
|
||||
|
||||
|
||||
groupNameMap = {}
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -111,63 +143,78 @@ def getGroup(lookfor, eager=None):
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return group
|
||||
|
||||
|
||||
categoryNameMap = {}
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getCategory(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
category = gamedata_session.query(Category).get(lookfor)
|
||||
else:
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.ID == lookfor).first()
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(
|
||||
Category.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in categoryNameMap:
|
||||
id = categoryNameMap[lookfor]
|
||||
if eager is None:
|
||||
category = gamedata_session.query(Category).get(id)
|
||||
else:
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.ID == id).first()
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(
|
||||
Category.ID == id).first()
|
||||
else:
|
||||
# Category names are unique, so we can use first() instead of one()
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(Category.name == lookfor).first()
|
||||
category = gamedata_session.query(Category).options(*processEager(eager)).filter(
|
||||
Category.name == lookfor).first()
|
||||
categoryNameMap[lookfor] = category.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return category
|
||||
|
||||
|
||||
metaGroupNameMap = {}
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getMetaGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
metaGroup = gamedata_session.query(MetaGroup).get(lookfor)
|
||||
else:
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.ID == lookfor).first()
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(
|
||||
MetaGroup.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
if lookfor in metaGroupNameMap:
|
||||
id = metaGroupNameMap[lookfor]
|
||||
if eager is None:
|
||||
metaGroup = gamedata_session.query(MetaGroup).get(id)
|
||||
else:
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.ID == id).first()
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(
|
||||
MetaGroup.ID == id).first()
|
||||
else:
|
||||
# MetaGroup names are unique, so we can use first() instead of one()
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(MetaGroup.name == lookfor).first()
|
||||
metaGroup = gamedata_session.query(MetaGroup).options(*processEager(eager)).filter(
|
||||
MetaGroup.name == lookfor).first()
|
||||
metaGroupNameMap[lookfor] = metaGroup.ID
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return metaGroup
|
||||
|
||||
|
||||
@cachedQuery(1, "lookfor")
|
||||
def getMarketGroup(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
marketGroup = gamedata_session.query(MarketGroup).get(lookfor)
|
||||
else:
|
||||
marketGroup = gamedata_session.query(MarketGroup).options(*processEager(eager)).filter(MarketGroup.ID == lookfor).first()
|
||||
marketGroup = gamedata_session.query(MarketGroup).options(*processEager(eager)).filter(
|
||||
MarketGroup.ID == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return marketGroup
|
||||
|
||||
|
||||
@cachedQuery(2, "where", "filter")
|
||||
def getItemsByCategory(filter, where=None, eager=None):
|
||||
if isinstance(filter, int):
|
||||
@@ -178,7 +225,9 @@ def getItemsByCategory(filter, where=None, eager=None):
|
||||
raise TypeError("Need integer or string as argument")
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
return gamedata_session.query(Item).options(*processEager(eager)).join(Item.group, Group.category).filter(filter).all()
|
||||
return gamedata_session.query(Item).options(*processEager(eager)).join(Item.group, Group.category).filter(
|
||||
filter).all()
|
||||
|
||||
|
||||
@cachedQuery(3, "where", "nameLike", "join")
|
||||
def searchItems(nameLike, where=None, join=None, eager=None):
|
||||
@@ -194,10 +243,14 @@ def searchItems(nameLike, where=None, join=None, eager=None):
|
||||
items = gamedata_session.query(Item).options(*processEager(eager)).join(*join)
|
||||
for token in nameLike.split(' '):
|
||||
token_safe = u"%{0}%".format(sqlizeString(token))
|
||||
items = items.filter(processWhere(Item.name.like(token_safe, escape="\\"), where))
|
||||
if where is not None:
|
||||
items = items.filter(and_(Item.name.like(token_safe, escape="\\"), where))
|
||||
else:
|
||||
items = items.filter(Item.name.like(token_safe, escape="\\"))
|
||||
items = items.limit(100).all()
|
||||
return items
|
||||
|
||||
|
||||
@cachedQuery(2, "where", "itemids")
|
||||
def getVariations(itemids, where=None, eager=None):
|
||||
for itemid in itemids:
|
||||
@@ -210,9 +263,11 @@ def getVariations(itemids, where=None, eager=None):
|
||||
itemfilter = or_(*(metatypes_table.c.parentTypeID == itemid for itemid in itemids))
|
||||
filter = processWhere(itemfilter, where)
|
||||
joinon = items_table.c.typeID == metatypes_table.c.typeID
|
||||
vars = gamedata_session.query(Item).options(*processEager(eager)).join((metatypes_table, joinon)).filter(filter).all()
|
||||
vars = gamedata_session.query(Item).options(*processEager(eager)).join((metatypes_table, joinon)).filter(
|
||||
filter).all()
|
||||
return vars
|
||||
|
||||
|
||||
@cachedQuery(1, "attr")
|
||||
def getAttributeInfo(attr, eager=None):
|
||||
if isinstance(attr, basestring):
|
||||
@@ -227,6 +282,7 @@ def getAttributeInfo(attr, eager=None):
|
||||
result = None
|
||||
return result
|
||||
|
||||
|
||||
@cachedQuery(1, "field")
|
||||
def getMetaData(field):
|
||||
if isinstance(field, basestring):
|
||||
@@ -235,6 +291,7 @@ def getMetaData(field):
|
||||
raise TypeError("Need string as argument")
|
||||
return data
|
||||
|
||||
|
||||
@cachedQuery(2, "itemIDs", "attributeID")
|
||||
def directAttributeRequest(itemIDs, attrIDs):
|
||||
for itemID in itemIDs:
|
||||
@@ -244,9 +301,9 @@ def directAttributeRequest(itemIDs, attrIDs):
|
||||
if not isinstance(itemID, int):
|
||||
raise TypeError("All itemIDs must be integer")
|
||||
|
||||
q = select((eos.types.Item.typeID, eos.types.Attribute.attributeID, eos.types.Attribute.value),
|
||||
and_(eos.types.Attribute.attributeID.in_(attrIDs), eos.types.Item.typeID.in_(itemIDs)),
|
||||
from_obj=[join(eos.types.Attribute, eos.types.Item)])
|
||||
q = select((Item.typeID, Attribute.attributeID, Attribute.value),
|
||||
and_(Attribute.attributeID.in_(attrIDs), Item.typeID.in_(itemIDs)),
|
||||
from_obj=[join(Attribute, Item)])
|
||||
|
||||
result = gamedata_session.execute(q).fetchall()
|
||||
return result
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
from sqlalchemy import Column, Table, Integer, String, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.types import Traits
|
||||
|
||||
from eos.db import gamedata_meta
|
||||
from eos.types import Traits
|
||||
|
||||
traits_table = Table("invtraits", gamedata_meta,
|
||||
Column("typeID", Integer, ForeignKey("invtypes.typeID"), primary_key=True),
|
||||
Column("traitText", String))
|
||||
|
||||
mapper(Traits, traits_table);
|
||||
mapper(Traits, traits_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, Integer, String
|
||||
from sqlalchemy.orm import mapper, synonym
|
||||
@@ -24,10 +24,10 @@ from eos.db import gamedata_meta
|
||||
from eos.types import Unit
|
||||
|
||||
groups_table = Table("dgmunits", gamedata_meta,
|
||||
Column("unitID", Integer, primary_key = True),
|
||||
Column("unitID", Integer, primary_key=True),
|
||||
Column("unitName", String),
|
||||
Column("displayName", String))
|
||||
|
||||
mapper(Unit, groups_table,
|
||||
properties = {"ID" : synonym("unitID"),
|
||||
"name" : synonym("unitName")})
|
||||
properties={"ID": synonym("unitID"),
|
||||
"name": synonym("unitName")})
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
import config
|
||||
import logging
|
||||
import shutil
|
||||
import time
|
||||
|
||||
import config
|
||||
import migrations
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def getVersion(db):
|
||||
cursor = db.execute('PRAGMA user_version')
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def update(saveddata_engine):
|
||||
currversion = getVersion(saveddata_engine)
|
||||
|
||||
if currversion == config.dbversion:
|
||||
def getAppVersion():
|
||||
return migrations.appVersion
|
||||
|
||||
|
||||
def update(saveddata_engine):
|
||||
dbVersion = getVersion(saveddata_engine)
|
||||
appVersion = getAppVersion()
|
||||
|
||||
if dbVersion == appVersion:
|
||||
return
|
||||
|
||||
if currversion < config.dbversion:
|
||||
if dbVersion < appVersion:
|
||||
# Automatically backup database
|
||||
toFile = "%s/saveddata_migration_%d-%d_%s.db"%(
|
||||
toFile = "%s/saveddata_migration_%d-%d_%s.db" % (
|
||||
config.savePath,
|
||||
currversion,
|
||||
config.dbversion,
|
||||
dbVersion,
|
||||
appVersion,
|
||||
time.strftime("%Y%m%d_%H%M%S"))
|
||||
|
||||
shutil.copyfile(config.saveDB, toFile)
|
||||
|
||||
for version in xrange(currversion, config.dbversion):
|
||||
module = __import__('eos.db.migrations.upgrade%d'%(version+1), fromlist=True)
|
||||
upgrade = getattr(module, "upgrade", False)
|
||||
if upgrade:
|
||||
upgrade(saveddata_engine)
|
||||
for version in xrange(dbVersion, appVersion):
|
||||
func = migrations.updates[version + 1]
|
||||
if func:
|
||||
logger.info("Applying database update: %d", version + 1)
|
||||
func(saveddata_engine)
|
||||
|
||||
# when all is said and done, set version to current
|
||||
saveddata_engine.execute('PRAGMA user_version = %d'%config.dbversion)
|
||||
saveddata_engine.execute("PRAGMA user_version = {}".format(appVersion))
|
||||
|
||||
@@ -7,3 +7,24 @@ define an upgrade() function with the logic. Please note that there must be as
|
||||
many upgrade files as there are database versions (version 5 would include
|
||||
upgrade files 1-5)
|
||||
"""
|
||||
|
||||
import pkgutil
|
||||
import re
|
||||
|
||||
updates = {}
|
||||
appVersion = 0
|
||||
|
||||
prefix = __name__ + "."
|
||||
for importer, modname, ispkg in pkgutil.iter_modules(__path__, prefix):
|
||||
# loop through python files, extracting update number and function, and
|
||||
# adding it to a list
|
||||
modname_tail = modname.rsplit('.', 1)[-1]
|
||||
module = __import__(modname, fromlist=True)
|
||||
m = re.match("^upgrade(?P<index>\d+)$", modname_tail)
|
||||
if not m:
|
||||
continue
|
||||
index = int(m.group("index"))
|
||||
appVersion = max(appVersion, index)
|
||||
upgrade = getattr(module, "upgrade", False)
|
||||
if upgrade:
|
||||
updates[index] = upgrade
|
||||
|
||||
@@ -45,7 +45,7 @@ CONVERSIONS = {
|
||||
8746, # Quantum Co-Processor
|
||||
8745, # Photonic CPU Enhancer
|
||||
15425, # Naiyon's Modified Co-Processor (never existed but convert
|
||||
# anyway as some fits may include it)
|
||||
# anyway as some fits may include it)
|
||||
],
|
||||
8748: [ # Upgraded Co-Processor
|
||||
8747, # Nanomechanical CPU Enhancer I
|
||||
@@ -70,7 +70,7 @@ CONVERSIONS = {
|
||||
16543, # Micro 'Vigor' Core Augmentation
|
||||
],
|
||||
8089: [ # Compact Light Missile Launcher
|
||||
8093, # Prototype 'Arbalest' Light Missile Launcher
|
||||
8093, # Prototype 'Arbalest' Light Missile Launcher
|
||||
],
|
||||
8091: [ # Ample Light Missile Launcher
|
||||
7993, # Experimental TE-2100 Light Missile Launcher
|
||||
@@ -82,6 +82,7 @@ CONVERSIONS = {
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update fits schema to include target resists attribute
|
||||
try:
|
||||
@@ -92,6 +93,7 @@ def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
|
||||
17
eos/db/migrations/upgrade10.py
Normal file
17
eos/db/migrations/upgrade10.py
Normal file
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
Migration 10
|
||||
|
||||
- Adds active attribute to projected fits
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update projectedFits schema to include active attribute
|
||||
try:
|
||||
saveddata_engine.execute("SELECT active FROM projectedFits LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE projectedFits ADD COLUMN active BOOLEAN")
|
||||
saveddata_engine.execute("UPDATE projectedFits SET active = 1")
|
||||
saveddata_engine.execute("UPDATE projectedFits SET amount = 1")
|
||||
116
eos/db/migrations/upgrade11.py
Normal file
116
eos/db/migrations/upgrade11.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
Migration 11
|
||||
|
||||
- Converts modules based on December Release 2015 Tiericide
|
||||
Some modules have been unpublished (and unpublished module attributes are removed
|
||||
from database), which causes pyfa to crash. We therefore replace these
|
||||
modules with their new replacements
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
16467: ( # Medium Gremlin Compact Energy Neutralizer
|
||||
16471, # Medium Unstable Power Fluctuator I
|
||||
),
|
||||
22947: ( # 'Beatnik' Small Remote Armor Repairer
|
||||
23414, # 'Brotherhood' Small Remote Armor Repairer
|
||||
),
|
||||
8295: ( # Type-D Restrained Shield Flux Coil
|
||||
8293, # Beta Reactor Control: Shield Flux I
|
||||
),
|
||||
16499: ( # Heavy Knave Scoped Energy Nosferatu
|
||||
16501, # E500 Prototype Energy Vampire
|
||||
),
|
||||
16477: ( # Heavy Infectious Scoped Energy Neutralizer
|
||||
16473, # Heavy Rudimentary Energy Destabilizer I
|
||||
),
|
||||
16475: ( # Heavy Gremlin Compact Energy Neutralizer
|
||||
16479, # Heavy Unstable Power Fluctuator I
|
||||
),
|
||||
16447: ( # Medium Solace Scoped Remote Armor Repairer
|
||||
16445, # Medium 'Arup' Remote Armor Repairer
|
||||
),
|
||||
508: ( # 'Basic' Shield Flux Coil
|
||||
8325, # Alpha Reactor Shield Flux
|
||||
8329, # Marked Generator Refitting: Shield Flux
|
||||
8323, # Partial Power Plant Manager: Shield Flux
|
||||
8327, # Type-E Power Core Modification: Shield Flux
|
||||
),
|
||||
1419: ( # 'Basic' Shield Power Relay
|
||||
8341, # Alpha Reactor Shield Power Relay
|
||||
8345, # Marked Generator Refitting: Shield Power Relay
|
||||
8339, # Partial Power Plant Manager: Shield Power Relay
|
||||
8343, # Type-E Power Core Modification: Shield Power Relay
|
||||
),
|
||||
16439: ( # Small Solace Scoped Remote Armor Repairer
|
||||
16437, # Small 'Arup' Remote Armor Repairer
|
||||
),
|
||||
16505: ( # Medium Ghoul Compact Energy Nosferatu
|
||||
16511, # Medium Diminishing Power System Drain I
|
||||
),
|
||||
8297: ( # Mark I Compact Shield Flux Coil
|
||||
8291, # Local Power Plant Manager: Reaction Shield Flux I
|
||||
),
|
||||
16455: ( # Large Solace Scoped Remote Armor Repairer
|
||||
16453, # Large 'Arup' Remote Armor Repairer
|
||||
),
|
||||
6485: ( # M51 Benefactor Compact Shield Recharger
|
||||
6491, # Passive Barrier Compensator I
|
||||
6489, # 'Benefactor' Ward Reconstructor
|
||||
6487, # Supplemental Screen Generator I
|
||||
),
|
||||
5137: ( # Small Knave Scoped Energy Nosferatu
|
||||
5135, # E5 Prototype Energy Vampire
|
||||
),
|
||||
8579: ( # Medium Murky Compact Remote Shield Booster
|
||||
8581, # Medium 'Atonement' Remote Shield Booster
|
||||
),
|
||||
8531: ( # Small Murky Compact Remote Shield Booster
|
||||
8533, # Small 'Atonement' Remote Shield Booster
|
||||
),
|
||||
16497: ( # Heavy Ghoul Compact Energy Nosferatu
|
||||
16503, # Heavy Diminishing Power System Drain I
|
||||
),
|
||||
4477: ( # Small Gremlin Compact Energy Neutralizer
|
||||
4475, # Small Unstable Power Fluctuator I
|
||||
),
|
||||
8337: ( # Mark I Compact Shield Power Relay
|
||||
8331, # Local Power Plant Manager: Reaction Shield Power Relay I
|
||||
),
|
||||
23416: ( # 'Peace' Large Remote Armor Repairer
|
||||
22951, # 'Pacifier' Large Remote Armor Repairer
|
||||
),
|
||||
5141: ( # Small Ghoul Compact Energy Nosferatu
|
||||
5139, # Small Diminishing Power System Drain I
|
||||
),
|
||||
4471: ( # Small Infectious Scoped Energy Neutralizer
|
||||
4473, # Small Rudimentary Energy Destabilizer I
|
||||
),
|
||||
16469: ( # Medium Infectious Scoped Energy Neutralizer
|
||||
16465, # Medium Rudimentary Energy Destabilizer I
|
||||
),
|
||||
8335: ( # Type-D Restrained Shield Power Relay
|
||||
8333, # Beta Reactor Control: Shield Power Relay I
|
||||
),
|
||||
405: ( # 'Micro' Remote Shield Booster
|
||||
8631, # Micro Asymmetric Remote Shield Booster
|
||||
8627, # Micro Murky Remote Shield Booster
|
||||
8629, # Micro 'Atonement' Remote Shield Booster
|
||||
8633, # Micro S95a Remote Shield Booster
|
||||
),
|
||||
8635: ( # Large Murky Compact Remote Shield Booster
|
||||
8637, # Large 'Atonement' Remote Shield Booster
|
||||
),
|
||||
16507: ( # Medium Knave Scoped Energy Nosferatu
|
||||
16509, # E50 Prototype Energy Vampire
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
340
eos/db/migrations/upgrade12.py
Normal file
340
eos/db/migrations/upgrade12.py
Normal file
@@ -0,0 +1,340 @@
|
||||
"""
|
||||
Migration 12
|
||||
|
||||
- Converts modules based on March 2016 Module Tiericide
|
||||
Some modules have been unpublished (and unpublished module attributes are removed
|
||||
from database), which causes pyfa to crash. We therefore replace these
|
||||
modules with their new replacements
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
16457: ( # Crosslink Compact Ballistic Control System
|
||||
16459, # Muon Coil Bolt Array I
|
||||
16461, # Multiphasic Bolt Array I
|
||||
16463, # 'Pandemonium' Ballistic Enhancement
|
||||
),
|
||||
5281: ( # Coadjunct Scoped Remote Sensor Booster
|
||||
7218, # Piercing ECCM Emitter I
|
||||
),
|
||||
5365: ( # Cetus Scoped Burst Jammer
|
||||
5359, # 1Z-3 Subversive ECM Eruption
|
||||
),
|
||||
1973: ( # Sensor Booster I
|
||||
1947, # ECCM - Radar I
|
||||
2002, # ECCM - Ladar I
|
||||
2003, # ECCM - Magnetometric I
|
||||
2004, # ECCM - Gravimetric I
|
||||
2005, # ECCM - Omni I
|
||||
),
|
||||
1951: ( # 'Basic' Tracking Enhancer
|
||||
6322, # Beta-Nought Tracking Mode
|
||||
6323, # Azimuth Descalloping Tracking Enhancer
|
||||
6324, # F-AQ Delay-Line Scan Tracking Subroutines
|
||||
6321, # Beam Parallax Tracking Program
|
||||
),
|
||||
521: ( # 'Basic' Damage Control
|
||||
5829, # GLFF Containment Field
|
||||
5831, # Interior Force Field Array
|
||||
5835, # F84 Local Damage System
|
||||
5833, # Systematic Damage Control
|
||||
),
|
||||
22925: ( # 'Bootleg' Remote Sensor Booster
|
||||
22939, # 'Boss' Remote Sensor Booster
|
||||
22941, # 'Entrepreneur' Remote Sensor Booster
|
||||
),
|
||||
5443: ( # Faint Epsilon Scoped Warp Scrambler
|
||||
5441, # Fleeting Progressive Warp Scrambler I
|
||||
),
|
||||
1963: ( # Remote Sensor Booster I
|
||||
1959, # ECCM Projector I
|
||||
),
|
||||
6325: ( # Fourier Compact Tracking Enhancer
|
||||
6326, # Sigma-Nought Tracking Mode I
|
||||
6327, # Auto-Gain Control Tracking Enhancer I
|
||||
6328, # F-aQ Phase Code Tracking Subroutines
|
||||
),
|
||||
21486: ( # 'Kindred' Gyrostabilizer
|
||||
21488, # Monophonic Stabilization Actuator I
|
||||
),
|
||||
19927: ( # Hypnos Scoped Magnetometric ECM
|
||||
9518, # Initiated Ion Field ECM I
|
||||
),
|
||||
10188: ( # 'Basic' Magnetic Field Stabilizer
|
||||
11111, # Insulated Stabilizer Array
|
||||
11109, # Linear Flux Stabilizer
|
||||
11115, # Gauss Field Balancer
|
||||
11113, # Magnetic Vortex Stabilizer
|
||||
),
|
||||
22919: ( # 'Monopoly' Magnetic Field Stabilizer
|
||||
22917, # 'Capitalist' Magnetic Field Stabilizer I
|
||||
),
|
||||
5839: ( # IFFA Compact Damage Control
|
||||
5841, # Emergency Damage Control I
|
||||
5843, # F85 Peripheral Damage System I
|
||||
5837, # Pseudoelectron Containment Field I
|
||||
),
|
||||
522: ( # 'Micro' Cap Battery
|
||||
4747, # Micro Ld-Acid Capacitor Battery I
|
||||
4751, # Micro Ohm Capacitor Reserve I
|
||||
4745, # Micro F-4a Ld-Sulfate Capacitor Charge Unit
|
||||
4749, # Micro Peroxide Capacitor Power Cell
|
||||
3480, # Micro Capacitor Battery II
|
||||
),
|
||||
518: ( # 'Basic' Gyrostabilizer
|
||||
5915, # Lateral Gyrostabilizer
|
||||
5919, # F-M2 Weapon Inertial Suspensor
|
||||
5913, # Hydraulic Stabilization Actuator
|
||||
5917, # Stabilized Weapon Mounts
|
||||
),
|
||||
19931: ( # Compulsive Scoped Multispectral ECM
|
||||
19933, # 'Hypnos' Multispectral ECM I
|
||||
),
|
||||
5403: ( # Faint Scoped Warp Disruptor
|
||||
5401, # Fleeting Warp Disruptor I
|
||||
),
|
||||
23902: ( # 'Trebuchet' Heat Sink I
|
||||
23900, # 'Mangonel' Heat Sink I
|
||||
),
|
||||
1893: ( # 'Basic' Heat Sink
|
||||
5845, # Heat Exhaust System
|
||||
5856, # C3S Convection Thermal Radiator
|
||||
5855, # 'Boreas' Coolant System
|
||||
5854, # Stamped Heat Sink
|
||||
),
|
||||
6160: ( # F-90 Compact Sensor Booster
|
||||
20214, # Extra Radar ECCM Scanning Array I
|
||||
20220, # Extra Ladar ECCM Scanning Array I
|
||||
20226, # Extra Gravimetric ECCM Scanning Array I
|
||||
20232, # Extra Magnetometric ECCM Scanning Array I
|
||||
7948, # Gravimetric Positional ECCM Sensor System I
|
||||
7964, # Radar Positional ECCM Sensor System I
|
||||
7965, # Omni Positional ECCM Sensor System I
|
||||
7966, # Ladar Positional ECCM Sensor System I
|
||||
7970, # Magnetometric Positional ECCM Sensor System I
|
||||
20218, # Conjunctive Radar ECCM Scanning Array I
|
||||
20224, # Conjunctive Ladar ECCM Scanning Array I
|
||||
20230, # Conjunctive Gravimetric ECCM Scanning Array I
|
||||
20236, # Conjunctive Magnetometric ECCM Scanning Array I
|
||||
6157, # Supplemental Scanning CPU I
|
||||
),
|
||||
23418: ( # 'Radical' Damage Control
|
||||
22893, # 'Gonzo' Damage Control I
|
||||
),
|
||||
19952: ( # Umbra Scoped Radar ECM
|
||||
9520, # 'Penumbra' White Noise ECM
|
||||
),
|
||||
1952: ( # Sensor Booster II
|
||||
2258, # ECCM - Omni II
|
||||
2259, # ECCM - Gravimetric II
|
||||
2260, # ECCM - Ladar II
|
||||
2261, # ECCM - Magnetometric II
|
||||
2262, # ECCM - Radar II
|
||||
),
|
||||
5282: ( # Linked Enduring Sensor Booster
|
||||
7219, # Scattering ECCM Projector I
|
||||
),
|
||||
1986: ( # Signal Amplifier I
|
||||
2579, # Gravimetric Backup Array I
|
||||
2583, # Ladar Backup Array I
|
||||
2587, # Magnetometric Backup Array I
|
||||
2591, # Multi Sensor Backup Array I
|
||||
4013, # RADAR Backup Array I
|
||||
),
|
||||
4871: ( # Large Compact Pb-Acid Cap Battery
|
||||
4875, # Large Ohm Capacitor Reserve I
|
||||
4869, # Large F-4a Ld-Sulfate Capacitor Charge Unit
|
||||
4873, # Large Peroxide Capacitor Power Cell
|
||||
),
|
||||
1964: ( # Remote Sensor Booster II
|
||||
1960, # ECCM Projector II
|
||||
),
|
||||
5933: ( # Counterbalanced Compact Gyrostabilizer
|
||||
5931, # Cross-Lateral Gyrostabilizer I
|
||||
5935, # F-M3 Munition Inertial Suspensor
|
||||
5929, # Pneumatic Stabilization Actuator I
|
||||
),
|
||||
4025: ( # X5 Enduring Stasis Webifier
|
||||
4029, # 'Langour' Drive Disruptor I
|
||||
),
|
||||
4027: ( # Fleeting Compact Stasis Webifier
|
||||
4031, # Patterned Stasis Web I
|
||||
),
|
||||
22937: ( # 'Enterprise' Remote Tracking Computer
|
||||
22935, # 'Tycoon' Remote Tracking Computer
|
||||
),
|
||||
22929: ( # 'Marketeer' Tracking Computer
|
||||
22927, # 'Economist' Tracking Computer I
|
||||
),
|
||||
1987: ( # Signal Amplifier II
|
||||
2580, # Gravimetric Backup Array II
|
||||
2584, # Ladar Backup Array II
|
||||
2588, # Magnetometric Backup Array II
|
||||
2592, # Multi Sensor Backup Array II
|
||||
4014, # RADAR Backup Array II
|
||||
),
|
||||
19939: ( # Enfeebling Scoped Ladar ECM
|
||||
9522, # Faint Phase Inversion ECM I
|
||||
),
|
||||
5340: ( # P-S Compact Remote Tracking Computer
|
||||
5341, # 'Prayer' Remote Tracking Computer
|
||||
),
|
||||
19814: ( # Phased Scoped Target Painter
|
||||
19808, # Partial Weapon Navigation
|
||||
),
|
||||
1949: ( # 'Basic' Signal Amplifier
|
||||
1946, # Basic RADAR Backup Array
|
||||
1982, # Basic Ladar Backup Array
|
||||
1983, # Basic Gravimetric Backup Array
|
||||
1984, # Basic Magnetometric Backup Array
|
||||
1985, # Basic Multi Sensor Backup Array
|
||||
6193, # Emergency Magnetometric Scanners
|
||||
6194, # Emergency Multi-Frequency Scanners
|
||||
6202, # Emergency RADAR Scanners
|
||||
6216, # Emergency Ladar Scanners
|
||||
6217, # Emergency Gravimetric Scanners
|
||||
6225, # Sealed RADAR Backup Cluster
|
||||
6238, # Sealed Magnetometric Backup Cluster
|
||||
6239, # Sealed Multi-Frequency Backup Cluster
|
||||
6241, # Sealed Ladar Backup Cluster
|
||||
6242, # Sealed Gravimetric Backup Cluster
|
||||
6257, # Surplus RADAR Reserve Array
|
||||
6258, # F-42 Reiterative RADAR Backup Sensors
|
||||
6283, # Surplus Magnetometric Reserve Array
|
||||
6284, # F-42 Reiterative Magnetometric Backup Sensors
|
||||
6285, # Surplus Multi-Frequency Reserve Array
|
||||
6286, # F-42 Reiterative Multi-Frequency Backup Sensors
|
||||
6289, # Surplus Ladar Reserve Array
|
||||
6290, # F-42 Reiterative Ladar Backup Sensors
|
||||
6291, # Surplus Gravimetric Reserve Array
|
||||
6292, # F-42 Reiterative Gravimetric Backup Sensors
|
||||
6309, # Amplitude Signal Enhancer
|
||||
6310, # 'Acolyth' Signal Booster
|
||||
6311, # Type-E Discriminative Signal Augmentation
|
||||
6312, # F-90 Positional Signal Amplifier
|
||||
),
|
||||
21527: ( # 'Firewall' Signal Amplifier
|
||||
21521, # Gravimetric Firewall
|
||||
21523, # Ladar Firewall
|
||||
21525, # Magnetometric Firewall
|
||||
21527, # Multi Sensor Firewall
|
||||
21529, # RADAR Firewall
|
||||
),
|
||||
23416: ( # 'Peace' Large Remote Armor Repairer
|
||||
None, # 'Pacifier' Large Remote Armor Repairer
|
||||
),
|
||||
6176: ( # F-12 Enduring Tracking Computer
|
||||
6174, # Monopulse Tracking Mechanism I
|
||||
),
|
||||
6159: ( # Alumel-Wired Enduring Sensor Booster
|
||||
7917, # Alumel Radar ECCM Sensor Array I
|
||||
7918, # Alumel Ladar ECCM Sensor Array I
|
||||
7922, # Alumel Gravimetric ECCM Sensor Array I
|
||||
7926, # Alumel Omni ECCM Sensor Array I
|
||||
7937, # Alumel Magnetometric ECCM Sensor Array I
|
||||
7867, # Supplemental Ladar ECCM Scanning Array I
|
||||
7869, # Supplemental Gravimetric ECCM Scanning Array I
|
||||
7870, # Supplemental Omni ECCM Scanning Array I
|
||||
7887, # Supplemental Radar ECCM Scanning Array I
|
||||
7889, # Supplemental Magnetometric ECCM Scanning Array I
|
||||
20216, # Incremental Radar ECCM Scanning Array I
|
||||
20222, # Incremental Ladar ECCM Scanning Array I
|
||||
20228, # Incremental Gravimetric ECCM Scanning Array I
|
||||
20234, # Incremental Magnetometric ECCM Scanning Array I
|
||||
7892, # Prototype ECCM Radar Sensor Cluster
|
||||
7893, # Prototype ECCM Ladar Sensor Cluster
|
||||
7895, # Prototype ECCM Gravimetric Sensor Cluster
|
||||
7896, # Prototype ECCM Omni Sensor Cluster
|
||||
7914, # Prototype ECCM Magnetometric Sensor Cluster
|
||||
6158, # Prototype Sensor Booster
|
||||
),
|
||||
5849: ( # Extruded Compact Heat Sink
|
||||
5846, # Thermal Exhaust System I
|
||||
5858, # C4S Coiled Circuit Thermal Radiator
|
||||
5857, # 'Skadi' Coolant System I
|
||||
),
|
||||
22895: ( # 'Shady' Sensor Booster
|
||||
22897, # 'Forger' ECCM - Magnetometric I
|
||||
),
|
||||
11105: ( # Vortex Compact Magnetic Field Stabilizer
|
||||
11103, # Insulated Stabilizer Array I
|
||||
11101, # Linear Flux Stabilizer I
|
||||
11107, # Gauss Field Balancer I
|
||||
),
|
||||
22945: ( # 'Executive' Remote Sensor Dampener
|
||||
22943, # 'Broker' Remote Sensor Dampener I
|
||||
),
|
||||
6173: ( # Optical Compact Tracking Computer
|
||||
6175, # 'Orion' Tracking CPU I
|
||||
),
|
||||
5279: ( # F-23 Compact Remote Sensor Booster
|
||||
7217, # Spot Pulsing ECCM I
|
||||
7220, # Phased Muon ECCM Caster I
|
||||
5280, # Connected Remote Sensor Booster
|
||||
),
|
||||
4787: ( # Small Compact Pb-Acid Cap Battery
|
||||
4791, # Small Ohm Capacitor Reserve I
|
||||
4785, # Small F-4a Ld-Sulfate Capacitor Charge Unit
|
||||
4789, # Small Peroxide Capacitor Power Cell
|
||||
),
|
||||
19946: ( # BZ-5 Scoped Gravimetric ECM
|
||||
9519, # FZ-3 Subversive Spatial Destabilizer ECM
|
||||
),
|
||||
6073: ( # Medium Compact Pb-Acid Cap Battery
|
||||
6097, # Medium Ohm Capacitor Reserve I
|
||||
6111, # Medium F-4a Ld-Sulfate Capacitor Charge Unit
|
||||
6083, # Medium Peroxide Capacitor Power Cell
|
||||
),
|
||||
21484: ( # 'Full Duplex' Ballistic Control System
|
||||
21482, # Ballistic 'Purge' Targeting System I
|
||||
),
|
||||
6296: ( # F-89 Compact Signal Amplifier
|
||||
6218, # Protected Gravimetric Backup Cluster I
|
||||
6222, # Protected Ladar Backup Cluster I
|
||||
6226, # Protected Magnetometric Backup Cluster I
|
||||
6230, # Protected Multi-Frequency Backup Cluster I
|
||||
6234, # Protected RADAR Backup Cluster I
|
||||
6195, # Reserve Gravimetric Scanners
|
||||
6199, # Reserve Ladar Scanners
|
||||
6203, # Reserve Magnetometric Scanners
|
||||
6207, # Reserve Multi-Frequency Scanners
|
||||
6212, # Reserve RADAR Scanners
|
||||
20238, # Secure Gravimetric Backup Cluster I
|
||||
20244, # Secure Ladar Backup Cluster I
|
||||
20250, # Secure Magnetometric Backup Cluster I
|
||||
20260, # Secure Radar Backup Cluster I
|
||||
6244, # F-43 Repetitive Gravimetric Backup Sensors
|
||||
6252, # F-43 Repetitive Ladar Backup Sensors
|
||||
6260, # F-43 Repetitive Magnetometric Backup Sensors
|
||||
6268, # F-43 Repetitive Multi-Frequency Backup Sensors
|
||||
6276, # F-43 Repetitive RADAR Backup Sensors
|
||||
20240, # Shielded Gravimetric Backup Cluster I
|
||||
20246, # Shielded Ladar Backup Cluster I
|
||||
20252, # Shielded Magnetometric Backup Cluster I
|
||||
20262, # Shielded Radar Backup Cluster I
|
||||
6243, # Surrogate Gravimetric Reserve Array I
|
||||
6251, # Surrogate Ladar Reserve Array I
|
||||
6259, # Surrogate Magnetometric Reserve Array I
|
||||
6267, # Surrogate Multi-Frequency Reserve Array I
|
||||
6275, # Surrogate RADAR Reserve Array I
|
||||
20242, # Warded Gravimetric Backup Cluster I
|
||||
20248, # Warded Ladar Backup Cluster I
|
||||
20254, # Warded Magnetometric Backup Cluster I
|
||||
20264, # Warded Radar Backup Cluster I
|
||||
6294, # 'Mendicant' Signal Booster I
|
||||
6293, # Wavelength Signal Enhancer I
|
||||
6295, # Type-D Attenuation Signal Augmentation
|
||||
),
|
||||
5302: ( # Phased Muon Scoped Sensor Dampener
|
||||
5300, # Indirect Scanning Dampening Unit I
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
16
eos/db/migrations/upgrade13.py
Normal file
16
eos/db/migrations/upgrade13.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
Migration 13
|
||||
|
||||
- Alters fits table to introduce implant location attribute
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update fits schema to include implant location attribute
|
||||
try:
|
||||
saveddata_engine.execute("SELECT implantLocation FROM fits LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN implantLocation INTEGER;")
|
||||
saveddata_engine.execute("UPDATE fits SET implantLocation = 0")
|
||||
21
eos/db/migrations/upgrade14.py
Normal file
21
eos/db/migrations/upgrade14.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Migration 14
|
||||
|
||||
- This should take care of issue #586.
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
if saveddata_engine.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='fighters'").scalar() == 'fighters':
|
||||
# Fighters table exists
|
||||
try:
|
||||
saveddata_engine.execute("SELECT active FROM fighters LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
# if we don't have the active column, we are on an old pre-release version. Drop the tables and move on
|
||||
# (they will be recreated)
|
||||
|
||||
saveddata_engine.execute("DROP TABLE fighters")
|
||||
saveddata_engine.execute("DROP TABLE fightersAbilities")
|
||||
21
eos/db/migrations/upgrade15.py
Normal file
21
eos/db/migrations/upgrade15.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Migration 15
|
||||
|
||||
- Delete projected modules on citadels
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
sql = """
|
||||
DELETE FROM modules WHERE ID IN
|
||||
(
|
||||
SELECT m.ID FROM modules AS m
|
||||
JOIN fits AS f ON m.fitID = f.ID
|
||||
WHERE f.shipID IN ("35832", "35833", "35834", "40340")
|
||||
AND m.projected = 1
|
||||
)
|
||||
"""
|
||||
|
||||
saveddata_engine.execute(sql)
|
||||
15
eos/db/migrations/upgrade16.py
Normal file
15
eos/db/migrations/upgrade16.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Migration 16
|
||||
|
||||
- Alters fits table to introduce notes attribute
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update fits schema to include notes attribute
|
||||
try:
|
||||
saveddata_engine.execute("SELECT notes FROM fits LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE fits ADD COLUMN notes VARCHAR;")
|
||||
40
eos/db/migrations/upgrade17.py
Normal file
40
eos/db/migrations/upgrade17.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
Migration 17
|
||||
|
||||
- Moves all fleet boosters to the new schema
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
from eos.db import saveddata_session
|
||||
from eos.db.saveddata.fit import commandFits_table
|
||||
|
||||
sql = """
|
||||
SELECT sm.memberID as boostedFit, s.leaderID AS squadBoost, w.leaderID AS wingBoost, g.leaderID AS gangBoost
|
||||
FROM squadmembers sm
|
||||
JOIN squads s ON s.ID = sm.squadID
|
||||
JOIN wings w on w.ID = s.wingID
|
||||
JOIN gangs g on g.ID = w.gangID
|
||||
"""
|
||||
|
||||
results = saveddata_session.execute(sql)
|
||||
|
||||
inserts = []
|
||||
|
||||
for row in results:
|
||||
boosted = row["boostedFit"]
|
||||
types = ("squad", "wing", "gang")
|
||||
for x in types:
|
||||
value = row["{}Boost".format(x)]
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
inserts.append({"boosterID": value, "boostedID": boosted, "active": 1})
|
||||
try:
|
||||
saveddata_session.execute(commandFits_table.insert(),
|
||||
{"boosterID": value, "boostedID": boosted, "active": 1})
|
||||
except Exception:
|
||||
pass
|
||||
saveddata_session.commit()
|
||||
68
eos/db/migrations/upgrade18.py
Normal file
68
eos/db/migrations/upgrade18.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
Migration 8
|
||||
|
||||
- Converts modules from old Warfare Links to Command Modules
|
||||
"""
|
||||
|
||||
CONVERSIONS = {
|
||||
42526: ( # Armor Command Burst I
|
||||
20069, # Armored Warfare Link - Damage Control I
|
||||
20409, # Armored Warfare Link - Passive Defense I
|
||||
22227, # Armored Warfare Link - Rapid Repair I
|
||||
),
|
||||
43552: ( # Armor Command Burst II
|
||||
4264, # Armored Warfare Link - Damage Control II
|
||||
4266, # Armored Warfare Link - Passive Defense II
|
||||
4266, # Armored Warfare Link - Rapid Repair II
|
||||
),
|
||||
42527: ( # Information Command Burst I
|
||||
11052, # Information Warfare Link - Sensor Integrity I
|
||||
20405, # Information Warfare Link - Recon Operation I
|
||||
20406, # Information Warfare Link - Electronic Superiority I
|
||||
),
|
||||
43554: ( # Information Command Burst II
|
||||
4268, # Information Warfare Link - Electronic Superiority II
|
||||
4270, # Information Warfare Link - Recon Operation II
|
||||
4272, # Information Warfare Link - Sensor Integrity II
|
||||
),
|
||||
42529: ( # Shield Command Burst I
|
||||
20124, # Siege Warfare Link - Active Shielding I
|
||||
20514, # Siege Warfare Link - Shield Harmonizing I
|
||||
22228, # Siege Warfare Link - Shield Efficiency I
|
||||
),
|
||||
43555: ( # Shield Command Burst II
|
||||
4280, # Siege Warfare Link - Active Shielding II
|
||||
4282, # Siege Warfare Link - Shield Efficiency II
|
||||
4284 # Siege Warfare Link - Shield Harmonizing II
|
||||
),
|
||||
42530: ( # Skirmish Command Burst I
|
||||
11017, # Skirmish Warfare Link - Interdiction Maneuvers I
|
||||
20070, # Skirmish Warfare Link - Evasive Maneuvers I
|
||||
20408, # Skirmish Warfare Link - Rapid Deployment I
|
||||
),
|
||||
43556: ( # Skirmish Command Burst II
|
||||
4286, # Skirmish Warfare Link - Evasive Maneuvers II
|
||||
4288, # Skirmish Warfare Link - Interdiction Maneuvers II
|
||||
4290 # Skirmish Warfare Link - Rapid Deployment II
|
||||
),
|
||||
42528: ( # Mining Foreman Burst I
|
||||
22553, # Mining Foreman Link - Harvester Capacitor Efficiency I
|
||||
22555, # Mining Foreman Link - Mining Laser Field Enhancement I
|
||||
22557, # Mining Foreman Link - Laser Optimization I
|
||||
),
|
||||
43551: ( # Mining Foreman Burst II
|
||||
4274, # Mining Foreman Link - Harvester Capacitor Efficiency II
|
||||
4276, # Mining Foreman Link - Laser Optimization II
|
||||
4278 # Mining Foreman Link - Mining Laser Field Enhancement II
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
20
eos/db/migrations/upgrade19.py
Normal file
20
eos/db/migrations/upgrade19.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
Migration 19
|
||||
|
||||
- Deletes broken references to fits from the commandFits table (see GH issue #844)
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
from eos.db import saveddata_session
|
||||
|
||||
sql = """
|
||||
DELETE FROM commandFits
|
||||
WHERE boosterID NOT IN (select ID from fits)
|
||||
OR boostedID NOT IN (select ID from fits)
|
||||
"""
|
||||
|
||||
saveddata_session.execute(sql)
|
||||
saveddata_session.commit()
|
||||
@@ -6,6 +6,7 @@ Migration 2
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update characters schema to include default chars
|
||||
try:
|
||||
|
||||
15
eos/db/migrations/upgrade20.py
Normal file
15
eos/db/migrations/upgrade20.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Migration 20
|
||||
|
||||
- Adds support for alpha clones to the characters table
|
||||
"""
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Update characters schema to include alphaCloneID
|
||||
try:
|
||||
saveddata_engine.execute("SELECT alphaCloneID FROM characters LIMIT 1")
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
saveddata_engine.execute("ALTER TABLE characters ADD COLUMN alphaCloneID INTEGER;")
|
||||
@@ -6,6 +6,7 @@ Migration 3
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
try:
|
||||
saveddata_engine.execute("SELECT modeID FROM fits LIMIT 1")
|
||||
|
||||
@@ -10,7 +10,6 @@ Migration 4
|
||||
and output of itemDiff.py
|
||||
"""
|
||||
|
||||
|
||||
CONVERSIONS = {
|
||||
506: ( # 'Basic' Capacitor Power Relay
|
||||
8205, # Alpha Reactor Control: Capacitor Power Relay
|
||||
@@ -131,11 +130,12 @@ CONVERSIONS = {
|
||||
),
|
||||
}
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
|
||||
@@ -4,5 +4,6 @@ Migration 5
|
||||
Simply deletes damage profiles with a blank name. See GH issue #256
|
||||
"""
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
saveddata_engine.execute('DELETE FROM damagePatterns WHERE name LIKE ?', ("",))
|
||||
|
||||
@@ -4,6 +4,8 @@ Migration 6
|
||||
Overwrites damage profile 0 to reset bad uniform values (bad values set with bug)
|
||||
"""
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
saveddata_engine.execute('DELETE FROM damagePatterns WHERE name LIKE ? OR ID LIKE ?', ("Uniform", "1"))
|
||||
saveddata_engine.execute('INSERT INTO damagePatterns VALUES (?, ?, ?, ?, ?, ?, ?)', (1, "Uniform", 25, 25, 25, 25, None))
|
||||
saveddata_engine.execute('INSERT INTO damagePatterns VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
(1, "Uniform", 25, 25, 25, 25, None))
|
||||
|
||||
@@ -8,17 +8,16 @@ Migration 7
|
||||
Pyfa.
|
||||
"""
|
||||
|
||||
|
||||
CONVERSIONS = {
|
||||
640: ( # Scorpion
|
||||
4005, # Scorpion Ishukone Watch
|
||||
)
|
||||
}
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert ships
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "fits" SET "shipID" = ? WHERE "shipID" = ?', (replacement_item, retired_item))
|
||||
|
||||
saveddata_engine.execute('UPDATE "fits" SET "shipID" = ? WHERE "shipID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
"""
|
||||
Migration 4
|
||||
Migration 8
|
||||
|
||||
- Converts modules based on Proteus Module Tiericide
|
||||
- Converts modules based on Carnyx Module Tiericide
|
||||
Some modules have been unpublished (and unpublished module attributes are removed
|
||||
from database), which causes pyfa to crash. We therefore replace these
|
||||
modules with their new replacements
|
||||
|
||||
Based on http://community.eveonline.com/news/patch-notes/patch-notes-for-proteus/
|
||||
and output of itemDiff.py
|
||||
"""
|
||||
|
||||
|
||||
CONVERSIONS = {
|
||||
8529: ( # Large F-S9 Regolith Compact Shield Extender
|
||||
8409, # Large Subordinate Screen Stabilizer I
|
||||
@@ -74,15 +70,16 @@ CONVERSIONS = {
|
||||
11321, # 800mm Reinforced Nanofiber Plates I
|
||||
),
|
||||
11317: ( # 800mm Rolled Tungsten Compact Plates
|
||||
11315, # 800mm Reinforced Titanium Plates I
|
||||
11315, # 800mm Reinforced Titanium Plates I
|
||||
),
|
||||
}
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
# Convert modules
|
||||
for replacement_item, list in CONVERSIONS.iteritems():
|
||||
for retired_item in list:
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?', (replacement_item, retired_item))
|
||||
|
||||
saveddata_engine.execute('UPDATE "modules" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
saveddata_engine.execute('UPDATE "cargo" SET "itemID" = ? WHERE "itemID" = ?',
|
||||
(replacement_item, retired_item))
|
||||
|
||||
25
eos/db/migrations/upgrade9.py
Normal file
25
eos/db/migrations/upgrade9.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Migration 9
|
||||
|
||||
Effectively drops UNIQUE constraint from boosters table. SQLite does not support
|
||||
this, so we have to copy the table to the updated schema and then rename it
|
||||
"""
|
||||
|
||||
tmpTable = """
|
||||
CREATE TABLE boostersTemp (
|
||||
'ID' INTEGER NOT NULL,
|
||||
'itemID' INTEGER,
|
||||
'fitID' INTEGER NOT NULL,
|
||||
'active' BOOLEAN,
|
||||
PRIMARY KEY(ID),
|
||||
FOREIGN KEY('fitID') REFERENCES fits ('ID')
|
||||
)
|
||||
"""
|
||||
|
||||
|
||||
def upgrade(saveddata_engine):
|
||||
saveddata_engine.execute(tmpTable)
|
||||
saveddata_engine.execute(
|
||||
"INSERT INTO boostersTemp (ID, itemID, fitID, active) SELECT ID, itemID, fitID, active FROM boosters")
|
||||
saveddata_engine.execute("DROP TABLE boosters")
|
||||
saveddata_engine.execute("ALTER TABLE boostersTemp RENAME TO boosters")
|
||||
@@ -1,3 +1,18 @@
|
||||
__all__ = ["character", "fit", "module", "user", "skill", "price",
|
||||
"booster", "drone", "implant", "fleet", "damagePattern",
|
||||
"miscData", "targetResists"]
|
||||
__all__ = [
|
||||
"character",
|
||||
"fit",
|
||||
"module",
|
||||
"user",
|
||||
"skill",
|
||||
"price",
|
||||
"booster",
|
||||
"drone",
|
||||
"implant",
|
||||
"damagePattern",
|
||||
"miscData",
|
||||
"targetResists",
|
||||
"override",
|
||||
"crest",
|
||||
"implantSet",
|
||||
"loadDefaultDatabaseValues"
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,25 +15,27 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, ForeignKey, Integer, UniqueConstraint, Boolean
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
from sqlalchemy import Table, Column, ForeignKey, Integer, Boolean
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Booster
|
||||
|
||||
boosters_table = Table("boosters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("itemID", Integer),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False),
|
||||
Column("active", Boolean),
|
||||
UniqueConstraint("itemID", "fitID"))
|
||||
)
|
||||
|
||||
# Legacy booster side effect code, should disable but a mapper relies on it.
|
||||
activeSideEffects_table = Table("boostersActiveSideEffects", saveddata_meta,
|
||||
Column("boosterID", ForeignKey("boosters.ID"), primary_key = True),
|
||||
Column("effectID", Integer, primary_key = True))
|
||||
Column("boosterID", ForeignKey("boosters.ID"), primary_key=True),
|
||||
Column("effectID", Integer, primary_key=True))
|
||||
|
||||
|
||||
class ActiveSideEffectsDummy(object):
|
||||
def __init__(self, effectID):
|
||||
@@ -42,6 +44,6 @@ class ActiveSideEffectsDummy(object):
|
||||
|
||||
mapper(ActiveSideEffectsDummy, activeSideEffects_table)
|
||||
mapper(Booster, boosters_table,
|
||||
properties = {"_Booster__activeSideEffectDummies" : relation(ActiveSideEffectsDummy)})
|
||||
properties={"_Booster__activeSideEffectDummies": relation(ActiveSideEffectsDummy)})
|
||||
|
||||
Booster._Booster__activeSideEffectIDs = association_proxy("_Booster__activeSideEffectDummies", "effectID")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,18 +15,18 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Cargo
|
||||
|
||||
cargo_table = Table("cargo", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
|
||||
Column("itemID", Integer, nullable = False),
|
||||
Column("amount", Integer, nullable = False))
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=False),
|
||||
Column("amount", Integer, nullable=False))
|
||||
|
||||
mapper(Cargo, cargo_table)
|
||||
mapper(Cargo, cargo_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,30 +15,46 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import charImplants_table
|
||||
from eos.types import Character, User, Skill, Implant
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
from eos.types import Character, User, Skill, Implant
|
||||
|
||||
characters_table = Table("characters", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("name", String, nullable = False),
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("name", String, nullable=False),
|
||||
Column("apiID", Integer),
|
||||
Column("apiKey", String),
|
||||
Column("defaultChar", Integer),
|
||||
Column("chars", String, nullable = True),
|
||||
Column("chars", String, nullable=True),
|
||||
Column("defaultLevel", Integer, nullable=True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable = True))
|
||||
Column("alphaCloneID", Integer, nullable=True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable=True))
|
||||
|
||||
mapper(Character, characters_table,
|
||||
properties = {"_Character__owner" : relation(User, backref = "characters"),
|
||||
"_Character__skills" : relation(Skill, backref="character", cascade = "all,delete-orphan"),
|
||||
"_Character__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all,delete-orphan', single_parent=True,
|
||||
primaryjoin = charImplants_table.c.charID == characters_table.c.ID,
|
||||
secondaryjoin = charImplants_table.c.implantID == Implant.ID,
|
||||
secondary = charImplants_table),})
|
||||
properties={
|
||||
"_Character__alphaCloneID": characters_table.c.alphaCloneID,
|
||||
"savedName": characters_table.c.name,
|
||||
"_Character__owner": relation(
|
||||
User,
|
||||
backref="characters"),
|
||||
"_Character__skills": relation(
|
||||
Skill,
|
||||
backref="character",
|
||||
cascade="all,delete-orphan"),
|
||||
"_Character__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
cascade='all,delete-orphan',
|
||||
backref='character',
|
||||
single_parent=True,
|
||||
primaryjoin=charImplants_table.c.charID == characters_table.c.ID,
|
||||
secondaryjoin=charImplants_table.c.implantID == Implant.ID,
|
||||
secondary=charImplants_table),
|
||||
}
|
||||
)
|
||||
|
||||
31
eos/db/saveddata/crest.py
Normal file
31
eos/db/saveddata/crest.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, String
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import CrestChar
|
||||
|
||||
crest_table = Table("crest", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("name", String, nullable=False, unique=True),
|
||||
Column("refresh_token", String, nullable=False))
|
||||
|
||||
mapper(CrestChar, crest_table)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper
|
||||
@@ -24,7 +24,7 @@ from eos.db import saveddata_meta
|
||||
from eos.types import DamagePattern
|
||||
|
||||
damagePatterns_table = Table("damagePatterns", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("name", String),
|
||||
Column("emAmount", Integer),
|
||||
Column("thermalAmount", Integer),
|
||||
|
||||
162
eos/db/saveddata/databaseRepair.py
Normal file
162
eos/db/saveddata/databaseRepair.py
Normal file
@@ -0,0 +1,162 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import sqlalchemy
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DatabaseCleanup:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def ExecuteSQLQuery(saveddata_engine, query):
|
||||
try:
|
||||
results = saveddata_engine.execute(query)
|
||||
return results
|
||||
except sqlalchemy.exc.DatabaseError:
|
||||
logger.error("Failed to connect to database or error executing query:\n%s",query)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def OrphanedCharacterSkills(saveddata_engine):
|
||||
# Find orphaned character skills.
|
||||
# This solves an issue where the character doesn't exist, but skills for that character do.
|
||||
# See issue #917
|
||||
logger.debug("Running database cleanup for character skills.")
|
||||
query = "SELECT COUNT(*) AS num FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def OrphanedFitDamagePatterns(saveddata_engine):
|
||||
# Find orphaned damage patterns.
|
||||
# This solves an issue where the damage pattern doesn't exist, but fits reference the pattern.
|
||||
# See issue #777
|
||||
logger.debug("Running database cleanup for orphaned damage patterns attached to fits.")
|
||||
query = "SELECT COUNT(*) AS num FROM fits WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
# Get Uniform damage pattern ID
|
||||
uniform_query = "SELECT ID FROM damagePatterns WHERE name = 'Uniform'"
|
||||
uniform_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, uniform_query)
|
||||
|
||||
if uniform_results is None:
|
||||
return
|
||||
|
||||
rows = uniform_results.fetchall()
|
||||
|
||||
if len(rows) == 0:
|
||||
logger.error("Missing uniform damage pattern.")
|
||||
elif len(rows) > 1:
|
||||
logger.error("More than one uniform damage pattern found.")
|
||||
else:
|
||||
uniform_damage_pattern_id = rows[0]['ID']
|
||||
update_query = "UPDATE 'fits' SET 'damagePatternID' = " + str(uniform_damage_pattern_id) + \
|
||||
" WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL"
|
||||
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def OrphanedFitCharacterIDs(saveddata_engine):
|
||||
# Find orphaned character IDs. This solves an issue where the character doesn't exist, but fits reference the pattern.
|
||||
logger.debug("Running database cleanup for orphaned characters attached to fits.")
|
||||
query = "SELECT COUNT(*) AS num FROM fits WHERE characterID NOT IN (SELECT ID FROM characters) OR characterID IS NULL"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
# Get All 5 character ID
|
||||
all5_query = "SELECT ID FROM characters WHERE name = 'All 5'"
|
||||
all5_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, all5_query)
|
||||
|
||||
if all5_results is None:
|
||||
return
|
||||
|
||||
rows = all5_results.fetchall()
|
||||
|
||||
if len(rows) == 0:
|
||||
logger.error("Missing 'All 5' character.")
|
||||
elif len(rows) > 1:
|
||||
logger.error("More than one 'All 5' character found.")
|
||||
else:
|
||||
all5_id = rows[0]['ID']
|
||||
update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \
|
||||
" WHERE characterID not in (select ID from characters) OR characterID IS NULL"
|
||||
update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def NullDamagePatternNames(saveddata_engine):
|
||||
# Find damage patterns that are missing the name.
|
||||
# This solves an issue where the damage pattern ends up with a name that is null.
|
||||
# See issue #949
|
||||
logger.debug("Running database cleanup for missing damage pattern names.")
|
||||
query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name IS NULL OR name = ''"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM damagePatterns WHERE name IS NULL OR name = ''"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
|
||||
@staticmethod
|
||||
def NullTargetResistNames(saveddata_engine):
|
||||
# Find target resists that are missing the name.
|
||||
# This solves an issue where the target resist ends up with a name that is null.
|
||||
# See issue #949
|
||||
logger.debug("Running database cleanup for missing target resist names.")
|
||||
query = "SELECT COUNT(*) AS num FROM targetResists WHERE name IS NULL OR name = ''"
|
||||
results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
|
||||
if results is None:
|
||||
return
|
||||
|
||||
row = results.first()
|
||||
|
||||
if row and row['num']:
|
||||
query = "DELETE FROM targetResists WHERE name IS NULL OR name = ''"
|
||||
delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query)
|
||||
logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,19 +15,20 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Drone
|
||||
|
||||
drones_table = Table("drones", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
|
||||
Column("itemID", Integer, nullable = False),
|
||||
Column("amount", Integer, nullable = False),
|
||||
Column("amountActive", Integer, nullable = False),
|
||||
Column("projected", Boolean, default = False))
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=False),
|
||||
Column("amount", Integer, nullable=False),
|
||||
Column("amountActive", Integer, nullable=False),
|
||||
Column("projected", Boolean, default=False))
|
||||
|
||||
mapper(Drone, drones_table)
|
||||
|
||||
50
eos/db/saveddata/fighter.py
Normal file
50
eos/db/saveddata/fighter.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Fighter, Fit
|
||||
from eos.types import FighterAbility
|
||||
|
||||
fighters_table = Table("fighters", saveddata_meta,
|
||||
Column("groupID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=False),
|
||||
Column("active", Boolean, nullable=True),
|
||||
Column("amount", Integer, nullable=False),
|
||||
Column("projected", Boolean, default=False))
|
||||
|
||||
fighter_abilities_table = Table("fightersAbilities", saveddata_meta,
|
||||
Column("groupID", Integer, ForeignKey("fighters.groupID"), primary_key=True,
|
||||
index=True),
|
||||
Column("effectID", Integer, nullable=False, primary_key=True),
|
||||
Column("active", Boolean, default=False))
|
||||
|
||||
mapper(Fighter, fighters_table,
|
||||
properties={
|
||||
"owner": relation(Fit),
|
||||
"_Fighter__abilities": relation(
|
||||
FighterAbility,
|
||||
backref="fighter",
|
||||
cascade='all, delete, delete-orphan'),
|
||||
})
|
||||
|
||||
mapper(FighterAbility, fighter_abilities_table)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,63 +15,216 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String, Boolean
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||
from sqlalchemy.sql import and_
|
||||
from sqlalchemy.orm import relation, reconstructor, mapper, relationship
|
||||
from sqlalchemy import ForeignKey, Column, Integer, String, Table, Boolean
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.module import modules_table
|
||||
from eos.db.saveddata.drone import drones_table
|
||||
from eos.db import saveddata_session
|
||||
from eos.db.saveddata.cargo import cargo_table
|
||||
from eos.db.saveddata.drone import drones_table
|
||||
from eos.db.saveddata.fighter import fighters_table
|
||||
from eos.db.saveddata.implant import fitImplants_table
|
||||
from eos.types import Fit, Module, User, Booster, Drone, Cargo, Implant, Character, DamagePattern, TargetResists
|
||||
from eos.effectHandlerHelpers import HandledModuleList, HandledDroneList, \
|
||||
HandledImplantBoosterList, HandledProjectedModList, HandledProjectedDroneList, \
|
||||
HandledProjectedFitList, HandledCargoList
|
||||
from eos.db.saveddata.module import modules_table
|
||||
from eos.effectHandlerHelpers import HandledModuleList, HandledImplantBoosterList, HandledProjectedModList, \
|
||||
HandledDroneCargoList, HandledProjectedDroneList
|
||||
from eos.types import Fit as es_Fit, Module, User, Booster, Drone, Fighter, Cargo, Implant, Character, DamagePattern, \
|
||||
TargetResists, ImplantLocation
|
||||
|
||||
fits_table = Table("fits", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable = True, index = True),
|
||||
Column("shipID", Integer, nullable = False, index = True),
|
||||
Column("name", String, nullable = False),
|
||||
Column("timestamp", Integer, nullable = False),
|
||||
Column("characterID", ForeignKey("characters.ID"), nullable = True),
|
||||
Column("damagePatternID", ForeignKey("damagePatterns.ID"), nullable=True),
|
||||
Column("booster", Boolean, nullable = False, index = True, default = 0),
|
||||
Column("targetResistsID", ForeignKey("targetResists.ID"), nullable=True),
|
||||
Column("modeID", Integer, nullable=True),
|
||||
)
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable=True, index=True),
|
||||
Column("shipID", Integer, nullable=False, index=True),
|
||||
Column("name", String, nullable=False),
|
||||
Column("timestamp", Integer, nullable=False),
|
||||
Column("characterID", ForeignKey("characters.ID"), nullable=True),
|
||||
Column("damagePatternID", ForeignKey("damagePatterns.ID"), nullable=True),
|
||||
Column("booster", Boolean, nullable=False, index=True, default=0),
|
||||
Column("targetResistsID", ForeignKey("targetResists.ID"), nullable=True),
|
||||
Column("modeID", Integer, nullable=True),
|
||||
Column("implantLocation", Integer, nullable=False, default=ImplantLocation.FIT),
|
||||
Column("notes", String, nullable=True),
|
||||
)
|
||||
|
||||
projectedFits_table = Table("projectedFits", saveddata_meta,
|
||||
Column("sourceID", ForeignKey("fits.ID"), primary_key = True),
|
||||
Column("victimID", ForeignKey("fits.ID"), primary_key = True),
|
||||
Column("amount", Integer))
|
||||
mapper(Fit, fits_table,
|
||||
properties = {"_Fit__modules" : relation(Module, collection_class = HandledModuleList,
|
||||
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False),
|
||||
order_by = modules_table.c.position, cascade='all, delete, delete-orphan'),
|
||||
"_Fit__projectedModules" : relation(Module, collection_class = HandledProjectedModList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)),
|
||||
"owner" : relation(User, backref = "fits"),
|
||||
"_Fit__boosters" : relation(Booster, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True),
|
||||
"_Fit__drones" : relation(Drone, collection_class = HandledDroneList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)),
|
||||
"_Fit__cargo" : relation(Cargo, collection_class = HandledCargoList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(cargo_table.c.fitID == fits_table.c.ID)),
|
||||
"_Fit__projectedDrones" : relation(Drone, collection_class = HandledProjectedDroneList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)),
|
||||
"_Fit__implants" : relation(Implant, collection_class = HandledImplantBoosterList, cascade='all, delete, delete-orphan', single_parent=True,
|
||||
primaryjoin = fitImplants_table.c.fitID == fits_table.c.ID,
|
||||
secondaryjoin = fitImplants_table.c.implantID == Implant.ID,
|
||||
secondary = fitImplants_table),
|
||||
"_Fit__character" : relation(Character, backref = "fits"),
|
||||
"_Fit__damagePattern" : relation(DamagePattern),
|
||||
"_Fit__targetResists" : relation(TargetResists),
|
||||
"_Fit__projectedFits" : relation(Fit,
|
||||
primaryjoin = projectedFits_table.c.victimID == fits_table.c.ID,
|
||||
secondaryjoin = fits_table.c.ID == projectedFits_table.c.sourceID,
|
||||
secondary = projectedFits_table,
|
||||
collection_class = HandledProjectedFitList)
|
||||
})
|
||||
Column("sourceID", ForeignKey("fits.ID"), primary_key=True),
|
||||
Column("victimID", ForeignKey("fits.ID"), primary_key=True),
|
||||
Column("amount", Integer, nullable=False, default=1),
|
||||
Column("active", Boolean, nullable=False, default=1),
|
||||
)
|
||||
|
||||
commandFits_table = Table("commandFits", saveddata_meta,
|
||||
Column("boosterID", ForeignKey("fits.ID"), primary_key=True),
|
||||
Column("boostedID", ForeignKey("fits.ID"), primary_key=True),
|
||||
Column("active", Boolean, nullable=False, default=1)
|
||||
)
|
||||
|
||||
|
||||
class ProjectedFit(object):
|
||||
def __init__(self, sourceID, source_fit, amount=1, active=True):
|
||||
self.sourceID = sourceID
|
||||
self.source_fit = source_fit
|
||||
self.active = active
|
||||
self.__amount = amount
|
||||
|
||||
@reconstructor
|
||||
def init(self):
|
||||
if self.source_fit.isInvalid:
|
||||
# Very rare for this to happen, but be prepared for it
|
||||
saveddata_session.delete(self.source_fit)
|
||||
saveddata_session.flush()
|
||||
saveddata_session.refresh(self.victim_fit)
|
||||
|
||||
# We have a series of setters and getters here just in case someone
|
||||
# downgrades and screws up the table with NULL values
|
||||
@property
|
||||
def amount(self):
|
||||
return self.__amount or 1
|
||||
|
||||
@amount.setter
|
||||
def amount(self, amount):
|
||||
self.__amount = amount
|
||||
|
||||
def __repr__(self):
|
||||
return "ProjectedFit(sourceID={}, victimID={}, amount={}, active={}) at {}".format(
|
||||
self.sourceID, self.victimID, self.amount, self.active, hex(id(self))
|
||||
)
|
||||
|
||||
|
||||
class CommandFit(object):
|
||||
def __init__(self, boosterID, booster_fit, active=True):
|
||||
self.boosterID = boosterID
|
||||
self.booster_fit = booster_fit
|
||||
self.active = active
|
||||
|
||||
@reconstructor
|
||||
def init(self):
|
||||
if self.booster_fit.isInvalid:
|
||||
# Very rare for this to happen, but be prepared for it
|
||||
saveddata_session.delete(self.booster_fit)
|
||||
saveddata_session.flush()
|
||||
saveddata_session.refresh(self.boosted_fit)
|
||||
|
||||
def __repr__(self):
|
||||
return "CommandFit(boosterID={}, boostedID={}, active={}) at {}".format(
|
||||
self.boosterID, self.boostedID, self.active, hex(id(self))
|
||||
)
|
||||
|
||||
|
||||
es_Fit._Fit__projectedFits = association_proxy(
|
||||
"victimOf", # look at the victimOf association...
|
||||
"source_fit", # .. and return the source fits
|
||||
creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit)
|
||||
)
|
||||
|
||||
es_Fit._Fit__commandFits = association_proxy(
|
||||
"boostedOf", # look at the boostedOf association...
|
||||
"booster_fit", # .. and return the booster fit
|
||||
creator=lambda boosterID, booster_fit: CommandFit(boosterID, booster_fit)
|
||||
)
|
||||
mapper(es_Fit, fits_table,
|
||||
properties={
|
||||
"_Fit__modules": relation(
|
||||
Module,
|
||||
collection_class=HandledModuleList,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == False), # noqa
|
||||
order_by=modules_table.c.position,
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"_Fit__projectedModules": relation(
|
||||
Module,
|
||||
collection_class=HandledProjectedModList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(modules_table.c.fitID == fits_table.c.ID, modules_table.c.projected == True)), # noqa
|
||||
"owner": relation(
|
||||
User,
|
||||
backref="fits"),
|
||||
"itemID": fits_table.c.shipID,
|
||||
"shipID": fits_table.c.shipID,
|
||||
"_Fit__boosters": relation(
|
||||
Booster,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True),
|
||||
"_Fit__drones": relation(
|
||||
Drone,
|
||||
collection_class=HandledDroneCargoList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == False)), # noqa
|
||||
"_Fit__fighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledDroneCargoList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == False)), # noqa
|
||||
"_Fit__cargo": relation(
|
||||
Cargo,
|
||||
collection_class=HandledDroneCargoList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(cargo_table.c.fitID == fits_table.c.ID)),
|
||||
"_Fit__projectedDrones": relation(
|
||||
Drone,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(drones_table.c.fitID == fits_table.c.ID, drones_table.c.projected == True)), # noqa
|
||||
"_Fit__projectedFighters": relation(
|
||||
Fighter,
|
||||
collection_class=HandledProjectedDroneList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
single_parent=True,
|
||||
primaryjoin=and_(fighters_table.c.fitID == fits_table.c.ID, fighters_table.c.projected == True)), # noqa
|
||||
"_Fit__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='fit',
|
||||
single_parent=True,
|
||||
primaryjoin=fitImplants_table.c.fitID == fits_table.c.ID,
|
||||
secondaryjoin=fitImplants_table.c.implantID == Implant.ID,
|
||||
secondary=fitImplants_table),
|
||||
"_Fit__character": relation(
|
||||
Character,
|
||||
backref="fits"),
|
||||
"_Fit__damagePattern": relation(DamagePattern),
|
||||
"_Fit__targetResists": relation(TargetResists),
|
||||
"projectedOnto": relationship(
|
||||
ProjectedFit,
|
||||
primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID,
|
||||
backref='source_fit',
|
||||
collection_class=attribute_mapped_collection('victimID'),
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"victimOf": relationship(
|
||||
ProjectedFit,
|
||||
primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID,
|
||||
backref='victim_fit',
|
||||
collection_class=attribute_mapped_collection('sourceID'),
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"boostedOnto": relationship(
|
||||
CommandFit,
|
||||
primaryjoin=commandFits_table.c.boosterID == fits_table.c.ID,
|
||||
backref='booster_fit',
|
||||
collection_class=attribute_mapped_collection('boostedID'),
|
||||
cascade='all, delete, delete-orphan'),
|
||||
"boostedOf": relationship(
|
||||
CommandFit,
|
||||
primaryjoin=fits_table.c.ID == commandFits_table.c.boostedID,
|
||||
backref='boosted_fit',
|
||||
collection_class=attribute_mapped_collection('boosterID'),
|
||||
cascade='all, delete, delete-orphan'),
|
||||
}
|
||||
)
|
||||
|
||||
mapper(ProjectedFit, projectedFits_table,
|
||||
properties={
|
||||
"_ProjectedFit__amount": projectedFits_table.c.amount,
|
||||
}
|
||||
)
|
||||
|
||||
mapper(CommandFit, commandFits_table)
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
#===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper, relation
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Fleet, Wing, Squad, Fit
|
||||
from eos.db.saveddata.fit import fits_table
|
||||
|
||||
gangs_table = Table("gangs", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("leaderID", ForeignKey("fits.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")),
|
||||
Column("name", String))
|
||||
|
||||
wings_table = Table("wings", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("gangID", ForeignKey("gangs.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")),
|
||||
Column("leaderID", ForeignKey("fits.ID")))
|
||||
|
||||
squads_table = Table("squads", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("wingID", ForeignKey("wings.ID")),
|
||||
Column("leaderID", ForeignKey("fits.ID")),
|
||||
Column("boosterID", ForeignKey("fits.ID")))
|
||||
|
||||
squadmembers_table = Table("squadmembers", saveddata_meta,
|
||||
Column("squadID", ForeignKey("squads.ID"), primary_key = True),
|
||||
Column("memberID", ForeignKey("fits.ID"), primary_key = True))
|
||||
|
||||
mapper(Fleet, gangs_table,
|
||||
properties = {"wings" : relation(Wing, backref="gang"),
|
||||
"leader" : relation(Fit, primaryjoin = gangs_table.c.leaderID == fits_table.c.ID),
|
||||
"booster": relation(Fit, primaryjoin = gangs_table.c.boosterID == fits_table.c.ID)})
|
||||
|
||||
mapper(Wing, wings_table,
|
||||
properties = {"squads" : relation(Squad, backref="wing"),
|
||||
"leader" : relation(Fit, primaryjoin = wings_table.c.leaderID == fits_table.c.ID),
|
||||
"booster": relation(Fit, primaryjoin = wings_table.c.boosterID == fits_table.c.ID)})
|
||||
|
||||
mapper(Squad, squads_table,
|
||||
properties = {"leader" : relation(Fit, primaryjoin = squads_table.c.leaderID == fits_table.c.ID),
|
||||
"booster" : relation(Fit, primaryjoin = squads_table.c.boosterID == fits_table.c.ID),
|
||||
"members" : relation(Fit,
|
||||
primaryjoin = squads_table.c.ID == squadmembers_table.c.squadID,
|
||||
secondaryjoin = squadmembers_table.c.memberID == fits_table.c.ID,
|
||||
secondary = squadmembers_table)})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
@@ -24,16 +24,20 @@ from eos.db import saveddata_meta
|
||||
from eos.types import Implant
|
||||
|
||||
implants_table = Table("implants", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("itemID", Integer),
|
||||
Column("active", Boolean))
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("itemID", Integer),
|
||||
Column("active", Boolean))
|
||||
|
||||
fitImplants_table = Table("fitImplants", saveddata_meta,
|
||||
Column("fitID", ForeignKey("fits.ID"), index = True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key = True))
|
||||
Column("fitID", ForeignKey("fits.ID"), index=True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key=True))
|
||||
|
||||
charImplants_table = Table("charImplants", saveddata_meta,
|
||||
Column("charID", ForeignKey("characters.ID"), index = True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key = True))
|
||||
Column("charID", ForeignKey("characters.ID"), index=True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key=True))
|
||||
|
||||
implantsSetMap_table = Table("implantSetMap", saveddata_meta,
|
||||
Column("setID", ForeignKey("implantSets.ID"), index=True),
|
||||
Column("implantID", ForeignKey("implants.ID"), primary_key=True))
|
||||
|
||||
mapper(Implant, implants_table)
|
||||
|
||||
45
eos/db/saveddata/implantSet.py
Normal file
45
eos/db/saveddata/implantSet.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2016 Ryan Holmes
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, String
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.db.saveddata.implant import implantsSetMap_table
|
||||
from eos.effectHandlerHelpers import HandledImplantBoosterList
|
||||
from eos.types import Implant, ImplantSet
|
||||
|
||||
implant_set_table = Table("implantSets", saveddata_meta,
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("name", String, nullable=False),
|
||||
)
|
||||
|
||||
mapper(ImplantSet, implant_set_table,
|
||||
properties={
|
||||
"_ImplantSet__implants": relation(
|
||||
Implant,
|
||||
collection_class=HandledImplantBoosterList,
|
||||
cascade='all, delete, delete-orphan',
|
||||
backref='set',
|
||||
single_parent=True,
|
||||
primaryjoin=implantsSetMap_table.c.setID == implant_set_table.c.ID,
|
||||
secondaryjoin=implantsSetMap_table.c.implantID == Implant.ID,
|
||||
secondary=implantsSetMap_table),
|
||||
}
|
||||
)
|
||||
198
eos/db/saveddata/loadDefaultDatabaseValues.py
Normal file
198
eos/db/saveddata/loadDefaultDatabaseValues.py
Normal file
@@ -0,0 +1,198 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import eos.db
|
||||
from eos.saveddata.damagePattern import DamagePattern as es_DamagePattern
|
||||
from eos.saveddata.targetResists import TargetResists as es_TargetResists
|
||||
|
||||
|
||||
class ImportError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DefaultDatabaseValues():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
instance = None
|
||||
|
||||
@classmethod
|
||||
def importDamageProfileDefaults(cls):
|
||||
damageProfileList = [["Uniform", "25", "25", "25", "25"], ["[Generic]EM", "100", "0", "0", "0"],
|
||||
["[Generic]Thermal", "0", "100", "0", "0"], ["[Generic]Kinetic", "0", "0", "100", "0"],
|
||||
["[Generic]Explosive", "0", "0", "0", "100"],
|
||||
["[NPC][Asteroid] Blood Raiders", "5067", "4214", "0", "0"],
|
||||
["[Bombs]Concussion Bomb", "0", "0", "6400", "0"],
|
||||
["[Bombs]Electron Bomb", "6400", "0", "0", "0"],
|
||||
["[Bombs]Scorch Bomb", "0", "6400", "0", "0"],
|
||||
["[Bombs]Shrapnel Bomb", "0", "0", "0", "6400"],
|
||||
["[Frequency Crystals][T2] Gleam", "56", "56", "0", "0"],
|
||||
["[Frequency Crystals][T2] Aurora", "40", "24", "0", "0"],
|
||||
["[Frequency Crystals][T2] Scorch", "72", "16", "0", "0"],
|
||||
["[Frequency Crystals][T2] Conflagration", "61.6", "61.6", "0", "0"],
|
||||
["[Frequency Crystals]Gamma", "61.6", "35.2", "0", "0"],
|
||||
["[Frequency Crystals]Infrared", "44", "17.6", "0", "0"],
|
||||
["[Frequency Crystals]Microwave", "35.2", "17.6", "0", "0"],
|
||||
["[Frequency Crystals]Multifrequency", "61.6", "44", "0", "0"],
|
||||
["[Frequency Crystals]Radio", "44", "0", "0", "0"],
|
||||
["[Frequency Crystals]Standard", "44", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Ultraviolet", "52.8", "26.4", "0", "0"],
|
||||
["[Frequency Crystals]Xray", "52.8", "35.2", "0", "0"],
|
||||
["[Hybrid Charges][T2] Void", "0", "61.6", "61.6", "0"],
|
||||
["[Hybrid Charges][T2] Null", "0", "48", "40", "0"],
|
||||
["[Hybrid Charges][T2] Javelin", "0", "64", "48", "0"],
|
||||
["[Hybrid Charges][T2] Spike", "0", "32", "32", "0"],
|
||||
["[Hybrid Charges]Antimatter", "0", "48", "67.2", "0"],
|
||||
["[Hybrid Charges]Iridium", "0", "28.8", "38.4", "0"],
|
||||
["[Hybrid Charges]Iron", "0", "19.2", "28.8", "0"],
|
||||
["[Hybrid Charges]Lead", "0", "28.8", "48", "0"],
|
||||
["[Hybrid Charges]Plutonium", "0", "48", "57.6", "0"],
|
||||
["[Hybrid Charges]Thorium", "0", "38.4", "48", "0"],
|
||||
["[Hybrid Charges]Tungsten", "0", "19.2", "38.4", "0"],
|
||||
["[Hybrid Charges]Uranium", "0", "38.4", "57.6", "0"],
|
||||
["[Missiles]Mjolnir", "100", "0", "0", "0"], ["[Missiles]Inferno", "0", "100", "0", "0"],
|
||||
["[Missiles]Scourge", "0", "0", "100", "0"], ["[Missiles]Nova", "0", "0", "0", "100"],
|
||||
["[Missiles][Structure) Standup Missile", "100", "100", "100", "100"],
|
||||
["[Projectile Ammo][T2] Tremor", "0", "0", "24", "40"],
|
||||
["[Projectile Ammo][T2] Quake", "0", "0", "40", "72"],
|
||||
["[Projectile Ammo][T2] Hail", "0", "0", "26.4", "96.8"],
|
||||
["[Projectile Ammo][T2] Barrage", "0", "0", "40", "48"],
|
||||
["[Projectile Ammo]Carbonized Lead", "0", "0", "35.2", "8.8"],
|
||||
["[Projectile Ammo]Depleted Uranium", "0", "26.4", "17.6", "26.4"],
|
||||
["[Projectile Ammo]EMP", "79.2", "0", "8.8", "17.6"],
|
||||
["[Projectile Ammo]Fusion", "0", "0", "17.6", "88"],
|
||||
["[Projectile Ammo]Nuclear", "0", "0", "8.8", "35.2"],
|
||||
["[Projectile Ammo]Phased Plasma", "0", "88", "17.6", "0"],
|
||||
["[Projectile Ammo]Proton", "26.4", "0", "17.6", "0"],
|
||||
["[Projectile Ammo]Titanium Sabot", "0", "0", "52.8", "176"],
|
||||
["[NPC][Burner] Cruor (Blood Raiders)", "90", "90", "0", "0"],
|
||||
["[NPC][Burner] Dramiel (Angel)", "55", "0", "20", "96"],
|
||||
["[NPC][Burner] Daredevil (Serpentis)", "0", "110", "154", "0"],
|
||||
["[NPC][Burner] Succubus (Sanshas Nation)", "135", "30", "0", "0"],
|
||||
["[NPC][Burner] Worm (Guristas)", "0", "0", "228", "0"],
|
||||
["[NPC][Burner] Enyo", "0", "147", "147", "0"],
|
||||
["[NPC][Burner] Hawk", "0", "0", "247", "0"],
|
||||
["[NPC][Burner] Jaguar", "36", "0", "50", "182"],
|
||||
["[NPC][Burner] Vengeance", "232", "0", "0", "0"],
|
||||
["[NPC][Burner] Ashimmu (Blood Raiders)", "260", "100", "0", "0"],
|
||||
["[NPC][Burner] Talos", "0", "413", "413", "0"],
|
||||
["[NPC][Burner] Sentinel", "0", "75", "0", "90"],
|
||||
["[NPC][Asteroid] Angel Cartel", "1838", "562", "2215", "3838"],
|
||||
["[NPC][Deadspace] Angel Cartel", "369", "533", "1395", "3302"],
|
||||
["[NPC][Deadspace] Blood Raiders", "6040", "5052", "10", "15"],
|
||||
["[NPC][Asteroid] Guristas", "0", "1828", "7413", "0"],
|
||||
["[NPC][Deadspace] Guristas", "0", "1531", "9680", "0"],
|
||||
["[NPC][Asteroid] Rogue Drone", "394", "666", "1090", "1687"],
|
||||
["[NPC][Deadspace] Rogue Drone", "276", "1071", "1069", "871"],
|
||||
["[NPC][Asteroid] Sanshas Nation", "5586", "4112", "0", "0"],
|
||||
["[NPC][Deadspace] Sanshas Nation", "3009", "2237", "0", "0"],
|
||||
["[NPC][Asteroid] Serpentis", "0", "5373", "4813", "0"],
|
||||
["[NPC][Deadspace] Serpentis", "0", "3110", "1929", "0"],
|
||||
["[NPC][Mission] Amarr Empire", "4464", "3546", "97", "0"],
|
||||
["[NPC][Mission] Caldari State", "0", "2139", "4867", "0"],
|
||||
["[NPC][Mission] CONCORD", "336", "134", "212", "412"],
|
||||
["[NPC][Mission] Gallente Federation", "9", "3712", "2758", "0"],
|
||||
["[NPC][Mission] Khanid", "612", "483", "43", "6"],
|
||||
["[NPC][Mission] Minmatar Republic", "1024", "388", "1655", "4285"],
|
||||
["[NPC][Mission] Mordus Legion", "25", "262", "625", "0"],
|
||||
["[NPC][Mission] Thukker", "0", "52", "10", "79"],
|
||||
["[NPC][Other] Sleepers", "1472", "1472", "1384", "1384"],
|
||||
["[NPC][Other] Sansha Incursion", "1682", "1347", "3678", "3678"]]
|
||||
|
||||
for damageProfileRow in damageProfileList:
|
||||
name, em, therm, kin, exp = damageProfileRow
|
||||
damageProfile = eos.db.getDamagePattern(name)
|
||||
if damageProfile is None:
|
||||
damageProfile = es_DamagePattern(em, therm, kin, exp)
|
||||
damageProfile.name = name
|
||||
eos.db.save(damageProfile)
|
||||
|
||||
@classmethod
|
||||
def importResistProfileDefaults(cls):
|
||||
targetResistProfileList = [["Uniform (25%)", "0.25", "0.25", "0.25", "0.25"],
|
||||
["Uniform (50%)", "0.50", "0.50", "0.50", "0.50"],
|
||||
["Uniform (75%)", "0.75", "0.75", "0.75", "0.75"],
|
||||
["Uniform (90%)", "0.90", "0.90", "0.90", "0.90"],
|
||||
["[T1 Resist]Shield", "0.0", "0.20", "0.40", "0.50"],
|
||||
["[T1 Resist]Armor", "0.50", "0.45", "0.25", "0.10"],
|
||||
["[T1 Resist]Hull", "0.33", "0.33", "0.33", "0.33"],
|
||||
["[T1 Resist]Shield (+T2 DCU)", "0.125", "0.30", "0.475", "0.562"],
|
||||
["[T1 Resist]Armor (+T2 DCU)", "0.575", "0.532", "0.363", "0.235"],
|
||||
["[T1 Resist]Hull (+T2 DCU)", "0.598", "0.598", "0.598", "0.598"],
|
||||
["[T2 Resist]Amarr (Shield)", "0.0", "0.20", "0.70", "0.875"],
|
||||
["[T2 Resist]Amarr (Armor)", "0.50", "0.35", "0.625", "0.80"],
|
||||
["[T2 Resist]Caldari (Shield)", "0.20", "0.84", "0.76", "0.60"],
|
||||
["[T2 Resist]Caldari (Armor)", "0.50", "0.8625", "0.625", "0.10"],
|
||||
["[T2 Resist]Gallente (Shield)", "0.0", "0.60", "0.85", "0.50"],
|
||||
["[T2 Resist]Gallente (Armor)", "0.50", "0.675", "0.8375", "0.10"],
|
||||
["[T2 Resist]Minmatar (Shield)", "0.75", "0.60", "0.40", "0.50"],
|
||||
["[T2 Resist]Minmatar (Armor)", "0.90", "0.675", "0.25", "0.10"],
|
||||
["[NPC][Asteroid] Angel Cartel", "0.54", "0.42", "0.37", "0.32"],
|
||||
["[NPC][Asteroid] Blood Raiders", "0.34", "0.39", "0.45", "0.52"],
|
||||
["[NPC][Asteroid] Guristas", "0.55", "0.35", "0.3", "0.48"],
|
||||
["[NPC][Asteroid] Rogue Drones", "0.35", "0.38", "0.44", "0.49"],
|
||||
["[NPC][Asteroid] Sanshas Nation", "0.35", "0.4", "0.47", "0.53"],
|
||||
["[NPC][Asteroid] Serpentis", "0.49", "0.38", "0.29", "0.51"],
|
||||
["[NPC][Deadspace] Angel Cartel", "0.59", "0.48", "0.4", "0.32"],
|
||||
["[NPC][Deadspace] Blood Raiders", "0.31", "0.39", "0.47", "0.56"],
|
||||
["[NPC][Deadspace] Guristas", "0.57", "0.39", "0.31", "0.5"],
|
||||
["[NPC][Deadspace] Rogue Drones", "0.42", "0.42", "0.47", "0.49"],
|
||||
["[NPC][Deadspace] Sanshas Nation", "0.31", "0.39", "0.47", "0.56"],
|
||||
["[NPC][Deadspace] Serpentis", "0.49", "0.38", "0.29", "0.56"],
|
||||
["[NPC][Mission] Amarr Empire", "0.34", "0.38", "0.42", "0.46"],
|
||||
["[NPC][Mission] Caldari State", "0.51", "0.38", "0.3", "0.51"],
|
||||
["[NPC][Mission] CONCORD", "0.47", "0.46", "0.47", "0.47"],
|
||||
["[NPC][Mission] Gallente Federation", "0.51", "0.38", "0.31", "0.52"],
|
||||
["[NPC][Mission] Khanid", "0.51", "0.42", "0.36", "0.4"],
|
||||
["[NPC][Mission] Minmatar Republic", "0.51", "0.46", "0.41", "0.35"],
|
||||
["[NPC][Mission] Mordus Legion", "0.32", "0.48", "0.4", "0.62"],
|
||||
["[NPC][Other] Sleeper", "0.61", "0.61", "0.61", "0.61"],
|
||||
["[NPC][Other] Sansha Incursion", "0.65", "0.63", "0.64", "0.65"],
|
||||
["[NPC][Burner] Cruor (Blood Raiders)", "0.8", "0.73", "0.69", "0.67"],
|
||||
["[NPC][Burner] Dramiel (Angel)", "0.35", "0.48", "0.61", "0.68"],
|
||||
["[NPC][Burner] Daredevil (Serpentis)", "0.69", "0.59", "0.59", "0.43"],
|
||||
["[NPC][Burner] Succubus (Sanshas Nation)", "0.35", "0.48", "0.61", "0.68"],
|
||||
["[NPC][Burner] Worm (Guristas)", "0.48", "0.58", "0.69", "0.74"],
|
||||
["[NPC][Burner] Enyo", "0.58", "0.72", "0.86", "0.24"],
|
||||
["[NPC][Burner] Hawk", "0.3", "0.86", "0.79", "0.65"],
|
||||
["[NPC][Burner] Jaguar", "0.78", "0.65", "0.48", "0.56"],
|
||||
["[NPC][Burner] Vengeance", "0.66", "0.56", "0.75", "0.86"],
|
||||
["[NPC][Burner] Ashimmu (Blood Raiders)", "0.8", "0.76", "0.68", "0.7"],
|
||||
["[NPC][Burner] Talos", "0.68", "0.59", "0.59", "0.43"],
|
||||
["[NPC][Burner] Sentinel", "0.58", "0.45", "0.52", "0.66"]]
|
||||
|
||||
for targetResistProfileRow in targetResistProfileList:
|
||||
name, em, therm, kin, exp = targetResistProfileRow
|
||||
resistsProfile = eos.db.eos.db.getTargetResists(name)
|
||||
if resistsProfile is None:
|
||||
resistsProfile = es_TargetResists(em, therm, kin, exp)
|
||||
resistsProfile.name = name
|
||||
eos.db.save(resistsProfile)
|
||||
|
||||
@classmethod
|
||||
def importRequiredDefaults(cls):
|
||||
damageProfileList = [["Uniform", "25", "25", "25", "25"]]
|
||||
|
||||
for damageProfileRow in damageProfileList:
|
||||
name, em, therm, kin, exp = damageProfileRow
|
||||
damageProfile = eos.db.getDamagePattern(name)
|
||||
if damageProfile is None:
|
||||
damageProfile = es_DamagePattern(em, therm, kin, exp)
|
||||
damageProfile.name = name
|
||||
eos.db.save(damageProfile)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2011 Anton Vorobyov
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,15 +15,16 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Column, Table, String
|
||||
from sqlalchemy.orm import mapper
|
||||
from eos.types import MiscData
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import MiscData
|
||||
|
||||
miscdata_table = Table("miscdata", saveddata_meta,
|
||||
Column("fieldName", String, primary_key=True),
|
||||
Column("fieldValue", String))
|
||||
Column("fieldName", String, primary_key=True),
|
||||
Column("fieldValue", String))
|
||||
|
||||
mapper(MiscData, miscdata_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean
|
||||
from sqlalchemy.orm import relation, mapper
|
||||
@@ -24,16 +24,15 @@ from eos.db import saveddata_meta
|
||||
from eos.types import Module, Fit
|
||||
|
||||
modules_table = Table("modules", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable = False, index = True),
|
||||
Column("itemID", Integer, nullable = True),
|
||||
Column("dummySlot", Integer, nullable = True, default = None),
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("fitID", Integer, ForeignKey("fits.ID"), nullable=False, index=True),
|
||||
Column("itemID", Integer, nullable=True),
|
||||
Column("dummySlot", Integer, nullable=True, default=None),
|
||||
Column("chargeID", Integer),
|
||||
Column("state", Integer, CheckConstraint("state >= -1"), CheckConstraint("state <= 2")),
|
||||
Column("projected", Boolean, default = False, nullable = False),
|
||||
Column("projected", Boolean, default=False, nullable=False),
|
||||
Column("position", Integer),
|
||||
CheckConstraint('("dummySlot" = NULL OR "itemID" = NULL) AND "dummySlot" != "itemID"'))
|
||||
|
||||
mapper(Module, modules_table,
|
||||
properties = {"owner" : relation(Fit)})
|
||||
|
||||
properties={"owner": relation(Fit)})
|
||||
|
||||
31
eos/db/saveddata/override.py
Normal file
31
eos/db/saveddata/override.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Override
|
||||
|
||||
overrides_table = Table("overrides", saveddata_meta,
|
||||
Column("itemID", Integer, primary_key=True, index=True),
|
||||
Column("attrID", Integer, primary_key=True, index=True),
|
||||
Column("value", Float, nullable=False))
|
||||
|
||||
mapper(Override, overrides_table)
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,17 +15,18 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Float, Integer
|
||||
from sqlalchemy.orm import mapper
|
||||
|
||||
from eos.db import saveddata_meta
|
||||
from eos.types import Price
|
||||
|
||||
prices_table = Table("prices", saveddata_meta,
|
||||
Column("typeID", Integer, primary_key=True),
|
||||
Column("price", Float),
|
||||
Column("time", Integer, nullable = False),
|
||||
Column("time", Integer, nullable=False),
|
||||
Column("failed", Integer))
|
||||
|
||||
mapper(Price, prices_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,12 +15,16 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy.sql import and_
|
||||
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.db.saveddata.fit import projectedFits_table
|
||||
from eos.db.util import processEager, processWhere
|
||||
from eos.db import saveddata_session, sd_lock
|
||||
from eos.types import User, Character, Fit, Price, DamagePattern, Fleet, MiscData, Wing, Squad, TargetResists
|
||||
from eos.db.saveddata.fleet import squadmembers_table
|
||||
|
||||
from eos.types import *
|
||||
from eos.db.saveddata.fit import projectedFits_table
|
||||
from sqlalchemy.sql import and_
|
||||
import eos.config
|
||||
@@ -28,13 +32,17 @@ import eos.config
|
||||
configVal = getattr(eos.config, "saveddataCache", None)
|
||||
if configVal is True:
|
||||
import weakref
|
||||
|
||||
itemCache = {}
|
||||
queryCache = {}
|
||||
|
||||
def cachedQuery(type, amount, *keywords):
|
||||
itemCache[type] = localItemCache = weakref.WeakValueDictionary()
|
||||
queryCache[type] = typeQueryCache = {}
|
||||
|
||||
def deco(function):
|
||||
localQueryCache = typeQueryCache[function] = {}
|
||||
|
||||
def setCache(cacheKey, args, kwargs):
|
||||
items = function(*args, **kwargs)
|
||||
IDs = set()
|
||||
@@ -43,7 +51,7 @@ if configVal is True:
|
||||
for item in stuff:
|
||||
ID = getattr(item, "ID", None)
|
||||
if ID is None:
|
||||
#Some uncachable data, don't cache this query
|
||||
# Some uncachable data, don't cache this query
|
||||
del localQueryCache[cacheKey]
|
||||
break
|
||||
localItemCache[ID] = item
|
||||
@@ -69,7 +77,7 @@ if configVal is True:
|
||||
for ID in IDs:
|
||||
data = localItemCache.get(ID)
|
||||
if data is None:
|
||||
#Fuck, some of our stuff isn't cached it seems.
|
||||
# Fuck, some of our stuff isn't cached it seems.
|
||||
items = setCache(cacheKey, args, kwargs)
|
||||
break
|
||||
items.append(data)
|
||||
@@ -81,11 +89,13 @@ if configVal is True:
|
||||
break
|
||||
|
||||
return items
|
||||
|
||||
return checkAndReturn
|
||||
|
||||
return deco
|
||||
|
||||
def removeCachedEntry(type, ID):
|
||||
if not type in queryCache:
|
||||
if type not in queryCache:
|
||||
return
|
||||
functionCache = queryCache[type]
|
||||
for _, localCache in functionCache.iteritems():
|
||||
@@ -110,11 +120,13 @@ else:
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return checkAndReturn
|
||||
|
||||
return deco
|
||||
|
||||
def removeCachedEntry(*args, **kwargs):
|
||||
return
|
||||
|
||||
|
||||
def sqlizeString(line):
|
||||
# Escape backslashes first, as they will be as escape symbol in queries
|
||||
# Then escape percent and underscore signs
|
||||
@@ -122,6 +134,7 @@ def sqlizeString(line):
|
||||
line = line.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_").replace("*", "%")
|
||||
return line
|
||||
|
||||
|
||||
@cachedQuery(User, 1, "lookfor")
|
||||
def getUser(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -140,6 +153,7 @@ def getUser(lookfor, eager=None):
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return user
|
||||
|
||||
|
||||
@cachedQuery(Character, 1, "lookfor")
|
||||
def getCharacter(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -153,17 +167,20 @@ def getCharacter(lookfor, eager=None):
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(Character).options(*eager).filter(Character.name == lookfor).first()
|
||||
character = saveddata_session.query(Character).options(*eager).filter(
|
||||
Character.savedName == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return character
|
||||
|
||||
|
||||
def getCharacterList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
characters = saveddata_session.query(Character).options(*eager).all()
|
||||
return characters
|
||||
|
||||
|
||||
def getCharactersForUser(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
eager = processEager(eager)
|
||||
@@ -173,6 +190,7 @@ def getCharactersForUser(lookfor, eager=None):
|
||||
raise TypeError("Need integer as argument")
|
||||
return characters
|
||||
|
||||
|
||||
@cachedQuery(Fit, 1, "lookfor")
|
||||
def getFit(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -182,52 +200,17 @@ def getFit(lookfor, eager=None):
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fit = saveddata_session.query(Fit).options(*eager).filter(Fit.ID == fitID).first()
|
||||
fit = saveddata_session.query(Fit).options(*eager).filter(Fit.ID == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
if fit and fit.isInvalid:
|
||||
with sd_lock:
|
||||
removeInvalid([fit])
|
||||
return None
|
||||
|
||||
return fit
|
||||
|
||||
@cachedQuery(Fleet, 1, "fleetID")
|
||||
def getFleet(fleetID, eager=None):
|
||||
if isinstance(fleetID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
fleet = saveddata_session.query(Fleet).get(fleetID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fleet = saveddata_session.query(Fleet).options(*eager).filter(Fleet.ID == fleetID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return fleet
|
||||
|
||||
@cachedQuery(Wing, 1, "wingID")
|
||||
def getWing(wingID, eager=None):
|
||||
if isinstance(wingID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
wing = saveddata_session.query(Wing).get(wingID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
wing = saveddata_session.query(Wing).options(*eager).filter(Wing.ID == wingID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return wing
|
||||
|
||||
@cachedQuery(Squad, 1, "squadID")
|
||||
def getSquad(squadID, eager=None):
|
||||
if isinstance(squadID, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
squad = saveddata_session.query(Squad).get(squadID)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
squad = saveddata_session.query(Squad).options(*eager).filter(Fleet.ID == squadID).first()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
return squad
|
||||
|
||||
def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
@@ -244,11 +227,13 @@ def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
|
||||
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
|
||||
else:
|
||||
raise TypeError("ShipID must be integer")
|
||||
|
||||
return fits
|
||||
|
||||
|
||||
def getBoosterFits(ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
Get all the fits that are flagged as a boosting ship
|
||||
@@ -264,45 +249,52 @@ def getBoosterFits(ownerID=None, where=None, eager=None):
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
|
||||
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
|
||||
|
||||
return fits
|
||||
|
||||
|
||||
def countAllFits():
|
||||
with sd_lock:
|
||||
count = saveddata_session.query(Fit).count()
|
||||
return count
|
||||
|
||||
def countFitsWithShip(shipID, ownerID=None, where=None, eager=None):
|
||||
|
||||
def countFitsWithShip(lookfor, ownerID=None, where=None, eager=None):
|
||||
"""
|
||||
Get all the fits using a certain ship.
|
||||
If no user is passed, do this for all users.
|
||||
"""
|
||||
if isinstance(shipID, int):
|
||||
if ownerID is not None and not isinstance(ownerID, int):
|
||||
raise TypeError("OwnerID must be integer")
|
||||
filter = Fit.shipID == shipID
|
||||
if ownerID is not None:
|
||||
filter = and_(filter, Fit.ownerID == ownerID)
|
||||
if ownerID is not None and not isinstance(ownerID, int):
|
||||
raise TypeError("OwnerID must be integer")
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
count = saveddata_session.query(Fit).options(*eager).filter(filter).count()
|
||||
if isinstance(lookfor, int):
|
||||
filter = Fit.shipID == lookfor
|
||||
elif isinstance(lookfor, list):
|
||||
if len(lookfor) == 0:
|
||||
return 0
|
||||
filter = Fit.shipID.in_(lookfor)
|
||||
else:
|
||||
raise TypeError("ShipID must be integer")
|
||||
raise TypeError("You must supply either an integer or ShipID must be integer")
|
||||
|
||||
if ownerID is not None:
|
||||
filter = and_(filter, Fit.ownerID == ownerID)
|
||||
|
||||
filter = processWhere(filter, where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
count = saveddata_session.query(Fit).options(*eager).filter(filter).count()
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def getFitList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).all()
|
||||
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).all())
|
||||
|
||||
return fits
|
||||
|
||||
def getFleetList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fleets = saveddata_session.query(Fleet).options(*eager).all()
|
||||
return fleets
|
||||
|
||||
@cachedQuery(Price, 1, "typeID")
|
||||
def getPrice(typeID):
|
||||
@@ -313,12 +305,14 @@ def getPrice(typeID):
|
||||
raise TypeError("Need integer as argument")
|
||||
return price
|
||||
|
||||
|
||||
def clearPrices():
|
||||
with sd_lock:
|
||||
deleted_rows = saveddata_session.query(Price).delete()
|
||||
commit()
|
||||
return deleted_rows
|
||||
|
||||
|
||||
def getMiscData(field):
|
||||
if isinstance(field, basestring):
|
||||
with sd_lock:
|
||||
@@ -327,18 +321,28 @@ def getMiscData(field):
|
||||
raise TypeError("Need string as argument")
|
||||
return data
|
||||
|
||||
|
||||
def getDamagePatternList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
patterns = saveddata_session.query(DamagePattern).options(*eager).all()
|
||||
return patterns
|
||||
|
||||
|
||||
def getTargetResistsList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
patterns = saveddata_session.query(TargetResists).options(*eager).all()
|
||||
return patterns
|
||||
|
||||
|
||||
def getImplantSetList(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
sets = saveddata_session.query(ImplantSet).options(*eager).all()
|
||||
return sets
|
||||
|
||||
|
||||
@cachedQuery(DamagePattern, 1, "lookfor")
|
||||
def getDamagePattern(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -348,15 +352,18 @@ def getDamagePattern(lookfor, eager=None):
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.ID == lookfor).first()
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
|
||||
DamagePattern.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.name == lookfor).first()
|
||||
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
|
||||
DamagePattern.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return pattern
|
||||
|
||||
|
||||
@cachedQuery(TargetResists, 1, "lookfor")
|
||||
def getTargetResists(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
@@ -366,36 +373,52 @@ def getTargetResists(lookfor, eager=None):
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(TargetResists).options(*eager).filter(TargetResists.ID == lookfor).first()
|
||||
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
|
||||
TargetResists.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(TargetResists).options(*eager).filter(TargetResists.name == lookfor).first()
|
||||
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
|
||||
TargetResists.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return pattern
|
||||
|
||||
|
||||
@cachedQuery(ImplantSet, 1, "lookfor")
|
||||
def getImplantSet(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(ImplantSet).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(
|
||||
TargetResists.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Improper argument")
|
||||
return pattern
|
||||
|
||||
|
||||
def searchFits(nameLike, where=None, eager=None):
|
||||
if not isinstance(nameLike, basestring):
|
||||
raise TypeError("Need string as argument")
|
||||
# Prepare our string for request
|
||||
nameLike = u"%{0}%".format(sqlizeString(nameLike))
|
||||
|
||||
#Add any extra components to the search to our where clause
|
||||
# Add any extra components to the search to our where clause
|
||||
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
fits = saveddata_session.query(Fit).options(*eager).filter(filter).all()
|
||||
fits = removeInvalid(saveddata_session.query(Fit).options(*eager).filter(filter).all())
|
||||
|
||||
return fits
|
||||
|
||||
def getSquadsIDsWithFitID(fitID):
|
||||
if isinstance(fitID, int):
|
||||
with sd_lock:
|
||||
squads = saveddata_session.query(squadmembers_table.c.squadID).filter(squadmembers_table.c.memberID == fitID).all()
|
||||
squads = tuple(entry[0] for entry in squads)
|
||||
return squads
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
def getProjectedFits(fitID):
|
||||
if isinstance(fitID, int):
|
||||
@@ -406,14 +429,72 @@ def getProjectedFits(fitID):
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
|
||||
def getCrestCharacters(eager=None):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
characters = saveddata_session.query(CrestChar).options(*eager).all()
|
||||
return characters
|
||||
|
||||
|
||||
@cachedQuery(CrestChar, 1, "lookfor")
|
||||
def getCrestCharacter(lookfor, eager=None):
|
||||
if isinstance(lookfor, int):
|
||||
if eager is None:
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(CrestChar).get(lookfor)
|
||||
else:
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.ID == lookfor).first()
|
||||
elif isinstance(lookfor, basestring):
|
||||
eager = processEager(eager)
|
||||
with sd_lock:
|
||||
character = saveddata_session.query(CrestChar).options(*eager).filter(CrestChar.name == lookfor).first()
|
||||
else:
|
||||
raise TypeError("Need integer or string as argument")
|
||||
return character
|
||||
|
||||
|
||||
def getOverrides(itemID, eager=None):
|
||||
if isinstance(itemID, int):
|
||||
return saveddata_session.query(Override).filter(Override.itemID == itemID).all()
|
||||
else:
|
||||
raise TypeError("Need integer as argument")
|
||||
|
||||
|
||||
def clearOverrides():
|
||||
with sd_lock:
|
||||
deleted_rows = saveddata_session.query(Override).delete()
|
||||
commit()
|
||||
return deleted_rows
|
||||
|
||||
|
||||
def getAllOverrides(eager=None):
|
||||
return saveddata_session.query(Override).all()
|
||||
|
||||
|
||||
def removeInvalid(fits):
|
||||
invalids = [f for f in fits if f.isInvalid]
|
||||
|
||||
if invalids:
|
||||
map(fits.remove, invalids)
|
||||
map(saveddata_session.delete, invalids)
|
||||
saveddata_session.commit()
|
||||
|
||||
return fits
|
||||
|
||||
|
||||
def add(stuff):
|
||||
with sd_lock:
|
||||
saveddata_session.add(stuff)
|
||||
|
||||
|
||||
def save(stuff):
|
||||
add(stuff)
|
||||
commit()
|
||||
|
||||
|
||||
def remove(stuff):
|
||||
removeCachedEntry(type(stuff), stuff.ID)
|
||||
with sd_lock:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, ForeignKey
|
||||
from sqlalchemy.orm import mapper
|
||||
@@ -24,8 +24,8 @@ from eos.db import saveddata_meta
|
||||
from eos.types import Skill
|
||||
|
||||
skills_table = Table("characterSkills", saveddata_meta,
|
||||
Column("characterID", ForeignKey("characters.ID"), primary_key = True, index = True),
|
||||
Column("itemID", Integer, primary_key = True),
|
||||
Column("_Skill__level", Integer, nullable = True))
|
||||
Column("characterID", ForeignKey("characters.ID"), primary_key=True, index=True),
|
||||
Column("itemID", Integer, primary_key=True),
|
||||
Column("_Skill__level", Integer, nullable=True))
|
||||
|
||||
mapper(Skill, skills_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2014 Ryan Holmes
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, Float, ForeignKey, String
|
||||
from sqlalchemy.orm import mapper
|
||||
@@ -24,12 +24,12 @@ from eos.db import saveddata_meta
|
||||
from eos.types import TargetResists
|
||||
|
||||
targetResists_table = Table("targetResists", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("name", String),
|
||||
Column("emAmount", Float),
|
||||
Column("thermalAmount", Float),
|
||||
Column("kineticAmount", Float),
|
||||
Column("explosiveAmount", Float),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable=True))
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("name", String),
|
||||
Column("emAmount", Float),
|
||||
Column("thermalAmount", Float),
|
||||
Column("kineticAmount", Float),
|
||||
Column("explosiveAmount", Float),
|
||||
Column("ownerID", ForeignKey("users.ID"), nullable=True))
|
||||
|
||||
mapper(TargetResists, targetResists_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy import Table, Column, Integer, String, Boolean
|
||||
from sqlalchemy.orm import mapper
|
||||
@@ -24,9 +24,9 @@ from eos.db import saveddata_meta
|
||||
from eos.types import User
|
||||
|
||||
users_table = Table("users", saveddata_meta,
|
||||
Column("ID", Integer, primary_key = True),
|
||||
Column("username", String, nullable = False, unique = True),
|
||||
Column("password", String, nullable = False),
|
||||
Column("admin", Boolean, nullable = False))
|
||||
Column("ID", Integer, primary_key=True),
|
||||
Column("username", String, nullable=False, unique=True),
|
||||
Column("password", String, nullable=False),
|
||||
Column("admin", Boolean, nullable=False))
|
||||
|
||||
mapper(User, users_table)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,7 +15,7 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
from sqlalchemy.orm import eagerload
|
||||
from sqlalchemy.sql import and_
|
||||
@@ -31,8 +31,9 @@ replace = {"attributes": "_Item__attributes",
|
||||
"damagePattern": "_Fit__damagePattern",
|
||||
"projectedFits": "_Fit__projectedFits"}
|
||||
|
||||
|
||||
def processEager(eager):
|
||||
if eager == None:
|
||||
if eager is None:
|
||||
return tuple()
|
||||
else:
|
||||
l = []
|
||||
@@ -44,6 +45,7 @@ def processEager(eager):
|
||||
|
||||
return l
|
||||
|
||||
|
||||
def _replacements(eagerString):
|
||||
splitEager = eagerString.split(".")
|
||||
for i in xrange(len(splitEager)):
|
||||
@@ -54,6 +56,7 @@ def _replacements(eagerString):
|
||||
|
||||
return ".".join(splitEager)
|
||||
|
||||
|
||||
def processWhere(clause, where):
|
||||
if where is not None:
|
||||
if not hasattr(where, "__iter__"):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
@@ -15,10 +15,15 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
# from sqlalchemy.orm.attributes import flag_modified
|
||||
import logging
|
||||
|
||||
import eos.db
|
||||
import eos.types
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HandledList(list):
|
||||
def filteredItemPreAssign(self, filter, *args, **kwargs):
|
||||
@@ -101,6 +106,15 @@ class HandledList(list):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def remove(self, thing):
|
||||
# We must flag it as modified, otherwise it not be removed from the database
|
||||
# @todo: flag_modified isn't in os x skel. need to rebuild to include
|
||||
# flag_modified(thing, "itemID")
|
||||
if thing.isInvalid: # see GH issue #324
|
||||
thing.itemID = 0
|
||||
list.remove(self, thing)
|
||||
|
||||
|
||||
class HandledModuleList(HandledList):
|
||||
def append(self, mod):
|
||||
emptyPosition = float("Inf")
|
||||
@@ -115,10 +129,19 @@ class HandledModuleList(HandledList):
|
||||
del self[emptyPosition]
|
||||
mod.position = emptyPosition
|
||||
HandledList.insert(self, emptyPosition, mod)
|
||||
if mod.isInvalid:
|
||||
self.remove(mod)
|
||||
return
|
||||
|
||||
mod.position = len(self)
|
||||
HandledList.append(self, mod)
|
||||
if mod.isInvalid:
|
||||
self.remove(mod)
|
||||
return
|
||||
|
||||
# fix for #529, where a module may be in incorrect state after CCP changes mechanics of module
|
||||
if not mod.isValidState(mod.state):
|
||||
mod.state = eos.types.State.ONLINE
|
||||
|
||||
def insert(self, index, mod):
|
||||
mod.position = index
|
||||
@@ -143,139 +166,88 @@ class HandledModuleList(HandledList):
|
||||
dummy.position = index
|
||||
self[index] = dummy
|
||||
|
||||
def toModule(self, index, mod):
|
||||
mod.position = index
|
||||
self[index] = mod
|
||||
|
||||
def freeSlot(self, slot):
|
||||
for i in range(len(self) -1, -1, -1):
|
||||
for i in range(len(self)):
|
||||
mod = self[i]
|
||||
if mod.getModifiedItemAttr("subSystemSlot") == slot:
|
||||
del self[i]
|
||||
self.toDummy(i)
|
||||
break
|
||||
|
||||
class HandledDroneList(HandledList):
|
||||
|
||||
class HandledDroneCargoList(HandledList):
|
||||
def find(self, item):
|
||||
for d in self:
|
||||
if d.item == item:
|
||||
yield d
|
||||
for o in self:
|
||||
if o.item == item:
|
||||
yield o
|
||||
|
||||
def findFirst(self, item):
|
||||
for d in self.find(item):
|
||||
return d
|
||||
for o in self.find(item):
|
||||
return o
|
||||
|
||||
def append(self, drone):
|
||||
list.append(self, drone)
|
||||
def append(self, thing):
|
||||
HandledList.append(self, thing)
|
||||
|
||||
def remove(self, drone):
|
||||
HandledList.remove(self, drone)
|
||||
if thing.isInvalid:
|
||||
self.remove(thing)
|
||||
|
||||
def appendItem(self, item, amount = 1):
|
||||
if amount < 1: ValueError("Amount of drones to add should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
|
||||
if d is None:
|
||||
d = eos.types.Drone(item)
|
||||
self.append(d)
|
||||
|
||||
d.amount += amount
|
||||
return d
|
||||
|
||||
def removeItem(self, item, amount):
|
||||
if amount < 1: ValueError("Amount of drones to remove should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
if d is None: return
|
||||
d.amount -= amount
|
||||
if d.amount <= 0:
|
||||
self.remove(d)
|
||||
return None
|
||||
|
||||
return d
|
||||
|
||||
class HandledCargoList(HandledList):
|
||||
# shameless copy of HandledDroneList
|
||||
# I have no idea what this does, but I needed it
|
||||
# @todo: investigate this
|
||||
def find(self, item):
|
||||
for d in self:
|
||||
if d.item == item:
|
||||
yield d
|
||||
|
||||
def findFirst(self, item):
|
||||
for d in self.find(item):
|
||||
return d
|
||||
|
||||
def append(self, cargo):
|
||||
list.append(self, cargo)
|
||||
|
||||
def remove(self, cargo):
|
||||
HandledList.remove(self, cargo)
|
||||
|
||||
def appendItem(self, item, qty = 1):
|
||||
if qty < 1: ValueError("Amount of cargo to add should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
|
||||
if d is None:
|
||||
d = eos.types.Cargo(item)
|
||||
self.append(d)
|
||||
|
||||
d.qty += qty
|
||||
return d
|
||||
|
||||
def removeItem(self, item, qty):
|
||||
if qty < 1: ValueError("Amount of cargo to remove should be >= 1")
|
||||
d = self.findFirst(item)
|
||||
if d is None: return
|
||||
d.qty -= qty
|
||||
if d.qty <= 0:
|
||||
self.remove(d)
|
||||
return None
|
||||
|
||||
return d
|
||||
|
||||
class HandledImplantBoosterList(HandledList):
|
||||
def __init__(self):
|
||||
self.__slotCache = {}
|
||||
def append(self, thing):
|
||||
if thing.isInvalid:
|
||||
HandledList.append(self, thing)
|
||||
self.remove(thing)
|
||||
return
|
||||
|
||||
def append(self, implant):
|
||||
if self.__slotCache.has_key(implant.slot):
|
||||
raise ValueError("Implant/Booster slot already in use, remove the old one first or set replace = True")
|
||||
self.__slotCache[implant.slot] = implant
|
||||
HandledList.append(self, implant)
|
||||
# if needed, remove booster that was occupying slot
|
||||
oldObj = next((m for m in self if m.slot == thing.slot), None)
|
||||
if oldObj:
|
||||
logging.info("Slot %d occupied with %s, replacing with %s", thing.slot, oldObj.item.name, thing.item.name)
|
||||
oldObj.itemID = 0 # hack to remove from DB. See GH issue #324
|
||||
self.remove(oldObj)
|
||||
|
||||
def remove(self, implant):
|
||||
HandledList.remove(self, implant)
|
||||
del self.__slotCache[implant.slot]
|
||||
# While we deleted this implant, in edge case seems like not all references
|
||||
# to it are removed and object still lives in session; forcibly remove it,
|
||||
# or otherwise when adding the same booster twice booster's table (typeID, fitID)
|
||||
# constraint will report database integrity error
|
||||
# TODO: make a proper fix, probably by adjusting fit-boosters sqlalchemy relationships
|
||||
eos.db.remove(implant)
|
||||
HandledList.append(self, thing)
|
||||
|
||||
def freeSlot(self, slot):
|
||||
if hasattr(slot, "slot"):
|
||||
slot = slot.slot
|
||||
|
||||
try:
|
||||
implant = self.__slotCache[slot]
|
||||
except KeyError:
|
||||
return False
|
||||
try:
|
||||
self.remove(implant)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
class HandledProjectedModList(HandledList):
|
||||
def append(self, proj):
|
||||
if proj.isInvalid:
|
||||
# we must include it before we remove it. doing it this way ensures
|
||||
# rows and relationships in database are removed as well
|
||||
HandledList.append(self, proj)
|
||||
self.remove(proj)
|
||||
return
|
||||
|
||||
proj.projected = True
|
||||
isSystemEffect = proj.item.group.name == "Effect Beacon"
|
||||
|
||||
if isSystemEffect:
|
||||
# remove other system effects - only 1 per fit plz
|
||||
oldEffect = next((m for m in self if m.item.group.name == "Effect Beacon"), None)
|
||||
|
||||
if oldEffect:
|
||||
logging.info("System effect occupied with %s, replacing with %s", oldEffect.item.name, proj.item.name)
|
||||
self.remove(oldEffect)
|
||||
|
||||
HandledList.append(self, proj)
|
||||
|
||||
# Remove non-projectable modules
|
||||
if not proj.item.isType("projected") and not isSystemEffect:
|
||||
self.remove(proj)
|
||||
|
||||
|
||||
class HandledProjectedDroneList(HandledDroneCargoList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
HandledList.append(self, proj)
|
||||
|
||||
class HandledProjectedDroneList(HandledDroneList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
list.append(self, proj)
|
||||
# Remove invalid or non-projectable drones
|
||||
if proj.isInvalid or not proj.item.isType("projected"):
|
||||
self.remove(proj)
|
||||
|
||||
class HandledProjectedFitList(HandledList):
|
||||
def append(self, proj):
|
||||
proj.projected = True
|
||||
list.append(self, proj)
|
||||
|
||||
class HandledItem(object):
|
||||
def preAssignItemAttr(self, *args, **kwargs):
|
||||
@@ -293,6 +265,7 @@ class HandledItem(object):
|
||||
def forceItemAttr(self, *args, **kwargs):
|
||||
self.itemModifiedAttributes.force(*args, **kwargs)
|
||||
|
||||
|
||||
class HandledCharge(object):
|
||||
def preAssignChargeAttr(self, *args, **kwargs):
|
||||
self.chargeModifiedAttributes.preAssign(*args, **kwargs)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
# 2010 Anton Vorobyov
|
||||
#
|
||||
@@ -16,4 +16,4 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
#===============================================================================
|
||||
# ===============================================================================
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Used by:
|
||||
# Modules named like: Dynamic Fuel Valve (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"capacitorNeed", container.getModifiedItemAttr("capNeedBonus"))
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
# Implant: Zor's Custom Navigation Hyper-Link
|
||||
# Skill: Acceleration Control
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Used by:
|
||||
# Implants named like: Eifyr and Co. 'Rogue' Acceleration Control AC (6 of 6)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Propulsion Module",
|
||||
"speedFactor", implant.getModifiedItemAttr("speedFBonus"))
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
# Implant: Poteque 'Prospector' Archaeology AC-905
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda module: module.item.requiresSkill("Archaeology"),
|
||||
"accessDifficultyBonus",
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
# Implant: Poteque 'Prospector' Hacking HC-905
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
fit.modules.filteredItemIncrease(lambda c: c.item.requiresSkill("Hacking"),
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
"accessDifficultyBonus",
|
||||
container.getModifiedItemAttr("accessDifficultyBonusModifier"), position="post")
|
||||
|
||||
@@ -2,9 +2,120 @@
|
||||
#
|
||||
# Used by:
|
||||
# Module: Reactive Armor Hardener
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
runTime = "late"
|
||||
type = "active"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
for type in ("kinetic", "thermal", "explosive", "em"):
|
||||
attr = "armor%sDamageResonance" % type.capitalize()
|
||||
fit.ship.multiplyItemAttr(attr, module.getModifiedItemAttr(attr),
|
||||
stackingPenalties=True, penaltyGroup="preMul")
|
||||
damagePattern = fit.damagePattern
|
||||
|
||||
# Skip if there is no damage pattern. Example: projected ships or fleet boosters
|
||||
if damagePattern:
|
||||
# logger.debug("Damage Pattern: %f/%f/%f/%f", damagePattern.emAmount, damagePattern.thermalAmount, damagePattern.kineticAmount, damagePattern.explosiveAmount)
|
||||
# logger.debug("Original Armor Resists: %f/%f/%f/%f", fit.ship.getModifiedItemAttr('armorEmDamageResonance'), fit.ship.getModifiedItemAttr('armorThermalDamageResonance'), fit.ship.getModifiedItemAttr('armorKineticDamageResonance'), fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'))
|
||||
|
||||
# Populate a tuple with the damage profile modified by current armor resists.
|
||||
baseDamageTaken = (
|
||||
damagePattern.emAmount * fit.ship.getModifiedItemAttr('armorEmDamageResonance'),
|
||||
damagePattern.thermalAmount * fit.ship.getModifiedItemAttr('armorThermalDamageResonance'),
|
||||
damagePattern.kineticAmount * fit.ship.getModifiedItemAttr('armorKineticDamageResonance'),
|
||||
damagePattern.explosiveAmount * fit.ship.getModifiedItemAttr('armorExplosiveDamageResonance'),
|
||||
)
|
||||
# logger.debug("Damage Adjusted for Armor Resists: %f/%f/%f/%f", baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])
|
||||
|
||||
resistanceShiftAmount = module.getModifiedItemAttr(
|
||||
'resistanceShiftAmount') / 100 # The attribute is in percent and we want a fraction
|
||||
RAHResistance = [
|
||||
module.getModifiedItemAttr('armorEmDamageResonance'),
|
||||
module.getModifiedItemAttr('armorThermalDamageResonance'),
|
||||
module.getModifiedItemAttr('armorKineticDamageResonance'),
|
||||
module.getModifiedItemAttr('armorExplosiveDamageResonance'),
|
||||
]
|
||||
|
||||
# Simulate RAH cycles until the RAH either stops changing or enters a loop.
|
||||
# The number of iterations is limited to prevent an infinite loop if something goes wrong.
|
||||
cycleList = []
|
||||
loopStart = -20
|
||||
for num in range(50):
|
||||
# logger.debug("Starting cycle %d.", num)
|
||||
# The strange order is to emulate the ingame sorting when different types have taken the same amount of damage.
|
||||
# This doesn't take into account stacking penalties. In a few cases fitting a Damage Control causes an inaccurate result.
|
||||
damagePattern_tuples = [
|
||||
(0, baseDamageTaken[0] * RAHResistance[0], RAHResistance[0]),
|
||||
(3, baseDamageTaken[3] * RAHResistance[3], RAHResistance[3]),
|
||||
(2, baseDamageTaken[2] * RAHResistance[2], RAHResistance[2]),
|
||||
(1, baseDamageTaken[1] * RAHResistance[1], RAHResistance[1]),
|
||||
]
|
||||
# logger.debug("Damage taken this cycle: %f/%f/%f/%f", damagePattern_tuples[0][1], damagePattern_tuples[3][1], damagePattern_tuples[2][1], damagePattern_tuples[1][1])
|
||||
|
||||
# Sort the tuple to drop the highest damage value to the bottom
|
||||
sortedDamagePattern_tuples = sorted(damagePattern_tuples, key=lambda damagePattern: damagePattern[1])
|
||||
|
||||
if sortedDamagePattern_tuples[2][1] == 0:
|
||||
# One damage type: the top damage type takes from the other three
|
||||
# Since the resistances not taking damage will end up going to the type taking damage we just do the whole thing at once.
|
||||
change0 = 1 - sortedDamagePattern_tuples[0][2]
|
||||
change1 = 1 - sortedDamagePattern_tuples[1][2]
|
||||
change2 = 1 - sortedDamagePattern_tuples[2][2]
|
||||
change3 = -(change0 + change1 + change2)
|
||||
elif sortedDamagePattern_tuples[1][1] == 0:
|
||||
# Two damage types: the top two damage types take from the other two
|
||||
# Since the resistances not taking damage will end up going equally to the types taking damage we just do the whole thing at once.
|
||||
change0 = 1 - sortedDamagePattern_tuples[0][2]
|
||||
change1 = 1 - sortedDamagePattern_tuples[1][2]
|
||||
change2 = -(change0 + change1) / 2
|
||||
change3 = -(change0 + change1) / 2
|
||||
else:
|
||||
# Three or four damage types: the top two damage types take from the other two
|
||||
change0 = min(resistanceShiftAmount, 1 - sortedDamagePattern_tuples[0][2])
|
||||
change1 = min(resistanceShiftAmount, 1 - sortedDamagePattern_tuples[1][2])
|
||||
change2 = -(change0 + change1) / 2
|
||||
change3 = -(change0 + change1) / 2
|
||||
|
||||
RAHResistance[sortedDamagePattern_tuples[0][0]] = sortedDamagePattern_tuples[0][2] + change0
|
||||
RAHResistance[sortedDamagePattern_tuples[1][0]] = sortedDamagePattern_tuples[1][2] + change1
|
||||
RAHResistance[sortedDamagePattern_tuples[2][0]] = sortedDamagePattern_tuples[2][2] + change2
|
||||
RAHResistance[sortedDamagePattern_tuples[3][0]] = sortedDamagePattern_tuples[3][2] + change3
|
||||
# logger.debug("Resistances shifted to %f/%f/%f/%f", RAHResistance[0], RAHResistance[1], RAHResistance[2], RAHResistance[3])
|
||||
|
||||
# See if the current RAH profile has been encountered before, indicating a loop.
|
||||
for i, val in enumerate(cycleList):
|
||||
tolerance = 1e-06
|
||||
if abs(RAHResistance[0] - val[0]) <= tolerance and \
|
||||
abs(RAHResistance[1] - val[1]) <= tolerance and \
|
||||
abs(RAHResistance[2] - val[2]) <= tolerance and \
|
||||
abs(RAHResistance[3] - val[3]) <= tolerance:
|
||||
loopStart = i
|
||||
# logger.debug("Loop found: %d-%d", loopStart, num)
|
||||
break
|
||||
if loopStart >= 0:
|
||||
break
|
||||
|
||||
cycleList.append(list(RAHResistance))
|
||||
|
||||
if loopStart < 0:
|
||||
logger.error("Reactive Armor Hardener failed to find equilibrium. Damage profile after armor: %f/%f/%f/%f",
|
||||
baseDamageTaken[0], baseDamageTaken[1], baseDamageTaken[2], baseDamageTaken[3])
|
||||
|
||||
# Average the profiles in the RAH loop, or the last 20 if it didn't find a loop.
|
||||
loopCycles = cycleList[loopStart:]
|
||||
numCycles = len(loopCycles)
|
||||
average = [0, 0, 0, 0]
|
||||
for cycle in loopCycles:
|
||||
for i in range(4):
|
||||
average[i] += cycle[i]
|
||||
|
||||
for i in range(4):
|
||||
average[i] = round(average[i] / numCycles, 3)
|
||||
|
||||
# Set the new resistances
|
||||
# logger.debug("Setting new resist profile: %f/%f/%f/%f", average[0], average[1], average[2],average[3])
|
||||
for i, attr in enumerate((
|
||||
'armorEmDamageResonance', 'armorThermalDamageResonance', 'armorKineticDamageResonance',
|
||||
'armorExplosiveDamageResonance')):
|
||||
module.increaseItemAttr(attr, average[i] - module.getModifiedItemAttr(attr))
|
||||
fit.ship.multiplyItemAttr(attr, average[i], stackingPenalties=True, penaltyGroup="preMul")
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#
|
||||
# Used by:
|
||||
# Modules from group: Missile Launcher Bomb (2 of 2)
|
||||
# Modules from group: Shield Extender (25 of 25)
|
||||
# Modules from group: Shield Extender (33 of 33)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))
|
||||
fit.ship.increaseItemAttr("signatureRadius", module.getModifiedItemAttr("signatureRadiusAdd"))
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# advancedDroneInterfacingMaxGroupDCUSkillLevel
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Advanced Drone Interfacing
|
||||
type = "passive"
|
||||
def handler(fit, skill, context):
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.group.name == "Drone Control Unit",
|
||||
"maxGroupActive", skill.level)
|
||||
@@ -5,7 +5,9 @@
|
||||
# Implant: Zor's Custom Navigation Link
|
||||
# Skill: Afterburner
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Afterburner"),
|
||||
"duration", container.getModifiedItemAttr("durationBonus") * level)
|
||||
"duration", container.getModifiedItemAttr("durationBonus") * level)
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
# Modules from group: Nanofiber Internal Structure (7 of 7)
|
||||
# Modules from group: Reinforced Bulkhead (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility",
|
||||
module.getModifiedItemAttr("agilityMultiplier"),
|
||||
stackingPenalties = True)
|
||||
stackingPenalties=True)
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
# Used by:
|
||||
# Modules named like: Polycarbon Engine Housing (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.boostItemAttr("agility", module.getModifiedItemAttr("agilityMultiplier"), stackingPenalties = True)
|
||||
fit.ship.boostItemAttr("agility", module.getModifiedItemAttr("agilityMultiplier"), stackingPenalties=True)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# ammoFallofMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Advanced Artillery Ammo (6 of 6)
|
||||
# Charges from group: Advanced Autocannon Ammo (6 of 6)
|
||||
# Charges from group: Advanced Beam Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Blaster Charge (6 of 6)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Railgun Charge (6 of 6)
|
||||
# Charges from group: Advanced Artillery Ammo (8 of 8)
|
||||
# Charges from group: Advanced Autocannon Ammo (8 of 8)
|
||||
# Charges from group: Advanced Beam Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Blaster Charge (8 of 8)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Railgun Charge (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("falloff", module.getModifiedChargeAttr("fallofMultiplier") or 1)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# ammoInfluenceCapNeed
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (458 of 829)
|
||||
# Items from category: Charge (465 of 899)
|
||||
# Charges from group: Frequency Crystal (185 of 185)
|
||||
# Charges from group: Hybrid Charge (209 of 209)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
# Dirty hack to work around cap charges setting cap booster
|
||||
# injection amount to zero
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# ammoInfluenceRange
|
||||
#
|
||||
# Used by:
|
||||
# Items from category: Charge (559 of 829)
|
||||
# Items from category: Charge (571 of 899)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))
|
||||
module.multiplyItemAttr("maxRange", module.getModifiedChargeAttr("weaponRangeMultiplier"))
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# ammoSpeedMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Festival Charges (8 of 8)
|
||||
# Charges from group: Festival Charges (9 of 9)
|
||||
# Charges from group: Interdiction Probe (2 of 2)
|
||||
# Charges from group: Survey Probe (3 of 3)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("speed", module.getModifiedChargeAttr("speedMultiplier") or 1)
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# ammoTrackingMultiplier
|
||||
#
|
||||
# Used by:
|
||||
# Charges from group: Advanced Artillery Ammo (6 of 6)
|
||||
# Charges from group: Advanced Autocannon Ammo (6 of 6)
|
||||
# Charges from group: Advanced Beam Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Blaster Charge (6 of 6)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (6 of 6)
|
||||
# Charges from group: Advanced Railgun Charge (6 of 6)
|
||||
# Charges from group: Advanced Artillery Ammo (8 of 8)
|
||||
# Charges from group: Advanced Autocannon Ammo (8 of 8)
|
||||
# Charges from group: Advanced Beam Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Blaster Charge (8 of 8)
|
||||
# Charges from group: Advanced Pulse Laser Crystal (8 of 8)
|
||||
# Charges from group: Advanced Railgun Charge (8 of 8)
|
||||
# Charges from group: Projectile Ammo (129 of 129)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
module.multiplyItemAttr("trackingSpeed", module.getModifiedChargeAttr("trackingSpeedMultiplier"))
|
||||
module.multiplyItemAttr("trackingSpeed", module.getModifiedChargeAttr("trackingSpeedMultiplier"))
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
# Implants named like: grade Halo (18 of 18)
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.implants.filteredItemMultiply(
|
||||
lambda implant: "signatureRadiusBonus" in implant.itemModifiedAttributes and "implantSetAngel" in implant.itemModifiedAttributes,
|
||||
fit.appliedImplants.filteredItemMultiply(
|
||||
lambda implant: "signatureRadiusBonus" in implant.itemModifiedAttributes and
|
||||
"implantSetAngel" in implant.itemModifiedAttributes,
|
||||
"signatureRadiusBonus",
|
||||
implant.getModifiedItemAttr("implantSetAngel"))
|
||||
implant.getModifiedItemAttr("implantSetAngel"))
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
# Used by:
|
||||
# Modules from group: Warp Core Stabilizer (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, module, context):
|
||||
fit.ship.increaseItemAttr("warmScrambleStatus", module.getModifiedItemAttr("warpScrambleStrength"))
|
||||
fit.ship.increaseItemAttr("warmScrambleStatus", module.getModifiedItemAttr("warpScrambleStrength"))
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
# Implant: Poteque 'Prospector' Environmental Analysis EY-1005
|
||||
# Skill: Archaeology
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, container, context):
|
||||
level = container.level if "skill" in context else 1
|
||||
fit.modules.filteredItemIncrease(lambda mod: mod.item.requiresSkill("Archaeology"),
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
#
|
||||
# Used by:
|
||||
# Implants named like: Exile Booster (4 of 4)
|
||||
# Implant: Antipharmakon Kosybo
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, booster, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Repair Systems") or mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", booster.getModifiedItemAttr("armorDamageAmountBonus"))
|
||||
fit.modules.filteredItemBoost(
|
||||
lambda mod: mod.item.requiresSkill("Repair Systems") or mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", booster.getModifiedItemAttr("armorDamageAmountBonus"))
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
# Used by:
|
||||
# Modules named like: Auxiliary Nano Pump (8 of 8)
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Capital Repair Systems"),
|
||||
"armorDamageAmount", implant.getModifiedItemAttr("repairBonus"),
|
||||
stackingPenalties = True)
|
||||
stackingPenalties=True)
|
||||
|
||||
11
eos/effects/armoredcommanddurationbonus.py
Normal file
11
eos/effects/armoredcommanddurationbonus.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# armoredCommandDurationBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armored Command
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
lvl = src.level
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "buffDuration",
|
||||
src.getModifiedItemAttr("durationBonus") * lvl)
|
||||
20
eos/effects/armoredcommandmindlink.py
Normal file
20
eos/effects/armoredcommandmindlink.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# armoredCommandMindlink
|
||||
#
|
||||
# Used by:
|
||||
# Implant: Armored Command Mindlink
|
||||
# Implant: Federation Navy Command Mindlink
|
||||
# Implant: Imperial Navy Command Mindlink
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff2Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff1Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff4Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff3Multiplier",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "buffDuration",
|
||||
src.getModifiedItemAttr("mindlinkBonus"))
|
||||
17
eos/effects/armoredcommandstrengthbonus.py
Normal file
17
eos/effects/armoredcommandstrengthbonus.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# armoredCommandStrengthBonus
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armored Command Specialist
|
||||
type = "passive"
|
||||
|
||||
|
||||
def handler(fit, src, context):
|
||||
lvl = src.level
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff1Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff2Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff4Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
fit.modules.filteredChargeBoost(lambda mod: mod.item.requiresSkill("Armored Command"), "warfareBuff3Multiplier",
|
||||
src.getModifiedItemAttr("commandStrengthBonus") * lvl)
|
||||
@@ -1,9 +0,0 @@
|
||||
# armoredSquadronCommand
|
||||
#
|
||||
# Used by:
|
||||
# Skill: Armored Warfare Specialist
|
||||
runTime = "early"
|
||||
type = "passive"
|
||||
def handler(fit, skill, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"),
|
||||
"commandBonus", skill.getModifiedItemAttr("squadronCommandBonus") * skill.level)
|
||||
@@ -1,10 +0,0 @@
|
||||
# armoredWarfareMindlink
|
||||
#
|
||||
# Used by:
|
||||
# Implant: Armored Warfare Mindlink
|
||||
# Implant: Federation Navy Warfare Mindlink
|
||||
# Implant: Imperial Navy Warfare Mindlink
|
||||
type = "passive"
|
||||
def handler(fit, implant, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Armored Warfare Specialist"),
|
||||
"commandBonus", implant.getModifiedItemAttr("mindlinkBonus"))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user