2014-01-03 13:32:13 -05:00
|
|
|
GRAVATAR_URL = 'https://www.gravatar.com/'
|
|
|
|
cache = {}
|
2014-06-30 22:16:26 -04:00
|
|
|
CocoModel = require './CocoModel'
|
2014-07-09 14:23:05 -04:00
|
|
|
util = require 'lib/utils'
|
2014-11-04 10:52:23 -05:00
|
|
|
ThangType = require './ThangType'
|
2014-01-03 13:32:13 -05:00
|
|
|
|
|
|
|
module.exports = class User extends CocoModel
|
2014-06-30 22:16:26 -04:00
|
|
|
@className: 'User'
|
2014-04-22 14:11:08 -04:00
|
|
|
@schema: require 'schemas/models/user'
|
2014-06-30 22:16:26 -04:00
|
|
|
urlRoot: '/db/user'
|
2014-07-10 04:30:23 -04:00
|
|
|
notyErrors: false
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-07-30 16:23:43 -04:00
|
|
|
onLoaded: ->
|
|
|
|
CocoModel.pollAchievements() # Check for achievements on login
|
|
|
|
super arguments...
|
|
|
|
|
2014-09-01 12:11:10 -04:00
|
|
|
isAdmin: -> 'admin' in @get('permissions', true)
|
2014-08-23 14:07:52 -04:00
|
|
|
isAnonymous: -> @get('anonymous', true)
|
|
|
|
displayName: -> @get('name', true)
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-07-07 13:29:34 -04:00
|
|
|
getPhotoURL: (size=80, useJobProfilePhoto=false, useEmployerPageAvatar=false) ->
|
2014-04-10 20:54:28 -04:00
|
|
|
photoURL = if useJobProfilePhoto then @get('jobProfile')?.photoURL else null
|
|
|
|
photoURL ||= @get('photoURL')
|
|
|
|
if photoURL
|
2014-06-30 22:16:26 -04:00
|
|
|
prefix = if photoURL.search(/\?/) is -1 then '?' else '&'
|
2014-04-09 19:46:44 -04:00
|
|
|
return "#{photoURL}#{prefix}s=#{size}" if photoURL.search('http') isnt -1 # legacy
|
|
|
|
return "/file/#{photoURL}#{prefix}s=#{size}"
|
2014-07-07 13:29:34 -04:00
|
|
|
return "/db/user/#{@id}/avatar?s=#{size}&employerPageAvatar=#{useEmployerPageAvatar}"
|
2014-01-03 13:32:13 -05:00
|
|
|
|
2014-08-07 16:03:00 -04:00
|
|
|
getSlugOrID: -> @get('slug') or @get('_id')
|
|
|
|
|
2014-07-16 13:51:44 -04:00
|
|
|
set: ->
|
|
|
|
if arguments[0] is 'jobProfileApproved' and @get("jobProfileApproved") is false and not @get("jobProfileApprovedDate")
|
|
|
|
@set "jobProfileApprovedDate", (new Date()).toISOString()
|
|
|
|
super arguments...
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-07-10 14:50:16 -04:00
|
|
|
@getUnconflictedName: (name, done) ->
|
|
|
|
$.ajax "/auth/name/#{name}",
|
|
|
|
success: (data) -> done data.name
|
|
|
|
statusCode: 409: (data) ->
|
|
|
|
response = JSON.parse data.responseText
|
|
|
|
done response.name
|
|
|
|
|
2014-04-21 19:15:23 -04:00
|
|
|
getEnabledEmails: ->
|
2014-08-23 14:07:52 -04:00
|
|
|
(emailName for emailName, emailDoc of @get('emails', true) when emailDoc.enabled)
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-04-21 19:15:23 -04:00
|
|
|
setEmailSubscription: (name, enabled) ->
|
|
|
|
newSubs = _.clone(@get('emails')) or {}
|
|
|
|
(newSubs[name] ?= {}).enabled = enabled
|
|
|
|
@set 'emails', newSubs
|
2014-06-30 22:16:26 -04:00
|
|
|
|
2014-04-22 14:11:10 -04:00
|
|
|
isEmailSubscriptionEnabled: (name) -> (@get('emails') or {})[name]?.enabled
|
2014-05-26 12:21:56 -04:00
|
|
|
|
|
|
|
a = 5
|
2014-07-30 16:23:43 -04:00
|
|
|
b = 100
|
|
|
|
c = b
|
2014-05-26 12:21:56 -04:00
|
|
|
|
2014-07-30 16:23:43 -04:00
|
|
|
# y = a * ln(1/b * (x + c)) + 1
|
2014-05-26 12:21:56 -04:00
|
|
|
@levelFromExp: (xp) ->
|
2014-07-30 16:23:43 -04:00
|
|
|
if xp > 0 then Math.floor(a * Math.log((1/b) * (xp + c))) + 1 else 1
|
2014-05-26 12:21:56 -04:00
|
|
|
|
2014-07-30 16:23:43 -04:00
|
|
|
# x = b * e^((y-1)/a) - c
|
2014-05-26 12:21:56 -04:00
|
|
|
@expForLevel: (level) ->
|
2014-07-30 16:23:43 -04:00
|
|
|
if level > 1 then Math.ceil Math.exp((level - 1)/ a) * b - c else 0
|
2014-05-26 12:21:56 -04:00
|
|
|
|
2014-11-11 01:07:55 -05:00
|
|
|
@tierFromLevel: (level) ->
|
|
|
|
# TODO: math
|
|
|
|
# For now, just eyeball it.
|
|
|
|
tiersByLevel[Math.min(level, tiersByLevel.length - 1)]
|
|
|
|
|
|
|
|
@levelForTier: (tier) ->
|
|
|
|
# TODO: math
|
|
|
|
for tierThreshold, level in tiersByLevel
|
|
|
|
return level if tierThreshold >= tier
|
|
|
|
|
2014-05-26 12:21:56 -04:00
|
|
|
level: ->
|
2014-05-31 17:19:55 -04:00
|
|
|
User.levelFromExp(@get('points'))
|
2014-09-26 05:28:54 -04:00
|
|
|
|
2014-11-11 01:07:55 -05:00
|
|
|
tier: ->
|
|
|
|
User.tierFromLevel @level()
|
|
|
|
|
2014-09-26 05:28:54 -04:00
|
|
|
gems: ->
|
|
|
|
gemsEarned = @get('earned')?.gems ? 0
|
2014-11-01 17:15:57 -04:00
|
|
|
gemsPurchased = @get('purchased')?.gems ? 0
|
|
|
|
gemsSpent = @get('spent') ? 0
|
2014-09-26 05:28:54 -04:00
|
|
|
gemsEarned + gemsPurchased - gemsSpent
|
|
|
|
|
2014-11-11 19:36:44 -05:00
|
|
|
heroes: ->
|
|
|
|
heroes = (me.get('earned')?.heroes ? []).concat(me.get('purchased')?.heroes ? []).concat([ThangType.heroes.captain, ThangType.heroes.knight])
|
2014-11-15 15:46:57 -05:00
|
|
|
heroes = _.values ThangType.heroes if me.isAdmin()
|
2014-11-11 19:36:44 -05:00
|
|
|
heroes
|
2014-11-04 10:52:23 -05:00
|
|
|
items: -> (me.get('earned')?.items ? []).concat(me.get('purchased')?.items ? []).concat([ThangType.items['simple-boots']])
|
2014-11-01 17:15:57 -04:00
|
|
|
levels: -> (me.get('earned')?.levels ? []).concat(me.get('purchased')?.levels ? [])
|
|
|
|
ownsHero: (heroOriginal) -> heroOriginal in @heroes()
|
|
|
|
ownsItem: (itemOriginal) -> itemOriginal in @items()
|
|
|
|
ownsLevel: (levelOriginal) -> levelOriginal in @levels()
|
2014-10-23 19:36:59 -04:00
|
|
|
|
|
|
|
getBranchingGroup: ->
|
|
|
|
return @branchingGroup if @branchingGroup
|
|
|
|
group = me.get('testGroupNumber') % 4
|
|
|
|
@branchingGroup = switch group
|
|
|
|
when 0 then 'no-practice'
|
|
|
|
when 1 then 'all-practice'
|
|
|
|
when 2 then 'choice-explicit'
|
|
|
|
when 3 then 'choice-implicit'
|
|
|
|
@branchingGroup = 'choice-explicit' if me.isAdmin()
|
2014-11-05 13:40:37 -05:00
|
|
|
application.tracker.identify branchingGroup: @branchingGroup unless me.isAdmin()
|
2014-10-23 19:36:59 -04:00
|
|
|
@branchingGroup
|
2014-10-30 21:30:21 -04:00
|
|
|
|
2014-11-08 00:56:49 -05:00
|
|
|
getCastButtonTextGroup: ->
|
|
|
|
# Group 0 is original behavior
|
|
|
|
unless @castButtonTextGroup?
|
|
|
|
if me.isAdmin()
|
|
|
|
@castButtonTextGroup = 0
|
|
|
|
else
|
|
|
|
@castButtonTextGroup = me.get('testGroupNumber') % 7
|
|
|
|
application.tracker.identify castButtonTextGroup: @castButtonTextGroup
|
|
|
|
@castButtonTextGroup
|
|
|
|
|
2014-11-10 00:33:47 -05:00
|
|
|
getDirectFirstGroup: ->
|
2014-11-10 14:08:17 -05:00
|
|
|
# Group -1 is not participating
|
2014-11-10 00:33:47 -05:00
|
|
|
# Group 0 is original behavior
|
|
|
|
# Group 1 goes directly to first level if new user
|
2014-11-10 14:08:17 -05:00
|
|
|
# Targetting users with testGroupNumber < 128
|
2014-11-10 00:33:47 -05:00
|
|
|
unless @directFirstGroup?
|
2014-11-10 14:08:17 -05:00
|
|
|
if me.isAdmin() or me.get('testGroupNumber') >= 128
|
|
|
|
@directFirstGroup = -1
|
2014-11-10 00:33:47 -05:00
|
|
|
else
|
|
|
|
@directFirstGroup = me.get('testGroupNumber') % 2
|
|
|
|
application.tracker.identify directFirstGroup: @directFirstGroup
|
|
|
|
@directFirstGroup
|
|
|
|
|
2014-11-10 14:08:17 -05:00
|
|
|
getExperimentalLangGroup: ->
|
|
|
|
# Group -1 is not participating
|
|
|
|
# Group 0 is original behavior
|
|
|
|
# Group 1 isn't shown experimental languages in hero modal when launching beginner campaign level
|
|
|
|
# Targetting users with testGroupNumber >= 128
|
|
|
|
unless @experimentalLangGroup?
|
|
|
|
if me.isAdmin() or me.get('testGroupNumber') < 128
|
|
|
|
@experimentalLangGroup = -1
|
|
|
|
else
|
|
|
|
@experimentalLangGroup = me.get('testGroupNumber') % 2
|
|
|
|
application.tracker.identify experimentalLangGroup: @experimentalLangGroup
|
|
|
|
@experimentalLangGroup
|
|
|
|
|
2014-11-18 11:05:20 -05:00
|
|
|
## Test complete; feel free to repurpose for another test.
|
|
|
|
# https://mixpanel.com/report/227350/segmentation/#action:segment,arb_event:'Saw%20Victory',bool_op:and,chart_type:bar,from_date:-17,segfilter:!((filter:(operand:!('Dungeons%20of%20Kithgard'),operator:%3D%3D),property:level,selected_property_type:string,type:string),(filter:(operand:'',operator:set),property:highlightArrowGroup,selected_property_type:string,type:string),(property:highlightArrowGroup,selected_property_type:string,type:string)),segment_type:string,to_date:0,type:unique,unit:day
|
|
|
|
# https://www.dropbox.com/s/jot1ikz7nk7jti5/Screenshot%202014-11-18%2008.04.00.png?dl=0
|
|
|
|
#getHighlightArrowSoundGroup: ->
|
|
|
|
# return @highlightArrowGroup if @highlightArrowGroup
|
|
|
|
# group = me.get('testGroupNumber') % 8
|
|
|
|
# @highlightArrowGroup = switch group
|
|
|
|
# when 0, 1, 2, 3 then 'sound-off'
|
|
|
|
# when 4, 5, 6, 7 then 'sound-on'
|
|
|
|
# @highlightArrowGroup = 'sound-off' if me.isAdmin()
|
|
|
|
# application.tracker.identify highlightArrowGroup: @highlightArrowGroup unless me.isAdmin()
|
|
|
|
# @highlightArrowGroup
|
2014-11-05 13:40:37 -05:00
|
|
|
|
|
|
|
getKithmazeGroup: ->
|
|
|
|
return @kithmazeGroup if @kithmazeGroup
|
|
|
|
group = me.get('testGroupNumber') % 16
|
|
|
|
@kithmazeGroup = switch group
|
|
|
|
when 0, 1, 2, 3, 4, 5, 6, 7 then 'the-first-kithmaze'
|
|
|
|
when 8, 9, 10, 11, 12, 13, 14, 15 then 'haunted-kithmaze'
|
|
|
|
@kithmazeGroup = 'haunted-kithmaze' if me.isAdmin()
|
|
|
|
application.tracker.identify kithmazeGroup: @kithmazeGroup unless me.isAdmin()
|
|
|
|
@kithmazeGroup
|
2014-11-11 01:07:55 -05:00
|
|
|
|
|
|
|
tiersByLevel = [-1, 0, 0.05, 0.14, 0.18, 0.32, 0.41, 0.5, 0.64, 0.82, 0.91, 1.04, 1.22, 1.35, 1.48, 1.65, 1.78, 1.96, 2.1, 2.24, 2.38, 2.55, 2.69, 2.86, 3.03, 3.16, 3.29, 3.42, 3.58, 3.74, 3.89, 4.04, 4.19, 4.32, 4.47, 4.64, 4.79, 4.96]
|