Merged db.coffee.

This commit is contained in:
Nick Winter 2015-02-18 09:07:49 -08:00
commit 96959169ee
15 changed files with 183 additions and 130 deletions

View file

@ -97,10 +97,15 @@ createQuadraticFunc = (params) ->
createLogFunc = (params) ->
(x) -> if x > 0 then (params.a or 1) * Math.log((params.b or 1) * (x + (params.c or 0))) + (params.d or 0) else 0
# f(x) = ax^b + c
createPowFunc = (params) ->
(x) -> (params.a or 1) * Math.pow(x, params.b or 1) + (params.c or 0)
module.exports.functionCreators =
linear: positify(createLinearFunc)
quadratic: positify(createQuadraticFunc)
logarithmic: positify(createLogFunc)
pow: positify(createPowFunc)
# Call done with true to satisfy the 'until' goal and stop repeating func
module.exports.keepDoingUntil = (func, wait=100, totalWait=5000) ->

View file

@ -649,9 +649,12 @@ module.exports.thangNames = thangNames =
]
'Ninja': [
'Amara'
'Itachi'
'Kosaraju'
'Madara'
'Minato'
'Naruto'
'Obito'
'Sakura'
'Sasuke'
'Shigeru'

View file

@ -19,8 +19,8 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
editor: "עורך"
blog: "בלוג"
forum: "פורום"
# account: "Account"
# profile: "Profile"
account: "חשבון"
profile: "פרופיל"
# stats: "Stats"
# code: "Code"
admin: "אדמין" # Only shows up when you are an admin
@ -30,7 +30,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
about: "עלינו"
contact: "צור קשר"
twitter_follow: "עקוב אחרינו בטוויטר"
# teachers: "Teachers"
teachers: "מורים"
modal:
close: "סגור"
@ -50,27 +50,27 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
play:
play_as: "שחק בתור " # Ladder page
spectate: "צופה" # Ladder page
# players: "players" # Hover over a level on /play
# hours_played: "hours played" # Hover over a level on /play
# items: "Items" # Tooltip on item shop button from /play
# unlock: "Unlock" # For purchasing items and heroes
# confirm: "Confirm"
# owned: "Owned" # For items you own
# locked: "Locked"
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
# available: "Available"
players: "שחקנים" # Hover over a level on /play
hours_played: "שעות משחק" # Hover over a level on /play
items: "כלים" # Tooltip on item shop button from /play
unlock: "קנה" # For purchasing items and heroes
confirm: "אשר"
owned: "נרכש" # For items you own
locked: "נעול"
purchasable: "ניתן לרכישה" # For a hero you unlocked but haven't purchased
available: "זמין"
# skills_granted: "Skills Granted" # Property documentation details
# heroes: "Heroes" # Tooltip on hero shop button from /play
# achievements: "Achievements" # Tooltip on achievement list button from /play
# account: "Account" # Tooltip on account button from /play
# settings: "Settings" # Tooltip on settings button from /play
# next: "Next" # Go from choose hero to choose inventory before playing a level
# change_hero: "Change Hero" # Go back from choose inventory to choose hero
heroes: "דמויות" # Tooltip on hero shop button from /play
achievements: "הישגים" # Tooltip on achievement list button from /play
account: "חשבון" # Tooltip on account button from /play
settings: "הגדרות" # Tooltip on settings button from /play
next: "הבא" # Go from choose hero to choose inventory before playing a level
change_hero: "שנה דמות" # Go back from choose inventory to choose hero
# choose_inventory: "Equip Items"
# buy_gems: "Buy Gems"
buy_gems: "רכש אבני חן"
# subscription_required: "Subscription Required"
# older_campaigns: "Older Campaigns"
# anonymous: "Anonymous Player"
anonymous: "משתמש אנונימי"
level_difficulty: "רמת קושי: "
campaign_beginner: "מסע המתחילים"
# awaiting_levels_adventurer_prefix: "We release five levels per week."
@ -92,22 +92,22 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# campaign_classic_algorithms: "Classic Algorithms"
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
# share_progress_modal:
# blurb: "Youre making great progress! Tell someone how much you've learned with CodeCombat."
# email_invalid: "Email address invalid."
share_progress_modal:
blurb: ".אתה מתקדם מצויין! ספר למישהו כמה למדת"
email_invalid: ".כתובת המייל שהוזנה שגויה"
# form_blurb: "Enter their email below and well show them!"
# form_label: "Email Address"
# placeholder: "email address"
form_label: "כתובת מייל"
placeholder: "כתובת המייל"
# title: "Excellent Work, Apprentice"
# tell_friend: "Tell your Friend"
# tell_parent: "Tell your Parent"
tell_friend: "ספר לחברים"
tell_parent: "ספר להורים"
login:
sign_up: "הירשם"
log_in: "היכנס"
# logging_in: "Logging In"
log_in: "תחברס"
logging_in: "מתחבר"
log_out: "צא"
# forgot_password: "Forgot your password?"
forgot_password: "שכחתי סיסמא"
# authenticate_gplus: "Authenticate G+"
# load_profile: "Load G+ Profile"
# load_email: "Load G+ Email"
@ -122,21 +122,21 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
sign_up: "הירשם"
log_in: "כנס עם סיסמה"
# social_signup: "Or, you can sign up through Facebook or G+:"
# required: "You need to log in before you can go that way."
# login_switch: "Already have an account?"
required: ".יש להתחבר על מנת לגשת לשלב זה"
login_switch: "? כבר יש לך משתמש"
recover:
recover_account_title: "שחזר סיסמה"
send_password: "שלח סיסמה חדשה"
# recovery_sent: "Recovery email sent."
recovery_sent: "מייל לשחזור סיסמא נשלח"
# items:
items:
# primary: "Primary"
# secondary: "Secondary"
# armor: "Armor"
armor: "שריון"
# accessories: "Accessories"
# misc: "Misc"
# books: "Books"
books: "ספרי כישוף"
common:
# back: "Back" # When used as an action verb, like "Navigate backward"
@ -144,19 +144,19 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
loading: "...טוען"
saving: "...שומר"
sending: "...שולח"
# send: "Send"
send: "שלח"
cancel: "ביטול"
save: "שמור"
# publish: "Publish"
# create: "Create"
publish: "פרסם"
create: "צור"
manual: "מדריך"
fork: "קילשון"
play: "שחק" # When used as an action verb, like "Play next level"
# retry: "Retry"
# actions: "Actions"
# info: "Info"
# help: "Help"
# watch: "Watch"
retry: "נסה שוב"
actions: "פעולות"
info: "מידע"
help: "עזרה"
watch: "צפה"
# unwatch: "Unwatch"
# submit_patch: "Submit Patch"
# submit_changes: "Submit Changes"

View file

@ -1,17 +1,17 @@
module.exports = nativeDescription: "मानक हिन्दी", englishDescription: "Hindi", translation:
# home:
# slogan: "Learn to Code by Playing a Game"
# no_ie: "CodeCombat does not run in Internet Explorer 8 or older. Sorry!" # Warning that only shows up in IE8 and older
# no_mobile: "CodeCombat wasn't designed for mobile devices and may not work!" # Warning that shows up on mobile devices
# play: "Play" # The big play button that opens up the campaign view.
home:
slogan: "खेल खेल के द्वारा कोड करना सीखें"
no_ie: "CodeCombat Internet Explorer 8 या पुराने में नहीं चलता है| असुविधा के लिए खेद है!" # Warning that only shows up in IE8 and older
no_mobile: "CodeCombat मोबाइल उपकरणों के लिए तैयार नहीं है और काम नहीं कर सकता!" # Warning that shows up on mobile devices
play: "खेलें " # The big play button that opens up the campaign view.
# old_browser: "Uh oh, your browser is too old to run CodeCombat. Sorry!" # Warning that shows up on really old Firefox/Chrome/Safari
# old_browser_suffix: "You can try anyway, but it probably won't work."
# ipad_browser: "Bad news: CodeCombat doesn't run on iPad in the browser. Good news: our native iPad app is awaiting Apple approval."
# campaign: "Campaign"
# for_beginners: "For Beginners"
# multiplayer: "Multiplayer" # Not currently shown on home page
# for_developers: "For Developers" # Not currently shown on home page.
# or_ipad: "Or download for iPad"
campaign: "अभियान"
for_beginners: "नौसिखिये के लिए"
multiplayer: "मल्टीप्लेयर" # Not currently shown on home page
for_developers: "डेवलपर्स के लिए" # Not currently shown on home page.
or_ipad: "या iPad के लिए डाउनलोड करें"
# nav:
# play: "Levels" # The top nav bar entry where players choose which levels to play

View file

@ -52,7 +52,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
spectate: "관중모드" # Ladder page
# players: "players" # Hover over a level on /play
# hours_played: "hours played" # Hover over a level on /play
# items: "Items" # Tooltip on item shop button from /play
items: "아이템" # Tooltip on item shop button from /play
# unlock: "Unlock" # For purchasing items and heroes
# confirm: "Confirm"
# owned: "Owned" # For items you own
@ -92,12 +92,12 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# campaign_classic_algorithms: "Classic Algorithms"
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
# share_progress_modal:
share_progress_modal:
# blurb: "Youre making great progress! Tell someone how much you've learned with CodeCombat."
# email_invalid: "Email address invalid."
# form_blurb: "Enter their email below and well show them!"
# form_label: "Email Address"
# placeholder: "email address"
form_label: "이메일"
placeholder: "이메일"
# title: "Excellent Work, Apprentice"
# tell_friend: "Tell your Friend"
# tell_parent: "Tell your Parent"
@ -130,13 +130,13 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
send_password: "복구 비밀번호 전송"
# recovery_sent: "Recovery email sent."
# items:
items:
# primary: "Primary"
# secondary: "Secondary"
# armor: "Armor"
armor: "갑옷"
# accessories: "Accessories"
# misc: "Misc"
# books: "Books"
books: ""
common:
# back: "Back" # When used as an action verb, like "Navigate backward"
@ -164,7 +164,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
general:
and: "그리고"
name: "이름"
# date: "Date"
date: "날짜"
body: "구성"
version: "버전"
# pending: "Pending"
@ -179,9 +179,9 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
version_history_for: "버전 히스토리 : "
# select_changes: "Select two changes below to see the difference."
# undo_prefix: "Undo"
# undo_shortcut: "(Ctrl+Z)"
undo_shortcut: "(Ctrl+Z)"
# redo_prefix: "Redo"
# redo_shortcut: "(Ctrl+Shift+Z)"
redo_shortcut: "(Ctrl+Shift+Z)"
# play_preview: "Play preview of current level"
result: "결과"
results: "결과들"
@ -205,25 +205,25 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
hard: "상급"
player: "플레이어"
# player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
# warrior: "Warrior"
# ranger: "Ranger"
# wizard: "Wizard"
warrior: "전사"
ranger: "레인저"
wizard: "마법사"
# units:
# second: "second"
# seconds: "seconds"
# minute: "minute"
# minutes: "minutes"
# hour: "hour"
# hours: "hours"
# day: "day"
# days: "days"
# week: "week"
# weeks: "weeks"
# month: "month"
# months: "months"
# year: "year"
# years: "years"
units:
second: ""
seconds: ""
minute: ""
minutes: ""
hour: "시간"
hours: "시간"
day: ""
days: ""
week: ""
weeks: ""
month: "개월"
months: "개월"
year: ""
years: ""
play_level:
done: "완료"
@ -355,13 +355,13 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# multiplayer_caption: "Play with friends!"
# auth_caption: "Save your progress."
# leaderboard:
leaderboard:
# leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_players: "Top Players by"
# day: "Today"
# week: "This Week"
day: "오늘"
week: "이번 주"
# all: "All-Time"
# time: "Time"
# damage_taken: "Damage Taken"
@ -433,7 +433,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
choose_hero:
# choose_hero: "Choose Your Hero"
# programming_language: "Programming Language"
programming_language: "프로그래밍 언어"
# programming_language_description: "Which programming language do you want to use?"
# default: "Default"
# experimental: "Experimental"
@ -444,7 +444,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
lua_blurb: "게임 스크립팅 언어"
io_blurb: "간단하지만 아직 잘 알려지지 않은 언어."
# status: "Status"
# weapons: "Weapons"
weapons: "무기"
# weapons_warrior: "Swords - Short Range, No Magic"
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic"
# weapons_wizard: "Wands, Staffs - Long Range, Magic"
@ -485,7 +485,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
options:
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
# volume_label: "Volume"
# music_label: "Music"
music_label: "음악"
# music_description: "Turn background music on/off."
# autorun_label: "Autorun"
# autorun_description: "Control automatic code execution."
@ -520,17 +520,17 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# press_paragraph_1_prefix: "Want to write about us? Feel free to download and use all of the resources included in our"
# press_paragraph_1_link: "press packet"
# press_paragraph_1_suffix: ". All logos and images may be used without contacting us directly."
# team: "Team"
# george_title: "CEO"
team: ""
george_title: "최고경영자"
# george_blurb: "Businesser"
# scott_title: "Programmer"
scott_title: "프로그래머"
# scott_blurb: "Reasonable One"
# nick_title: "Programmer"
nick_title: "프로그래머"
# nick_blurb: "Motivation Guru"
# michael_title: "Programmer"
michael_title: "프로그래머"
# michael_blurb: "Sys Admin"
# matt_title: "Programmer"
# matt_blurb: "Bicyclist"
matt_title: "프로그래머"
matt_blurb: "자전거 타는 사람"
# teachers:
# title: "CodeCombat for Teachers"
@ -588,7 +588,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
forum_page: "포럼"
forum_suffix: " 대신에."
# faq_prefix: "There's also a"
# faq: "FAQ"
faq: "자주 묻는 질문"
# 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."
@ -706,9 +706,9 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
revert: "되돌리기"
revert_models: "모델 되돌리기"
pick_a_terrain: "지형을 선택하세요."
# dungeon: "Dungeon"
dungeon: "지하 감옥"
# indoor: "Indoor"
# desert: "Desert"
desert: "사막"
grassy: "풀로 덮인"
small: "작게"
# large: "Large"
@ -1007,10 +1007,10 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# user_remark: "User Remark"
# user_remarks: "User Remarks"
# versions: "Versions"
# items: "Items"
items: "아이템"
# heroes: "Heroes"
# achievement: "Achievement"
# clas: "CLAs"
clas: "CLAs"
# play_counts: "Play Counts"
# feedback: "Feedback"
# payment_info: "Payment Info"

View file

@ -112,7 +112,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
load_profile: "Carregar Perfil do G+"
load_email: "Carregar E-mail do G+"
finishing: "A terminar"
sign_in_with_facebook: "Iniciar sessão com o Facebook"
sign_in_with_facebook: "Iniciar sessão com o F"
sign_in_with_gplus: "Iniciar sessão com o G+"
signup_switch: "Queres criar uma conta?"
@ -606,7 +606,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
me_tab: "Eu"
picture_tab: "Fotografia"
upload_picture: "Anexar uma fotografia"
# god_mode: "God Mode"
god_mode: "Modo Deus"
password_tab: "Palavra-passe"
emails_tab: "E-mails"
admin: "Administrador"
@ -860,7 +860,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
ratio: "Rácio"
leaderboard: "Tabela de Classificação"
battle_as: "Lutar como "
summary_your: "As tuas "
summary_your: "As Tuas "
summary_matches: "Partidas - "
summary_wins: " Vitórias, "
summary_losses: " Derrotas"

View file

@ -66,7 +66,7 @@ _.extend AchievementSchema.properties,
type: 'object'
description: 'Function that gives total experience for X amount achieved'
properties:
kind: {enum: ['linear', 'logarithmic', 'quadratic'] }
kind: {enum: ['linear', 'logarithmic', 'quadratic', 'pow'] }
parameters:
type: 'object'
default: { a: 1, b: 0, c: 0 }

View file

@ -424,7 +424,7 @@ $gameControlMargin: 30px
#volume-button
position: absolute
left: 1%
right: 1%
top: 1%
padding: 3px 8px
@include opacity(0.75)
@ -450,9 +450,9 @@ $gameControlMargin: 30px
#back-button
position: absolute
left: 70px
left: -webkit-calc(1% + 55px)
left: calc(1% + 55px)
right: 70px
right: -webkit-calc(1% + 55px)
right: calc(1% + 55px)
top: 1%
padding: 3px 8px
@include opacity(0.75)
@ -565,7 +565,12 @@ $gameControlMargin: 30px
margin-top: 30px
min-width: 100px
#small-nav-logo
position: absolute
top: 1%
left: 1%
height: 60px
z-index: 1
body.ipad #campaign-view
// iPad only supports up to Kithgard Gates for now.

View file

@ -1,3 +1,6 @@
a(href="/")
img#small-nav-logo(src="/images/pages/base/logo.png", title="CodeCombat - Learn how to code by playing a game", alt="CodeCombat")
if campaign
.map
.gradient.horizontal-gradient.top-gradient

View file

@ -250,6 +250,7 @@ module.exports = class InventoryModal extends ModalView
onUnequippedItemClick: (e) ->
return if @justDoubleClicked
return if @justClickedEquipItemButton
itemEl = $(e.target).closest('.item')
#@playSound 'menu-button-click'
@selectUnequippedItem(itemEl)
@ -270,6 +271,8 @@ module.exports = class InventoryModal extends ModalView
itemEl = $(e.target).closest('.item')
@selectUnequippedItem(itemEl)
@equipSelectedItem()
@justClickedEquipItemButton = true
_.defer => @justClickedEquipItemButton = false
#- Select/equip higher-level, all encompassing methods the callbacks all use

View file

@ -27,7 +27,7 @@ whenAllFinished = ->
async.parallel [
# Misc
(c) -> report UserHandler.recalculateStats, 'gamesCompleted', c
#(c) -> report UserHandler.recalculateStats, 'gamesCompleted', c
# Edits
(c) -> report UserHandler.recalculateStats, 'articleEdits', c

View file

@ -30,31 +30,31 @@ LevelSessionSchema.plugin(AchievablePlugin)
previous = {}
LevelSessionSchema.post 'init', (doc) ->
previous[doc.get 'id'] =
unless doc.previousStateInfo
doc.previousStateInfo =
'state.complete': doc.get 'state.complete'
'playtime': doc.get 'playtime'
playtime: doc.get 'playtime'
LevelSessionSchema.pre 'save', (next) ->
User = require '../../users/User' # Avoid mutual inclusion cycles
@set('changed', new Date())
id = @get('id')
initd = id of previous
initd = @previousStateInfo?
levelID = @get('levelID')
userID = @get('creator')
activeUserEvent = null
# Newly completed level
if not (initd and previous[id]['state']?['complete']) and @get('state.complete')
if not (initd and @previousStateInfo['state.complete']) and @get('state.complete')
User.update {_id: userID}, {$inc: 'stats.gamesCompleted': 1}, {}, (err, count) ->
log.error err if err?
activeUserEvent = "level-completed/#{levelID}"
# Spent at least 30s playing this level
if not initd and @get('playtime') >= 30 or initd and (@get('playtime') - previous[id]['playtime'] >= 30)
if not initd and @get('playtime') >= 30 or initd and (@get('playtime') - @previousStateInfo['playtime'] >= 30)
activeUserEvent = "level-playtime/#{levelID}"
delete previous[id] if initd
if activeUserEvent?
User.saveActiveUser userID, activeUserEvent, next
else

View file

@ -43,7 +43,9 @@ module.exports.setup = (app) ->
handler[req.route.method](req, res, parts[1..]...)
catch error
errorMessage = "Error trying db method #{req?.route?.method} route #{parts} from #{name}: #{error}"
# TODO: add user info to this log
if req.user?
userInfo = req.user.getUserInfo()
errorMessage += "\n-- User Info Id: #{userInfo.id} #{if req.user.isAnonymous() then '' else 'Email:'} #{userInfo.email}"
log.error(errorMessage)
log.error(error)
log.error(error.stack)

View file

@ -45,6 +45,12 @@ UserSchema.methods.isAdmin = ->
UserSchema.methods.isAnonymous = ->
@get 'anonymous'
UserSchema.methods.getUserInfo = ->
info =
id : @get('_id')
email : if @get('anonymous') then 'Unregistered User' else @get('email')
return info
UserSchema.methods.trackActivity = (activityName, increment) ->
now = new Date()
increment ?= parseInt increment or 1

View file

@ -518,18 +518,23 @@ UserHandler = class UserHandler extends Handler
countEdits = (model, done) ->
statKey = User.statsMapping.edits[model.modelName]
return done(new Error 'Could not resolve statKey for model') unless statKey?
userStream = User.find().stream()
userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false
usersTotal = 0
usersFinished = 0
numberRunning = 0
doneWithUser = (err) ->
log.error err if err?
++usersFinished
--numberRunning
userStream.resume()
done?() if streamFinished and usersFinished is usersTotal
userStream.on 'error', (err) -> log.error err
userStream.on 'close', -> streamFinished = true
userStream.on 'data', (user) ->
usersTotal += 1
++usersTotal
++numberRunning
userStream.pause() if numberRunning > 20
userObjectID = user.get('_id')
userStringID = userObjectID.toHexString()
@ -540,6 +545,7 @@ UserHandler = class UserHandler extends Handler
else
update = $unset: {}
update.$unset[statKey] = ''
console.log "... updating #{userStringID} patches #{statKey} to #{count}, #{usersTotal} players found so far." if count
User.findByIdAndUpdate user.get('_id'), update, (err) ->
log.error err if err?
doneWithUser()
@ -565,20 +571,26 @@ UserHandler = class UserHandler extends Handler
update = {}
update[method] = {}
update[method][statName] = count or ''
console.log "... updating #{user.get('_id')} patches #{JSON.stringify(query)} #{statName} to #{count}, #{usersTotal} players found so far." if count
User.findByIdAndUpdate user.get('_id'), update, doneUpdatingUser
userStream = User.find().stream()
userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false
usersTotal = 0
usersFinished = 0
numberRunning = 0
doneWithUser = (err) ->
log.error err if err?
++usersFinished
--numberRunning
userStream.resume()
done?() if streamFinished and usersFinished is usersTotal
userStream.on 'error', (err) -> log.error err
userStream.on 'close', -> streamFinished = true
userStream.on 'data', (user) ->
usersTotal += 1
++usersTotal
++numberRunning
userStream.pause() if numberRunning > 20
userObjectID = user.get '_id'
userStringID = userObjectID.toHexString()
# Extend query with a patch ownership test
@ -596,18 +608,23 @@ UserHandler = class UserHandler extends Handler
countPatchesByUsers = (query, statName, done) ->
Patch = require '../patches/Patch'
userStream = User.find().stream()
userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false
usersTotal = 0
usersFinished = 0
numberRunning = 0
doneWithUser = (err) ->
log.error err if err?
++usersFinished
--numberRunning
userStream.resume()
done?() if streamFinished and usersFinished is usersTotal
userStream.on 'error', (err) -> log.error err
userStream.on 'close', -> streamFinished = true
userStream.on 'data', (user) ->
usersTotal += 1
++usersTotal
++numberRunning
userStream.pause() if numberRunning > 20
userObjectID = user.get '_id'
userStringID = userObjectID.toHexString()
# Extend query with a patch ownership test
@ -618,28 +635,37 @@ UserHandler = class UserHandler extends Handler
update = {}
update[method] = {}
update[method][statName] = count or ''
console.log "... updating #{userStringID} patches #{query} to #{count}, #{usersTotal} players found so far." if count
User.findByIdAndUpdate user.get('_id'), update, doneWithUser
statRecalculators:
gamesCompleted: (done) ->
LevelSession = require '../levels/sessions/LevelSession'
userStream = User.find().stream()
userStream = User.find({anonymous: false}).sort('_id').stream()
streamFinished = false
usersTotal = 0
usersFinished = 0
numberRunning = 0
doneWithUser = (err) ->
log.error err if err?
++usersFinished
done?() if streamFinished and usersFinished is usersTotal
--numberRunning
userStream.resume()
if streamFinished and usersFinished is usersTotal
console.log "----------- Finished recalculating statistics for gamesCompleted for #{usersFinished} players. -----------"
done?()
userStream.on 'error', (err) -> log.error err
userStream.on 'close', -> streamFinished = true
userStream.on 'data', (user) ->
usersTotal += 1
++usersTotal
++numberRunning
userStream.pause() if numberRunning > 20
userID = user.get('_id').toHexString()
LevelSession.count {creator: userID, 'state.complete': true}, (err, count) ->
update = if count then {$set: 'stats.gamesCompleted': count} else {$unset: 'stats.gamesCompleted': ''}
console.log "... updating #{userID} gamesCompleted to #{count}, #{usersTotal} players found so far." if Math.random() < 0.001
User.findByIdAndUpdate user.get('_id'), update, doneWithUser
articleEdits: (done) ->