-
Xiao Gui authored2f89da50
util.js 6.85 KiB
(function(exports) {
exports.camelToSnake = s => s.replace(/[A-Z]/g, s => `_${s.toLowerCase()}`)
const flattenReducer = (acc, curr) => acc.concat(curr)
exports.flattenReducer = flattenReducer
const getIdObj = fullId => {
if (!fullId) return null
if (typeof fullId === 'string') {
const re = /([a-z]{1,}\/[a-z]{1,}\/[a-z]{1,}\/v[0-9.]{1,})\/([0-9a-f-]{1,}$)/.exec(fullId)
if (re) return { kgSchema: re[1], kgId: re[2] }
return null
} else {
const { kg = {} } = fullId
const { kgSchema , kgId } = kg
if (!kgSchema || !kgId) return null
return { kgSchema, kgId }
}
}
const setsContain = (set1, set2) => {
for (const el of set2){
if (!set1.has(el)) return false
}
return true
}
const HEMISPHERE = {
LEFT_HEMISPHERE: `left`,
RIGHT_HEMISPHERE: `right`
}
exports.getRegionHemisphere = region => {
if (!region) return null
return (region.name && region.name.includes(' right') || (!!region.status && region.status.includes('right')))
? HEMISPHERE.RIGHT_HEMISPHERE
: (region.name && region.name.includes(' left') || (!!region.status && region.status.includes('left')))
? HEMISPHERE.LEFT_HEMISPHERE
: null
}
exports.setsContain = setsContain
exports.setsEql = (set1, set2) => {
if (set1.size !== set2.size) return false
if (!setsContain(set1, set2)) return false
if (!setsContain(set2, set1)) return false
return true
}
exports.arrayOrderedEql = function arrayOrderedEql(arr1, arr2) {
if (arr1.length !== arr2.length) return false
for (const idx in arr1) {
if (arr1[idx] !== arr2[idx]) return false
}
return true
}
exports.strToRgb = str => {
if (typeof str !== 'string') throw new Error(`strToRgb input must be typeof string !`)
let hash = 0
// run at least 2 cycles, or else, len 1 string does not get hashed well
for (let i = 0; i < str.length || i < 5; i++) {
hash = str.charCodeAt(i % str.length) + ((hash << 5) - hash);
}
const returnV = []
for (let i = 0; i < 3; i++) {
const value = (hash >> (i * 8)) & 0xFF;
returnV.push(value)
}
return returnV
}
exports.getUniqueRegionId = (template, parcellation, region) => {
const templateId = template ? (template['@id'] || template['name']) : `untitled-template`
const parcId = parcellation ? (parcellation['@id'] || parcellation['name']) : `untitled-parcellation`
const regionId = region ? region['name'] : `untitled-region`
return `${templateId}/${parcId}/${regionId}`
}
exports.getIdObj = getIdObj
exports.getIdFromKgIdObj = kg => {
if(kg.kgId && kg.kgSchema) {
return `${kg.kgSchema}/${kg.kgId}`
}
return null
}
exports.getIdFromFullId = fullId => {
const idObj = getIdObj(fullId)
if (!idObj) return null
const { kgSchema, kgId } = idObj
return `${kgSchema}/${kgId}`
}
const getIdsObj = fullId => {
const returnArray = []
if (!fullId) return returnArray
const legacyFullId = getIdObj(fullId)
if (legacyFullId) returnArray.push(`${legacyFullId['kgSchema']}/${legacyFullId['kgId']}`)
const { ['minds/core/parcellationregion/v1.0.0']: uniMindsParcRegScheIds} = fullId
for (const key in uniMindsParcRegScheIds || {}) {
returnArray.push(`minds/core/parcellationregion/v1.0.0/${key}`)
}
return returnArray
}
exports.getStringIdsFromRegion = region => {
const { fullId, relatedAreas = [] } = region
/**
* other ways of getting id?
*/
const relatedAreasId = relatedAreas
.map(({ fullId }) => getIdsObj(fullId))
.reduce(flattenReducer, [])
return [
...getIdsObj(fullId),
...relatedAreasId
]
}
const defaultConfig = {
timeout: 1000,
retries: 3
}
exports.retry = async (fn, { timeout = defaultConfig.timeout, retries = defaultConfig.retries } = defaultConfig) => {
let retryNo = 0
while (retryNo < retries) {
retryNo ++
try {
const result = await fn()
return result
} catch (e) {
console.warn(`fn failed, retry after ${timeout} milliseconds`)
await (() => new Promise(rs => setTimeout(rs, timeout)))()
}
}
throw new Error(`fn failed ${retries} times. Aborting.`)
}
exports.race = async (fn, { timeout = defaultConfig.timeout } = {}) => {
return Promise.race([
fn(),
new Promise((_rs, rj) => setTimeout(rj, timeout, `timed out: ${timeout}`))
])
}
const flattenRegions = regions => regions.concat(
...regions.map(region => region.children && region.children instanceof Array
? flattenRegions(region.children)
: [])
)
exports.flattenRegions = flattenRegions
exports.hexToRgb = hex => hex && hex.match(/[a-fA-F0-9]{2}/g).map(v => parseInt(v, 16))
exports.rgbToHex = rgb => rgb && `#${rgb.map(color => color.toString(16).padStart(2, '0')).join("")}`
exports.getRandomHex = (digit = 1024 * 1024 * 1024 * 1024) => Math.round(Math.random() * digit).toString(16)
/**
* No license defined
* https://gist.github.com/mjackson/5311256#file-color-conversion-algorithms-js
*/
exports.rgbToHsl = (r, g, b) => {
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [ h, s, l ];
}
exports.verifyPositionArg = val => {
return (
Array.isArray(val) &&
val.length === 3 &&
val.every(n =>
typeof n === 'number' &&
!Number.isNaN(n)
)
)
}
const getPad = ({ length, pad }) => {
if (pad.length !== 1) throw new Error(`pad needs to be precisely 1 character`)
return input => {
const padNum = Math.max(input.toString().length - length, 0)
const padString = Array(padNum).fill(pad).join('')
return `${padString}${input}`
}
}
exports.getDateString = () => {
const d = new Date()
const pad2 = getPad({ pad: '0', length: 2 })
const year = d.getFullYear()
const month = d.getMonth() + 1
const date = d.getDate()
const hr = d.getHours()
const min = d.getMinutes()
return `${year}${pad2(month)}${pad2(date)}_${pad2(hr)}${pad2(min)}`
}
function isVec4(input) {
if (!Array.isArray(input)) return false
if (input.length !== 4) return false
return input.every(v => typeof v === "number")
}
function isMat4(input) {
if (!Array.isArray(input)) return false
if (input.length !== 4) return false
return input.every(isVec4)
}
exports.isVec4 = isVec4
exports.isMat4 = isMat4
})(typeof exports === 'undefined' ? module.exports : exports)