feat(plugins/community/splatoon): upgrade s3si version
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
// deno-fmt-ignore-file
|
// deno-fmt-ignore-file
|
||||||
// deno-lint-ignore-file
|
// deno-lint-ignore-file
|
||||||
// This code was bundled using `deno bundle` and it's not recommended to edit it manually
|
// This code was bundled using `deno bundle` and it's not recommended to edit it manually
|
||||||
// https://raw.githubusercontent.com/spacemeowx2/s3si.ts/main/s3si.ts
|
|
||||||
|
|
||||||
class APIError extends Error {
|
class APIError extends Error {
|
||||||
response;
|
response;
|
||||||
@@ -13,9 +12,9 @@ class APIError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const AGENT_NAME = "s3si.ts";
|
const AGENT_NAME = "s3si.ts";
|
||||||
const S3SI_VERSION = "0.1.36";
|
const S3SI_VERSION = "0.2.1";
|
||||||
const NSOAPP_VERSION = "2.3.1";
|
const NSOAPP_VERSION = "2.4.0";
|
||||||
const WEB_VIEW_VERSION = "2.0.0-8a061f6c";
|
const WEB_VIEW_VERSION = "2.0.0-18810d39";
|
||||||
const S3SI_LINK = "https://github.com/spacemeowx2/s3si.ts";
|
const S3SI_LINK = "https://github.com/spacemeowx2/s3si.ts";
|
||||||
const USERAGENT = `${AGENT_NAME}/${S3SI_VERSION} (${S3SI_LINK})`;
|
const USERAGENT = `${AGENT_NAME}/${S3SI_VERSION} (${S3SI_LINK})`;
|
||||||
const DEFAULT_APP_USER_AGENT = "Mozilla/5.0 (Linux; Android 11; Pixel 5) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/94.0.4606.61 Mobile Safari/537.36";
|
const DEFAULT_APP_USER_AGENT = "Mozilla/5.0 (Linux; Android 11; Pixel 5) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/94.0.4606.61 Mobile Safari/537.36";
|
||||||
@@ -5033,6 +5032,11 @@ function s3siGameId(id) {
|
|||||||
const tsUuid = fullId.slice(fullId.length - 52, fullId.length);
|
const tsUuid = fullId.slice(fullId.length - 52, fullId.length);
|
||||||
return mod6.v5.generate(S3SI_NAMESPACE, tsUuid);
|
return mod6.v5.generate(S3SI_NAMESPACE, tsUuid);
|
||||||
}
|
}
|
||||||
|
function s3sCoopGameId(id) {
|
||||||
|
const fullId = mod.decode(id);
|
||||||
|
const tsUuid = fullId.slice(fullId.length - 52, fullId.length);
|
||||||
|
return mod6.v5.generate(COOP_NAMESPACE, tsUuid);
|
||||||
|
}
|
||||||
function parseHistoryDetailId(id) {
|
function parseHistoryDetailId(id) {
|
||||||
const plainText = new TextDecoder().decode(mod.decode(id));
|
const plainText = new TextDecoder().decode(mod.decode(id));
|
||||||
const vsRE = /VsHistoryDetail-([a-z0-9-]+):(\w+):(\d{8}T\d{6})_([0-9a-f-]{36})/;
|
const vsRE = /VsHistoryDetail-([a-z0-9-]+):(\w+):(\d{8}T\d{6})_([0-9a-f-]{36})/;
|
||||||
@@ -5460,6 +5464,7 @@ var Queries;
|
|||||||
Queries["LatestBattleHistoriesQuery"] = "4f5f26e64bca394b45345a65a2f383bd";
|
Queries["LatestBattleHistoriesQuery"] = "4f5f26e64bca394b45345a65a2f383bd";
|
||||||
Queries["RegularBattleHistoriesQuery"] = "d5b795d09e67ce153e622a184b7e7dfa";
|
Queries["RegularBattleHistoriesQuery"] = "d5b795d09e67ce153e622a184b7e7dfa";
|
||||||
Queries["BankaraBattleHistoriesQuery"] = "de4754588109b77dbcb90fbe44b612ee";
|
Queries["BankaraBattleHistoriesQuery"] = "de4754588109b77dbcb90fbe44b612ee";
|
||||||
|
Queries["XBattleHistoriesQuery"] = "45c74fefb45a49073207229ca65f0a62";
|
||||||
Queries["PrivateBattleHistoriesQuery"] = "1d6ed57dc8b801863126ad4f351dfb9a";
|
Queries["PrivateBattleHistoriesQuery"] = "1d6ed57dc8b801863126ad4f351dfb9a";
|
||||||
Queries["VsHistoryDetailQuery"] = "291295ad311b99a6288fc95a5c4cb2d2";
|
Queries["VsHistoryDetailQuery"] = "291295ad311b99a6288fc95a5c4cb2d2";
|
||||||
Queries["CoopHistoryQuery"] = "6ed02537e4a65bbb5e7f4f23092f6154";
|
Queries["CoopHistoryQuery"] = "6ed02537e4a65bbb5e7f4f23092f6154";
|
||||||
@@ -5612,6 +5617,9 @@ class Splatnet3 {
|
|||||||
const resp = await this.request(Queries.BankaraBattleHistoriesQuery);
|
const resp = await this.request(Queries.BankaraBattleHistoriesQuery);
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
async getXBattleHistories() {
|
||||||
|
return await this.request(Queries.XBattleHistoriesQuery);
|
||||||
|
}
|
||||||
async getCoopHistories() {
|
async getCoopHistories() {
|
||||||
const resp = await this.request(Queries.CoopHistoryQuery);
|
const resp = await this.request(Queries.CoopHistoryQuery);
|
||||||
return resp;
|
return resp;
|
||||||
@@ -5709,6 +5717,16 @@ const COOP_POINT_MAP = {
|
|||||||
2: 0,
|
2: 0,
|
||||||
3: 20
|
3: 20
|
||||||
};
|
};
|
||||||
|
async function checkResponse(resp) {
|
||||||
|
if (Math.floor(resp.status / 100) !== 2) {
|
||||||
|
const json = await resp.json().catch(()=>undefined);
|
||||||
|
throw new APIError({
|
||||||
|
response: resp,
|
||||||
|
json,
|
||||||
|
message: "Failed to fetch data from stat.ink"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
class StatInkAPI {
|
class StatInkAPI {
|
||||||
statInk;
|
statInk;
|
||||||
FETCH_LOCK;
|
FETCH_LOCK;
|
||||||
@@ -5719,11 +5737,7 @@ class StatInkAPI {
|
|||||||
this.statInk = "https://stat.ink";
|
this.statInk = "https://stat.ink";
|
||||||
this.FETCH_LOCK = new Mutex();
|
this.FETCH_LOCK = new Mutex();
|
||||||
this.cache = {};
|
this.cache = {};
|
||||||
this._specialMap = new Map();
|
|
||||||
this._salmonWeaponMap = new Map();
|
this._salmonWeaponMap = new Map();
|
||||||
this.getSpecial = ()=>{
|
|
||||||
throw new Error("Not implemented");
|
|
||||||
};
|
|
||||||
this.getSalmonWeapon = ()=>this._getCached(`${this.statInk}/api/v3/salmon/weapon?full=1`);
|
this.getSalmonWeapon = ()=>this._getCached(`${this.statInk}/api/v3/salmon/weapon?full=1`);
|
||||||
this.getWeapon = ()=>this._getCached(`${this.statInk}/api/v3/weapon?full=1`);
|
this.getWeapon = ()=>this._getCached(`${this.statInk}/api/v3/weapon?full=1`);
|
||||||
this.getAbility = ()=>this._getCached(`${this.statInk}/api/v3/ability?full=1`);
|
this.getAbility = ()=>this._getCached(`${this.statInk}/api/v3/ability?full=1`);
|
||||||
@@ -5744,6 +5758,7 @@ class StatInkAPI {
|
|||||||
url: type === "VsInfo" ? `${this.statInk}/api/v3/s3s/uuid-list` : `${this.statInk}/api/v3/salmon/uuid-list`,
|
url: type === "VsInfo" ? `${this.statInk}/api/v3/s3s/uuid-list` : `${this.statInk}/api/v3/salmon/uuid-list`,
|
||||||
headers: this.requestHeaders()
|
headers: this.requestHeaders()
|
||||||
});
|
});
|
||||||
|
await checkResponse(response);
|
||||||
const uuidResult = await response.json();
|
const uuidResult = await response.json();
|
||||||
if (!Array.isArray(uuidResult)) {
|
if (!Array.isArray(uuidResult)) {
|
||||||
throw new APIError({
|
throw new APIError({
|
||||||
@@ -5819,6 +5834,7 @@ class StatInkAPI {
|
|||||||
url,
|
url,
|
||||||
headers: this.requestHeaders()
|
headers: this.requestHeaders()
|
||||||
});
|
});
|
||||||
|
await checkResponse(resp);
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
this.cache[url] = json;
|
this.cache[url] = json;
|
||||||
return json;
|
return json;
|
||||||
@@ -5840,25 +5856,6 @@ class StatInkAPI {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_specialMap;
|
|
||||||
async getSpecialMap() {
|
|
||||||
if (this._specialMap.size === 0) {
|
|
||||||
const specials = await this.getSpecial();
|
|
||||||
for (const special of specials){
|
|
||||||
for (const name of Object.values(special.name).flatMap((n)=>this._getAliasName(n))){
|
|
||||||
const prevKey = this._specialMap.get(name);
|
|
||||||
if (prevKey !== undefined && prevKey !== special.key) {
|
|
||||||
console.warn(`Duplicate weapon name: ${name}`);
|
|
||||||
}
|
|
||||||
this._specialMap.set(name, special.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this._specialMap.size === 0) {
|
|
||||||
throw new Error("Failed to get salmon weapon map");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._specialMap;
|
|
||||||
}
|
|
||||||
_salmonWeaponMap;
|
_salmonWeaponMap;
|
||||||
async getSalmonWeaponMap() {
|
async getSalmonWeaponMap() {
|
||||||
if (this._salmonWeaponMap.size === 0) {
|
if (this._salmonWeaponMap.size === 0) {
|
||||||
@@ -5878,7 +5875,6 @@ class StatInkAPI {
|
|||||||
}
|
}
|
||||||
return this._salmonWeaponMap;
|
return this._salmonWeaponMap;
|
||||||
}
|
}
|
||||||
getSpecial;
|
|
||||||
getSalmonWeapon;
|
getSalmonWeapon;
|
||||||
getWeapon;
|
getWeapon;
|
||||||
getAbility;
|
getAbility;
|
||||||
@@ -5926,7 +5922,8 @@ class StatInkExporter {
|
|||||||
for (const id of list){
|
for (const id of list){
|
||||||
const s3sId = await gameId(id);
|
const s3sId = await gameId(id);
|
||||||
const s3siId = await s3siGameId(id);
|
const s3siId = await s3siGameId(id);
|
||||||
if (!uuid.includes(s3sId) && !uuid.includes(s3siId)) {
|
const s3sCoopId = await s3sCoopGameId(id);
|
||||||
|
if (!uuid.includes(s3sId) && !uuid.includes(s3siId) && !uuid.includes(s3sCoopId)) {
|
||||||
out.push(id);
|
out.push(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5960,6 +5957,8 @@ class StatInkExporter {
|
|||||||
} else if (modeId === 8) {
|
} else if (modeId === 8) {
|
||||||
throw new Error("Tri-color battle is not supported");
|
throw new Error("Tri-color battle is not supported");
|
||||||
}
|
}
|
||||||
|
} else if (vsMode === "X_MATCH") {
|
||||||
|
return "xmatch";
|
||||||
}
|
}
|
||||||
throw new TypeError(`Unknown vsMode ${vsMode}`);
|
throw new TypeError(`Unknown vsMode ${vsMode}`);
|
||||||
}
|
}
|
||||||
@@ -6021,7 +6020,7 @@ class StatInkExporter {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
async mapBattle({ challengeProgress , bankaraMatchChallenge , listNode , detail: vsDetail , rankBeforeState , rankState }) {
|
async mapBattle({ groupInfo , challengeProgress , bankaraMatchChallenge , listNode , detail: vsDetail , rankBeforeState , rankState }) {
|
||||||
const { knockout , vsRule: { rule } , myTeam , otherTeams , bankaraMatch , festMatch , playedTime } = vsDetail;
|
const { knockout , vsRule: { rule } , myTeam , otherTeams , bankaraMatch , festMatch , playedTime } = vsDetail;
|
||||||
const self = vsDetail.myTeam.players.find((i)=>i.isMyself);
|
const self = vsDetail.myTeam.players.find((i)=>i.isMyself);
|
||||||
if (!self) {
|
if (!self) {
|
||||||
@@ -6073,7 +6072,7 @@ class StatInkExporter {
|
|||||||
result.our_team_count = myTeam?.result?.score ?? undefined;
|
result.our_team_count = myTeam?.result?.score ?? undefined;
|
||||||
result.their_team_count = otherTeams?.[0]?.result?.score ?? undefined;
|
result.their_team_count = otherTeams?.[0]?.result?.score ?? undefined;
|
||||||
result.rank_exp_change = bankaraMatch?.earnedUdemaePoint ?? undefined;
|
result.rank_exp_change = bankaraMatch?.earnedUdemaePoint ?? undefined;
|
||||||
if (listNode) {
|
if (listNode?.udemae) {
|
||||||
[result.rank_before, result.rank_before_s_plus] = parseUdemae(listNode.udemae);
|
[result.rank_before, result.rank_before_s_plus] = parseUdemae(listNode.udemae);
|
||||||
}
|
}
|
||||||
if (bankaraMatchChallenge && challengeProgress) {
|
if (bankaraMatchChallenge && challengeProgress) {
|
||||||
@@ -6085,9 +6084,17 @@ class StatInkExporter {
|
|||||||
result.rank_after = result.rank_before;
|
result.rank_after = result.rank_before;
|
||||||
result.rank_after_s_plus = result.rank_before_s_plus;
|
result.rank_after_s_plus = result.rank_before_s_plus;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (challengeProgress) {
|
||||||
result.challenge_win = challengeProgress.winCount;
|
result.challenge_win = challengeProgress.winCount;
|
||||||
result.challenge_lose = challengeProgress.loseCount;
|
result.challenge_lose = challengeProgress.loseCount;
|
||||||
}
|
}
|
||||||
|
if (vsDetail.xMatch) {
|
||||||
|
result.x_power_before = result.x_power_after = vsDetail.xMatch.lastXPower;
|
||||||
|
if (groupInfo?.xMatchMeasurement && groupInfo?.xMatchMeasurement.state === "COMPLETED" && challengeProgress?.index === 0) {
|
||||||
|
result.x_power_after = groupInfo.xMatchMeasurement.xPowerAfter;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (rankBeforeState && rankState) {
|
if (rankBeforeState && rankState) {
|
||||||
result.rank_before_exp = rankBeforeState.rankPoint;
|
result.rank_before_exp = rankBeforeState.rankPoint;
|
||||||
result.rank_after_exp = rankState.rankPoint;
|
result.rank_after_exp = rankState.rankPoint;
|
||||||
@@ -6103,22 +6110,22 @@ class StatInkExporter {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
isRandomWeapon(image) {
|
isRandom(image) {
|
||||||
const RANDOM_WEAPON_FILENAME = "473fffb2442075078d8bb7125744905abdeae651b6a5b7453ae295582e45f7d1";
|
const RANDOM_FILENAME = "473fffb2442075078d8bb7125744905abdeae651b6a5b7453ae295582e45f7d1";
|
||||||
const url = image?.url;
|
const url = image?.url;
|
||||||
if (typeof url === "string") {
|
if (typeof url === "string") {
|
||||||
return url.includes(RANDOM_WEAPON_FILENAME);
|
return url.includes(RANDOM_FILENAME);
|
||||||
} else if (url === undefined || url === null) {
|
} else if (url === undefined || url === null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return url.pathname.includes(RANDOM_WEAPON_FILENAME);
|
return url.pathname.includes(RANDOM_FILENAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async mapCoopWeapon({ name , image }) {
|
async mapCoopWeapon({ name , image }) {
|
||||||
const weaponMap = await this.api.getSalmonWeaponMap();
|
const weaponMap = await this.api.getSalmonWeaponMap();
|
||||||
const weapon = weaponMap.get(name);
|
const weapon = weaponMap.get(name);
|
||||||
if (!weapon) {
|
if (!weapon) {
|
||||||
if (this.isRandomWeapon(image)) {
|
if (this.isRandom(image)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
throw new Error(`Weapon not found: ${name}`);
|
throw new Error(`Weapon not found: ${name}`);
|
||||||
@@ -6131,13 +6138,23 @@ class StatInkExporter {
|
|||||||
const hash = /\/(\w+)_0\.\w+/.exec(imageName)?.[1] ?? "";
|
const hash = /\/(\w+)_0\.\w+/.exec(imageName)?.[1] ?? "";
|
||||||
const special = SPLATNET3_STATINK_MAP.COOP_SPECIAL_MAP[hash];
|
const special = SPLATNET3_STATINK_MAP.COOP_SPECIAL_MAP[hash];
|
||||||
if (!special) {
|
if (!special) {
|
||||||
|
if (this.isRandom(image)) {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
throw new Error(`Special not found: ${name} (${imageName})`);
|
throw new Error(`Special not found: ${name} (${imageName})`);
|
||||||
}
|
}
|
||||||
return Promise.resolve(special);
|
return Promise.resolve(special);
|
||||||
}
|
}
|
||||||
async mapCoopPlayer({ player , weapons , specialWeapon , defeatEnemyCount , deliverCount , goldenAssistCount , goldenDeliverCount , rescueCount , rescuedCount }) {
|
async mapCoopPlayer(isMyself, { player , weapons , specialWeapon , defeatEnemyCount , deliverCount , goldenAssistCount , goldenDeliverCount , rescueCount , rescuedCount }) {
|
||||||
|
const disconnected = [
|
||||||
|
goldenDeliverCount,
|
||||||
|
deliverCount,
|
||||||
|
rescueCount,
|
||||||
|
rescuedCount,
|
||||||
|
defeatEnemyCount
|
||||||
|
].every((v)=>v === 0) || !specialWeapon;
|
||||||
return {
|
return {
|
||||||
me: player.isMyself ? "yes" : "no",
|
me: isMyself ? "yes" : "no",
|
||||||
name: player.name,
|
name: player.name,
|
||||||
number: player.nameId,
|
number: player.nameId,
|
||||||
splashtag_title: player.byname,
|
splashtag_title: player.byname,
|
||||||
@@ -6150,7 +6167,7 @@ class StatInkExporter {
|
|||||||
rescue: rescueCount,
|
rescue: rescueCount,
|
||||||
rescued: rescuedCount,
|
rescued: rescuedCount,
|
||||||
defeat_boss: defeatEnemyCount,
|
defeat_boss: defeatEnemyCount,
|
||||||
disconnected: specialWeapon ? "no" : "yes"
|
disconnected: disconnected ? "yes" : "no"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
mapKing(id) {
|
mapKing(id) {
|
||||||
@@ -6162,7 +6179,9 @@ class StatInkExporter {
|
|||||||
}
|
}
|
||||||
async mapWave(wave) {
|
async mapWave(wave) {
|
||||||
const event = wave.eventWave ? SPLATNET3_STATINK_MAP.COOP_EVENT_MAP[b64Number(wave.eventWave.id)] : undefined;
|
const event = wave.eventWave ? SPLATNET3_STATINK_MAP.COOP_EVENT_MAP[b64Number(wave.eventWave.id)] : undefined;
|
||||||
const special_uses = (await Promise.all(wave.specialWeapons.map((w)=>this.mapSpecial(w)))).reduce((p, key)=>({
|
const special_uses = (await Promise.all(wave.specialWeapons.map((w)=>this.mapSpecial(w)))).flatMap((key)=>key ? [
|
||||||
|
key
|
||||||
|
] : []).reduce((p, key)=>({
|
||||||
...p,
|
...p,
|
||||||
[key]: (p[key] ?? 0) + 1
|
[key]: (p[key] ?? 0) + 1
|
||||||
}), {});
|
}), {});
|
||||||
@@ -6199,12 +6218,16 @@ class StatInkExporter {
|
|||||||
let title_before = undefined;
|
let title_before = undefined;
|
||||||
let title_exp_before = undefined;
|
let title_exp_before = undefined;
|
||||||
const expDiff = COOP_POINT_MAP[clear_waves];
|
const expDiff = COOP_POINT_MAP[clear_waves];
|
||||||
if (nonNullable(title_exp_after) && nonNullable(expDiff)) {
|
if (nonNullable(title_after) && nonNullable(title_exp_after) && nonNullable(expDiff)) {
|
||||||
if (title_exp_after === 40 && expDiff === 20) {} else if (title_exp_after === 40 && expDiff < 0 && title_after !== "8") {} else if (title_exp_after === 999 && expDiff !== 0) {
|
if (title_exp_after === 40 && expDiff === 20) {} else if (title_exp_after === 40 && expDiff < 0 && title_after !== "8") {} else if (title_exp_after === 999 && expDiff !== 0) {
|
||||||
title_before = title_after;
|
title_before = title_after;
|
||||||
} else {
|
} else {
|
||||||
title_before = title_after;
|
if (title_exp_after - expDiff >= 0) {
|
||||||
title_exp_before = title_exp_after - expDiff;
|
title_before = title_after;
|
||||||
|
title_exp_before = title_exp_after - expDiff;
|
||||||
|
} else {
|
||||||
|
title_before = (parseInt(title_after) - 1).toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let fail_reason = null;
|
let fail_reason = null;
|
||||||
@@ -6240,8 +6263,8 @@ class StatInkExporter {
|
|||||||
job_bonus: detail.jobBonus,
|
job_bonus: detail.jobBonus,
|
||||||
waves: await Promise.all(detail.waveResults.map((w)=>this.mapWave(w))),
|
waves: await Promise.all(detail.waveResults.map((w)=>this.mapWave(w))),
|
||||||
players: await Promise.all([
|
players: await Promise.all([
|
||||||
this.mapCoopPlayer(myResult),
|
this.mapCoopPlayer(true, myResult),
|
||||||
...memberResults.map((p)=>this.mapCoopPlayer(p))
|
...memberResults.map((p)=>this.mapCoopPlayer(false, p))
|
||||||
]),
|
]),
|
||||||
bosses,
|
bosses,
|
||||||
agent: AGENT_NAME,
|
agent: AGENT_NAME,
|
||||||
@@ -6387,7 +6410,7 @@ const splusParams = ()=>{
|
|||||||
300 + level * 350,
|
300 + level * 350,
|
||||||
300 + (level + 1) * 350
|
300 + (level + 1) * 350
|
||||||
],
|
],
|
||||||
charge: 160
|
charge: 180
|
||||||
};
|
};
|
||||||
if (level === 9) {
|
if (level === 9) {
|
||||||
item.promotion = true;
|
item.promotion = true;
|
||||||
@@ -6400,7 +6423,7 @@ const splusParams = ()=>{
|
|||||||
0,
|
0,
|
||||||
9999
|
9999
|
||||||
],
|
],
|
||||||
charge: 160
|
charge: 180
|
||||||
});
|
});
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
@@ -6461,7 +6484,7 @@ const RANK_PARAMS = [
|
|||||||
200,
|
200,
|
||||||
500
|
500
|
||||||
],
|
],
|
||||||
charge: 100
|
charge: 110
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
rank: "A",
|
rank: "A",
|
||||||
@@ -6469,7 +6492,7 @@ const RANK_PARAMS = [
|
|||||||
500,
|
500,
|
||||||
800
|
800
|
||||||
],
|
],
|
||||||
charge: 110
|
charge: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
rank: "A+",
|
rank: "A+",
|
||||||
@@ -6477,7 +6500,7 @@ const RANK_PARAMS = [
|
|||||||
800,
|
800,
|
||||||
1100
|
1100
|
||||||
],
|
],
|
||||||
charge: 120,
|
charge: 130,
|
||||||
promotion: true
|
promotion: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -6486,14 +6509,14 @@ const RANK_PARAMS = [
|
|||||||
300,
|
300,
|
||||||
1000
|
1000
|
||||||
],
|
],
|
||||||
charge: 150,
|
charge: 170,
|
||||||
promotion: true
|
promotion: true
|
||||||
},
|
},
|
||||||
...splusParams()
|
...splusParams()
|
||||||
];
|
];
|
||||||
function addRank(state, delta) {
|
function addRank(state, delta) {
|
||||||
const { rank , rankPoint } = state;
|
const { rank , rankPoint } = state;
|
||||||
const { gameId , rankAfter , isPromotion , isRankUp , isChallengeFirst } = delta;
|
const { gameId , timestamp , rankAfter , isPromotion , isRankUp , isChallengeFirst } = delta;
|
||||||
const rankIndex = RANK_PARAMS.findIndex((r)=>r.rank === rank);
|
const rankIndex = RANK_PARAMS.findIndex((r)=>r.rank === rank);
|
||||||
if (rankIndex === -1) {
|
if (rankIndex === -1) {
|
||||||
throw new Error(`Rank not found: ${rank}`);
|
throw new Error(`Rank not found: ${rank}`);
|
||||||
@@ -6502,12 +6525,14 @@ function addRank(state, delta) {
|
|||||||
if (isChallengeFirst) {
|
if (isChallengeFirst) {
|
||||||
return {
|
return {
|
||||||
gameId,
|
gameId,
|
||||||
|
timestamp,
|
||||||
rank,
|
rank,
|
||||||
rankPoint: rankPoint - rankParam.charge
|
rankPoint: rankPoint - rankParam.charge
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (rankIndex === RANK_PARAMS.length - 1) {
|
if (rankIndex === RANK_PARAMS.length - 1) {
|
||||||
return {
|
return {
|
||||||
|
timestamp,
|
||||||
gameId,
|
gameId,
|
||||||
rank,
|
rank,
|
||||||
rankPoint: Math.min(rankPoint + delta.rankPoint, rankParam.pointRange[1])
|
rankPoint: Math.min(rankPoint + delta.rankPoint, rankParam.pointRange[1])
|
||||||
@@ -6517,12 +6542,14 @@ function addRank(state, delta) {
|
|||||||
const nextRankParam = RANK_PARAMS[rankIndex + 1];
|
const nextRankParam = RANK_PARAMS[rankIndex + 1];
|
||||||
return {
|
return {
|
||||||
gameId,
|
gameId,
|
||||||
|
timestamp,
|
||||||
rank: nextRankParam.rank,
|
rank: nextRankParam.rank,
|
||||||
rankPoint: nextRankParam.pointRange[0]
|
rankPoint: nextRankParam.pointRange[0]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
gameId,
|
gameId,
|
||||||
|
timestamp,
|
||||||
rank: rankAfter ?? rank,
|
rank: rankAfter ?? rank,
|
||||||
rankPoint: rankPoint + delta.rankPoint
|
rankPoint: rankPoint + delta.rankPoint
|
||||||
};
|
};
|
||||||
@@ -6547,6 +6574,7 @@ function generateDeltaList(state, flatten) {
|
|||||||
let delta = {
|
let delta = {
|
||||||
beforeGameId,
|
beforeGameId,
|
||||||
gameId: i.gameId,
|
gameId: i.gameId,
|
||||||
|
timestamp: Math.floor(i.time.getTime() / 1000),
|
||||||
rankPoint: 0,
|
rankPoint: 0,
|
||||||
isPromotion: false,
|
isPromotion: false,
|
||||||
isRankUp: false,
|
isRankUp: false,
|
||||||
@@ -6582,12 +6610,16 @@ function generateDeltaList(state, flatten) {
|
|||||||
}
|
}
|
||||||
function getRankState(i) {
|
function getRankState(i) {
|
||||||
const rank = i.detail.udemae;
|
const rank = i.detail.udemae;
|
||||||
|
if (!rank) {
|
||||||
|
throw new Error("rank must be defined");
|
||||||
|
}
|
||||||
const param = RANK_PARAMS.find((i)=>i.rank === rank);
|
const param = RANK_PARAMS.find((i)=>i.rank === rank);
|
||||||
if (!param) {
|
if (!param) {
|
||||||
throw new Error(`Rank not found: ${rank}`);
|
throw new Error(`Rank not found: ${rank}`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
gameId: i.gameId,
|
gameId: i.gameId,
|
||||||
|
timestamp: Math.floor(i.time.getTime() / 1000),
|
||||||
rank,
|
rank,
|
||||||
rankPoint: -1
|
rankPoint: -1
|
||||||
};
|
};
|
||||||
@@ -6627,6 +6659,7 @@ class RankTracker {
|
|||||||
async updateState(history) {
|
async updateState(history) {
|
||||||
const flatten = await Promise.all(history.flatMap(({ historyDetails , bankaraMatchChallenge })=>{
|
const flatten = await Promise.all(history.flatMap(({ historyDetails , bankaraMatchChallenge })=>{
|
||||||
return historyDetails.nodes.map((j, index)=>({
|
return historyDetails.nodes.map((j, index)=>({
|
||||||
|
id: j.id,
|
||||||
time: battleTime(j.id),
|
time: battleTime(j.id),
|
||||||
gameId: gameId(j.id),
|
gameId: gameId(j.id),
|
||||||
bankaraMatchChallenge,
|
bankaraMatchChallenge,
|
||||||
@@ -6683,6 +6716,8 @@ class GameFetcher {
|
|||||||
bankaraHistory;
|
bankaraHistory;
|
||||||
coopLock = new Mutex();
|
coopLock = new Mutex();
|
||||||
coopHistory;
|
coopHistory;
|
||||||
|
xMatchLock = new Mutex();
|
||||||
|
xMatchHistory;
|
||||||
constructor({ cache =new MemoryCache() , splatnet , state }){
|
constructor({ cache =new MemoryCache() , splatnet , state }){
|
||||||
this._splatnet = splatnet;
|
this._splatnet = splatnet;
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
@@ -6712,7 +6747,23 @@ class GameFetcher {
|
|||||||
getRankStateById(id) {
|
getRankStateById(id) {
|
||||||
return this.rankTracker.getRankStateById(id);
|
return this.rankTracker.getRankStateById(id);
|
||||||
}
|
}
|
||||||
|
getXMatchHistory() {
|
||||||
|
if (!this._splatnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this.xMatchLock.use(async ()=>{
|
||||||
|
if (this.xMatchHistory) {
|
||||||
|
return this.xMatchHistory;
|
||||||
|
}
|
||||||
|
const { xBattleHistories: { historyGroups } } = await this.splatnet.getXBattleHistories();
|
||||||
|
this.xMatchHistory = historyGroups.nodes;
|
||||||
|
return this.xMatchHistory;
|
||||||
|
});
|
||||||
|
}
|
||||||
getBankaraHistory() {
|
getBankaraHistory() {
|
||||||
|
if (!this._splatnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return this.bankaraLock.use(async ()=>{
|
return this.bankaraLock.use(async ()=>{
|
||||||
if (this.bankaraHistory) {
|
if (this.bankaraHistory) {
|
||||||
return this.bankaraHistory;
|
return this.bankaraHistory;
|
||||||
@@ -6723,6 +6774,9 @@ class GameFetcher {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
getCoopHistory() {
|
getCoopHistory() {
|
||||||
|
if (!this._splatnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return this.coopLock.use(async ()=>{
|
return this.coopLock.use(async ()=>{
|
||||||
if (this.coopHistory) {
|
if (this.coopHistory) {
|
||||||
return this.coopHistory;
|
return this.coopHistory;
|
||||||
@@ -6750,16 +6804,20 @@ class GameFetcher {
|
|||||||
groupInfo
|
groupInfo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async getBattleMetaById(id) {
|
async getBattleMetaById(id, vsMode) {
|
||||||
const gid = await gameId(id);
|
const gid = await gameId(id);
|
||||||
const bankaraHistory = this._splatnet ? await this.getBankaraHistory() : [];
|
|
||||||
const gameIdMap = new Map();
|
const gameIdMap = new Map();
|
||||||
for (const i of bankaraHistory){
|
let group = null;
|
||||||
for (const j of i.historyDetails.nodes){
|
let listNode = null;
|
||||||
gameIdMap.set(j, await gameId(j.id));
|
if (vsMode === "BANKARA" || vsMode === "X_MATCH") {
|
||||||
|
const bankaraHistory = vsMode === "BANKARA" ? await this.getBankaraHistory() : await this.getXMatchHistory();
|
||||||
|
for (const i of bankaraHistory){
|
||||||
|
for (const j of i.historyDetails.nodes){
|
||||||
|
gameIdMap.set(j, await gameId(j.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
group = bankaraHistory.find((i)=>i.historyDetails.nodes.some((i)=>gameIdMap.get(i) === gid)) ?? null;
|
||||||
}
|
}
|
||||||
const group = bankaraHistory.find((i)=>i.historyDetails.nodes.some((i)=>gameIdMap.get(i) === gid));
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
return {
|
return {
|
||||||
type: "VsInfo",
|
type: "VsInfo",
|
||||||
@@ -6767,16 +6825,19 @@ class GameFetcher {
|
|||||||
bankaraMatchChallenge: null,
|
bankaraMatchChallenge: null,
|
||||||
listNode: null,
|
listNode: null,
|
||||||
rankState: null,
|
rankState: null,
|
||||||
rankBeforeState: null
|
rankBeforeState: null,
|
||||||
|
groupInfo: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const { bankaraMatchChallenge } = group;
|
const { bankaraMatchChallenge , xMatchMeasurement } = group;
|
||||||
const listNode = group.historyDetails.nodes.find((i)=>gameIdMap.get(i) === gid) ?? null;
|
const { historyDetails , ...groupInfo } = group;
|
||||||
const index = group.historyDetails.nodes.indexOf(listNode);
|
listNode = historyDetails.nodes.find((i)=>gameIdMap.get(i) === gid) ?? null;
|
||||||
|
const index = historyDetails.nodes.indexOf(listNode);
|
||||||
let challengeProgress = null;
|
let challengeProgress = null;
|
||||||
if (bankaraMatchChallenge) {
|
const challengeOrMeasurement = bankaraMatchChallenge || xMatchMeasurement;
|
||||||
const pastBattles = group.historyDetails.nodes.slice(0, index);
|
if (challengeOrMeasurement) {
|
||||||
const { winCount , loseCount } = bankaraMatchChallenge;
|
const pastBattles = historyDetails.nodes.slice(0, index);
|
||||||
|
const { winCount , loseCount } = challengeOrMeasurement;
|
||||||
challengeProgress = {
|
challengeProgress = {
|
||||||
index,
|
index,
|
||||||
winCount: winCount - pastBattles.filter((i)=>i.judgement == "WIN").length,
|
winCount: winCount - pastBattles.filter((i)=>i.judgement == "WIN").length,
|
||||||
@@ -6793,7 +6854,8 @@ class GameFetcher {
|
|||||||
listNode,
|
listNode,
|
||||||
challengeProgress,
|
challengeProgress,
|
||||||
rankState: after ?? null,
|
rankState: after ?? null,
|
||||||
rankBeforeState: before ?? null
|
rankBeforeState: before ?? null,
|
||||||
|
groupInfo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
cacheDetail(id, getter) {
|
cacheDetail(id, getter) {
|
||||||
@@ -6820,7 +6882,7 @@ class GameFetcher {
|
|||||||
}
|
}
|
||||||
async fetchBattle(id) {
|
async fetchBattle(id) {
|
||||||
const detail = await this.cacheDetail(id, ()=>this.splatnet.getBattleDetail(id).then((r)=>r.vsHistoryDetail));
|
const detail = await this.cacheDetail(id, ()=>this.splatnet.getBattleDetail(id).then((r)=>r.vsHistoryDetail));
|
||||||
const metadata = await this.getBattleMetaById(id);
|
const metadata = await this.getBattleMetaById(id, detail.vsMode.mode);
|
||||||
const game = {
|
const game = {
|
||||||
...metadata,
|
...metadata,
|
||||||
detail
|
detail
|
||||||
|
|||||||
Reference in New Issue
Block a user