Files
Mortal-Copied/log-viewer/files/js/archive_player.js
e2hang b7a7d7404a
Some checks failed
deploy-docs / build (push) Has been cancelled
build-libriichi / build (push) Has been cancelled
Mortal
2025-10-07 20:30:03 +08:00

533 lines
14 KiB
JavaScript

// Generated by CoffeeScript 1.6.3
var BAKAZE_TO_STR, TSUPAIS, TSUPAI_TO_IMAGE_NAME, cloneBoard, comparePais, currentActionId, currentKyokuId, currentViewpoint, deleteTehai, dumpBoard, getCurrentKyoku, goBack, goNext, initPlayers, kyokus, loadAction, paiToImageUrl, parsePai, playerInfos, removeRed, renderAction, renderCurrentAction, renderHo, renderPai, renderPais, ripai, sortPais, _base, _base1;
window.console || (window.console = {});
(_base = window.console).log || (_base.log = function() {});
(_base1 = window.console).error || (_base1.error = function() {});
TSUPAIS = [null, "E", "S", "W", "N", "P", "F", "C"];
TSUPAI_TO_IMAGE_NAME = {
"E": "ji_e",
"S": "ji_s",
"W": "ji_w",
"N": "ji_n",
"P": "no",
"F": "ji_h",
"C": "ji_c"
};
BAKAZE_TO_STR = {
"E": "東",
"S": "南",
"W": "西",
"N": "北"
};
kyokus = [];
currentKyokuId = 0;
currentActionId = 0;
currentViewpoint = 0;
playerInfos = [{}, {}, {}, {}];
parsePai = function(pai) {
if (pai.match(/^([1-9])(.)(r)?$/)) {
return {
type: RegExp.$2,
number: parseInt(RegExp.$1),
red: RegExp.$3 ? true : false
};
} else {
return {
type: "t",
number: TSUPAIS.indexOf(pai),
red: false
};
}
};
comparePais = function(lhs, rhs) {
var lhsRep, parsedLhs, parsedRhs, rhsRep;
parsedLhs = parsePai(lhs);
lhsRep = parsedLhs.type + parsedLhs.number + (parsedLhs.red ? "1" : "0");
parsedRhs = parsePai(rhs);
rhsRep = parsedRhs.type + parsedRhs.number + (parsedRhs.red ? "1" : "0");
if (lhsRep < rhsRep) {
return -1;
} else if (lhsRep > rhsRep) {
return 1;
} else {
return 0;
}
};
sortPais = function(pais) {
return pais.sort(comparePais);
};
paiToImageUrl = function(pai, pose) {
var ext, name, parsedPai, redSuffix;
if (pai) {
if (pai === "?") {
name = "bk";
ext = "gif";
} else {
parsedPai = parsePai(pai);
if (parsedPai.type === "t") {
name = TSUPAI_TO_IMAGE_NAME[pai];
} else {
redSuffix = parsedPai.red ? "r" : "";
name = "" + parsedPai.type + "s" + parsedPai.number + redSuffix;
}
ext = parsedPai.red ? "png" : "gif";
}
if (pose === void 0) {
pose = 1;
}
return "files/images/p_" + name + "_" + pose + "." + ext;
} else {
return "files/images/blank.png";
}
};
cloneBoard = function(board) {
var bk, bv, newBoard, newPlayer, pk, player, pv, _i, _len;
newBoard = {};
for (bk in board) {
bv = board[bk];
if (bk === "players") {
newBoard[bk] = [];
for (_i = 0, _len = bv.length; _i < _len; _i++) {
player = bv[_i];
newPlayer = {};
for (pk in player) {
pv = player[pk];
newPlayer[pk] = pv;
}
newBoard[bk].push(newPlayer);
}
} else {
newBoard[bk] = bv;
}
}
return newBoard;
};
initPlayers = function(board) {
var player, _i, _len, _ref, _results;
_ref = board.players;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
player = _ref[_i];
player.tehais = null;
player.furos = [];
player.ho = [];
player.reach = false;
_results.push(player.reachHoIndex = null);
}
return _results;
};
removeRed = function(pai) {
if (!pai) {
return null;
}
if (pai.match(/^(.+)r$/)) {
return RegExp.$1;
} else {
return pai;
}
};
loadAction = function(action) {
var actorPlayer, board, furos, i, kyoku, pai, prevBoard, targetPlayer, _i, _j, _k, _l, _len, _len1, _m, _n, _o, _ref, _ref1, _ref2;
if (kyokus.length > 0) {
kyoku = kyokus[kyokus.length - 1];
board = cloneBoard(kyoku.actions[kyoku.actions.length - 1].board);
} else {
kyoku = null;
board = null;
}
if (board && ("actor" in action)) {
actorPlayer = board.players[action.actor];
} else {
actorPlayer = null;
}
if (board && ("target" in action)) {
targetPlayer = board.players[action.target];
} else {
targetPlayer = null;
}
switch (action.type) {
case "start_game":
for (i = _i = 0; _i < 4; i = ++_i) {
playerInfos[i].name = action.names[i];
}
break;
case "end_game":
null;
break;
case "start_kyoku":
kyoku = {
actions: [],
bakaze: action.bakaze,
kyokuNum: action.kyoku,
honba: action.honba
};
kyokus.push(kyoku);
prevBoard = board;
board = {
players: [{}, {}, {}, {}],
doraMarkers: [action.dora_marker]
};
initPlayers(board);
for (i = _j = 0; _j < 4; i = ++_j) {
board.players[i].tehais = action.tehais[i];
if (prevBoard) {
board.players[i].score = prevBoard.players[i].score;
} else {
board.players[i].score = 25000;
}
}
break;
case "end_kyoku":
null;
break;
case "tsumo":
actorPlayer.tehais = actorPlayer.tehais.concat([action.pai]);
break;
case "dahai":
deleteTehai(actorPlayer, action.pai);
actorPlayer.ho = actorPlayer.ho.concat([action.pai]);
break;
case "reach":
actorPlayer.reachHoIndex = actorPlayer.ho.length;
break;
case "reach_accepted":
actorPlayer.reach = true;
break;
case "chi":
case "pon":
case "daiminkan":
targetPlayer.ho = targetPlayer.ho.slice(0, targetPlayer.ho.length - 1);
_ref = action.consumed;
for (_k = 0, _len = _ref.length; _k < _len; _k++) {
pai = _ref[_k];
deleteTehai(actorPlayer, pai);
}
actorPlayer.furos = actorPlayer.furos.concat([
{
type: action.type,
taken: action.pai,
consumed: action.consumed,
target: action.target
}
]);
break;
case "ankan":
_ref1 = action.consumed;
for (_l = 0, _len1 = _ref1.length; _l < _len1; _l++) {
pai = _ref1[_l];
deleteTehai(actorPlayer, pai);
}
actorPlayer.furos = actorPlayer.furos.concat([
{
type: action.type,
consumed: action.consumed
}
]);
break;
case "kakan":
deleteTehai(actorPlayer, action.pai);
actorPlayer.furos = actorPlayer.furos.concat([]);
furos = actorPlayer.furos;
for (i = _m = 0, _ref2 = furos.length; 0 <= _ref2 ? _m < _ref2 : _m > _ref2; i = 0 <= _ref2 ? ++_m : --_m) {
if (furos[i].type === "pon" && removeRed(furos[i].taken) === removeRed(action.pai)) {
furos[i] = {
type: "kakan",
taken: action.pai,
consumed: action.consumed,
target: furos[i].target
};
}
}
break;
case "hora":
case "ryukyoku":
null;
break;
case "dora":
board.doraMarkers = board.doraMarkers.concat([action.dora_marker]);
break;
case "error":
null;
break;
default:
throw "unknown action: " + action.type;
}
if (action.scores) {
for (i = _n = 0; _n < 4; i = ++_n) {
board.players[i].score = action.scores[i];
}
}
if (kyoku) {
for (i = _o = 0; _o < 4; i = ++_o) {
if (action.actor !== void 0 && i !== action.actor) {
ripai(board.players[i]);
}
}
action.board = board;
return kyoku.actions.push(action);
}
};
deleteTehai = function(player, pai) {
var idx;
player.tehais = player.tehais.concat([]);
idx = player.tehais.lastIndexOf(pai);
if (idx < 0) {
idx = player.tehais.lastIndexOf("?");
}
if (idx < 0) {
throw "pai not in tehai";
}
return player.tehais[idx] = null;
};
ripai = function(player) {
var pai;
if (player.tehais) {
player.tehais = (function() {
var _i, _len, _ref, _results;
_ref = player.tehais;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
pai = _ref[_i];
if (pai) {
_results.push(pai);
}
}
return _results;
})();
return sortPais(player.tehais);
}
};
dumpBoard = function(board) {
var consumedStr, furo, hoStr, i, player, tehaisStr, _i, _j, _len, _ref, _results;
_results = [];
for (i = _i = 0; _i < 4; i = ++_i) {
player = board.players[i];
if (player.tehais) {
tehaisStr = player.tehais.join(" ");
_ref = player.furos;
for (_j = 0, _len = _ref.length; _j < _len; _j++) {
furo = _ref[_j];
consumedStr = furo.consumed.join(" ");
tehaisStr += " [" + furo.taken + "/" + consumedStr + "]";
}
console.log("[" + i + "] tehais: " + tehaisStr);
}
if (player.ho) {
hoStr = player.ho.join(" ");
_results.push(console.log("[" + i + "] ho: " + hoStr));
} else {
_results.push(void 0);
}
}
return _results;
};
renderPai = function(pai, view, pose) {
if (pose === void 0) {
pose = 1;
}
view.attr("src", paiToImageUrl(pai, pose));
switch (pose) {
case 1:
view.addClass("pai");
return view.removeClass("laid-pai");
case 3:
view.addClass("laid-pai");
return view.removeClass("pai");
default:
throw "unknown pose";
}
};
renderPais = function(pais, view, poses) {
var i, _i, _ref, _results;
pais || (pais = []);
poses || (poses = []);
view.resize(pais.length);
_results = [];
for (i = _i = 0, _ref = pais.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
_results.push(renderPai(pais[i], view.at(i), poses[i]));
}
return _results;
};
renderHo = function(player, offset, pais, view) {
var i, reachIndex, _i, _ref, _results;
if (player.reachHoIndex === null) {
reachIndex = null;
} else {
reachIndex = player.reachHoIndex - offset;
}
view.resize(pais.length);
_results = [];
for (i = _i = 0, _ref = pais.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
_results.push(renderPai(pais[i], view.at(i), i === reachIndex ? 3 : 1));
}
return _results;
};
renderAction = function(action) {
var dir, displayAction, furo, furoView, ho, i, infoView, j, k, kyoku, laidPos, pais, player, poses, v, view, wanpais, _i, _j, _ref, _ref1, _ref2, _ref3;
displayAction = {};
for (k in action) {
v = action[k];
if (k !== "board" && k !== "logs") {
displayAction[k] = v;
}
}
$("#action-label").text(JSON.stringify(displayAction, null, 2));
$("#log-label").text((action.logs && action.logs[currentViewpoint]) || "");
kyoku = getCurrentKyoku();
for (i = _i = 0; _i < 4; i = ++_i) {
player = action.board.players[i];
view = Dytem.players.at((i - currentViewpoint + 4) % 4);
infoView = Dytem.playerInfos.at(i);
infoView.score.text(player.score);
infoView.viewpoint.text(i === currentViewpoint ? "+" : "");
if (!player.tehais) {
renderPais([], view.tehais);
view.tsumoPai.hide();
} else if (player.tehais.length % 3 === 2) {
renderPais(player.tehais.slice(0, player.tehais.length - 1), view.tehais);
view.tsumoPai.show();
renderPai(player.tehais[player.tehais.length - 1], view.tsumoPai);
} else {
renderPais(player.tehais, view.tehais);
view.tsumoPai.hide();
}
ho = player.ho || [];
renderHo(player, 0, ho.slice(0, 6), view.hoRows.at(0).pais);
renderHo(player, 6, ho.slice(6, 12), view.hoRows.at(1).pais);
renderHo(player, 12, ho.slice(12), view.hoRows.at(2).pais);
view.furos.resize(player.furos.length);
if (player.furos) {
j = player.furos.length - 1;
while (j >= 0) {
furo = player.furos[j];
furoView = view.furos.at(player.furos.length - 1 - j);
if (furo.type === "ankan") {
pais = ["?"].concat(furo.consumed.slice(0, 2)).concat(["?"]);
poses = [1, 1, 1, 1];
} else {
dir = (4 + furo.target - i) % 4;
if ((_ref = furo.type) === "daiminkan" || _ref === "kakan") {
laidPos = [null, 3, 1, 0][dir];
} else {
laidPos = [null, 2, 1, 0][dir];
}
pais = furo.consumed.concat([]);
poses = [1, 1, 1];
[].splice.apply(pais, [laidPos, laidPos - laidPos].concat(_ref1 = [furo.taken])), _ref1;
[].splice.apply(poses, [laidPos, laidPos - laidPos].concat(_ref2 = [3])), _ref2;
}
renderPais(pais, furoView.pais, poses);
--j;
}
}
}
wanpais = ["?", "?", "?", "?", "?", "?"];
for (i = _j = 0, _ref3 = action.board.doraMarkers.length; 0 <= _ref3 ? _j < _ref3 : _j > _ref3; i = 0 <= _ref3 ? ++_j : --_j) {
wanpais[i + 2] = action.board.doraMarkers[i];
}
return renderPais(wanpais, Dytem.wanpais);
};
getCurrentKyoku = function() {
return kyokus[currentKyokuId];
};
renderCurrentAction = function() {
return renderAction(getCurrentKyoku().actions[currentActionId]);
};
goNext = function() {
if (currentActionId === getCurrentKyoku().actions.length - 1) {
return;
}
++currentActionId;
$("#action-id-label").val(currentActionId);
return renderCurrentAction();
};
goBack = function() {
if (currentActionId === 0) {
return;
}
--currentActionId;
$("#action-id-label").val(currentActionId);
return renderCurrentAction();
};
$(function() {
var action, bakazeStr, honba, i, j, kyokuNum, label, playerInfoView, playerView, _i, _j, _k, _l, _len, _ref;
$(window).bind("mousewheel", function(e) {
e.preventDefault();
if (e.originalEvent.wheelDelta < 0) {
return goNext();
} else if (e.originalEvent.wheelDelta > 0) {
return goBack();
}
});
$("#prev-button").click(goBack);
$("#next-button").click(goNext);
$("#go-button").click(function() {
currentActionId = parseInt($("#action-id-label").val());
return renderCurrentAction();
});
$("#kyokuSelector").change(function() {
currentKyokuId = parseInt($("#kyokuSelector").val());
currentActionId = 0;
return renderCurrentAction();
});
$("#viewpoint-button").click(function() {
currentViewpoint = (currentViewpoint + 1) % 4;
return renderCurrentAction();
});
for (_i = 0, _len = allActions.length; _i < _len; _i++) {
action = allActions[_i];
loadAction(action);
}
Dytem.init();
for (i = _j = 0; _j < 4; i = ++_j) {
playerView = Dytem.players.append();
playerView.addClass("player-" + i);
for (j = _k = 0; _k < 3; j = ++_k) {
playerView.hoRows.append();
}
playerInfoView = Dytem.playerInfos.append();
playerInfoView.index.text(i);
playerInfoView.name.text(playerInfos[i].name);
}
for (i = _l = 0, _ref = kyokus.length; 0 <= _ref ? _l < _ref : _l > _ref; i = 0 <= _ref ? ++_l : --_l) {
bakazeStr = BAKAZE_TO_STR[kyokus[i].bakaze];
honba = kyokus[i].honba;
kyokuNum = kyokus[i].kyokuNum;
label = "" + bakazeStr + kyokuNum + "局 " + honba + "本場";
$("#kyokuSelector").get(0).options[i] = new Option(label, i);
}
console.log("loaded");
return renderCurrentAction();
});