'user strict'
const { ErrorCodes } = require('../Errors/ErrorCodes')
const { capitalize } = require('./Capitalize')
const { RankBuilder } = require('../Structures/RankBuilder')
const { AchievementType } = require('../Interfaces')
const { AchievementBuilder } = require('../Structures/AchievementBuilder')
const { isNotPositiveInteger } = require('./ValidateInteger')
const { MissingValue, InvalidValue, AchievementInvalidProgress } = require('../Errors/LME')
/** @typedef {import('../../typings').Rank} Rank */
/** @typedef {import('../../typings').Achievement} Achievement */
/**
* Validates RankBuilder/Rank and AchievementBuilder/Achievement instances and objects.
*/
class ValRnkAchv {
/**
* Validate a AchievementBuilder/Achievement instance or object.
* @param {AchievementBuilder|Achievement} validate - The AchievementBuilder/Achievement instance or object to validate.
* @returns {Boolean} - Returns true if the AchievementBuilder/Achievement instance or object is valid.
*
* @throws {MissingValue} - If the validate argument is missing.
* @throws {InvalidValue} - If the validate argument is not a AchievementBuilder instance or an object.
*/
static validateAchievement (validate) {
if (!validate) throw new MissingValue(ErrorCodes.MissingArgument, 'validate')
if (!(validate instanceof AchievementBuilder) && typeof validate !== 'object') throw new InvalidValue(ErrorCodes.InvalidValue, 'validate', 'a or AchievementBuilder instance or an object.')
/** @type {import('../../typings').Achievement} */
const data = validate instanceof AchievementBuilder ? validate.toJSON() : validate
const achievementProperties = ['name', 'description', 'reward', 'type', 'progress']
for (const key of achievementProperties) data[key] ??= undefined
// We loop through the data object and call the corresponding setter method.
for (const [key, value] of Object.entries(data)) this[`set${capitalize(key)}`](value)
return true
}
/**
* Validate a RankBuilder/Rank instance or object.
* @param {RankBuilder|Rank} validate - The RankBuilder/Rank instance or object to validate.
* @returns {Boolean} - Returns true if the RankBuilder/Rank instance or object is valid.
*
* @throws {MissingValue} - If the validate argument is missing.
* @throws {InvalidValue} - If the validate argument is not a RankBuilder instance or an object.
*/
static validateRank (validate) {
if (!validate) throw new MissingValue(ErrorCodes.MissingArgument, 'validate')
if (!(validate instanceof RankBuilder) && typeof validate !== 'object') throw new InvalidValue(ErrorCodes.InvalidValue, 'validate', 'a RankBuilder instance or an object.')
/** @type {import('../../typings').Rank} */
let data
// Depending on the type of the validate argument, we do different things.
if (validate instanceof RankBuilder) data = validate.toJSON()
else data = validate
const rankProperties = ['nameplate', 'color', 'priority', 'max', 'min']
for (const key of rankProperties) data[key] ??= undefined
// We loop through the data object and call the corresponding setter method.
for (const [key, value] of Object.entries(data)) this[`set${capitalize(key)}`](value)
return true
}
static setNameplate (nameplate) {
if (!nameplate) throw new MissingValue(ErrorCodes.MissingProperty, 'nameplate')
if (typeof nameplate !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'nameplate', 'a string')
return true
}
static setColor (color) {
if (!color) throw new MissingValue(ErrorCodes.MissingProperty, 'color')
if (typeof color !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'color', 'a string')
return true
}
static setPriority (priority) {
if (!priority) throw new MissingValue(ErrorCodes.MissingProperty, 'priority')
if (isNotPositiveInteger(priority)) throw new InvalidValue(ErrorCodes.InvalidValue, 'priority', 'a positive integer')
return true
}
static setMax (max) {
if (!max) throw new MissingValue(ErrorCodes.MissingProperty, 'max')
if (isNotPositiveInteger(max)) throw new InvalidValue(ErrorCodes.InvalidValue, 'max', 'a positive integer')
return true
}
static setMin (min) {
if (!min) throw new MissingValue(ErrorCodes.MissingProperty, 'min')
if (isNotPositiveInteger(min)) throw new InvalidValue(ErrorCodes.InvalidValue, 'min', 'a positive integer')
return true
}
static setName (name) {
if (!name) throw new MissingValue(ErrorCodes.MissingProperty, 'name')
if (typeof name !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'name', 'a string')
return true
}
static setDescription (description) {
if (!description) throw new MissingValue(ErrorCodes.MissingProperty, 'description')
if (typeof description !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'description', 'a string')
return true
}
static setReward (reward) {
if (!reward) throw new MissingValue(ErrorCodes.MissingProperty, 'reward')
if (isNotPositiveInteger(reward)) throw new InvalidValue(ErrorCodes.InvalidValue, 'reward', 'a positive integer')
return true
}
static setType (type) {
if (!type) throw new MissingValue(ErrorCodes.MissingProperty, 'type')
if (!Object.values(AchievementType).includes(type)) throw new InvalidValue(ErrorCodes.InvalidValue, 'type', 'a valid achievement type.')
return true
}
static setThumbnail (thumbnail) {
if (!thumbnail) return undefined
if (thumbnail && typeof thumbnail !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'thumbnail', 'a string')
return true
}
static setProgress (progress) {
if (!progress) throw new MissingValue(ErrorCodes.MissingProperty, 'progress')
if (!Array.isArray(progress) || progress.length !== 2) throw new AchievementInvalidProgress(ErrorCodes.AchievementInvalidProgress)
if (progress.some(v => typeof v !== 'number' || v < 0 || isNaN(v) || !isFinite(v) || v % 1 !== 0)) throw new AchievementInvalidProgress(ErrorCodes.InvalidValue, 'progress', 'an array of two positive integers.')
if (progress[0] > progress[1]) throw new AchievementInvalidProgress(ErrorCodes.AchievementGraterProgress)
return true
}
}
module.exports = { ValRnkAchv }