2014-06-30 22:16:26 -04:00
mongoose = require ' mongoose '
jsonschema = require ' ../../app/schemas/models/achievement '
2014-05-21 13:47:17 -04:00
log = require ' winston '
2014-11-28 20:49:41 -05:00
utils = require ' ../../app/core/utils '
2014-06-09 11:28:35 -04:00
plugins = require ( ' ../plugins/plugins ' )
2014-06-13 12:04:25 -04:00
AchievablePlugin = require ' ../plugins/achievements '
2014-08-29 15:41:25 -04:00
TreemaUtils = require ' ../../bower_components/treema/treema-utils.js '
2015-03-21 21:49:32 -04:00
config = require ' ../../server_config '
2016-08-26 17:41:21 -04:00
co = require ' co '
2014-05-13 16:46:56 -04:00
# `pre` and `post` are not called for update operations executed directly on the database,
# including `Model.update`,`.findByIdAndUpdate`,`.findOneAndUpdate`, `.findOneAndRemove`,and `.findByIdAndRemove`.order
# to utilize `pre` or `post` middleware, you should `find()` the document, and call the `init`, `validate`, `save`,
# or `remove` functions on the document. See [explanation](http://github.com/LearnBoost/mongoose/issues/964).
AchievementSchema = new mongoose . Schema ( {
2014-05-21 13:47:17 -04:00
userField: String
2015-03-21 21:49:32 -04:00
} , { strict: false , read: config . mongo . readpref } )
2014-05-13 16:46:56 -04:00
2015-01-27 13:02:47 -05:00
AchievementSchema . index (
{
_fts: ' text '
_ftsx: 1
} ,
{
name: ' search index '
sparse: true
weights: { name: 1 }
default_language: ' english '
' language_override ' : ' language '
' textIndexVersion ' : 2
} )
AchievementSchema . index ( { i18nCoverage: 1 } , { name: ' translation coverage index ' , sparse: true } )
AchievementSchema . index ( { slug: 1 } , { name: ' slug index ' , sparse: true , unique: true } )
2015-12-03 14:15:34 -05:00
AchievementSchema . index ( { related: 1 } , { name: ' related index ' , sparse: true } )
2016-08-30 18:46:34 -04:00
AchievementSchema . index ( { updated: 1 } , { name: ' updated index ' } )
2015-01-27 13:02:47 -05:00
2014-06-03 06:40:47 -04:00
AchievementSchema.methods.objectifyQuery = ->
2014-05-21 13:47:17 -04:00
try
2014-06-30 22:16:26 -04:00
@ set ( ' query ' , JSON . parse ( @ get ( ' query ' ) ) ) if typeof @ get ( ' query ' ) == ' string '
2014-05-21 13:47:17 -04:00
catch error
2014-05-24 14:45:53 -04:00
log . error " Couldn ' t convert query string to object because of #{ error } "
2014-05-21 13:47:17 -04:00
@ set ( ' query ' , { } )
2014-06-03 06:40:47 -04:00
AchievementSchema.methods.stringifyQuery = ->
2014-06-30 22:16:26 -04:00
@ set ( ' query ' , JSON . stringify ( @ get ( ' query ' ) ) ) if typeof @ get ( ' query ' ) != ' string '
2014-05-21 13:47:17 -04:00
2014-06-14 09:34:23 -04:00
AchievementSchema.methods.getExpFunction = ->
2014-08-29 15:41:25 -04:00
func = @ get ( ' function ' ) ? { }
TreemaUtils . populateDefaults ( func , jsonschema . properties . function )
return utils . functionCreators [ func . kind ] ( func . parameters ) if func . kind of utils . functionCreators
2014-06-03 06:40:47 -04:00
2014-06-14 14:12:17 -04:00
AchievementSchema.statics.jsonschema = jsonschema
2015-02-13 20:10:30 -05:00
AchievementSchema.statics.achievementCollections = { }
2014-06-14 09:34:23 -04:00
2014-06-24 07:49:54 -04:00
# Reloads all achievements into memory.
# TODO might want to tweak this to only load new achievements
2016-08-26 17:41:21 -04:00
AchievementSchema.statics.loadAchievements = co . wrap ->
2014-06-14 09:34:23 -04:00
AchievementSchema . statics . resetAchievements ( )
2016-08-26 17:41:21 -04:00
t0 = new Date ( )
2016-04-06 13:56:06 -04:00
Achievement = require ( ' ./Achievement ' )
2016-08-26 17:41:21 -04:00
achievements = yield Achievement . find ( { collection: { $ne: ' level.sessions ' } } )
return if t0 < @ lastReset # if a test has run resetAchievements during the fetch, abort
for achievement in achievements
collection = achievement . get ' collection '
AchievementSchema . statics . achievementCollections [ collection ] ? = [ ]
if _ . find AchievementSchema . statics . achievementCollections [ collection ] , ( (a) -> a . get ( ' _id ' ) . toHexString ( ) is achievement . get ( ' _id ' ) . toHexString ( ) )
log . warn " Uh oh, we tried to add another copy of the same achievement #{ achievement . get ( ' _id ' ) } #{ achievement . get ( ' name ' ) } to the #{ collection } achievement list... "
else
AchievementSchema . statics . achievementCollections [ collection ] . push achievement
unless achievement . get ( ' query ' )
log . error " Uh oh, there is an achievement with an empty query: #{ achievement } "
return AchievementSchema . statics . achievementCollections
2014-06-14 09:34:23 -04:00
AchievementSchema.statics.getLoadedAchievements = ->
2015-02-13 20:10:30 -05:00
AchievementSchema . statics . achievementCollections
2014-06-14 09:34:23 -04:00
AchievementSchema.statics.resetAchievements = ->
2015-02-13 20:10:30 -05:00
delete AchievementSchema . statics . achievementCollections [ collection ] for collection of AchievementSchema . statics . achievementCollections
2016-08-26 17:41:21 -04:00
@lastReset = new Date ( )
2016-04-11 14:59:51 -04:00
AchievementSchema.statics.editableProperties = [
' name '
' query '
' worth '
' collection '
' description '
' userField '
' proportionalTo '
' icon '
' function '
' related '
' difficulty '
' category '
' rewards '
' i18n '
' i18nCoverage '
2016-08-24 10:37:08 -04:00
' hidden '
2016-04-11 14:59:51 -04:00
]
2016-08-24 18:46:35 -04:00
AchievementSchema.statics.postEditableProperties = [ ]
2016-04-11 14:59:51 -04:00
AchievementSchema.statics.jsonSchema = require ' ../../app/schemas/models/achievement '
2014-06-14 09:34:23 -04:00
2014-06-24 07:49:54 -04:00
# Queries are stored as JSON strings, objectify them upon loading
2014-06-13 12:04:25 -04:00
AchievementSchema . post ' init ' , (doc) -> doc . objectifyQuery ( )
2014-05-21 13:47:17 -04:00
2014-06-13 12:04:25 -04:00
AchievementSchema . pre ' save ' , (next) ->
2014-05-21 13:47:17 -04:00
@ stringifyQuery ( )
2016-08-30 18:46:34 -04:00
if not @ get ( ' updated ' )
@ set ( ' updated ' , new Date ( ) . toISOString ( ) )
2014-05-21 13:47:17 -04:00
next ( )
2014-06-13 12:04:25 -04:00
# Reload achievements upon save
2015-02-13 19:33:03 -05:00
# This is going to basically not work when there is more than one application server, right?
2014-06-14 09:34:23 -04:00
AchievementSchema . post ' save ' , -> @ constructor . loadAchievements ( )
2014-05-21 13:47:17 -04:00
2014-05-19 17:20:50 -04:00
AchievementSchema . plugin ( plugins . NamedPlugin )
2014-05-31 17:19:55 -04:00
AchievementSchema . plugin ( plugins . SearchablePlugin , { searchable: [ ' name ' ] } )
2014-10-27 20:11:48 -04:00
AchievementSchema . plugin plugins . TranslationCoveragePlugin
2015-02-05 15:01:19 -05:00
AchievementSchema . plugin plugins . PatchablePlugin
2014-06-09 11:28:35 -04:00
2014-07-03 15:20:06 -04:00
module.exports = Achievement = mongoose . model ( ' Achievement ' , AchievementSchema , ' achievements ' )
2014-06-10 14:05:32 -04:00
2014-06-14 09:34:23 -04:00
AchievementSchema . statics . loadAchievements ( )