Unlisted
Edited
Nov 18, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
currentSystemStats(10, 100, 1200, 2)
Insert cell
currentSystemStats = (attendees, avgTicket, npExpenses, musicians) => {
const income = attendees * avgTicket
const afterNpExpenses = income - npExpenses
// Callers always get the full guarantee
const callerGuarantee = PERFORMER_GUARANTEE
// If there are more musicians than our limit, we divide the maximum guarantee by the number of musicians
const musicianGuarantee = musicians <= MUSICIAN_LIMIT ? PERFORMER_GUARANTEE: PERFORMER_GUARANTEE * MUSICIAN_LIMIT / musicians
const rawProfit = afterNpExpenses - callerGuarantee - musicianGuarantee * musicians
// BIDA takes $100 if there's more than $100 raw profit, no profit if there's a loss
const bida100 = Math.max(Math.min(100, rawProfit), 0)
const profitToSplit = Math.max(rawProfit - bida100, 0)
// BIDA additionally takes half of the remaining profit
const performerProfit = profitToSplit / 2
// The performers split evenly what remains
const performerProfitPer = Math.floor(performerProfit / (musicians + 1))
const musicianPay = musicianGuarantee + performerProfitPer
const callerPay = callerGuarantee + performerProfitPer
const bidaProfit = afterNpExpenses - musicianPay * musicians - callerPay

return {
attendees,
musicians,
income,
musicianPay,
callerPay,
bidaProfit,
system: 'current',
}
}
Insert cell
newSystemStats = (attendees, avgTicket, npExpenses, musicians) => {
const income = attendees * avgTicket
const afterNpExpenses = income - npExpenses
// Callers always get the full guarantee
const callerGuarantee = PERFORMER_GUARANTEE
// If there are more musicians than our limit, we divide the maximum guarantee by the number of musicians
const musicianGuarantee = musicians <= MUSICIAN_LIMIT ? PERFORMER_GUARANTEE: PERFORMER_GUARANTEE * MUSICIAN_LIMIT / musicians
// Each performer gets $bonusRate/attendee above the threshold.
// If there are fewer than bonusThreshold attendees this amount will be 0
const performerBonus = Math.max(attendees - bonusThreshold, 0) * bonusRate
const musicianPay = musicianGuarantee + performerBonus
const callerPay = callerGuarantee + performerBonus
const bidaProfit = afterNpExpenses - musicianPay * musicians - callerPay

return {
attendees,
musicians,
income,
musicianPay,
callerPay,
bidaProfit,
system: 'proposed',
}
}
Insert cell
Insert cell
Insert cell
Insert cell
scenarios = d3.cross(attendeeCounts, bandSizes)
.map(([attendees, musicians]) => [
newSystemStats(
attendees,
avgTicket,
nonPerformerExpenses,
musicians
),
currentSystemStats(
attendees,
avgTicket,
nonPerformerExpenses,
musicians
)
])
.flat()
Insert cell
Insert cell
PERFORMER_GUARANTEE = 125
Insert cell
MUSICIAN_LIMIT = 4
Insert cell
PAY_COLOR = '#058'
Insert cell
PROFIT_COLOR = '#4C2'
Insert cell
Insert cell
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