スクリプトの利用は、自己責任でお願いします。
雀魂の部屋別の戦績を取得するスクリプトです。開発者ツールで実行できます。
牌譜屋にないデータ(銅の間と銀の間での戦績や、被ツモ率、横移動率)の確認が可能です。1
window.to_stats = (res, is_recent) => {
const room_names = "銅, 銀, 金, 玉, 王, 王".split(", ");
const rule_names = "一, 東, 南, CPU, 一".split(", ");
const stats = [];
const types = mjcore.E_Round_Result;
const all_types = Object.values(types).filter(Number.isInteger);
const rank_stat = res.detail_data.rank_statistic;
const st_name = is_recent ? "month_statistic" : "total_statistic";
if (is_recent) {
stats.since = new Date(rank_stat.month_refresh_time * 1000);
}
rank_stat[st_name].level_data_list.map(RankLevelData =>
RankLevelData.statistic.game_mode.map(({
mode,
round_end,
fly_count,
game_final_position,
game_count_sum,
ming_count_sum,
liqi_count_sum,
xun_count_sum,
dadian_sum,
}) => {
const sum = (..._types) => round_end
.filter(r => _types.includes(r.type))
.map(r => r.sum)
.reduce((p, c) => p + c, 0);
const rounds = sum(...all_types);
const hora_sum = sum(types.zimo, types.rong);
const rank = RankLevelData.rank_level - 1;
return {
_sort_index: rank * 2 + mode,
is3: mode >= 10,
games: game_count_sum,
room_name: room_names[rank] + rule_names[mode % 10],
heichaku: game_final_position.reduce((p, c, i) => p + c * (i + 1)) / game_count_sum,
first: game_final_position[0] / game_count_sum,
second: game_final_position[1] / game_count_sum,
third: game_final_position[2] / game_count_sum,
forth: game_final_position[3] / game_count_sum || 0,
hora: hora_sum / rounds,
hoju: sum(types.fangchong) / rounds,
tsumo: sum(types.zimo) / hora_sum || 0,
furo: ming_count_sum / rounds,
riichi: liqi_count_sum / rounds,
tobi: fly_count / game_count_sum,
hitsumo: sum(types.beizimo) / rounds,
ryukyoku: sum(types.liuju) / rounds,
yokoido: sum(types.shaoji) / rounds,
junsu: xun_count_sum / hora_sum || 0,
daten: dadian_sum / hora_sum || 0,
};
})
).forEach(stat => stats.push(...stat));
return stats.sort((a, b) => a._sort_index < b._sort_index ? -1 : 1);
};
window.show_stats = (stats, is3 = false) => {
const chart_colors = [
"hwb(134 36% 30%)",
"hwb(188 29% 23%)",
"hwb(208 62% 46%)",
"hwb(354 41% 9%)",
];
const chart_length = 20;
if (stats.since) {
console.log("since", stats.since.toLocaleString("ja-JP"));
}
for (const st of stats) {
if (st.is3 === !is3) continue;
const stat_values = Object.entries({
"": `${st.games}戦`.padStart(6, " "),
和: st.hora,
放: st.hoju,
被: st.hitsumo,
流: st.ryukyoku,
横: st.yokoido,
自: st.tsumo,
副: st.furo,
立: st.riichi,
着: st.heichaku.toFixed(2),
// 飛: st.tobi,
// 巡: st.junsu.toFixed(1).padStart(4, " "),
// 打: st.daten.toFixed(0).padStart(4, " "),
}).map(([k, v]) => k + (
typeof v === "string" ? v : (v * 100).toFixed(1).padStart(4, " ")
));
const chart_ratios = st.is3
? [st.first, 0, st.second, st.third]
: [st.first, st.second, st.third, st.forth];
const chart_labels = chart_ratios.map(r =>
`${Math.round(r * 100) || ""}`
);
const chart_styles = chart_ratios.map((r, i) => `
padding: 0 ${(r * chart_length - chart_labels[i].length / 2) / 2}em;
background-color: ${chart_colors[i]};
color: white;
line-height: 1.5;
`);
console.log(`${st.room_name} %c${chart_labels.join("%c")}%c ${stat_values.join(" ")}`, ...chart_styles, "");
}
};
window.get_stats = (account_id = 0, is3 = false, is_recent = false) => {
account_id ||= GameMgr.Inst.account_id;
const zone_icons = "Ⓒ, Ⓙ, Ⓔ".split(", ");
const verified_icons = ", 🐾, 𝙋".split(", ");
const rank_names = "初, 士, 傑, 豪, 聖, 魂, 魂".split(", ");
const max_scores = [20, 80, 200, 600, 800, 1000, 1200, 1400, 2000, 2800, 3200, 3600, 4000, 6000, 9000];
const zone = zone_icons[game.Tools.get_zone_id(account_id) - 1];
const rule = is3 ? "三麻" : "四麻";
app.NetAgent.sendReq2Lobby("Lobby", "fetchAccountInfo", {account_id}, (err, res) => {
if (err || res.error) return;
const verified = verified_icons[res.account.verified];
const name = `${zone} ${res.account.nickname}${verified}`;
const level = is3 ? res.account.level3 : res.account.level;
const rank_id = `${level.id}`[2] - 1;
const rank_lv = (level.id % 100) - 1;
const rank = rank_names[rank_id] + (rank_lv + 1);
const konten = rank_id === rank_names.length - 1;
const score = level.score / (konten ? 100 : 1);
const max_score = max_scores[rank_id * 3 + rank_lv] || 20;
console.log(`%c${name}%c ${rule} ${rank} ${score}/${max_score}`, "font-size: 1.3em;", "");
app.NetAgent.sendReq2Lobby("Lobby", "fetchAccountStatisticInfo", {account_id}, (_err, _res) => {
if (_err || _res.error) return;
show_stats(to_stats(_res, is_recent), is3);
});
});
};
get_stats();
// get_stats(0, true); // 三人麻雀の場合
-
ただし、流局率と平均打点が、牌譜屋の値と異なります。 ↩