You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
543 lines
14 KiB
543 lines
14 KiB
import { computed } from "vue";
|
|
|
|
/////////////////////////////////////////
|
|
// Helper
|
|
/////////////////////////////////////////
|
|
|
|
function setPoints(page, set){
|
|
let points = [0, 0]; // need to get updated for more player
|
|
let ret;
|
|
const m = page.game.sets.length-1;
|
|
for (const i in page.game.sets) {
|
|
const set = page.game.sets[i];
|
|
const points = legPoints(page, set, set.legs[set.legs.length-1]);
|
|
const winner = getWinner(points, page.legs);
|
|
if (winner > -1)
|
|
points[winner] += 1;
|
|
else
|
|
return points;
|
|
|
|
if (set == set){
|
|
return points;
|
|
}
|
|
}
|
|
return points;
|
|
}
|
|
|
|
function legPoints(page, set, leg){
|
|
let points = [0, 0]; // need to get updated for more player
|
|
let ret;
|
|
const m = set.legs.length-1;
|
|
for (const i in set.legs) {
|
|
const l = set.legs[i];
|
|
if (l.visits[l.visits.length-1].toGo === undefined) {
|
|
return points;
|
|
}
|
|
if (l.visits[l.visits.length-1].toGo[0] == 0)
|
|
points[0] += 1;
|
|
else if (l.visits[l.visits.length-1].toGo[1] == 0)
|
|
points[1] += 1;
|
|
if (l == leg){
|
|
return points;
|
|
}
|
|
}
|
|
return points;
|
|
}
|
|
|
|
function newPlayerStats(player) {
|
|
return {
|
|
player: player.uuid,
|
|
average: [0, 0],
|
|
first9: [0, 0],
|
|
checkouts: [0, 0],
|
|
checkins: [0, 0],
|
|
checkinPoints: [],
|
|
checkoutPoints: [],
|
|
"60+": 0,
|
|
"100+": 0,
|
|
"140+": 0,
|
|
"180": 0
|
|
};
|
|
}
|
|
|
|
function addNewSetStats(stats, scorers) {
|
|
stats["sets"].push(newStats(scorers));
|
|
stats["sets"][0]["legs"] = [];
|
|
return stats;
|
|
}
|
|
|
|
function addNewLegStats(stats, scorers) {
|
|
stats["sets"].at(-1)["legs"].push(newStats(scorers));
|
|
return stats;
|
|
}
|
|
|
|
function newStats(scorers) {
|
|
const stats = {
|
|
stats: []
|
|
}
|
|
scorers.forEach((scorer) => {
|
|
scorer.member.forEach((player) => {
|
|
const n = newPlayerStats(player);
|
|
stats.stats.push(n);
|
|
});
|
|
});
|
|
return stats;
|
|
}
|
|
|
|
function newVisit(playerUUID, round) {
|
|
return {
|
|
player: playerUUID,
|
|
throws: [],
|
|
visit: round,
|
|
checkoutTries: 0,
|
|
checkinTries: 0,
|
|
numDarts: 0,
|
|
}
|
|
}
|
|
|
|
function clearLastVisit(page){
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
const visit = leg.visits[leg.visits.length-1];
|
|
const ret = visit["throws"];
|
|
visit["throws"] = [];
|
|
visit["checkoutTries"] = 0;
|
|
visit["checkinTries"] = 0;
|
|
visit["numDarts"] = 0;
|
|
delete visit["sum"];
|
|
delete visit["toGo"];
|
|
return ret;
|
|
}
|
|
|
|
function getWinner(points, mode) {
|
|
const sorted = [...points].map((e,i) => [e,i]).sort((a, b) => b[0] - a[0]);
|
|
const k = points.length;
|
|
const sum = points.reduce((a,c) => a+c, 0);
|
|
if (sum < mode && sorted[0][0] <= mode/k){
|
|
// not over yet
|
|
return -1;
|
|
}
|
|
if (sorted[0][0] == sorted[1][0]){
|
|
// Draw
|
|
return -2;
|
|
}
|
|
// winner id
|
|
return sorted[0][1];
|
|
}
|
|
|
|
function addNewSet(page){
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const k = player2scorer(page)[set.legs[0].visits[0].player];
|
|
const p = page.scorers[(k+1)%2].member[0].uuid;
|
|
page.game.sets.push({
|
|
// points: [...points],
|
|
legs: [{
|
|
points: Array(2).fill(0),
|
|
visits: [newVisit(p, 1)]
|
|
}]
|
|
});
|
|
}
|
|
|
|
function addNewLeg(page){
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
const k = player2scorer(page)[leg.visits[0].player];
|
|
console.log(k, k+1);
|
|
|
|
const p = page.scorers[(k+1)%2].member[0].uuid;
|
|
page.game.sets[page.game.sets.length-1].legs.push({
|
|
// points: [...points],
|
|
visits: [newVisit(p, 1)]
|
|
});
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// Exports
|
|
/////////////////////////////////////////
|
|
|
|
export function playerFromUUID(uuid, players){
|
|
return players[players.map((p) => p.uuid).indexOf(uuid)];
|
|
}
|
|
|
|
export const getFinalWinner = (page) => {
|
|
const points = setPoints(page, page.sets[page.sets.length-1]);
|
|
return getWinner(points, page.sets);
|
|
};
|
|
|
|
export function initStats(page) {
|
|
const stats = newStats(page.scorers);
|
|
stats.sets = [];
|
|
addNewSetStats(stats, page.scorers);
|
|
addNewLegStats(stats, page.scorers);
|
|
page.stats = stats;
|
|
}
|
|
|
|
export function initGame(page) {
|
|
page.game = {
|
|
sets: [{
|
|
points: new Array(2).fill(0),
|
|
legs: [{
|
|
points: new Array(2).fill(0),
|
|
visits: [newVisit(page.scorers[0].member[0].uuid, 1)]
|
|
}]
|
|
}]
|
|
}
|
|
}
|
|
|
|
function updateStats(page, visit){
|
|
const playerUUIDs = allPlayers(page).map((p) => p.uuid);
|
|
const k = playerUUIDs.indexOf(visit.player);
|
|
|
|
const todos = [page.stats["stats"][k]];
|
|
todos.push(page.stats["sets"].at(-1)["stats"][k]);
|
|
todos.push(page.stats["sets"].at(-1)["legs"].at(-1)["stats"][k]);
|
|
|
|
todos.forEach((value, i) => {
|
|
todos[i]["average"][0] += visit["sum"];
|
|
todos[i]["average"][1] += visit["numDarts"];
|
|
if (visit["visit"] < 4) {
|
|
todos[i]["first9"][0] += visit["sum"];
|
|
todos[i]["first9"][1] += visit["numDarts"];
|
|
}
|
|
if (visit["toGo"][k] == 0) {
|
|
todos[i]["checkouts"][0] += 1;
|
|
todos[i]["checkoutPoints"].push(visit["sum"]);
|
|
}
|
|
if (visit["checkinTries"] != 0 && visit["sum"] != 0) {
|
|
todos[i]["checkins"][0] += 1;
|
|
todos[i]["checkinPoints"].push(visit["sum"]);
|
|
}
|
|
todos[i]["checkouts"][1] += visit["checkoutTries"];
|
|
todos[i]["checkins"][1] += visit["checkinTries"];
|
|
if (visit["sum"] == 180) {
|
|
todos[i]["180"] += 1;
|
|
} else if (visit["sum"] >= 140) {
|
|
todos[i]["140+"] += 1;
|
|
} else if (visit["sum"] >= 100) {
|
|
todos[i]["100+"] += 1;
|
|
} else if (visit["sum"] >= 60) {
|
|
todos[i]["60+"] += 1;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getNextPlayer(page, visit) {
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
|
|
const offset = 1*(leg.visits[0].player == page.scorers[0].member[0].uuid);
|
|
const order = [];
|
|
for (let index = 0; index < page.scorers[0].member.length; index++) {
|
|
order.push(page.scorers[1-offset].member[index].uuid);
|
|
order.push(page.scorers[offset].member[index].uuid);
|
|
}
|
|
const nextid = (order.indexOf(visit.player)+1);
|
|
return [order[nextid%order.length], (nextid == order.length)];
|
|
}
|
|
|
|
export function player2scorer(page){
|
|
return Object.entries(page.scorers).reduce((result, [scorersId, scorer]) => {
|
|
// Use the map method to create an array of key-value pairs for each "member"
|
|
scorer.member.forEach(player => {
|
|
result[player.uuid] = parseInt(scorersId);
|
|
});
|
|
return result;
|
|
}, {});
|
|
}
|
|
|
|
export function allPlayers(page){
|
|
return Object.entries(page.scorers).reduce((result, [scorersId, scorer]) => {
|
|
return result.concat(scorer.member);
|
|
}, []);
|
|
}
|
|
|
|
export const formatDate = (d) => {
|
|
return `${d.getFullYear()}-${(d.getMonth()+1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
|
|
};
|
|
|
|
|
|
export function recalcStats(page){
|
|
// const set = page.game.sets[page.game.sets.length-1];
|
|
// const leg = set.legs[set.legs.length-1];
|
|
// const visit = leg.visits[leg.visits.length-1];
|
|
initStats(page);
|
|
const lastset = page.game["sets"].length-1;
|
|
page.game["sets"].forEach((set, i) => {
|
|
const lastleg = set.legs.length-1;
|
|
set.legs.forEach((leg, j) => {
|
|
const lastvisit = leg["visits"].length-1;
|
|
leg.visits.forEach((visit, k) => {
|
|
if (!(k == lastvisit && j == lastleg && i == lastset)) {
|
|
updateStats(page, visit);
|
|
}
|
|
if (k == lastvisit && j != lastleg) {
|
|
addNewLegStats(page.stats, page.scorers);
|
|
}
|
|
});
|
|
if (j == lastleg && i != lastset) {
|
|
addNewSetStats(page.stats, page.scorers);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
export function removeLastVisit(page){
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
// const visit = leg.visits[leg.visits.length-1];
|
|
|
|
// delete last visit.
|
|
leg["visits"].pop();
|
|
if (leg["visits"].length == 0){
|
|
set["legs"].pop();
|
|
if (set["legs"].length == 0){
|
|
page.game["sets"].pop();
|
|
if (page.game["sets"].length == 0){
|
|
initGame(page);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
// clearLastVisit
|
|
const ret = clearLastVisit(page);
|
|
recalcStats(page);
|
|
return ret;
|
|
}
|
|
|
|
export function storeVisit(page, throws, sum, numDarts, outTries, inTries=0) {
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
const visit = leg.visits[leg.visits.length-1];
|
|
|
|
visit["numDarts"] = numDarts;
|
|
visit["throws"] = throws;
|
|
visit["checkoutTries"] = outTries;
|
|
visit["checkinTries"] = inTries;
|
|
visit["sum"] = sum
|
|
|
|
const k = player2scorer(page)[visit["player"]];
|
|
let toGo;
|
|
if (leg["visits"].length-2 < 0) {
|
|
toGo = Array(2).fill(page.modus);
|
|
} else {
|
|
toGo = [...leg["visits"][leg["visits"].length-2]["toGo"]];
|
|
}
|
|
const rest = toGo[k] - visit["sum"];
|
|
if (rest < 0 || (page.out == "Double" && rest == 1)) {
|
|
visit["sum"] = 0;
|
|
} else {
|
|
toGo[k] = rest;
|
|
}
|
|
visit["toGo"] = toGo;
|
|
if (page.in != "Straight" && page.modus == toGo[k] && visit["sum"] == 0) {
|
|
visit["checkinTries"] = 3;
|
|
}
|
|
// update stats
|
|
updateStats(page, visit);
|
|
|
|
let update = [];
|
|
if (rest != 0) {
|
|
// Normal case...next players turn
|
|
const [nextPlayer, newRound] = getNextPlayer(page, visit);
|
|
const nVisit = newVisit(nextPlayer, visit["visit"]+1*newRound);
|
|
leg.visits.push(nVisit);
|
|
}
|
|
else {
|
|
// rest == 0 leg finished
|
|
const newlegp = legPoints(page, set, leg);
|
|
let winner = getWinner(newlegp, page.legs);
|
|
if (winner == -1) {
|
|
// new Leg
|
|
addNewLeg(page);
|
|
addNewLegStats(page.stats, page.scorers);
|
|
} else {
|
|
// new set?
|
|
const newsetp = setPoints(page, set);
|
|
winner = getWinner(newsetp, page.sets);
|
|
if (winner == -1) {
|
|
// new Set
|
|
addNewSet(page);
|
|
addNewSetStats(page.stats, page.scorers);
|
|
addNewLegStats(page.stats, page.scorers);
|
|
} else {
|
|
// ask for continue or game over
|
|
if (winner == -2) {
|
|
page.stats["winner"] = "DRAW";
|
|
} else {
|
|
page.stats["winner"] = visit["player"];
|
|
}
|
|
|
|
page.enddate = formatDate(new Date(Date.now()));
|
|
return [newsetp, newlegp];
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function endGame(page){
|
|
// const set = page.game.sets[page.game.sets.length-1];
|
|
// const leg = set.legs[set.legs.length-1];
|
|
// const visit = leg.visits[leg.visits.length-1];
|
|
// const winner = getWinner(newsetp, page.sets);
|
|
// set["points"] = newsetp;
|
|
// leg["points"] = newlegp;
|
|
}
|
|
|
|
export function extension(page){
|
|
const set = page.game.sets[page.game.sets.length-1];
|
|
const leg = set.legs[set.legs.length-1];
|
|
page.enddate = undefined;
|
|
// leg["points"] = newlegp;
|
|
// new Leg
|
|
addNewLeg(page);
|
|
addNewLegStats(page.stats, page.scorers);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// GameProps
|
|
/////////////////////////////////////////
|
|
|
|
export function getGameProps(page, current_set, current_leg) {
|
|
const ret = {};
|
|
|
|
if (current_set === undefined) {
|
|
current_set = computed(() => {
|
|
if (page.game != undefined) {
|
|
return page.game.sets[page.game.sets.length - 1]
|
|
}
|
|
return undefined;
|
|
});
|
|
}
|
|
ret.current_set = current_set;
|
|
|
|
|
|
if (current_leg === undefined) {
|
|
current_leg = computed(() => {
|
|
if (current_set.value != undefined) {
|
|
return current_set.value.legs[current_set.value.legs.length - 1]
|
|
}
|
|
return undefined;
|
|
});
|
|
}
|
|
ret.current_leg = current_leg;
|
|
|
|
const current_toGo = computed(() => {
|
|
if (current_leg.value != undefined) {
|
|
if (current_leg.value.visits.length < 2) {
|
|
return [page.modus, page.modus]
|
|
} else {
|
|
const end = current_leg.value.visits[current_leg.value.visits.length - 1].toGo;
|
|
if (end) return end;
|
|
return current_leg.value.visits[current_leg.value.visits.length - 2].toGo;
|
|
}
|
|
}
|
|
return [0, 0]; // need to get updated for more player
|
|
});
|
|
ret.current_toGo = current_toGo;
|
|
|
|
const current_set_points = computed(() => {
|
|
if (current_set.value != undefined) {
|
|
return setPoints(page, current_set.value);
|
|
}
|
|
return undefined;
|
|
});
|
|
ret.current_set_points = current_set_points;
|
|
|
|
const current_leg_points = computed(() => {
|
|
if (current_set.value != undefined || current_leg.value != undefined) {
|
|
return legPoints(page, current_set.value, current_leg.value);
|
|
}
|
|
return undefined;
|
|
});
|
|
ret.current_leg_points = current_leg_points;
|
|
|
|
const current_scorer_idx = computed(() => {
|
|
if (current_leg.value != undefined) {
|
|
const len = current_leg.value.visits.length;
|
|
return player2scorer(page)[current_leg.value.visits[len - 1].player];
|
|
}
|
|
return undefined;
|
|
});
|
|
ret.current_scorer_idx = current_scorer_idx;
|
|
|
|
const breaks = computed(() => {
|
|
let b = [0,0];
|
|
for (const j in page.game.sets) {
|
|
const set = page.game.sets[j];
|
|
for (const i in set.legs) {
|
|
const l = set.legs[i];
|
|
if (l.visits[l.visits.length-1].toGo === undefined) {
|
|
return b;
|
|
}
|
|
if (l.visits[l.visits.length-1].toGo[0] == 0 && i%2 == 1)
|
|
b[0] += 1;
|
|
else if (l.visits[l.visits.length-1].toGo[1] == 0 && i%2 == 0)
|
|
b[1] += 1;
|
|
}
|
|
}
|
|
return b;
|
|
});
|
|
ret.breaks = breaks;
|
|
|
|
const getVal = (tr) => {
|
|
const val = tr.trim();
|
|
if (val == "") {
|
|
return 0;
|
|
}
|
|
if (val == "SB") {
|
|
return 25;
|
|
}
|
|
if (val == "DB") {
|
|
return 50;
|
|
}
|
|
if (val[0] == "S" || val[0] == "O" || val[0] == "I") {
|
|
return parseFloat(val.substring(1));
|
|
}
|
|
if (val[0] == "D") {
|
|
return 2 * parseFloat(val.substring(1));
|
|
}
|
|
if (val[0] == "T") {
|
|
return 3 * parseFloat(val.substring(1));
|
|
}
|
|
if (val[0] == "M") {
|
|
return 0;
|
|
} else {
|
|
// TODO: Check for Na
|
|
return parseFloat(val);
|
|
}
|
|
}
|
|
const verifySum = (sum) => {
|
|
if (sum > 180 || [179, 178, 176, 175, 173, 172, 169, 166, 163].indexOf(sum) > -1) {
|
|
return -1;
|
|
} else if (current_toGo.value[current_scorer_idx.value] - sum < 0) {
|
|
return -2;
|
|
} if (current_toGo.value[current_scorer_idx.value] - sum == 0) {
|
|
// bogey numbers
|
|
if (page.out == "Double" && (sum > 170 || [169, 168, 166, 165, 163, 162, 159].indexOf(sum) > -1)) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
} else if (current_toGo.value[current_scorer_idx.value] - sum <= 50) {
|
|
return 1;
|
|
} else if (page.in != "Straight" && current_toGo.value[current_scorer_idx.value] == page.modus && sum != 0) {
|
|
return 3;
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
const checkVisit = (throws) => {
|
|
const tr = throws.split(",");
|
|
let sum = 0;
|
|
tr.forEach((t, i) => {
|
|
sum += getVal(t);
|
|
});
|
|
const res = verifySum(sum);
|
|
return [res, sum];
|
|
}
|
|
ret.checkVisit = checkVisit;
|
|
|
|
return ret;
|
|
} |