common.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. import math from './math.js'
  2. import * as THREE from 'three'
  3. var common = {
  4. valueFromHash(e, t) {
  5. var i = new RegExp('[#&?]' + e + '=([^#&?]*)'),
  6. n = i.exec(window.location.href)
  7. if (!n) return t
  8. var r = n[1]
  9. return 'boolean' == typeof t ? 'true' === r || '1' === r : 'number' == typeof t ? parseFloat(r) : window.decodeURIComponent(r)
  10. },
  11. lowerMedian(e, t) {
  12. if (0 === e.length) return null
  13. ;(t = t || 2),
  14. e.sort(function (e, t) {
  15. return e - t
  16. })
  17. var i = Math.floor(e.length / t)
  18. return e[i]
  19. },
  20. stableSort(e, t) {
  21. return e
  22. .map(function (e, t) {
  23. return {
  24. value: e,
  25. index: t,
  26. }
  27. })
  28. .sort(function (e, i) {
  29. var n = t(e.value, i.value)
  30. return 0 !== n ? n : e.index - i.index
  31. })
  32. .map(function (e) {
  33. return e.value
  34. })
  35. },
  36. sortByScore: function (list, request, rank) {
  37. var i = request ? common.filterAll(list, request) : list
  38. return 0 === i.length
  39. ? []
  40. : (i = i
  41. .map(function (e) {
  42. let scores = rank.map(function (f) {
  43. return f(e)
  44. }) //add
  45. return {
  46. item: e,
  47. scores,
  48. score: scores.reduce(function (t, i) {
  49. return t + i
  50. }, 0),
  51. }
  52. })
  53. .sort(function (e, t) {
  54. return t.score - e.score
  55. }))
  56. },
  57. filterAll(e, t) {
  58. return e.filter(function (e) {
  59. return t.every(function (t) {
  60. return t(e)
  61. })
  62. })
  63. },
  64. getMixedSet: function (arr1, arr2) {
  65. //交集
  66. return arr1.filter(item => arr2.includes(item))
  67. },
  68. getUnionSet: function (arr1, arr2) {
  69. //并集
  70. return arr1.concat(arr2.filter(item => !arr1.includes(item)))
  71. },
  72. getDifferenceSet: function (arr1, arr2) {
  73. //差集 不能识别重复的,如getDifferenceSet([1,2,2],[1,1,2]) 为空
  74. var arr11 = arr1.filter(item => !arr2.includes(item))
  75. var arr22 = arr2.filter(item => !arr1.includes(item))
  76. return arr11.concat(arr22)
  77. },
  78. getDifferenceSetMuti: function (arr) {
  79. //收集绝对没有重复的元素,也就是判断出现次数=1的
  80. var set = []
  81. arr.forEach(arr1 => {
  82. arr1.forEach(item => {
  83. var index = set.indexOf(item)
  84. if (index > -1) {
  85. set.splice(index, 1)
  86. } else {
  87. set.push(item)
  88. }
  89. })
  90. })
  91. return set
  92. },
  93. pushToGroupAuto: function (items, groups, recognizeFunction, judgeRelationFun) {
  94. //自动分组。 items是将分到一起的组合。items.length = 1 or 2.
  95. let isSame = (a, b) => {
  96. return a == b || (recognizeFunction && recognizeFunction(a, b))
  97. }
  98. var atGroups = groups.filter(group =>
  99. group.find(
  100. item => (isSame(item, items[0]) || isSame(item, items[1])) && (!judgeRelationFun || judgeRelationFun(group)) //根据关系进一步判断是否应该一组
  101. )
  102. )
  103. if (atGroups.length) {
  104. //在不同组
  105. //因为items是一组的,所以先都放入组1
  106. items.forEach(item => {
  107. if (!atGroups[0].includes(item)) atGroups[0].push(item)
  108. })
  109. if (atGroups.length > 1) {
  110. //如果在不同组,说明这两个组需要合并
  111. var combineGroup = []
  112. combineGroup.relationships = [items.slice()]
  113. atGroups.forEach(group => {
  114. let relationships = common.getUnionSet(combineGroup.relationships, group.relationships)
  115. combineGroup = common.getUnionSet(combineGroup, group)
  116. combineGroup.relationships = relationships
  117. groups.splice(groups.indexOf(group), 1)
  118. })
  119. groups.push(combineGroup)
  120. } else {
  121. atGroups[0].relationships.push(items.slice())
  122. }
  123. } else {
  124. //直接加入为一组
  125. items.relationships = [items.slice()]
  126. groups.push(items)
  127. }
  128. },
  129. disconnectGroup: function (pairs, groups, recognizeFunction) {
  130. //将atGroup中的pairs关系解除,然后重新分组
  131. let isSame = (a, b) => {
  132. return a == b || (recognizeFunction && recognizeFunction(a, b))
  133. }
  134. let oldGroups = groups.slice()
  135. pairs.forEach(items => {
  136. let relationship
  137. let atGroup = groups.find(group => {
  138. let r = group.relationships.find(arr => items.every(e => arr.some(a => isSame(a, e))))
  139. if (r) {
  140. relationship = r
  141. return true
  142. }
  143. }) //能找到relationships 有包含items的, 代表它们有绑定关系
  144. if (!atGroup) return
  145. //断开连接时,因为组内没有其他成员的连接信息,所以需要清除整组,并将剩余的一个个重新连接
  146. groups.splice(groups.indexOf(atGroup), 1) //删除
  147. atGroup.relationships.splice(atGroup.relationships.indexOf(relationship), 1)
  148. let newGroups_ = [] //为了防止裂解的该组(因之前有judgeRelationFun但现在没传)混入其他组,先放一个空组合里
  149. atGroup.relationships.forEach(pair => {
  150. //然后再重新生成这两个和组的关系,各自分组
  151. common.pushToGroupAuto(pair, newGroups_, recognizeFunction)
  152. })
  153. groups.push(...newGroups_)
  154. })
  155. let newGroups = groups.filter(e => !oldGroups.includes(e))
  156. return { newGroups }
  157. },
  158. removeFromGroup: function (items, atGroup, groups, recognizeFunction) {
  159. //将该组移除items中的所有元素,以及包含它的关系
  160. let isSame = (a, b) => {
  161. return a == b || (recognizeFunction && recognizeFunction(a, b))
  162. }
  163. let newRelations = atGroup.relationships.filter(arr => !arr.some(e => items.some(item => isSame(e, item))))
  164. if (newRelations.length == atGroup.relationships) return
  165. //断开连接时,因为组内没有其他成员的连接信息,所以需要清除整组,并将剩余的一个个重新连接
  166. groups.splice(groups.indexOf(atGroup), 1) //删除
  167. let newGroups = [] //为了防止裂解的该组(因之前有judgeRelationFun但现在没传)混入其他组,先放一个空组合里
  168. atGroup.relationships.forEach(pair => {
  169. //然后再重新生成这两个和组的关系,各自分组
  170. common.pushToGroupAuto(pair, newGroups, recognizeFunction)
  171. })
  172. groups.push(...newGroups)
  173. return { newGroups }
  174. },
  175. }
  176. common.dataURLtoBlob = function (dataurl) {
  177. //将base64转换blob
  178. var arr = dataurl.split(','),
  179. mime = arr[0].match(/:(.*?);/)[1],
  180. bstr = atob(arr[1]),
  181. n = bstr.length,
  182. u8arr = new Uint8Array(n)
  183. while (n--) {
  184. u8arr[n] = bstr.charCodeAt(n)
  185. }
  186. return new Blob([u8arr], { type: mime })
  187. }
  188. common.dataURLtoFile = function (dataurl, filename) {
  189. //将base64转换为文件
  190. var arr = dataurl.split(','),
  191. mime = arr[0].match(/:(.*?);/)[1],
  192. bstr = atob(arr[1]),
  193. n = bstr.length,
  194. u8arr = new Uint8Array(n)
  195. while (n--) {
  196. u8arr[n] = bstr.charCodeAt(n)
  197. }
  198. return new File([u8arr], filename, { type: mime })
  199. }
  200. common.saveFile = function (data, filename, cb) {
  201. var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a')
  202. save_link.href = data
  203. save_link.download = filename
  204. var event = document.createEvent('MouseEvents')
  205. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
  206. save_link.dispatchEvent(event)
  207. cb && cb()
  208. }
  209. common.replaceAll = function (str, f, e) {
  210. //f全部替换成e
  211. var reg = new RegExp(f, 'g') //创建正则RegExp对象
  212. return str.replace(reg, e)
  213. }
  214. common.randomWord = function (randomFlag, min, max) {
  215. //随机字符串
  216. var str = '',
  217. range = min,
  218. arr = [
  219. '0',
  220. '1',
  221. '2',
  222. '3',
  223. '4',
  224. '5',
  225. '6',
  226. '7',
  227. '8',
  228. '9',
  229. 'a',
  230. 'b',
  231. 'c',
  232. 'd',
  233. 'e',
  234. 'f',
  235. 'g',
  236. 'h',
  237. 'i',
  238. 'j',
  239. 'k',
  240. 'l',
  241. 'm',
  242. 'n',
  243. 'o',
  244. 'p',
  245. 'q',
  246. 'r',
  247. 's',
  248. 't',
  249. 'u',
  250. 'v',
  251. 'w',
  252. 'x',
  253. 'y',
  254. 'z',
  255. 'A',
  256. 'B',
  257. 'C',
  258. 'D',
  259. 'E',
  260. 'F',
  261. 'G',
  262. 'H',
  263. 'I',
  264. 'J',
  265. 'K',
  266. 'L',
  267. 'M',
  268. 'N',
  269. 'O',
  270. 'P',
  271. 'Q',
  272. 'R',
  273. 'S',
  274. 'T',
  275. 'U',
  276. 'V',
  277. 'W',
  278. 'X',
  279. 'Y',
  280. 'Z',
  281. ]
  282. if (randomFlag) {
  283. // 随机长度
  284. range = Math.round(Math.random() * (max - min)) + min
  285. }
  286. for (var i = 0; i < range; i++) {
  287. var pos = Math.round(Math.random() * (arr.length - 1))
  288. str += arr[pos]
  289. }
  290. return str
  291. }
  292. common.getRandomSid = function () {
  293. //5-7位随机字符串 + 6位时间 为热点准备
  294. var pre = common.randomWord(true, 5, 7)
  295. var post = new Date().getTime() + ''
  296. var len = post.length
  297. post = post.substring(len - 8, len - 5) + post.substring(len - 3, len) //其实还是有可能重复的....
  298. return pre + post
  299. }
  300. common.getTime = function (second) {
  301. //秒
  302. var str = '' //不支持大于60分钟的时间哟
  303. var minute = parseInt(second / 60)
  304. if (minute < 10) str += '0'
  305. str += minute
  306. second = parseInt(second % 60) + ''
  307. if (second.length == 1) second = '0' + second
  308. str = str + ':' + second
  309. return str
  310. }
  311. ;(common.CloneJson = function (data) {
  312. var str = JSON.stringify(data)
  313. return JSON.parse(str)
  314. }),
  315. (common.CloneObject = function (copyObj, isSimpleCopy, simpleCopyList = [], judgeSimpleCopyFun) {
  316. //isSimpleCopy 只复制最外层
  317. //复制json result的可能:普通数字或字符串、普通数组、复杂对象
  318. simpleCopyList.includes(THREE.Object3D) || simpleCopyList.push(THREE.Object3D) //遇到simpleCopyList中的类直接使用不拷贝
  319. judgeSimpleCopyFun || (judgeSimpleCopyFun=()=>{})
  320. if (!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className) || judgeSimpleCopyFun(copyObj)) {
  321. return copyObj
  322. }
  323. if (copyObj instanceof Array) {
  324. return copyObj.map(e => {
  325. return this.CloneObject(e, isSimpleCopy, simpleCopyList, judgeSimpleCopyFun)
  326. })
  327. } else {
  328. if (copyObj.clone instanceof Function) {
  329. //解决一部分
  330. return copyObj.clone()
  331. }
  332. }
  333. let result = {}
  334. for (var key in copyObj) {
  335. if (copyObj[key] instanceof Object && !isSimpleCopy ) result[key] = this.CloneObject(copyObj[key], isSimpleCopy, simpleCopyList, judgeSimpleCopyFun)
  336. else result[key] = copyObj[key]
  337. //如果是函数类同基本数据,即复制引用
  338. }
  339. return result
  340. }),
  341. (common.CloneClassObject = function (copyObj) {
  342. //复杂类对象
  343. var newobj = new copyObj.constructor()
  344. this.CopyClassObject(newobj, copyObj)
  345. return newobj
  346. }),
  347. (common.CopyClassObject = function (targetObj, copyObj) {
  348. //复杂类对象
  349. for (let i in copyObj) {
  350. if (i in copyObj.__proto__) break //到函数了跳出
  351. targetObj[i] = this.CloneObject(copyObj[i])
  352. }
  353. }),
  354. (common.ifSame = function (object1, object2) {
  355. if (object1 == object2) return true
  356. // 0 != undefined , 0 == ''
  357. else if (!object1 || !object2) return false
  358. else if (object1.constructor != object2.constructor) {
  359. return false
  360. } else if (object1 instanceof Array) {
  361. if (object1.length != object2.length) return false
  362. var _object2 = object2.slice(0)
  363. for (let i = 0; i < object1.length; i++) {
  364. var u = _object2.find(e => ifSame(object1[i], e))
  365. if (u == void 0 && !_object2.includes(u) && !object1.includes(u)) return false
  366. else {
  367. let index = _object2.indexOf(u)
  368. _object2.splice(index, 1)
  369. }
  370. }
  371. return true
  372. } else if (object1.equals instanceof Function) {
  373. //复杂数据仅支持这种,其他的可能卡住?
  374. return object1.equals(object2)
  375. } else if (typeof object1 == 'number' || typeof object1 == 'string') {
  376. if (isNaN(object1) && isNaN(object2)) return true
  377. else return object1 == object2
  378. } else if (typeof object1 == 'object') {
  379. var keys1 = Object.keys(object1)
  380. var keys2 = Object.keys(object2)
  381. if (!ifSame(keys1, keys2)) return false
  382. for (let i in object1) {
  383. var same = ifSame(object1[i], object2[i])
  384. if (!same) return false
  385. }
  386. return true
  387. } else {
  388. console.log('isSame出现例外')
  389. }
  390. })
  391. common.intervalTool = {
  392. //延时update,防止卡顿
  393. list: [],
  394. isWaiting: function (name, func, delayTime) {
  395. let item = this.list.find(e => e.name == name)
  396. if (!item) {
  397. //如果没有该项, 则加入循环
  398. let ifContinue = func()
  399. item = { name }
  400. this.list.push(item)
  401. setTimeout(() => {
  402. var a = this.list.indexOf(item)
  403. this.list.splice(a, 1)
  404. if (item.requestUpdate || ifContinue) this.isWaiting(name, func, delayTime) //循环
  405. }, delayTime)
  406. } else {
  407. //如果有该项,说明现在请求下一次继续更新
  408. /* if(delayTime == 0){//想立刻更新一次
  409. func()
  410. }else{ */
  411. item.requestUpdate = true
  412. //}
  413. }
  414. },
  415. }
  416. common.batchHandling = {
  417. //分批处理
  418. lists: [],
  419. getSlice: function (name, items, { stopWhenAllUsed, minCount = 5, maxCount = 100, durBound1, durBound2, maxUseCount }) {
  420. if (
  421. items.length == 0 ||
  422. ((maxUseCount = maxUseCount == void 0 ? common.getBestCount({ name, minCount, maxCount, durBound1, durBound2, ifLog: false }) : maxUseCount), !maxUseCount) //本次最多可以使用的个数
  423. ) {
  424. return { list: [] }
  425. }
  426. if (!this.lists[name]) this.lists[name] = { list: [] }
  427. //更新列表项目,但不变原来的顺序
  428. let list = this.lists[name].list.filter(a => items.some(item => a.item == item)) //去掉已经不在items里的项目
  429. this.lists[name].list = list
  430. items.forEach(item => {
  431. //增加新的项目。
  432. if (!list.some(a => a.item == item)) {
  433. list.push({ item, count: 0 })
  434. }
  435. })
  436. //至此,在后排的都是未使用的
  437. let unUsed = list.filter(e => e.count == 0) //未使用的项目(count为0)优先
  438. let result = []
  439. unUsed.slice(0, maxUseCount).forEach(e => {
  440. result.push(e.item)
  441. e.count++
  442. })
  443. if (unUsed.length > maxUseCount) {
  444. //还是剩有未使用的项目,等待下一次
  445. } else {
  446. //所有项目都能使用一次
  447. if (!stopWhenAllUsed) {
  448. //若不是全部使用就停止
  449. let wholeCount = Math.min(items.length, maxUseCount)
  450. let restCount = wholeCount - result.length //补齐
  451. list.slice(0, restCount).forEach(e => {
  452. result.push(e.item)
  453. e.count++
  454. })
  455. }
  456. list.forEach(e => e.count--) //复原,等待新的循环
  457. }
  458. return { list: result }
  459. },
  460. addSliceListen({ getList, callback, minCount, maxCount, durBound1, durBound2, maxHistory, player }) {
  461. let unUpdate, lastUpdate
  462. player.on('update', e => {
  463. if (player.flying) return
  464. let waitForUpdate = getList()
  465. let stopWhenAllUsed = !player.lastFrameChanged
  466. let standardUpdate = player.lastFrameChanged || !lastUpdate //相机变化或第一次
  467. let list
  468. if (standardUpdate) {
  469. list = waitForUpdate
  470. unUpdate = null
  471. } else {
  472. if (!unUpdate) {
  473. unUpdate = common.getDifferenceSet(waitForUpdate, lastUpdate)
  474. //unUpdate = unUpdate.filter(e => e.visible) //如飞出后最后一次更新之后,都隐藏了,隐藏的就不用更新了
  475. }
  476. list = unUpdate
  477. }
  478. let result = common.batchHandling.getSlice('ifVideoInsight', list, { stopWhenAllUsed, minCount, maxCount, durBound1: 3, durBound2: 13, maxHistory: 3 }) //iphonex稳定后大概在7-10。
  479. let updateList = result.list
  480. //updateList.length && console.log(updateList.map(e=>e.sid))
  481. updateList.forEach(callback)
  482. if (!standardUpdate) {
  483. //相机停止变化后只更新还未更新的
  484. unUpdate = common.getDifferenceSet(unUpdate, updateList)
  485. }
  486. lastUpdate = updateList
  487. })
  488. },
  489. }
  490. common.getBestCount = (function () {
  491. let lastCount = {}
  492. return function ({ name, minCount = 1, maxCount = 6, durBound1 = 1, durBound2 = 4, ifLog, maxHistory }) {
  493. let timeStamp = performance.getEntriesByName('loop-start')
  494. let count
  495. if (timeStamp.length) {
  496. let dur = performance.now() - timeStamp[timeStamp.length - 1].startTime
  497. /*let k = -(maxCount - minCount) / (durBound2 - durBound1)
  498. let m = maxCount - durBound1 * k
  499. count = THREE.MathUtils.clamp(Math.round(k * dur + m), minCount, maxCount) //dur在iphoneX中静止有7,pc是2
  500. */
  501. count = Math.round(math.linearClamp(dur, durBound1, durBound2, maxCount, minCount))
  502. if (maxHistory) {
  503. if (!lastCount[name]) lastCount[name] = []
  504. if (count == 0 && lastCount[name].length > maxHistory - 1 && !lastCount[name].some(e => e > 0)) {
  505. count = 1
  506. }
  507. lastCount[name].push(count)
  508. if (lastCount[name].length > maxHistory) lastCount[name].splice(0, 1)
  509. }
  510. ifLog && console.log(name, count, ' ,dur:', dur.toFixed(3))
  511. } else {
  512. count = maxCount // ?
  513. }
  514. //主要在手机端有效果。
  515. return count
  516. }
  517. })()
  518. common.timeMeasuring = {
  519. reportTimings: false,
  520. collection: {},
  521. registerCollect(name, o) {
  522. this.collection[name] = o
  523. o.measures = []
  524. o.sum = 0
  525. },
  526. addTimeMark: function (name, type, ifLog) {
  527. let record = this.collection[name]
  528. let now = performance.now()
  529. let needRecord = record && (record.measures.length < record.minCount || now - record.lastAddTime > record.refreshTime) //间隔时间超过refreshTime重新收集
  530. if (needRecord || this.reportTimings) {
  531. if (type == 'end' && performance.getEntriesByName(name + '-start').length == 0) return
  532. performance.mark(name + '-' + type)
  533. if (type == 'end') {
  534. let measure = performance.measure(name, name + '-start', name + '-end')
  535. if (!measure) {
  536. //console.error('没找到measure',name) //可能是其他地方报错了没进行下去所以找不到
  537. return
  538. }
  539. if (ifLog) console.log(name, '耗时', measure.duration.toFixed(3))
  540. if (needRecord) {
  541. if (record.measures.length >= record.minCount) {
  542. //先清空上一轮的
  543. record.measures = []
  544. record.sum = 0
  545. }
  546. record.measures.push(measure.duration)
  547. record.sum += measure.duration
  548. record.mean = record.sum / record.measures.length
  549. record.measures.sort((a, b) => a - b)
  550. record.median = record.measures[parseInt(record.measures.length / 2)]
  551. record.lastAddTime = now
  552. if (record.measures.length == record.minCount) {
  553. //console.log(record)
  554. }
  555. }
  556. }
  557. }
  558. },
  559. report: function (timestamp) {
  560. //原resolveTimings
  561. //打印用时。 注:performance手机的精度只到整数位
  562. if (!this.toggle) {
  563. this.toggle = timestamp
  564. }
  565. let duration = timestamp - this.toggle
  566. if (duration > 1000.0) {
  567. if (this.reportTimings) {
  568. let measures = performance.getEntriesByType('measure')
  569. let names = new Set()
  570. for (let measure of measures) {
  571. names.add(measure.name)
  572. }
  573. let groups = new Map()
  574. for (let name of names) {
  575. groups.set(name, {
  576. measures: [],
  577. sum: 0,
  578. n: 0,
  579. min: Infinity,
  580. max: -Infinity,
  581. })
  582. }
  583. for (let measure of measures) {
  584. let group = groups.get(measure.name)
  585. group.measures.push(measure)
  586. group.sum += measure.duration
  587. group.n++
  588. group.min = Math.min(group.min, measure.duration)
  589. group.max = Math.max(group.max, measure.duration)
  590. }
  591. for (let [name, group] of groups) {
  592. group.mean = group.sum / group.n
  593. group.measures.sort((a, b) => a.duration - b.duration)
  594. if (group.n === 1) {
  595. group.median = group.measures[0].duration
  596. } else if (group.n > 1) {
  597. group.median = group.measures[parseInt(group.n / 2)].duration
  598. }
  599. }
  600. let cn = Array.from(names).reduce((a, i) => Math.max(a, i.length), 0) + 5
  601. let cmin = 5
  602. let cmed = 5
  603. let cmax = 5
  604. let csam = 4
  605. let message =
  606. ` ${'NAME'.padEnd(cn)} |` +
  607. ` ${'MIN'.padStart(cmin)} |` +
  608. ` ${'MEDIAN'.padStart(cmed)} |` +
  609. ` ${'MAX'.padStart(cmax)} |` +
  610. ` ${'AVE'.padStart(cmax)} |` +
  611. ` ${'SAMPLES'.padStart(csam)} \n`
  612. message += ` ${'-'.repeat(message.length)}\n`
  613. names = Array.from(names).sort()
  614. for (let name of names) {
  615. let group = groups.get(name)
  616. let min = group.min.toFixed(2)
  617. let median = group.median.toFixed(2)
  618. let max = group.max.toFixed(2)
  619. let n = group.n
  620. let ave = group.mean.toFixed(2) //add
  621. message +=
  622. ` ${name.padEnd(cn)} |` +
  623. ` ${min.padStart(cmin)} |` +
  624. ` ${median.padStart(cmed)} |` +
  625. ` ${max.padStart(cmax)} |` +
  626. ` ${ave.padStart(cmax)} |` +
  627. ` ${n.toString().padStart(csam)}\n`
  628. }
  629. message += `\n`
  630. console.log(message)
  631. }
  632. performance.clearMarks()
  633. performance.clearMeasures()
  634. this.toggle = timestamp
  635. }
  636. },
  637. }
  638. export default common