Merge branch 'master' into production

This commit is contained in:
Scott Erickson 2014-04-19 10:28:57 -07:00
commit 6641e60f2d
4 changed files with 147 additions and 45 deletions

View file

@ -73,7 +73,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
creating: "账户创建中……" creating: "账户创建中……"
sign_up: "注册" sign_up: "注册"
log_in: "登录" log_in: "登录"
# social_signup: "Or, you can sign up through Facebook or G+:" social_signup: "或者你可以通过Facebook或G+注册:"
home: home:
slogan: "通过游戏学习 Javascript" slogan: "通过游戏学习 Javascript"
@ -114,7 +114,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
forum_page: "我们的论坛" forum_page: "我们的论坛"
forum_suffix: "" forum_suffix: ""
send: "反馈意见" send: "反馈意见"
# contact_candidate: "Contact Candidate" contact_candidate: "联系参选人"
# recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 18% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns." # recruitment_reminder: "Use this form to reach out to candidates you are interested in interviewing. Remember that CodeCombat charges 18% of first-year salary. The fee is due upon hiring the employee and is refundable for 90 days if the employee does not remain employed. Part time, remote, and contract employees are free, as are interns."
diplomat_suggestion: diplomat_suggestion:
@ -128,13 +128,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
wizard_settings: wizard_settings:
title: "设置向导" title: "设置向导"
customize_avatar: "设置你的头像" customize_avatar: "设置你的头像"
# active: "Active" active: "启用"
# color: "Color" color: "颜色"
# group: "Group" group: "类别"
clothes: "衣服" clothes: "衣服"
trim: "条纹" trim: "条纹"
cloud: "" cloud: ""
# team: "Team" team: "队伍"
spell: "魔法球" spell: "魔法球"
boots: "鞋子" boots: "鞋子"
hue: "颜色" hue: "颜色"
@ -177,27 +177,27 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
profile_for_suffix: "" profile_for_suffix: ""
# approved: "Approved" # approved: "Approved"
# not_approved: "Not Approved" # not_approved: "Not Approved"
# looking_for: "Looking for:" looking_for: "寻找"
# last_updated: "Last updated:" last_updated: "最后一次更新:"
# contact: "Contact" contact: "联系"
# work_experience: "Work Experience" work_experience: "工作经验"
# education: "Education" education: "教育程度"
# our_notes: "Our Notes" # our_notes: "Our Notes"
# projects: "Projects" projects: "项目"
# employers: # employers:
# want_to_hire_our_players: "Want to hire expert CodeCombat players?" want_to_hire_our_players: "想要雇用CodeCombat上的专业玩家"
# contact_george: "Contact George to see our candidates" # contact_george: "Contact George to see our candidates"
# candidates_count_prefix: "We currently have " candidates_count_prefix: "我们当前有 "
# candidates_count_many: "many" candidates_count_many: "很多"
# candidates_count_suffix: "highly skilled and vetted developers looking for work." # candidates_count_suffix: "highly skilled and vetted developers looking for work."
# candidate_name: "Name" candidate_name: "姓名"
# candidate_location: "Location" candidate_location: "地点"
# candidate_looking_for: "Looking For" candidate_looking_for: "寻找"
# candidate_role: "Role" candidate_role: "角色"
# candidate_top_skills: "Top Skills" candidate_top_skills: "高级技能"
# candidate_years_experience: "Yrs Exp" candidate_years_experience: "多年工作经验"
# candidate_last_updated: "Last Updated" candidate_last_updated: "最后一次更新"
play_level: play_level:
level_load_error: "关卡不能载入: " level_load_error: "关卡不能载入: "
@ -250,17 +250,17 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
editor_config_title: "编辑器配置" editor_config_title: "编辑器配置"
editor_config_language_label: "编程语言" editor_config_language_label: "编程语言"
editor_config_language_description: "请输入你想写的编程语言." editor_config_language_description: "请输入你想写的编程语言."
# editor_config_keybindings_label: "Key Bindings" editor_config_keybindings_label: "按键设置s"
# editor_config_keybindings_default: "Default (Ace)" editor_config_keybindings_default: "默认 (Ace)"
# editor_config_keybindings_description: "Adds additional shortcuts known from the common editors." # editor_config_keybindings_description: "Adds additional shortcuts known from the common editors."
# editor_config_invisibles_label: "Show Invisibles" editor_config_invisibles_label: "显示隐藏的"
# editor_config_invisibles_description: "Displays invisibles such as spaces or tabs." editor_config_invisibles_description: "显示诸如空格或TAB键。"
# editor_config_indentguides_label: "Show Indent Guides" editor_config_indentguides_label: "显示缩进提示"
# editor_config_indentguides_description: "Displays vertical lines to see indentation better." editor_config_indentguides_description: "显示一条竖线以使缩进更明显。"
# editor_config_behaviors_label: "Smart Behaviors" # editor_config_behaviors_label: "Smart Behaviors"
# editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes." # editor_config_behaviors_description: "Autocompletes brackets, braces, and quotes."
loading_ready: "载入完成!" loading_ready: "载入完成!"
# tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor." tip_insert_positions: "使用Shift+左键来插入拼写编辑器。"
tip_toggle_play: "用 Ctrl+P 来暂停或继续" tip_toggle_play: "用 Ctrl+P 来暂停或继续"
tip_scrub_shortcut: "用 Ctrl+[ 和 Ctrl+] 来倒退和快进." tip_scrub_shortcut: "用 Ctrl+[ 和 Ctrl+] 来倒退和快进."
tip_guide_exists: "点击页面上方的指南, 可以获得更多有用信息." tip_guide_exists: "点击页面上方的指南, 可以获得更多有用信息."
@ -285,15 +285,15 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
tip_no_try: "做. 或是不做. 这世上不存在'尝试'这种东西. - 尤达大师" tip_no_try: "做. 或是不做. 这世上不存在'尝试'这种东西. - 尤达大师"
# tip_patience: "Patience you must have, young Padawan. - Yoda" # tip_patience: "Patience you must have, young Padawan. - Yoda"
tip_documented_bug: "一个写在文档里的漏洞不算漏洞, 那是个功能." tip_documented_bug: "一个写在文档里的漏洞不算漏洞, 那是个功能."
tip_impossible: "It always seems impossible until it's done. - Nelson Mandela" tip_impossible: "在事情未完成之前,一切都看似不可能. - 纳尔逊·曼德拉"
tip_talk_is_cheap: "多说无用, 亮出你的代码. - Linus Torvalds" tip_talk_is_cheap: "多说无用, 亮出你的代码. - Linus Torvalds"
# tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay" # tip_first_language: "The most disastrous thing that you can ever learn is your first programming language. - Alan Kay"
time_current: "现在:" time_current: "现在:"
time_total: "最大:" time_total: "最大:"
time_goto: "跳到:" time_goto: "跳到:"
# infinite_loop_try_again: "Try Again" infinite_loop_try_again: "请重试"
# infinite_loop_reset_level: "Reset Level" infinite_loop_reset_level: "重置等级"
# infinite_loop_comment_out: "Comment Out My Code" infinite_loop_comment_out: "为我的代码添加注释"
admin: admin:
av_title: "管理员视图" av_title: "管理员视图"
@ -361,7 +361,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
thang_search_title: "在这里搜索物品类型" thang_search_title: "在这里搜索物品类型"
level_search_title: "在这里搜索关卡" level_search_title: "在这里搜索关卡"
signup_to_create: "注册之后就可以创建一个新的关卡" signup_to_create: "注册之后就可以创建一个新的关卡"
# read_only_warning2: "Note: you can't save any edits here, because you're not logged in." read_only_warning2: "提示:你不能保存任何编辑,因为你没有登陆"
article: article:
edit_btn_preview: "预览" edit_btn_preview: "预览"
@ -373,13 +373,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
body: "正文" body: "正文"
version: "版本" version: "版本"
commit_msg: "提交信息" commit_msg: "提交信息"
# version_history: "Version History" version_history: "版本历史"
version_history_for: "版本历史: " version_history_for: "版本历史: "
result: "结果" result: "结果"
results: "结果" results: "结果"
description: "描述" description: "描述"
or: "" or: ""
# subject: "Subject" subject: "主题"
email: "邮件" email: "邮件"
password: "密码" password: "密码"
message: "信息" message: "信息"
@ -395,7 +395,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
easy: "容易" easy: "容易"
medium: "中等" medium: "中等"
hard: "困难" hard: "困难"
# player: "Player" player: "玩家"
about: about:
who_is_codecombat: "什么是 CodeCombat?" who_is_codecombat: "什么是 CodeCombat?"
@ -538,7 +538,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
scribe_introduction_url_mozilla: "Mozilla 开发者社区" scribe_introduction_url_mozilla: "Mozilla 开发者社区"
# scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you." # scribe_introduction_suf: " has built. If your idea of fun is articulating the concepts of programming in Markdown form, then this class might be for you."
# scribe_attribute_1: "Skill in words is pretty much all you need. Not only grammar and spelling, but able to convey complicated ideas to others." # scribe_attribute_1: "Skill in words is pretty much all you need. Not only grammar and spelling, but able to convey complicated ideas to others."
# contact_us_url: "Contact us" contact_us_url: "联系我们"
scribe_join_description: "介绍一下你自己, 比如你的编程经历和你喜欢写什么东西, 我们将从这里开始了解你!!" scribe_join_description: "介绍一下你自己, 比如你的编程经历和你喜欢写什么东西, 我们将从这里开始了解你!!"
more_about_scribe: "了解如何成为一名文书" more_about_scribe: "了解如何成为一名文书"
scribe_subscribe_desc: "通过电子邮件获得写作新文档的通知。" scribe_subscribe_desc: "通过电子邮件获得写作新文档的通知。"
@ -610,7 +610,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
summary_wins: " 胜利, " summary_wins: " 胜利, "
summary_losses: " 失败" summary_losses: " 失败"
rank_no_code: "没有新代码可供评分" rank_no_code: "没有新代码可供评分"
# rank_my_game: "Rank My Game!" rank_my_game: "为我的游戏评分!"
rank_submitting: "正在提交..." rank_submitting: "正在提交..."
# rank_submitted: "Submitted for Ranking" # rank_submitted: "Submitted for Ranking"
rank_failed: "评分失败" rank_failed: "评分失败"
@ -665,7 +665,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
gplus_friends: "G+ 朋友" gplus_friends: "G+ 朋友"
# gplus_friend_sessions: "G+ Friend Sessions" # gplus_friend_sessions: "G+ Friend Sessions"
leaderboard: "排行榜" leaderboard: "排行榜"
# user_schema: "User Schema" user_schema: "用户模式"
# user_profile: "User Profile" user_profile: "User Profile"
# patches: "Patches" patches: "补丁"
# model: "Model" # model: "Model"

View file

@ -255,7 +255,7 @@ module.exports = class ThangsTabView extends View
# @thangsTreema.deselectAll() # @thangsTreema.deselectAll()
selectAddThang: (e) => selectAddThang: (e) =>
return unless e? and $(e.target).closest('.editor-level-thangs-tab-view').length return unless e? and $(e.target).closest('#editor-level-thangs-tab-view').length
if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event if e then target = $(e.target) else target = @$el.find('.add-thangs-palette') # pretend to click on background if no event
return true if target.attr('id') is 'surface' return true if target.attr('id') is 'surface'
target = target.closest('.add-thang-palette-icon') target = target.closest('.add-thang-palette-icon')

103
scripts/mail.coffee Normal file
View file

@ -0,0 +1,103 @@
do (setupLodash = this) ->
GLOBAL._ = require 'lodash'
_.str = require 'underscore.string'
_.mixin _.str.exports()
async = require 'async'
serverSetup = require '../server_setup'
sendwithus = require '../server/sendwithus'
User = require '../server/users/User.coffee'
Level = require '../server/levels/Level.coffee'
LevelSession = require '../server/levels/sessions/LevelSession.coffee'
alreadyEmailed = []
DEBUGGING = true
sendInitialRecruitingEmail = ->
leaderboards = [
{slug: 'brawlwood', team: 'humans', limit: 55, name: "Brawlwood", original: "52d97ecd32362bc86e004e87", majorVersion: 0}
{slug: 'brawlwood', team: 'ogres', limit: 40, name: "Brawlwood", original: "52d97ecd32362bc86e004e87", majorVersion: 0}
{slug: 'dungeon-arena', team: 'humans', limit: 200, name: "Dungeon Arena", original: "53173f76c269d400000543c2", majorVersion: 0}
{slug: 'dungeon-arena', team: 'ogres', limit: 150, name: "Dungeon Arena", original: "53173f76c269d400000543c2", majorVersion: 0}
]
async.waterfall [
(callback) -> async.map leaderboards, grabSessions, callback
(sessionLists, callback) -> async.map collapseSessions(sessionLists), grabUser, callback
(users, callback) -> async.map users, emailUser, callback
], (err, results) ->
return console.log "Error:", err if err
console.log "Looked at sending to #{results.length} users; sent to #{_.filter(results).length}."
console.log "Sent to: ['#{(user.email for user in results when user).join('\', \'')}']"
grabSessions = (levelInfo, callback) ->
queryParameters =
level: {original: levelInfo.original, majorVersion: levelInfo.majorVersion}
team: levelInfo.team
submitted: true
sortParameters = totalScore: -1
selectString = 'totalScore creator'
query = LevelSession
.find(queryParameters)
.limit(levelInfo.limit)
.sort(sortParameters)
.select(selectString)
.lean()
query.exec (err, sessions) ->
return callback err if err
for session, rank in sessions
session.levelInfo = levelInfo
session.rank = rank + 1
callback null, sessions
collapseSessions = (sessionLists) ->
userRanks = {}
for sessionList in sessionLists
for session in sessionList
ranks = userRanks[session.creator] ? []
ranks.push session
userRanks[session.creator] = _.sortBy ranks, 'rank'
topSessions = []
for userID, ranks of userRanks
topSessions.push ranks[0]
topSessions
grabUser = (session, callback) ->
findParameters = _id: session.creator
selectString = 'email emailSubscriptions name jobProfile'
query = User
.findOne(findParameters)
.select(selectString)
.lean()
query.exec (err, user) ->
return callback err if err
user.session = session
callback null, user
totalEmailsSent = 0
emailUser = (user, callback) ->
return callback null, false if user.emails?.recruiting?.enabled is false # TODO: later, obey also "announcements" when that's untangled
return callback null, false if user.email in alreadyEmailed
return callback null, false if DEBUGGING and (totalEmailsSent > 1 or Math.random() > 0.1)
++totalEmailsSent
name = if user.firstName and user.lastName then "#{user.firstName}" else user.name
name = "Wizard" if not name or name is "Anoner"
team = user.session.levelInfo.team
team = team.substr(0, team.length - 1)
context =
email_id: sendwithus.templates.one_time_recruiting_email
recipient:
address: if DEBUGGING then 'nick@codecombat.com' else user.email
name: name
email_data:
name: name
level_name: user.session.levelInfo.name
place: "##{user.session.rank}" # like "#31"
level_race: team
sendwithus.api.send context, (err, result) ->
return callback err if err
callback null, user
serverSetup.connectToDatabase()
sendInitialRecruitingEmail()

View file

@ -1,12 +1,10 @@
config = require '../server_config' config = require '../server_config'
sendwithusAPI = require 'sendwithus' sendwithusAPI = require 'sendwithus'
swuAPIKey = config.mail.sendwithusAPIKey swuAPIKey = config.mail.sendwithusAPIKey
queues = require './commons/queue'
module.exports.setupRoutes = (app) -> module.exports.setupRoutes = (app) ->
return return
debug = not config.isProduction debug = not config.isProduction
module.exports.api = new sendwithusAPI swuAPIKey, debug module.exports.api = new sendwithusAPI swuAPIKey, debug
if config.unittest if config.unittest
@ -16,3 +14,4 @@ module.exports.templates =
ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4' ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4'
patch_created: 'tem_xhxuNosLALsizTNojBjNcL' patch_created: 'tem_xhxuNosLALsizTNojBjNcL'
change_made_notify_watcher: 'tem_7KVkfmv9SZETb25dtHbUtG' change_made_notify_watcher: 'tem_7KVkfmv9SZETb25dtHbUtG'
one_time_recruiting_email: 'tem_mdFMgtcczHKYu94Jmq68j8'