codecombat/app/schemas/models/campaign.schema.coffee
Matt Lott d72e4eb750 Practice levels Ux and next level algorithm
Update classroom and gameplay Ux to surface practice levels as 3a, 3b,
etc.
Update next level logic to leverage practice levels based on per level
completion playtime thresholds.
Patrol buster and patrol buster A are live for testing.
Fix a few classroom Ux progress hover bubble info bugs.

Closes #3767
2016-06-27 14:05:42 -07:00

142 lines
6.1 KiB
CoffeeScript

c = require './../schemas'
CampaignSchema = c.object
default:
type: 'hero'
c.extendNamedProperties CampaignSchema # name first
_.extend CampaignSchema.properties, {
i18n: {type: 'object', title: 'i18n', format: 'i18n', props: ['name', 'fullName', 'description']}
fullName: { type: 'string', title: 'Full Name', description: 'Ex.: "Kithgard Dungeon"' }
description: { type: 'string', format: 'string', description: 'How long it takes and what players learn.' }
type: c.shortString(title: 'Type', description: 'What kind of campaign this is.', 'enum': ['hero', 'course'])
ambientSound: c.object {},
mp3: { type: 'string', format: 'sound-file' }
ogg: { type: 'string', format: 'sound-file' }
backgroundImage: c.array {}, {
type: 'object'
additionalProperties: false
properties: {
image: { type: 'string', format: 'image-file' }
width: { type: 'number' }
}
}
backgroundColor: { type: 'string' }
backgroundColorTransparent: { type: 'string' }
adjacentCampaigns: { type: 'object', format: 'campaigns', additionalProperties: {
title: 'Campaign'
type: 'object'
format: 'campaign'
properties: {
#- denormalized from other Campaigns, either updated automatically or fetched dynamically
id: { type: 'string', format: 'hidden' }
name: { type: 'string', format: 'hidden' }
description: { type: 'string', format: 'hidden' }
i18n: { type: 'object', format: 'hidden' }
slug: { type: 'string', format: 'hidden' }
#- normal properties
position: c.point2d()
rotation: { type: 'number', format: 'degrees' }
color: { type: 'string' }
showIfUnlocked: { type: 'string', links: [{rel: 'db', href: '/db/level/{($)}/version'}], format: 'latest-version-original-reference' }
}
}}
levelsUpdated: c.date()
levels: { type: 'object', format: 'levels', additionalProperties: {
title: 'Level'
type: 'object'
format: 'level'
additionalProperties: false
# key is the original property
properties: {
#- denormalized from Level
name: { type: 'string', format: 'hidden' }
description: { type: 'string', format: 'hidden' }
i18n: { type: 'object', format: 'hidden' }
requiresSubscription: { type: 'boolean' }
replayable: { type: 'boolean' }
type: {'enum': ['ladder', 'ladder-tutorial', 'hero', 'hero-ladder', 'hero-coop', 'course', 'course-ladder', 'game-dev']}
slug: { type: 'string', format: 'hidden' }
original: { type: 'string', format: 'hidden' }
adventurer: { type: 'boolean' }
practice: { type: 'boolean' }
practiceThresholdMinutes: {type: 'number'}
adminOnly: { type: 'boolean' }
disableSpaces: { type: ['boolean','number'] }
hidesSubmitUntilRun: { type: 'boolean' }
hidesPlayButton: { type: 'boolean' }
hidesRunShortcut: { type: 'boolean' }
hidesHUD: { type: 'boolean' }
hidesSay: { type: 'boolean' }
hidesCodeToolbar: { type: 'boolean' }
hidesRealTimePlayback: { type: 'boolean' }
backspaceThrottle: { type: 'boolean' }
lockDefaultCode: { type: ['boolean','number'] }
moveRightLoopSnippet: { type: 'boolean' }
realTimeSpeedFactor: { type: 'number' }
autocompleteFontSizePx: { type: 'number' }
requiredCode: c.array {}, {
type: 'string'
}
suspectCode: c.array {}, {
type: 'object'
properties: {
name: { type: 'string' }
pattern: { type: 'string' }
}
}
requiredGear: { type: 'object', additionalProperties: {
type: 'array'
items: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
}}
restrictedGear: { type: 'object', additionalProperties: {
type: 'array'
items: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
}}
allowedHeroes: { type: 'array', items: {
type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference'
}}
#- denormalized from Achievements
rewards: { type: 'array', items: {
type: 'object'
additionalProperties: false
properties:
achievement: { type: 'string', links: [{rel: 'db', href: '/db/achievement/{{$}}'}], format: 'achievement' }
item: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
hero: { type: 'string', links: [{rel: 'db', href: '/db/thang.type/{($)}/version'}], format: 'latest-version-original-reference' }
level: { type: 'string', links: [{rel: 'db', href: '/db/level/{($)}/version'}], format: 'latest-version-original-reference' }
type: { enum: ['heroes', 'items', 'levels'] }
}}
campaign: c.shortString title: 'Campaign', description: 'Which campaign this level is part of (like "desert").', format: 'hidden' # Automatically set by campaign editor.
campaignIndex: c.int title: 'Campaign Index', description: 'The 0-based index of this level in its campaign.', format: 'hidden' # Automatically set by campaign editor.
scoreTypes: c.array {title: 'Score Types', description: 'What metric to show leaderboards for.', uniqueItems: true},
c.shortString(title: 'Score Type', 'enum': ['time', 'damage-taken', 'damage-dealt', 'gold-collected', 'difficulty']) # TODO: good version of LoC; total gear value.
tasks: c.array {title: 'Tasks', description: 'Tasks to be completed for this level.'}, c.task
concepts: c.array {title: 'Programming Concepts', description: 'Which programming concepts this level covers.'}, c.concept
picoCTFProblem: { type: 'string', description: 'Associated picoCTF problem ID, if this is a picoCTF level' }
#- normal properties
position: c.point2d()
}
}}
}
c.extendBasicProperties CampaignSchema, 'campaign'
c.extendTranslationCoverageProperties CampaignSchema
c.extendPatchableProperties CampaignSchema
module.exports = CampaignSchema