Skip to content

Commit

Permalink
Merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
nwinter committed Mar 12, 2018
2 parents 0438d76 + 2f9bfba commit 7337e6d
Show file tree
Hide file tree
Showing 79 changed files with 1,573 additions and 2,355 deletions.
Binary file modified app/assets/images/common/button-background-active-border.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/assets/images/common/button-background-disabled-border.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/assets/images/common/button-background-pressed-border.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions app/collections/Levels.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CocoCollection = require 'collections/CocoCollection'
Level = require 'models/Level'
utils = require 'core/utils'

module.exports = class LevelCollection extends CocoCollection
url: '/db/level'
Expand All @@ -16,3 +17,19 @@ module.exports = class LevelCollection extends CocoCollection
fetchForCampaign: (campaignSlug, options={}) ->
options.url = "/db/campaign/#{campaignSlug}/levels"
@fetch(options)

getSolutionsMap: (language) ->
@models.reduce((map, level) =>
targetLang = level.get('primerLanguage') or language
solutions = level.getSolutions().filter((s) => s.language is targetLang)
map[level.get('original')] = solutions?.map((s) => @fingerprint(s.source, s.language))
map
, {})

fingerprint: (code, language) ->
# Add a zero-width-space at the end of every comment line
switch language
when 'javascript' then code.replace /^(\/\/.*)/gm, "$1​"
when 'lua' then code.replace /^(--.*)/gm, "$1​"
when 'html' then code.replace /^(<!--.*)-->/gm, "$1​-->"
else code.replace /^(#.*)/gm, "$1​"
130 changes: 130 additions & 0 deletions app/core/components/PieComponent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<!--Src: https://www.npmjs.com/package/vue-pie-chart-->
<template>
<svg :viewBox=viewBox>
<circle
cx=0
cy=0
r=1
stroke="transparent"
:stroke-width="strokeWidth / 5"
/>
<path
v-if=!circle
:d=path
:stroke=color
:stroke-width="strokeWidth / 5"
:opacity=opacity
/>
<circle
v-if=circle
cx=0
cy=0
r=1
:stroke=color
:stroke-width="strokeWidth / 5"
:opacity=opacity
/>
<text
x=0 y=0
text-anchor=middle
alignment-baseline=middle
:style=labelStyle()
>
{{label || _label}}
</text>
<text
x=0 :y="width / 10"
text-anchor=middle
alignment-baseline=middle
:style=labelStyle(true)
>
{{labelSmall}}
</text>
</svg>
</template>

<script>
module.exports = Vue.extend({
name: 'pie-chart',
props: {
ratio: Number,
percent: {
type: Number,
default: 42
},
strokeWidth: {
type: Number,
default: 1,
validator: (v) => v > 0 && v <= 10
},
label: String,
labelSmall: String,
color: {
type: String,
default: '#40a070'
},
opacity: {
type: Number,
default: 0.7
}
},
computed: {
width: function () {
return 2 + this.strokeWidth / 5
},
viewBox: function () {
let c = 1 + this.strokeWidth / 10
let w = this.width
return `${-c} ${-c} ${w} ${w}`
},
circle: function () {
return this._ratio % 1 === 0
},
_ratio: function () {
let r = this.percent / 100
return isFinite(this.ratio) ? this.ratio : r
},
_label: function () {
let p = (this._ratio * 100).toFixed(0)
return `${p} %`
},
arc: function () {
let r = this._ratio // short hand
let deg = 2 * Math.PI * r
let x = 1 * Math.sin(deg)
let y = -1 * Math.cos(deg)
let negative = r < 0
let large = 0
// 0 ccw, 1 clock-wise
let rotation = negative ? 0 : 1
if (negative && x > 0) {
large = 1
} else if (!negative && x < 0) {
large = 1
}
return `A 1 1 0 ${large} ${rotation} ${x} ${y}`
},
path: function () {
return `M 0 -1 ${this.arc}`
}
},
methods: {
labelStyle: function (small) {
let size = small
? this.width / 13
: this.width / 10
return `font-size:${size}pt`
},
}
})

function ratioOK (val) {
return
}
</script>

<style scoped>
svg path, svg circle {
fill: transparent;
}
</style>
3 changes: 2 additions & 1 deletion app/core/store/index.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ store = new Vuex.Store({
updateFeatures: (state, features) -> state.features = features
}
modules: {
me: require('./modules/me')
me: require('./modules/me'),
game: require('./modules/game')
}
})

Expand Down
17 changes: 17 additions & 0 deletions app/core/store/modules/game.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
levelSchema = require('schemas/models/level')
api = require('core/api')

# TODO: Be explicit about the properties being stored
emptyLevel = _.zipObject(([key, null] for key in _.keys(levelSchema.properties)))

# This module should eventually include things such as: session, player code, score, thangs, etc
module.exports = {
namespaced: true
state: {
level: emptyLevel
}
mutations: {
updateLevel: (state, updates) ->
_.assign(state.level, $.extend(true, {}, updates))
}
}
11 changes: 8 additions & 3 deletions app/core/urls.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ module.exports =
return "/students/project-gallery/#{courseInstanceID}"

playDevLevel: ({level, session, course}) ->
shareURL = "#{window.location.origin}/play/#{level.get('type')}-level/#{level.get('slug')}/#{session.id}"
shareURL += "?course=#{course.id}" if course
level = level.attributes || level
session = session.attributes || session
course = course?.attributes || course
shareURL = "#{window.location.origin}/play/#{level.type}-level/#{level.slug}/#{session._id}"
shareURL += "?course=#{course._id}" if course
return shareURL

courseArenaLadder: ({level, courseInstance}) ->
"/play/ladder/#{level.get('slug')}/course/#{courseInstance.id}"
level = level.attributes || level
courseInstance = courseInstance.attributes || courseInstance
"/play/ladder/#{level.slug}/course/#{courseInstance._id}"

courseLevel: ({level, courseInstance}) ->
url = "/play/level/#{level.get('slug')}?course=#{courseInstance.get('courseID')}&course-instance=#{courseInstance.id}"
Expand Down
6 changes: 3 additions & 3 deletions app/lib/LevelBus.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ module.exports = class LevelBus extends Bus

onWinnabilityUpdated: (e) ->
return unless @onPoint() and e.winnable
return unless e.level.get('slug') in ['ace-of-coders', 'elemental-wars', 'the-battle-of-sky-span', 'tesla-tesoro', 'escort-duty'] # Mirror matches don't otherwise show victory, so we win here.
return unless e.level.get('slug') in ['ace-of-coders', 'elemental-wars', 'the-battle-of-sky-span', 'tesla-tesoro', 'escort-duty', 'treasure-games'] # Mirror matches don't otherwise show victory, so we win here.
return if @session.get('state')?.complete
@onVictory()

Expand Down Expand Up @@ -252,7 +252,7 @@ module.exports = class LevelBus extends Bus
# don't let what the server returns overwrite changes since the save began
tempSession = new LevelSession _id: @session.id
tempSession.save(patch, {patch: true, type: 'PUT'})

updateSessionConcepts: ->
return unless @session.get('codeLanguage') in ['javascript', 'python']
try
Expand All @@ -266,7 +266,7 @@ module.exports = class LevelBus extends Bus
# critical piece of code, so want to make sure this can fail gracefully.
console.error('Unable to parse concepts from this AST.')
console.error(e)


destroy: ->
clearInterval(@timerIntervalID)
Expand Down
2 changes: 1 addition & 1 deletion app/lib/LevelLoader.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ module.exports = class LevelLoader extends CocoClass
{target: 'public', access: 'write'}
]
codeLanguage: @fakeSessionConfig.codeLanguage or me.get('aceConfig')?.language or 'python'
_id: 'A Fake Session ID'
_id: LevelSession.fakeID
@session = new LevelSession initVals
@session.loaded = true
@fakeSessionConfig.callback? @session, @level
Expand Down
2 changes: 1 addition & 1 deletion app/lib/LevelSetupManager.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ module.exports = class LevelSetupManager extends CocoClass
@onInventoryModalPlayClicked()
return

if @level.get('assessment') is 'open-ended'
if @level.isSummative()
@onInventoryModalPlayClicked()
return

Expand Down
2 changes: 1 addition & 1 deletion app/lib/coursesHelper.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ module.exports =
sessions = _.filter sessionsForLevel, (session) ->
session.get('creator') is userID

courseProgress[levelID][userID].session = _.find(sessions, (s) -> s.completed()) or _.first(sessions)
courseProgress[levelID][userID].session = (_.find(sessions, (s) -> s.completed()) or _.first(sessions))?.toJSON()

if _.size(sessions) is 0 # haven't gotten to this level yet, but might have completed others before
courseProgress.started ||= false unless isOptional #no-op
Expand Down
6 changes: 0 additions & 6 deletions app/lib/surface/Surface.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -687,18 +687,12 @@ module.exports = Surface = class Surface extends CocoClass
return if @cinematic
@cinematic = true
@onResize()
if @heroLank and @options.levelType not in ['hero-ladder', 'course-ladder']
@previousCameraZoom = @camera.zoom
@camera.zoomTo @heroLank.sprite, Math.min(@camera.zoom * 2, 3), 3000

onCinematicPlaybackEnded: (e) ->
return unless @cinematic
@cinematic = false
@onResize()
_.delay @onResize, resizeDelay + 100 # Do it again just to be double sure that we don't stay zoomed in due to timing problems.
if @handleEvents
if @previousCameraZoom and @options.levelType not in ['hero-ladder', 'course-ladder']
@camera.zoomTo @camera.newTarget or @camera.target, @previousCameraZoom, 3000

onFlagColorSelected: (e) ->
@normalCanvas.add(@webGLCanvas).toggleClass 'flag-color-selected', Boolean(e.color)
Expand Down
12 changes: 9 additions & 3 deletions app/lib/world/GoalManager.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,13 @@ module.exports = class GoalManager extends CocoClass
goals = (g for g in goals when not g.optional)
goals = (g for g in goals when g.team in [undefined, @team]) if @team
statuses = (goal.status for goal in goals)
overallStatus = 'success' if statuses.length > 0 and _.every(statuses, (s) -> s is 'success' or (ignoreIncomplete and s is null))
overallStatus = 'failure' if statuses.length > 0 and 'failure' in statuses
#console.log 'got overallStatus', overallStatus, 'from goals', goals, 'goalStates', @goalStates, 'statuses', statuses
isSuccess = (s) -> s is 'success' or (ignoreIncomplete and s is null)
if _.any(goals.map((g) => g.concepts?.length))
conceptStatuses = goals.filter((g) => g.concepts?.length).map((g) => g.status)
levelStatuses = goals.filter((g) => !g.concepts?.length).map((g) => g.status)
overallStatus = if _.all(levelStatuses, isSuccess) and _.any(conceptStatuses, isSuccess) then 'success' else 'failure'
else
overallStatus = 'success' if statuses.length > 0 and _.every(statuses, isSuccess)
overallStatus

# WORLD GOAL TRACKING
Expand All @@ -143,6 +147,8 @@ module.exports = class GoalManager extends CocoClass
keyFrame: 0 # when it became a 'success' or 'failure'
team: goal.team
optional: goal.optional
hiddenGoal: goal.hiddenGoal
concepts: goal.concepts
}
@initGoalState(state, [goal.killThangs, goal.saveThangs], 'killed')
for getTo in goal.getAllToLocations ? []
Expand Down
Loading

0 comments on commit 7337e6d

Please sign in to comment.