Dashboard monthly revenue counts, and tabs

This commit is contained in:
Matt Lott 2016-02-20 17:27:25 -08:00
parent 16969e1d5a
commit cac9a7463f
4 changed files with 317 additions and 236 deletions
app
core
styles/admin
templates/admin
views/admin

View file

@ -12,7 +12,7 @@ module.exports.createContiguousDays = (timeframeDays, skipToday=true) ->
currentDate.setUTCDate(currentDate.getUTCDate() + 1) currentDate.setUTCDate(currentDate.getUTCDate() + 1)
days days
module.exports.createLineChart = (containerSelector, chartLines) -> module.exports.createLineChart = (containerSelector, chartLines, containerWidth) ->
# Creates a line chart within 'containerSelector' based on chartLines # Creates a line chart within 'containerSelector' based on chartLines
return unless chartLines?.length > 0 and containerSelector return unless chartLines?.length > 0 and containerSelector
@ -20,7 +20,7 @@ module.exports.createLineChart = (containerSelector, chartLines) ->
keyHeight = 20 keyHeight = 20
xAxisHeight = 20 xAxisHeight = 20
yAxisWidth = 40 yAxisWidth = 40
containerWidth = $(containerSelector).width() containerWidth = $(containerSelector).width() unless containerWidth
containerHeight = $(containerSelector).height() containerHeight = $(containerSelector).height()
yScaleCount = 0 yScaleCount = 0

View file

@ -1,5 +1,16 @@
#admin-analytics-view #admin-analytics-view
// Force compact top site chrome
background-position: center -226px
padding-top: 50px
#site-nav
top: -80px
#nav-logo
display: none
#small-nav-logo
display: inline-block
height: 30px
#site-content-area #site-content-area
width: 100% width: 100%
.big-stat .big-stat

View file

@ -32,201 +32,246 @@ block content
div.description Campaign Monthly Active Users div.description Campaign Monthly Active Users
div.count= campaignBigMAU div.count= campaignBigMAU
h3 KPI 60 days ul.nav.nav-tabs
.kpi-recent-chart.line-chart-container li.active
a(data-target="#tab_kpis", data-toggle="tab") KPIs
li
a(data-target="#tab_active_classes", data-toggle="tab") Active Classes
li
a(data-target="#tab_revenue", data-toggle="tab") Revenue
li
a(data-target="#tab_classroom", data-toggle="tab") Classroom
li
a(data-target="#tab_campaign", data-toggle="tab") Campaign
li
a(data-target="#tab_campaign_vs_classroom", data-toggle="tab") Campaign vs Classroom
h3 KPI 365 days .tab-content
.kpi-chart.line-chart-container .tab-pane.active#tab_kpis
h3 KPI 60 days
.kpi-recent-chart.line-chart-container
h1 Table of Contents h3 KPI 365 days
b Graphs .kpi-chart.line-chart-container
div
a(href='#active-classes-graph') Active Classes
div
a(href='#recurring-revenue-graph') Recurring Revenue
div
a(href='#classroom-daus-graph') Classroom Daily Active Users
div
a(href='#classroom-maus-graph') Classroom Monthly Active Users
div
a(href='#campaign-daus-graph') Campaign Daily Active Users
div
a(href='#campaign-maus-graph') Campaign Monthly Active Users
div
a(href='#campaign-vs-classroom-paid-maus-recent-graph') Campaign vs Classroom Paid Monthly Active Users (90 days)
div
a(href='#campaign-vs-classroom-paid-maus-graph') Campaign vs Classroom Paid Monthly Active Users (365 days)
div
a(href='#enrollments-graph') Enrollments Issued and Redeemed
b Tables
div
a(href='#furthest-courses-table') Furthest Course
div
a(href='#school-counts-table') School Counts
div
a(href='#active-classes-table') Active Classes
div
a(href='#recurring-revenue-table') Recurring Revenue
div
a(href='#active-users-table') Active Users
div
a(href='#enrollments-table') Enrollments
h3#active-classes-graph Active Classes 90 days .tab-pane#tab_active_classes
.small Active class: 12+ students in a classroom, with 6+ who played in last 30 days. Played == 'Started Level' analytics event. h3 Active Classes 90 days
.small Paid student: user.coursePrepaidID set and prepaid.properties.trialRequestID NOT set .small Active class: 12+ students in a classroom, with 6+ who played in last 30 days. Played == 'Started Level' analytics event.
.small Trial student: user.coursePrepaidID set and prepaid.properties.trialRequestID set .small Paid student: user.coursePrepaidID set and prepaid.properties.trialRequestID NOT set
.small Paid class: at least one paid student in the classroom .small Trial student: user.coursePrepaidID set and prepaid.properties.trialRequestID set
.small Trial class: not paid, at least one trial student in classroom .small Paid class: at least one paid student in the classroom
.small Free class: not paid, not trial .small Trial class: not paid, at least one trial student in classroom
.active-classes-chart.line-chart-container .small Free class: not paid, not trial
.active-classes-chart.line-chart-container
h3#recurring-revenue-graph Recurring Revenue 90 days h1#active-classes-table Active Classes
.recurring-revenue-chart.line-chart-container table.table.table-striped.table-condensed
h3#classroom-daus-graph Classroom Daily Active Users 90 days
.small Paid student: user.coursePrepaidID set and prepaid.properties.trialRequestID NOT set
.small Trial student: user.coursePrepaidID set and prepaid.properties.trialRequestID set
.small Free student: not paid, not trial
.classroom-daily-active-users-chart.line-chart-container
h3#classroom-maus-graph Classroom Monthly Active Users 90 days
.classroom-monthly-active-users-chart.line-chart-container
h3#campaign-daus-graph Campaign Daily Active Users 90 days
.small Paid user: had monthly or yearly sub on given day
.small Free user: not paid
.campaign-daily-active-users-chart.line-chart-container
h3#campaign-maus-graph Campaign Monthly Active Users 90 days
.campaign-monthly-active-users-chart.line-chart-container
h3#campaign-vs-classroom-paid-maus-recent-graph Campaign vs Classroom Paid Monthly Active Users 90 days
.campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container
h3#campaign-vs-classroom-paid-maus-graph Campaign vs Classroom Paid Monthly Active Users 365 days
.small TODO: aggregate active user data from last year
.campaign-vs-classroom-monthly-active-users-chart.line-chart-container
h3#enrollments-graph Enrollments Issued and Redeemed 90 days
.paid-courses-chart.line-chart-container
h3#furthest-courses-table Furthest Course
.small Teacher: owner of a course instance
.small Student: member of a course instance (assigned to course)
.small For course instances created in last #{view.furthestCourseDayRange} days, not Single Player, hourOfCode != true
.small Counts are not summed. I.e. a student or teacher only contributes to the count of one course.
if view.teacherCourseDistribution
table.table.table-striped.table-condensed
tr
th Course
th Teachers
th Students
th Avg students per teacher
each count, courseIndex in view.teacherCourseDistribution
tr tr
td= view.courses.models[courseIndex].get('name') th Day
td= count for group in activeClassGroups
td= view.studentCourseDistribution[courseIndex] || 0 th= group.replace('Active classes', '')
td= Math.round((view.studentCourseDistribution[courseIndex] || 0) / count) each activeClass in activeClasses
else tr
div Loading ... td= activeClass.day
each val in activeClass.groups
td= val
h3#school-counts-table School Counts
.small Only including schools with #{view.minSchoolCount}+ counts .tab-pane#tab_revenue
if view.schoolCounts h3 Daily Recurring Revenue 90 days
table.table.table-striped.table-condensed .recurring-daily-revenue-chart-90.line-chart-container
tr
th h3 Monthly Recurring Revenue 90 days
th School Name .recurring-monthly-revenue-chart-90.line-chart-container
th User Count
each val, i in view.schoolCounts h3 Daily Recurring Revenue 365 days
.recurring-daily-revenue-chart-365.line-chart-container
h3 Monthly Recurring Revenue 365 days
.recurring-monthly-revenue-chart-365.line-chart-container
h1#recurring-revenue-table Recurring Revenue
table.table.table-striped.table-condensed
tr tr
td= i + 1 th Day
td= val.schoolName for group in revenueGroups
td= val.count th= group.replace('DRR ', 'Daily ').replace('MRR ', 'Monthly ')
else each entry in revenue
div Loading ... tr
td= entry.day
each val in entry.groups
td $#{(val / 100).toFixed(2)}
h1#active-classes-table Active Classes .tab-pane#tab_classroom
table.table.table-striped.table-condensed h3#classroom-daus-graph Classroom Daily Active Users 90 days
tr .small Paid student: user.coursePrepaidID set and prepaid.properties.trialRequestID NOT set
th Day .small Trial student: user.coursePrepaidID set and prepaid.properties.trialRequestID set
for group in activeClassGroups .small Free student: not paid, not trial
th= group.replace('Active classes', '') .classroom-daily-active-users-chart.line-chart-container
each activeClass in activeClasses
tr
td= activeClass.day
each val in activeClass.groups
td= val
h1#recurring-revenue-table Recurring Revenue h3#classroom-maus-graph Classroom Monthly Active Users 90 days
table.table.table-striped.table-condensed .classroom-monthly-active-users-chart.line-chart-container
tr
th Day
for group in revenueGroups
th= group.replace('DRR ', 'Daily ')
each entry in revenue
tr
td= entry.day
each val in entry.groups
td $#{(val / 100).toFixed(2)}
h1#active-users-table Active Users h3#enrollments-graph Enrollments Issued and Redeemed 90 days
if activeUsers.length > 0 .paid-courses-chart.line-chart-container
- var eventNames = [];
each count, event in activeUsers[0].events
- eventNames.push(event)
- eventNames.sort(function (a, b) {
- if (a.indexOf('campaign') == b.indexOf('campaign') || a.indexOf('classroom') == b.indexOf('classroom')) {
- return a.localeCompare(b);
- }
- else if (a.indexOf('campaign') > b.indexOf('campaign')) {
- return 1;
- }
- else {
- return -1;
- }
- });
table.table.table-striped.table-condensed
tr
th(style='min-width:85px;') Day
each eventName in eventNames
th= eventName
th DAU Campaign Total
th DAU Classroom Total
each activeUser in activeUsers
tr
td= activeUser.day
- var dauCampaignTotal = 0
- var dauClassroomTotal = 0
each eventName in eventNames
td= activeUser.events[eventName] || 0
if eventName.indexOf('DAU campaign') >= 0
- dauCampaignTotal += (activeUser.events[eventName] || 0);
else if eventName.indexOf('DAU classroom') >= 0
- dauClassroomTotal += (activeUser.events[eventName] || 0);
td= dauCampaignTotal
td= dauClassroomTotal
h1#enrollments-table Enrollments h3#furthest-courses-table Furthest Course
table.table.table-striped.table-condensed .small Teacher: owner of a course instance
tr .small Student: member of a course instance (assigned to course)
th Day .small For course instances created in last #{view.furthestCourseDayRange} days, not Single Player, hourOfCode != true
th Paid Enrollments Issued .small Counts are not summed. I.e. a student or teacher only contributes to the count of one course.
th Paid Enrollments Redeemed if view.teacherCourseDistribution
th Trial Enrollments Issued table.table.table-striped.table-condensed
th Trial Enrollments Redeemed tr
each day in enrollmentDays th Course
tr th Teachers
td= day th Students
if dayEnrollmentsMap[day] th Avg students per teacher
td= dayEnrollmentsMap[day].paidIssued || 0 each count, courseIndex in view.teacherCourseDistribution
td= dayEnrollmentsMap[day].paidRedeemed || 0 tr
td= dayEnrollmentsMap[day].trialIssued || 0 td= view.courses.models[courseIndex].get('name')
td= dayEnrollmentsMap[day].trialRedeemed || 0 td= count
td= view.studentCourseDistribution[courseIndex] || 0
td= Math.round((view.studentCourseDistribution[courseIndex] || 0) / count)
else
div Loading ...
#school-counts
h3 School Counts
.small Only including schools with #{view.minSchoolCount}+ counts
if view.schoolCounts
table.table.table-striped.table-condensed
tr
th
th School Name
th User Count
each val, i in view.schoolCounts
tr
td= i + 1
td= val.schoolName
td= val.count
else else
td 0 div Loading ...
td 0
td 0 h1#active-users-table Active Users
td 0 if activeUsers.length > 0
- var eventNames = [];
each count, event in activeUsers[0].events
if event.indexOf('classroom') >= 0
- eventNames.push(event)
- eventNames.sort(function (a, b) {return a.localeCompare(b);});
table.table.table-striped.table-condensed
tr
th(style='min-width:85px;') Day
each eventName in eventNames
th= eventName
th DAU Classroom Total
each activeUser in activeUsers
tr
td= activeUser.day
- var dauClassroomTotal = 0
each eventName in eventNames
if eventName.indexOf('DAU') >= 0
- dauClassroomTotal += (activeUser.events[eventName] || 0);
td= activeUser.events[eventName] || 0
td= dauClassroomTotal
h1#enrollments-table Enrollments
table.table.table-striped.table-condensed
tr
th Day
th Paid Enrollments Issued
th Paid Enrollments Redeemed
th Trial Enrollments Issued
th Trial Enrollments Redeemed
each day in enrollmentDays
tr
td= day
if dayEnrollmentsMap[day]
td= dayEnrollmentsMap[day].paidIssued || 0
td= dayEnrollmentsMap[day].paidRedeemed || 0
td= dayEnrollmentsMap[day].trialIssued || 0
td= dayEnrollmentsMap[day].trialRedeemed || 0
else
td 0
td 0
td 0
td 0
.tab-pane#tab_campaign
h3#campaign-daus-graph Campaign Daily Active Users 90 days
.small Paid user: had monthly or yearly sub on given day
.small Free user: not paid
.campaign-daily-active-users-chart.line-chart-container
h3#campaign-maus-graph Campaign Monthly Active Users 90 days
.campaign-monthly-active-users-chart.line-chart-container
h1#active-users-table Active Users
if activeUsers.length > 0
- var eventNames = [];
each count, event in activeUsers[0].events
if event.indexOf('campaign') >= 0
- eventNames.push(event)
- eventNames.sort(function (a, b) {return a.localeCompare(b);});
table.table.table-striped.table-condensed
tr
th(style='min-width:85px;') Day
each eventName in eventNames
th= eventName
th DAU Total
each activeUser in activeUsers
tr
td= activeUser.day
- var dauCampaignTotal = 0
each eventName in eventNames
if eventName.indexOf('DAU') >= 0
- dauCampaignTotal += (activeUser.events[eventName] || 0);
td= activeUser.events[eventName] || 0
td= dauCampaignTotal
.tab-pane#tab_campaign_vs_classroom
h3#campaign-vs-classroom-paid-maus-recent-graph Campaign vs Classroom Paid Monthly Active Users 90 days
.campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container
h3#campaign-vs-classroom-paid-maus-graph Campaign vs Classroom Paid Monthly Active Users 365 days
.small TODO: aggregate active user data from last year
.campaign-vs-classroom-monthly-active-users-chart.line-chart-container
h1#active-users-table Active Users
if activeUsers.length > 0
- var eventNames = [];
each count, event in activeUsers[0].events
- eventNames.push(event)
- eventNames.sort(function (a, b) {
- if (a.indexOf('campaign') == b.indexOf('campaign') || a.indexOf('classroom') == b.indexOf('classroom')) {
- return a.localeCompare(b);
- }
- else if (a.indexOf('campaign') > b.indexOf('campaign')) {
- return 1;
- }
- else {
- return -1;
- }
- });
table.table.table-striped.table-condensed
tr
th(style='min-width:85px;') Day
each eventName in eventNames
th= eventName
th DAU Campaign Total
th DAU Classroom Total
each activeUser in activeUsers
tr
td= activeUser.day
- var dauCampaignTotal = 0
- var dauClassroomTotal = 0
each eventName in eventNames
td= activeUser.events[eventName] || 0
if eventName.indexOf('DAU campaign') >= 0
- dauCampaignTotal += (activeUser.events[eventName] || 0);
else if eventName.indexOf('DAU classroom') >= 0
- dauClassroomTotal += (activeUser.events[eventName] || 0);
td= dauCampaignTotal
td= dauClassroomTotal

View file

@ -7,8 +7,6 @@ RootView = require 'views/core/RootView'
template = require 'templates/admin/analytics' template = require 'templates/admin/analytics'
utils = require 'core/utils' utils = require 'core/utils'
# TODO: switch page to tabs instead of table of contents
module.exports = class AnalyticsView extends RootView module.exports = class AnalyticsView extends RootView
id: 'admin-analytics-view' id: 'admin-analytics-view'
template: template template: template
@ -86,18 +84,20 @@ module.exports = class AnalyticsView extends RootView
url: '/db/analytics_perday/-/recurring_revenue' url: '/db/analytics_perday/-/recurring_revenue'
method: 'POST' method: 'POST'
success: (data) => success: (data) =>
# Organize data by day, then group # Organize data by day, then group
groupMap = {} groupMap = {}
dayGroupCountMap = {} dayGroupCountMap = {}
for dailyRevenue in data for dailyRevenue in data
dayGroupCountMap[dailyRevenue.day] ?= {} dayGroupCountMap[dailyRevenue.day] ?= {}
dayGroupCountMap[dailyRevenue.day]['Daily Total'] = 0 dayGroupCountMap[dailyRevenue.day]['DRR Total'] = 0
for group, val of dailyRevenue.groups for group, val of dailyRevenue.groups
groupMap[group] = true groupMap[group] = true
dayGroupCountMap[dailyRevenue.day][group] = val dayGroupCountMap[dailyRevenue.day][group] = val
dayGroupCountMap[dailyRevenue.day]['Daily Total'] += val dayGroupCountMap[dailyRevenue.day]['DRR Total'] += val
@revenueGroups = Object.keys(groupMap) @revenueGroups = Object.keys(groupMap)
@revenueGroups.push 'Daily Total' @revenueGroups.push 'DRR Total'
# Build list of recurring revenue entries, where each entry is a day of individual group values # Build list of recurring revenue entries, where each entry is a day of individual group values
@revenue = [] @revenue = []
for day of dayGroupCountMap for day of dayGroupCountMap
@ -106,23 +106,35 @@ module.exports = class AnalyticsView extends RootView
for group in @revenueGroups for group in @revenueGroups
data.groups.push(dayGroupCountMap[day][group] ? 0) data.groups.push(dayGroupCountMap[day][group] ? 0)
@revenue.push data @revenue.push data
# Order present to past
@revenue.sort (a, b) -> b.day.localeCompare(a.day) @revenue.sort (a, b) -> b.day.localeCompare(a.day)
return unless @revenue.length > 0 return unless @revenue.length > 0
# Add monthly recurring revenue values # Add monthly recurring revenue values
@revenueGroups.push 'Monthly'
monthlyValues = [] # For each daily group, add up monthly values walking forward through time, and add to revenue groups
for i in [@revenue.length-1..0] monthlyDailyGroupMap = {}
dailyTotal = @revenue[i].groups[@revenue[i].groups.length - 1] dailyGroupIndexMap = {}
monthlyValues.push(dailyTotal) for group, i in @revenueGroups
monthlyValues.shift() while monthlyValues.length > 30 monthlyDailyGroupMap[group.replace('DRR', 'MRR')] = group
if monthlyValues.length is 30 dailyGroupIndexMap[group] = i
@revenue[i].groups.push(_.reduce(monthlyValues, (s, num) -> s + num)) for monthlyGroup, dailyGroup of monthlyDailyGroupMap
monthlyValues = []
for i in [@revenue.length-1..0]
dailyTotal = @revenue[i].groups[dailyGroupIndexMap[dailyGroup]]
monthlyValues.push(dailyTotal)
monthlyValues.shift() while monthlyValues.length > 30
if monthlyValues.length is 30
@revenue[i].groups.push(_.reduce(monthlyValues, (s, num) -> s + num))
for monthlyGroup, dailyGroup of monthlyDailyGroupMap
@revenueGroups.push monthlyGroup
@updateAllKPIChartData() @updateAllKPIChartData()
@updateRevenueChartData() @updateRevenueChartData()
@render?() @render?()
}, 0).load() }, 0).load()
@supermodel.addRequestResource({ @supermodel.addRequestResource({
@ -134,7 +146,7 @@ module.exports = class AnalyticsView extends RootView
return -1 if a.count > b.count return -1 if a.count > b.count
return 0 if a.count is b.count return 0 if a.count is b.count
1 1
@render?() @renderSelectors?('#school-counts')
}, 0).load() }, 0).load()
@supermodel.addRequestResource({ @supermodel.addRequestResource({
@ -272,17 +284,21 @@ module.exports = class AnalyticsView extends RootView
points points
createLineCharts: -> createLineCharts: ->
d3Utils.createLineChart('.kpi-recent-chart', @kpiRecentChartLines) visibleWidth = $('.kpi-recent-chart').width()
d3Utils.createLineChart('.kpi-chart', @kpiChartLines) d3Utils.createLineChart('.kpi-recent-chart', @kpiRecentChartLines, visibleWidth)
d3Utils.createLineChart('.active-classes-chart', @activeClassesChartLines) d3Utils.createLineChart('.kpi-chart', @kpiChartLines, visibleWidth)
d3Utils.createLineChart('.classroom-daily-active-users-chart', @classroomDailyActiveUsersChartLines) d3Utils.createLineChart('.active-classes-chart', @activeClassesChartLines, visibleWidth)
d3Utils.createLineChart('.classroom-monthly-active-users-chart', @classroomMonthlyActiveUsersChartLines) d3Utils.createLineChart('.classroom-daily-active-users-chart', @classroomDailyActiveUsersChartLines, visibleWidth)
d3Utils.createLineChart('.campaign-daily-active-users-chart', @campaignDailyActiveUsersChartLines) d3Utils.createLineChart('.classroom-monthly-active-users-chart', @classroomMonthlyActiveUsersChartLines, visibleWidth)
d3Utils.createLineChart('.campaign-monthly-active-users-chart', @campaignMonthlyActiveUsersChartLines) d3Utils.createLineChart('.campaign-daily-active-users-chart', @campaignDailyActiveUsersChartLines, visibleWidth)
d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersRecentChartLines) d3Utils.createLineChart('.campaign-monthly-active-users-chart', @campaignMonthlyActiveUsersChartLines, visibleWidth)
d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersChartLines) d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-recent-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersRecentChartLines, visibleWidth)
d3Utils.createLineChart('.paid-courses-chart', @enrollmentsChartLines) d3Utils.createLineChart('.campaign-vs-classroom-monthly-active-users-chart.line-chart-container', @campaignVsClassroomMonthlyActiveUsersChartLines, visibleWidth)
d3Utils.createLineChart('.recurring-revenue-chart', @revenueChartLines) d3Utils.createLineChart('.paid-courses-chart', @enrollmentsChartLines, visibleWidth)
d3Utils.createLineChart('.recurring-daily-revenue-chart-90', @revenueDailyChartLines90Days, visibleWidth)
d3Utils.createLineChart('.recurring-monthly-revenue-chart-90', @revenueMonthlyChartLines90Days, visibleWidth)
d3Utils.createLineChart('.recurring-daily-revenue-chart-365', @revenueDailyChartLines365Days, visibleWidth)
d3Utils.createLineChart('.recurring-monthly-revenue-chart-365', @revenueMonthlyChartLines365Days, visibleWidth)
updateAllKPIChartData: -> updateAllKPIChartData: ->
@kpiRecentChartLines = [] @kpiRecentChartLines = []
@ -644,9 +660,11 @@ module.exports = class AnalyticsView extends RootView
line.max = dailyMax for line in @enrollmentsChartLines line.max = dailyMax for line in @enrollmentsChartLines
updateRevenueChartData: -> updateRevenueChartData: ->
@revenueChartLines = [] @revenueDailyChartLines90Days = []
@revenueMonthlyChartLines90Days = []
@revenueDailyChartLines365Days = []
@revenueMonthlyChartLines365Days = []
return unless @revenue?.length return unless @revenue?.length
days = d3Utils.createContiguousDays(90)
groupDayMap = {} groupDayMap = {}
for entry in @revenue for entry in @revenue
@ -655,24 +673,31 @@ module.exports = class AnalyticsView extends RootView
groupDayMap[@revenueGroups[i]][entry.day] ?= 0 groupDayMap[@revenueGroups[i]][entry.day] ?= 0
groupDayMap[@revenueGroups[i]][entry.day] += count groupDayMap[@revenueGroups[i]][entry.day] += count
colorIndex = 0 addRevenueChartLine = (days, eventPrefix, lines) =>
dailyMax = 0 colorIndex = 0
for group, entries of groupDayMap dailyMax = 0
data = [] for group, entries of groupDayMap
for day, count of entries continue unless group.indexOf(eventPrefix) >= 0
data.push data = []
day: day for day, count of entries
value: count / 100 data.push
data.reverse() day: day
points = @createLineChartPoints(days, data) value: count / 100
@revenueChartLines.push data.reverse()
points: points points = @createLineChartPoints(days, data)
description: group.replace('DRR ', 'Daily ') lines.push
lineColor: @lineColors[colorIndex++ % @lineColors.length] points: points
strokeWidth: 1 description: group.replace(eventPrefix + ' ', 'Daily ')
min: 0 lineColor: @lineColors[colorIndex++ % @lineColors.length]
max: _.max(points, 'y').y strokeWidth: 1
showYScale: group in ['Daily Total', 'Monthly'] min: 0
dailyMax = _.max(points, 'y').y if group is 'Daily Total' max: _.max(points, 'y').y
for line in @revenueChartLines when line.description isnt 'Monthly' showYScale: group is eventPrefix + ' Total'
line.max = dailyMax dailyMax = _.max(points, 'y').y if group is eventPrefix + ' Total'
for line in lines
line.max = dailyMax
addRevenueChartLine(d3Utils.createContiguousDays(90), 'DRR', @revenueDailyChartLines90Days)
addRevenueChartLine(d3Utils.createContiguousDays(90), 'MRR', @revenueMonthlyChartLines90Days)
addRevenueChartLine(d3Utils.createContiguousDays(365), 'DRR', @revenueDailyChartLines365Days)
addRevenueChartLine(d3Utils.createContiguousDays(365), 'MRR', @revenueMonthlyChartLines365Days)