From d51eddef29b71da6c329c55136b991cc757570cd Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Tue, 20 Jan 2015 15:02:24 -0800 Subject: [PATCH 1/4] Update campaign editor analytics Double-click level row in overview to open level details view. --- app/schemas/subscriptions/editor.coffee | 3 +++ .../campaign/campaign-analytics-modal.jade | 3 ++- .../campaign/CampaignAnalyticsModal.coffee | 24 ++++++++++++------- .../editor/campaign/CampaignEditorView.coffee | 10 ++++++++ 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/app/schemas/subscriptions/editor.coffee b/app/schemas/subscriptions/editor.coffee index 2665438be..a0a416f25 100644 --- a/app/schemas/subscriptions/editor.coffee +++ b/app/schemas/subscriptions/editor.coffee @@ -1,6 +1,9 @@ c = require 'schemas/schemas' module.exports = + 'editor:campaign-analytics-modal-closed': c.object {title: 'Campaign editor analytics modal closed'}, + targetLevelSlug: {type: 'string'} + 'editor:save-new-version': c.object {title: 'Save New Version', description: 'Published when a version gets saved', required: ['major', 'commitMessage']}, major: {type: 'boolean'} commitMessage: {type: 'string'} diff --git a/app/templates/editor/campaign/campaign-analytics-modal.jade b/app/templates/editor/campaign/campaign-analytics-modal.jade index db429e173..01b5e01b5 100644 --- a/app/templates/editor/campaign/campaign-analytics-modal.jade +++ b/app/templates/editor/campaign/campaign-analytics-modal.jade @@ -7,6 +7,7 @@ block modal-header-content input.form-control#input-startday(type='text', style='width:100px;', value=campaignCompletions.startDay) input.form-control#input-endday(type='text', style='width:100px;', value=campaignCompletions.endDay) button.btn.btn-default.btn-sm#reload-button(style='margin-left:10px;') Reload + div(style='font-size:10px') Double-click row to open level details. block modal-body-content if campaignCompletions && campaignCompletions.levels @@ -23,7 +24,7 @@ block modal-body-content td Completion % tbody - for (var i = 0; i < campaignCompletions.levels.length; i++) - tr + tr.level(data-level-slug=campaignCompletions.levels[i].level) td.level-name-container= campaignCompletions.levels[i].level span.level-name-background(style="width:#{campaignCompletions.levels[i].usersRemaining || 0}%;") td= campaignCompletions.levels[i].started diff --git a/app/views/editor/campaign/CampaignAnalyticsModal.coffee b/app/views/editor/campaign/CampaignAnalyticsModal.coffee index e2c33c038..7af2e3a70 100644 --- a/app/views/editor/campaign/CampaignAnalyticsModal.coffee +++ b/app/views/editor/campaign/CampaignAnalyticsModal.coffee @@ -13,6 +13,7 @@ module.exports = class CampaignAnalyticsModal extends ModalView events: 'click #reload-button': 'onClickReloadButton' + 'dblclick .level': 'onDblClickLevel' constructor: (options, @campaignHandle, @campaignCompletions) -> super options @@ -29,6 +30,20 @@ module.exports = class CampaignAnalyticsModal extends ModalView $("#input-endday").datepicker dateFormat: "yy-mm-dd" @addCompletionLineGraphs() + onClickReloadButton: () => + startDay = $('#input-startday').val() + endDay = $('#input-endday').val() + delete @campaignCompletions.levels + @campaignCompletions.startDay = startDay + @campaignCompletions.endDay = endDay + @render() + @getCampaignAnalytics startDay, endDay + + onDblClickLevel: (e) -> + row = $(e.target).parents('.level') + Backbone.Mediator.publish 'editor:campaign-analytics-modal-closed', targetLevelSlug: row.data 'level-slug' + @hide() + addCompletionLineGraphs: -> return unless @campaignCompletions.levels for level in @campaignCompletions.levels @@ -81,15 +96,6 @@ module.exports = class CampaignAnalyticsModal extends ModalView .attr('stroke-width', 1) .attr('fill', 'none') - onClickReloadButton: () => - startDay = $('#input-startday').val() - endDay = $('#input-endday').val() - delete @campaignCompletions.levels - @campaignCompletions.startDay = startDay - @campaignCompletions.endDay = endDay - @render() - @getCampaignAnalytics startDay, endDay - getCampaignAnalytics: (startDay, endDay) => if startDay? startDayDashed = startDay diff --git a/app/views/editor/campaign/CampaignEditorView.coffee b/app/views/editor/campaign/CampaignEditorView.coffee index db3cb140e..a32e9d818 100644 --- a/app/views/editor/campaign/CampaignEditorView.coffee +++ b/app/views/editor/campaign/CampaignEditorView.coffee @@ -24,6 +24,9 @@ module.exports = class CampaignEditorView extends RootView 'click #analytics-button': 'onClickAnalyticsButton' 'click #save-button': 'onClickSaveButton' + subscriptions: + 'editor:campaign-analytics-modal-closed' : 'onAnalyticsModalClosed' + constructor: (options, @campaignHandle) -> super(options) @campaign = new Campaign({_id:@campaignHandle}) @@ -140,6 +143,13 @@ module.exports = class CampaignEditorView extends RootView onClickAnalyticsButton: -> @openModalView new CampaignAnalyticsModal {}, @campaignHandle, @campaignAnalytics + onAnalyticsModalClosed: (options) -> + if options.targetLevelSlug? and @treema.childrenTreemas?.levels?.childrenTreemas? + for original, level of @treema.childrenTreemas.levels.childrenTreemas + if level.data?.slug is options.targetLevelSlug + @openCampaignLevelView @supermodel.getModelByOriginal Level, original + break + onClickSaveButton: -> @toSave.set @toSave.filter (m) -> m.hasLocalChanges() @openModalView new SaveCampaignModal({}, @toSave) From 3c36d1cc06b93180cc465a09931fccb38a69fb99 Mon Sep 17 00:00:00 2001 From: Matt Lott Date: Tue, 20 Jan 2015 16:04:02 -0800 Subject: [PATCH 2/4] Update campaign editor analytics Adjust level completion line graph stroke-weight based on daily started count in campaign overview. --- .../campaign/CampaignAnalyticsModal.coffee | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/app/views/editor/campaign/CampaignAnalyticsModal.coffee b/app/views/editor/campaign/CampaignAnalyticsModal.coffee index 7af2e3a70..d10b22f8d 100644 --- a/app/views/editor/campaign/CampaignAnalyticsModal.coffee +++ b/app/views/editor/campaign/CampaignAnalyticsModal.coffee @@ -53,48 +53,43 @@ module.exports = class CampaignAnalyticsModal extends ModalView days.push day: day rate: level['days'][day].finished / level['days'][day].started + count: level['days'][day].started days.sort (a, b) -> a.day - b.day data = [] for i in [0...days.length] data.push x: i y: days[i].rate + c: days[i].count @addLineGraph '#background' + level.level, data addLineGraph: (containerSelector, lineData, lineColor='green', min=0, max=1.0) -> # Add a line chart to the given container + # Adjust stroke-weight based on segment count: width 0.3 to 3.0 for counts roughly 100 to 10000 # TODO: Move this to a utility library vis = d3.select(containerSelector) width = $(containerSelector).width() height = $(containerSelector).height() xRange = d3.scale.linear().range([0, width]).domain([d3.min(lineData, (d) -> d.x), d3.max(lineData, (d) -> d.x)]) yRange = d3.scale.linear().range([height, 0]).domain([min, max]) - xAxis = d3.svg.axis() - .scale(xRange) - .tickSize(5) - .tickSubdivide(true) - yAxis = d3.svg.axis() - .scale(yRange) - .tickSize(5) - .orient('left') - .tickSubdivide(true) - vis.append('svg:g') - .attr('class', 'x axis') - .attr('transform', 'translate(0,' + height + ')') - .call(xAxis) - vis.append('svg:g') - .attr('class', 'y axis') - .attr('transform', 'translate(0,0)') - .call(yAxis) - lineFunc = d3.svg.line() - .x((d) -> xRange(d.x)) - .y((d) -> yRange(d.y)) - .interpolate('linear') - vis.append('svg:path') - .attr('d', lineFunc(lineData)) - .attr('stroke', lineColor) - .attr('stroke-width', 1) - .attr('fill', 'none') + lines = [] + for i in [0...lineData.length-1] + lines.push + x1: xRange(lineData[i].x) + y1: yRange(lineData[i].y) + x2: xRange(lineData[i + 1].x) + y2: yRange(lineData[i + 1].y) + strokeWidth: Math.min(3, Math.max(0.3, Math.log(lineData[i].c/10)/2)) + vis.selectAll('.line') + .data(lines) + .enter() + .append("line") + .attr("x1", (d) -> d.x1) + .attr("y1", (d) -> d.y1) + .attr("x2", (d) -> d.x2) + .attr("y2", (d) -> d.y2) + .style("stroke-width", (d) -> d.strokeWidth) + .style("stroke", lineColor) getCampaignAnalytics: (startDay, endDay) => if startDay? From 6c5f472112481de5ed6a4bb8b14b4a586a237181 Mon Sep 17 00:00:00 2001 From: katemamba Date: Thu, 22 Jan 2015 00:22:40 +0530 Subject: [PATCH 3/4] Update factories.py for enabling devsetup in ubuntu --- scripts/devSetup/factories.py | 48 ++++++++++++++--------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/scripts/devSetup/factories.py b/scripts/devSetup/factories.py index 493427072..c4acfdc59 100644 --- a/scripts/devSetup/factories.py +++ b/scripts/devSetup/factories.py @@ -101,35 +101,6 @@ class LinuxSetup(SetupFactory): def distroSetup(self): distro = self.detectDistro() - if distro == "arch": - print("Arch Linux detected. Would you like to install \n" - "NodeJS and MongoDB via pacman? [y/N]") - if raw_input().lower() in ["y", "yes"]: - try: - subprocess.check_call(["pacman", "-S", - "nodejs", "mongodb", - "--noconfirm"]) - except subprocess.CalledProcessError as err: - print("Installation failed. Retry, Continue, or " - "Abort? [r/c/A]") - answer = raw_input().lower() - if answer in ["r", "retry"]: - return(self.distroSetup()) - elif answer in ["c", "continue"]: - return() - else: - exit(1) - else: - #try: - #print("Enabling and starting MongoDB in systemd.") - #subprocess.check_call(["systemctl", "enable", - # "mongodb.service"]) - #subprocess.check_call(["systemctl", "start", - # "mongodb.service"]) - #print("Node and Mongo installed. Continuing.") - #except subprocess.CalledProcessError as err: - #print("Mongo failed to start. Aborting") - #exit(1) if distro == "ubuntu": print("Ubuntu installation detected. Would you like to install \n" "NodeJS and MongoDB via apt-get? [y/N]") @@ -180,3 +151,22 @@ class LinuxSetup(SetupFactory): #except subprocess.CalledProcessError as err: #print("Mongo failed to start. Aborting.") #exit(1) + if distro == "arch": + print("Arch Linux detected. Would you like to install \n" + "NodeJS and MongoDB via pacman? [y/N]") + if raw_input().lower() in ["y", "yes"]: + try: + subprocess.check_call(["pacman", "-S", + "nodejs", "mongodb", + "--noconfirm"]) + except subprocess.CalledProcessError as err: + print("Installation failed. Retry, Continue, or " + "Abort? [r/c/A]") + answer = raw_input().lower() + if answer in ["r", "retry"]: + return(self.distroSetup()) + elif answer in ["c", "continue"]: + return() + else: + exit(1) + From 7dd128780faf1d103d3c02badea76aa6a62cb4e2 Mon Sep 17 00:00:00 2001 From: Nick Winter Date: Wed, 21 Jan 2015 11:49:56 -0800 Subject: [PATCH 4/4] Unlocking all audition levels in Auditions campaign. --- app/lib/world/thang.coffee | 2 +- app/models/Level.coffee | 1 - app/views/editor/level/LevelEditView.coffee | 2 +- app/views/play/CampaignView.coffee | 1 + app/views/play/level/modal/HeroVictoryModal.coffee | 4 ++-- config.coffee | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/lib/world/thang.coffee b/app/lib/world/thang.coffee index 05d21249a..6797720d6 100644 --- a/app/lib/world/thang.coffee +++ b/app/lib/world/thang.coffee @@ -73,7 +73,7 @@ module.exports = class Thang for [prop, type] in props unless type in ThangState.trackedPropertyTypes # How should errors for busted Components work? We can't recover from this and run the world. - throw new Error "Type #{type} for property #{prop} is not a trackable property type: #{trackedPropertyTypes}" + throw new Error "Type #{type} for property #{prop} is not a trackable property type: #{ThangState.trackedPropertyTypes}" oldPropIndex = @trackedPropertiesKeys.indexOf prop if oldPropIndex is -1 @trackedPropertiesKeys.push prop diff --git a/app/models/Level.coffee b/app/models/Level.coffee index bf5178e9d..6fa720673 100644 --- a/app/models/Level.coffee +++ b/app/models/Level.coffee @@ -9,7 +9,6 @@ module.exports = class Level extends CocoModel @levels: 'dungeons-of-kithgard': '5411cb3769152f1707be029c' 'defense-of-plainswood': '541b67f71ccc8eaae19f3c62' - 'the-mighty-sand-yak': '5480b9d01bf0b10000711c5f' urlRoot: '/db/level' serialize: (supermodel, session, otherSession, cached=false) -> diff --git a/app/views/editor/level/LevelEditView.coffee b/app/views/editor/level/LevelEditView.coffee index 2ed868b2d..da6e1fe36 100644 --- a/app/views/editor/level/LevelEditView.coffee +++ b/app/views/editor/level/LevelEditView.coffee @@ -200,5 +200,5 @@ module.exports = class LevelEditView extends RootView incrementBuildTime: => return if application.userIsIdle - @levelBuildTime ?= @level.get('buildTime') + @levelBuildTime ?= @level.get('buildTime') ? 0 ++@levelBuildTime diff --git a/app/views/play/CampaignView.coffee b/app/views/play/CampaignView.coffee index 07fff7412..add5f3ff1 100644 --- a/app/views/play/CampaignView.coffee +++ b/app/views/play/CampaignView.coffee @@ -138,6 +138,7 @@ module.exports = class CampaignView extends RootView level.locked = not me.ownsLevel level.original level.locked = false if @levelStatusMap[level.slug] in ['started', 'complete'] level.locked = false if @editorMode + level.locked = false if @campaign.get('name') is 'Auditions' level.disabled = true if level.adminOnly and @levelStatusMap[level.slug] not in ['started', 'complete'] level.color = 'rgb(255, 80, 60)' if level.requiresSubscription diff --git a/app/views/play/level/modal/HeroVictoryModal.coffee b/app/views/play/level/modal/HeroVictoryModal.coffee index b2313eb04..d88760dae 100644 --- a/app/views/play/level/modal/HeroVictoryModal.coffee +++ b/app/views/play/level/modal/HeroVictoryModal.coffee @@ -88,7 +88,7 @@ module.exports = class HeroVictoryModal extends ModalView me.fetch cache: false unless me.loading @readyToContinue = true if not @achievements.models.length - + # have to use a something resource because addModelResource doesn't handle models being upserted/fetched via POST like we're doing here @newEarnedAchievementsResource = @supermodel.addSomethingResource('earned achievements') if @newEarnedAchievements.length @@ -314,7 +314,7 @@ module.exports = class HeroVictoryModal extends ModalView AudioPlayer.playSound name, 1 getNextLevelCampaign: -> - {'kithgard-gates': 'forest', 'siege-of-stonehold': 'desert'}[@level.get('slug')] or @level.get 'campaign' # Much easier to just keep this updated than to dynamically figure it out. + {'kithgard-gates': 'forest', 'siege-of-stonehold': 'desert', 'clash-of-clones': 'mountain'}[@level.get('slug')] or @level.get 'campaign' # Much easier to just keep this updated than to dynamically figure it out. getNextLevelLink: -> link = '/play' diff --git a/config.coffee b/config.coffee index bfe7fd781..7b9945fd8 100644 --- a/config.coffee +++ b/config.coffee @@ -126,7 +126,7 @@ exports.config = 'vendor/scripts/jasmine-html.js' 'vendor/scripts/jasmine-boot.js' 'vendor/scripts/jasmine-mock-ajax.js' - + # vendor.js ordering 'bower_components/jquery/dist/jquery.js' 'bower_components/lodash/dist/lodash.js'