segments: Joi.func(), order: Joi.array().items(Joi.object().keys({ member: Joi.func().required(), direction: Joi.any().valid('asc', 'desc').required() })), filters: Joi.array().items(Joi.object().keys({ member: Joi.func().required(), operator: Joi.any().valid('contains', 'notContains', 'equals', 'set', 'notSet', 'gt', 'gte', 'lt', 'lte'), params: Joi.array().items(Joi.string().allow('').optional()) })), timeDimension: Joi.object().keys({ dimension: Joi.func().required(), dateRange: Joi.string().required(), granularity: Joi.any().valid('hour', 'day', 'week', 'month', 'year', null) }), visualization: Joi.object().keys({ type: Joi.any().valid('bar', 'line', 'table', 'area', 'singleValue', 'pie').required(), autoScale: Joi.boolean(), showTotal: Joi.boolean(), }), layout: Joi.object().keys({ w: Joi.any().valid(...Array(19).fill(0).map((_, i) => i + 6)).required(), h: Joi.any().valid(...Array(47).fill(0).map((_, i) => i + 4)).required(), x: Joi.any().valid(...Array(24).fill(0).map((_, i) => i)).required(), y: Joi.number().required() }).required() })