index.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { BitFlags } from './bit-flags';
  8. import { StringBuilder } from './string-builder';
  9. import { UUID } from './uuid';
  10. import { Mask } from './mask';
  11. import { Progress } from '../mol-task';
  12. export * from './value-cell';
  13. export { BitFlags, StringBuilder, UUID, Mask };
  14. export const noop = function () { };
  15. export function round(n: number, d: number) {
  16. let f = Math.pow(10, d);
  17. return Math.round(f * n) / f;
  18. }
  19. export function arrayEqual<T>(arr1: T[], arr2: T[]) {
  20. const length = arr1.length;
  21. if (length !== arr2.length) return false;
  22. for (let i = 0; i < length; i++) {
  23. if (arr1[i] !== arr2[i]) {
  24. return false;
  25. }
  26. }
  27. return true;
  28. }
  29. const hasOwnProperty = Object.prototype.hasOwnProperty;
  30. export function deepEqual(a: any, b: any) {
  31. // from https://github.com/epoberezkin/fast-deep-equal MIT
  32. if (a === b) return true;
  33. const arrA = Array.isArray(a);
  34. const arrB = Array.isArray(b);
  35. if (arrA && arrB) {
  36. if (a.length !== b.length) return false;
  37. for (let i = 0; i < a.length; i++) {
  38. if (!deepEqual(a[i], b[i])) return false;
  39. }
  40. return true;
  41. }
  42. if (arrA !== arrB) return false;
  43. if (a && b && typeof a === 'object' && typeof b === 'object') {
  44. const keys = Object.keys(a);
  45. if (keys.length !== Object.keys(b).length) return false;
  46. const dateA = a instanceof Date;
  47. const dateB = b instanceof Date;
  48. if (dateA && dateB) return a.getTime() === b.getTime();
  49. if (dateA !== dateB) return false;
  50. const regexpA = a instanceof RegExp;
  51. const regexpB = b instanceof RegExp;
  52. if (regexpA && regexpB) return a.toString() === b.toString();
  53. if (regexpA !== regexpB) return false;
  54. for (let i = 0; i < keys.length; i++) {
  55. if (!hasOwnProperty.call(b, keys[i])) return false;
  56. }
  57. for (let i = 0; i < keys.length; i++) {
  58. if (!deepEqual(a[keys[i]], b[keys[i]])) return false;
  59. }
  60. return true;
  61. }
  62. return false;
  63. }
  64. export function shallowEqual(a: any, b: any) {
  65. if (a === b) return true;
  66. const arrA = Array.isArray(a);
  67. const arrB = Array.isArray(b);
  68. if (arrA && arrB) return shallowEqualArrays(a, b);
  69. if (arrA !== arrB) return false;
  70. if (a && b && typeof a === 'object' && typeof b === 'object') {
  71. return shallowEqualObjects(a, b);
  72. }
  73. return false;
  74. }
  75. export function shallowEqualObjects(a: {}, b: {}) {
  76. if (a === b) return true;
  77. if (!a || !b) return false;
  78. const keys = Object.keys(a);
  79. if (Object.keys(b).length !== keys.length) return false;
  80. for (const k of keys) {
  81. if (!hasOwnProperty.call(a, k) || (a as any)[k] !== (b as any)[k]) return false;
  82. }
  83. return true;
  84. }
  85. export function shallowEqualArrays(a: any[], b: any[]) {
  86. if (a === b) return true;
  87. if (!a || !b) return false;
  88. if (a.length !== b.length) return false;
  89. for (let i = 0, il = a.length; i < il; ++i) {
  90. if (a[i] !== b[i]) return false;
  91. }
  92. return true;
  93. }
  94. /** Returns `value` if not `undefined`, otherwise returns `defaultValue` */
  95. export function defaults<T>(value: T | undefined, defaultValue: T): T {
  96. return value !== undefined ? value : defaultValue;
  97. }
  98. export function extend<S, T, U>(object: S, source: T, guard?: U): S & T & U {
  99. let v: any;
  100. let s = <any>source;
  101. let o = <any>object;
  102. let g = <any>guard;
  103. for (let k of Object.keys(source)) {
  104. v = s[k];
  105. if (v !== void 0) o[k] = v;
  106. else if (guard) o[k] = g[k];
  107. }
  108. if (guard) {
  109. for (let k of Object.keys(guard)) {
  110. v = o[k];
  111. if (v === void 0) o[k] = g[k];
  112. }
  113. }
  114. return <any>object;
  115. }
  116. export function shallowClone<T>(o: T): T {
  117. return extend({}, o) as T;
  118. }
  119. function _assign<T>(target: T): T {
  120. for (let s = 1; s < arguments.length; s++) {
  121. let from = arguments[s];
  122. for (let key of Object.keys(from)) {
  123. if (hasOwnProperty.call(from, key)) {
  124. (target as any)[key] = from[key];
  125. }
  126. }
  127. }
  128. return target;
  129. }
  130. export declare function _assignType<T>(o: T, ...from: any[]): T;
  131. export const assign: (<T>(o: T, ...from: any[]) => T) = (Object as any).assign || _assign;
  132. function _shallowMerge1<T>(source: T, update: T) {
  133. let changed = false;
  134. for (let k of Object.keys(update)) {
  135. if (!hasOwnProperty.call(update, k)) continue;
  136. if ((update as any)[k] !== (source as any)[k]) {
  137. changed = true;
  138. break;
  139. }
  140. }
  141. if (!changed) return source;
  142. return assign(shallowClone(source), update);
  143. }
  144. function _shallowMerge<T>(source: T) {
  145. let ret = source;
  146. for (let s = 1; s < arguments.length; s++) {
  147. if (!arguments[s]) continue;
  148. ret = _shallowMerge1(source, arguments[s]);
  149. if (ret !== source) {
  150. for (let i = s + 1; i < arguments.length; i++) {
  151. ret = assign(ret, arguments[i]);
  152. }
  153. break;
  154. }
  155. }
  156. return ret;
  157. }
  158. export const merge: (<T>(source: T, ...rest: Partial<T>[]) => T) = _shallowMerge;
  159. function padTime(n: number) { return (n < 10 ? '0' : '') + n; }
  160. export function formatTime(d: Date) {
  161. const h = d.getHours(), m = d.getMinutes(), s = d.getSeconds();
  162. return `${h}:${padTime(m)}:${padTime(s)}`;
  163. }
  164. export function formatProgress(p: Progress) {
  165. const tp = p.root.progress;
  166. if (tp.isIndeterminate) return tp.message;
  167. const x = (100 * tp.current / tp.max).toFixed(2);
  168. return `${tp.message} ${x}%`;
  169. }