return matches; }; // interface function FFA(numPlayers, grs, advs, opts) { if (!(this instanceof FFA)) { return new FFA(numPlayers, grs, advs, opts); } this.version = 1; this.advs = advs; this.limit = opts ? opts.limit | 0 : 0; this.numPlayers = numPlayers; Base.call(this, FFA, elimination(numPlayers, grs, advs, this.limit)); } FFA.prototype = Object.create(Base.prototype); FFA.parse = Base.parse.bind(null, FFA); FFA.invalid = invalid; FFA.idString = idString; FFA.prototype.unscorable = function (id, score, allowPast) { var invReason = Base.prototype.unscorable.call(this, id, score, allowPast); if (invReason !== null) { return invReason; } var adv = this.advs[id.r - 1] || 0; if (adv > 0 && score[adv] === score[adv - 1]) { return "scores must unambiguous decide who advances"; } if (!adv && this.limit > 0) { // number of groups in last round is the match number of the very last match // because of the ordering this always works!
if (invReason !== null) { console.error("invalid TieBreaker configuration: %dp from GroupStage results %j" , limit, gsResults); console.error("reason: ", invReason); } else { var res = resultsByGroup(gsResults); this.version = 1; this.posAry = posByGroup(res); this.oldRes = gsResults; this.limit = limit; Base.call(this, TieBreaker, createTbForGroups(this.posAry, limit)); } } TieBreaker.prototype = Object.create(Base.prototype); TieBreaker.parse = Base.parse.bind(null, TieBreaker); TieBreaker.invalid = invalid; TieBreaker.idString = idString; // given valid (gsResults, limit) do we actually need to tiebreak to pick top limit? TieBreaker.isNecessary = function (gsResults, limit) { var tb = new TieBreaker(gsResults, limit); return (tb.matches && tb.matches.length > 0); }; TieBreaker.prototype.unscorable = function (id, score, allowPast) { var invReason = Base.prototype.unscorable.call(this, id, score, allowPast); if (invReason !== null) { return invReason; } if ($.nub(score).length !== score.length) {