Skip to content

Commit 621196c

Browse files
committed
Added early GAC stuff that isn't fully tested because CORS
1 parent d48a055 commit 621196c

8 files changed

Lines changed: 259 additions & 1 deletion

File tree

site/account-viewer/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ <h3>Profile Stats</h3>
7979
<ul id="profileStatList"></ul>
8080
</div>
8181
</section>
82+
83+
<section class="gac-info hidden">
84+
<div class="card">
85+
<h3>GAC Stats (ALPHA)</h3>
86+
<ul id="gacInfo"></ul>
87+
</div>
88+
</section>
8289
</main>
8390

8491
<script type="module" src="/src/account-viewer/main.ts"></script>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export interface EventInstance {
2+
eventInstanceId: string;
3+
startTime: number;
4+
endTime: number;
5+
season: number;
6+
instanceId: string;
7+
mode: "3v3" | "5v5";
8+
}
9+
10+
export async function getInstanceIds(roundType: "5v5" | "3v3"): Promise<EventInstance | null> {
11+
try {
12+
const resp = await fetch(`https://gahistory.c3po.wtf/${roundType}/info.json`);
13+
14+
if (!resp.ok) {
15+
console.error("HTTP error", resp.status, resp.statusText);
16+
return null;
17+
}
18+
19+
const data: EventInstance = await resp.json();
20+
return data;
21+
} catch (err) {
22+
console.error("Fetch failed:", err);
23+
return null;
24+
}
25+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { getRound } from "./request.ts"
2+
import type { GACResp } from "./request.ts"
3+
import { getPlayerPlayerId } from "../requestMaker.ts"
4+
import type { PlayerResp } from "../requestMaker.ts"
5+
import { galacticPowerMappings } from "../listBuilderMappings.ts"
6+
7+
export let round5v5: GACResp | null = null;
8+
export let round3v3: GACResp | null = null;
9+
10+
async function getData(playerId: string): Promise<void> {
11+
if (!round5v5 || round5v5.playerId !== playerId) {
12+
const tempRound5v5 = await getRound(playerId, "5v5");
13+
if (!tempRound5v5) {
14+
return;
15+
}
16+
round5v5 = tempRound5v5;
17+
}
18+
19+
if (!round3v3 || round3v3.playerId !== playerId) {
20+
const tempRound3v3 = await getRound(playerId, "3v3");
21+
if (!tempRound3v3) {
22+
return;
23+
}
24+
round3v3 = tempRound3v3;
25+
}
26+
}
27+
28+
export async function getWins(playerId: string, gp: number): Promise<number | null> {
29+
await getData(playerId);
30+
31+
if ((!round5v5 || !round3v3) || (round5v5.playerId !== playerId || round3v3.playerId !== playerId)) {
32+
console.error("Could not find round 5v5 or round 3v3, exiting")
33+
return null;
34+
}
35+
36+
let winCounter = 0;
37+
38+
for (const round of round5v5.matchResult) {
39+
const homeScore = round.home.score;
40+
const awayScore = round.away.score;
41+
42+
if (homeScore > awayScore) {
43+
winCounter++;
44+
continue;
45+
}
46+
if (homeScore === awayScore) {
47+
let won = await getTieWinner(round.away.playerId, gp);
48+
if (won) {
49+
winCounter++;
50+
continue;
51+
}
52+
}
53+
}
54+
55+
return winCounter;
56+
}
57+
58+
async function getTieWinner(awayPlayerId: string, homeGP: number): Promise<boolean> {
59+
const awayProfile: PlayerResp = await getPlayerPlayerId(awayPlayerId);
60+
let awayGP = 0;
61+
galacticPowerMappings.forEach(stat => {
62+
const playerStat = awayProfile.profileStat.find(ps => ps.index === stat.index)
63+
if (playerStat) {
64+
awayGP = Number(playerStat.value);
65+
}
66+
});
67+
if (awayGP === 0) {
68+
console.error("Found a player with 0 GP...");
69+
return true;
70+
}
71+
72+
if (homeGP > awayGP) {
73+
return true
74+
}
75+
return false
76+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
export interface GACResp {
2+
matchResult: MatchResult[];
3+
territoryMapId: string;
4+
eventInstanceId: string;
5+
league: string;
6+
startTime: number;
7+
endTime: number;
8+
date: string;
9+
mode: string;
10+
season: number;
11+
playerId: string;
12+
}
13+
14+
export interface MatchResult {
15+
attackResult: AttackResult[];
16+
matchId: number;
17+
home: PlayerSummary;
18+
away: PlayerSummary;
19+
matchState: number;
20+
}
21+
22+
export interface PlayerSummary {
23+
playerName: string;
24+
playerId: string;
25+
score: string;
26+
}
27+
28+
export interface AttackResult {
29+
duelResult: DuelResult[];
30+
zoneId: string;
31+
}
32+
33+
export interface DuelResult {
34+
defenderUnit: Unit[];
35+
attackerUnit: Unit[];
36+
startTime: string;
37+
endTime: string;
38+
battleOutcome: number;
39+
defenderDatacron: Datacron;
40+
attackerDatacron: Datacron;
41+
}
42+
43+
export interface Unit {
44+
definitionId: string;
45+
healthPercent: number;
46+
shieldPercent: number;
47+
squadUnitType: number;
48+
relicTier: number;
49+
tier: number;
50+
rarity: number;
51+
level: number;
52+
}
53+
54+
export interface Datacron {
55+
tag: string[];
56+
affix: Affix[];
57+
id: string;
58+
setId: number;
59+
templateId: string;
60+
highestTierApplied: number;
61+
}
62+
63+
export interface Affix {
64+
tag: string[];
65+
targetRule: string;
66+
abilityId: string;
67+
statType: number;
68+
statValue: string;
69+
requiredUnitTier: number;
70+
requiredRelicTier: number;
71+
scopeIcon: string;
72+
}
73+
74+
export async function getRound(playerId: string, roundType: "5v5" | "3v3"): Promise<GACResp | null> {
75+
try {
76+
const resp = await fetch(`https://gahistory.c3po.wtf/${roundType}/${playerId}.json`);
77+
78+
if (!resp.ok) {
79+
console.error("HTTP error", resp.status, resp.statusText);
80+
return null;
81+
}
82+
83+
const data: GACResp = await resp.json();
84+
return data;
85+
} catch (err) {
86+
console.error("Fetch failed:", err);
87+
return null;
88+
}
89+
}

site/src/account-viewer/listBuilder.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { PlayerResp, UnitsResp } from "./requestMaker.ts";
33
import { profileStatMappings, playerMappings, galacticPowerMappings, speedModMappings, pipMappings, relicMappings, gearMappings, rarityMappings } from "./listBuilderMappings.ts";
44
import { getSpeedModCount, getPipCount, countOffensePercentRolls } from "./mods.ts";
55
import { ULLocation, relicChart, gearChart, starChart, activeChart } from "./locations.ts"
6+
import { getWins } from "./grand-arena/main.ts"
7+
import { getInstanceIds } from "./grand-arena/getRecentRounds.ts"
68

79
function handleLastSeen(player: PlayerResp): void {
810
let lastSeen = new Date(Number(player.lastActivityTime)).toLocaleString();
@@ -136,6 +138,35 @@ function checkIfShip(units: UnitsResp[], defId: string): boolean {
136138
return false;
137139
}
138140

141+
async function handleGACWins(player: PlayerResp): Promise<void> {
142+
let gp = 0;
143+
galacticPowerMappings.forEach(stat => {
144+
const playerStat = player.profileStat.find(ps => ps.index === stat.index)
145+
if (playerStat) {
146+
gp = Number(playerStat.value);
147+
}
148+
});
149+
if (gp === 0) {
150+
console.error("Found a player with 0 GP...");
151+
return;
152+
}
153+
154+
const wins = await getWins(player.playerId, gp);
155+
const recent3v3 = await getInstanceIds("3v3");
156+
const recent5v5 = await getInstanceIds("5v5");
157+
if (!wins || !recent3v3 || !recent5v5) {
158+
console.error("Missing wins, recent3v3, or recent5v5 in handleGACWins()");
159+
return;
160+
}
161+
162+
let seasons: number[] = [];
163+
seasons.push(recent3v3.season);
164+
seasons.push(recent5v5.season);
165+
seasons.sort((a, b) => a - b);
166+
167+
ULLocation("gacInfo", `Wins in seasons ${seasons[0]} and ${seasons[1]}: ${wins}`);
168+
}
169+
139170
export async function FillList(allyCode: string) {
140171
const units = await getUnits();
141172
if (!units) {
@@ -190,6 +221,9 @@ export async function FillList(allyCode: string) {
190221
case 10:
191222
handleLastSeen(player);
192223
break;
224+
case 11:
225+
await handleGACWins(player);
226+
break;
193227
default:
194228
console.error(`Found unknown playerMappings key: ${key}`)
195229
}

site/src/account-viewer/listBuilderMappings.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,9 @@ export const playerMappings: Record<string, { displayType: number; displayName:
230230
"lastActive": {
231231
"displayType": 10,
232232
"displayName": "",
233+
},
234+
"GACWins": {
235+
"displayType": 11,
236+
"displayName": "",
233237
}
234238
};

site/src/account-viewer/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const loadingScreen = document.getElementById("loadingScreen") as HTMLElement;
1313
const backBtn = document.getElementById("backToInput") as HTMLButtonElement;
1414

1515
const dashboardSections = document.querySelectorAll<HTMLElement>(
16-
".player-info, .stats-grid, .charts-grid, .stats-grid-2, .back"
16+
".player-info, .stats-grid, .charts-grid, .stats-grid-2, .back" //, .gac-info
1717
);
1818

1919
submitBtn.addEventListener("click", async () => {

site/src/account-viewer/requestMaker.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,29 @@ export async function getPlayer(allyCode: string): Promise<any> {
167167
}
168168
}
169169

170+
export async function getPlayerPlayerId(playerId: string): Promise<any> {
171+
const header = await makeAuthHeader("It96XCNbCtVhN7Hg+a2cPSJJ7WF7jG6YuBybI1lLS4XykNQwcWm+0fkk2ciKaeLy", "LegoFan9", "GET", "/player");
172+
//console.log("Authorization:", header);
173+
174+
try {
175+
const resp = await fetch(`${SERVER_URL}/player?playerId=${playerId}`, {
176+
headers: { Authorization: header }
177+
});
178+
179+
if (!resp.ok) {
180+
console.error("HTTP error", resp.status, resp.statusText);
181+
return null;
182+
}
183+
184+
const data = await resp.json();
185+
//console.log(`Response:\n${JSON.stringify(data, null, 2)}`);
186+
return data;
187+
} catch (err) {
188+
console.error("Fetch failed:", err);
189+
return null;
190+
}
191+
}
192+
170193
export function cleanAllyCode(input: string): string | null {
171194
const digitsOnly = input.replace(/\D/g, "");
172195

0 commit comments

Comments
 (0)