mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 01:55:38 -05:00
Merge branch 'master' of https://github.com/codecombat/codecombat
This commit is contained in:
commit
a8c483a59f
2 changed files with 364 additions and 93 deletions
270
app/lib/simulator/Simulator.coffee
Normal file
270
app/lib/simulator/Simulator.coffee
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
SuperModel = require 'models/SuperModel'
|
||||||
|
LevelLoader = require 'lib/LevelLoader'
|
||||||
|
GoalManager = require 'lib/world/GoalManager'
|
||||||
|
|
||||||
|
module.exports = class Simulator
|
||||||
|
constructor: ->
|
||||||
|
@retryDelayInSeconds = 10
|
||||||
|
@taskURL = "/queue/scoring"
|
||||||
|
|
||||||
|
|
||||||
|
fetchAndSimulateTask: =>
|
||||||
|
$.ajax
|
||||||
|
url: @taskURL
|
||||||
|
type: "GET"
|
||||||
|
error: @handleFetchTaskError
|
||||||
|
success: @setupSimulationAndLoadLevel
|
||||||
|
|
||||||
|
cleanupSimulation: ->
|
||||||
|
|
||||||
|
|
||||||
|
handleFetchTaskError: (errorData) =>
|
||||||
|
console.log "There were no games to score. Error: #{JSON.stringify errorData}"
|
||||||
|
console.log "Retrying in #{@retryDelayInSeconds}"
|
||||||
|
_.delay @fetchAndSimulateTask, @retryDelayInSeconds * 1000
|
||||||
|
|
||||||
|
|
||||||
|
setupSimulationAndLoadLevel: (taskData) =>
|
||||||
|
@task = new SimulationTask(taskData)
|
||||||
|
@superModel = new SuperModel()
|
||||||
|
@god = new God()
|
||||||
|
@levelLoader = new LevelLoader @task.getLevelName(), @superModel, @task.getFirstSessionID()
|
||||||
|
|
||||||
|
@levelLoader.once 'loaded-all', @simulateGame
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
simulateGame: =>
|
||||||
|
@assignWorldAndLevelFromLevelLoaderAndDestroyIt()
|
||||||
|
@setupGod()
|
||||||
|
try
|
||||||
|
@commenceSimulationAndSetupCallback()
|
||||||
|
catch e
|
||||||
|
console.log "There was an error in simulation. Trying again in #{retryDelayInSeconds} seconds"
|
||||||
|
console.log "Error #{e}"
|
||||||
|
_.delay @fetchAndSimulateTask, @retryDelayInSeconds * 1000
|
||||||
|
|
||||||
|
assignWorldAndLevelFromLevelLoaderAndDestroyIt: ->
|
||||||
|
@world = @levelLoader.world
|
||||||
|
@level = @levelLoader.level
|
||||||
|
@levelLoader.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
setupGod: ->
|
||||||
|
@god.level = @level.serialize @supermodel
|
||||||
|
@god.worldClassMap = world.classMap
|
||||||
|
@setupGoalManager()
|
||||||
|
@setupGodSpells()
|
||||||
|
|
||||||
|
|
||||||
|
setupGoalManager: ->
|
||||||
|
@god.goalManager = new GoalManager @world
|
||||||
|
@god.goalManager.goals = @fetchGoalsFromWorldNoteChain()
|
||||||
|
@god.goalManager.goalStates = @manuallyGenerateGoalStates()
|
||||||
|
|
||||||
|
commenceSimulationAndSetupCallback: ->
|
||||||
|
@god.createWorld()
|
||||||
|
Backbone.Mediator.subscribeOnce 'god:new-world-created', @processResults, @
|
||||||
|
|
||||||
|
|
||||||
|
processResults: (simulationResults) ->
|
||||||
|
taskResults = @formTaskResultsObject simulationResults
|
||||||
|
sendResultsBackToServer taskResults
|
||||||
|
|
||||||
|
sendResultsBackToServer: (results) =>
|
||||||
|
$.ajax
|
||||||
|
url: @taskURL
|
||||||
|
data: results
|
||||||
|
type: "PUT"
|
||||||
|
success: @handleTaskResultsTransferSuccess
|
||||||
|
error: @handleTaskResultsTransferError
|
||||||
|
complete: @cleanupAndSimulateAnotherTask()
|
||||||
|
|
||||||
|
handleTaskResultsTransferSuccess: (result) ->
|
||||||
|
console.log "Task registration result: #{JSON.stringify result}"
|
||||||
|
|
||||||
|
handleTaskResultsTransferError: (error) ->
|
||||||
|
console.log "Task registration error: #{JSON.stringify error}"
|
||||||
|
|
||||||
|
cleanupAndSimulateAnotherTask: =>
|
||||||
|
@cleanupSimulation()
|
||||||
|
@fetchAndSimulateTask()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
formTaskResultsObject: (simulationResults) ->
|
||||||
|
taskResults =
|
||||||
|
taskID: @task.getTaskID()
|
||||||
|
receiptHandle: @task.getReceiptHandle()
|
||||||
|
calculationTime: 500
|
||||||
|
sessions: []
|
||||||
|
|
||||||
|
for session in @task.sessions
|
||||||
|
sessionResult =
|
||||||
|
sessionID: session.sessionID
|
||||||
|
sessionChangedTime: session.sessionChangedTime
|
||||||
|
metrics:
|
||||||
|
rank: @calculateSessionRank session.sessionID, simulationResults.goalStates
|
||||||
|
|
||||||
|
taskResults.sessions.push sessionResult
|
||||||
|
|
||||||
|
return taskResults
|
||||||
|
|
||||||
|
|
||||||
|
calculateSessionRank: (sessionID, goalStates) ->
|
||||||
|
humansDestroyed = goalStates["destroy-humans"].status is "success"
|
||||||
|
ogresDestroyed = goalStates["destroy-ogres"].status is "success"
|
||||||
|
console.log "Humans destroyed:#{humansDestroyed}"
|
||||||
|
console.log "Ogres destroyed:#{ogresDestroyed}"
|
||||||
|
console.log "Team Session Map: #{JSON.stringify @teamSessionMap}"
|
||||||
|
if humansDestroyed is ogresDestroyed
|
||||||
|
return 0
|
||||||
|
else if humansDestroyed and @teamSessionMap["ogres"] is sessionID
|
||||||
|
return 0
|
||||||
|
else if humansDestroyed and @teamSessionMap["ogres"] isnt sessionID
|
||||||
|
return 1
|
||||||
|
else if ogresDestroyed and @teamSessionMap["humans"] is sessionID
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fetchGoalsFromWorldNoteChain: -> return @god.goalManager.world.scripts[0].noteChain[0].goals.add
|
||||||
|
|
||||||
|
|
||||||
|
manuallyGenerateGoalStates: ->
|
||||||
|
goalStates =
|
||||||
|
"destroy-humans":
|
||||||
|
keyFrame: 0
|
||||||
|
killed:
|
||||||
|
"Human Base": false
|
||||||
|
status: "incomplete"
|
||||||
|
"destroy-ogres":
|
||||||
|
keyFrame:0
|
||||||
|
killed:
|
||||||
|
"Ogre Base": false
|
||||||
|
status: "incomplete"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setupGodSpells: ->
|
||||||
|
@generateSpellsObject()
|
||||||
|
@god.spells = @spells
|
||||||
|
|
||||||
|
|
||||||
|
generateSpellsObject: (currentUserCodeMap) ->
|
||||||
|
@userCodeMap = currentUserCodeMap
|
||||||
|
@spells = {}
|
||||||
|
for thang in @level.attributes.thangs
|
||||||
|
continue if @thangIsATemplate thang
|
||||||
|
@generateSpellKeyToSourceMapPropertiesFromThang thang
|
||||||
|
|
||||||
|
|
||||||
|
thangIsATemplate: (thang) ->
|
||||||
|
for component in thang.components
|
||||||
|
continue unless @componentHasProgrammableMethods component
|
||||||
|
for methodName, method of component.config.programmableMethods
|
||||||
|
return true if methodBelongsToTemplateThang method
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
componentHasProgrammableMethods: (component) -> component.config? and _.has component.config, 'programmableMethods'
|
||||||
|
|
||||||
|
methodBelongsToTemplateThang: (method) -> typeof method is 'string'
|
||||||
|
|
||||||
|
generateSpellKeyToSourceMapPropertiesFromThang: (thang) =>
|
||||||
|
for component in thang.components
|
||||||
|
continue unless @componentHasProgrammableMethods component
|
||||||
|
|
||||||
|
for methodName, method of component.config.programmableMethods
|
||||||
|
spellKey = @generateSpellKeyFromThangIDAndMethodName thang.id, methodName
|
||||||
|
|
||||||
|
@createSpellAndAssignName spellKey, methodName
|
||||||
|
@createSpellThang thang, method, spellKey
|
||||||
|
@transpileSpell thang, spellKey, methodName
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
generateSpellKeyFromThangIDAndMethodName: (thang, methodName) ->
|
||||||
|
spellKeyComponents = [thang.id, methodName]
|
||||||
|
pathComponents[0] = _.string.slugify pathComponents[0]
|
||||||
|
pathComponents.join '/'
|
||||||
|
|
||||||
|
createSpellAndAssignName: (spellKey, spellName) ->
|
||||||
|
@spells[spellKey] ?= {}
|
||||||
|
@spells[spellKey].name = methodName
|
||||||
|
|
||||||
|
createSpellThang: (thang, method, spellKey) ->
|
||||||
|
@spells[spellKey].thangs ?= {}
|
||||||
|
@spells[spellKey].thangs[thang.id] ?= {}
|
||||||
|
@spells[spellKey].thangs[thang.id].aether = @createAether @spells[spellKey].name, method
|
||||||
|
|
||||||
|
transpileSpell: (thang, spellKey, methodName) ->
|
||||||
|
slugifiedThangID = _.string.slugify thang.id
|
||||||
|
source = @currentUserCodeMap[slugifiedThangID]?[methodName] ? ""
|
||||||
|
@spells[spellKey].thangs[thang.id].aether.transpile source
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
createAether: (methodName, method) ->
|
||||||
|
aetherOptions =
|
||||||
|
functionName: methodName
|
||||||
|
protectAPI: false
|
||||||
|
includeFlow: false
|
||||||
|
return new Aether aetherOptions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SimulationTask
|
||||||
|
constructor: (@rawData) ->
|
||||||
|
|
||||||
|
|
||||||
|
getLevelName: ->
|
||||||
|
levelName = @rawData.sessions?[0]?.levelID
|
||||||
|
return levelName if levelName?
|
||||||
|
@throwMalformedTaskError "The level name couldn't be deduced from the task."
|
||||||
|
|
||||||
|
generateTeamToSessionMap: ->
|
||||||
|
teamSessionMap = {}
|
||||||
|
for session in @rawData.sessions
|
||||||
|
@throwMalformedTaskError "Two players share the same team" if teamSessionMap[session.team]?
|
||||||
|
teamSessionMap[session.team] = session.sessionID
|
||||||
|
|
||||||
|
teamSessionMap
|
||||||
|
|
||||||
|
throwMalformedTaskError: (errorString) ->
|
||||||
|
throw new Error "The task was malformed, reason: #{errorString}"
|
||||||
|
|
||||||
|
getFirstSessionID: -> @rawData.sessions[0].sessionID
|
||||||
|
|
||||||
|
getTaskID: -> @rawData.taskID
|
||||||
|
|
||||||
|
getReceiptHandle: -> @rawData.receiptHandle
|
||||||
|
|
||||||
|
getSessions: -> @rawData.sessions
|
||||||
|
|
||||||
|
generateSpellKeyToSourceMap: ->
|
||||||
|
spellKeyToSourceMap = {}
|
||||||
|
|
||||||
|
for session in @rawData.sessions
|
||||||
|
teamSpells = session.teamSpells[session.team]
|
||||||
|
_.merge spellKeyToSourceMap, _.pick(session.code, teamSpells)
|
||||||
|
|
||||||
|
commonSpells = session.teamSpells["common"]
|
||||||
|
_.merge spellKeyToSourceMap, _.pick(session.code, commonSpells) if commonSpells?
|
||||||
|
|
||||||
|
spellKeyToSourceMap
|
||||||
|
|
|
@ -3,14 +3,14 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
loading: "Loading..."
|
loading: "Loading..."
|
||||||
saving: "儲存中..."
|
saving: "儲存中..."
|
||||||
sending: "發送中...."
|
sending: "發送中...."
|
||||||
cancel: "退出"
|
cancel: "取消"
|
||||||
# save: "Save"
|
save: "存檔"
|
||||||
delay_1_sec: "1 秒"
|
delay_1_sec: "1 秒"
|
||||||
delay_3_sec: "3 秒"
|
delay_3_sec: "3 秒"
|
||||||
delay_5_sec: "5 秒"
|
delay_5_sec: "5 秒"
|
||||||
manual: "手動手动"
|
manual: "手動發動"
|
||||||
# fork: "Fork"
|
fork: "Fork"
|
||||||
play: "玩"
|
play: "播放" # Play timeline in a level.
|
||||||
|
|
||||||
modal:
|
modal:
|
||||||
close: "關閉"
|
close: "關閉"
|
||||||
|
@ -20,18 +20,18 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
page_not_found: "找不到網頁"
|
page_not_found: "找不到網頁"
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
play: "玩"
|
play: "開始遊戲"
|
||||||
editor: "編輯"
|
editor: "編輯"
|
||||||
blog: "博客"
|
blog: "官方部落格" # Official blog
|
||||||
forum: "論壇"
|
forum: "論壇"
|
||||||
admin: "超級管理員"
|
admin: "系統管理員"
|
||||||
home: "首頁"
|
home: "首頁"
|
||||||
contribute: "貢獻"
|
contribute: "貢獻"
|
||||||
legal: "法律"
|
legal: "版權聲明" # Copyright
|
||||||
about: "關於"
|
about: "關於"
|
||||||
contact: "聯繫我們"
|
contact: "聯繫我們"
|
||||||
twitter_follow: "關注"
|
twitter_follow: "在Twitter關注"
|
||||||
# employers: "Employers"
|
employers: "招募訊息"
|
||||||
|
|
||||||
# versions:
|
# versions:
|
||||||
# save_version_title: "Save New Version"
|
# save_version_title: "Save New Version"
|
||||||
|
@ -43,61 +43,61 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
|
|
||||||
login:
|
login:
|
||||||
sign_up: "註冊"
|
sign_up: "註冊"
|
||||||
log_in: "登錄"
|
log_in: "登入"
|
||||||
log_out: "退出"
|
log_out: "登出"
|
||||||
recover: "找回帳戶"
|
recover: "找回帳號"
|
||||||
|
|
||||||
recover:
|
recover:
|
||||||
recover_account_title: "復原帳戶"
|
recover_account_title: "復原帳號"
|
||||||
# send_password: "Send Recovery Password"
|
send_password: "送出新密碼"
|
||||||
|
|
||||||
signup:
|
signup:
|
||||||
# create_account_title: "Create Account to Save Progress"
|
create_account_title: "建立帳號儲存進度"
|
||||||
description: "這是免費的。超簡單的喲:"
|
description: "登入以儲存遊戲進度:"
|
||||||
email_announcements: "通過郵件接收通知"
|
email_announcements: "通過郵件接收通知"
|
||||||
coppa: "13歲以上或非美國公民"
|
coppa: "13歲以上或非美國公民"
|
||||||
coppa_why: "爲什麽?"
|
coppa_why: "爲什麽?"
|
||||||
creating: "帳戶創建中..."
|
creating: "帳號建立中..."
|
||||||
sign_up: "註冊"
|
sign_up: "註冊"
|
||||||
log_in: "登錄"
|
log_in: "登入"
|
||||||
|
|
||||||
home:
|
home:
|
||||||
slogan: "通過玩遊戲學習Javascript 腳本語言"
|
slogan: "通過玩遊戲學習Javascript 腳本語言"
|
||||||
no_ie: "抱歉!Internet Explorer 9 等舊的瀏覽器打不開此網站"
|
no_ie: "抱歉!Internet Explorer 9 等舊的瀏覽器打不開此網站"
|
||||||
no_mobile: "CodeCombat 不是針對手機設備設計的,所以可能會出問題!"
|
no_mobile: "CodeCombat 不是針對手機設備設計的,所以可能會出問題!"
|
||||||
play: "玩"
|
play: "開始遊戲"
|
||||||
|
|
||||||
play:
|
play:
|
||||||
choose_your_level: "選取難度"
|
choose_your_level: "選取關卡"
|
||||||
adventurer_prefix: "你可以選擇以下任意關卡,或者討論以上的關卡 "
|
adventurer_prefix: "你可以選擇以下任意關卡,或者討論以上的關卡 "
|
||||||
adventurer_forum: "冒險家論壇"
|
adventurer_forum: "冒險家論壇"
|
||||||
adventurer_suffix: "."
|
adventurer_suffix: "."
|
||||||
campaign_beginner: "新手作戰"
|
campaign_beginner: "新手指南"
|
||||||
campaign_beginner_description: "...在這裡可以學到編程技巧。"
|
campaign_beginner_description: "...在這裡可以學到編程技巧。"
|
||||||
campaign_dev: "隨機關卡"
|
campaign_dev: "隨機關卡"
|
||||||
campaign_dev_description: "...在這裡你可以學到做一些複雜功能的接口。"
|
campaign_dev_description: "...在這裡你可以學到做一些較複雜的程式技巧。"
|
||||||
campaign_multiplayer: "多人競技場"
|
campaign_multiplayer: "多人競技場"
|
||||||
campaign_multiplayer_description: "...在這裡你可以和其他玩家們進行代碼近戰。"
|
campaign_multiplayer_description: "...在這裡你可以和其他玩家進行對戰。"
|
||||||
campaign_player_created: "已創建的玩家"
|
campaign_player_created: "玩家建立的關卡"
|
||||||
campaign_player_created_description: "...在這裡你可以與你的小夥伴的創造力戰鬥 <a href=\"/contribute#artisan\">技術指導</a>."
|
campaign_player_created_description: "...挑戰同伴的創意 <a href=\"/contribute#artisan\">技術指導</a>."
|
||||||
level_difficulty: "難度"
|
level_difficulty: "難度"
|
||||||
|
|
||||||
contact:
|
contact:
|
||||||
contact_us: "聯繫我們"
|
contact_us: "聯繫我們"
|
||||||
welcome: "很高興收到你的信!用這個表格給我們發電郵。 "
|
welcome: "很高興收到你的信!用這個表格給我們發電郵。 "
|
||||||
contribute_prefix: "如果你想貢獻代碼,請看 "
|
contribute_prefix: "如果你想貢獻程式,請看 "
|
||||||
contribute_page: "貢獻代碼頁面"
|
contribute_page: "程式貢獻頁面"
|
||||||
contribute_suffix: "!"
|
contribute_suffix: "!"
|
||||||
forum_prefix: "對於任何公共部份,放手去做吧 "
|
forum_prefix: "如果有任何問題, 請至"
|
||||||
forum_page: "我們的論壇"
|
forum_page: "論壇"
|
||||||
forum_suffix: "代替。"
|
forum_suffix: "討論。"
|
||||||
sending: "發送中。。。"
|
sending: "發送中。。。"
|
||||||
send: "意見反饋"
|
send: "意見反饋"
|
||||||
|
|
||||||
diplomat_suggestion:
|
diplomat_suggestion:
|
||||||
title: "幫我們翻譯CodeCombat"
|
title: "幫我們翻譯CodeCombat"
|
||||||
sub_heading: "我們需要您的語言技能"
|
sub_heading: "我們需要您的語言技能"
|
||||||
pitch_body: "我們開發了CodeCombat的英文版,但是現在我們的玩家遍佈全球。很多人想玩中文(繁体)版的,卻不會說英文,所以如果你中英文都會,請考慮一下參加我們的翻譯工作,幫忙把 CodeCombat 網站還有所有的關卡翻譯成中文(繁体)。"
|
pitch_body: "我們開發了CodeCombat的英文版,但是現在我們的玩家遍佈全球。很多人想玩中文版的,卻不會說英文,所以如果你中英文都會,請考慮一下參加我們的翻譯工作,幫忙把 CodeCombat 網站還有所有的關卡翻譯成中文(繁体)。"
|
||||||
missing_translations: "直至所有正體中文的翻譯完畢,當無法提供正體中文時還會以英文顯示。"
|
missing_translations: "直至所有正體中文的翻譯完畢,當無法提供正體中文時還會以英文顯示。"
|
||||||
learn_more: "關於成為外交官"
|
learn_more: "關於成為外交官"
|
||||||
subscribe_as_diplomat: "註冊成為外交官"
|
subscribe_as_diplomat: "註冊成為外交官"
|
||||||
|
@ -107,91 +107,92 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
# customize_avatar: "Customize Your Avatar"
|
# customize_avatar: "Customize Your Avatar"
|
||||||
|
|
||||||
account_settings:
|
account_settings:
|
||||||
title: "帳戶設置"
|
title: "帳號設定"
|
||||||
not_logged_in: "登錄或創建一個帳戶來修改設置。"
|
not_logged_in: "登錄或建立一個帳號來修改設置。"
|
||||||
autosave: "自動保存修改"
|
autosave: "自動保存修改"
|
||||||
me_tab: "我"
|
me_tab: "我"
|
||||||
picture_tab: "圖片"
|
picture_tab: "頭像"
|
||||||
wizard_tab: "巫師"
|
wizard_tab: "巫師"
|
||||||
password_tab: "密碼"
|
password_tab: "密碼"
|
||||||
emails_tab: "郵件"
|
emails_tab: "郵件"
|
||||||
gravatar_select: "選擇使用 Gravatar 照片"
|
gravatar_select: "選擇一個Gravatar"
|
||||||
gravatar_add_photos: "添加小圖和照片到一个 Gravatar 帳戶供你選擇。"
|
gravatar_add_photos: "上傳頭像到Gravatar"
|
||||||
gravatar_add_more_photos: "添加更多照片到你的 Gravatar 帳戶并查看。"
|
# gravatar_add_more_photos: "Add thumbnails and photos to a Gravatar account for your email to choose an image."
|
||||||
wizard_color: "巫師 衣服 顏色"
|
wizard_color: "巫師 衣服 顏色"
|
||||||
new_password: "新密碼"
|
new_password: "新密碼"
|
||||||
new_password_verify: "核實"
|
new_password_verify: "確認密碼"
|
||||||
email_subscriptions: "郵箱驗證"
|
email_subscriptions: "訂閱"
|
||||||
email_announcements: "通知"
|
email_announcements: "通知"
|
||||||
email_announcements_description: "接收關於 CodeCombat 最近的新聞和發展的郵件。"
|
email_notifications_description: "接收帳號通知"
|
||||||
|
email_announcements_description: "接收關於 CodeCombat 的新聞和開發消息。"
|
||||||
contributor_emails: "貢獻者電郵"
|
contributor_emails: "貢獻者電郵"
|
||||||
contribute_prefix: "我們在尋找志同道合的人!請到 "
|
contribute_prefix: "我們在尋找志同道合的人!請到 "
|
||||||
contribute_page: "貢獻頁面"
|
contribute_page: "貢獻頁面"
|
||||||
contribute_suffix: " 查看更多信息。"
|
contribute_suffix: " 查看更多信息。"
|
||||||
email_toggle: "切換所有"
|
email_toggle: "全選"
|
||||||
error_saving: "保存時出錯"
|
error_saving: "保存時發生錯誤"
|
||||||
saved: "保存修改"
|
saved: "修改已儲存"
|
||||||
password_mismatch: "密碼不匹配。"
|
password_mismatch: "密碼不正確。"
|
||||||
|
|
||||||
account_profile:
|
account_profile:
|
||||||
edit_settings: "編輯設置"
|
edit_settings: "帳號設定"
|
||||||
profile_for_prefix: "關於TA的基本資料:"
|
profile_for_prefix: "關於"
|
||||||
# profile_for_suffix: ""
|
profile_for_suffix: "的基本資料"
|
||||||
profile: "基本資料"
|
profile: "基本資料"
|
||||||
user_not_found: "沒有找到用戶。檢查URL?"
|
user_not_found: "沒有找到用戶。檢查URL?"
|
||||||
gravatar_not_found_mine: "我們找不到TA的基本資料:"
|
gravatar_not_found_mine: "我們找不到有關"
|
||||||
gravatar_not_found_email_suffix: "."
|
gravatar_not_found_email_suffix: "的資料"
|
||||||
gravatar_signup_prefix: "去註冊 "
|
gravatar_signup_prefix: "請至"
|
||||||
gravatar_signup_suffix: " 去設置!"
|
gravatar_signup_suffix: " 註冊帳號"
|
||||||
gravatar_not_found_other: "哎呦,沒有與這個人的郵箱相關的資料。"
|
gravatar_not_found_other: "哎呦,找不到這個地址的資料。"
|
||||||
gravatar_contact: "聯繫"
|
gravatar_contact: "聯繫我們"
|
||||||
gravatar_websites: "網站"
|
gravatar_websites: "網站"
|
||||||
gravatar_accounts: "顯示為"
|
gravatar_accounts: "顯示為"
|
||||||
gravatar_profile_link: "完善 Gravatar 資料"
|
gravatar_profile_link: "完善 Gravatar 資料"
|
||||||
|
|
||||||
play_level:
|
play_level:
|
||||||
level_load_error: "關卡不能載入。"
|
level_load_error: "載入關卡時發生錯誤。"
|
||||||
done: "完成"
|
done: "完成"
|
||||||
grid: "格子"
|
grid: "格子"
|
||||||
customize_wizard: "自定義巫師"
|
customize_wizard: "自定義巫師"
|
||||||
home: "主頁"
|
home: "首頁"
|
||||||
guide: "指南"
|
guide: "指南"
|
||||||
multiplayer: "多人遊戲"
|
multiplayer: "多人遊戲"
|
||||||
restart: "重新開始"
|
restart: "重新開始"
|
||||||
goals: "目標"
|
goals: "目標"
|
||||||
action_timeline: "行動時間軸"
|
action_timeline: "行動時間軸"
|
||||||
click_to_select: "點擊選擇一個單元。"
|
click_to_select: "點擊選擇一個單元。"
|
||||||
reload_title: "重載所有代碼?"
|
reload_title: "重新載入程式碼?"
|
||||||
reload_really: "確定重載這一關,返回開始處?"
|
reload_really: "確定重設所有的程式碼?"
|
||||||
reload_confirm: "重載所有"
|
reload_confirm: "重設所有程式碼"
|
||||||
# victory_title_prefix: ""
|
victory_title_prefix: ""
|
||||||
victory_title_suffix: " 完成"
|
victory_title_suffix: " 完成"
|
||||||
victory_sign_up: "保存進度"
|
victory_sign_up: "保存進度"
|
||||||
victory_sign_up_poke: "想保存你的代碼?創建一個免費帳戶吧!"
|
victory_sign_up_poke: "想保存你的程式碼?建立一個免費帳號吧!"
|
||||||
victory_rate_the_level: "評估關卡: "
|
victory_rate_the_level: "評估關卡: "
|
||||||
victory_play_next_level: "下一關"
|
victory_play_next_level: "下一關"
|
||||||
victory_go_home: "返回主頁"
|
victory_go_home: "返回首頁"
|
||||||
victory_review: "給我們反饋!"
|
victory_review: "給我們回饋!"
|
||||||
victory_hour_of_code_done: "你完成了嗎?"
|
victory_hour_of_code_done: "你完成了嗎?"
|
||||||
victory_hour_of_code_done_yes: "是的,我完成了我的代碼!"
|
victory_hour_of_code_done_yes: "是的,我完成了我的程式碼!"
|
||||||
multiplayer_title: "多人遊戲設置"
|
multiplayer_title: "多人遊戲設定"
|
||||||
multiplayer_link_description: "把這個鏈接告訴小夥伴們,一起玩吧。"
|
multiplayer_link_description: "把這個連結告訴同伴們,一起玩吧。"
|
||||||
multiplayer_hint_label: "提示:"
|
multiplayer_hint_label: "提示:"
|
||||||
multiplayer_hint: " 點擊全選,然後按 Apple-C(苹果電腦)或 Ctrl-C 複製鏈接。"
|
multiplayer_hint: " 點擊全選,然後按 ⌘-C 或 Ctrl-C 複製連結。"
|
||||||
multiplayer_coming_soon: "多人遊戲的更多特性!"
|
multiplayer_coming_soon: "請期待更多的多人關卡!"
|
||||||
guide_title: "指南"
|
guide_title: "指南"
|
||||||
tome_minion_spells: "助手的咒語"
|
tome_minion_spells: "助手的咒語"
|
||||||
tome_read_only_spells: "只讀的咒語"
|
tome_read_only_spells: "唯讀的咒語"
|
||||||
tome_other_units: "其他單元"
|
tome_other_units: "其他單位"
|
||||||
tome_cast_button_castable: "發動"
|
tome_cast_button_castable: "發動"
|
||||||
tome_cast_button_casting: "發動中"
|
tome_cast_button_casting: "發動中"
|
||||||
tome_cast_button_cast: "咒語"
|
tome_cast_button_cast: "咒語"
|
||||||
tome_autocast_delay: "自動施法延遲"
|
tome_autocast_delay: "自動施法延遲"
|
||||||
tome_select_spell: "選擇一個法術"
|
tome_select_spell: "選擇一個法術"
|
||||||
tome_select_a_thang: "選擇人物來 "
|
tome_select_a_thang: "選擇一個人物來施放"
|
||||||
tome_available_spells: "可用的法術"
|
tome_available_spells: "可用的法術"
|
||||||
hud_continue: "繼續 (按 shift-空格)"
|
hud_continue: "繼續 (按 shift-空格)"
|
||||||
# spell_saved: "Spell Saved"
|
spell_saved: "咒語已儲存"
|
||||||
|
|
||||||
# admin:
|
# admin:
|
||||||
# av_title: "Admin Views"
|
# av_title: "Admin Views"
|
||||||
|
@ -245,33 +246,33 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
||||||
|
|
||||||
# general:
|
# general:
|
||||||
# and: "and"
|
# and: "and"
|
||||||
or: "或"
|
# or: "或"
|
||||||
name: "名字"
|
# name: "名字"
|
||||||
# body: "Body"
|
# body: "Body"
|
||||||
# version: "Version"
|
# version: "Version"
|
||||||
# commit_msg: "Commit Message"
|
# commit_msg: "Commit Message"
|
||||||
# version_history_for: "Version History for: "
|
# version_history_for: "Version History for: "
|
||||||
# results: "Results"
|
# results: "Results"
|
||||||
# description: "Description"
|
# description: "Description"
|
||||||
email: "郵箱"
|
# email: "Email"
|
||||||
message: "留言"
|
# message: "訊息"
|
||||||
|
|
||||||
# about:
|
about:
|
||||||
# who_is_codecombat: "Who is CodeCombat?"
|
who_is_codecombat: "什麼是CodeCombat?"
|
||||||
# why_codecombat: "Why CodeCombat?"
|
why_codecombat: "為什麼使用CodeCombat?"
|
||||||
# who_description_prefix: "together started CodeCombat in 2013. We also created "
|
who_description_prefix: "在2013年共同創立了CodeCombat. 在2008年, 我們創立了"
|
||||||
# who_description_suffix: "in 2008, growing it to the #1 web and iOS application for learning to write Chinese and Japanese characters."
|
who_description_suffix: ",排名第一的中、日文字的學習網頁及iOS系統應用程式。"
|
||||||
# who_description_ending: "Now it's time to teach people to write code."
|
who_description_ending: "這次,我們將教大家如何寫程式。"
|
||||||
# why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that."
|
why_paragraph_1: "當我們在研發Skritter時,George不會寫程式,所以常常無法展現他的想法。他嘗試去學,然而課程成果緩慢。他的室友曾想學習新技能,試過Codecademy,但厭倦了。每周也都有其他朋友投入Codecademy,卻都以失敗告終。我們發現,這與我們藉由Skritter所想解決的問題是一致的─人們需要的不是繁瑣又密集的課程, 而是快速而大量的練習。我們知道該如何改善這個情況。"
|
||||||
# why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it."
|
why_paragraph_2: "想學程式嗎? 你不需要課程。你需要的只是大量的時間去\"玩\"程式。"
|
||||||
# why_paragraph_3_prefix: "That's what programming is about. It's gotta be fun. Not fun like"
|
why_paragraph_3_prefix: "寫程式應該是有趣的。當然不是"
|
||||||
# why_paragraph_3_italic: "yay a badge"
|
why_paragraph_3_italic: "「耶!拿到獎章了。」"
|
||||||
# why_paragraph_3_center: "but fun like"
|
why_paragraph_3_center: "的有趣, 而是"
|
||||||
# why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!"
|
why_paragraph_3_italic_caps: "「媽我不要出去玩,我要寫完這段!」"
|
||||||
# why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing."
|
why_paragraph_3_suffix: "般引人入勝。這是為甚麼CodeCombat被設計成多人對戰「遊戲」,而不是遊戲化「課程」。在你對這遊戲無法自拔之前,我們是不會放棄的─幫然,這個遊戲,將是有益於你的。"
|
||||||
# why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age."
|
why_paragraph_4: "如果你要沉迷遊戲的話,就來沉迷CodeCombat,成為科技時代的魔法師吧!"
|
||||||
# why_ending: "And hey, it's free. "
|
why_ending: "啊還有,他是免費的。"
|
||||||
# why_ending_url: "Start wizarding now!"
|
why_ending_url: "那還等什麼? 馬上開始!"
|
||||||
# george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
|
# george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere."
|
||||||
# scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
|
# scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one."
|
||||||
# nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
|
# nick_description: "Programming wizard, eccentric motivation mage, and upside-down experimenter. Nick can do anything and chooses to build CodeCombat."
|
||||||
|
|
Loading…
Reference in a new issue