编码级别:初级
时长:5 分钟(
)
项目类型:使用自定义菜单实现自动化
目标
- 了解此解决方案的用途。
- 了解 Apps 脚本服务在
解决方案。
- 设置脚本。
- 运行脚本。
关于此解决方案
为最多 64 人或团队创建锦标赛组别。此解决方案创建了
表示单场淘汰赛的树形图。
工作原理
脚本会循环遍历玩家列表,并确定每轮游戏的次数。
括号里不需要的字词。脚本会设置 Bracket 工作表的格式,以创建
树形图,并将玩家的传递给第一轮。
Apps 脚本服务
此解决方案使用以下服务:
电子表格服务 - 获取
球员并为锦标赛绘制树状图。
前提条件
如需使用此示例,您需要满足以下前提条件:
- Google 账号(Google Workspace 账号可能
需要管理员批准)。
- 可以访问互联网的网络浏览器。
设置脚本
点击下方按钮,复制 Create a Tourname Backet(创建比赛括号)
电子表格示例。
复制
运行脚本
- 在复制的电子表格中,依次点击括号制作工具 > 创建
括号。您可能需要刷新页面才能看到此自定义菜单。
出现提示时,为脚本授权。
如果 OAuth 同意屏幕显示以下警告:“此应用未经验证”,
选择高级 > 以继续操作
前往“{Project Name}”(不安全)。
点击括号制作工具
> 再次创建括号。
请切换到 Bracket 标签页,查看锦标赛排行榜。
查看代码
如需查看此解决方案的 Apps 脚本代码,请点击
下面查看源代码:
查看源代码
Code.gs
// To learn how to use this script, refer to the documentation:
// https://developers.google.com/apps-script/samples/automations/bracket-maker
/*
Copyright 2022 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const RANGE_PLAYER1 = 'FirstPlayer';
const SHEET_PLAYERS = 'Players';
const SHEET_BRACKET = 'Bracket';
const CONNECTOR_WIDTH = 15;
/**
* Adds a custom menu item to run the script.
*/
function onOpen() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
ss.addMenu('Bracket maker',
[{name: 'Create bracket', functionName: 'createBracket'}]);
}
/**
* Creates the brackets based on the data provided on the players.
*/
function createBracket() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let rangePlayers = ss.getRangeByName(RANGE_PLAYER1);
let sheetControl = ss.getSheetByName(SHEET_PLAYERS);
let sheetResults = ss.getSheetByName(SHEET_BRACKET);
// Gets the players from column A. Assumes the entire column is filled.
rangePlayers = rangePlayers.offset(0, 0, sheetControl.getMaxRows() -
rangePlayers.getRowIndex() + 1, 1);
let players = rangePlayers.getValues();
// Figures out how many players there are by skipping the empty cells.
let numPlayers = 0;
for (let i = 0; i < players.length; i++) {
if (!players[i][0] || players[i][0].length == 0) {
break;
}
numPlayers++;
}
players = players.slice(0, numPlayers);
// Provides some error checking in case there are too many or too few players/teams.
if (numPlayers > 64) {
Browser.msgBox('Sorry, this script can only create brackets for 64 or fewer players.');
return; // Early exit
}
if (numPlayers < 3) {
Browser.msgBox('Sorry, you must have at least 3 players.');
return; // Early exit
}
// Clears the 'Bracket' sheet and all formatting.
sheetResults.clear();
let upperPower = Math.ceil(Math.log(numPlayers) / Math.log(2));
// Calculates the number that is a power of 2 and lower than numPlayers.
let countNodesUpperBound = Math.pow(2, upperPower);
// Calculates the number that is a power of 2 and higher than numPlayers.
let countNodesLowerBound = countNodesUpperBound / 2;
// Determines the number of nodes that will not show in the 1st level.
let countNodesHidden = numPlayers - countNodesLowerBound;
// Enters the players for the 1st round.
let currentPlayer = 0;
for (let i = 0; i < countNodesLowerBound; i++) {
if (i < countNodesHidden) {
// Must be on the first level
let rng = sheetResults.getRange(i * 4 + 1, 1);
setBracketItem_(rng, players);
setBracketItem_(rng.offset(2, 0, 1, 1), players);
setConnector_(sheetResults, rng.offset(0, 1, 3, 1));
setBracketItem_(rng.offset(1, 2, 1, 1));
} else {
// This player gets a bye.
setBracketItem_(sheetResults.getRange(i * 4 + 2, 3), players);
}
}
// Fills in the rest of the bracket.
upperPower--;
for (let i = 0; i < upperPower; i++) {
let pow1 = Math.pow(2, i + 1);
let pow2 = Math.pow(2, i + 2);
let pow3 = Math.pow(2, i + 3);
for (let j = 0; j < Math.pow(2, upperPower - i - 1); j++) {
setBracketItem_(sheetResults.getRange((j * pow3) + pow2, i * 2 + 5));
setConnector_(sheetResults, sheetResults.getRange((j * pow3) + pow1, i * 2 + 4, pow2 + 1, 1));
}
}
}
/**
* Sets the value of an item in the bracket and the color.
* @param {Range} rng The Spreadsheet Range.
* @param {string[]} players The list of players.
*/
function setBracketItem_(rng, players) {
if (players) {
let rand = Math.ceil(Math.random() * players.length);
rng.setValue(players.splice(rand - 1, 1)[0][0]);
}
rng.setBackgroundColor('yellow');
}
/**
* Sets the color and width for connector cells.
* @param {Sheet} sheet The spreadsheet to setup.
* @param {Range} rng The spreadsheet range.
*/
function setConnector_(sheet, rng) {
sheet.setColumnWidth(rng.getColumnIndex(), CONNECTOR_WIDTH);
rng.setBackgroundColor('green');
}
贡献者
此示例由 Google 在 Google 开发者专家的帮助下进行维护。
后续步骤