mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 03:29:51 +01:00
Compare commits
6
Commits
d485a463dd
...
877ba9408d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
877ba9408d | ||
|
|
8dc9a6b46d | ||
|
|
b3e439669b | ||
|
|
08c909fbe2 | ||
|
|
a44e2e9866 | ||
|
|
bae2f253bc |
No files matched your search
+2
-1
@@ -7,7 +7,8 @@
|
||||
"dev": "cd packages/website && bun run dev",
|
||||
"build": "cd packages/website && bun run build",
|
||||
"discover-ids": "cd packages/scripts && bun run discover-ids",
|
||||
"build-protos": "cd packages/scripts && bun run build-protos"
|
||||
"build-protos": "cd packages/scripts && bun run build-protos",
|
||||
"record-performance": "cd packages/scripts && bun run record-performance"
|
||||
},
|
||||
"type": "module",
|
||||
"workspaces": [
|
||||
|
||||
@@ -6,23 +6,35 @@ interface EnvironmentConfig {
|
||||
aliases: Record<string, string>;
|
||||
}
|
||||
|
||||
export const environments = import.meta.glob(
|
||||
"../../../../environments/*.json",
|
||||
{
|
||||
let hasReadEnvironments = false;
|
||||
const environments: Record<string, EnvironmentConfig> = {};
|
||||
|
||||
/**
|
||||
* This is set up this way to avoid errors in runtimes where
|
||||
* `import.meta.glob` does not exist.
|
||||
*/
|
||||
function readEnvironments() {
|
||||
if (hasReadEnvironments) return;
|
||||
|
||||
hasReadEnvironments = true;
|
||||
|
||||
const glob = import.meta.glob("../../../../environments/*.json", {
|
||||
eager: true,
|
||||
import: "default",
|
||||
},
|
||||
) as Record<string, EnvironmentConfig>;
|
||||
const root = "../../../../environments";
|
||||
}) as Record<string, EnvironmentConfig>;
|
||||
const root = "../../../../environments";
|
||||
|
||||
for (const key in environments) {
|
||||
const trimmed = key.slice(root.length + 1, -5);
|
||||
for (const key in glob) {
|
||||
const trimmed = key.slice(root.length + 1, -5);
|
||||
|
||||
environments[trimmed] = environments[key];
|
||||
delete environments[key];
|
||||
environments[trimmed] = glob[key];
|
||||
delete environments[key];
|
||||
}
|
||||
}
|
||||
|
||||
export function environmentConfig() {
|
||||
readEnvironments();
|
||||
|
||||
const environment = assertSecret(import.meta.env.PUBLIC_ENVIRONMENT);
|
||||
|
||||
if (!(environment in environments)) {
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import { times } from 'lodash-es';
|
||||
import { ReadStream, WriteStream } from './buffer';
|
||||
|
||||
export class DidsReadStream extends ReadStream {
|
||||
dids() {
|
||||
this.magic();
|
||||
this.header();
|
||||
return this.body();
|
||||
}
|
||||
|
||||
magic() {
|
||||
const magic = this.utf8(4);
|
||||
if (magic !== 'DIDS') {
|
||||
throw new Error(`Invalid DIDS magic number: "${magic}"`);
|
||||
}
|
||||
}
|
||||
|
||||
header() {
|
||||
return {
|
||||
version: this.uint16(),
|
||||
};
|
||||
}
|
||||
|
||||
body() {
|
||||
const count = this.uint32();
|
||||
return times(count, () => this.uint32());
|
||||
}
|
||||
}
|
||||
|
||||
export class DidsWriteStream extends WriteStream {
|
||||
dids(ids: number[]) {
|
||||
this.magic();
|
||||
this.header();
|
||||
this.body(ids);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
magic() {
|
||||
this.utf8('DIDS');
|
||||
}
|
||||
|
||||
header() {
|
||||
this.uint16(1);
|
||||
}
|
||||
|
||||
body(ids: number[]) {
|
||||
this.uint32(ids.length);
|
||||
ids.forEach((id) => this.uint32(id));
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
export * from './buffer';
|
||||
export * from './bufferToBigInt';
|
||||
export * from './dds';
|
||||
export * from './dids';
|
||||
export * from './pvr';
|
||||
export * from './rts';
|
||||
export * from './sc2';
|
||||
export * from './scg';
|
||||
export * from './scpg';
|
||||
export * from './windows';
|
||||
|
||||
export * from "./buffer";
|
||||
export * from "./bufferToBigInt";
|
||||
export * from "./dds";
|
||||
export * from "./pvr";
|
||||
export * from "./rts";
|
||||
export * from "./sc2";
|
||||
export * from "./scg";
|
||||
export * from "./scpg";
|
||||
export * from "./windows";
|
||||
@@ -3,7 +3,8 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"discover-ids": "bun src/discoverIds/index.ts",
|
||||
"build-protos": "bun src/protos.ts"
|
||||
"build-protos": "bun src/protos.ts",
|
||||
"record-performance": "bun src/recordPerformance/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzkit/closed": "workspace:*",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { decompress } from "lz4js";
|
||||
|
||||
export class IdArray {
|
||||
constructor(
|
||||
private array: Uint32Array = new Uint32Array(),
|
||||
@@ -57,6 +59,11 @@ export class IdArray {
|
||||
return new IdArray(uintArray, size);
|
||||
}
|
||||
|
||||
static fromCompressed(bytes: Uint8Array) {
|
||||
const decompressed = decompress(bytes);
|
||||
return this.fromBytes(decompressed);
|
||||
}
|
||||
|
||||
static fromArray(array: number[]) {
|
||||
const uintArray = new Uint32Array(this.nextPowerOf2(array.length));
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
export const WORKING_DIR = `../../temp/ids`;
|
||||
export const REPO = "blitzkit/ids";
|
||||
|
||||
export const ACCOMMODATED_ID_COUNT = 10_000_000_000; // 10B ids
|
||||
export const MAX_BYTES_PER_CHUNK = 100 * 1_000_000; // 100MB
|
||||
|
||||
|
||||
@@ -1,41 +1,34 @@
|
||||
import { range } from "lodash-es";
|
||||
import { compress, decompress } from "lz4js";
|
||||
import { compress } from "lz4js";
|
||||
import { exit } from "node:process";
|
||||
import { GitObjectStorage } from "../core/blitzkit/gitObjectStorage";
|
||||
import { IdArray } from "../core/blitzkit/idArray";
|
||||
import {
|
||||
ACCOMMODATED_ID_COUNT,
|
||||
API_RATE,
|
||||
MAX_BYTES_PER_CHUNK,
|
||||
MAX_DRY_STREAK,
|
||||
MAX_IDS_PER_CALL,
|
||||
REPO,
|
||||
WORKING_DIR,
|
||||
} from "./constants";
|
||||
import { ManifestV1, QuickInfo, RegionDescriptor } from "./types";
|
||||
import { sleep, withinTimeLimit } from "./time";
|
||||
import { IdsManifest, QuickInfo, RegionDescriptor } from "./types";
|
||||
|
||||
const storage = await new GitObjectStorage(
|
||||
REPO,
|
||||
WORKING_DIR,
|
||||
"blitzkit/data-ids",
|
||||
"../../temp/ids",
|
||||
import.meta.env.GH_TOKEN,
|
||||
).init();
|
||||
|
||||
const t0 = performance.now();
|
||||
const maxT = (5 * 60 + 55) * 60 * 1000; // 5hr 55min
|
||||
const t1 = t0 + maxT;
|
||||
|
||||
await storage.mkdir("chunks");
|
||||
|
||||
console.log(`Discovering pre-existing chunks...`);
|
||||
|
||||
const discoveredChunks: (IdArray | null)[] = [];
|
||||
|
||||
const manifest = await storage.json<ManifestV1>("manifest.json");
|
||||
const manifest = await storage.json<IdsManifest>("manifest.json");
|
||||
|
||||
for (let i = 0; i < manifest.chunks; i++) {
|
||||
const bytes = await storage.bytes(`chunks/chunk-${i}.dat.lz4`);
|
||||
const uncompressed = decompress(bytes);
|
||||
const ids = IdArray.fromBytes(uncompressed);
|
||||
const ids = IdArray.fromCompressed(bytes);
|
||||
|
||||
discoveredChunks.push(ids);
|
||||
}
|
||||
@@ -189,14 +182,6 @@ function fillQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
function sleep() {
|
||||
return new Promise((resolve) => setTimeout(resolve, 1000 / API_RATE));
|
||||
}
|
||||
|
||||
function withinTimeLimit() {
|
||||
return performance.now() < t1;
|
||||
}
|
||||
|
||||
console.log("Starting discovery loop...");
|
||||
|
||||
while (withinTimeLimit() && regions.length > 0) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { API_RATE } from "./constants";
|
||||
|
||||
const MAX_COMPUTE_TIME = (5 * 60 + 55) * 60 * 1000; // 5hr 55min
|
||||
|
||||
const t0 = performance.now();
|
||||
const t1 = t0 + MAX_COMPUTE_TIME;
|
||||
|
||||
export function withinTimeLimit() {
|
||||
return performance.now() < t1;
|
||||
}
|
||||
|
||||
export function sleep() {
|
||||
return new Promise((resolve) => setTimeout(resolve, 1000 / API_RATE));
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface ManifestV1 {
|
||||
export type IdsManifest = IdsManifestV1;
|
||||
|
||||
interface IdsManifestV1 {
|
||||
version: 1;
|
||||
last_verified: number;
|
||||
chunks: number;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const IDS_API_BASE = "https://ids.blitzkit.app";
|
||||
@@ -0,0 +1,64 @@
|
||||
import { idToRegion } from "@blitzkit/core";
|
||||
import { GitObjectStorage } from "../core/blitzkit/gitObjectStorage";
|
||||
import { IdArray } from "../core/blitzkit/idArray";
|
||||
import { API_RATE } from "../discoverIds/constants";
|
||||
import { sleep, withinTimeLimit } from "../discoverIds/time";
|
||||
import { IdsManifest } from "../discoverIds/types";
|
||||
import { IDS_API_BASE } from "./constants";
|
||||
import { PerformanceManifest, QuickStatistics } from "./types";
|
||||
|
||||
const applicationId = import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID;
|
||||
|
||||
const storage = await new GitObjectStorage(
|
||||
"blitzkit/data-performance",
|
||||
"../../temp/performance",
|
||||
import.meta.env.GH_TOKEN,
|
||||
).init();
|
||||
|
||||
const manifest = await storage.json<PerformanceManifest>("manifest.json");
|
||||
const idsManifest = await fetch(`${IDS_API_BASE}/manifest.json`).then(
|
||||
(response) => response.json() as Promise<IdsManifest>,
|
||||
);
|
||||
|
||||
while (withinTimeLimit()) {
|
||||
manifest.last_updated = (manifest.last_updated + 1) % idsManifest.chunks;
|
||||
|
||||
const url = `${IDS_API_BASE}/chunks/chunk-${manifest.last_updated}.dat.lz4`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const buffer = await response.arrayBuffer();
|
||||
const bytes = new Uint8Array(buffer);
|
||||
|
||||
const ids = IdArray.fromCompressed(bytes);
|
||||
const size = ids.size();
|
||||
|
||||
console.log(
|
||||
`Chunk ${manifest.last_updated} contains ${size} ids, estimated to take ${(size / API_RATE / 60).toFixed(0)}min`,
|
||||
);
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
await sleep();
|
||||
|
||||
const id = ids.get(i);
|
||||
const domain = idToRegion(id);
|
||||
|
||||
const url = `https://api.wotblitz.${
|
||||
domain
|
||||
}/wotb/tanks/stats/?application_id=${applicationId}&account_id=${id}`;
|
||||
const response = await fetch(url);
|
||||
const json = (await response.json()) as QuickStatistics;
|
||||
|
||||
const data = json.data[id];
|
||||
|
||||
if (json.status !== "ok" || data === null) {
|
||||
console.log(`Failed player ${id}; skipping...`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const tank of data) {
|
||||
console.log(new Date(tank.battle_life_time * 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// storage.commit();
|
||||
@@ -0,0 +1,26 @@
|
||||
export type PerformanceManifest = PerformanceManifestV1;
|
||||
|
||||
interface PerformanceManifestV1 {
|
||||
version: 1;
|
||||
last_updated: number;
|
||||
}
|
||||
|
||||
export interface QuickStatistics {
|
||||
status: string;
|
||||
data: Record<string, QuickStatisticsTank[] | null>;
|
||||
}
|
||||
|
||||
interface QuickStatisticsTank {
|
||||
last_battle_time: number;
|
||||
battle_life_time: number;
|
||||
tank_id: number;
|
||||
|
||||
all: Record<string, number>;
|
||||
}
|
||||
|
||||
interface Observations {
|
||||
count: number;
|
||||
observations: Record<number, Observation>;
|
||||
}
|
||||
|
||||
interface Observation {}
|
||||
+16
-3
@@ -1,6 +1,6 @@
|
||||
import { blueDark, orangeDark } from "@radix-ui/colors";
|
||||
import { ContactShadows } from "@react-three/drei";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import { invalidate, useFrame } from "@react-three/fiber";
|
||||
import { clamp, times } from "lodash-es";
|
||||
import { Quicklime } from "quicklime";
|
||||
import {
|
||||
@@ -71,7 +71,16 @@ export function Lighting() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContactShadows blur={2 ** 1} opacity={2 ** 1} />
|
||||
<ContactShadows
|
||||
near={0}
|
||||
far={2 ** 6}
|
||||
width={1.5}
|
||||
height={1.5}
|
||||
blur={2 ** 0.5}
|
||||
opacity={2 ** -0.4}
|
||||
resolution={2 ** 7}
|
||||
depthWrite={false}
|
||||
/>
|
||||
|
||||
{animate && (
|
||||
<Animator
|
||||
@@ -145,8 +154,12 @@ function Animator({ stop, t0, animationTime, wrapper }: AnimatorProps) {
|
||||
const factor =
|
||||
!hasPbr && display !== TankopediaDisplay.StaticArmor ? NON_PBR_FACTOR : 1;
|
||||
|
||||
useEffect(() => {
|
||||
invalidate();
|
||||
}, [requestedDisplay === display]);
|
||||
|
||||
const apply = useCallback((t: number) => {
|
||||
if (wrapper.current === null) return;
|
||||
if (!wrapper.current) return;
|
||||
|
||||
for (const child of wrapper.current.children) {
|
||||
if (child instanceof SpotLight) {
|
||||
|
||||
Reference in new issue
Block a user