Files
procat2/cateditor/src/pagination.js
2019-05-31 01:41:56 -07:00

183 lines
4.2 KiB
JavaScript

const MAX_PAGE_MATERIALS = 16
const MATERIALS_PER_ROW = 4
const MAX_BLOCK_SIZE = 3
function chunkify(array, size) {
let chunks = []
for (let i = 0, j = array.length; i < j; i += size) {
let slice = array.slice(i, i + size)
chunks.push(slice)
}
return chunks
}
function copyModel(model) {
if (model) {
return JSON.parse(JSON.stringify(model))
} else {
console.error('no model to copy')
}
}
function copyModels(models) {
let copies = []
if (models) {
for (let model of models) {
let copy = copyModel(model)
copies.push(copy)
}
}
return copies
}
// split models with too many materials
function splitModels(models) {
let splits = []
for (let model of models) {
if (model.size > MAX_BLOCK_SIZE) {
let chunks = chunkify(model.ids, MAX_PAGE_MATERIALS)
for (let chunk of chunks) {
let splitModel = copyModel(model)
splitModel.ids = chunk
splits.push(splitModel)
}
} else {
splits.push(copyModel(model))
}
}
return splits
}
// join adjacent models with the same model number
function joinModels(models) {
let joins = []
let lastModel = null
for (let model of models) {
model = copyModel(model)
if (lastModel) {
if (lastModel.model === model.model) {
// match - join
lastModel.ids.push(...model.ids)
// uniquify
lastModel.ids = lastModel.ids.filter((v, i, a) => a.indexOf(v) === i)
} else {
// no match - add
joins.push(model)
lastModel = model
}
} else {
// first - add
joins.push(model)
lastModel = model
}
}
return joins
}
export function paginateModels(models) {
models = joinModels(models)
for (let model of models) {
model.size = modelBlockSize(model)
}
models = splitModels(models)
for (let model of models) {
model.size = modelBlockSize(model)
}
models = copyModels(models)
let pages = []
let currentSize = 0
let currentPage = []
for (let model of models) {
if (model.size < 1) {
// skip empty models
continue
}
currentSize += model.size
if (currentSize > 3) {
pages.push(currentPage)
currentPage = [model]
currentSize = model.size
} else {
currentPage.push(model)
}
}
if (currentPage.length > 0) {
pages.push(currentPage)
}
return pages
}
export function modelBlockSize(model) {
if (!model || !model.ids) return 0
if (model.ids.length <= MATERIALS_PER_ROW) return 1
if (model.ids.length <= MATERIALS_PER_ROW * 2) return 2
if (model.ids.length <= MATERIALS_PER_ROW * 4) return 3
return MAX_BLOCK_SIZE + 1 // generic "too big"
}
// de-paginate, essentially
export function modelsFromSection(section, getters) {
// remove pages, return models (blocks) in order.
// combine blocks with the same model number.
let models = []
if (section && section.pages) {
for (let page of section.pages) {
for (let model of page) {
model = copyModel(model)
if (model.ids && model.ids.length > 0) {
// add extra info from a material
let material = getters.material(model.ids[0])
if (material) {
model = extendModelFromMaterial(material, model)
} else {
console.log('no material found for id', model.ids[0])
}
models.push(model)
}
}
}
}
return joinModels(models)
}
export function sectionTitle(material) {
// "Trailhead (Men)"
if (material) {
return `${material.category} (${material.gender})`
} else {
return '(unknown)'
}
}
// add properties from the material to the model,
// creating it if necessary.
export function extendModelFromMaterial(material, model = {}) {
if (material) {
if (!model['name']) {
// don't overwrite possibly overridden value
model['name'] = material.name
}
model['model'] = material.model
model['family'] = material.family
model['gender'] = material.gender
model['category'] = material.category
// make sure the material id is in the list
let ids = model['ids'] || []
if (!ids.includes(material.id)) {
ids.push(material.id)
model['ids'] = ids
}
}
return model
}