Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
034429cd47 | ||
|
|
57867317cc | ||
|
|
c2e314b193 | ||
|
|
9d2af1de13 | ||
|
|
232823566b | ||
|
|
958f0f2a52 | ||
|
|
b34fef2147 | ||
|
|
fe661124fa | ||
|
|
457dcbcad5 | ||
|
|
c18ee70eba | ||
|
|
095ffc3d6a | ||
|
|
e8b91648b1 | ||
|
|
1b43f6ba99 | ||
|
|
fc5360363c | ||
|
|
47b3c3029e | ||
|
|
dea7f34ca3 | ||
|
|
1e5026ea4a | ||
|
|
98f568ff6a | ||
|
|
10a6f8371d | ||
|
|
0933aa6615 | ||
|
|
746592418d | ||
|
|
e2404b063c | ||
|
|
bae1301556 | ||
|
|
c2de4952ad | ||
|
|
cce61d8075 | ||
|
|
34a0388f45 | ||
|
|
9d62965fc3 | ||
|
|
892434e28f | ||
|
|
2597fe4bcd | ||
|
|
f85b4b36bd | ||
|
|
f777dafefc | ||
|
|
6ef65ccea3 | ||
|
|
974b27a313 | ||
|
|
5124d8abcd | ||
|
|
849bd356c0 | ||
|
|
6406486441 | ||
|
|
2993ada2e5 | ||
|
|
f083c18dd0 | ||
|
|
c7021c5689 | ||
|
|
815369805a | ||
|
|
d8feb5c3a8 | ||
|
|
cb101da8a8 | ||
|
|
71481f5971 | ||
|
|
817796ed3c | ||
|
|
ebb7618f2d | ||
|
|
9717f153cd | ||
|
|
afa0cfaeef | ||
|
|
298b89b227 | ||
|
|
3b94034767 | ||
|
|
444b4c21af | ||
|
|
3e9c828781 | ||
|
|
ca3a1fbe3f | ||
|
|
5f28b541e3 | ||
|
|
18edd349f2 | ||
|
|
f7c6a065c1 | ||
|
|
91d48eeadd | ||
|
|
21bafa1b7b | ||
|
|
38af2f2817 | ||
|
|
8faa1143e9 | ||
|
|
8f34ebbca4 | ||
|
|
1c03701e17 | ||
|
|
c8edd16eb3 | ||
|
|
b96ff2e239 | ||
|
|
a575da3005 | ||
|
|
3ca2dece3e | ||
|
|
191d6133b2 | ||
|
|
b15e73e3a8 | ||
|
|
9a6b8ab979 | ||
|
|
87786d41a7 | ||
|
|
ee7ffe7bc8 | ||
|
|
379a33375d | ||
|
|
bd3f5dea05 | ||
|
|
146d36234e | ||
|
|
f3edcb8077 | ||
|
|
9e492015ff | ||
|
|
d2977182d9 | ||
|
|
7d2d65bab8 | ||
|
|
415c3bd066 | ||
|
|
990ab1520c | ||
|
|
81cb1afeff | ||
|
|
dba5a0a2cd | ||
|
|
04cd205fee | ||
|
|
ec93d8e9ab | ||
|
|
56321d9e33 | ||
|
|
d39ab43e74 | ||
|
|
787d3ae6ea | ||
|
|
035f751bf1 | ||
|
|
43442ac829 | ||
|
|
da02a089b9 | ||
|
|
476d8e804a | ||
|
|
43e1d53d39 | ||
|
|
5372068830 | ||
|
|
025cec3687 | ||
|
|
c47c629a83 | ||
|
|
2b7907f8f7 | ||
|
|
903d4e4d95 | ||
|
|
8857b2baae | ||
|
|
f7bbb17f66 | ||
|
|
f407ffe4bb | ||
|
|
791a09daae | ||
|
|
9592c0b55f | ||
|
|
d9a34dc60e | ||
|
|
30e4e4e9b3 | ||
|
|
bd3ea9a8ec | ||
|
|
8131b69422 | ||
|
|
340d9c2666 | ||
|
|
2a169fac34 | ||
|
|
4819100ec6 | ||
|
|
f39a94cbe0 | ||
|
|
e61598f768 | ||
|
|
04ee3a0a44 | ||
|
|
8fa613f1e2 | ||
|
|
bdc240df08 | ||
|
|
7169e0d91a | ||
|
|
889ed7e191 | ||
|
|
1fb8dac805 | ||
|
|
9f71ac68b9 | ||
|
|
c1f3517a79 | ||
|
|
adb0af0f18 | ||
|
|
f79f1ffdc3 | ||
|
|
1c9b7463fc | ||
|
|
80741d66fc | ||
|
|
f02fb00e8c | ||
|
|
3d353cc3cf | ||
|
|
c54ceb944e | ||
|
|
37a2ba3566 | ||
|
|
caff7bb6d0 | ||
|
|
01c491aee0 | ||
|
|
fd408d6777 | ||
|
|
6d1ed1e56e | ||
|
|
46f9d605f7 | ||
|
|
a65ea42b81 | ||
|
|
40f8c6a915 | ||
|
|
4678359f36 | ||
|
|
f91bd63646 | ||
|
|
c1872262f5 | ||
|
|
082e112758 | ||
|
|
4cb7d50eb5 | ||
|
|
8c050add23 | ||
|
|
2610697d86 | ||
|
|
64f1de37ad | ||
|
|
58f6862279 | ||
|
|
b47f6fdb32 | ||
|
|
ce5a53d0ff | ||
|
|
6ee1fa13d3 | ||
|
|
196f780bb3 | ||
|
|
088d5a2941 | ||
|
|
47abdaed6f | ||
|
|
30f6055a69 | ||
|
|
9d4b750dfd | ||
|
|
d1308bc625 | ||
|
|
db40256bb4 | ||
|
|
70f1ebadfc | ||
|
|
43adaf85f5 | ||
|
|
8d5e78a510 | ||
|
|
9d6d893373 | ||
|
|
9840982aa2 | ||
|
|
8e216ebe46 | ||
|
|
889ae39e3b | ||
|
|
265eff98bf | ||
|
|
ef7d1dcfb3 | ||
|
|
607ebc0025 | ||
|
|
0f0bc9569d | ||
|
|
169e892678 | ||
|
|
fe249e2704 | ||
|
|
b8be5d5e38 | ||
|
|
77d6c93b90 | ||
|
|
4fedaf1cea | ||
|
|
b2220f885e | ||
|
|
3181f9c4e7 | ||
|
|
153d0d326d | ||
|
|
7f9b349de6 | ||
|
|
b3a50f2b27 | ||
|
|
fb49628375 | ||
|
|
394a74c3a0 | ||
|
|
370bf826c0 | ||
|
|
38ca1499e2 | ||
|
|
2deced699b | ||
|
|
6405af7ec7 | ||
|
|
fa2bdfca12 | ||
|
|
872e7ce704 | ||
|
|
110d3c1007 | ||
|
|
7a27b70c29 | ||
|
|
2ffe5a137c | ||
|
|
bf0246ec26 | ||
|
|
b71feca802 | ||
|
|
da1fbeeca4 | ||
|
|
53174db351 | ||
|
|
19d2ad4cb2 | ||
|
|
3325536bbc | ||
|
|
4220177b02 | ||
|
|
796aca21cf | ||
|
|
3510768786 | ||
|
|
6197642d5e | ||
|
|
b60f8bfd57 | ||
|
|
9437d16908 | ||
|
|
de9077e0d2 | ||
|
|
4a6e946809 | ||
|
|
935c578ef6 | ||
|
|
0e06ff52ba | ||
|
|
fa4590d8f6 | ||
|
|
5620b118f4 | ||
|
|
d53b31ca40 | ||
|
|
a4a5d53f66 | ||
|
|
9f4c8c9088 | ||
|
|
472172c504 | ||
|
|
bc08656806 | ||
|
|
bd6f1f3570 | ||
|
|
716b446272 | ||
|
|
96a9e5b938 | ||
|
|
83e31e6352 | ||
|
|
49d0dbe86d | ||
|
|
e141a7ca3f | ||
|
|
adad668157 | ||
|
|
267f23cad8 | ||
|
|
f605801555 | ||
|
|
19e81ff78a | ||
|
|
9232a95e00 | ||
|
|
6dcef6b199 | ||
|
|
e355bd10b1 | ||
|
|
ceb4ed52c0 | ||
|
|
227750efad | ||
|
|
8a76558f01 | ||
|
|
db7c865c76 | ||
|
|
8e35e0d6d9 | ||
|
|
c9d50f39b5 | ||
|
|
77ac893a7c | ||
|
|
ac60a436f1 | ||
|
|
2ba9f0f4c8 | ||
|
|
47c3aa4842 | ||
|
|
d2edf4b89d | ||
|
|
11a0c246dc | ||
|
|
cba93b3d55 | ||
|
|
fa9b6c6d97 | ||
|
|
bef48eca62 | ||
|
|
e42ff03c4b | ||
|
|
ec628e4a0d | ||
|
|
8865a48936 | ||
|
|
d3a9c3bd95 | ||
|
|
90bff59af3 | ||
|
|
9efe9860ae | ||
|
|
f6a418499b | ||
|
|
66740bcb8d | ||
|
|
035e257926 | ||
|
|
e63549158b | ||
|
|
7fb64e690f | ||
|
|
54798c30b1 | ||
|
|
4c0f7b61e4 | ||
|
|
206ac373d2 | ||
|
|
c626e84f7d | ||
|
|
90ec5fa80b | ||
|
|
d496b46b6f | ||
|
|
7af1fdcf6b | ||
|
|
199e156e53 | ||
|
|
f5578ee788 | ||
|
|
c0a3628b3b | ||
|
|
fa8922e0a6 | ||
|
|
bf6991ce06 | ||
|
|
7f49245f15 | ||
|
|
f55313e0cd | ||
|
|
69c388f243 | ||
|
|
35788657a8 | ||
|
|
d531698867 | ||
|
|
cc4177bf14 | ||
|
|
d377067441 | ||
|
|
b2f026c212 | ||
|
|
07cdb0788c | ||
|
|
01f919ddd3 | ||
|
|
4b1fda9680 | ||
|
|
79d03233ae | ||
|
|
522b40aff1 | ||
|
|
06c878dd2c | ||
|
|
f5c589373d | ||
|
|
2689568650 | ||
|
|
fabf649608 | ||
|
|
080af86e1b | ||
|
|
e5b58cd5ff | ||
|
|
3500389628 | ||
|
|
1129f0d60b | ||
|
|
b3a6a47a6a | ||
|
|
bdb3844bcc | ||
|
|
f0bb25efc1 | ||
|
|
bfd23db3ff | ||
|
|
9c63177f03 | ||
|
|
24b4e32f50 | ||
|
|
2e7bde8861 | ||
|
|
56c626e8a1 | ||
|
|
c12eb9f68a | ||
|
|
8bc94e7c10 | ||
|
|
e8e6161911 | ||
|
|
d4f6b1a003 | ||
|
|
6cafbc1ffe | ||
|
|
b3336289e8 | ||
|
|
3b92b43cb3 | ||
|
|
2f3dca8f4c | ||
|
|
0c76f76a5b | ||
|
|
d37e0390fb | ||
|
|
a185dbe644 | ||
|
|
5b9fb1ea00 | ||
|
|
5106b7c97d | ||
|
|
d88cb02d94 | ||
|
|
7fd128ac49 | ||
|
|
a637dca083 | ||
|
|
23a33c7722 | ||
|
|
918a0d73b9 | ||
|
|
ca9f991bcb | ||
|
|
2e9388d3c7 | ||
|
|
383196bdd3 | ||
|
|
e69e66f5f7 | ||
|
|
b9c5c3c931 | ||
|
|
edb9104d77 | ||
|
|
e0feb45f48 | ||
|
|
bc211822aa | ||
|
|
e33ae0f81b | ||
|
|
8467fb98d6 | ||
|
|
62cb2c7217 | ||
|
|
f2331261cf | ||
|
|
26ae7bcbdf | ||
|
|
291b93b7d7 | ||
|
|
73fccbb2bb | ||
|
|
7e92f8ac50 | ||
|
|
da767213cb | ||
|
|
d81eddba44 | ||
|
|
83599539b5 | ||
|
|
c145aa9499 | ||
|
|
ffeaba6a18 | ||
|
|
c68df74943 | ||
|
|
1c3e98678f | ||
|
|
b1a1e07f7d | ||
|
|
46f8c72bef | ||
|
|
a4f2902365 | ||
|
|
bcda936585 | ||
|
|
c16a5f1701 | ||
|
|
569f803ab2 | ||
|
|
7bd797cb3a | ||
|
|
1e875540fc | ||
|
|
bcde6907c8 | ||
|
|
a19c772bba | ||
|
|
24ca684db3 | ||
|
|
6fd8b83d39 | ||
|
|
3ecc87431a | ||
|
|
082e41bd76 | ||
|
|
6f0bfa6b22 | ||
|
|
bcb8669898 | ||
|
|
4bdb4f47fa | ||
|
|
a51cbc51de | ||
|
|
060d00ccc4 | ||
|
|
1ddc51f6c7 | ||
|
|
b222cbe41c | ||
|
|
53b4c0db69 | ||
|
|
ebaef28f06 | ||
|
|
0948b52957 | ||
|
|
bc51c59fe1 | ||
|
|
17a3d45e92 | ||
|
|
2fd8416887 | ||
|
|
46f11af717 | ||
|
|
c0670e9025 | ||
|
|
bc9cc4ba2a | ||
|
|
38ee4c6f12 | ||
|
|
72aa528db2 | ||
|
|
5d63b8c239 | ||
|
|
f78c1ea75f | ||
|
|
38989689f5 | ||
|
|
1e5094f3ff | ||
|
|
067178e94d | ||
|
|
58002958bf | ||
|
|
ca030688cb | ||
|
|
b883f5b9e2 | ||
|
|
85f815c538 | ||
|
|
b2ddd5f286 | ||
|
|
11bbcc7993 | ||
|
|
70f7b862e3 | ||
|
|
544eb92a6b | ||
|
|
7a123b68db | ||
|
|
b89925e86b | ||
|
|
fc1f3cdb55 | ||
|
|
19717aeb79 | ||
|
|
60a115b7d8 | ||
|
|
bc85b354a0 | ||
|
|
1b611fa7c4 | ||
|
|
34ba3ffdde | ||
|
|
af4d2dbfd0 | ||
|
|
0b12f65949 | ||
|
|
b8beb6e8be | ||
|
|
09ba8663e6 | ||
|
|
b7558c33da | ||
|
|
9174f3c9d0 | ||
|
|
2c8c04387b | ||
|
|
b1e5502b04 | ||
|
|
ddf2c2b2ac | ||
|
|
2a70602f7e | ||
|
|
c128d8ab0c | ||
|
|
0e57c37296 | ||
|
|
e0c0ec6fc3 | ||
|
|
31bb92c089 | ||
|
|
417385f231 | ||
|
|
62bfab0960 | ||
|
|
809f807da8 | ||
|
|
8f098d435a | ||
|
|
574b1eec92 | ||
|
|
7bd8629706 | ||
|
|
9d7c60e92d | ||
|
|
12cf05cb50 | ||
|
|
acd7162aa1 | ||
|
|
efbb8376ef | ||
|
|
bc4fa60f67 | ||
|
|
f13b0f2255 | ||
|
|
4ea8615fb5 | ||
|
|
7877eaa89b | ||
|
|
a8a50ac948 | ||
|
|
4206286c21 | ||
|
|
eec9a4c9e6 | ||
|
|
469ffa145a | ||
|
|
e1fdab42c0 | ||
|
|
39238a6491 | ||
|
|
fdc662fedf | ||
|
|
9d805f63d5 | ||
|
|
68273ea295 | ||
|
|
def5e4fa4f | ||
|
|
f3b1240990 | ||
|
|
8c25037cb8 | ||
|
|
31936d6e6c | ||
|
|
cc622ef189 | ||
|
|
6ef0448d9f | ||
|
|
01dc3137d8 | ||
|
|
543e963d1d | ||
|
|
c12a66eeab | ||
|
|
a9f2ba776a | ||
|
|
e7525006b5 | ||
|
|
ded71bf4f9 | ||
|
|
1b9cf8b604 | ||
|
|
01e7353ef4 | ||
|
|
73294af296 | ||
|
|
c3dc844167 | ||
|
|
1eaa276b76 | ||
|
|
2b37e08f19 | ||
|
|
de52b525fb | ||
|
|
8c39b6e3df | ||
|
|
75c6bf2b68 | ||
|
|
0308a10690 | ||
|
|
eab8bac68c | ||
|
|
19783ccbd6 | ||
|
|
10799e52ce | ||
|
|
92bb4af5ec | ||
|
|
846c2a4962 | ||
|
|
84300389f9 | ||
|
|
cb2846a256 | ||
|
|
9cfa2357b0 | ||
|
|
eaa67ba1fe | ||
|
|
d8a5f57787 | ||
|
|
13651650ab | ||
|
|
901f1bfe42 | ||
|
|
8bb5032ee4 | ||
|
|
bf59d127f9 | ||
|
|
4fb0aa3936 | ||
|
|
ed8a1c2f57 | ||
|
|
059358cff4 | ||
|
|
939acad30c | ||
|
|
4d09b3deb1 | ||
|
|
a5c4dad3d4 | ||
|
|
2cb5e4e173 | ||
|
|
708bcab2f3 | ||
|
|
2de077a3ab | ||
|
|
63084d1855 | ||
|
|
1575b803c0 | ||
|
|
afe041f969 | ||
|
|
9644692084 | ||
|
|
b52c3c6c68 | ||
|
|
0260fc6fbc | ||
|
|
73bd76bcdb | ||
|
|
2960f85671 | ||
|
|
34c742555d | ||
|
|
3b1066fade | ||
|
|
6753cedd33 | ||
|
|
2951ccdad5 | ||
|
|
93e405c370 | ||
|
|
016fe1c3d3 | ||
|
|
c816f7a923 | ||
|
|
43b6453fcb | ||
|
|
559fb30da9 | ||
|
|
273ab97d3f | ||
|
|
fcac511a28 | ||
|
|
b811be4284 | ||
|
|
1a19e56523 | ||
|
|
e5a235ba41 | ||
|
|
1448584f2f | ||
|
|
4433855047 | ||
|
|
02f63ee5f0 | ||
|
|
36f0299e51 | ||
|
|
170056cc55 | ||
|
|
a212d2142c | ||
|
|
d89575b25d | ||
|
|
8f9306a3db | ||
|
|
5f9e631011 | ||
|
|
b290c88c1d | ||
|
|
2e888525c6 | ||
|
|
d54c08dc4e | ||
|
|
821076ae59 | ||
|
|
13e11e4e09 | ||
|
|
0ab53a7825 | ||
|
|
15cb472189 | ||
|
|
39a6e2c38e | ||
|
|
7c6c0a2b81 | ||
|
|
3c63323814 | ||
|
|
44f00e042e | ||
|
|
3a99205194 | ||
|
|
c2e550e33d | ||
|
|
b01a03c6ce | ||
|
|
0251bfc842 | ||
|
|
89d4cadb61 | ||
|
|
e33fdffd99 | ||
|
|
082996b152 | ||
|
|
e9c3953085 | ||
|
|
9f2ced6bfd | ||
|
|
281549add3 | ||
|
|
91945a3b27 | ||
|
|
162c7c9e59 | ||
|
|
ba46a2b801 | ||
|
|
13af8688a3 | ||
|
|
fcf7c5c056 | ||
|
|
ab8c52bb75 | ||
|
|
08d4e301d2 | ||
|
|
428a0bbad5 | ||
|
|
4da4cf5259 | ||
|
|
72a24b2770 | ||
|
|
9141f3d63f | ||
|
|
c34edbd3ac | ||
|
|
eea2024549 | ||
|
|
ee74c5ea5b | ||
|
|
158ceca599 | ||
|
|
b8f3c3eece | ||
|
|
e835498e59 | ||
|
|
0250546ab5 | ||
|
|
f820d05082 | ||
|
|
9ba239caf0 | ||
|
|
51a59fe2d4 | ||
|
|
6753d8a073 | ||
|
|
46719cd32a | ||
|
|
47b8f75447 | ||
|
|
ea68c8e82c | ||
|
|
8d1745d47e | ||
|
|
aa93ae6918 | ||
|
|
66cb197b53 | ||
|
|
94cf7ebea8 | ||
|
|
5405da365b | ||
|
|
a0df425115 | ||
|
|
62cf1265f8 | ||
|
|
ba7e772e56 | ||
|
|
8f8c91e0b0 | ||
|
|
5bbe93bcec | ||
|
|
561b59d235 | ||
|
|
38870ca3f7 | ||
|
|
cbe7b42fb8 | ||
|
|
ad1ad80026 | ||
|
|
a6c3ac36ef | ||
|
|
a9e88f6943 | ||
|
|
77ac1453f3 | ||
|
|
e094267223 | ||
|
|
b03589f6f0 | ||
|
|
3486dde8c1 | ||
|
|
c08bf359f5 | ||
|
|
002d0d4bc0 | ||
|
|
7db02aa579 | ||
|
|
b47e6436e7 | ||
|
|
7b6e291a0a | ||
|
|
b8f6394d94 | ||
|
|
0b5c2e42fb | ||
|
|
fce5f19100 | ||
|
|
05ad24c8f5 | ||
|
|
5295aa37be | ||
|
|
3e12d6bb9d | ||
|
|
019514b699 | ||
|
|
a32ee2a344 | ||
|
|
ea480aa365 | ||
|
|
d70a980058 | ||
|
|
3157bc5e1b | ||
|
|
e72b703ab2 | ||
|
|
c1f3c0dc6b | ||
|
|
30f7db1bc2 | ||
|
|
07a147a043 | ||
|
|
9488602f5b | ||
|
|
a0c9895122 | ||
|
|
c1bd91a7f9 | ||
|
|
1d65ff3e0c | ||
|
|
f7fac5ad26 | ||
|
|
e45f055493 | ||
|
|
8946f115c0 | ||
|
|
86353dc1cf | ||
|
|
5168fb4098 | ||
|
|
c04192e15e | ||
|
|
638c2c73da | ||
|
|
f368769068 | ||
|
|
9f347fa1f2 | ||
|
|
b44f897528 | ||
|
|
efd1a80ee1 | ||
|
|
a70100c835 | ||
|
|
f51e365ec4 | ||
|
|
a5e0f33f02 | ||
|
|
dc85b49f9c | ||
|
|
72c90b3e92 | ||
|
|
df566709c8 | ||
|
|
3617e11792 | ||
|
|
b243b12d1c | ||
|
|
d0d28baee0 | ||
|
|
001b0c356f | ||
|
|
4984c522ba | ||
|
|
be64934eb4 | ||
|
|
7669c2d76b | ||
|
|
00244846cb | ||
|
|
480fda34ce | ||
|
|
103c1b4338 | ||
|
|
2acee91524 | ||
|
|
6f42e2835c | ||
|
|
e724069cbd | ||
|
|
417858f21a | ||
|
|
a362301515 | ||
|
|
86fd714923 | ||
|
|
871b746cce | ||
|
|
d12440f60a | ||
|
|
4bb78b2532 | ||
|
|
3cd23cd718 | ||
|
|
59abda933f | ||
|
|
47f5f86da1 | ||
|
|
6094875ffb | ||
|
|
0644c9a67f | ||
|
|
c91ab29a23 | ||
|
|
8f4e33fd5a | ||
|
|
8cf5012602 | ||
|
|
23a23e36bb | ||
|
|
0480445bae | ||
|
|
ae07b8de4c | ||
|
|
4c746cbb86 | ||
|
|
890a4d142b | ||
|
|
ff9bda29cf | ||
|
|
5ca9e29f3d | ||
|
|
c804a3d564 | ||
|
|
369ba08780 | ||
|
|
0692933148 | ||
|
|
26852981ba | ||
|
|
8199bd550d | ||
|
|
c56eaa258d | ||
|
|
d4e8ec125f | ||
|
|
3e3ed35fb0 | ||
|
|
3530e8d0f0 | ||
|
|
a1f6bbdf1f | ||
|
|
b053018958 | ||
|
|
5adc69977b | ||
|
|
a741cc305a | ||
|
|
96f5ad8b96 | ||
|
|
18dbb658ff | ||
|
|
512134162d | ||
|
|
7e1949ccc7 | ||
|
|
db0c4a1d71 | ||
|
|
1c64305678 | ||
|
|
95b8532660 | ||
|
|
9b3c7451b7 | ||
|
|
1911508552 | ||
|
|
f5ac301c7e | ||
|
|
e37b91c2e3 | ||
|
|
0a92dc0d2d | ||
|
|
754b16af10 | ||
|
|
b434bc4c78 | ||
|
|
dba2e2f170 | ||
|
|
312077a74a | ||
|
|
817d77a437 | ||
|
|
13b85e7164 | ||
|
|
352e174af2 | ||
|
|
aadcaedae5 | ||
|
|
40c69382a1 | ||
|
|
8f4ea5f2fd | ||
|
|
a11975adec | ||
|
|
578f6f4d0f | ||
|
|
ae267adf27 | ||
|
|
c76fc97922 | ||
|
|
730ad56677 | ||
|
|
80b161b9fc | ||
|
|
66016dedf0 | ||
|
|
7314f1d9b1 | ||
|
|
605edd547d | ||
|
|
864c29933a | ||
|
|
ff15a37e10 | ||
|
|
237f676af8 | ||
|
|
5e0e80e965 | ||
|
|
586cd84349 | ||
|
|
230b2df5fd | ||
|
|
033d361cea | ||
|
|
dbbde066f8 | ||
|
|
785e9650e5 | ||
|
|
0b697a94bd | ||
|
|
163c41f568 | ||
|
|
0582339332 | ||
|
|
062e6e9626 | ||
|
|
6dfb727fa2 | ||
|
|
d469f990f6 | ||
|
|
909474d4cb | ||
|
|
c9eee14b21 | ||
|
|
7fe35243db | ||
|
|
647c9240a5 | ||
|
|
fe0fdc0964 | ||
|
|
9dc4483d70 | ||
|
|
9ed2b79a4b | ||
|
|
28a9f9a849 | ||
|
|
5044a5be48 | ||
|
|
c4053b9ba8 | ||
|
|
53c00258ac | ||
|
|
99123b733d | ||
|
|
92c81d60db | ||
|
|
9218eb09d6 | ||
|
|
cae4836e17 | ||
|
|
172b410d82 | ||
|
|
371dcad568 | ||
|
|
32ee10445d | ||
|
|
f9d0659bd4 | ||
|
|
f6b4bb3923 | ||
|
|
9ccd183607 | ||
|
|
5e06a606ef | ||
|
|
2f6b186ea8 | ||
|
|
dd8875e951 | ||
|
|
232fc3140c | ||
|
|
8e6d2b9873 | ||
|
|
6239a72bce | ||
|
|
9e0c4ddb9a | ||
|
|
4a6b5e3aa9 | ||
|
|
a7d8f08522 | ||
|
|
6aa4686c30 | ||
|
|
f9ccb06d1f | ||
|
|
1f378137f1 | ||
|
|
7235291e69 | ||
|
|
1f39ecefe4 | ||
|
|
5a25f335cd | ||
|
|
88a6ab2d95 | ||
|
|
5208cf8678 | ||
|
|
857cba902a | ||
|
|
6753a72d97 | ||
|
|
14fb62bda4 | ||
|
|
21122c620b | ||
|
|
cb6ce4f183 | ||
|
|
884531700b | ||
|
|
6ca9e637dc | ||
|
|
0a4e696bc1 | ||
|
|
2cf0bda352 | ||
|
|
35d03c9e21 | ||
|
|
c10060decc | ||
|
|
d408df8b4c | ||
|
|
b3ecb1e9b9 | ||
|
|
9306773b5b | ||
|
|
1245fab7ae | ||
|
|
a6e8dd6632 | ||
|
|
56d8392f12 | ||
|
|
39e4bce254 | ||
|
|
b745ad2fa7 | ||
|
|
ff66d99fc6 | ||
|
|
f15bee34fb | ||
|
|
60164cfb78 | ||
|
|
d543e42268 | ||
|
|
9bd26ef3bf | ||
|
|
0d5b2aedc7 | ||
|
|
3ea872c6a4 | ||
|
|
e65582a432 | ||
|
|
88cc37a6af | ||
|
|
b40b7b2472 | ||
|
|
73f7e84192 | ||
|
|
c9d5b46ae8 | ||
|
|
d4e16048e9 | ||
|
|
daa549e650 | ||
|
|
fe562915cb | ||
|
|
fff42b61e1 | ||
|
|
90ee71c9ca | ||
|
|
a1c80c3d27 | ||
|
|
8b10f2cc4a | ||
|
|
28dde23115 | ||
|
|
b433129354 | ||
|
|
7e0fb82905 | ||
|
|
75bacd5586 | ||
|
|
21daf9f3bb | ||
|
|
fa625dc887 | ||
|
|
376b3f04e5 | ||
|
|
12ee9d381d | ||
|
|
b90938108a | ||
|
|
7b136e61a1 | ||
|
|
0f9f15b268 | ||
|
|
fdd8aac017 | ||
|
|
ce4f7a55b6 | ||
|
|
def75da1d8 | ||
|
|
2b81c71c5a | ||
|
|
436a519db8 | ||
|
|
c624136dc7 | ||
|
|
cd546b274f | ||
|
|
2f650af0f7 | ||
|
|
4ffb7cac7c | ||
|
|
6361b09129 | ||
|
|
cb87a3067c | ||
|
|
510eebd2f4 | ||
|
|
15a8e53e22 | ||
|
|
99fb44633e | ||
|
|
9a8c0399be | ||
|
|
3f264d6a49 | ||
|
|
818a6b38cb | ||
|
|
d60a102c0d | ||
|
|
0627f678ea | ||
|
|
4ad10deb00 | ||
|
|
f61725a021 | ||
|
|
6d2bb7b131 | ||
|
|
9db43db3cf | ||
|
|
7a22ce5af5 | ||
|
|
68239351b5 | ||
|
|
61eab0bca8 | ||
|
|
2aefe3f9e3 | ||
|
|
adb0bb2e69 | ||
|
|
b1a59aa871 | ||
|
|
0a19157dbb | ||
|
|
382a23b661 | ||
|
|
98107291f5 | ||
|
|
c6779a714b | ||
|
|
ef8f0fd72d | ||
|
|
634bd2ea07 | ||
|
|
f8f88ff8f2 | ||
|
|
8a2dc24f7e | ||
|
|
dcc3ab6e4e | ||
|
|
dabeab8612 | ||
|
|
66dbc5b2ed | ||
|
|
2e2ab9b2d9 | ||
|
|
662e0bb9ce | ||
|
|
3f40e94235 | ||
|
|
483b625f2d | ||
|
|
d18cf625d0 | ||
|
|
b42df81b48 | ||
|
|
536fed5448 | ||
|
|
dc01eff812 | ||
|
|
5471c7fa32 | ||
|
|
83e28b4dac | ||
|
|
af95897bde | ||
|
|
4c2f6bea25 | ||
|
|
fdf77a43cb | ||
|
|
f1855a569a | ||
|
|
a0434b6ed2 | ||
|
|
365c714213 | ||
|
|
875abf4d32 | ||
|
|
6b9bf76da2 | ||
|
|
610c75d274 | ||
|
|
81826d0549 | ||
|
|
8caf4069dc | ||
|
|
6c496e616d | ||
|
|
3d5dd54ec0 | ||
|
|
e7bfe81940 | ||
|
|
fb9c04c779 | ||
|
|
84a1af8100 | ||
|
|
b804e60bac | ||
|
|
604e751bf4 | ||
|
|
2ce083222e | ||
|
|
9a44b1fcfb | ||
|
|
9df47777d0 | ||
|
|
aa78bc4045 | ||
|
|
4bfe34ba53 | ||
|
|
ad0fc69596 | ||
|
|
cfe71e15a4 | ||
|
|
bf7a319770 | ||
|
|
cadc84b32f | ||
|
|
7bde92c7f1 | ||
|
|
965d36cdc5 | ||
|
|
f8ef0063e4 | ||
|
|
fb4e00afc4 | ||
|
|
6ed9a191b9 | ||
|
|
b503f4fa8f | ||
|
|
7020e5641f | ||
|
|
5b4601b671 | ||
|
|
3e952faad3 | ||
|
|
c51abc1c64 | ||
|
|
c7e2780d17 | ||
|
|
28e2139683 | ||
|
|
20c839394a | ||
|
|
c5e1a7d6ab | ||
|
|
579d7570af | ||
|
|
1d1d751d43 | ||
|
|
86664b5491 | ||
|
|
b7e9898163 | ||
|
|
d4c0b01343 | ||
|
|
af67126156 | ||
|
|
9930360405 | ||
|
|
4fb61d6dbd | ||
|
|
bcb7ca5c4c | ||
|
|
d1fb5da002 | ||
|
|
17935fbe89 | ||
|
|
48578407db | ||
|
|
bda0c4ef1b | ||
|
|
7ea5e444b3 | ||
|
|
bef362935a | ||
|
|
f3144be382 | ||
|
|
818ee1d447 | ||
|
|
67e45ada85 | ||
|
|
bdc7132337 | ||
|
|
c5214f8d89 | ||
|
|
2be4dbea7a | ||
|
|
b951c81bf5 | ||
|
|
8c221a1295 | ||
|
|
c41f721a96 | ||
|
|
6910f3c95e | ||
|
|
e23f898c5f | ||
|
|
3cf81afc4a | ||
|
|
ca463a0f0e | ||
|
|
a76572ebe3 | ||
|
|
1a92cbd951 | ||
|
|
54c5faf929 | ||
|
|
d1d9e9e4d1 | ||
|
|
5ca64f839e | ||
|
|
4e7cd6f681 | ||
|
|
ba9f593716 | ||
|
|
9d3d74c7c5 | ||
|
|
aae26523ff | ||
|
|
338a2a14bf | ||
|
|
1a66cab435 | ||
|
|
3363c9ab58 | ||
|
|
10f64902aa | ||
|
|
25e1f4caa4 | ||
|
|
222fa89422 | ||
|
|
750e145f03 | ||
|
|
3bbbbfa402 | ||
|
|
f728751fa9 | ||
|
|
f5425d0e54 | ||
|
|
debaaccf4c | ||
|
|
a3e20501af | ||
|
|
c87a75f3fd | ||
|
|
55729c5eda | ||
|
|
06cbcc2339 | ||
|
|
1afe860e76 | ||
|
|
c0ac935652 | ||
|
|
7c76b0f5a5 | ||
|
|
42091c54b7 | ||
|
|
396b48d017 | ||
|
|
5bf83da726 | ||
|
|
bb1c0c7625 | ||
|
|
1170676141 | ||
|
|
7baaaa9db9 | ||
|
|
c1ecef0179 | ||
|
|
393da234e4 | ||
|
|
032d98e6bd | ||
|
|
f4a90cd531 | ||
|
|
82f03583fe | ||
|
|
81c1a50052 | ||
|
|
c7207799e2 | ||
|
|
e0a719ee93 | ||
|
|
ee6d2e7d82 | ||
|
|
14710b5218 | ||
|
|
4b5e0d1c1c | ||
|
|
9968e8346c | ||
|
|
bc4da17f10 | ||
|
|
da56c563fc | ||
|
|
95f4dbf6a0 | ||
|
|
6c36f343ea | ||
|
|
9257ebdd1e | ||
|
|
8f1017195f | ||
|
|
20da294b36 | ||
|
|
a63415461a | ||
|
|
2bb4c78551 | ||
|
|
2909e61721 | ||
|
|
171da2a194 | ||
|
|
933c468e2d | ||
|
|
0d1eb9b12e | ||
|
|
02a03b4d68 | ||
|
|
ef9f3bd361 | ||
|
|
f18b6ee754 | ||
|
|
deb9e463e1 | ||
|
|
c799534009 | ||
|
|
aea01072fb | ||
|
|
ca8dd5a702 | ||
|
|
e79c4a1e3f | ||
|
|
e19d0d948a | ||
|
|
a160ccd095 | ||
|
|
d2d0477186 | ||
|
|
c742c0725d | ||
|
|
9e6343a111 | ||
|
|
faf33b5f2d | ||
|
|
8a78ac7d82 | ||
|
|
d7c7814b3a | ||
|
|
15bf02f829 | ||
|
|
4f62a594b3 | ||
|
|
64253d0120 | ||
|
|
286936131d | ||
|
|
95588ef6b6 | ||
|
|
daef04ccd8 | ||
|
|
86e385c548 | ||
|
|
cc193b99d6 | ||
|
|
c026007937 | ||
|
|
dbc117a9d4 | ||
|
|
34665bd97a | ||
|
|
6d05e607b3 | ||
|
|
14bfc3018b | ||
|
|
7e4f195f94 | ||
|
|
4b6de934a5 | ||
|
|
14fbb595fd | ||
|
|
18a5fb80d0 | ||
|
|
551ef79f03 | ||
|
|
81aec6bad2 | ||
|
|
d08949c597 | ||
|
|
212aee0373 | ||
|
|
059b78c9fb | ||
|
|
11ba5fc28e | ||
|
|
fbde9ec64f | ||
|
|
6600bba58c | ||
|
|
9e340d2e16 | ||
|
|
6f784e9e94 | ||
|
|
62f6aabf05 | ||
|
|
46457a8bdc | ||
|
|
1081e836f5 | ||
|
|
dfe1e37592 | ||
|
|
0b9db21c10 | ||
|
|
57527115d4 | ||
|
|
8d2679c458 | ||
|
|
ca00f18a6a | ||
|
|
466f68701f | ||
|
|
1bb83da253 | ||
|
|
bd1e17bac9 | ||
|
|
322f95e42e | ||
|
|
3ea77f5899 | ||
|
|
882e61ff44 | ||
|
|
d991be4934 | ||
|
|
dfba8bd15f | ||
|
|
87e23673fb | ||
|
|
8fbd1acf4a | ||
|
|
d7dfbaa799 | ||
|
|
04ce20857e | ||
|
|
4550246d63 | ||
|
|
dd673f44ae | ||
|
|
3245284ecc | ||
|
|
3d9872a671 | ||
|
|
f02db2a2d8 | ||
|
|
d1ebb79432 | ||
|
|
44f03a1fce | ||
|
|
6b6ee94d9b | ||
|
|
81c2ca80bc | ||
|
|
c83cec8ed7 | ||
|
|
93ffe5c507 | ||
|
|
8cd1a70333 | ||
|
|
06ae024c2c | ||
|
|
ce8fd0f22f | ||
|
|
7dc1aff1dc | ||
|
|
a60003127f | ||
|
|
7d1ba58806 | ||
|
|
963d71e221 | ||
|
|
2a804fda1c | ||
|
|
597a1a04d2 | ||
|
|
aec6f49ea1 | ||
|
|
e1ad710de5 | ||
|
|
edc8447617 | ||
|
|
f726d4f8e8 | ||
|
|
1f333f6b88 | ||
|
|
9b855fca47 | ||
|
|
c5f433fdf4 | ||
|
|
fd61dae1c1 | ||
|
|
2c45f9759f | ||
|
|
0d3261f748 | ||
|
|
d38e873800 | ||
|
|
ca38914095 | ||
|
|
ee5beeea45 | ||
|
|
a9d40d9f49 | ||
|
|
e3864b86a4 |
No files matched your search
@@ -1,34 +0,0 @@
|
|||||||
name: CD Asia Ratings Latest
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
host:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Use node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
cache: "npm"
|
|
||||||
|
|
||||||
- name: Install Yarn
|
|
||||||
run: npm install --location=global yarn
|
|
||||||
|
|
||||||
- name: Use node_modules cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: "**/node_modules"
|
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: yarn
|
|
||||||
|
|
||||||
- name: Generate leaderboard
|
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=asia --latest
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
name: CD Asia Ratings Leaderboards
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 17 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
host:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Use node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
cache: "npm"
|
|
||||||
|
|
||||||
- name: Install Yarn
|
|
||||||
run: npm install --location=global yarn
|
|
||||||
|
|
||||||
- name: Use node_modules cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: "**/node_modules"
|
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: yarn
|
|
||||||
|
|
||||||
- name: Generate leaderboard
|
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=asia
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
name: CD Build Assets
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: main
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
token: ${{ secrets.GH_TOKEN }}
|
||||||
|
|
||||||
|
- name: Use node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install Yarn
|
||||||
|
run: npm install --location=global yarn
|
||||||
|
|
||||||
|
- name: Use node_modules cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: '**/node_modules'
|
||||||
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn
|
||||||
|
|
||||||
|
- name: Add fixed sharp
|
||||||
|
run: yarn add [email protected] --ignore-engines
|
||||||
|
|
||||||
|
- name: Setup DepotDownloader
|
||||||
|
run: yarn setup:depotdownloader
|
||||||
|
|
||||||
|
- name: Run DepotDownloader
|
||||||
|
run: ./temp/depotDownloader/DepotDownloader.exe -app 444200 -username ${{ secrets.DEPOT_DOWNLOADER_USERNAME }} -password "${{ secrets.DEPOT_DOWNLOADER_PASSWORD }}"
|
||||||
|
|
||||||
|
- name: Apply patches
|
||||||
|
run: |
|
||||||
|
$env:GH_TOKEN = "${{ secrets.GH_TOKEN }}"
|
||||||
|
$env:DISCORD_TOKEN = "${{ secrets.DISCORD_TOKEN }}"
|
||||||
|
$env:DISCORD_BLITZ_DB = "${{ secrets.DISCORD_BLITZ_DB }}"
|
||||||
|
$env:WOTB_DLC_CDN = "${{ secrets.WOTB_DLC_CDN }}"
|
||||||
|
yarn setup:patches --depot
|
||||||
|
|
||||||
|
- name: Build assets
|
||||||
|
run: |
|
||||||
|
$env:GH_TOKEN = "${{ secrets.GH_TOKEN }}"
|
||||||
|
$env:DISCORD_TOKEN = "${{ secrets.DISCORD_TOKEN }}"
|
||||||
|
$env:DISCORD_BLITZ_DB = "${{ secrets.DISCORD_BLITZ_DB }}"
|
||||||
|
yarn build:assets --all-targets --depot ${{ github.ref == 'refs/heads/main' && '--production' || '' }}
|
||||||
@@ -2,7 +2,7 @@ name: CD Docs
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -18,10 +18,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
uses: actions/deploy-pages@v1
|
uses: actions/deploy-pages@v1
|
||||||
|
|
||||||
- name: Archive build
|
- name: Archive build
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
path: docs/.vitepress/dist
|
path: docs/.vitepress/dist
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
name: CD Host
|
name: CD Host
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches: main
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 */6 * * *'
|
- cron: '0 */5 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
release:
|
||||||
|
types: [created, published, released, edited]
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -15,7 +19,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD North America Ratings Latest
|
name: CD Rating Asia
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *'
|
- cron: '0 17 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -10,10 +10,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -31,4 +31,4 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=na --latest
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingleaderboard --region=asia --target=midnight --production
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD Europe Ratings Latest
|
name: CD Rating Europe
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *"
|
- cron: '0 23 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -10,13 +10,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: "npm"
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,11 +24,11 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: "**/node_modules"
|
path: '**/node_modules'
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=eu --latest
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingleaderboard --region=eu --target=midnight --production
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
name: CD Europe Ratings Leaderboards
|
name: CD Rating Latest
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 23 * * *"
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
host:
|
host:
|
||||||
@@ -10,13 +10,13 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: "npm"
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install Yarn
|
- name: Install Yarn
|
||||||
run: npm install --location=global yarn
|
run: npm install --location=global yarn
|
||||||
@@ -24,11 +24,11 @@ jobs:
|
|||||||
- name: Use node_modules cache
|
- name: Use node_modules cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: "**/node_modules"
|
path: '**/node_modules'
|
||||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate all leaderboards
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=eu
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingleaderboard --region=na,asia,eu --target=latest --production
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: CD North America Ratings Leaderboards
|
name: CD Rating North America
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
@@ -10,10 +10,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -31,4 +31,4 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Generate leaderboard
|
- name: Generate leaderboard
|
||||||
run: GH_TOKEN=${{ secrets.GH_TOKEN }} yarn publish:ratingsleaderboard --region=na
|
run: GH_TOKEN=${{ secrets.GH_TOKEN }} DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }} DISCORD_BLITZ_DB=${{ secrets.DISCORD_BLITZ_DB }} yarn publish:ratingleaderboard --region=na --target=midnight --production
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: CI Build Bot
|
name: CI Build Bot
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: push
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -13,10 +13,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -34,10 +34,10 @@ jobs:
|
|||||||
run: yarn
|
run: yarn
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: yarn build:bot
|
run: yarn build:bot --production
|
||||||
|
|
||||||
- name: Archive build
|
- name: Archive build
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: bot
|
name: bot
|
||||||
path: dist/bot
|
path: dist/bot
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: CI Build Docs
|
name: CI Build Docs
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: push
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -13,10 +13,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
run: yarn build:docs
|
run: yarn build:docs
|
||||||
|
|
||||||
- name: Archive build
|
- name: Archive build
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: dist/docs
|
path: dist/docs
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name: CI Build Website
|
name: CI Build Website
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: push
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -13,10 +13,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use node
|
- name: Use node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
run: yarn build:website
|
run: yarn build:website
|
||||||
|
|
||||||
- name: Archive build
|
- name: Archive build
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: website
|
name: website
|
||||||
path: dist/website
|
path: dist/website
|
||||||
@@ -8,9 +8,15 @@ dist/
|
|||||||
dist.*
|
dist.*
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
/test.*
|
/test.*
|
||||||
test.*
|
|
||||||
/docs/.vitepress/dist
|
/docs/.vitepress/dist
|
||||||
/docs/.vitepress/cache
|
/docs/.vitepress/cache
|
||||||
servers.csv
|
servers.csv
|
||||||
.next/
|
.next/
|
||||||
tsconfig.tsbuildinfo
|
tsconfig.tsbuildinfo
|
||||||
|
temp/
|
||||||
|
/.yarn
|
||||||
|
/.VSCodeCounter
|
||||||
|
/.yarn
|
||||||
|
depots
|
||||||
|
public/sitemap*.xml
|
||||||
|
public/robots.txt
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "submodules/closedkrieg"]
|
||||||
|
path = submodules/closedkrieg
|
||||||
|
url = https://github.com/tresabhi/closedkrieg
|
||||||
@@ -1,53 +1,159 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"AABBOX",
|
||||||
"Abhi",
|
"Abhi",
|
||||||
"accountinfo",
|
"accountinfo",
|
||||||
|
"aeson",
|
||||||
|
"alphatest",
|
||||||
|
"APAC",
|
||||||
|
"apcr",
|
||||||
|
"applypatches",
|
||||||
|
"artefacts",
|
||||||
|
"atgm",
|
||||||
|
"AYUV",
|
||||||
|
"bbox",
|
||||||
"bepaint",
|
"bepaint",
|
||||||
|
"betakrieg",
|
||||||
|
"BINORMAL",
|
||||||
|
"Binormals",
|
||||||
|
"BKRL",
|
||||||
|
"bkwd",
|
||||||
"blitzstars",
|
"blitzstars",
|
||||||
|
"Camo",
|
||||||
|
"CDON",
|
||||||
|
"classname",
|
||||||
"cleandist",
|
"cleandist",
|
||||||
|
"closedkrieg",
|
||||||
"cockroackdb",
|
"cockroackdb",
|
||||||
|
"Coef",
|
||||||
|
"cooldown",
|
||||||
|
"corsproxy",
|
||||||
|
"CUBEMAP",
|
||||||
|
"CUBETEXCOORD",
|
||||||
"customperiod",
|
"customperiod",
|
||||||
|
"datasource",
|
||||||
|
"Ddpf",
|
||||||
|
"Ddsd",
|
||||||
|
"debugflags",
|
||||||
"deburr",
|
"deburr",
|
||||||
|
"decalmask",
|
||||||
|
"defence",
|
||||||
|
"degressive",
|
||||||
|
"devkrieg",
|
||||||
"diacriticless",
|
"diacriticless",
|
||||||
|
"donotremove",
|
||||||
|
"drei",
|
||||||
|
"Droodles",
|
||||||
|
"dvpd",
|
||||||
|
"dvpl",
|
||||||
|
"DVPLCRC",
|
||||||
|
"dvpm",
|
||||||
|
"dxgi",
|
||||||
"Everytime",
|
"Everytime",
|
||||||
|
"FASTNAME",
|
||||||
|
"FOURCC",
|
||||||
|
"fsformat",
|
||||||
|
"Fullscreen",
|
||||||
"fullstats",
|
"fullstats",
|
||||||
"fuzzysort",
|
"fuzzysort",
|
||||||
|
"gamemode",
|
||||||
|
"glsl",
|
||||||
|
"GLTF",
|
||||||
|
"haha",
|
||||||
|
"highp",
|
||||||
|
"iife",
|
||||||
|
"immer",
|
||||||
|
"Inclusivity",
|
||||||
|
"JOINTINDEX",
|
||||||
|
"JOINTWEIGHT",
|
||||||
"kranvagn",
|
"kranvagn",
|
||||||
|
"krieg",
|
||||||
"Leaderboard",
|
"Leaderboard",
|
||||||
"leaderboards",
|
"leaderboards",
|
||||||
|
"lerp",
|
||||||
|
"LINEARSIZE",
|
||||||
|
"loddist",
|
||||||
|
"lods",
|
||||||
|
"metallicness",
|
||||||
|
"minitelrose",
|
||||||
|
"Minotauro",
|
||||||
|
"MIPMAPCOUNT",
|
||||||
|
"modeltransform",
|
||||||
|
"MURICA",
|
||||||
|
"NEGATIVEX",
|
||||||
|
"NEGATIVEY",
|
||||||
|
"NEGATIVEZ",
|
||||||
|
"nmatname",
|
||||||
|
"noout",
|
||||||
|
"normalmap",
|
||||||
"Oopsy",
|
"Oopsy",
|
||||||
|
"OPTML",
|
||||||
"outdir",
|
"outdir",
|
||||||
"outfile",
|
"outfile",
|
||||||
"ownedtanks",
|
"ownedtanks",
|
||||||
|
"PIXELFORMAT",
|
||||||
"playerachievements",
|
"playerachievements",
|
||||||
"playerinfo",
|
"playerinfo",
|
||||||
"ratingsleaderboard",
|
"pngjs",
|
||||||
|
"POSITIVEX",
|
||||||
|
"POSITIVEY",
|
||||||
|
"POSITIVEZ",
|
||||||
|
"Promisable",
|
||||||
|
"Pyogenics",
|
||||||
|
"ratingleaderboard",
|
||||||
|
"raycaster",
|
||||||
|
"researchable",
|
||||||
"Resvg",
|
"Resvg",
|
||||||
"roboto",
|
"roboto",
|
||||||
|
"SCPG",
|
||||||
"searchclans",
|
"searchclans",
|
||||||
"searchplayers",
|
"searchplayers",
|
||||||
"searchtanks",
|
"searchtanks",
|
||||||
|
"SHAREDEXP",
|
||||||
"SKLLD",
|
"SKLLD",
|
||||||
"Smri",
|
"Smri",
|
||||||
|
"Specularity",
|
||||||
|
"SSAO",
|
||||||
"startcase",
|
"startcase",
|
||||||
"statsfull",
|
"statsfull",
|
||||||
|
"steamapps",
|
||||||
"Stringifying",
|
"Stringifying",
|
||||||
|
"struct",
|
||||||
|
"structs",
|
||||||
"strvk",
|
"strvk",
|
||||||
"subnation",
|
"subnation",
|
||||||
|
"Synx",
|
||||||
"tankaverages",
|
"tankaverages",
|
||||||
|
"Tankerch",
|
||||||
"tankopedia",
|
"tankopedia",
|
||||||
|
"tankopedias",
|
||||||
"tankstats",
|
"tankstats",
|
||||||
|
"texconv",
|
||||||
|
"TEXCOORD",
|
||||||
"tresabhi",
|
"tresabhi",
|
||||||
|
"tungstentip",
|
||||||
|
"TYPELESS",
|
||||||
|
"ubjson",
|
||||||
"Unicum",
|
"Unicum",
|
||||||
|
"UNLOCALIZED",
|
||||||
|
"UNORM",
|
||||||
"Unregistering",
|
"Unregistering",
|
||||||
"vickers",
|
"vickers",
|
||||||
"vitepress",
|
"vitepress",
|
||||||
|
"Vovko",
|
||||||
"wargaming",
|
"wargaming",
|
||||||
"webp",
|
"webp",
|
||||||
"winrate",
|
"winrate",
|
||||||
|
"wireframe",
|
||||||
|
"WOTB",
|
||||||
"wotblitz",
|
"wotblitz",
|
||||||
|
"xffn",
|
||||||
|
"xkdkw",
|
||||||
|
"XMLDVPL",
|
||||||
|
"YAMLDVPL",
|
||||||
"zustand"
|
"zustand"
|
||||||
],
|
],
|
||||||
"deno.enable": false,
|
"deno.enable": false,
|
||||||
"deno.unstable": false
|
"deno.unstable": false,
|
||||||
|
"cSpell.enableFiletypes": ["glsl"]
|
||||||
}
|
}
|
||||||
@@ -14,31 +14,10 @@ Go to [application directory for Blitzkrieg](https://discord.com/application-dir
|
|||||||
|
|
||||||
### https://blitz-krieg.vercel.app/
|
### https://blitz-krieg.vercel.app/
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Visit the documentation website
|
## Visit the documentation website
|
||||||
|
|
||||||
### https://tresabhi.github.io/blitzkrieg/
|
### https://tresabhi.github.io/blitzkrieg/
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Run the bot
|
|
||||||
|
|
||||||
### Install dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn
|
|
||||||
```
|
|
||||||
|
|
||||||
### Create `.env`
|
|
||||||
|
|
||||||
```env
|
|
||||||
GH_TOKEN={YOUR_GITHUB_TOKEN_HERE}
|
|
||||||
DISCORD_TOKEN={YOUR_DISCORD_TOKE_HERE}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run the command
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn dev:bot
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
files:
|
||||||
|
- source: /src/lang/en-US.json
|
||||||
|
translation: /src/lang/%locale%.json
|
||||||
@@ -13,7 +13,7 @@ export default defineConfig({
|
|||||||
themeConfig: {
|
themeConfig: {
|
||||||
nav: [
|
nav: [
|
||||||
{ text: 'Home', link: '/' },
|
{ text: 'Home', link: '/' },
|
||||||
{ text: 'Guide', link: '/guide/about' },
|
{ text: 'Guide', link: '/guide/introduction' },
|
||||||
],
|
],
|
||||||
|
|
||||||
sidebar: [
|
sidebar: [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Blitzkrieg 1.14.1
|
# Blitzkrieg 1.14.2
|
||||||
|
|
||||||
A late night hot fix for my homies
|
A late night hot fix for my homies
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Blitzkrieg 1.14.3
|
||||||
|
|
||||||
|
Pull your brush out and start polishing.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Rows in `/breakdown` are now chunked into `8` per image
|
||||||
|
- This is true unless the number of pages exceeds `10` in which case the rows are even distributed across all `10` pages
|
||||||
|
- `10` is the maximum number of images that Discord allows
|
||||||
|
- Short region names are used in username autocomplete instead of their full names
|
||||||
|
- Example: "North America" is "NA" now
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Removed reference to username inference in the username option description
|
||||||
|
- Removed an unnecessary type `asd` that did absolutely nothing used nowhere
|
||||||
|
|
||||||
|
## Technical changes
|
||||||
|
|
||||||
|
- Image orders are now preserved even if processed in parallel and all completed out of order
|
||||||
|
- `fetchBlitz` is now throttled to `10` requests per second
|
||||||
|
- Request overflows are managed by queueing
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Blitzkrieg 1.14.4
|
||||||
|
|
||||||
|
Streamers get some knowledge today
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Added a video in the embed button prompt
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Blitzkrieg 1.15.0
|
||||||
|
|
||||||
|
Ratings will never be the same.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Blitzkrieg ratings leaderboard
|
||||||
|
- Available at https://blitz-krieg.vercel.app/tools/ratings
|
||||||
|
- **Highly experimental; [please report bugs on Discord server](https://discord.gg/nDt7AjGJQH)**
|
||||||
|
- Current season leaderboards are live meaning that there may be scores and positions that are out of order
|
||||||
|
- Options
|
||||||
|
- Regions can be swapped between NA, EU, and Asia
|
||||||
|
- The current season and all archived season (from 49 and onwards) are available
|
||||||
|
- Jump: used to jump to certain players
|
||||||
|
- Score: finds the first player with at least your desired score
|
||||||
|
- Position: finds the player at that position
|
||||||
|
- League: finds the top-most player in that league
|
||||||
|
- Player: finds the player
|
||||||
|
- **Jumping to scores and positions for the current season is a compounding function (hence the loading screen) and is limited to the speed of Wargaming's APIs which is pretty darn slow**
|
||||||
|
- Page controls
|
||||||
|
- Flip between pages left and right
|
||||||
|
- 33 players are loaded at once
|
||||||
|
- Left control is disabled on the first page and vice versa
|
||||||
|
- Page turning controls are also disabled if the next/previous page hasn't loaded yet
|
||||||
|
- Page numbers can be manually typed in the text field too
|
||||||
|
- This is available both at the top and the bottom of the screen
|
||||||
|
- Players
|
||||||
|
- Shows the position of the player
|
||||||
|
- Shows the player nickname and clan name
|
||||||
|
- "Deleted player ID" us shown when loading a deleted player
|
||||||
|
- A skeleton is shown when the player and clan is loading
|
||||||
|
- Shows the player percentile
|
||||||
|
- Shows reward for the position
|
||||||
|
- This is blank when there is no reward
|
||||||
|
- This column isn't available for archived seasons
|
||||||
|
- Shows the score
|
||||||
|
- A skeleton is shown when loading
|
||||||
|
- Click on a row to highlight it
|
||||||
|
- Using a jump button also highlights a row
|
||||||
|
- `/credits`: thanks who helped made this project
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Error messages that user face are now even more simplified
|
||||||
|
- Increased username and clan autocomplete size limits to `25`
|
||||||
|
- Added capability for per-page accent theming
|
||||||
|
- Example: the ratings page is red while the session tracker is blue
|
||||||
|
- Simplified welcome message for SKLLD clan server
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Isolated tankopedia info
|
||||||
|
- Implemented `corsproxy.io` for non-timeout tolerant endpoints
|
||||||
|
- Latest archived season number is now data driven
|
||||||
|
- Ratings archives are now public
|
||||||
|
- This eliminates the need of `octokit`
|
||||||
|
- Ratings leaderboard archiver is now error tolerant
|
||||||
|
- Fetch attempts are made every `1000ms`
|
||||||
|
- Blitz errors are now managed better freeing up the queue faster
|
||||||
|
- Isolated first archived season number
|
||||||
|
- Added more advanced PSAs
|
||||||
|
- These can now feature images or embeds
|
||||||
|
- These can now modify message contents
|
||||||
|
- These can also now be secret
|
||||||
|
|
||||||
|
## Experimental Changes
|
||||||
|
|
||||||
|
- Added tankopedia extractor
|
||||||
|
- Retrieves tankopedia data from the game files
|
||||||
|
- This is not utilized as of right now
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Blitzkrieg 1.15.1
|
||||||
|
|
||||||
|
'MURICA!
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- "Neighbor" is now spelled in the American way
|
||||||
|
- Updated documentation website with the latest information
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Fixed the guide link on the documentation website
|
||||||
|
|
||||||
|
## Technical features
|
||||||
|
|
||||||
|
- Added capability to fetch patiently while also parsing the JSON
|
||||||
|
|
||||||
|
## Technical changes
|
||||||
|
|
||||||
|
- Removed neighbor relative position caching
|
||||||
|
|
||||||
|
## Technical fixes
|
||||||
|
|
||||||
|
- `/ratings` now uses the non-caching APIs
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Blitzkrieg 1.15.10
|
||||||
|
|
||||||
|
The 10th patch for the `1.15` update is here, breaking the record of the most patches for a single update!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added `/today`
|
||||||
|
- This is a direct alias for `/breakdown today`
|
||||||
|
- Drastically simplified ratings command
|
||||||
|
- `/ratings current` and `/ratings archive` have been now merged
|
||||||
|
- Where the data is fetched from is now decided directly from the chosen season number
|
||||||
|
- Simplified many error messages
|
||||||
|
- Title bar description text is now centered when there is no image
|
||||||
|
- It always felt awkward when there was no image on the left but the left still aligned to the right
|
||||||
|
- Removed `/link`'s requirement to select a username explicitly from the search results
|
||||||
|
- Full names for regions are now used in the `/link` command
|
||||||
|
- So "NA" turns into "North America"
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Fixed contrast issues with WN8 percentile colors behind white text
|
||||||
|
- Archived ratings neighbors now functions once again
|
||||||
|
- Disabled tankopedia; this feature isn't finished yet and the changes were accidentally leaked
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Blitzkrieg 1.15.11
|
||||||
|
|
||||||
|
There's an easter egg somewhere in this update 🤔
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added `/permissions` which lists all permissions required to run the bot and checks if the bot has them or not
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Error messages now do no use embeds, instead utilize simple headings and paragraphs
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Blitzkrieg 1.15.12
|
||||||
|
|
||||||
|
Sometimes embeds need love too.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Session embeds are now translucent by default
|
||||||
|
- Session embed titles are now the username of the player by default
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Blitzkrieg 1.15.13
|
||||||
|
|
||||||
|
I have run out of things to say here. This patch fixes like 1 thing haha.
|
||||||
|
|
||||||
|
# Technical Fixes
|
||||||
|
|
||||||
|
- Tank deltas are now filtered by last battle time
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Blitzkrieg 1.15.2
|
||||||
|
|
||||||
|
Infinity reduced to a finite value.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Added a maximum value to the jump to position button
|
||||||
|
- Removed neighbor checking for the seeding player
|
||||||
|
- This fixes the jump to position button not loading at all
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Blitzkrieg 1.15.3
|
||||||
|
|
||||||
|
The bot now gets more expressive!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- The bot can now have presence messages; examples:
|
||||||
|
- "Living in {number} servers"
|
||||||
|
- "Server {number} users"
|
||||||
|
- "Observing {number} channels"
|
||||||
|
- More will be added in the future! Give me some ideas
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Moved `/credits` to `/about creators`
|
||||||
|
- `/debug` command now ditches embeds and has better information to serve
|
||||||
|
|
||||||
|
## Technical Features
|
||||||
|
|
||||||
|
- Added a workflow and lint for package and changelog version miss match
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Removed manual trigger for Asian latest ratings leaderboard archiver
|
||||||
|
- Leaderboard archiver now accepts an explicit target like `midnight` or `latest`
|
||||||
|
- Combined midnight and latest leaderboard archival workflow into one file
|
||||||
|
|
||||||
|
## Technical Fixed
|
||||||
|
|
||||||
|
- Reviewed all workflow triggers and updated them
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Blitzkrieg 1.15.4
|
||||||
|
|
||||||
|
Unlocking future potential
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Moved the word "Ratings" to the front of the workflow name
|
||||||
|
- Renamed `blitzkrieg-db` to `blitzkrieg-assets`
|
||||||
|
- Moved the region folders from the root to `regions`
|
||||||
|
|
||||||
|
## Technical Fixes
|
||||||
|
|
||||||
|
- The ratings leaderboard archiver now correctly skips undefined players
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Blitzkrieg 1.15.5
|
||||||
|
|
||||||
|
Oops, this should've been in the last patch.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- User and channel cache is now guild cache exhaustive
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Blitzkrieg 1.15.6
|
||||||
|
|
||||||
|
This should have also been in the last update lol.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Changed the format of `/about creators` and added one more person
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Archived ratings leaderboards are now fetched from the correct URL path
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Blitzkrieg 1.15.7
|
||||||
|
|
||||||
|
Simple yet powerful theming options for the session tracker
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- The accent color of the session tracker (hence the embed too) can now be tweaked
|
||||||
|
- Access this setting via the dropdown from Options > Accent color
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Reimplemented the commas for last numbers in the overflow count of the ratings leaderboard
|
||||||
|
- For example, "+1234567 more" will now read "+1,234,567 more"
|
||||||
|
|
||||||
|
## Technical Features
|
||||||
|
|
||||||
|
- Added class names for more in-depth customization for those who are comfortable with CSS
|
||||||
|
- `session-tracker-root`
|
||||||
|
- `session-tracker-row`
|
||||||
|
- `session-tracker-row-stat`
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Blitzkrieg 1.15.8
|
||||||
|
|
||||||
|
A request fulfilled \:\)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added custom titles in session tracker
|
||||||
|
- Change the title through Options > Edit title...
|
||||||
|
- Colors are shown when selecting a theme color for the session tracker
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Blitzkrieg 1.15.9
|
||||||
|
|
||||||
|
~~Curiosity killed the cat~~ Ratings killed the Blitzkrieg
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Deleted ratings players are now handled properly
|
||||||
|
|
||||||
|
## Technical Fixes
|
||||||
|
|
||||||
|
- Latest archived season number
|
||||||
|
- Is now cached properly
|
||||||
|
- Is now fetched in a chaining fashion correctly
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Blitzkrieg 1.16.0
|
||||||
|
|
||||||
|
This version introduces the long awaited (and desperately needed) Blitzkrieg Tankopedia.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
- [Pyogenics](https://github.com/pyogenics): technical documentation on WoTB 3d models
|
||||||
|
- [aeson](https://discord.gg/WHdER7ZPAD): human encyclopedia on WoTB file layout
|
||||||
|
- [\[OPTML\]](https://discord.gg/Su8w9KtEVE), [\_34](https://www.twitch.tv/34wotb), [Droodles_YT](https://www.youtube.com/@DroodlesBlitz): Tankopedia beta-testing
|
||||||
|
- Minitelrose, ChickenMan7777: external module exceptions
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added Tankopedia
|
||||||
|
- Check out the tool here: https://blitz-krieg.vercel.app/tools/tankopedia
|
||||||
|
- The root page features a search engine for efficiently finding tanks
|
||||||
|
- Search bar: lets you search tanks via it's name
|
||||||
|
- Sort: lets you sort tanks by their statistics and generic things like names and tiers
|
||||||
|
- Reset button (trash icon): resets all filters and sorts
|
||||||
|
- Test tanks: lets you control wether you want to include test tanks
|
||||||
|
- Tree type filter: filters tech tree, premium, and collector tanks
|
||||||
|
- Nations: filters tanks by nation
|
||||||
|
- Tank type filter: filters tanks by tank designation
|
||||||
|
- Tier filter: filters tanks by tier
|
||||||
|
- The search result itself displays the national flag, tier, type, image, and name of the tank
|
||||||
|
- Clicking on the tank redirects you to the tank's page
|
||||||
|
- Tankopedia page
|
||||||
|
- Tank sandbox: the first thing you'll see is a 3D model of the tank
|
||||||
|
- On slim mobile devices, click "Load model" to reveal it
|
||||||
|
- Model tab
|
||||||
|
- This model has all PBR features and is identical to the one in the game
|
||||||
|
- You can click and drag the turret to rotate it
|
||||||
|
- You can do the same with the gun but with the added control of elevating and depressing it
|
||||||
|
- Armor tab
|
||||||
|
- Shows red where the tank (the protagonist) cannot be penetrated
|
||||||
|
- You can switch the shells that the shooter (the antagonist) shoots
|
||||||
|
- By default, the antagonist tank is the same as the protagonist
|
||||||
|
- You can change antagonists using the antagonist bar
|
||||||
|
- Searching through antagonists is identical to the root search page
|
||||||
|
- You may also swap the protagonist and antagonist using the swap button
|
||||||
|
- Click on the tank's armor anywhere to get intimate details about it
|
||||||
|
- Shows spaced armor, gaps between layers of armor, ricochets, penetration losses over events, thickness, angled thicknesses, and angles
|
||||||
|
- View button (eye icon): allows you to pose the tank in a few preset configurations
|
||||||
|
- Sandbox settings
|
||||||
|
- Green penetration: shows the penetrable parts of the tank as green instead of using transparency
|
||||||
|
- Show grid: shows a grid under the tank
|
||||||
|
- View environment: shows the lighting environment around the tank
|
||||||
|
- Lighting: preset lighting environments
|
||||||
|
- Wireframe: displays armor as vertices instead of faces
|
||||||
|
- Fullscreen button: toggles fullscreen
|
||||||
|
- Note that some functionalities are disabled in fullscreen
|
||||||
|
- Modules: switch around modules to view it change live in the 3D model and affect stats
|
||||||
|
- Provisions, equipments, miscellaneous, and consumables also affect stats
|
||||||
|
- Stats
|
||||||
|
- As you switch around the configurations of the tank, the change in stats are displayed using green and red arrows with delta numbers
|
||||||
|
- Statistics also display their units
|
||||||
|
- Fire section
|
||||||
|
- This deals with statistics relating to the firepower of the tank
|
||||||
|
- You can switch shells that the stats are based on using the buttons to the right of the title
|
||||||
|
- You can also view the penetration loss over distance using the slider if available under the penetration section
|
||||||
|
- Statistics for maneuverability, survivability, and crew training are also displayed
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Navigation bar
|
||||||
|
- Added credit to myself along with the logo and moved the whole thing to the left side
|
||||||
|
- Added a link to the discord icon to the right
|
||||||
|
- Removed polka dots from the background
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- The `/ratings` command once again has the username field as an optional parameter
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Blitzkrieg 1.16.1
|
||||||
|
|
||||||
|
Armor sandbox gains 25% rendering speed and 40% memory efficiency with added accuracy and features.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Multiple layers of spaced armors are now calculated properly by the visual armor highlighting
|
||||||
|
- Added opaque mode to view armor highlighting without any transparency
|
||||||
|
- Added breakdown on layers of armor penetrated
|
||||||
|
- Penetration of each layer is shown represented by a color and an index
|
||||||
|
- Green: penetration
|
||||||
|
- Red: blocked
|
||||||
|
- Yellow: ricochet
|
||||||
|
- This also shows layers encountered after a ricochet
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Accuracy now doesn't drop the further the shot is placed from the origin
|
||||||
|
- HE shells no longer loose penetration like how HEAT shells do when traveling between layers of armor
|
||||||
|
- Persistent settings are now merged in the correct order making them truly persistent now
|
||||||
|
- Enhanced armor and calibrated shells are now properly synced from the get go
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Spaced armor and external module scenes have been merged
|
||||||
|
- They now use additive blending
|
||||||
|
- Colors are now normalized by the penetration value instead of maximum armor plate thickness
|
||||||
|
- Shell normalization now doesn't violate arccosine's domain
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Blitzkrieg 1.16.2
|
||||||
|
|
||||||
|
¡Hola desde el mundo del español!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added translations for Spanish to the bot
|
||||||
|
- Your language will be inferred automatically from your Discord settings
|
||||||
|
- Any untranslated languages and words we forgot to translate will be left in English
|
||||||
|
- If you have your language set to Spanish and see English in any places, please let us know on [the official Discord server](https://discord.gg/nDt7AjGJQH)
|
||||||
|
- All `/about` commands except for `commands` remain in English
|
||||||
|
- Tank names are still in English
|
||||||
|
- The website remains unchanged
|
||||||
|
- The title bar (featured as the big text on top of most commands) has now been made more compact
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- "Tank type" is now called "tank class"
|
||||||
|
- Removed `/player-achievements` and `search-tanks`
|
||||||
|
- They will be reintroduced in the future in a far better way
|
||||||
|
- Also removed a `SKLLD` server exclusive `/eligible` command
|
||||||
|
- This will be generalized for all clans in the future
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Fixed the red glowing floor underneath the tank sandbox
|
||||||
|
- This has been replaced with a static image
|
||||||
|
- The refresh button is now properly removed when lacking permissions
|
||||||
|
- Tank names that start with a number are now properly inferred from command inputs
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Command registration is now error tolerant meaning that if a single command fails to initiate, it will be discarded until the next restart
|
||||||
|
- We are currently looking into how we can allow the command to retry registration after a fixed amount of time
|
||||||
|
- Due to the implications of the code added which can be very easily exploited by hackers, a single file has been added to the repository as a closed source submodule and will remain closed unless a third party open-source implementation is made public
|
||||||
|
- Removed preview commands
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Blitzkrieg 1.16.3
|
||||||
|
|
||||||
|
Further polishing and corrections for the Tankopedia.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added a few more stats to view for the Tankopedia
|
||||||
|
- Added the count of shells in the magazine for auto-reloaders
|
||||||
|
- The optimal shell index was moved below this stats
|
||||||
|
- Shell reloads for auto-reloaders now abide crew stats
|
||||||
|
- Intra-clip is now also shown for auto-reloaders
|
||||||
|
- Added 1 more decimal place worth of precision when viewing and changing gun pitch and yaw
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- "Inter-clip" is now correctly spelled as "intra-clip"
|
||||||
|
- Tanks with initial gun pitches (like the Minotauro) are now handled correctly
|
||||||
|
- The stats now reflect the fact that the gun is naturally pitched downwards
|
||||||
|
- The view model now compensates for the natural pitch
|
||||||
|
- Tanks with the improved vertical stabilizer equipment are now handled correctly
|
||||||
|
- The view model now allows you to pitch the gun further as intended when the equipment is on
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Blitzkrieg 1.16.4
|
||||||
|
|
||||||
|
A few issues here and there addressed for good measure.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- Armor layer penetration indices are now much more compact.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Reverted splash mechanics changes from `1.16.1` as it made them less accurate.
|
||||||
|
- Auto-reloaders now report their DPM stats correctly with crew training.
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- All files in the project were reviewed and constant exports were isolated.
|
||||||
|
- The downloaded game in the workflow now also includes the latest patches.
|
||||||
|
- Asset building now uses sharp under the hood which should in theory be faster.
|
||||||
|
- Fetching CDON LZ4 files now uses `no-store` instead of `no-cache`
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Blitzkrieg 1.17.0
|
||||||
|
|
||||||
|
A preview command and a touchup.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added `/research` in preview only accessible in the official Discord server.
|
||||||
|
- More details will be posted when the command is made public.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
- `/owned-tanks` now returns a simple text message listing all the tanks instead of an image.
|
||||||
|
- This is meant to improve the readability and ease of copying.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Blitzkrieg 1.17.1
|
||||||
|
|
||||||
|
Some stability fixes.
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- `sharp` is now included in the build instead of having being installed before runtime.
|
||||||
|
- Png converter cache is now more memory efficient.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Blitzkrieg 1.17.2
|
||||||
|
|
||||||
|
Introducing the new `/research` command!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Added the `/research` command
|
||||||
|
- Type in the name of a tech tree tank you desire to research and this command will list all the expenses in researching all tanks in that line
|
||||||
|
- The starting tank is inferred automatically by the tanks you own
|
||||||
|
- This may be a bit inaccurate because of the lack of accurate information Wargaming provides about owned tanks
|
||||||
|
- You are also manually provide a starting tank and a user to see the progress on a line for
|
||||||
|
- Replaced Vercel Analytics (which collapsed under the insane amount of traffic on the website) with Google Analytics
|
||||||
|
- Spaced armor can now be toggled in the Tankopedia armor sandbox
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Blitzkrieg 1.18.0
|
||||||
|
|
||||||
|
Introducing the new `/rating` command!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- `/rating` command
|
||||||
|
- Features statistics on today's performance in ratings
|
||||||
|
- The included stats are battles, winrate, damage, survival, and kills
|
||||||
|
- This command also features the score, rank, and league you are at plus the reward you'll get if you are high enough on the leaderboard
|
||||||
|
- `/ratings`, the old leaderboard command, has been renamed `/rating-leaderboard`
|
||||||
|
- Reward icons have been removed from the leaderboard
|
||||||
|
|
||||||
|
## Technical Changes
|
||||||
|
|
||||||
|
- Rating leaderboards are now built in a more action-efficient manner.
|
||||||
|
- This version also introduces the BKRL (Blitzkrieg rating leaderboard) file format which is an efficient way to store entire leaderboards of regions to disk (1 MB per 40,000 users).
|
||||||
|
- Latest archival actions now build all regions at once in a single action.
|
||||||
|
- The sharp module is now included in the build.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# Blitzkrieg 1.18.1
|
||||||
|
|
||||||
|
HE gets more accurate and say goodbye to NaNaNaNaNaN.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- Armor highlighting now works on Apple MacBooks
|
||||||
|
- Applied equipments now persist after switching shells
|
||||||
|
- The bottom of the tank sandbox panel can now be interacted with as it was previously blocked by an invisible layer
|
||||||
|
- `/rating` now uses the midnight leaderboard instead of the absolute latest one
|
||||||
|
- 0-battle stats are now hidden
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Blitzkrieg 1.18.2
|
||||||
|
|
||||||
|
Redefining how micro a micro-path is.
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- The pitch and yaw controls, along with the quick equipment buttons, can once again be interacted with
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Blitzkrieg Rating Leaderboard
|
||||||
|
|
||||||
|
A straightforward way of storing the entire World of Tanks Blitz rating leaderboard to disk.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
primary BlitzkriegRatingLeaderboard {
|
||||||
|
utf8"BKRL" magic;
|
||||||
|
Header header;
|
||||||
|
primary Body<header> body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Header {
|
||||||
|
uint16 version; // always 1
|
||||||
|
Format format;
|
||||||
|
uint32 count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Format enum<uint8> {
|
||||||
|
Base,
|
||||||
|
Superset1,
|
||||||
|
}
|
||||||
|
|
||||||
|
Body<Header header> match<header.format> {
|
||||||
|
Base {
|
||||||
|
primary {
|
||||||
|
uint32 id;
|
||||||
|
uint16 score;
|
||||||
|
}[header.count] entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
Superset1 {
|
||||||
|
primary {
|
||||||
|
uint32 id;
|
||||||
|
uint16 score;
|
||||||
|
|
||||||
|
uint32 battles;
|
||||||
|
uint32 wins;
|
||||||
|
uint32 survived;
|
||||||
|
|
||||||
|
uint32 damage;
|
||||||
|
uint32 kills;
|
||||||
|
}[header.count] entries;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# Cedilla Object Notation
|
||||||
|
|
||||||
|
1. JSON compressed as CDON, written directly to disk (a direct 50% reduction).
|
||||||
|
2. CDON further compressed with LZ4 (a clean 90% reduction).
|
||||||
|
3. The raw JSON file as fetched from a random data source.
|
||||||
|
4. CDON decompressed once again to JSON. Note that this file is a little larger than the original JSON file as it contains a lot more decimal places due to float precision (this shouldn't affect the size in memory).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
FS stands for "Fast String".
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
primary CedillaObjectNotation {
|
||||||
|
utf8"CDON" magic;
|
||||||
|
Header header;
|
||||||
|
primary Body<header.fsFormat> body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Header {
|
||||||
|
uint16 version; // always 1
|
||||||
|
FSFormat fsFormat;
|
||||||
|
StringTable<fsFormat> stringTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSFormat enum<uint8> {
|
||||||
|
Format8,
|
||||||
|
Format16,
|
||||||
|
Format32,
|
||||||
|
}
|
||||||
|
|
||||||
|
FSPrimitive<FSFormat fsFormat> match(fsFormat) {
|
||||||
|
Format8: uint8;
|
||||||
|
Format16: uint16;
|
||||||
|
Format32: uint32;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTable<FSFormat fsFormat> {
|
||||||
|
FSPrimitive<fsFormat> count;
|
||||||
|
String[count] strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
Body<FSFormat fsFormat> {
|
||||||
|
primary Value<fsFormat> object;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType enum<uint8> {
|
||||||
|
Null,
|
||||||
|
Boolean,
|
||||||
|
Uint8,
|
||||||
|
Uint16,
|
||||||
|
Uint32,
|
||||||
|
Uint64,
|
||||||
|
Int8,
|
||||||
|
Int16,
|
||||||
|
Int32,
|
||||||
|
Int64,
|
||||||
|
Float32,
|
||||||
|
Float64,
|
||||||
|
String,
|
||||||
|
FS,
|
||||||
|
Array,
|
||||||
|
Object,
|
||||||
|
}
|
||||||
|
|
||||||
|
String {
|
||||||
|
uint32 length;
|
||||||
|
primary utf8<length> value;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringValue Value & { (ValueType.String | ValueType.FS) type }
|
||||||
|
|
||||||
|
Value<FSFormat fsFormat> {
|
||||||
|
ValueType type;
|
||||||
|
match<type> {
|
||||||
|
Boolean: { uint8 value; }
|
||||||
|
Uint8: { uint8 value; }
|
||||||
|
Uint16: { uint16 value; }
|
||||||
|
Uint32: { uint32 value; }
|
||||||
|
Uint64: { uint64 value; }
|
||||||
|
Int8: { int8 value; }
|
||||||
|
Int16: { int16 value; }
|
||||||
|
Int32: { int32 value; }
|
||||||
|
Int64: { int64 value; }
|
||||||
|
Float32: { float32 value; }
|
||||||
|
Float64: { float64 value; }
|
||||||
|
String: { String value; }
|
||||||
|
FS: { FSPrimitive<fsFormat> index; }
|
||||||
|
Array: {
|
||||||
|
uint32 count;
|
||||||
|
Value[count] values;
|
||||||
|
}
|
||||||
|
Object: {
|
||||||
|
uint32 count;
|
||||||
|
StringValue[count] keys;
|
||||||
|
Value[count] values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Team
|
||||||
|
|
||||||
|
- TrèsAbhi: creator & programmer
|
||||||
|
- Prince_NA: game advisor & tester
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
- S0AP: bot verification process & initial advertizement platform
|
||||||
|
- Vovko: discord bot rendering pipeline
|
||||||
|
- Maddox: game file decompression
|
||||||
|
- Pyogenics: tank model decompression
|
||||||
|
- Aeson: game files layout
|
||||||
|
- Minitelrose, ChickenMan7777: 3-caliber rule edge cases
|
||||||
|
- \_34, HisRoyalFatness, Synx, xkdkw: embed UX
|
||||||
|
- [OPTML], Aeson, \_34, Droodles: beta testing tankopedia
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Damage Per Minute (DPM)
|
||||||
|
|
||||||
|
The damage per minute of a tank is the average damage that can be dealt in that tank with the first shell (usually AP) in 60 seconds.
|
||||||
|
|
||||||
|
## Regular and Auto Loaders
|
||||||
|
|
||||||
|
The damage per minute for these types of guns are calculated by allowing the gun to shoot as soon as the shell is loaded (and in the case of auto loaders, the clip is dumped as fast as the inter-clip time will allow).
|
||||||
|
|
||||||
|
## Auto Reloaders
|
||||||
|
|
||||||
|
These types of guns have 3 DPM values.
|
||||||
|
|
||||||
|
- Damage per minute: calculated if you were to treat the shells like a normal auto loader where you dump all shells, wait for all shells to reload, and repeat.
|
||||||
|
- Maximum: some tanks gain DPM the deeper they go into the clip and others maintain a higher DPM the less shells used. The "maximum" DPM is calculated if you were to treat the gun as a single-shot regular gun with the shell with the lowest reload. The shell with the highest DPM is listed as "Optimal shell index."
|
||||||
|
- Effective: this is the maximum DPM tacked on with dumping the remaining shells at the beginning or the end of the 60 seconds.
|
||||||
|
- If "Optimal shell index" is 1, the clip must be dumped first then used as a single shot.
|
||||||
|
- If "Optimal shell index" is any other number, the gun should be treated as a single shot then dumped for the highest effective DPM.
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Installing Blitzkrieg
|
|
||||||
|
|
||||||
It's easy as 1, 2, 3!
|
|
||||||
|
|
||||||
## Step 1
|
|
||||||
|
|
||||||
Join a server that already has Blitzkrieg or [join our official Discord server](https://discord.gg/nDt7AjGJQH).
|
|
||||||
|
|
||||||
## Step 2
|
|
||||||
|
|
||||||
View the bot's profile and click "Add to Server".
|
|
||||||
|
|
||||||
<video src="https://i.imgur.com/Zq0P3m2.mp4" autoplay loop muted width=320 title="how to install"></video>
|
|
||||||
|
|
||||||
## Step 3
|
|
||||||
|
|
||||||
Review the permissions the bot is asking for and add it to your server!
|
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
Blitzkrieg is a multipurpose bot for anything and everything World of Tanks Blitz.
|
🎉 Services for everything and anything World of Tanks Blitz
|
||||||
|
|
||||||
|
## Bot
|
||||||
|
|
||||||
|
Blitzkrieg is available as a Discord bot and can be [installed very easily](/guide/invite).
|
||||||
|
|
||||||
- Track statistics
|
- Track statistics
|
||||||
- Find inactive players in a clan
|
- Find inactive players in a clan
|
||||||
@@ -8,3 +12,11 @@ Blitzkrieg is a multipurpose bot for anything and everything World of Tanks Blit
|
|||||||
- Create embeds for streams
|
- Create embeds for streams
|
||||||
- Track a player/tanks statistical evolution
|
- Track a player/tanks statistical evolution
|
||||||
- ...and a variety of other similar things
|
- ...and a variety of other similar things
|
||||||
|
|
||||||
|
## Website
|
||||||
|
|
||||||
|
Provides a bunch of very helpful tools; https://blitz-krieg.vercel.app/
|
||||||
|
|
||||||
|
- Session tracker
|
||||||
|
- Rating leaderboard
|
||||||
|
- Way more to come
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Permissions
|
|
||||||
|
|
||||||
The following Discord permissions are required by the bot to ensure full functionality:
|
|
||||||
|
|
||||||
- Manage nicknames
|
|
||||||
- Read messages / view channels
|
|
||||||
- Attach files
|
|
||||||
@@ -12,10 +12,10 @@ hero:
|
|||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: Add to Discord Server
|
text: Add to Discord Server
|
||||||
link: guide/install
|
link: /guide/invite
|
||||||
- theme: alt
|
- theme: alt
|
||||||
text: Guide
|
text: Guide
|
||||||
link: /guide/about
|
link: /guide/introduction
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: Clean and Efficient UI
|
- title: Clean and Efficient UI
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 183 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
/** @type {import('next-sitemap').IConfig} */
|
||||||
|
module.exports = {
|
||||||
|
siteUrl: process.env.SITE_URL || 'https://blitz-krieg.vercel.app',
|
||||||
|
generateRobotsTxt: true,
|
||||||
|
sourceDir: 'dist/website',
|
||||||
|
};
|
||||||
@@ -1,12 +1,21 @@
|
|||||||
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
|
import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin';
|
||||||
|
|
||||||
const withVanillaExtract = createVanillaExtractPlugin();
|
const withVanillaExtract = createVanillaExtractPlugin({ tests: /\.css$/ });
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
...withVanillaExtract(),
|
...withVanillaExtract({
|
||||||
|
webpack: (config) => {
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.glsl$/,
|
||||||
|
type: 'asset/source',
|
||||||
|
});
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
distDir: 'dist/website',
|
distDir: 'dist/website',
|
||||||
|
reactStrictMode: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"main": "server.js",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"start": "node --enable-source-maps server.cjs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +1,102 @@
|
|||||||
{
|
{
|
||||||
"name": "blitzkrieg",
|
"name": "blitzkrieg",
|
||||||
"version": "1.14.0",
|
"version": "1.18.2",
|
||||||
"description": "🎉 Tools for everything World of Tanks Blitz",
|
"description": "🎉 Tools for everything World of Tanks Blitz",
|
||||||
"main": "src/server.ts",
|
"main": "src/server.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:bot": "vite-node --script scripts/build",
|
"build:bot": "vite-node --script scripts/build",
|
||||||
"build:website": "next build",
|
"build:website": "next build && next-sitemap --config next-sitemap.config.cjs",
|
||||||
"build:docs": "vitepress build docs",
|
"build:docs": "vitepress build docs",
|
||||||
"build:ratingsleaderboard": "vite-node --script scripts/buildRatingsLeaderboard",
|
"build:ratingleaderboard": "vite-node --script scripts/buildRatingLeaderboard",
|
||||||
"dev:bot": "yarn build:bot && yarn start:bot",
|
"build:assets": "vite-node --max_old_space_size=16384 --script scripts/buildAssets/index",
|
||||||
|
"build:test": "vite-node --script scripts/buildTest",
|
||||||
|
"dev:bot": "vite-node --script scripts/build --production && yarn start:bot",
|
||||||
"dev:docs": "vitepress dev docs",
|
"dev:docs": "vitepress dev docs",
|
||||||
"dev:website": "next dev",
|
"dev:website": "next dev",
|
||||||
"start:bot": "node --enable-source-maps dist/bot/index.cjs",
|
"start:bot": "node --enable-source-maps dist/bot/index.cjs",
|
||||||
"start:website": "next start",
|
"start:website": "next start",
|
||||||
"host:docs": "vitepress preview docs",
|
"host:docs": "vitepress preview docs",
|
||||||
"publish:ratingsleaderboard": "vite-node --script scripts/buildRatingsLeaderboard --publish",
|
"publish:ratingleaderboard": "vite-node --script scripts/buildRatingLeaderboard --publish",
|
||||||
"zip": "zip -r dist.zip dist",
|
"setup:patches": "vite-node --script scripts/applyPatches",
|
||||||
"lint": "npx tsc",
|
"lint": "npx tsc",
|
||||||
"lint:website": "next lint",
|
"lint:website": "next lint",
|
||||||
"format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\"",
|
"format": "prettier --write \"**/*.@(json|js|jsx|css|md|ts|tsx|html|xml|yml|gltf)\"",
|
||||||
|
"lint:version": "vite-node --script scripts/checkVersionMissMatch",
|
||||||
"knip": "knip",
|
"knip": "knip",
|
||||||
"update": "yarn upgrade --latest"
|
"update": "yarn upgrade --latest",
|
||||||
|
"setup:depotdownloader": "vite-node --script scripts/setupDepotDownloader",
|
||||||
|
"tunnel": "cloudflared tunnel --url http://localhost:3000"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@gltf-transform/core": "^3.9.0",
|
||||||
|
"@octokit/plugin-throttling": "^8.1.3",
|
||||||
"@octokit/rest": "^20.0.1",
|
"@octokit/rest": "^20.0.1",
|
||||||
"@prisma/client": "^5.4.1",
|
"@prisma/client": "^5.4.1",
|
||||||
"@radix-ui/colors": "^3.0.0-rc.4",
|
"@radix-ui/colors": "^3.0.0",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/themes": "^1.1.2",
|
"@radix-ui/themes": "^2.0.1",
|
||||||
|
"@react-three/drei": "^9.93.0",
|
||||||
|
"@react-three/fiber": "^8.15.14",
|
||||||
"@resvg/resvg-js": "^2.4.1",
|
"@resvg/resvg-js": "^2.4.1",
|
||||||
|
"@types/three": "^0.160.0",
|
||||||
"@vanilla-extract/css": "^1.13.0",
|
"@vanilla-extract/css": "^1.13.0",
|
||||||
"bepaint": "^0.1.0-beta.3",
|
"bepaint": "^0.1.0-beta.3",
|
||||||
|
"decompress": "^4.2.1",
|
||||||
"discord.js": "^14.13.0",
|
"discord.js": "^14.13.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.19.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"false": "^0.0.4",
|
||||||
"fuzzysort": "^2.0.4",
|
"fuzzysort": "^2.0.4",
|
||||||
"immer": "^10.0.2",
|
"immer": "^10.0.2",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"lz4js": "^0.2.0",
|
||||||
"markdown-escape": "^2.0.0",
|
"markdown-escape": "^2.0.0",
|
||||||
"next": "^13.5.2",
|
"next": "^14.1.0",
|
||||||
|
"next-sitemap": "^4.2.3",
|
||||||
|
"parse-dds": "^1.2.1",
|
||||||
|
"postprocessing": "^6.34.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-fuzzysort": "^1.0.1",
|
"react-fuzzysort": "^1.0.1",
|
||||||
"satori": "^0.10.8",
|
"react-promise-suspense": "^0.3.4",
|
||||||
|
"react-spinners": "^0.13.8",
|
||||||
|
"satori": "^0.10.13",
|
||||||
|
"sharp": "0.33.1",
|
||||||
|
"three": "0.159.0",
|
||||||
|
"three-stdlib": "^2.29.4",
|
||||||
"vite-node": "^0.34.5",
|
"vite-node": "^0.34.5",
|
||||||
"vitepress": "^1.0.0-rc.20",
|
"vitepress": "^1.0.0-rc.20",
|
||||||
"vitepress-plugin-auto-sidebar": "^1.1.0",
|
"vitepress-plugin-auto-sidebar": "^1.1.0",
|
||||||
|
"yaml": "^2.3.4",
|
||||||
"zustand": "^4.4.1"
|
"zustand": "^4.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@total-typescript/ts-reset": "^0.5.1",
|
"@total-typescript/ts-reset": "^0.5.1",
|
||||||
|
"@types/decompress": "^4.2.7",
|
||||||
"@types/escape-html": "^1.0.2",
|
"@types/escape-html": "^1.0.2",
|
||||||
"@types/express": "^4.17.18",
|
"@types/express": "^4.17.18",
|
||||||
|
"@types/js-yaml": "^4.0.8",
|
||||||
"@types/lodash": "^4.14.199",
|
"@types/lodash": "^4.14.199",
|
||||||
|
"@types/lz4": "^0.6.4",
|
||||||
"@types/markdown-escape": "^1.1.0",
|
"@types/markdown-escape": "^1.1.0",
|
||||||
"@types/node": "^20.6.5",
|
"@types/node": "^20.6.5",
|
||||||
|
"@types/parse-dds": "^1.0.3",
|
||||||
|
"@types/pngjs": "^6.0.4",
|
||||||
"@types/react": "^18.2.22",
|
"@types/react": "^18.2.22",
|
||||||
"@vanilla-extract/next-plugin": "^2.3.1",
|
"@vanilla-extract/next-plugin": "^2.3.1",
|
||||||
"compare-versions": "^6.1.0",
|
"compare-versions": "^6.1.0",
|
||||||
"knip": "^2.27.1",
|
"crc": "^4.3.2",
|
||||||
|
"fast-xml-parser": "^4.3.2",
|
||||||
|
"knip": "^3.4.0",
|
||||||
|
"lz4": "^0.6.5",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"prisma": "^5.4.1",
|
"prisma": "^5.4.1",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
}
|
},
|
||||||
|
"packageManager": "[email protected]"
|
||||||
}
|
}
|
||||||
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 8.2 MiB After Width: | Height: | Size: 5.4 MiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 3.8 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 1.3 MiB |
@@ -0,0 +1,48 @@
|
|||||||
|
import { mkdir, writeFile } from 'fs/promises';
|
||||||
|
import { parse as parsePath } from 'path';
|
||||||
|
import { parse as parseYaml } from 'yaml';
|
||||||
|
import { readStringDVPL } from '../src/core/blitz/readStringDVPL';
|
||||||
|
import { writeDVPL } from '../src/core/blitz/writeDVPL';
|
||||||
|
import { secrets } from '../src/core/blitzkrieg/secrets';
|
||||||
|
import { dvp } from '../submodules/closedkrieg/src/dvp';
|
||||||
|
import { DATA } from './buildAssets/constants';
|
||||||
|
|
||||||
|
const versionTextFile = await readStringDVPL(`${DATA}/version.txt.dvpl`);
|
||||||
|
const currentVersion = versionTextFile
|
||||||
|
.split(' ')[0]
|
||||||
|
.split('.')
|
||||||
|
.slice(0, 3)
|
||||||
|
.join('.');
|
||||||
|
|
||||||
|
console.log(`Installing patches for ${currentVersion}...`);
|
||||||
|
|
||||||
|
let patchIndex = 1;
|
||||||
|
while (true) {
|
||||||
|
const response = await fetch(
|
||||||
|
`${secrets.WOTB_DLC_CDN}/dlc/s${currentVersion}_${patchIndex}.yaml`,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
console.log(`Applying patch ${patchIndex}...`);
|
||||||
|
|
||||||
|
const data = parseYaml(await response.text());
|
||||||
|
const dvpm = await fetch(`${secrets.WOTB_DLC_CDN}/dlc/${data.dx11}`).then(
|
||||||
|
(response) => response.arrayBuffer(),
|
||||||
|
);
|
||||||
|
const dvpd = await fetch(
|
||||||
|
`${secrets.WOTB_DLC_CDN}/dlc/${data.dx11.replace('.dvpm', '.dvpd')}`,
|
||||||
|
).then((response) => response.arrayBuffer());
|
||||||
|
const files = await dvp(dvpm, dvpd);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
files.map(async ({ path, data }) => {
|
||||||
|
const { dir } = parsePath(path);
|
||||||
|
|
||||||
|
await mkdir(`${DATA}/${dir}`, { recursive: true });
|
||||||
|
await writeFile(`${DATA}/${path}.dvpl`, writeDVPL(Buffer.from(data)));
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
patchIndex++;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
|
import { exec } from 'child_process';
|
||||||
import { build } from 'esbuild';
|
import { build } from 'esbuild';
|
||||||
import { cp, readdir } from 'fs/promises';
|
import { cp, readdir } from 'fs/promises';
|
||||||
|
import { argv } from 'process';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
|
||||||
readdir('src/workers').then((workers) => {
|
const execPromise = promisify(exec);
|
||||||
|
const isProduction = argv.includes('--production');
|
||||||
|
|
||||||
|
await readdir('src/workers').then((workers) => {
|
||||||
const files = [
|
const files = [
|
||||||
'bot',
|
'bot',
|
||||||
'index',
|
'index',
|
||||||
@@ -25,9 +31,10 @@ readdir('src/workers').then((workers) => {
|
|||||||
'.js': '.cjs',
|
'.js': '.cjs',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
external: ['sharp'],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
minifyIdentifiers: false, // cause goofy errors
|
minifyIdentifiers: false, // causes goofy errors
|
||||||
minifySyntax: true,
|
minifySyntax: true,
|
||||||
minifyWhitespace: true,
|
minifyWhitespace: true,
|
||||||
|
|
||||||
@@ -36,9 +43,19 @@ readdir('src/workers').then((workers) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// copy schema.prisma
|
// copy schema.prisma
|
||||||
cp('prisma/schema.prisma', 'dist/bot/schema.prisma');
|
await cp('prisma/schema.prisma', 'dist/bot/schema.prisma');
|
||||||
readdir('node_modules/prisma').then((files) =>
|
await readdir('node_modules/prisma').then((files) =>
|
||||||
files
|
files
|
||||||
.filter((file) => file.endsWith('.node'))
|
.filter((file) => file.endsWith('.node'))
|
||||||
.map((file) => cp(`node_modules/prisma/${file}`, `dist/bot/${file}`)),
|
.map((file) => cp(`node_modules/prisma/${file}`, `dist/bot/${file}`)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isProduction) {
|
||||||
|
// install fixed sharp
|
||||||
|
console.log('Installing fixed sharp...');
|
||||||
|
await execPromise('yarn init -y && yarn add [email protected] --ignore-engines', {
|
||||||
|
cwd: 'dist/bot',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Generated:', await readdir('dist/bot'));
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import sharp from 'sharp';
|
||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { readStringDVPL } from '../../src/core/blitz/readStringDVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function boosterIcons(production: boolean) {
|
||||||
|
const boosterFiles = (await readdir(`${DATA}/${POI.boosterIcons}`)).filter(
|
||||||
|
(file) => !file.endsWith('@2x.txt.dvpl') && !file.startsWith('texture0'),
|
||||||
|
);
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(`${DATA}/${POI.boosterIcons}/texture0.packed.webp.dvpl`),
|
||||||
|
);
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
boosterFiles.map(async (file) => {
|
||||||
|
const name = file.match(/booster_(.+).txt.dvpl/)![1];
|
||||||
|
const sizes = (
|
||||||
|
await readStringDVPL(`${DATA}/${POI.boosterIcons}/${file}`)
|
||||||
|
)
|
||||||
|
.split('\n')[4]
|
||||||
|
.split(' ')
|
||||||
|
.map(Number);
|
||||||
|
const content = (
|
||||||
|
await image
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/boosters/${name}.webp`,
|
||||||
|
content,
|
||||||
|
encoding: 'base64',
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('booster icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function camouflageIcons(production: boolean) {
|
||||||
|
console.log('Building camouflage icons...');
|
||||||
|
const content = await readDVPLFile(
|
||||||
|
`${DATA}/${POI.defaultCamoIcon.replace('.webp', '.packed.webp.dvpl')}`,
|
||||||
|
).then((content) => content.toString('base64'));
|
||||||
|
const changes: FileChange[] = [
|
||||||
|
{
|
||||||
|
content,
|
||||||
|
encoding: 'base64',
|
||||||
|
path: 'icons/camo.webp',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await commitAssets('camo icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function circleFlags(production: boolean) {
|
||||||
|
const flags = await readdir(`${DATA}/${POI.flags}`);
|
||||||
|
const changes = await Promise.all(
|
||||||
|
flags
|
||||||
|
.filter(
|
||||||
|
(flag) =>
|
||||||
|
flag.startsWith('flag_profile-stat_') &&
|
||||||
|
!flag.endsWith('@2x.packed.webp.dvpl'),
|
||||||
|
)
|
||||||
|
.map(async (flag) => {
|
||||||
|
const content = await readBase64DVPL(`${DATA}/${POI.flags}/${flag}`);
|
||||||
|
const name = flag.match(/flag_profile-stat_(.+)\.packed\.webp/)![1];
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `flags/circle/${name}.webp`,
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('circle flags', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { argv } from 'process';
|
||||||
|
|
||||||
|
const isDepot = argv.includes('--depot');
|
||||||
|
export const WOTB_WIN32_DEPOT = 444202;
|
||||||
|
export const DATA = isDepot
|
||||||
|
? await (async () => {
|
||||||
|
const [installationVersion] = await readdir(`depots/${WOTB_WIN32_DEPOT}`);
|
||||||
|
return `depots/${WOTB_WIN32_DEPOT}/${installationVersion}/Data`;
|
||||||
|
})()
|
||||||
|
: 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data';
|
||||||
|
|
||||||
|
export const POI = {
|
||||||
|
vehicleDefinitions: 'XML/item_defs/vehicles',
|
||||||
|
strings: 'Strings',
|
||||||
|
cachedStrings: 'https://stufficons.wgcdn.co/localizations/en.yaml',
|
||||||
|
tankParameters: '3d/Tanks/Parameters',
|
||||||
|
smallIcons: 'Gfx/UI/BattleScreenHUD/SmallTankIcons',
|
||||||
|
bigIcons: 'Gfx/UI/BigTankIcons',
|
||||||
|
flags: 'Gfx/Lobby/flags',
|
||||||
|
'3d': '3d',
|
||||||
|
bigShellIcons: 'Gfx/Shared/tank-supply/ammunition/big',
|
||||||
|
moduleIcons: 'Gfx/UI/ModulesTechTree',
|
||||||
|
collisionMeshes: '3d/Tanks/CollisionMeshes',
|
||||||
|
optionalDevices: 'XML/item_defs/vehicles/common/optional_devices.xml',
|
||||||
|
optionalDeviceSlots:
|
||||||
|
'XML/item_defs/vehicles/common/optional_device_slots.xml',
|
||||||
|
optionalDeviceImageMappings:
|
||||||
|
'UI/Screens3/Lobby/Inventory/OptionalDevices/OptionalDevicesItemImage.style.yaml',
|
||||||
|
optionalDevicesImage:
|
||||||
|
'Gfx/UI/InventoryIcons/Big/OptionalDevices/texture0.packed.webp',
|
||||||
|
consumablesCommon: 'XML/item_defs/vehicles/common/consumables/common.xml',
|
||||||
|
consumableIcons: 'Gfx/UI/InventoryIcons/Big/Consumables',
|
||||||
|
provisionIcons: 'Gfx/UI/InventoryIcons/Big/Provisions',
|
||||||
|
equipmentItemImageMappings:
|
||||||
|
'UI/Screens3/Lobby/Inventory/Equipment/EquipmentItemImage.style.yaml',
|
||||||
|
provisionsCommon: 'XML/item_defs/vehicles/common/provisions/common.xml',
|
||||||
|
defaultCamoIcon: 'Gfx/UI/Hangar/IconCamouflage.webp',
|
||||||
|
boosterIcons: 'Gfx/Shared/boosters',
|
||||||
|
} as const;
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
import sharp from 'sharp';
|
||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { readStringDVPL } from '../../src/core/blitz/readStringDVPL';
|
||||||
|
import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL';
|
||||||
|
import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
import { ConsumablesCommon, ProvisionsCommon } from './definitions';
|
||||||
|
|
||||||
|
interface Mappings {
|
||||||
|
Header: { version: number };
|
||||||
|
StyleSheets: {
|
||||||
|
selectors: string[];
|
||||||
|
properties: { 'bg-sprite': string };
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function consumableProvisionIcons(production: boolean) {
|
||||||
|
console.log('Building consumable and provision icons...');
|
||||||
|
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
const consumablesTexture = sharp(
|
||||||
|
await readDVPLFile(
|
||||||
|
`${DATA}/${POI.consumableIcons}/texture0.packed.webp.dvpl`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const provisionsTexture = sharp(
|
||||||
|
await readDVPLFile(
|
||||||
|
`${DATA}/${POI.provisionIcons}/texture0.packed.webp.dvpl`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const equipmentItemImageMappings = await readYAMLDVPL<Mappings>(
|
||||||
|
`${DATA}/${POI.equipmentItemImageMappings}.dvpl`,
|
||||||
|
);
|
||||||
|
const consumablesCommon = await readXMLDVPL<{
|
||||||
|
root: ConsumablesCommon;
|
||||||
|
}>(`${DATA}/${POI.consumablesCommon}.dvpl`);
|
||||||
|
const provisionsCommon = await readXMLDVPL<{
|
||||||
|
root: ProvisionsCommon;
|
||||||
|
}>(`${DATA}/${POI.provisionsCommon}.dvpl`);
|
||||||
|
const styleSheets = Object.values(equipmentItemImageMappings.StyleSheets);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.values(consumablesCommon.root).map(async (consumable) => {
|
||||||
|
const styleSheet = styleSheets.find((styleSheet) =>
|
||||||
|
styleSheet.selectors.includes(
|
||||||
|
`.equipment_item.${consumable.icon} * .equipment-img`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!styleSheet) {
|
||||||
|
console.warn(
|
||||||
|
`No style sheet found for consumable ${consumable.icon}; skipping...`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configPath = styleSheet.properties['bg-sprite']
|
||||||
|
.replace('~res:/', '')
|
||||||
|
.replace('.psd', '')
|
||||||
|
.replace('.txt', '');
|
||||||
|
|
||||||
|
if (configPath.startsWith('Gfx/Shared')) {
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`),
|
||||||
|
);
|
||||||
|
const content = (
|
||||||
|
await image.trim({ threshold: 100 }).toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/consumables/${consumable.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||||
|
.split('\n')[4]
|
||||||
|
.split(' ')
|
||||||
|
.map(Number);
|
||||||
|
const content = (
|
||||||
|
await consumablesTexture
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/consumables/${consumable.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.values(provisionsCommon.root).map(async (provision) => {
|
||||||
|
const styleSheet = styleSheets.find((styleSheet) =>
|
||||||
|
styleSheet.selectors.includes(
|
||||||
|
`.equipment_item.${provision.icon} * .equipment-img`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!styleSheet) {
|
||||||
|
console.warn(
|
||||||
|
`No style sheet found for provision ${provision.icon}; skipping...`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configPath = styleSheet.properties['bg-sprite']
|
||||||
|
.replace('~res:/', '')
|
||||||
|
.replace('.psd', '')
|
||||||
|
.replace('.txt', '');
|
||||||
|
|
||||||
|
if (configPath.startsWith('Gfx/Shared')) {
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(`${DATA}/${configPath}.packed.webp.dvpl`),
|
||||||
|
);
|
||||||
|
const content = (
|
||||||
|
await image.trim({ threshold: 100 }).toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/provisions/${provision.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const sizes = (await readStringDVPL(`${DATA}/${configPath}.txt.dvpl`))
|
||||||
|
.split('\n')[4]
|
||||||
|
.split(' ')
|
||||||
|
.map(Number);
|
||||||
|
const content = (
|
||||||
|
await provisionsTexture
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/provisions/${provision.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('consumable and provision icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import sharp from 'sharp';
|
||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA } from './constants';
|
||||||
|
|
||||||
|
const ICONS = [
|
||||||
|
['currency_silver_m.packed.webp', 'silver'],
|
||||||
|
['currency_premium_xl.packed.webp', 'premium'],
|
||||||
|
['currency_gold_m.packed.webp', 'gold'],
|
||||||
|
['currency_free-xp_xl.packed.webp', 'free-xp'],
|
||||||
|
['currency_elite-xp_xl.packed.webp', 'elite-xp'],
|
||||||
|
['currency_crew-xp_xl.packed.webp', 'crew-xp'],
|
||||||
|
['currency_battle-xp_xl.packed.webp', 'xp'],
|
||||||
|
];
|
||||||
|
|
||||||
|
export async function currencies(production: boolean) {
|
||||||
|
console.log('Building currency icons...');
|
||||||
|
|
||||||
|
const changes = await Promise.all(
|
||||||
|
ICONS.map(async ([file, name]) => {
|
||||||
|
const content = (
|
||||||
|
await sharp(
|
||||||
|
await readDVPLFile(`${DATA}/Gfx/Lobby/currency/${file}.dvpl`),
|
||||||
|
)
|
||||||
|
.trim()
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `icons/currencies/${name}.webp`,
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('currency icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import sharp from 'sharp';
|
||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { readStringDVPL } from '../../src/core/blitz/readStringDVPL';
|
||||||
|
import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL';
|
||||||
|
import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
import { OptionalDevices } from './definitions';
|
||||||
|
|
||||||
|
interface Mappings {
|
||||||
|
Header: { version: number };
|
||||||
|
|
||||||
|
StyleSheets: {
|
||||||
|
selectors: string[];
|
||||||
|
properties: { 'bg-sprite': string };
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function equipmentIcons(production: boolean) {
|
||||||
|
console.log('Building equipment icons...');
|
||||||
|
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
const optionalDevices = await readXMLDVPL<{ root: OptionalDevices }>(
|
||||||
|
`${DATA}/${POI.optionalDevices}.dvpl`,
|
||||||
|
);
|
||||||
|
const mappings = await readYAMLDVPL<Mappings>(
|
||||||
|
`${DATA}/${POI.optionalDeviceImageMappings}.dvpl`,
|
||||||
|
);
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(`${DATA}/${POI.optionalDevicesImage}.dvpl`),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(optionalDevices.root).map(
|
||||||
|
async ([optionalDeviceKey, optionalDevice]) => {
|
||||||
|
if (optionalDeviceKey === 'nextAvailableId') return;
|
||||||
|
|
||||||
|
const mapping = mappings.StyleSheets.find((mapping) =>
|
||||||
|
mapping.selectors.includes(
|
||||||
|
`.optional_device_item.${optionalDevice.icon} #Img`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mapping) {
|
||||||
|
console.warn(
|
||||||
|
`No mapping found for ${optionalDevice.icon}; skipping...`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configPathRaw = mapping.properties['bg-sprite'];
|
||||||
|
const configPath = configPathRaw.replace('~res:/', '');
|
||||||
|
|
||||||
|
if (configPath.startsWith('Gfx/Lobby')) {
|
||||||
|
const configPathWebp = configPath.replace('.txt', '');
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(`${DATA}/${configPathWebp}.packed.webp.dvpl`),
|
||||||
|
);
|
||||||
|
const content = (await image.trim().toBuffer()).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/equipment/${optionalDevice.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const config = await readStringDVPL(`${DATA}/${configPath}.dvpl`);
|
||||||
|
const sizes = config.split('\n')[4].split(' ').map(Number);
|
||||||
|
const content = (
|
||||||
|
await image
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `icons/equipment/${optionalDevice.id}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('equipment icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { config } from 'dotenv';
|
||||||
|
import { argv } from 'process';
|
||||||
|
|
||||||
|
config();
|
||||||
|
|
||||||
|
const allTargets = argv.includes('--all-targets');
|
||||||
|
const targets = argv
|
||||||
|
.find((argument) => argument.startsWith('--target'))
|
||||||
|
?.split('=')[1]
|
||||||
|
.split(',');
|
||||||
|
const production = argv.includes('--production');
|
||||||
|
|
||||||
|
import { boosterIcons } from './boosterIcons';
|
||||||
|
import { camouflageIcons } from './camouflageIcons';
|
||||||
|
import { circleFlags } from './circleFlags';
|
||||||
|
import { consumableProvisionIcons } from './consumableProvisionIcons';
|
||||||
|
import { currencies } from './currencies';
|
||||||
|
import { definitions } from './definitions';
|
||||||
|
import { equipmentIcons } from './equipmentIcons';
|
||||||
|
import { moduleIcons } from './moduleIcons';
|
||||||
|
import { scratchedFlags } from './scratchedFlags';
|
||||||
|
import { shellIcons } from './shellIcons';
|
||||||
|
import { tankArmors } from './tankArmors';
|
||||||
|
import { tankIcons } from './tankIcons';
|
||||||
|
import { tankModels } from './tankModels';
|
||||||
|
|
||||||
|
if (!targets && !allTargets) throw new Error('No target(s) specified');
|
||||||
|
|
||||||
|
const methods = [
|
||||||
|
definitions,
|
||||||
|
tankIcons,
|
||||||
|
scratchedFlags,
|
||||||
|
circleFlags,
|
||||||
|
shellIcons,
|
||||||
|
moduleIcons,
|
||||||
|
equipmentIcons,
|
||||||
|
consumableProvisionIcons,
|
||||||
|
camouflageIcons,
|
||||||
|
boosterIcons,
|
||||||
|
tankArmors,
|
||||||
|
tankModels,
|
||||||
|
currencies,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const method of methods) {
|
||||||
|
if (allTargets || targets?.includes(method.name)) await method(production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function moduleIcons(production: boolean) {
|
||||||
|
console.log('Building module icons...');
|
||||||
|
|
||||||
|
const changes = await Promise.all(
|
||||||
|
(await readdir(`${DATA}/${POI.moduleIcons}`))
|
||||||
|
.filter(
|
||||||
|
(file) =>
|
||||||
|
!file.endsWith('@2x.packed.webp.dvpl') && file.startsWith('vehicle'),
|
||||||
|
)
|
||||||
|
.map(async (file) => {
|
||||||
|
const nameRaw = file.match(/vehicle(.+)\.packed\.webp\.dvpl/)![1];
|
||||||
|
const name = nameRaw[0].toLowerCase() + nameRaw.slice(1);
|
||||||
|
const content = await readBase64DVPL(
|
||||||
|
`${DATA}/${POI.moduleIcons}/${file}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
path: `icons/modules/${name}.webp`,
|
||||||
|
encoding: 'base64',
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('module icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function scratchedFlags(production: boolean) {
|
||||||
|
console.log('Building scratched flags...');
|
||||||
|
|
||||||
|
const flags = await readdir(`${DATA}/${POI.flags}`);
|
||||||
|
const changes = await Promise.all(
|
||||||
|
flags
|
||||||
|
.filter(
|
||||||
|
(flag) =>
|
||||||
|
flag.startsWith('flag_tutor-tank_') &&
|
||||||
|
!flag.endsWith('@2x.packed.webp.dvpl'),
|
||||||
|
)
|
||||||
|
.map(async (flag) => {
|
||||||
|
const content = await readBase64DVPL(`${DATA}/${POI.flags}/${flag}`);
|
||||||
|
const name = flag.match(/flag_tutor-tank_(.+)\.packed\.webp/)![1];
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `flags/scratched/${name}.webp`,
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('scratched flags', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import sharp from 'sharp';
|
||||||
|
import { readDVPLFile } from '../../src/core/blitz/readDVPLFile';
|
||||||
|
import { readStringDVPL } from '../../src/core/blitz/readStringDVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
|
||||||
|
export async function shellIcons(production: boolean) {
|
||||||
|
console.log('Building shell icons...');
|
||||||
|
|
||||||
|
const image = sharp(
|
||||||
|
await readDVPLFile(
|
||||||
|
`${DATA}/${POI.bigShellIcons}/texture0.packed.webp.dvpl`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const changes = await Promise.all(
|
||||||
|
(await readdir(`${DATA}/${POI.bigShellIcons}`))
|
||||||
|
.filter((file) => file.endsWith('_l.txt.dvpl'))
|
||||||
|
.map(async (file) => {
|
||||||
|
const name = file.match(/(.+)_l\.txt\.dvpl/)![1];
|
||||||
|
const sizes = (
|
||||||
|
await readStringDVPL(`${DATA}/${POI.bigShellIcons}/${file}`)
|
||||||
|
)
|
||||||
|
.split('\n')[4]
|
||||||
|
.split(' ')
|
||||||
|
.map(Number);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: (
|
||||||
|
await image
|
||||||
|
.clone()
|
||||||
|
.extract({
|
||||||
|
left: sizes[0],
|
||||||
|
top: sizes[1],
|
||||||
|
width: sizes[2],
|
||||||
|
height: sizes[3],
|
||||||
|
})
|
||||||
|
.toBuffer()
|
||||||
|
).toString('base64'),
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `icons/shells/${name}.webp`,
|
||||||
|
} satisfies FileChange;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('shell icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { NodeIO } from '@gltf-transform/core';
|
||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { extractArmor } from '../../src/core/blitz/extractArmor';
|
||||||
|
import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL';
|
||||||
|
import { toUniqueId } from '../../src/core/blitz/toUniqueId';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
import { VehicleDefinitionList } from './definitions';
|
||||||
|
|
||||||
|
export async function tankArmors(production: boolean) {
|
||||||
|
console.log('Building tank armors...');
|
||||||
|
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
const nodeIO = new NodeIO();
|
||||||
|
const nations = await readdir(`${DATA}/${POI.vehicleDefinitions}`).then(
|
||||||
|
(nations) => nations.filter((nation) => nation !== 'common'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
nations.map(async (nation) => {
|
||||||
|
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||||
|
`${DATA}/${POI.vehicleDefinitions}/${nation}/list.xml.dvpl`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(tanks.root).map(async ([tankKey, tank]) => {
|
||||||
|
if (tankKey.includes('tutorial_bot')) return;
|
||||||
|
|
||||||
|
const id = toUniqueId(nation, tank.id);
|
||||||
|
|
||||||
|
console.log(`Building armor ${id} @ ${nation}/${tankKey}`);
|
||||||
|
|
||||||
|
const model = await extractArmor(DATA, `${nation}-${tankKey}`);
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `3d/tanks/armor/${id}.glb`,
|
||||||
|
encoding: 'base64',
|
||||||
|
content: Buffer.from(await nodeIO.writeBinary(model)).toString(
|
||||||
|
'base64',
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('tank armor', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { Vector3Tuple } from 'three';
|
||||||
|
import { NATION_IDS } from '../../src/constants/nations';
|
||||||
|
import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL';
|
||||||
|
import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL';
|
||||||
|
import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
import { VehicleDefinitionList } from './definitions';
|
||||||
|
|
||||||
|
export interface TankParameters {
|
||||||
|
resourcesPath: {
|
||||||
|
smallIconPath: string;
|
||||||
|
bigIconPath: string;
|
||||||
|
blitzModelPath: string;
|
||||||
|
};
|
||||||
|
collision: {
|
||||||
|
[key: string]: {
|
||||||
|
points: Vector3Tuple;
|
||||||
|
bbox: {
|
||||||
|
min: Vector3Tuple;
|
||||||
|
max: Vector3Tuple;
|
||||||
|
};
|
||||||
|
averageThickness?: Record<string, number>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tankIcons(production: boolean) {
|
||||||
|
console.log('Building tank icons...');
|
||||||
|
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
const nations = await readdir(`${DATA}/${POI.vehicleDefinitions}`).then(
|
||||||
|
(nations) => nations.filter((nation) => nation !== 'common'),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
nations.map(async (nation) => {
|
||||||
|
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||||
|
`${DATA}/${POI.vehicleDefinitions}/${nation}/list.xml.dvpl`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(tanks.root).map(async ([tankKey, tank]) => {
|
||||||
|
if (tankKey.includes('tutorial_bot')) return;
|
||||||
|
|
||||||
|
const nationVehicleId = tank.id;
|
||||||
|
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
|
||||||
|
const parameters = await readYAMLDVPL<TankParameters>(
|
||||||
|
`${DATA}/${POI.tankParameters}/${nation}/${tankKey}.yaml.dvpl`,
|
||||||
|
);
|
||||||
|
const small = `${DATA}/${parameters.resourcesPath.smallIconPath
|
||||||
|
.replace(/~res:\//, '')
|
||||||
|
.replace(/\..+/, '')}.packed.webp.dvpl`;
|
||||||
|
const big = `${DATA}/${parameters.resourcesPath.bigIconPath
|
||||||
|
.replace(/~res:\//, '')
|
||||||
|
.replace(/\..+/, '')}.packed.webp.dvpl`;
|
||||||
|
|
||||||
|
if (big) {
|
||||||
|
changes.push({
|
||||||
|
content: await readBase64DVPL(big),
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `icons/tanks/big/${id}.webp`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (small) {
|
||||||
|
changes.push({
|
||||||
|
content: await readBase64DVPL(small),
|
||||||
|
encoding: 'base64',
|
||||||
|
path: `icons/tanks/small/${id}.webp`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets('tank icons', changes, production);
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { NodeIO } from '@gltf-transform/core';
|
||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import { extractModel } from '../../src/core/blitz/extractModel';
|
||||||
|
import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL';
|
||||||
|
import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL';
|
||||||
|
import { toUniqueId } from '../../src/core/blitz/toUniqueId';
|
||||||
|
import { commitAssets } from '../../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../../src/core/blitzkrieg/commitMultipleFiles';
|
||||||
|
import { DATA, POI } from './constants';
|
||||||
|
import { VehicleDefinitionList } from './definitions';
|
||||||
|
import { TankParameters } from './tankIcons';
|
||||||
|
|
||||||
|
export async function tankModels(production: boolean) {
|
||||||
|
console.log('Building tank models...');
|
||||||
|
|
||||||
|
const nodeIO = new NodeIO();
|
||||||
|
const nations = await readdir(`${DATA}/${POI.vehicleDefinitions}`).then(
|
||||||
|
(nations) => nations.filter((nation) => nation !== 'common'),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const nationIndex in nations) {
|
||||||
|
const nation = nations[nationIndex];
|
||||||
|
const changes: FileChange[] = [];
|
||||||
|
const tanks = await readXMLDVPL<{ root: VehicleDefinitionList }>(
|
||||||
|
`${DATA}/${POI.vehicleDefinitions}/${nation}/list.xml.dvpl`,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`Building models for ${nation}`);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.entries(tanks.root).map(async ([tankKey, tank]) => {
|
||||||
|
if (tankKey.includes('tutorial_bot')) return;
|
||||||
|
|
||||||
|
const id = toUniqueId(nation, tank.id);
|
||||||
|
|
||||||
|
console.log(`Building model ${id} @ ${nation}/${tankKey}`);
|
||||||
|
|
||||||
|
const parameters = await readYAMLDVPL<TankParameters>(
|
||||||
|
`${DATA}/${POI.tankParameters}/${nation}/${tankKey}.yaml.dvpl`,
|
||||||
|
);
|
||||||
|
const model = await extractModel(
|
||||||
|
DATA,
|
||||||
|
parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ''),
|
||||||
|
);
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
path: `3d/tanks/models/${id}.glb`,
|
||||||
|
content: Buffer.from(await nodeIO.writeBinary(model)).toString(
|
||||||
|
'base64',
|
||||||
|
),
|
||||||
|
encoding: 'base64',
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await commitAssets(`tank models ${nation}`, changes, production);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
import { chunk } from 'lodash';
|
||||||
|
import { argv } from 'process';
|
||||||
|
import {
|
||||||
|
RatingInfo,
|
||||||
|
RatingNeighbors,
|
||||||
|
RatingPlayer,
|
||||||
|
} from '../src/commands/ratingLeaderboard';
|
||||||
|
import { RegionSubdomain } from '../src/constants/regions';
|
||||||
|
import { getAccountInfo } from '../src/core/blitz/getAccountInfo';
|
||||||
|
import regionSubdomainToRegion from '../src/core/blitz/regionSubdomainToRegion';
|
||||||
|
import { commitAssets } from '../src/core/blitzkrieg/commitAssets';
|
||||||
|
import { FileChange } from '../src/core/blitzkrieg/commitMultipleFiles.js';
|
||||||
|
import { patientFetchJSON } from '../src/core/blitzkrieg/patientFetchJSON';
|
||||||
|
import { superCompress } from '../src/core/blitzkrieg/superCompress';
|
||||||
|
import {
|
||||||
|
BkrlBaseEntry,
|
||||||
|
BkrlFormat,
|
||||||
|
BkrlSuperset1Entry,
|
||||||
|
BkrlWriteStream,
|
||||||
|
} from '../src/core/streams/bkrl';
|
||||||
|
import { CdonValue, CdonWriteStream } from '../src/core/streams/cdon';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Central North American Time (UTC-5): use 0 5 * * *.
|
||||||
|
* Central European Time (UTC+1): use 0 23 * * *.
|
||||||
|
* Central Asia Standard Time (UTC+7): use 0 17 * * *.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const production = argv.includes('--production');
|
||||||
|
const target = argv
|
||||||
|
.find((arg) => arg.startsWith('--target='))
|
||||||
|
?.split('=')[1] as 'midnight' | 'latest' | undefined;
|
||||||
|
const regionSubdomains = argv
|
||||||
|
.find((arg) => arg.startsWith('--region='))
|
||||||
|
?.split('=')[1];
|
||||||
|
|
||||||
|
if (!target) throw new Error('Target parameter not specified');
|
||||||
|
if (!regionSubdomains) throw new Error('Region parameter not specified');
|
||||||
|
|
||||||
|
regionSubdomains.split(',').forEach(async (regionSubdomain) => {
|
||||||
|
const region = regionSubdomainToRegion(regionSubdomain as RegionSubdomain);
|
||||||
|
|
||||||
|
console.log(`Building ${target} rating leaderboard for ${region}`);
|
||||||
|
|
||||||
|
const NEIGHBORS = 2 ** 8;
|
||||||
|
const PLAYERS = await patientFetchJSON<RatingInfo>(
|
||||||
|
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||||
|
).then((data) => (data.detail === undefined ? data.count : undefined));
|
||||||
|
|
||||||
|
if (PLAYERS === undefined) {
|
||||||
|
throw new Error('No current rating season running');
|
||||||
|
}
|
||||||
|
|
||||||
|
const players: Record<number, RatingPlayer> = {};
|
||||||
|
const leaderboard: BkrlBaseEntry[] = [];
|
||||||
|
let registered = 0;
|
||||||
|
|
||||||
|
async function branchFromPlayer(id: number) {
|
||||||
|
const { neighbors } = await patientFetchJSON<RatingNeighbors>(
|
||||||
|
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstPlayer = neighbors[0];
|
||||||
|
const lastPlayer = neighbors[neighbors.length - 1];
|
||||||
|
|
||||||
|
const branches: Promise<void>[] = [];
|
||||||
|
if (!players[firstPlayer.number])
|
||||||
|
branches.push(branchFromPlayer(firstPlayer.spa_id));
|
||||||
|
if (!players[lastPlayer.number])
|
||||||
|
branches.push(branchFromPlayer(lastPlayer.spa_id));
|
||||||
|
|
||||||
|
neighbors.forEach((neighbor) => {
|
||||||
|
if (players[neighbor.number]) return;
|
||||||
|
|
||||||
|
players[neighbor.number] = neighbor;
|
||||||
|
registered++;
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Registered ${registered} / ${PLAYERS} (${(
|
||||||
|
(registered / PLAYERS!) *
|
||||||
|
100
|
||||||
|
).toFixed(2)}%)`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(branches);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function branchFromLeague(id: number) {
|
||||||
|
const { result } = await patientFetchJSON<{ result: RatingPlayer[] }>(
|
||||||
|
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstPlayer = result[0];
|
||||||
|
const lastPlayer = result.at(-1)!;
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
branchFromPlayer(firstPlayer.spa_id),
|
||||||
|
branchFromPlayer(lastPlayer.spa_id),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Branching from leagues...');
|
||||||
|
await Promise.all([
|
||||||
|
branchFromLeague(0),
|
||||||
|
branchFromLeague(1),
|
||||||
|
branchFromLeague(2),
|
||||||
|
branchFromLeague(3),
|
||||||
|
branchFromLeague(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log('Converting to an array...');
|
||||||
|
for (let index = 0; index < PLAYERS; index++) {
|
||||||
|
const listing = players[index + 1];
|
||||||
|
if (listing) {
|
||||||
|
leaderboard[index] = { id: listing.spa_id, score: listing.score };
|
||||||
|
} else {
|
||||||
|
console.warn(`Position ${index + 1} had no player`);
|
||||||
|
leaderboard[index] = { id: 0, score: 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Requesting further stats...');
|
||||||
|
const comprehensiveLeaderboard: BkrlSuperset1Entry[] = [];
|
||||||
|
let chunkIndex = 0;
|
||||||
|
for (const leaderboardChunk of chunk(leaderboard, 100)) {
|
||||||
|
console.log(
|
||||||
|
`Chunk ${chunkIndex + 1} of ${Math.ceil(leaderboard.length / 100)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const stats = await getAccountInfo(
|
||||||
|
region,
|
||||||
|
leaderboardChunk.map(({ id }) => id),
|
||||||
|
['statistics.rating'],
|
||||||
|
);
|
||||||
|
|
||||||
|
stats.forEach((stat, index) => {
|
||||||
|
const trueIndex = chunkIndex * 100 + index;
|
||||||
|
comprehensiveLeaderboard[trueIndex] =
|
||||||
|
leaderboardChunk[index].id === 0 ||
|
||||||
|
stat?.statistics.rating === undefined
|
||||||
|
? {
|
||||||
|
battles: 0,
|
||||||
|
damage: 0,
|
||||||
|
id: 0,
|
||||||
|
kills: 0,
|
||||||
|
score: 0,
|
||||||
|
survived: 0,
|
||||||
|
wins: 0,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
id: leaderboardChunk[index].id,
|
||||||
|
score: leaderboardChunk[index].score,
|
||||||
|
battles: stat.statistics.rating.battles,
|
||||||
|
damage: stat.statistics.rating.damage_dealt,
|
||||||
|
kills: stat.statistics.rating.frags,
|
||||||
|
survived: stat.statistics.rating.survived_battles,
|
||||||
|
wins: stat.statistics.rating.wins,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
chunkIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await patientFetchJSON<RatingInfo & { detail: undefined }>(
|
||||||
|
`https://${regionSubdomain}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
||||||
|
);
|
||||||
|
const normalizedServer = regionSubdomain === 'na' ? 'com' : regionSubdomain;
|
||||||
|
const infoContent = new CdonWriteStream().cdon(
|
||||||
|
info as unknown as CdonValue,
|
||||||
|
).uint8Array;
|
||||||
|
const leaderboardWriteStream = new BkrlWriteStream();
|
||||||
|
|
||||||
|
leaderboardWriteStream.bkrl({
|
||||||
|
format: BkrlFormat.Superset1,
|
||||||
|
entries: comprehensiveLeaderboard,
|
||||||
|
});
|
||||||
|
|
||||||
|
const changes: FileChange[] = [
|
||||||
|
{
|
||||||
|
path: `regions/${normalizedServer}/rating/${info.current_season}/info.cdon.lz4`,
|
||||||
|
content: superCompress(infoContent),
|
||||||
|
encoding: 'base64',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `regions/${normalizedServer}/rating/${info.current_season}/${target}.bkrl`,
|
||||||
|
content: Buffer.from(leaderboardWriteStream.uint8Array).toString(
|
||||||
|
'base64',
|
||||||
|
),
|
||||||
|
encoding: 'base64',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
commitAssets(
|
||||||
|
`rating leaderboard ${regionSubdomain} ${target}`,
|
||||||
|
changes,
|
||||||
|
production,
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
import { Octokit } from '@octokit/rest';
|
|
||||||
import { rm, writeFile } from 'fs/promises';
|
|
||||||
import { argv, env } from 'process';
|
|
||||||
import {
|
|
||||||
RatingsInfo,
|
|
||||||
RatingsNeighbors,
|
|
||||||
RatingsPlayer,
|
|
||||||
} from '../src/commands/ratings';
|
|
||||||
import commitMultipleFiles from './commitMultipleFiles.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Central North American Time (UTC-5): use 0 5 * * *.
|
|
||||||
* Central European Time (UTC+1): use 0 23 * * *.
|
|
||||||
* Central Asia Standard Time (UTC+7): use 0 17 * * *.
|
|
||||||
*
|
|
||||||
* na/ratings/49/info.json: season info like rewards, start & end time, etc.
|
|
||||||
* na/ratings/49/latest.json: the absolute latest leaderboard recorded at UTC+0 midnight
|
|
||||||
* na/ratings/49/midnight.json: last midnight's leaderboard relative to the region
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type BlitzkriegRatingsLeaderboard = { id: number; score: number }[];
|
|
||||||
|
|
||||||
const publish = argv.includes('--publish');
|
|
||||||
const latest = argv.includes('--latest');
|
|
||||||
const server = argv.find((arg) => arg.startsWith('--region='))?.split('=')[1];
|
|
||||||
|
|
||||||
if (!server) throw new Error('Region parameter not specified');
|
|
||||||
|
|
||||||
const NEIGHBORS = 1000;
|
|
||||||
const PLAYERS = await fetch(
|
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
|
||||||
)
|
|
||||||
.then((response) => response.json() as Promise<RatingsInfo>)
|
|
||||||
.then((data) => (data.detail === undefined ? data.count : undefined));
|
|
||||||
|
|
||||||
if (PLAYERS === undefined) {
|
|
||||||
throw new Error('No current ratings season running');
|
|
||||||
}
|
|
||||||
|
|
||||||
const players: Record<number, RatingsPlayer> = {};
|
|
||||||
const leaderboard: BlitzkriegRatingsLeaderboard = [];
|
|
||||||
let registered = 0;
|
|
||||||
|
|
||||||
async function branchFromPlayer(id: number) {
|
|
||||||
const { neighbors } = await fetch(
|
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
|
|
||||||
).then((response) => response.json() as Promise<RatingsNeighbors>);
|
|
||||||
|
|
||||||
const firstPlayer = neighbors[0];
|
|
||||||
const lastPlayer = neighbors[neighbors.length - 1];
|
|
||||||
|
|
||||||
const branches: Promise<void>[] = [];
|
|
||||||
if (!players[firstPlayer.number])
|
|
||||||
branches.push(branchFromPlayer(firstPlayer.spa_id));
|
|
||||||
if (!players[lastPlayer.number])
|
|
||||||
branches.push(branchFromPlayer(lastPlayer.spa_id));
|
|
||||||
|
|
||||||
neighbors.forEach((neighbor) => {
|
|
||||||
if (players[neighbor.number]) return;
|
|
||||||
|
|
||||||
players[neighbor.number] = neighbor;
|
|
||||||
registered++;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Registered ${registered} / ${PLAYERS} (${(
|
|
||||||
(registered / PLAYERS!) *
|
|
||||||
100
|
|
||||||
).toFixed(2)}%)`,
|
|
||||||
);
|
|
||||||
|
|
||||||
await Promise.all(branches);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function branchFromLeague(id: number) {
|
|
||||||
const { result } = await fetch(
|
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
|
|
||||||
).then((response) => response.json() as Promise<{ result: RatingsPlayer[] }>);
|
|
||||||
|
|
||||||
const firstPlayer = result[0];
|
|
||||||
const lastPlayer = result[result.length - 1];
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
branchFromPlayer(firstPlayer.spa_id),
|
|
||||||
branchFromPlayer(lastPlayer.spa_id),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Branching from leagues...');
|
|
||||||
await Promise.all([
|
|
||||||
branchFromLeague(0),
|
|
||||||
branchFromLeague(1),
|
|
||||||
branchFromLeague(2),
|
|
||||||
branchFromLeague(3),
|
|
||||||
branchFromLeague(4),
|
|
||||||
]);
|
|
||||||
|
|
||||||
console.log('Converting to an array...');
|
|
||||||
for (let index = 0; index < PLAYERS; index++) {
|
|
||||||
const listing = players[index + 1];
|
|
||||||
if (!listing) console.warn(`Position ${index + 1} had no player`);
|
|
||||||
|
|
||||||
leaderboard[index] = {
|
|
||||||
id: listing.spa_id,
|
|
||||||
score: listing.score,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const leaderboardJSON = JSON.stringify(leaderboard);
|
|
||||||
|
|
||||||
if (publish) {
|
|
||||||
const octokit = new Octokit({ auth: env.GH_TOKEN });
|
|
||||||
|
|
||||||
const info = await fetch(
|
|
||||||
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
|
|
||||||
).then(
|
|
||||||
(response) =>
|
|
||||||
response.json() as Promise<RatingsInfo & { detail: undefined }>,
|
|
||||||
);
|
|
||||||
const normalizedServer = server === 'na' ? 'com' : server;
|
|
||||||
|
|
||||||
const infoPath = `${normalizedServer}/ratings/${info.current_season}/info.json`;
|
|
||||||
const leaderboardPath = `${normalizedServer}/ratings/${info.current_season}/${
|
|
||||||
latest ? 'latest' : 'midnight'
|
|
||||||
}.json`;
|
|
||||||
const infoJSON = JSON.stringify(info);
|
|
||||||
|
|
||||||
console.log(`Publishing to season ${info.current_season}...`);
|
|
||||||
commitMultipleFiles(
|
|
||||||
octokit,
|
|
||||||
'tresabhi',
|
|
||||||
'blitzkrieg-db',
|
|
||||||
'main',
|
|
||||||
new Date().toString(),
|
|
||||||
[
|
|
||||||
{ path: infoPath, content: infoJSON },
|
|
||||||
{ path: leaderboardPath, content: leaderboardJSON },
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log('Writing to disk...');
|
|
||||||
await rm('dist.json', { force: true });
|
|
||||||
await writeFile('dist.json', leaderboardJSON);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { readdir } from 'fs/promises';
|
||||||
|
import packageJSON from '../package.json';
|
||||||
|
|
||||||
|
const { version } = packageJSON;
|
||||||
|
const changelogs = await readdir('docs/changelogs');
|
||||||
|
const hasVersion = changelogs.includes(`${version}.md`);
|
||||||
|
|
||||||
|
if (hasVersion) {
|
||||||
|
console.log(`Version ${version} found in changelogs`);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Version ${version} not found in changelogs`);
|
||||||
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import { Octokit } from '@octokit/rest';
|
|
||||||
|
|
||||||
export default async function commitMultipleFiles(
|
|
||||||
octokit: Octokit,
|
|
||||||
owner: string,
|
|
||||||
repo: string,
|
|
||||||
branch: string,
|
|
||||||
message: string,
|
|
||||||
changes: { path: string; content: string }[],
|
|
||||||
) {
|
|
||||||
// Get the latest commit SHA on the specified branch
|
|
||||||
const { data: refData } = await octokit.git.getRef({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
ref: `heads/${branch}`,
|
|
||||||
});
|
|
||||||
const latestCommitSha = refData.object.sha;
|
|
||||||
|
|
||||||
// Get the tree SHA for the latest commit
|
|
||||||
const { data: commitData } = await octokit.git.getCommit({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
commit_sha: latestCommitSha,
|
|
||||||
});
|
|
||||||
const treeSha = commitData.tree.sha;
|
|
||||||
|
|
||||||
// Create blobs for each file
|
|
||||||
const blobs = await Promise.all(
|
|
||||||
changes.map(async (change) => {
|
|
||||||
const { data: blobData } = await octokit.git.createBlob({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
content: change.content,
|
|
||||||
encoding: 'utf-8',
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
sha: blobData.sha,
|
|
||||||
path: change.path,
|
|
||||||
mode: '100644',
|
|
||||||
type: 'blob',
|
|
||||||
} as const;
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create a new tree with the new blobs
|
|
||||||
const { data: treeData } = await octokit.git.createTree({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
base_tree: treeSha,
|
|
||||||
tree: blobs,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new commit with the new tree
|
|
||||||
const { data: newCommitData } = await octokit.git.createCommit({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
message,
|
|
||||||
tree: treeData.sha,
|
|
||||||
parents: [latestCommitSha],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the branch reference to point to the new commit
|
|
||||||
await octokit.git.updateRef({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
ref: `heads/${branch}`,
|
|
||||||
sha: newCommitData.sha,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import decompress from 'decompress';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
import { mkdir, readdir, writeFile } from 'fs/promises';
|
||||||
|
|
||||||
|
if (!existsSync('temp')) {
|
||||||
|
console.log('Creating temp directory...');
|
||||||
|
await mkdir('temp');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Downloading depot downloader...');
|
||||||
|
await fetch(
|
||||||
|
'https://api.github.com/repos/SteamRE/DepotDownloader/releases/latest',
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(response) =>
|
||||||
|
response.json() as Promise<{
|
||||||
|
assets: { browser_download_url: string; name: string }[];
|
||||||
|
}>,
|
||||||
|
)
|
||||||
|
.then(({ assets }) => {
|
||||||
|
const asset = assets.find(({ name }) => name.includes('windows-x64'));
|
||||||
|
if (!asset) throw new Error('No asset found');
|
||||||
|
return fetch(asset.browser_download_url);
|
||||||
|
})
|
||||||
|
.then((response) => response.arrayBuffer())
|
||||||
|
.then((arrayBuffer) =>
|
||||||
|
writeFile('temp/depotDownloader.zip', Buffer.from(arrayBuffer)),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Unzipping...');
|
||||||
|
await decompress('temp/depotDownloader.zip', 'temp/depotDownloader');
|
||||||
|
|
||||||
|
console.log('Download complete; files:', await readdir('temp/depotDownloader'));
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"incremental": true,
|
||||||
|
"isolatedModules": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { Region } from '../../../../../../constants/regions';
|
||||||
|
import getRatingInfo from '../../../../../../core/blitz/getRatingInfo';
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: { region: Region } },
|
||||||
|
) {
|
||||||
|
return NextResponse.json(await getRatingInfo(params.region));
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { Region } from '../../../../../../../constants/regions';
|
||||||
|
import { getRatingLeague } from '../../../../../../../core/blitz/getRatingLeague';
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: { region: Region; league: number } },
|
||||||
|
) {
|
||||||
|
return NextResponse.json(
|
||||||
|
await getRatingLeague(params.region, params.league, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
import { Region } from '../../../../../../../constants/regions';
|
||||||
|
import { searchCurrentRatingPlayers } from '../../../../../../../core/blitz/searchCurrentRatingPlayers';
|
||||||
|
|
||||||
|
export async function GET(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: { region: Region; username: string } },
|
||||||
|
) {
|
||||||
|
return NextResponse.json(
|
||||||
|
await searchCurrentRatingPlayers(params.region, params.username),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { NextResponse } from 'next/server';
|
|
||||||
import { tankopedia } from '../../../core/blitzstars/tankopedia';
|
|
||||||
|
|
||||||
export async function GET() {
|
|
||||||
return NextResponse.json(await tankopedia);
|
|
||||||
}
|
|
||||||
@@ -3,25 +3,29 @@
|
|||||||
import { ContextMenu } from '@radix-ui/themes';
|
import { ContextMenu } from '@radix-ui/themes';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import * as Breakdown from '../../../components/Breakdown';
|
import * as Breakdown from '../../../components/Breakdown';
|
||||||
import { TreeTypeEnum } from '../../../components/Tanks';
|
|
||||||
import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID';
|
import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID';
|
||||||
import fetchBlitz from '../../../core/blitz/fetchWargaming';
|
import fetchBlitz from '../../../core/blitz/fetchBlitz';
|
||||||
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
import { resetSession } from '../../../core/blitzkrieg/resetSession';
|
||||||
import {
|
import {
|
||||||
TankopediaEntry,
|
TankDefinition,
|
||||||
tankopedia,
|
tankDefinitions,
|
||||||
} from '../../../core/blitzstars/tankopedia';
|
} from '../../../core/blitzkrieg/tankDefinitions';
|
||||||
|
import { tankAverages } from '../../../core/blitzstars/tankAverages';
|
||||||
import calculateWN8 from '../../../core/statistics/calculateWN8';
|
import calculateWN8 from '../../../core/statistics/calculateWN8';
|
||||||
import { deltaTankStats } from '../../../core/statistics/deltaTankStats';
|
import { deltaTankStats } from '../../../core/statistics/deltaTankStats';
|
||||||
import getWN8Percentile from '../../../core/statistics/getWN8Percentile';
|
import getWN8Percentile from '../../../core/statistics/getWN8Percentile';
|
||||||
import { resetSession, useSession } from '../../../stores/session';
|
import mutateSession, { useSession } from '../../../stores/session';
|
||||||
import { IndividualTankStats, TanksStats } from '../../../types/tanksStats';
|
import { IndividualTankStats, TanksStats } from '../../../types/tanksStats';
|
||||||
import { CustomColumnDisplay } from '../../tools/session/components/CustomColumn';
|
import { CustomColumnDisplay } from '../../tools/session/components/CustomColumn';
|
||||||
import { Menu } from '../../tools/session/components/Menu';
|
import { Menu } from '../../tools/session/components/Menu';
|
||||||
|
|
||||||
const REFRESH_RATE = 1 / 5;
|
const REFRESH_RATE = 1 / 5;
|
||||||
|
|
||||||
export default function SessionPage() {
|
interface SessionPageProps {
|
||||||
|
naked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SessionPage({ naked = true }: SessionPageProps) {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
const since = session.isTracking ? new Date(session.time) : undefined;
|
const since = session.isTracking ? new Date(session.time) : undefined;
|
||||||
const [diff, setDiff] = useState<
|
const [diff, setDiff] = useState<
|
||||||
@@ -30,7 +34,7 @@ export default function SessionPage() {
|
|||||||
|
|
||||||
list: {
|
list: {
|
||||||
stats: IndividualTankStats;
|
stats: IndividualTankStats;
|
||||||
tankopedia?: TankopediaEntry;
|
tankDefinitions?: TankDefinition;
|
||||||
career: IndividualTankStats;
|
career: IndividualTankStats;
|
||||||
currentWN8?: number;
|
currentWN8?: number;
|
||||||
careerWN8?: number;
|
careerWN8?: number;
|
||||||
@@ -72,6 +76,14 @@ export default function SessionPage() {
|
|||||||
0,
|
0,
|
||||||
) / careerBattles;
|
) / careerBattles;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (session.title === 'Untitled session') {
|
||||||
|
mutateSession((draft) => {
|
||||||
|
if (draft.isTracking) draft.title = draft.nickname;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [session.title]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function recalculateDiff() {
|
async function recalculateDiff() {
|
||||||
if (session.isTracking) {
|
if (session.isTracking) {
|
||||||
@@ -88,7 +100,7 @@ export default function SessionPage() {
|
|||||||
}),
|
}),
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
const awaitedTankopedia = await tankopedia;
|
const awaitedTankDefinitions = await tankDefinitions;
|
||||||
const awaitedTankAverages = await tankAverages;
|
const awaitedTankAverages = await tankAverages;
|
||||||
const careerWN8 =
|
const careerWN8 =
|
||||||
careerRaw[id].reduce(
|
careerRaw[id].reduce(
|
||||||
@@ -114,12 +126,12 @@ export default function SessionPage() {
|
|||||||
|
|
||||||
list: (
|
list: (
|
||||||
Object.values(
|
Object.values(
|
||||||
deltaTankStats(session.tankStats, career),
|
deltaTankStats(session.tankStats, career, session.time / 1000),
|
||||||
) as IndividualTankStats[]
|
) as IndividualTankStats[]
|
||||||
).map((stats) => {
|
).map((stats) => {
|
||||||
return {
|
return {
|
||||||
stats,
|
stats,
|
||||||
tankopedia: awaitedTankopedia[stats.tank_id],
|
tankDefinitions: awaitedTankDefinitions[stats.tank_id],
|
||||||
career: career[stats.tank_id],
|
career: career[stats.tank_id],
|
||||||
currentWN8: awaitedTankAverages[stats.tank_id]
|
currentWN8: awaitedTankAverages[stats.tank_id]
|
||||||
? calculateWN8(
|
? calculateWN8(
|
||||||
@@ -207,15 +219,10 @@ export default function SessionPage() {
|
|||||||
since !== undefined &&
|
since !== undefined &&
|
||||||
diff !== undefined && (
|
diff !== undefined && (
|
||||||
<Breakdown.Row
|
<Breakdown.Row
|
||||||
|
naked={naked}
|
||||||
|
color={session.color}
|
||||||
minimized={!session.showCareer}
|
minimized={!session.showCareer}
|
||||||
title={`Since ${since.toLocaleString(undefined, {
|
title={session.title}
|
||||||
hour: 'numeric',
|
|
||||||
minute: 'numeric',
|
|
||||||
hour12: true,
|
|
||||||
month: 'short',
|
|
||||||
year: 'numeric',
|
|
||||||
day: 'numeric',
|
|
||||||
})}`}
|
|
||||||
stats={session.customColumns.map((customColumn) => {
|
stats={session.customColumns.map((customColumn) => {
|
||||||
const rowStat = totalRowStats[customColumn.display];
|
const rowStat = totalRowStats[customColumn.display];
|
||||||
|
|
||||||
@@ -237,89 +244,91 @@ export default function SessionPage() {
|
|||||||
.sort(
|
.sort(
|
||||||
(a, b) => b.stats.last_battle_time - a.stats.last_battle_time,
|
(a, b) => b.stats.last_battle_time - a.stats.last_battle_time,
|
||||||
)
|
)
|
||||||
.map(({ stats, tankopedia, career, careerWN8, currentWN8 }) => {
|
.map(
|
||||||
const rowStats: Record<
|
({ stats, tankDefinitions, career, careerWN8, currentWN8 }) => {
|
||||||
CustomColumnDisplay,
|
const rowStats: Record<
|
||||||
Breakdown.RowStatItem | undefined
|
CustomColumnDisplay,
|
||||||
> = {
|
Breakdown.RowStatItem | undefined
|
||||||
battles: {
|
> = {
|
||||||
title: 'Battles',
|
battles: {
|
||||||
current: stats.all.battles.toLocaleString(),
|
title: 'Battles',
|
||||||
career: career.all.battles.toLocaleString(),
|
current: stats.all.battles.toLocaleString(),
|
||||||
},
|
career: career.all.battles.toLocaleString(),
|
||||||
winrate: {
|
},
|
||||||
title: 'Winrate',
|
winrate: {
|
||||||
current: `${(
|
title: 'Winrate',
|
||||||
100 *
|
current: `${(
|
||||||
(stats.all.wins / stats.all.battles)
|
100 *
|
||||||
).toFixed(2)}%`,
|
(stats.all.wins / stats.all.battles)
|
||||||
career: `${(
|
).toFixed(2)}%`,
|
||||||
100 *
|
career: `${(
|
||||||
(career.all.wins / career.all.battles)
|
100 *
|
||||||
).toFixed(2)}%`,
|
(career.all.wins / career.all.battles)
|
||||||
delta:
|
).toFixed(2)}%`,
|
||||||
stats.all.wins / stats.all.battles -
|
delta:
|
||||||
career.all.wins / career.all.battles,
|
stats.all.wins / stats.all.battles -
|
||||||
},
|
career.all.wins / career.all.battles,
|
||||||
wn8: {
|
},
|
||||||
title: 'WN8',
|
wn8: {
|
||||||
current:
|
title: 'WN8',
|
||||||
currentWN8 === undefined
|
current:
|
||||||
? undefined
|
currentWN8 === undefined
|
||||||
: Math.round(currentWN8).toLocaleString(),
|
? undefined
|
||||||
career:
|
: Math.round(currentWN8).toLocaleString(),
|
||||||
careerWN8 === undefined
|
career:
|
||||||
? undefined
|
careerWN8 === undefined
|
||||||
: Math.round(careerWN8).toLocaleString(),
|
? undefined
|
||||||
percentile:
|
: Math.round(careerWN8).toLocaleString(),
|
||||||
currentWN8 === undefined
|
percentile:
|
||||||
? undefined
|
currentWN8 === undefined
|
||||||
: getWN8Percentile(currentWN8),
|
? undefined
|
||||||
},
|
: getWN8Percentile(currentWN8),
|
||||||
damage: {
|
},
|
||||||
title: 'Damage',
|
damage: {
|
||||||
current: Math.round(
|
title: 'Damage',
|
||||||
stats.all.damage_dealt / stats.all.battles,
|
current: Math.round(
|
||||||
).toLocaleString(),
|
stats.all.damage_dealt / stats.all.battles,
|
||||||
career: Math.round(
|
).toLocaleString(),
|
||||||
career.all.damage_dealt / career.all.battles,
|
career: Math.round(
|
||||||
).toLocaleString(),
|
career.all.damage_dealt / career.all.battles,
|
||||||
delta:
|
).toLocaleString(),
|
||||||
stats.all.damage_dealt / stats.all.battles -
|
delta:
|
||||||
career.all.damage_dealt / career.all.battles,
|
stats.all.damage_dealt / stats.all.battles -
|
||||||
},
|
career.all.damage_dealt / career.all.battles,
|
||||||
none: undefined,
|
},
|
||||||
};
|
none: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Breakdown.Row
|
<Breakdown.Row
|
||||||
key={stats.tank_id}
|
naked={naked}
|
||||||
minimized={!session.showCareer}
|
color={session.color}
|
||||||
title={tankopedia?.name ?? `Unknown tank ${stats.tank_id}`}
|
key={stats.tank_id}
|
||||||
type="tank"
|
minimized={!session.showCareer}
|
||||||
tankType={tankopedia?.type}
|
title={
|
||||||
treeType={(() => {
|
tankDefinitions?.name ?? `Unknown tank ${stats.tank_id}`
|
||||||
if (tankopedia?.is_collectible)
|
}
|
||||||
return TreeTypeEnum.Collector;
|
type="tank"
|
||||||
if (tankopedia?.is_premium) return TreeTypeEnum.Premium;
|
tankType={tankDefinitions?.class}
|
||||||
})()}
|
treeType={tankDefinitions?.treeType}
|
||||||
stats={session.customColumns.map((customColumn) => {
|
stats={session.customColumns.map((customColumn) => {
|
||||||
const rowStat = rowStats[customColumn.display];
|
const rowStat = rowStats[customColumn.display];
|
||||||
|
|
||||||
if (!rowStat) return undefined;
|
if (!rowStat) return undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...rowStat,
|
...rowStat,
|
||||||
delta:
|
delta:
|
||||||
customColumn.showDelta &&
|
customColumn.showDelta &&
|
||||||
rowStat.percentile === undefined
|
rowStat.percentile === undefined
|
||||||
? rowStat.delta
|
? rowStat.delta
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
},
|
||||||
|
)}
|
||||||
</Breakdown.Root>
|
</Breakdown.Root>
|
||||||
</div>
|
</div>
|
||||||
</ContextMenu.Trigger>
|
</ContextMenu.Trigger>
|
||||||
|
|||||||
@@ -1,15 +1,25 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Flex, Theme } from '@radix-ui/themes';
|
import { CaretRightIcon } from '@radix-ui/react-icons';
|
||||||
|
import { AlertDialog, Button, Flex, Text, Theme } from '@radix-ui/themes';
|
||||||
import '@radix-ui/themes/styles.css';
|
import '@radix-ui/themes/styles.css';
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
import { Roboto_Flex } from 'next/font/google';
|
import { Roboto_Flex } from 'next/font/google';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode, useEffect, useState } from 'react';
|
||||||
|
import { SkyLine } from '../assets/art/SkyLine';
|
||||||
|
import { Analytics } from '../components/Analytics';
|
||||||
import Navbar from '../components/Navbar';
|
import Navbar from '../components/Navbar';
|
||||||
|
import PageWrapper from '../components/PageWrapper';
|
||||||
|
import isDev from '../core/blitzkrieg/isDev';
|
||||||
|
import { isLocalhost } from '../core/blitzkrieg/isLocalhost';
|
||||||
|
import { useApp } from '../stores/app';
|
||||||
|
import { mintTheme } from '../themes/mint';
|
||||||
|
|
||||||
config();
|
config();
|
||||||
|
|
||||||
|
const DEV_BUILD_AGREEMENT_COOLDOWN = 8 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
@@ -22,6 +32,16 @@ const robotoFlex = Roboto_Flex({
|
|||||||
export default function RootLayout({ children }: RootLayoutProps) {
|
export default function RootLayout({ children }: RootLayoutProps) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const isEmbed = pathname.split('/')[1] === 'embeds';
|
const isEmbed = pathname.split('/')[1] === 'embeds';
|
||||||
|
const [showDevBuildAlert, setShowDevBuildAlert] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setShowDevBuildAlert(
|
||||||
|
isDev() &&
|
||||||
|
!isLocalhost() &&
|
||||||
|
Date.now() - useApp.getState().devBuildAgreementTime >=
|
||||||
|
DEV_BUILD_AGREEMENT_COOLDOWN,
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={robotoFlex.className}>
|
<html lang="en" className={robotoFlex.className}>
|
||||||
@@ -31,25 +51,110 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
|||||||
name="description"
|
name="description"
|
||||||
content="🎉 Tools for everything World of Tanks Blitz"
|
content="🎉 Tools for everything World of Tanks Blitz"
|
||||||
/>
|
/>
|
||||||
|
<Analytics />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body
|
<body
|
||||||
style={{
|
style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
background: isEmbed
|
paddingTop: isEmbed ? 0 : '3.25rem',
|
||||||
? 'transparent'
|
backgroundColor: isEmbed ? 'transparent' : undefined,
|
||||||
: 'url(https://i.imgur.com/PhS06NJ.png)',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Theme
|
<Theme
|
||||||
appearance="dark"
|
appearance="dark"
|
||||||
panelBackground="translucent"
|
panelBackground="translucent"
|
||||||
radius="full"
|
radius="full"
|
||||||
accentColor="blue"
|
suppressHydrationWarning
|
||||||
|
suppressContentEditableWarning
|
||||||
>
|
>
|
||||||
{!isEmbed && <Navbar />}
|
{!isEmbed && <Navbar />}
|
||||||
|
<AlertDialog.Root open={showDevBuildAlert}>
|
||||||
|
<AlertDialog.Content>
|
||||||
|
<AlertDialog.Title>Experimental version!</AlertDialog.Title>
|
||||||
|
<AlertDialog.Description>
|
||||||
|
This version may have a lot of issues. Report issues to{' '}
|
||||||
|
<a href="https://discord.gg/nDt7AjGJQH" target="_blank">
|
||||||
|
the official Discord server
|
||||||
|
</a>
|
||||||
|
. Also consider using{' '}
|
||||||
|
<a href="https://blitz-krieg.vercel.app/">
|
||||||
|
the more stable release version
|
||||||
|
</a>
|
||||||
|
. You will be asked again in 8 days.
|
||||||
|
</AlertDialog.Description>
|
||||||
|
|
||||||
|
<Flex justify="end">
|
||||||
|
<Button
|
||||||
|
variant="solid"
|
||||||
|
onClick={() => {
|
||||||
|
setShowDevBuildAlert(false);
|
||||||
|
useApp.setState({ devBuildAgreementTime: Date.now() });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</AlertDialog.Content>
|
||||||
|
</AlertDialog.Root>
|
||||||
|
|
||||||
<Flex direction="column">{children}</Flex>
|
<Flex direction="column">{children}</Flex>
|
||||||
|
|
||||||
|
{!isEmbed && (
|
||||||
|
<PageWrapper>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://ko-fi.com/tresabhi"
|
||||||
|
style={{ textDecoration: 'none' }}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
align="center"
|
||||||
|
style={{
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 8,
|
||||||
|
backgroundColor: mintTheme.colors.componentInteractive,
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
gap="1"
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
zIndex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text size="4" color="mint">
|
||||||
|
Blitzkrieg. Free forever. For everyone.
|
||||||
|
</Text>
|
||||||
|
<Text color="mint">
|
||||||
|
<b>Consider supporting today 🍀</b>
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
color="mint"
|
||||||
|
style={{
|
||||||
|
zIndex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex>
|
||||||
|
<CaretRightIcon width={32} height={32} />
|
||||||
|
</Flex>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<SkyLine
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
right: 'min(8vw, 15%)',
|
||||||
|
top: '5%',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</a>
|
||||||
|
</PageWrapper>
|
||||||
|
)}
|
||||||
</Theme>
|
</Theme>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { theme } from '../stitches.config';
|
|||||||
|
|
||||||
export const tool = styleVariants({
|
export const tool = styleVariants({
|
||||||
enabled: {
|
enabled: {
|
||||||
boxShadow: `inset 0 -192px 128px -128px ${theme.colors.appBackground1}`,
|
boxShadow: `inset 0 -256px 512px -128px ${theme.colors.appBackground1}`,
|
||||||
|
|
||||||
':hover': {
|
':hover': {
|
||||||
boxShadow: `inset 0 -160px 128px -128px ${theme.colors.appBackground1}`,
|
boxShadow: `inset 0 -160px 128px -128px ${theme.colors.appBackground1}`,
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ export default function Page() {
|
|||||||
({
|
({
|
||||||
node: (
|
node: (
|
||||||
<Link
|
<Link
|
||||||
href={`/tools/${tool.id}`}
|
href={tool.href ?? `/tools/${tool.id}`}
|
||||||
|
target={tool.href ? '_blank' : undefined}
|
||||||
className={
|
className={
|
||||||
tool.disabled ? styles.tool.disabled : styles.tool.enabled
|
tool.disabled ? styles.tool.disabled : styles.tool.enabled
|
||||||
}
|
}
|
||||||
|
|||||||