Merge master

This commit is contained in:
Imperadeiro98 2016-02-27 08:07:59 +00:00
commit 02a91642fc
16 changed files with 302 additions and 241 deletions

View file

@ -41,6 +41,15 @@ module.exports.connectionFailure = connectionFailure = ->
)
showErrorModal(html)
module.exports.showNotyNetworkError = (jqxhr) ->
noty({
text: jqxhr.responseText or 'Unknown error'
layout: 'topCenter'
type: 'error'
killer: false,
dismissQueue: true
})
showErrorModal = (html) ->
# TODO: make a views/modal/error_modal view for this to use so the template can reuse templates/core/modal-base?
$('#modal-wrapper').html(html)

View file

@ -93,3 +93,12 @@ module.exports.clearFormAlerts = (el) ->
$('.alert.alert-warning', el).remove()
el.find('.help-block.error-help-block').remove()
el.find('.help-block.warning-help-block').remove()
module.exports.updateSelects = (el) ->
el.find('select').each (i, select) ->
value = $(select).attr('value')
$(select).val(value)
module.exports.validateEmail = (email) ->
filter = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$/i # https://news.ycombinator.com/item?id=5763990
return filter.test(email)

View file

@ -28,11 +28,17 @@ module.exports = class SpriteBuilder
anim.initialize(mode ? createjs.MovieClip.INDEPENDENT, startPosition ? 0, loops ? true, labels)
for tweenData in animData.tweens
tween = createjs.Tween
stopped = false
for func in tweenData
args = _.cloneDeep(func.a)
@dereferenceArgs(args, locals)
tween = tween[func.n](args...)
anim.timeline.addTween(tween)
if tween[func.n]
tween = tween[func.n](args...)
else
# If we, say, skipped a shadow get(), then the wait() may not be present
stopped = true
break
anim.timeline.addTween(tween) unless stopped
anim.nominalBounds = new createjs.Rectangle(animData.bounds...)
if animData.frameBounds

View file

@ -605,6 +605,14 @@
editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes."
about:
main_title:"If you want to learn to program, you need to write (a lot of) code."
main_description: "At CodeCombat, our job is to make sure you're doing that with a smile on your face."
mission_link: "Mission"
team_link: "Team"
community_link: "Community"
story_link: "Story"
careers_link: "Careers"
press_link: "Press"
mission_title: "Our mission: make programming accessible to every student on Earth."
mission_description_1: "Programming is magic. It's the ability to create things from pure imagination. We started CodeCombat to give learners the feeling of wizardly power at their fingertips by using typed code."
mission_description_2: "As it turns out, that enables them to learn faster too. WAY faster. It's like having a conversation instead of reading a manual. We want to bring that conversation to every school and to every student, because everyone should have the chance to learn the magic of programming."
@ -636,13 +644,15 @@
carlos_blurb: "Celery Man"
community_title: "...and our open-source community"
community_subtitle: "Over 450 contributors have helped build CodeCombat, with more joining every week!"
community_description_1: "CodeCombat is a community project, with hundreds of players volunteering to create levels, contribute to our code to add features, fix bugs, playtest, and even translate the game into 50 languages so far. Employees, contributors and the site gain by sharing ideas and pooling effort, as does the open source community in general. The site is built on numerous open source projects, and we are open sourced to give back to the community and provide code-curious players a familiar project to explore and experiment with. Anyone can join the CodeCombat community! Check out our "
community_description_link: "contribute page "
community_description_1: "CodeCombat is a community project, with hundreds of players volunteering to create levels, contribute to our code to add features, fix bugs, playtest, and even translate the game into 50 languages so far. Employees, contributors and the site gain by sharing ideas and pooling effort, as does the open source community in general. The site is built on numerous open source projects, and we are open sourced to give back to the community and provide code-curious players a familiar project to explore and experiment with. Anyone can join the CodeCombat community! Check out our"
community_description_link: "contribute page"
community_description_2: "for more info."
number_contributors: "Over 450 contributors have lent their support and time to this project."
story_title: "Our story so far"
story_subtitle: "Since 2013, CodeCombat has grown from a mere set of sketches to a living, thriving game."
story_statistic_1a: "5,000,000+"
story_statistic_1b: "total players"
story_statistic_1c: "have started their programming journey through CodeCombat"
story_statistic_2a: "Weve been translated into over 50 languages — our players hail from"
story_statistic_2b: "200+ countries"
story_statistic_3a: "Together, they have written"
@ -660,12 +670,13 @@
jobs_benefit_4: "Unlimited sick/personal days"
jobs_benefit_5: "Professional development and continuing education support"
jobs_benefit_6: "Medical/dental/vision insurance"
learn_more: "Learn More"
jobs_custom_title: "Create Your Own"
jobs_custom_description: "Are you passionate about CodeCombat but don't see a job listed that matches your qualifications? Write us and show how you think you can contribute to our team. We'd love to hear from you!"
jobs_custom_contact_1: "Send us a note at "
jobs_custom_contact_1: "Send us a note at"
jobs_custom_contact_2: "introducing yourself and we might get in touch in the future!"
contact_title: "Press & Contact"
contact_subtitle: "Need more information? Get in touch with us at "
contact_subtitle: "Need more information? Get in touch with us at"
screenshots_title: "Game Screenshots"
screenshots_hint: "(click to view full size)"
downloads_title: "Download Assets & Information"
@ -674,10 +685,10 @@
screenshots: "Screenshots"
character_art: "Character Art"
download_all: "Download All"
previous: "Previous"
next: "Next"
location_title: "We're located in downtown SF:"
teachers:
who_for_title: "Who is CodeCombat for?"
who_for_1: "We recommend CodeCombat for students aged 9 and up. No prior programming experience is needed. We've designed CodeCombat to appeal to both boys and girls."

View file

@ -32,7 +32,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
about: "소개"
contact: "문의"
twitter_follow: "팔로우"
teachers: "선생님"
teachers: "선생님"
careers: "채용"
modal:
@ -696,36 +696,36 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
shift: "Shift"
run_code: "현재 코드 실행"
run_real_time: "실시간 코드 실행"
# continue_script: "Continue past current script."
# skip_scripts: "Skip past all skippable scripts."
# toggle_playback: "Toggle play/pause."
# scrub_playback: "Scrub back and forward through time."
# single_scrub_playback: "Scrub back and forward through time by a single frame."
# scrub_execution: "Scrub through current spell execution."
# toggle_debug: "Toggle debug display."
# toggle_grid: "Toggle grid overlay."
# toggle_pathfinding: "Toggle pathfinding overlay."
# beautify: "Beautify your code by standardizing its formatting."
# maximize_editor: "Maximize/minimize code editor."
continue_script: "이미 끝난 현재 스크립트를 진행합니다."
skip_scripts: "모든 스킬할 스크립트를 지납니다."
toggle_playback: "플레이/일시중지 전환."
scrub_playback: "다시 스크럽을 통해 시간을 전달합니다."
single_scrub_playback: "다시 스크럽을 통해 단일 프레임으로 시간을 전달합니다."
scrub_execution: "현재 주문하는것을 통해 스크럽합니다."
toggle_debug: "디버그 화면 전환."
toggle_grid: "디버그 오버레이 전환"
toggle_pathfinding: "길 찾아주는 오버레이 전환."
beautify: "서식을 표준화하여 코드를 아름답게합니다."
maximize_editor: "코드 에디터 최대/최소."
community:
main_title: "코드 컴뱃 커뮤니티"
# introduction: "Check out the ways you can get involved below and decide what sounds the most fun. We look forward to working with you!"
# level_editor_prefix: "Use the CodeCombat"
# level_editor_suffix: "to create and edit levels. Users have created levels for their classes, friends, hackathons, students, and siblings. If create a new level sounds intimidating you can start by forking one of ours!"
# thang_editor_prefix: "We call units within the game 'thangs'. Use the"
# thang_editor_suffix: "to modify the CodeCombat source artwork. Allow units to throw projectiles, alter the direction of an animation, change a unit's hit points, or upload your own vector sprites."
# article_editor_prefix: "See a mistake in some of our docs? Want to make some instructions for your own creations? Check out the"
# article_editor_suffix: "and help CodeCombat players get the most out of their playtime."
# find_us: "Find us on these sites"
# social_github: "Check out all our code on GitHub"
# social_blog: "Read the CodeCombat blog on Sett"
# social_discource: "Join the discussion on our Discourse forum"
# social_facebook: "Like CodeCombat on Facebook"
# social_twitter: "Follow CodeCombat on Twitter"
# social_gplus: "Join CodeCombat on Google+"
# social_hipchat: "Chat with us in the public CodeCombat Slack channel"
# contribute_to_the_project: "Contribute to the project"
introduction: "아래에서 당신이 참여할 수있는 방법을 확인하고 가장 재미있어보이는것을 결정합니다. 우리는 당신과 함께 협력하는것을 기대합니다!"
level_editor_prefix: "코드컴뱃을 사용"
level_editor_suffix: "만들거나 수정하는 레벨입니다. 사용자들은 자신의 학급, 친구, 해커 톤, 학생, 형제 자매에 대한 수준을 만들어왔습니다. 만약 새로운 레벨 소리를 새로만들겠다면 우리중 하나를 포크해서 시작해도됩니다!"
thang_editor_prefix: "우리는 게임 내의 'thangs'을 유닛이라고 부릅니다."
thang_editor_suffix: " CodeCombat 소스 작품을 수정하여 사용합니다.유닛들이 발사체를 던지는것을 허용하며, 애니메이션의 방향을 변경하고, 유닛의 타격지점을 변경하거나, 우리의 벡터 스프라이트를 업로드 할 수도 있습니다."
article_editor_prefix: "우리의 문서가 틀린것을 보았나요? 자신의 작품에 대한 몇가지 지침을 원하십니까? 체크아웃을 하거나"
article_editor_suffix: "코드컴뱃 플레이어를 도와 자신의 플레이 시간을 최대한 활용하게해주십시오."
find_us: "이 사이트에서 우리를 찾기"
social_github: "GitHub에서 우리의 모든 코드를 체크아웃하기"
social_blog: "Sett의 코드컴뱃 블로그 읽기"
social_discource: "토론 포럼에서 토론에 참여하기"
social_facebook: "Facebook에서 코드컴뱃 좋아요하기"
social_twitter: "Twitter에서 코드컴뱃 팔로우하기"
social_gplus: "Google+로 코드컴뱃 참여하기"
social_hipchat: "공용 코드컴뱃 슬랙 체널에서 우리와 대화하기"
contribute_to_the_project: "프로젝트에 기여하기"
clans:
clan: "클랜"
@ -733,16 +733,16 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
new_name: "새로운 클랜 이름"
new_description: "새로운 클랜 설명"
make_private: "클랜을 비공개로 만들기"
# subs_only: "subscribers only"
subs_only: "오직 구독자만"
create_clan: "새로운 클랜 만들기"
private_preview: "미리보기"
# private_clans: "Private Clans"
private_clans: "비공개 클랜"
public_clans: "공개 클랜들"
my_clans: "내가 속한 클랜"
clan_name: "클랜 이름"
name: "이름"
chieftain: "클랜장"
# type: "Type"
type: "유형"
edit_clan_name: "클랜 이름 수정"
edit_clan_description: "클랜 설명 수정"
edit_name: "이름 변경"
@ -757,55 +757,55 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
invite_1: "초대:"
invite_2: "*링크를 보내 클랜 초대하기"
members: "멤버들"
# progress: "Progress"
# not_started_1: "not started"
# started_1: "started"
# complete_1: "complete"
# exp_levels: "Expand levels"
progress: "진행"
not_started_1: "시작되지않음"
started_1: "시작됨"
complete_1: "완료"
exp_levels: "레벨 확장"
rem_hero: "영웅 삭제"
status: "상태"
# complete_2: "Complete"
# started_2: "Started"
# not_started_2: "Not Started"
# view_solution: "Click to view solution."
# view_attempt: "Click to view attempt."
# latest_achievement: "Latest Achievement"
# playtime: "Playtime"
# last_played: "Last played"
# leagues_explanation: "Play in a league against other clan members in these multiplayer arena instances."
# track_concepts1: "Track concepts"
# track_concepts2a: "learned by each student"
# track_concepts2b: "learned by each member"
# track_concepts3a: "Track levels completed for each student"
# track_concepts3b: "Track levels completed for each member"
# track_concepts4a: "See your students'"
# track_concepts4b: "See your members'"
# track_concepts5: "solutions"
# track_concepts6a: "Sort students by name or progress"
# track_concepts6b: "Sort members by name or progress"
# track_concepts7: "Requires invitation"
# track_concepts8: "to join"
# private_require_sub: "Private clans require a subscription to create or join."
complete_2: "완료"
started_2: "시작됨"
not_started_2: "시작되지않음"
view_solution: "해결책을 보려면 클릭."
view_attempt: "시도를 보려면 클릭."
latest_achievement: "최신 도전과제"
playtime: "플레이타임"
last_played: "마지막으로 플레이한"
leagues_explanation: "이러한 멀티 분야인 경우에는 다른 클랜들에 대한 리그에서 플레이합니다."
track_concepts1: "트랙 컨셉"
track_concepts2a: "학생으로부터 학습됨"
track_concepts2b: "맴버로부터 학습됨"
track_concepts3a: "각자 학생들로부터 트랙 레벨이 완료됨"
track_concepts3b: "각자 맴버들로부터 트랙 레벨이 완료됨"
track_concepts4a: "당신의 학생 보기'"
track_concepts4b: "당신의 맴버 보기'"
track_concepts5: "솔루션"
track_concepts6a: "이름이나 진행상황으로 정렬된 학생들"
track_concepts6b: "이름이나 진행상황으로 정렬된 맴버들"
track_concepts7: "초대장 필요"
track_concepts8: "으로 참여"
private_require_sub: "비공개 클랜을 만들거나 참여해서 구독하는것을 권장합니다."
# courses:
# course: "Course"
# courses: "courses"
# create_new_class: "Create New Class"
# not_enrolled: "You are not enrolled in this course."
# visit_pref: "Please visit the"
# visit_suf: "page to enroll."
# select_class: "Select one of your classes"
# unnamed: "*unnamed*"
# select: "Select"
# unnamed_class: "Unnamed Class"
# edit_settings: "edit class settings"
# edit_settings1: "Edit Class Settings"
# progress: "Class Progress"
# add_students: "Add Students"
# stats: "Statistics"
# total_students: "Total students:"
# average_time: "Average level play time:"
# total_time: "Total play time:"
courses:
course: "코스"
courses: "코스들"
create_new_class: "새로운 클래스 만들기"
not_enrolled: "이 과정에 등록 되지 않습니다."
visit_pref: "등록 페이지를"
visit_suf: "방문하십시오."
select_class: "당신의 클래스 중 하나를 선택하십시오"
unnamed: "*이름없음*"
select: "선택"
unnamed_class: "이름없는 클래스"
edit_settings: "클래스 세팅 수정"
edit_settings1: "클래스 세팅 수정"
progress: "클래스 진행상황"
add_students: "학생 추가"
stats: "통계"
total_students: "총 학생:"
average_time: "평균 수준의 플레이 시간:"
total_time: "총 플레이 시간:"
# average_levels: "Average levels completed:"
# total_levels: "Total levels completed:"
# furthest_level: "Furthest level completed:"
@ -1015,22 +1015,22 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
classes:
archmage_title: "대마법사"
archmage_title_description: "(코더)"
# archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!"
archmage_summary: "당신이 만약 코딩 교육 게임에 관심있는 개발자라면, 코드컴뱃을 돕는 대마법사가 되어주십시오!"
artisan_title: "장인"
artisan_title_description: "(레벨 제작자)"
# artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program."
artisan_summary: "레벨을 만들거나 공유하여 당신과 친구들이 플레이합니다. 다른 프로그램을 가르치는 예술 장인이 되어보십시오!"
adventurer_title: "모험가"
adventurer_title_description: "(레벨 테스터)"
# adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release."
adventurer_summary: "우리의 새로운 레벨을 (심지어 구독자의 컨텐츠도) 일주일 먼저 무료로 얻을 수 있고 공개 릴리즈 전에 버그를 제보하여 우리를 도와주십시오."
scribe_title: "작가"
scribe_title_description: "(기사 에디터)"
# scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe."
scribe_summary: "좋은 코드는 좋은 문서가 필요합니다. 쓰기, 편집하고, 전 세계의 수백만 플레이어에 의해 판독된 문서를 향상시킬 수 있습니다."
diplomat_title: "외교관"
diplomat_title_description: "(번역가)"
# diplomat_summary: "CodeCombat is localized in 45+ languages by our Diplomats. Help us out and contribute translations."
diplomat_summary: "코드컴뱃은 Diplomats에 의해 45+ 언어로 지역화되었습니다. 우리를 도와 번역에 기여하십시오."
ambassador_title: "대사"
ambassador_title_description: "(지원)"
# ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
ambassador_summary: "포럼 사용자를 관리하는것과 질문들에 대한 방향을 제공합니다. 우리의 대사는 세계에 코드컴뱃을 나타냅니다."
editor:
main_title: "코드 컴뱃 에디터들"
@ -1038,7 +1038,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
thang_title: "Thang 에디터"
level_title: "레벨 에디터"
achievement_title: "업적 에디터"
# poll_title: "Poll Editor"
poll_title: "투표 에디터"
back: "뒤로"
revert: "되돌리기"
revert_models: "모델 되돌리기"
@ -1047,34 +1047,34 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
indoor: "내부"
desert: "사막"
grassy: "풀로 덮인"
# mountain: "Mountain"
# glacier: "Glacier"
mountain: ""
glacier: "빙하"
small: "작게"
large: "크게"
fork_title: "새 버전 가져오기"
fork_creating: "포크 생성중..."
# generate_terrain: "Generate Terrain"
generate_terrain: "지형 생성"
more: "더 보기"
wiki: "위키"
live_chat: "실시간 채팅"
# thang_main: "Main"
# thang_spritesheets: "Spritesheets"
# thang_colors: "Colors"
thang_main: "메인"
thang_spritesheets: "스프라이트시트"
thang_colors: "색갈"
level_some_options: "다른 옵션들?"
level_tab_thangs: "Thangs"
level_tab_scripts: "스크립트들"
level_tab_settings: "설정"
level_tab_components: "요소들"
level_tab_systems: "시스템"
# level_tab_docs: "Documentation"
level_tab_docs: "문서"
level_tab_thangs_title: "현재 Thangs"
# level_tab_thangs_all: "All"
level_tab_thangs_all: "모두"
level_tab_thangs_conditions: "컨디션 시작"
level_tab_thangs_add: "Thangs 추가"
# level_tab_thangs_search: "Search thangs"
# add_components: "Add Components"
# component_configs: "Component Configurations"
# config_thang: "Double click to configure a thang"
level_tab_thangs_search: "thangs 검색"
add_components: "구성요소 추가"
component_configs: "환경설정 구성요소"
config_thang: "thang을 설정하려면 더블클릭"
delete: "삭제"
duplicate: "복제"
stop_duplicate: "복제 중지"

View file

@ -15,9 +15,10 @@ $forest: #20572B
.style-flat
background: white
color: black
// Fonts
h1, h2, h3, h4, h5, h6
h1, h2, h3, h4, h5, h6, .text-h1, .text-h2, .text-h3, .text-h4, .text-h5, .text-h6
// Unsetting game styles
font-variant: normal
color: black
@ -200,6 +201,9 @@ $forest: #20572B
a.btn-primary-alt
color: $navy
// base-flat.jade
#footer
background-image: url("/images/pages/home/footer_background.png")
height: 229px
@ -237,3 +241,16 @@ $forest: #20572B
img
width: 150px
margin: 0 10px
// modal-base-flat.jade
&.modal-content
padding: 10px
border-radius: 0
box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5)
.button.close
position: absolute
top: 10px
left: 10px

View file

@ -7,60 +7,49 @@ block content
.row
//TODO: Size these correctly
.col-xs-10
h1 If you want to learn to program, you need to write (a lot of) code.
h1(data-i18n="about.main_title")
.row
.col-xs-8
h2 At CodeCombat, our job is to make sure you're doing that with a smile on your face.
h2(data-i18n="about.main_description")
#nav-container
nav#fixed-nav.nav.navbar
.container-fluid.text-center
ul.center-block
li.active
a(href="#mission")#mission-link
a(href="#mission")#mission-link
small.label(data-i18n="about.mission_link")
| Mission
li
a(href="#team")#team-link
small.label(data-i18n="about.team_link")
| Team
li
a(href="#community")#community-link
small.label(data-i18n="about.community_link")
| Community
li
a(href="#story")#story-link
small.label(data-i18n="about.story_link")
| Story
li
a(href="#jobs")#jobs-link
small.label(data-i18n="about.jobs_link")
| Careers
small.label(data-i18n="about.careers_link")
li
a(href="#contact")#contact-link
small.label(data-i18n="about.contact_link")
| Press
small.label(data-i18n="about.press_link")
#about-container.container
#mission.anchor.row
.col-sm-6#mission-graphic.responsive-side-margins
img(src="/images/pages/about/globe_white.png")
h2(data-i18n="about.mission_title")
| Our mission: make programming accessible to every student on Earth.
#mission-graphic-filler
.col-sm-5.col-sm-offset-1
#mission-text.responsive-side-margins
p(data-i18n="about.mission_description_1")
| Programming is magic. It's the ability to create things from pure imagination. We started CodeCombat to give learners the feeling of wizardly power at their fingertips by using typed code.
p(data-i18n="about.mission_description_2")
| As it turns out, that enables them to learn faster too. WAY faster. It's like having a conversation instead of reading a manual. We want to bring that conversation to every school and to every student, because everyone should have the chance to learn the magic of programming.
#team.anchor
.text-center
h3(data-i18n="about.team_title")
| Meet the CodeCombat team
h4.responsive-side-margins(data-i18n="about.team_values")
| We value open and respectful dialog, where the best idea wins. Our decisions are grounded in customer research and our process is focused on delivering tangible results for them. Everyone is hands-on, from our CEO to our Github contributors, because we value growth and learning in our team.
ul
// Full time
li
@ -104,9 +93,7 @@ block content
small(data-i18n="about.maka_title")
small(data-i18n="about.maka_blurb")
a(href="http://basicer.com/" rel="external")
li
li
a(href="http://basicer.com/" rel="external")
img(src="/images/pages/about/rob_small.png").img-thumbnail
.team-bio
@ -122,8 +109,6 @@ block content
small(data-i18n="about.josh_c_title")
small(data-i18n="about.josh_c_blurb")
a(href="http://robinyang.com/" rel="external")
li
a(href="http://robinyang.com/" rel="external")
img(src="/images/pages/about/robin_small.png").img-thumbnail
@ -135,7 +120,6 @@ block content
// Part time / contract
li
a(href="http://floor.is/lava/" rel="external")
img(src="/images/pages/about/josh_small.png").img-thumbnail
@ -178,120 +162,94 @@ block content
h6.label.team-name Carlos Maia
small(data-i18n="about.carlos_title")
small(data-i18n="about.carlos_blurb")
#community.anchor
#community-row-1.row.text-center
.col-sm-12
.text-center
h3(data-i18n="about.community_title")
| ...and our open-source community
h4(data-i18n="about.community_subtitle")
| Over 450 contributors have helped build CodeCombat, with more joining every week!
img(src="/images/pages/about/github_avatars.png")#community-avatars
#community-row-2.row
.col-sm-5
p.responsive-side-margins
span(data-i18n="about.community_description_1")
| CodeCombat is a community project, with hundreds of players volunteering to create levels, contribute to our code to add features, fix bugs, playtest, and even translate the game into 50 languages so far. Employees, contributors and the site gain by sharing ideas and pooling effort, as does the open source community in general. The site is built on numerous open source projects, and we are open sourced to give back to the community and provide code-curious players a familiar project to explore and experiment with. Anyone can join the CodeCombat community! Check out our
a(href="/contribute")
span.spr(data-i18n="about.community_description_1")
a(href="/contribute")
span(data-i18n="about.community_description_link")
| contribute page
span(data-i18n="about.community_description_2")
| for more info.
span.spl(data-i18n="about.community_description_2")
.col-sm-6.col-sm-offset-1#community-graphic.responsive-side-margins
h2 Over 450 contributors have lent their support and time to this project.
h2(data-i18n="about.number_contributors")
img(src="/images/pages/about/github.png")
#community-graphic-filler
#story.anchor
.text-center
h3(data-i18n="about.story_title")
| Our story so far
h4.responsive-side-margins(data-i18n="about.story_subtitle")
| Since 2013, CodeCombat has grown from a mere set of sketches to a living, thriving game.
.row
#story-graphic-1.col-lg-6
.media
.pull-left
img.media-object#story-image-1(src="/images/pages/about/Character_Silouhette.png")
img.media-object#story-image-1(src="/images/pages/about/character_silouhette.png")
.media-body
.media-heading.text-h1
span(data-i18n="about.story_statistic_1a")
| 5,000,000+
br
span(data-i18n="about.story_statistic_1b")
| total players
p.text-h5 have started their programming journey through CodeCombat
p.text-h5(data-i18n="about.story_statistic_1c")
.col-lg-5.col-lg-offset-1
#story-graphic-2
.media
p.text-h5(data-i18n="about.story_statistic_2a")
| Weve been translated into over 50 languages — our players hail from
.pull-right
img(src="/images/pages/about/globe_green.png")
.media-body
.media-heading.text-h1(data-i18n="about.story_statistic_2b")
| 200+ countries
#story-graphic-3.text-center
p
div.text-h5(data-i18n="about.story_statistic_3a")
| Together, they have written
#story-bracketed-text
div#left-bracket
img(src="/images/pages/about/bracket_left.png")
div.text-h1(data-i18n="about.story_statistic_3b")
| 1 billion lines of code and counting
div#right-bracket
img(src="/images/pages/about/bracket_right.png")
#story-languages
.text-center
.text-h5(data-i18n="about.story_statistic_3c")
| across six different programming languages
#language-icons.text-center
img.hidden-xs(src="/images/pages/about/Languages.png")
img.hidden-sm.hidden-md.hidden-lg(src="/images/pages/about/Languages_group1.png")
img.hidden-sm.hidden-md.hidden-lg(src="/images/pages/about/Languages_group2.png")
img.hidden-xs(src="/images/pages/about/languages.png")
img.hidden-sm.hidden-md.hidden-lg(src="/images/pages/about/languages_group1.png")
img.hidden-sm.hidden-md.hidden-lg(src="/images/pages/about/languages_group2.png")
#story-graphic-4.text-center
p
div.text-h5(data-i18n="about.story_long_way_1")
| Though we've come a long way...
figure
img(src="/images/pages/about/sketch.png")
figcaption
small(data-i18n="about.story_sketch_caption")
| Nick's very first sketch depicting a programming game in action.
p
.text-h5(data-i18n="about.story_long_way_2")
| we still have much to do before we complete our quest, so...
#jobs.anchor
.text-center
h3(data-i18n="about.jobs_title")
| Come work with us and help write CodeCombat history!
h4(data-i18n="about.jobs_subtitle")
| Don't see a good fit but interested in keeping in touch? See our "Create Your Own" listing.
#jobs-row.row
.col-sm-6.col-md-5.col-md-offset-1.col-lg-4.col-lg-offset-0
#benefits
h5(data-i18n="about.jobs_benefits")
| Employee Benefits
ul
li.small(data-i18n="about.jobs_benefit_1")
| Competitive salary and options
li.small(data-i18n="about.jobs_benefit_2")
| 15 day minimum vacation policy, excluding company holidays
li.small(data-i18n="about.jobs_benefit_3")
| Work from home flexibility
li.small(data-i18n="about.jobs_benefit_4")
| Unlimited sick/personal days
li.small(data-i18n="about.jobs_benefit_5")
| Professional development and continuing education support
li.small(data-i18n="about.jobs_benefit_6")
| Medical/dental/vision insurance
.col-sm-6.col-md-5.col-lg-4
.job-listing
h5 Software Engineer, iOS
@ -300,56 +258,48 @@ block content
| San Francisco • Fulltime
p.small Want to write the first iPad app for CodeCombat? Were looking for a product-focused engineer to translate our core gameplay and educational tools into an experience that feels like it was born on the iPad.
a.job-link.btn.btn-lg.btn-navy(href="https://jobs.lever.co/codecombat/eb190007-7195-49ee-a322-893b0d1cdcb4" rel="external")
| Learn More
span(data-i18n="about.learn_more")
.col-sm-6.col-md-5.col-md-offset-1.col-lg-4.col-lg-offset-0
.job-listing
h5 Head of Sales
.text-center
small.label
| San Francisco • Fulltime
p.small School districts are scrambling to offer computer science classes to all their students as a core subject. They have had no solution, because they can't afford to hire enough programming teachers until now.
p.small School districts are scrambling to offer computer science classes to all their students as a core subject. They have had no solution, because they can't afford to hire enough programming teachers until now.
a.job-link.btn.btn-lg.btn-navy(href="https://jobs.lever.co/codecombat/2d0194ed-7c69-4aab-b1f9-363ca4b9f04b" rel="external")
| Learn More
span(data-i18n="about.learn_more")
.col-sm-6.col-md-5.col-lg-4
.job-listing
h5 Sales Representative
.text-center
small.label
| San Francisco • Fulltime
p.small School districts are scrambling to offer computer science classes to all their students as a core subject. They have had no solution, because they can't afford to hire enough programming teachers until now.
p.small School districts are scrambling to offer computer science classes to all their students as a core subject. They have had no solution, because they can't afford to hire enough programming teachers until now.
a.job-link.btn.btn-lg.btn-navy(href="https://jobs.lever.co/codecombat/3f6ff123-16ce-4ecb-aba3-dcf4e8927c47" rel="external")
| Learn More
span(data-i18n="about.learn_more")
.col-sm-6.col-md-5.col-md-offset-1.col-lg-4.col-lg-offset-0
.job-listing
h5(data-i18n="about.jobs_custom_title")
| Create Your Own
p.small(data-i18n="about.jobs_custom_description")
| Are you passionate about CodeCombat but don't see a job listed that matches your qualifications? Write us and show how you think you can contribute to our team. We'd love to hear from you!
p.small
span(data-i18n="about.jobs_custom_contact_1")
| Send us a note at
span.spr(data-i18n="about.jobs_custom_contact_1")
a(href="mailto:team@codecombat.com")
| team@codecombat.com
span(data-i18n="about.jobs_custom_contact_2")
| introducing yourself and we might get in touch in the future!
| team@codecombat.com
span.spl(data-i18n="about.jobs_custom_contact_2")
#contact.anchor
.text-center
h3(data-i18n="about.contact_title")
| Press & Contact
h4(data-i18n="about.contact_subtitle")
| Need more information? Get in touch with us at
a(href="mailto:team@codecombat.com") team@codecombat.com
a(href="mailto:team@codecombat.com") team@codecombat.com
#files
.row
.col-md-6.col-lg-8
#screenshots
span.label(data-i18n="about.screenshots_title")
| Game Screenshots
.hidden-sm.hidden-md.hidden-lg
small(data-i18n="about.screenshots_hint")
| (click to view full size)
#screenshot-grid
a.screen-thumbnail(data-toggle="modal", data-target="#screenshot-lightbox", data-index='0')
img(src="/images/pages/about/screenshot_desert.png")
@ -361,44 +311,36 @@ block content
img(src="/images/pages/about/screenshot_glacier.png")
.clearfix.hidden-xs
small(data-i18n="about.screenshots_hint")
| (click to view full size)
.col-md-6.col-lg-4
#downloads-container
#downloads
.label(data-i18n="about.downloads_title")
| Download Assets & Information
ul
li
a.small(href="http://files.codecombat.com/presspack/AboutCodeCombat.pdf")
span(data-i18n="about.about_codecombat")
| About CodeCombat
| (.pdf)
li
a.small(href="http://files.codecombat.com/presspack/CodeCombat-Logo.ai")
span(data-i18n="about.logo")
| Logo
| (.ai)
li
a.small(href="http://files.codecombat.com/presspack/CodeCombat-Logo.png")
span(data-i18n="about.logo")
| Logo
| (.png)
li
a.small(href="http://files.codecombat.com/presspack/GameImages.zip")
span(data-i18n="about.screenshots")
| Screenshots
| (.zip)
li
a.small(href="http://files.codecombat.com/presspack/gameimages/CodeCombat_Splash.png")
span(data-i18n="about.character_art")
| Character Art
| (.png)
.text-center
a.btn.btn-lg.btn-primary-alt#download-button(href="http://files.codecombat.com/presspack/CodeCombat_PressPack.zip")
span.glyphicon.glyphicon-download-alt
span(data-i18n="about.download_all")
| Download All
#screenshot-lightbox.modal.fade(data-show="false")
.modal-dialog
.modal-content
@ -408,23 +350,23 @@ block content
li(data-target=".screenshot-display", data-slide-to="1")
li(data-target=".screenshot-display", data-slide-to="2")
li(data-target=".screenshot-display", data-slide-to="3")
.carousel-inner
.item.active
img#screenshot-desert(src="/images/pages/about/Desert.png")
img#screenshot-desert(src="/images/pages/about/desert.png")
.item
img#screenshot-forest(src="/images/pages/about/Forest.png")
img#screenshot-forest(src="/images/pages/about/forest.png")
.item
img#screenshot-dungeon(src="/images/pages/about/Dungeon.png")
img#screenshot-dungeon(src="/images/pages/about/dungeon.png")
.item
img#screenshot-glacier(src="/images/pages/about/Glacier.png")
img#screenshot-glacier(src="/images/pages/about/glacier.png")
a#carousel-left.left.carousel-control(href="#screenshot-carousel", role="button")
span.glyphicon.glyphicons-chevron-left.glyphicon-chevron-left(aria-hidden="true")
span.sr-only Previous
span.sr-only(data-i18n="about.previous")
a#carousel-right.right.carousel-control(href="#screenshot-carousel", role="button")
span.glyphicon.glyphicons-chevron-right.glyphicon-chevron-right(aria-hidden="true")
span.sr-only Next
span.sr-only(data-i18n="about.next")
#location
.row
.col-sm-4.col-sm-offset-2
@ -437,5 +379,4 @@ block content
.col-sm-4
p
b(data-i18n="about.location_title")
| We're located in downtown SF:
iframe(width="370", height="280", frameBorder="2", src="https://www.google.com/maps/embed/v1/place?key=AIzaSyAIGQz3OMbv5YWivScUM86-zESjEgJR2Xo&q=360+3rd+St+Suite+700,+San+Francisco,+CA+94107")

View file

@ -24,13 +24,7 @@ block content
th Phone
th Status
tbody
- var numReviewed = 0
- var maxReviewedShown = 1000
each trialRequest in trialRequests
if trialRequest.get('status') !== 'submitted'
- numReviewed++
if numReviewed > maxReviewedShown
- break
tr
td.created= trialRequest.get('created').substring(0, 10)
td.reviewed

View file

@ -1,5 +1,8 @@
#loading-error.text-center
if jqxhr.status === 401
if !jqxhr
h1(data-i18n="loading_error.unknown")
else if jqxhr.status === 401
h1
span.spr 401:
span(data-i18n="loading_error.login_required")

View file

@ -6,7 +6,7 @@ module.exports = class AboutView extends RootView
template: template
logoutRedirectURL: false
events:
'click #mission-link': 'onClickMissionLink'
'click #team-link': 'onClickTeamLink'
@ -17,12 +17,12 @@ module.exports = class AboutView extends RootView
'click .screen-thumbnail': 'onClickScreenThumbnail'
'click #carousel-left': 'onLeftPressed'
'click #carousel-right': 'onRightPressed'
shortcuts:
'right': 'onRightPressed'
'left': 'onLeftPressed'
'esc': 'onEscapePressed'
afterRender: ->
super(arguments...)
@$('#fixed-nav').affix({
@ -36,36 +36,36 @@ module.exports = class AboutView extends RootView
offset: 150
)
@$('#screenshot-lightbox').modal()
@$('#screenshot-carousel').carousel({
interval: 0
keyboard: false
})
onClickMissionLink: (event) ->
event.preventDefault()
@scrollToLink('#mission')
onClickTeamLink: (event) ->
event.preventDefault()
@scrollToLink('#team')
onClickCommunityLink: (event) ->
event.preventDefault()
@scrollToLink('#community')
onClickStoryLink: (event) ->
event.preventDefault()
@scrollToLink('#story')
onClickJobsLink: (event) ->
event.preventDefault()
@scrollToLink('#jobs')
onClickContactLink: (event) ->
event.preventDefault()
@scrollToLink('#contact')
onRightPressed: (event) ->
# Special handling, otherwise after you click the control, keyboard presses move the slide twice
return if event.type is 'keydown' and $(document.activeElement).is('.carousel-control')
@ -78,7 +78,7 @@ module.exports = class AboutView extends RootView
if $('#screenshot-lightbox').data('bs.modal')?.isShown
event.preventDefault()
$('#screenshot-carousel').carousel('prev')
onEscapePressed: (event) ->
if $('#screenshot-lightbox').data('bs.modal')?.isShown
event.preventDefault()
@ -89,5 +89,3 @@ module.exports = class AboutView extends RootView
event.preventDefault()
# Modal opening happens automatically from bootstrap
$('#screenshot-carousel').carousel($(event.currentTarget).data("index"))

View file

@ -55,7 +55,7 @@ module.exports = class NewHomeView extends RootView
middle: {'introduction-to-computer-science': '1-3', 'computer-science-5': '7-10', default: '5-8', total: '25-35 hours (about one semester)'}
high: {'introduction-to-computer-science': '1', 'computer-science-5': '6-9', default: '5-6', total: '22-28 hours (about one semester)'}
level = if e then $(e.target).val() else 'middle'
@$el.find('#courses-container .course-details').each ->
@$el.find('#courses-row .course-details').each ->
slug = $(@).data('course-slug')
duration = levels[level][slug] or levels[level].default
$(@).find('.course-duration .course-hours').text duration

View file

@ -18,9 +18,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
super options
@showMoreCancellations = false
@resetSubscriptionsData()
if me.isAdmin()
@refreshData()
_.delay (=> @refreshData()), 30 * 60 * 1000
@refreshData() if me.isAdmin()
getRenderData: ->
context = super()

View file

@ -138,7 +138,10 @@ module.exports = class LevelGuideView extends CocoView
tag.height = @helpVideoHeight
tag.width = @helpVideoWidth
tag.allowFullscreen = true
@$el.find('#help-video-player').replaceWith(tag)
tag.mozAllowFullscreen = true
$tag = $(tag)
$tag.attr('webkitallowfullscreen', true) # strong arm Safari into working
@$el.find('#help-video-player').replaceWith($tag)
@onMessageReceived = (e) =>
data = JSON.parse(e.data)

50
server/lib/closeIO.coffee Normal file
View file

@ -0,0 +1,50 @@
config = require '../../server_config'
log = require 'winston'
request = require 'request'
apiKey = config.closeIO?.apiKey
module.exports =
logError: (msg) ->
log.error("Close.io Error: #{msg}")
createSalesLead: (user, email, newLeadData) ->
return @logError('No API key available') unless apiKey
@getLead email, (error, lead) =>
return @logError(JSON.stringify(error)) if error
return if lead
@createLead(user, email, newLeadData)
createLead: (user, email, newLeadData) ->
name = newLeadData.name ? email
postData =
display_name: newLeadData.organization ? name
name: newLeadData.organization ? name
contacts: [{
emails: [{email: email}]
name: name
}]
custom: {}
postData.contacts[0].phones = [phone: newLeadData.phone] if newLeadData.phone
for key, val of newLeadData
continue if key in ['name', 'organization', 'phone']
continue if _.isEmpty(val)
postData.custom[key] = val
postData.custom['userID'] = user.get('_id').valueOf() if user
options =
uri: 'https://' + apiKey + ':X@app.close.io/api/v1/lead/',
body: JSON.stringify(postData)
request.post options, (error, response, body) =>
return @logError(JSON.stringify(error)) if error
getLead: (email, done) ->
uri = 'https://' + apiKey + ':X@app.close.io/api/v1/lead/?query=email_address:' + email
request.get uri, (error, response, body) =>
return done(error) if error
leads = JSON.parse(body)
return done("Unexpected leads format: " + body) unless leads.data?
if leads.data?.length is 1
return done(null, leads.data[0])
else if leads.data?.length > 1
return done('ERROR: multiple leads returned for ' + email + ' ' + leads.data.length)
return done()

View file

@ -1,3 +1,4 @@
closeIO = require '../lib/closeIO'
log = require 'winston'
mongoose = require 'mongoose'
config = require '../../server_config'
@ -26,18 +27,36 @@ TrialRequestSchema.pre 'save', (next) ->
TrialRequestSchema.post 'save', (doc) ->
if doc.get('status') is 'approved'
emailParams =
recipient:
address: doc.get('properties')?.email
email_id: sendwithus.templates.teacher_free_trial
sendwithus.api.send emailParams, (err, result) =>
log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
unless trialProperties = doc.get('properties')
log.error "Saving approved trial request #{doc.id} with no properties!"
return
# Subscribe to teacher news group
User.findById doc.get('applicant'), (err, user) =>
if err
log.error "Trial request user find error: #{err}"
return
# Send trial approved email
email = trialProperties.email ? user.get('emailLower')
emailParams =
recipient:
address: email
email_id: sendwithus.templates.teacher_free_trial
sendwithus.api.send emailParams, (err, result) =>
log.error "sendwithus trial request approved error: #{err}, result: #{result}" if err
closeIO.createSalesLead(user, email,
name: trialProperties.name
organization: trialProperties.organization
location: _.filter(_.at(trialProperties, 'city', 'state', 'country')).join(' ')
educationLevel: (trialProperties.educationLevel or []).join(', ')
numStudents: trialProperties.numStudents
role: trialProperties.role
phone: trialProperties.phoneNumber
notes: trialProperties.notes
)
# Subscribe to teacher news group
emails = _.cloneDeep(user.get('emails') ? {})
emails.teacherNews ?= {}
emails.teacherNews.enabled = true

View file

@ -34,6 +34,9 @@ else
config.apple =
verifyURL: process.env.COCO_APPLE_VERIFY_URL or 'https://sandbox.itunes.apple.com/verifyReceipt'
config.closeIO =
apiKey: process.env.COCO_CLOSEIO_API_KEY or ''
config.stripe =
secretKey: process.env.COCO_STRIPE_SECRET_KEY or 'sk_test_MFnZHYD0ixBbiBuvTlLjl2da'