memory-orm
Version:
client side ORM + map reduce
330 lines (329 loc) • 7.58 kB
JavaScript
'use strict'
Object.defineProperty(exports, '__esModule', { value: true })
exports.Map = void 0
const tslib_1 = require('tslib')
const get_1 = tslib_1.__importDefault(require('lodash/get'))
const set_1 = tslib_1.__importDefault(require('lodash/set'))
const orderBy_1 = tslib_1.__importDefault(require('lodash/orderBy'))
const Mem = tslib_1.__importStar(require('./userdata'))
function Dash(o, keys) {
Object.defineProperties(o, {
_diff: {
enumerable: false,
writable: true,
value: null,
},
diff: {
enumerable: false,
get() {
if (this._diff) {
return this._diff
}
this._diff = []
const end = this.length - 2
for (let idx = 0; idx < end; idx++) {
const a = this[idx]
const b = this[idx + 1]
const oo = {}
for (let key of keys) {
set_1.default(oo, key, get_1.default(b, key) - get_1.default(a, key))
}
this._diff.push(oo)
}
Dash(this._diff, keys)
return this._diff
},
},
})
return o
}
function navi_reduce(root) {
let is_did = false
for (const root_key of Object.keys(root)) {
const child = root[root_key]
if (!child) continue
const child_keys = Object.keys(child)
switch (child_keys.length) {
case 0:
is_did = true
root[root_key] = 0
break
case 1:
is_did = true
const new_key = child_keys[0]
const new_val = child[new_key]
delete root[root_key]
root[new_key] = new_val
break
default:
navi_reduce(child)
}
}
if (is_did) {
navi_reduce(root)
}
return root
}
class Map {
static bless(o) {
Reflect.setPrototypeOf(o, this.prototype)
return o
}
static init(o, cmd) {
if (cmd.id) {
o.id = cmd.id
}
if (cmd.list) {
o.list = []
}
if (cmd.count) {
o.count = 0
}
if (cmd.all) {
o.all = 0
}
if (cmd.count && cmd.all != null) {
o.variance_data = []
}
if (cmd.pow) {
o.pow = 0
}
if (cmd.set) {
o.hash = {}
}
if (cmd.navi) {
o.navi = {}
}
}
static reduce(query, path, item, o, cmd) {
if (!o) {
console.error('not found $format', path, cmd, query, item)
return
}
if (cmd.count) {
o.count += cmd.count
}
if (cmd.all) {
o.all += cmd.all
}
if (cmd.count && cmd.all != null) {
o.variance_data.push(cmd.all)
}
if (cmd.pow) {
o.pow *= cmd.pow
}
if (cmd.list) {
o.list.push(item)
}
if (cmd.set) {
o.hash[cmd.set] = item
}
if (cmd.max) {
if (cmd.max > o.max) {
o.max_is = item
o.max = cmd.max
}
}
if (cmd.min) {
if (o.min > cmd.min) {
o.min_is = item
o.min = cmd.min
}
}
if (cmd.navi) {
const head = []
let navi
let back = (navi = o.navi)
for (let idx of cmd.navi) {
head.push(idx)
const key = head.join('-')
back = navi
navi = navi[key] || (navi[key] = {})
}
}
}
static finish(query, path, o, list) {
if (!o) {
console.error('not found $format', path, query, list)
return
}
if (o.hash) {
o.set = Object.keys(o.hash)
}
if (o.count && o.pow != null) {
o.avg = Math.pow(o.pow, 1 / o.count)
}
if (o.count && o.all != null) {
o.avg = o.all * (1 / o.count)
}
const a = o.variance_data
if (a) {
delete o.variance_data
let sum = 0
for (let data of a) {
sum += Math.pow(data - o.avg, 2)
}
o.variance = sum / (o.count - 1)
o.sd = Math.pow(o.variance, 0.5)
o.standard = function (data) {
return (data - this.avg) / this.sd
}
}
if ('number' === typeof o.min && 'number' === typeof o.max) {
o.range = o.max - o.min
if (o.all) {
o.density = o.all / o.range
}
}
if (o.navi) {
navi_reduce(o.navi)
}
}
static order(query, path, from, origin, cmd, list) {
let o1 = from
if (cmd.belongs_to) {
if (o1 instanceof Array) {
for (const val of o1) {
Reflect.setPrototypeOf(val, Mem.Query[cmd.belongs_to].find(val.id))
}
} else {
for (const id in o1) {
const val = o1[id]
Reflect.setPrototypeOf(val, Mem.Query[cmd.belongs_to].find(id))
}
}
} else {
if (from instanceof Object) {
for (const id in from) {
const val = from[id]
// val.id = id
}
}
}
let o = o1
if (cmd.sort) {
o = orderBy_1.default(o, cmd.sort[0], cmd.sort[1])
}
const size = cmd.quantile
if (size) {
const pad = (o.length - 1) / size
const box = []
const end = size + 1
for (let i = 0; i < end; i++) {
box.push(o[Math.floor(i * pad)])
}
o.quantile = box
}
if (cmd.pluck) {
const ret = []
for (const oo of o) {
const val = get_1.default(oo, cmd.pluck)
if (val) {
ret.push(val)
}
}
o = ret
}
const key = cmd.index
if (key) {
let is_ary, counts
for (const ___ in o) {
const oo = o[___]
is_ary = 'number' === typeof get_1.default(oo, key)
counts = is_ary ? [] : {}
break
}
for (const ___ in o) {
const oo = o[___]
const idx = get_1.default(oo, key)
let a = counts[idx]
if (!a) {
counts[idx] = a = new list(query)
}
a.push(oo)
}
if (cmd.mode) {
let max_idx = null
let max_is = []
if (is_ary) {
const aa = counts
const end = aa.length
for (let idx = 0; idx < end; idx++) {
const a = aa[idx]
if (a && max_is.length < a.length) {
max_idx = idx
max_is = a
}
}
} else {
const aa = counts
for (const idx in aa) {
const a = aa[idx]
if (a && max_is.length < a.length) {
max_idx = idx
max_is = a
}
}
}
max_is.is_mode = max_idx
}
o = counts
}
return o
}
static dash(query, path, from, origin, cmd, list) {
if (!(from instanceof Array)) {
return from
}
let o = from
const keys = cmd.diff
if (keys) {
o = Dash(o, keys)
}
return o
}
static post_proc(query, path, from, origin, cmd, list) {
let per
let o = from
if (cmd.cover) {
const remain = []
const cover = []
for (let id of cmd.cover) {
if (origin[id]) {
cover.push(id)
} else {
remain.push(id)
}
}
o.remain = remain
o.cover = cover
}
if (cmd.page && (per = query.$page_by)) {
const p = []
p.all = from.length
for (let idx = 0; idx < from.length; idx++) {
let c
if (!(idx % per)) {
c = new list(query)
p.push(c)
}
const oo = from[idx]
c.push(oo)
}
p.page_idx = function (item) {
for (let page_idx = 0; page_idx < this.length; page_idx++) {
const a = this[page_idx]
if (a.includes(item)) {
return page_idx
}
}
return null
}
return p
} else {
return o
}
}
}
exports.Map = Map
//# sourceMappingURL=map.js.map