diff --git a/app/models/CocoModel.coffee b/app/models/CocoModel.coffee index f9b657ce8..f10035168 100644 --- a/app/models/CocoModel.coffee +++ b/app/models/CocoModel.coffee @@ -273,7 +273,7 @@ class CocoModel extends Backbone.Model achievements = new NewAchievementCollection achievements.fetch( success: (collection) -> - Backbone.Mediator.publish('achievements:new', collection) unless _.isEmpty(collection.models) + me.fetch (success: -> Backbone.Mediator.publish('achievements:new', collection)) unless _.isEmpty(collection.models) ) diff --git a/app/models/User.coffee b/app/models/User.coffee index 161a347f5..f224c85c9 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -78,13 +78,17 @@ module.exports = class User extends CocoModel a = 5 b = 40 - # y = a * ln(1/b * (x + b)) + # y = a * ln(1/b * (x + b)) + 1 @levelFromExp: (xp) -> - if xp > 0 then Math.floor(a * Math.log((1/b) * (xp + b))) else 0 + if xp > 0 then Math.floor(a * Math.log((1/b) * (xp + b))) + 1 else 1 - # x = (e^(y/a) - 1) * b + # x = (e^((y-1)/a) - 1) * b @expForLevel: (level) -> - Math.ceil((Math.exp(level / a) - 1) * b) + Math.ceil((Math.exp((level - 1)/ a) - 1) * b) level: -> - User.levelFromExp(@get('points')) \ No newline at end of file + User.levelFromExp(@get('points')) + + levelFromExp: (xp) -> User.levelFromExp(xp) + + expForLevel: (level) -> User.expForLevel(level) diff --git a/app/schemas/models/achievement.coffee b/app/schemas/models/achievement.coffee index 38f4a4e50..c064e969f 100644 --- a/app/schemas/models/achievement.coffee +++ b/app/schemas/models/achievement.coffee @@ -25,6 +25,7 @@ MongoFindQuerySchema = oneOf: [ #{ $ref: '#/definitions/' + MongoQueryOperatorSchema.id}, { type: 'string' } + { type: 'object' } ] additionalProperties: true # TODO make Treema accept new pattern matched keys definitions: {} @@ -49,6 +50,24 @@ _.extend(AchievementSchema.properties, proportionalTo: type: 'string' description: 'For repeatables only. Denotes the field a repeatable achievement needs for its calculations' + function: + type: 'object' + oneOf: [ + linear: + type: 'object' + properties: + a: {type: 'number', default: 1}, + required: ['a'] + description: 'f(x) = a * x' + logarithmic: + type:'object' + properties: + a: {type: 'number', default: 1} + b: {type: 'number', default: 1} + required: ['a', 'b'] + description: 'f(x) = a * ln(1/b * (x + b))' + ] + default: linear: a: 1 ) AchievementSchema.definitions = {} diff --git a/app/styles/notify.sass b/app/styles/notify.sass index c36e6b413..0a0b47cf1 100644 --- a/app/styles/notify.sass +++ b/app/styles/notify.sass @@ -1,10 +1,12 @@ .notifyjs-achievement-base - background: url("/images/pages/base/notify_mockup.png") + //background: url("/images/pages/base/notify_mockup.png") + background-image: url("/images/pages/base/modal_background.png") background-size: 100% 100% width: 500px height: 200px - padding: 35px 20px 15px 15px + padding: 35px 35px 15px 15px text-align: center + cursor: auto .achievement-body .achievement-image @@ -13,7 +15,10 @@ width: 100px height: 100px border-radius: 50% - margin: 30px 40px 20px 30px + margin: 20px 30px 20px 30px + -webkit-box-shadow: 0px 0px 36px 0px white + -moz-box-shadow: 0px 0px 36px 0px white + box-shadow: 0px 0px 36px 0px white .achievement-title font-family: Bangers @@ -23,13 +28,14 @@ margin-top: 10px font-size: 16px - .achievement-message - &:empty - display: none - - .achievement-progress - padding: 25px 0px 0px 0px + padding: 15px 0px 0px 0px + + .achievement-message + font-family: Bangers + font-size: 18px + &:empty + display: none .progress-wrapper .progress-bar-wrapper @@ -38,4 +44,4 @@ padding-left: 5px font-family: Bangers font-size: 16px - float: right \ No newline at end of file + float: right diff --git a/app/views/editor/achievement/edit.coffee b/app/views/editor/achievement/edit.coffee index 9c03af6a7..8a81befce 100644 --- a/app/views/editor/achievement/edit.coffee +++ b/app/views/editor/achievement/edit.coffee @@ -48,6 +48,7 @@ module.exports = class AchievementEditView extends View @treema = @$el.find('#achievement-treema').treema(options) @treema.build() + console.log @treema pushChangesToPreview: => 'TODO' # TODO might want some intrinsic preview thing @@ -73,4 +74,4 @@ module.exports = class AchievementEditView extends View res.success => url = "/editor/achievement/#{@achievement.get('slug') or @achievement.id}" - document.location.href = url \ No newline at end of file + document.location.href = url diff --git a/app/views/editor/achievement/home.coffee b/app/views/editor/achievement/home.coffee index f02be15b6..de8b7ce3b 100644 --- a/app/views/editor/achievement/home.coffee +++ b/app/views/editor/achievement/home.coffee @@ -8,11 +8,18 @@ module.exports = class AchievementSearchView extends SearchView tableTemplate: require 'templates/editor/achievement/table' projection: ['name', 'description', 'collection', 'slug'] + initialize: -> + console.log me.isAdmin() + unless me.isAdmin() + NotFoundView = require '../../not_found' + return new NotFoundView + else super() + getRenderData: -> context = super() context.currentEditor = 'editor.achievement_title' context.currentNew = 'editor.new_achievement_title' - context.currentNewSignup = 'editor.new_achievement_title_signup' + context.currentNewSignup = 'editor.new_achievement_title_login' context.currentSearch = 'editor.achievement_search_title' @$el.i18n() - context \ No newline at end of file + context diff --git a/app/views/kinds/RootView.coffee b/app/views/kinds/RootView.coffee index b6becd78f..fd036784b 100644 --- a/app/views/kinds/RootView.coffee +++ b/app/views/kinds/RootView.coffee @@ -39,17 +39,24 @@ module.exports = class RootView extends CocoView totalExpNeeded = nextLevelExp - currentLevelExp currentExp = me.get('points') worth = achievement.get('worth') - alreadyAchievedPercentage = 100 * (currentExp - currentLevelExp - achievement.get('worth')) / totalExpNeeded - newlyAchievedPercentage = 100 * achievement.get('worth') / totalExpNeeded + leveledUp = currentExp - worth < currentLevelExp + alreadyAchievedPercentage = 100 * (currentExp - currentLevelExp - worth) / totalExpNeeded + newlyAchievedPercentage = if currentLevelExp is currentExp then 0 else 100 * worth / totalExpNeeded console.debug "Current level is #{currentLevel} (#{currentLevelExp} xp), next level is #{nextLevel} (#{nextLevelExp} xp)." - console.debug "Need a total of #{nextLevelExp - currentLevelExp}, already had #{currentExp - currentLevelExp - worth} and just now earned #{worth}" + console.debug "Need a total of #{nextLevelExp - currentLevelExp}, already had #{currentExp - currentLevelExp - worth} and just now earned #{worth} totalling on #{currentExp}" alreadyAchievedBar = $("<div class='progress-bar progress-bar-warning' style='width:#{alreadyAchievedPercentage}%'></div>") - newlyAchievedBar = $("<div class='progress-bar progress-bar-success' style='width:#{newlyAchievedPercentage}%'></div>") - progressBar = $('<div class="progress"></div>').append(alreadyAchievedBar).append(newlyAchievedBar) - message = "Reached level #{currentLevel}!" if currentExp - worth < currentLevelExp + newlyAchievedBar = $("<div data-toggle='tooltip' class='progress-bar progress-bar-success' style='width:#{newlyAchievedPercentage}%'></div>") + emptyBar = $("<div data-toggle='tooltip' class='progress-bar progress-bar-white' style='width:#{100 - newlyAchievedPercentage - alreadyAchievedPercentage}%'></div>") + progressBar = $('<div class="progress" data-toggle="tooltip"></div>').append(alreadyAchievedBar).append(newlyAchievedBar).append(emptyBar) + message = if (currentLevel isnt 1) and leveledUp then "Reached level #{currentLevel}!" else null + alreadyAchievedBar.tooltip(title: "#{currentExp} XP in total") + newlyAchievedBar.tooltip(title: "#{worth} XP earned") + emptyBar.tooltip(title: "#{nextLevelExp - currentExp} XP until level #{nextLevel}") + + # TODO a default should be linked here imageURL = '/file/' + achievement.get('icon') data = title: achievement.get('name') @@ -60,11 +67,11 @@ module.exports = class RootView extends CocoView message: message options = - autoHideDelay: 15000 + autoHideDelay: 10000 globalPosition: 'bottom right' showDuration: 400 style: 'achievement' - autoHide: false + autoHide: true clickToHide: true $.notify( data, options ) diff --git a/server/achievements/Achievement.coffee b/server/achievements/Achievement.coffee index eff3bc857..faa625654 100644 --- a/server/achievements/Achievement.coffee +++ b/server/achievements/Achievement.coffee @@ -29,7 +29,7 @@ AchievementSchema.pre('save', (next) -> next() ) -AchievementSchema.plugin(plugins.SearchablePlugin, {searchable: ['name']}) AchievementSchema.plugin(plugins.NamedPlugin) +AchievementSchema.plugin(plugins.SearchablePlugin, {searchable: ['name']}) -module.exports = Achievement = mongoose.model('Achievement', AchievementSchema) \ No newline at end of file +module.exports = Achievement = mongoose.model('Achievement', AchievementSchema) diff --git a/server/commons/Handler.coffee b/server/commons/Handler.coffee index 199ae90b8..e8fdbd668 100644 --- a/server/commons/Handler.coffee +++ b/server/commons/Handler.coffee @@ -159,7 +159,7 @@ module.exports = class Handler return @sendNotFoundError(res) term = req.query.term matchedObjects = [] - filters = [{filter: {index: true}}] + filters = if @modelClass.schema.uses_coco_versions or @modelClass.schema.uses_coco_permissions then [filter: {index: true}] else [filter: {}] if @modelClass.schema.uses_coco_permissions and req.user filters.push {filter: {index: req.user.get('id')}} projection = null diff --git a/server/plugins/achievements.coffee b/server/plugins/achievements.coffee index 0975624da..70efd15fc 100644 --- a/server/plugins/achievements.coffee +++ b/server/plugins/achievements.coffee @@ -15,7 +15,6 @@ loadAchievements = -> category = achievement.get 'collection' achievements[category] = [] unless category of achievements achievements[category].push achievement - loadAchievements() module.exports = AchievablePlugin = (schema, options) -> @@ -62,11 +61,11 @@ module.exports = AchievablePlugin = (schema, options) -> console.error err if err? ) - if isRepeatable # TODO test more thoroughly + if isRepeatable console.log 'Upserting repeatable achievement called \'' + (achievement.get 'name') + '\' for ' + userID proportionalTo = achievement.get 'proportionalTo' originalAmount = util.getByPath(originalDocObj, proportionalTo) or 0 - newAmount = docObj.get proportionalTo + newAmount = docObj[proportionalTo] if originalAmount isnt newAmount earned.notified = false @@ -87,10 +86,5 @@ module.exports = AchievablePlugin = (schema, options) -> earnedPoints = achievement.get('worth') wrapUp() - - - - - delete before[doc.id] unless isNew # This assumes everything we patch has a _id - return \ No newline at end of file + return diff --git a/server/users/User.coffee b/server/users/User.coffee index 744b8db7b..f0cc8e514 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -127,3 +127,6 @@ UserSchema.statics.hashPassword = (password) -> shasum.digest('hex') module.exports = User = mongoose.model('User', UserSchema) + +AchievablePlugin = require '../plugins/achievements' +UserSchema.plugin(AchievablePlugin)