mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Add picoCTF problem descriptions to levels; streamline picoCTF flows more
This commit is contained in:
parent
0905a378a0
commit
b5bb662ed2
13 changed files with 100 additions and 14 deletions
|
@ -64,6 +64,10 @@ module.exports = class LevelLoader extends CocoClass
|
|||
@level.get = ->
|
||||
return 'course' if arguments[0] is 'type'
|
||||
originalGet.apply @, arguments
|
||||
if window.serverConfig.picoCTF
|
||||
@supermodel.addRequestResource(url: '/picoctf/problems', success: (picoCTFProblems) =>
|
||||
@level?.picoCTFProblem = _.find picoCTFProblems, pid: @level.get('picoCTFProblem')
|
||||
).load()
|
||||
@loadSession() unless @sessionless
|
||||
@populateLevel()
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
#course-victory-modal
|
||||
#course-victory-modal, #picoctf-victory-modal
|
||||
|
||||
//- Top-level modal container
|
||||
.modal-dialog
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
|
||||
html.no-borderimage
|
||||
#course-victory-modal
|
||||
#course-victory-modal, #picoctf-victory-modal
|
||||
.modal-dialog
|
||||
margin-top: 251px
|
||||
.background-wrapper
|
||||
|
|
|
@ -44,6 +44,6 @@
|
|||
|
||||
if !me.get('anonymous')
|
||||
#play-footer(class=me.isPremium() ? "premium" : "")
|
||||
p(class='footer-link-text')
|
||||
p(class='footer-link-text').picoctf-hide
|
||||
a.contact-link(title='Send CodeCombat a message', tabindex=-1, data-i18n="nav.contact") Contact
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
span(data-i18n="courses.course_membership_required_to_play") You'll need to join a course to play this level.
|
||||
a.btn.btn-lg.btn-warning(data-i18n="courses.go_to_courses", href="/courses") Go To Courses
|
||||
|
||||
#tip-wrapper
|
||||
#tip-wrapper.picoctf-hide
|
||||
strong.tip(data-i18n='play_level.tip_toggle_play') Toggle play/paused with Ctrl+P.
|
||||
strong.tip(data-i18n='play_level.tip_scrub_shortcut') Ctrl+[ and Ctrl+] rewind and fast-forward.
|
||||
strong.tip(data-i18n='play_level.tip_guide_exists') Click the guide, inside game menu (at the top of the page), for useful info.
|
||||
|
|
26
app/templates/play/level/modal/picoctf-victory-modal.jade
Normal file
26
app/templates/play/level/modal/picoctf-victory-modal.jade
Normal file
|
@ -0,0 +1,26 @@
|
|||
.modal-dialog
|
||||
.background-wrapper
|
||||
.modal-content
|
||||
.modal-header
|
||||
#close-modal.well.well-sm.well-parchment(data-dismiss="modal")
|
||||
span.glyphicon.glyphicon-remove
|
||||
#victory-header
|
||||
#victory-title
|
||||
if !me.get('preferredLanguage') || me.get('preferredLanguage').split('-')[0] == 'en'
|
||||
img(src="/images/pages/play/level/modal/victory_word.png", draggable="false")
|
||||
else
|
||||
h1(data-i18n="play_level.victory") Victory
|
||||
|
||||
.modal-body
|
||||
.container-fluid
|
||||
.row
|
||||
- var victoryText = view.level.get('victory');
|
||||
- victoryText = {body: 'You have gotten busted'}
|
||||
if victoryText && victoryText.body
|
||||
.well.well-sm.well-parchment
|
||||
h3= victoryText.body
|
||||
|
||||
.row
|
||||
.col-sm-5.col-sm-offset-2
|
||||
.col-sm-5
|
||||
a(href="/play/picoctf")#done-btn.btn.btn-illustrated.btn-primary.btn-block.btn-lg.text-uppercase Done
|
|
@ -71,7 +71,7 @@ module.exports = class CampaignView extends RootView
|
|||
@levelPlayCountMap = {}
|
||||
@levelDifficultyMap = {}
|
||||
if window.serverConfig.picoCTF
|
||||
@supermodel.addRequestResource(url: '/picoctf/problems', success: @onPicoCTFProblemsLoaded).load()
|
||||
@supermodel.addRequestResource(url: '/picoctf/problems', success: (@picoCTFProblems) =>).load()
|
||||
else
|
||||
@sessions = @supermodel.loadCollection(new LevelSessionsCollection(), 'your_sessions', {cache: false}, 0).model
|
||||
@listenToOnce @sessions, 'sync', @onSessionsLoaded
|
||||
|
@ -280,7 +280,7 @@ module.exports = class CampaignView extends RootView
|
|||
level.locked = false if problem.unlocked
|
||||
level.description = """
|
||||
### #{problem.name}
|
||||
#{problem.description}
|
||||
#{level.description or problem.description}
|
||||
|
||||
#{problem.category} - #{problem.score} points
|
||||
""" # Skipping #{problem.hints}
|
||||
|
@ -439,8 +439,6 @@ module.exports = class CampaignView extends RootView
|
|||
onCampaignsLoaded: (e) ->
|
||||
@render()
|
||||
|
||||
onPicoCTFProblemsLoaded: (@picoCTFProblems) =>
|
||||
|
||||
preloadLevel: (levelSlug) ->
|
||||
levelURL = "/db/level/#{levelSlug}"
|
||||
level = new Level().setURL levelURL
|
||||
|
|
|
@ -85,7 +85,7 @@ module.exports = class ControlBarView extends CocoView
|
|||
@homeViewArgs.push leagueType
|
||||
@homeViewArgs.push leagueID
|
||||
@homeLink += "/#{leagueType}/#{leagueID}"
|
||||
else if @level.get('type', true) in ['hero', 'hero-coop']
|
||||
else if @level.get('type', true) in ['hero', 'hero-coop'] or window.serverConfig.picoCTF
|
||||
@homeLink = '/play'
|
||||
@homeViewClass = 'views/play/CampaignView'
|
||||
campaign = @level.get 'campaign'
|
||||
|
|
|
@ -78,6 +78,8 @@ module.exports = class LevelLoadingView extends CocoView
|
|||
@docs = @level.get('documentation') ? {}
|
||||
specific = @docs.specificArticles or []
|
||||
@intro = _.find specific, name: 'Intro'
|
||||
if window.serverConfig.picoCTF
|
||||
@intro ?= body: ''
|
||||
|
||||
showReady: ->
|
||||
return if @shownReady
|
||||
|
@ -170,7 +172,18 @@ module.exports = class LevelLoadingView extends CocoView
|
|||
|
||||
unveilIntro: =>
|
||||
return if @destroyed or not @intro or @unveiled
|
||||
html = marked utils.filterMarkdownCodeLanguages(utils.i18n(@intro, 'body'))
|
||||
if window.serverConfig.picoCTF and problem = @level.picoCTFProblem
|
||||
html = marked """
|
||||
### #{problem.name}
|
||||
|
||||
#{@intro.body}
|
||||
|
||||
#{problem.description}
|
||||
|
||||
#{problem.category} - #{problem.score} points
|
||||
""", sanitize: false
|
||||
else
|
||||
html = marked utils.filterMarkdownCodeLanguages(utils.i18n(@intro, 'body'))
|
||||
@$el.find('.intro-doc').removeClass('hidden').find('.intro-doc-content').html html
|
||||
@resize()
|
||||
|
||||
|
@ -194,7 +207,7 @@ module.exports = class LevelLoadingView extends CocoView
|
|||
onClickStartSubscription: (e) ->
|
||||
@openModalView new SubscribeModal()
|
||||
levelSlug = @level?.get('slug') or @options.level?.get('slug')
|
||||
# TODO: Added levelID on 2/9/16. Remove level property and associated AnalyticsLogEvent 'properties.level' index later.
|
||||
# TODO: Added levelID on 2/9/16. Remove level property and associated AnalyticsLogEvent 'properties.level' index later.
|
||||
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'level loading', level: levelSlug, levelID: levelSlug
|
||||
|
||||
onSubscribed: ->
|
||||
|
|
|
@ -37,6 +37,7 @@ DuelStatsView = require './DuelStatsView'
|
|||
VictoryModal = require './modal/VictoryModal'
|
||||
HeroVictoryModal = require './modal/HeroVictoryModal'
|
||||
CourseVictoryModal = require './modal/CourseVictoryModal'
|
||||
PicoCTFVictoryModal = require './modal/PicoCTFVictoryModal'
|
||||
InfiniteLoopModal = require './modal/InfiniteLoopModal'
|
||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||
ContactModal = require 'views/core/ContactModal'
|
||||
|
@ -535,6 +536,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
options = {level: @level, supermodel: @supermodel, session: @session, hasReceivedMemoryWarning: @hasReceivedMemoryWarning, courseID: @courseID, courseInstanceID: @courseInstanceID}
|
||||
ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder'] then HeroVictoryModal else VictoryModal
|
||||
ModalClass = CourseVictoryModal if @courseID and @courseInstanceID
|
||||
ModalClass = PicoCTFVictoryModal if window.serverConfig.picoCTF
|
||||
victoryModal = new ModalClass(options)
|
||||
@openModalView(victoryModal)
|
||||
if me.get('anonymous')
|
||||
|
|
18
app/views/play/level/modal/PicoCTFVictoryModal.coffee
Normal file
18
app/views/play/level/modal/PicoCTFVictoryModal.coffee
Normal file
|
@ -0,0 +1,18 @@
|
|||
ModalView = require 'views/core/ModalView'
|
||||
template = require 'templates/play/level/modal/picoctf-victory-modal'
|
||||
|
||||
module.exports = class PicoCTFVictoryModal extends ModalView
|
||||
id: 'picoctf-victory-modal'
|
||||
template: template
|
||||
closesOnClickOutside: false
|
||||
|
||||
initialize: (options) ->
|
||||
@session = options.session
|
||||
@level = options.level
|
||||
|
||||
# TODO: submit to picoCTF server
|
||||
|
||||
@playSound 'victory'
|
||||
|
||||
onLoaded: ->
|
||||
super()
|
|
@ -21,6 +21,7 @@ module.exports = class Spell
|
|||
@worker = options.worker
|
||||
@levelID = options.levelID
|
||||
@levelType = options.level.get('type', true)
|
||||
@level = options.level
|
||||
|
||||
p = options.programmableMethod
|
||||
@commentI18N = p.i18n
|
||||
|
@ -63,6 +64,7 @@ module.exports = class Spell
|
|||
setLanguage: (@language) ->
|
||||
#console.log 'setting language to', @language, 'so using original source', @languages[language] ? @languages.javascript
|
||||
@originalSource = @languages[@language] ? @languages.javascript
|
||||
@originalSource = @addPicoCTFProblem() if window.serverConfig.picoCTF
|
||||
|
||||
# Translate comments chosen spoken language.
|
||||
return unless @commentContext
|
||||
|
@ -91,6 +93,14 @@ module.exports = class Spell
|
|||
when 'io' then @originalSource.replace /loop\n/, 'while true,\n'
|
||||
else @originalSource
|
||||
|
||||
addPicoCTFProblem: ->
|
||||
return unless problem = @level.picoCTFProblem
|
||||
description = """
|
||||
-- #{problem.name} --
|
||||
#{problem.description}
|
||||
""".replace /<p>(.*?)<\/p>/gi, '$1'
|
||||
("// #{line}" for line in description.split('\n')).join('\n') + '\n' + @originalSource
|
||||
|
||||
addThang: (thang) ->
|
||||
if @thangs[thang.id]
|
||||
@thangs[thang.id].thang = thang
|
||||
|
|
|
@ -32,7 +32,7 @@ module.exports = class GameMenuModal extends ModalView
|
|||
context = super(context)
|
||||
docs = @options.level.get('documentation') ? {}
|
||||
submenus = ['guide', 'options', 'save-load', 'multiplayer']
|
||||
submenus = _.without submenus, 'guide' unless docs.specificArticles?.length or docs.generalArticles?.length
|
||||
submenus = _.without submenus, 'guide' unless docs.specificArticles?.length or docs.generalArticles?.length or window.serverConfig.picoCTF
|
||||
submenus = _.without submenus, 'save-load' unless me.isAdmin() or /https?:\/\/localhost/.test(window.location.href)
|
||||
submenus = _.without submenus, 'multiplayer' unless me.isAdmin() or (@level?.get('type') in ['ladder', 'hero-ladder', 'course-ladder'] and @level.get('slug') not in ['ace-of-coders', 'elemental-wars'])
|
||||
@includedSubmenus = submenus
|
||||
|
|
|
@ -15,6 +15,7 @@ module.exports = class LevelGuideView extends CocoView
|
|||
'click .start-subscription-button': 'clickSubscribe'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
@levelSlug = options.level.get('slug')
|
||||
@sessionID = options.session.get('_id')
|
||||
@requiresSubscription = not me.isPremium()
|
||||
|
@ -39,10 +40,10 @@ module.exports = class LevelGuideView extends CocoView
|
|||
@docs = specific.concat(general)
|
||||
@docs = $.extend(true, [], @docs)
|
||||
@docs = [@docs[0]] if @firstOnly and @docs[0]
|
||||
@addPicoCTFProblem() if window.serverConfig.picoCTF
|
||||
doc.html = marked(utils.filterMarkdownCodeLanguages(utils.i18n(doc, 'body'))) for doc in @docs
|
||||
doc.slug = _.string.slugify(doc.name) for doc in @docs
|
||||
doc.name = (utils.i18n doc, 'name') for doc in @docs
|
||||
super options
|
||||
|
||||
destroy: ->
|
||||
if @vimeoListenerAttached
|
||||
|
@ -89,7 +90,7 @@ module.exports = class LevelGuideView extends CocoView
|
|||
clickSubscribe: (e) ->
|
||||
level = @levelSlug # Save ref to level slug
|
||||
@openModalView new SubscribeModal()
|
||||
# TODO: Added levelID on 2/9/16. Remove level property and associated AnalyticsLogEvent 'properties.level' index later.
|
||||
# TODO: Added levelID on 2/9/16. Remove level property and associated AnalyticsLogEvent 'properties.level' index later.
|
||||
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'help video clicked', level: level, levelID: level
|
||||
|
||||
clickTab: (e) =>
|
||||
|
@ -158,3 +159,17 @@ module.exports = class LevelGuideView extends CocoView
|
|||
else
|
||||
window.attachEvent('onmessage', @onMessageReceived, false)
|
||||
@vimeoListenerAttached = true
|
||||
|
||||
addPicoCTFProblem: ->
|
||||
return unless problem = @options.level.picoCTFProblem
|
||||
@docs = [name: 'Intro', body: '', slug: 'intro'] unless @docs.length
|
||||
for doc in @docs when doc.name in ['Overview', 'Intro']
|
||||
doc.body += """
|
||||
### #{problem.name}
|
||||
|
||||
#{problem.description}
|
||||
|
||||
#{problem.category} - #{problem.score} points
|
||||
|
||||
Hint: #{problem.hints}
|
||||
""".replace /<p>(.*?)<\/p>/gi, '$1'
|
||||
|
|
Loading…
Reference in a new issue