183 lines
4.2 KiB
JavaScript
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
|
|
}
|