Merge pull request #2460 from codecombat/master

Merge into production
This commit is contained in:
Michael Schmatz 2015-03-02 19:22:27 -05:00
commit d7e8e2f729
9 changed files with 595 additions and 585 deletions

View file

@ -69,9 +69,3 @@ Whether you're novice or pro, the CodeCombat team is ready to help you implement
![Alex Crooks](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Alex%20Crooks/alex_100.png)
![Danny Whittaker](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Danny%20Whittaker/danny_100.png)
![Kevin Holland](https://dl.dropboxusercontent.com/u/138899/GitHub%20Wikis/avatars/Kevin%20Holland/kevin_100.png)
----------
[![](http://1-ps.googleusercontent.com/x/s.google-melange.appspot.com/www.google-melange.com/soc/content/2-1-20140225/images/gsoc/logo/920x156xbanner-gsoc2014.png.pagespeed.ic.gdr4t3Igca.png)](http://www.google-melange.com/gsoc/homepage/google/gsoc2014)

View file

@ -69,6 +69,10 @@
<script src="/javascripts/aether.js"></script>
<script src="/javascripts/app.js"></script>
<![endif]-->
<!-- IE9 cors support breaks analytics logging: http://caniuse.com/#feat=cors -->
<!--[if IE 9]>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.2/jquery.xdomainrequest.min.js"></script>
<![endif]-->
<![if (gt IE 9)|(!IE)]>
<script src="/lib/ace/ace.js" defer></script>
<script src="/javascripts/vendor.js" defer></script>

File diff suppressed because it is too large Load diff

View file

@ -336,6 +336,7 @@
tip_adding_evil: "Adding a pinch of evil."
tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
tip_open_source_contribute: "You can help CodeCombat improve!"
tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
game_menu:
inventory_tab: "Inventory"

View file

@ -76,7 +76,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
awaiting_levels_adventurer_prefix: "Minden héten öt új szintet teszünk elérhetővé."
awaiting_levels_adventurer: "Jelentkezz fel mint Kalandor"
awaiting_levels_adventurer_suffix: "legyél az első aki új szinteken játszik."
# adjust_volume: "Adjust volume"
adjust_volume: "Hangerő beállítása"
choose_your_level: "Válaszd ki a pályát!" # The rest of this section is the old play view at /play-old and isn't very important.
adventurer_prefix: "Továbbugorhatsz bármelyik pályára, amit lent látsz. Vagy megbeszélheted a pályát a többiekkel "
adventurer_forum: "a Kalandozók Fórumán"
@ -166,20 +166,20 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
date: "Dátum"
body: "Test"
version: "Verzió"
# pending: "Pending"
# accepted: "Accepted"
# rejected: "Rejected"
pending: "Függőben"
accepted: "Elfogadva"
rejected: "Elutasítva"
# withdrawn: "Withdrawn"
# submitter: "Submitter"
# submitted: "Submitted"
submitter: "Beküldő"
submitted: "Beküldött"
commit_msg: "Üzenet feladása"
review: "Áttekintés"
version_history: "Verzió történet"
version_history_for: "Verzió története ennek: "
select_changes: "Válassz két lehetőséget alul, hogy lásd a különbséget."
# undo_prefix: "Undo"
undo_prefix: "Visszavonás"
# undo_shortcut: "(Ctrl+Z)"
# redo_prefix: "Redo"
redo_prefix: "Mégis"
# redo_shortcut: "(Ctrl+Shift+Z)"
play_preview: "Aktuális szint előnézete"
result: "Eredmény"
@ -204,9 +204,9 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
hard: "Nehéz"
player: "Játékos"
player_level: "Szint" # Like player level 5, not like level: Dungeons of Kithgard
# warrior: "Warrior"
# ranger: "Ranger"
# wizard: "Wizard"
warrior: "Harcos"
ranger: "Távolsági"
wizard: "Varázsló"
units:
second: "másodperc"
@ -254,7 +254,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
victory_sign_up_poke: "Szeretnéd, ha levelet küldenénk neked az újításokról? Regisztrálj ingyen egy fiókot, és nem maradsz le semmiről!"
victory_rate_the_level: "Értékeld a pályát: " # Only in old-style levels.
victory_return_to_ladder: "Vissza a ranglétrához"
victory_play_continue: "Tavább"
victory_play_continue: "Tovább"
victory_saving_progress: "Folyamat mentése"
victory_go_home: "Vissza a kezdőoldalra" # Only in old-style levels.
victory_review: "Mondd el a véleményedet!" # Only in old-style levels.
@ -268,7 +268,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
tome_other_units: "Egyéb egységek" # Only in old-style levels.
tome_cast_button_run: "Fuss"
tome_cast_button_running: "Futás"
# tome_cast_button_ran: "Ran"
tome_cast_button_ran: "Lefutott"
tome_submit_button: "Bemutatás"
tome_reload_method: "Eredeti Módszer újratöltése" # Title text for individual method reload button.
tome_select_method: "Válassz Módszert"
@ -293,14 +293,14 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
infinite_loop_reset_level: "Szint újra"
infinite_loop_comment_out: "Tegye a kódom kommentárba"
tip_toggle_play: "Játék/Szünet kapcsoló Ctrl+P."
# tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward."
tip_scrub_shortcut: "Ctrl+[ és Ctrl+] visszatekerés és gyors-előre."
tip_guide_exists: "Hasznos információkért kattints az oldal tetején az útmutatóra.."
tip_open_source: "A CodeCombat 100%-osan nyitott forráskódu."
tip_beta_launch: "CodeCombat Béta teszt 2013 Októberétől elérhető."
tip_think_solution: "A megoldásra gondolj, ne a problémára!"
tip_theory_practice: "Elméletben nincs különbség elmélet és gyakorlat között. A gyakorlatban viszont van. - Yogi Berra"
tip_error_free: "Két módon lehet hibátlan programot írni. De csak a harmadik működik. - Alan Perlis"
# tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
tip_debugging_program: "Ha a hibakeresés az az eljárás amikor eltüntetjük a program hibákat, akkor a programozás biztosan az az eljárás amikor elhelyezzük őket. - Edsger W. Dijkstra"
tip_forums: "Irány a fórumok, és mondd el mit gondolsz!!"
tip_baby_coders: "A jövőben még a bébik is Főmágusok lesznek."
tip_morale_improves: "A töltés addig folytatódik, amíg a morál javul."
@ -323,15 +323,15 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
tip_brute_force: "Ha kérdésesa helyzet, használj nyers erőt. - Ken Thompson"
tip_extrapolation: "Csak két fajta ember létezik. Az egyik, aki extrapolál hiányos adatokból..."
tip_superpower: "A programozás képessége van legközelebb a szuperképességekhez."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
tip_control_destiny: "A valódi nyílt forráskódban, jogodban áll irányítani a sorsod. - Linus Torvalds"
# tip_no_code: "No code is faster than no code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# tip_source_code: "I want to change the world but they would not give me the source code."
tip_code_never_lies: "A kód sosem hazudik, a kommentek néha. — Ron Jeffries"
tip_reusable_software: "Mielőtt a szoftware újrafelhasználható lesz, előbb használhatónak kell lennie."
tip_optimization_operator: "Minden nyelvben van egy optimalizáló operátor. A legtöbb nyelvben ez a //"
tip_lines_of_code: "A programírás állapotát mérni a programsorok által olyan, mint a repülő építés állapotát mérni a repülő súlya által. — Bill Gates"
tip_source_code: "Meg akarom változtatni a világot, de nem adnák oda a forráskódját."
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
tip_move_forward: "Bármit is teszel, haladj előre. - Martin Luther King Jr."
# tip_google: "Have a problem you can't solve? Google it!"
# tip_adding_evil: "Adding a pinch of evil."
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
@ -354,19 +354,19 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
multiplayer_caption: "Játssz a barátaiddal!"
auth_caption: "Mentsd el a fejlődésed."
# leaderboard:
# leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_players: "Top Players by"
# day: "Today"
# week: "This Week"
# all: "All-Time"
# time: "Time"
# damage_taken: "Damage Taken"
# damage_dealt: "Damage Dealt"
# difficulty: "Difficulty"
# gold_collected: "Gold Collected"
leaderboard:
leaderboard: "Ranglétra"
view_other_solutions: "Más Megoldások Megtekintése"
scores: "Pontok"
top_solutions: "Legjobb megoldások"
day: "Ma"
week: "A Héten"
all: "Mindenkori"
time: "Idő"
damage_taken: "Kapott Sebzés"
damage_dealt: "Kiosztott Sebzés"
difficulty: "Nehézség"
gold_collected: "Összegyűjtött Arany"
inventory:
choose_inventory: "felszerelési tárgyak"
@ -391,36 +391,35 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
prompt_title: "Nincs elég drágaköved"
prompt_body: "Szeretnél többet?"
prompt_button: "Lépj be a boltba"
# recovered: "Previous gems purchase recovered. Please refresh the page."
# price: "x3500 / mo"
recovered: "Az előző drágakő vásárlás helyreállt. Kérlek frissítsd az oldalt."
subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
comparison_blurb: "Élesítsd képességeid CodeCombat feliratkozással!"
feature1: "60+ alap pálya, 4 világon át"
feature2: "7 erőteljes <strong>új hős</strong> egyedi képességekkel!"
feature3: "30+ bónusz pálya"
feature4: "<strong>3500 bónusz drágakő</strong> minden hónapban!"
feature5: "Videó oktatóanyagok"
feature6: "Prémium email támogatás"
free: "Ingyenes"
month: "hónap"
subscribe_title: "Feliratkozás"
unsubscribe: "Leiratkozás"
# confirm_unsubscribe: "Confirm Unsubscribe"
# never_mind: "Never Mind, I Still Love You"
# thank_you_months_prefix: "Thank you for supporting us these last"
# thank_you_months_suffix: "months."
# thank_you: "Thank you for supporting CodeCombat."
# sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
# unsubscribe_feedback_placeholder: "O, what have we done?"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
confirm_unsubscribe: "Leiratkozás megerősítése"
never_mind: "Nembaj, akkor is Szeretlek"
thank_you_months_prefix: "Köszönjük hogy támogattál minket az elmúlt"
thank_you_months_suffix: "hónapban."
thank_you: "Köszönjük hogy támogatod a CodeCombat-ot."
sorry_to_see_you_go: "Sajnáljuk hogy elmész. Kérlek tudasd velünk mit csinálhattunk volna jobban."
unsubscribe_feedback_placeholder: "O, mit tettünk?"
parent_button: "Kérdezd meg a szülődet"
parent_email_description: "Küldünk nekik emailt, hogy vehessenek neked CodeCombat feliratkozást."
parent_email_input_invalid: "Érvénytelen email cím"
parent_email_input_label: "Szülő email címe"
parent_email_input_placeholder: "Írd be szülőd email címét"
parent_email_send: "Email Küldés"
parent_email_sent: "Email elküldve!"
parent_email_title: "Mi a szülőd email címe?"
parents: "Szülőknek"
parents_title: "A gyereke programozni tanul majd."
parents_blurb1: "A CodeCombattal a gyereke valódi programozási feladatokon keresztül tanul. Egyszerű utasításokkal kezdenek, aztán további témákba is betekintést kapnak."
@ -428,7 +427,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
parents_blurb3: "100%-os pénzvisszafizetés garancia: 1-kattintásossal leiratkozhat."
stripe_description: "Havi feliratkozás"
subscription_required_to_play: "Ehhez a szinthez fel kell iratkoznod."
# unlock_help_videos: "Subscribe to unlock all video tutorials."
unlock_help_videos: "Iratkozz fel, hogy feloldd az összes videó oktatóanyagot."
choose_hero:
choose_hero: "Válassz hőst."
@ -608,7 +607,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
forum_page: "fórumban"
forum_suffix: " is."
# faq_prefix: "There's also a"
# faq: "FAQ"
faq: "GYIK"
# subscribe_prefix: "If you need help figuring out a level, please"
# subscribe: "buy a CodeCombat subscription"
# subscribe_suffix: "and we'll be happy to help you with your code."

View file

@ -73,3 +73,4 @@
strong.tip.rare(data-i18n='play_level.tip_hate_computers') That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven
strong.tip.rare
a(href="https://github.com/codecombat/codecombat/wiki", data-i18n='play_level.tip_open_source_contribute') You can help CodeCombat improve!
strong.tip.rare(data-i18n='play_level.tip_recurse') To iterate is human, to recurse divine. - L. Peter Deutsch

View file

@ -1,8 +1,10 @@
// To use: set the range you want below, make sure your environment has the stripe key, then run:
// node scripts/analytics/subscriptions.js
// node scripts/analytics/subscriptionStats.js
require('coffee-script');
require('coffee-script/register');
_ = require('lodash');
config = require('../../server_config');
if(config.stripe.secretKey.indexOf('sk_test_')==0) {
throw new Error('You should not run this on the test data... Get your environment in gear.');
@ -11,8 +13,8 @@ if(config.stripe.secretKey.indexOf('sk_test_')==0) {
stripe = require('stripe')(config.stripe.secretKey);
var range = {
gt: ''+(new Date('2015-01-01').getTime()/1000),
lt: ''+(new Date('2015-02-01').getTime()/1000)
gt: ''+(new Date('2015-02-01').getTime()/1000),
lt: ''+(new Date('2015-03-01').getTime()/1000)
};
begin = function(starting_after) {
@ -36,7 +38,7 @@ onInvoicesReceived = function(err, invoices) {
begin(invoices.data[i].id);
}
else {
console.log('How many customers paid for a subscription:', customersPaid.length);
console.log('How many customers paid for a subscription:', _.unique(customersPaid).length);
loadNewCustomers();
}
}

View file

@ -25,6 +25,7 @@ for section in splitByCategories
dir = fs.readdirSync 'app/locale'
for file in dir when not (file in ['locale.coffee', 'en.coffee'])
fileSource = fs.readFileSync 'app/locale/' + file, encoding='utf8'
contents = require('../app/locale/' + file)
categories = contents.translation
lines = ["module.exports = nativeDescription: \"#{contents.nativeDescription}\", englishDescription: \"#{contents.englishDescription}\", translation:"]
@ -44,6 +45,13 @@ for file in dir when not (file in ['locale.coffee', 'en.coffee'])
if commentsMap[enCat]? and commentsMap[enCat][enTag]?
comment = " \##{commentsMap[enCat][enTag]}"
if fileSource.search(new RegExp("#? #{enTag}: \"#{tag}\".*\{change\}.*")) >= 0 and comment.search(/.*\{change\}/) < 0
comment = " \#" + comment if comment is ""
comment = comment + " {change}"
lines.push "#{if tagMissing then '#' else ''} #{enTag}: \"#{tag}\"#{comment}"
newContents = lines.join('\n') + '\n'
fs.writeFileSync 'app/locale/' + file, newContents
enSource = enSource.replace /\s?(#\s)?\{change\}/g, ""
fs.writeFileSync 'app/locale/en.coffee', enSource

View file

@ -2,6 +2,8 @@ log = require 'winston'
mongoose = require 'mongoose'
plugins = require '../plugins/plugins'
utils = require '../lib/utils'
http = require 'http'
config = require '../../server_config'
AnalyticsLogEventSchema = new mongoose.Schema({
u: mongoose.Schema.Types.ObjectId
@ -17,74 +19,31 @@ AnalyticsLogEventSchema = new mongoose.Schema({
AnalyticsLogEventSchema.index({event: 1, _id: 1})
AnalyticsLogEventSchema.statics.logEvent = (user, event, properties={}) ->
# Replaces some keys and values with analytics string IDs to reduce the size of events
unless user?
log.warn 'No user given to analytics logEvent.'
return
# TODO: Replace methods inefficient, watch logEvent server perf.
doc = new AnalyticsLogEvent
user: user
event: event
properties: properties
if config.isProduction and not config.unittest
docString = JSON.stringify doc
headers =
"Content-Type":'application/json'
"Content-Length": docString.length
replaceKeys = (slimProperties, callback) ->
# Replace all slimProperties key values with string IDs
for key, value of slimProperties
if isNaN(parseInt(key))
utils.getAnalyticsStringID key, (stringID) ->
if stringID > 0
slimProperties[stringID] = value
delete slimProperties[key]
replaceKeys slimProperties, callback
else
callback()
return
callback()
replaceProperties = (slimProperties, callback) ->
# Replace select slimProperties property values with string IDs
for key, value of slimProperties
if key in ['level', 'levelID', 'label', 'style'] and isNaN(parseInt(value))
if key is 'levelID'
key = 'level'
slimProperties['level'] = _.cloneDeep slimProperties['levelID']
delete slimProperties['levelID']
utils.getAnalyticsStringID value, (stringID) ->
if stringID > 0
slimProperties[key] = stringID
replaceProperties slimProperties, callback
else
callback()
return
callback()
saveDoc = (eventID, slimProperties) ->
replaceProperties slimProperties, ->
replaceKeys slimProperties, ->
doc = new AnalyticsLogEvent
u: user
e: eventID
p: slimProperties
# TODO: Remove these legacy properties after we stop querying for them, sometime after ~3/10/15
user: user
event: event
properties: properties
doc.save()
utils.getAnalyticsStringID event, (eventID) ->
if eventID > 0
slimProperties = _.cloneDeep properties
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
# Event-specific updates
if event is 'Saw Victory'
delete slimProperties.level
if event is 'Heard Sprite' and slimProperties.message?
utils.getAnalyticsStringID slimProperties.message, (stringID) ->
slimProperties.message = stringID if stringID > 0
saveDoc eventID, slimProperties
return
saveDoc eventID, slimProperties
else
log.warn "Unable to get analytics string ID for " + event
options =
host: 'analytics.codecombat.com'
port: 80
path: '/analytics'
method: 'POST'
headers: headers
req = http.request options, (res) ->
req.on 'error', (e) -> log.warn e
req.write(docString)
req.end()
else
doc.save()
module.exports = AnalyticsLogEvent = mongoose.model('analytics.log.event', AnalyticsLogEventSchema)