Public
Edited
Feb 10, 2023
Insert cell
Insert cell
getCanvasTeams = () => { // NOTE not a real function, these are console commands for different pages...
// first put students into teams manually on Canvas.
// then, run this command to open all collapsed groups on the groups page
document.querySelectorAll('.group-collapsed-item').forEach(g => g.click())
// then, read names of students per team
let teams = [...document.querySelectorAll('.group')].map(g => ({
name: g.querySelector('.group-name').textContent,
players: [...g.querySelectorAll('.group-user-name')].map(e => ({name: e.textContent.trim()}))}))
.filter(t => t.name.includes('Code') && t.players.length >= 3)
// then, dump data and go to course roster and run this to add login ids
const $ = () => {} // (uses jquery)
teams.map(t => ({...t, players: t.players.map(p => ({...p, loginId: $(`.roster_user_name:contains('${p.name}')`).closest('td').next().text().trim() }))}))
// then, go to code defenders and convert login ids to CodeDefenders ids
teams.map(t => ({...t, players: t.players.map(p => ({...p, userId: $(`td:contains('${p.loginId}')`).prev().text().trim() }))}))
// dump the result into a text file!
}
Insert cell
// all the stuff needed to go--see bottom for commands to run
everything = {
// all the stuff needed to go--see bottom for commands to run
async function addPlayer ({userId, gameId, role }) {
await new Promise(resolve => setTimeout(resolve, 1000)) // pause 1 second between players
console.log('Adding player', {userId, gameId, role })
const getFormData = object => Object.keys(object).reduce((formData, key) => {
formData.append(key, object[key]);
return formData;
}, new FormData());
const data = new URLSearchParams(getFormData({formType:'addPlayerToGame',
userId, gameId, role}))
await fetch("/admin/games", {
method: "post",
headers: {
//'Accept': 'application/json',
'Content-Type': "application/x-www-form-urlencoded"
},
body: data
})
}
async function assignTeamToGame({team, role, gameId}) {
// for player in args.team.players, addPlayer(player.userId, args.role, args.gameId)
for (const p of team.players) { await addPlayer({userId: p.userId, role, gameId}) }
}
function assignPairsToGames({pairs, gameIds}) {
// returns a list of assignments of {team, gameId, role}
// for (gameId, pair) in zip(args.pairs, args.gameIds), pair.map assignTeamToGame({gameId, team})
const zip = (l, r) => l.map((e, i) => [e, r[i]])
return zip(pairs, gameIds).map(([pair, gameId]) => [{gameId, team: pair[0], role: 'ATTACKER'}, {gameId, team: pair[1], role: 'DEFENDER'}]).flat()
// for (const [pair, gameId] of ()) {
// await assignTeamToGame({gameId, team: pair[0], role: 'ATTACKER'})
// await assignTeamToGame({gameId, team: pair[1], role: 'DEFENDER'})
// }
}
async function stageAssignments(assignments) {
for (const assignment of assignments) {
await assignTeamToGame(assignment)
}
}
function randomlyPairTeams({teams}) {
// returns pairs (requires teams is even)
// randomly sort args.teams, then zip(args.teams[:half], args.teams[half:]) and map ['ATTACKER', 'DEFENDER'] to role for those teams
const rand = teams.sort(() => Math.random() > .5)
const zip = (l, r) => l.map((e, i) => [e, r[i]])
console.log('Remember to save these pairs!')
return zip(rand.slice(0, teams.length/2), rand.slice(teams.length/2, teams.length))
}
function readStagedGames() {
// Note you can use search bar to filter before querying
// return gameIds : ["T0", "T1"]
return [...document.querySelectorAll('#table-staged-games tbody tr td:nth-child(2)')].map(e => e.textContent)
}
// DO THESE!!!
// teams = allTeams.attu1 // get subset for this server
// pairs = randomlyPairTeams({teams})
// pairs2 = pairs.map(([l, r], i) => [r, pairs[(i + 1) % pairs.length][0]]) // for the second round, change pairings and swap alignments
// gameIds = readStagedGames()
// assignments = assignPairsToGames({pairs, gameIds})
// stageAssignments(assignments)
}
Insert cell
zip = (l, r) => l.map((e, i) => [e, r[i]])
Insert cell
pairs = zip([1, 2, 3], ['a', 'b', 'c'])
Insert cell
pairs.map(([l, r], i) => [r, pairs[(i + 1) % pairs.length][0]])
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more