jupyter-ijavascript-utils 1.6.4 → 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/format.js +133 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jupyter-ijavascript-utils",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "Utilities for working with iJavaScript - a Jupyter Kernel",
5
5
  "homepage": "https://jupyter-ijavascript-utils.onrender.com/",
6
6
  "main": "src/index.js",
package/src/format.js CHANGED
@@ -11,6 +11,11 @@
11
11
  * * {@link module:format.divideR|format.divideR} - Divides a number to provide { integer, remainder } - ex: 5/3 as ( 1, remainder 2 )
12
12
  * * Formatting Time
13
13
  * * {@link module:format.millisecondDuration|format.millisecondDuration}
14
+ * * Mapping Values
15
+ * * {@link module:format.mapDomain|format.mapDomain} - projects a value from a domain of expected values to a range of output values, ex: 10% of 2 Pi
16
+ * * Identifying Time Periods
17
+ * * {@link module:format.timePeriod|format.timePeriod} - Converts a time to a time period, very helpful for animations
18
+ * * {@link module:format.timePeriodPercent|format.timePeriodPercent} - Determines the percent complete of the current time period
14
19
  *
15
20
  * @module format
16
21
  * @exports format
@@ -285,9 +290,137 @@ module.exports.millisecondDuration = function millisecondDuration(milliseconds)
285
290
  return result;
286
291
  };
287
292
 
293
+ /**
294
+ * Ellipsifies a string (but only if it is longer than maxLen)
295
+ *
296
+ * @param {String} str - string to be ellipsified
297
+ * @param {Integer} [maxLen = 50] - the maximum length of str before getting ellipsified
298
+ * @returns {String}
299
+ * @example
300
+ * format.ellipsify('longName') // 'longName' (as maxLen is 50)
301
+ * format.ellipsify('longName', 8) // 'longName' (as maxLen is 8)
302
+ * format.ellipsify('longName', 4) // 'long…' (as str is longer than maxLen)
303
+ */
288
304
  module.exports.ellipsify = function ellipsify(str, maxLen = 50) {
289
305
  if (str && str.length > maxLen) {
290
306
  return `${str.substring(0, maxLen)}…`;
291
307
  }
292
308
  return str;
293
309
  };
310
+
311
+ /**
312
+ * projects a value from a domain of expected values to a range of output values, ex: 10% of 2 Pi.
313
+ *
314
+ * This is SUPER helpful in normalizing values, or converting values from one "range" of values to another.
315
+ *
316
+ * @param {Number} val - value to be mapped
317
+ * @param {Array} domain - [min, max] - domain of possible input values
318
+ * @param {Array} domain.domainMin - minimum input value (anything at or below maps to rangeMin)
319
+ * @param {Array} domain.domainMax - maximum input value (anything at or above maps to rangeMax)
320
+ * @param {Array} range - [min, max] - range of values to map to
321
+ * @param {Array} range.rangeMin - minimum output value
322
+ * @param {Array} range.rangeMax - maximum output value
323
+ * @returns Number
324
+ * @example
325
+ *
326
+ * format.mapDomain(-2, [0, 10], [0, 1])
327
+ * // 0 - since it is below the minimum value
328
+ * format.mapDomain(0, [0, 10], [0, 1])
329
+ * // 0 - since it is the minimum value
330
+ * format.mapDomain(5, [0, 10], [0, 1])
331
+ * // 0.5 - since it is 5/10
332
+ * format.mapDomain(12, [0, 10], [0, 1])
333
+ * // 1 - since it is above the maximum value
334
+ *
335
+ * format.mapDomain(0.5, [0, 1], [0, 10])
336
+ * // 5 - since it is half of 0-1, and half of 1-10
337
+ * format.mapDomain(0.5, [0, 1], [0, Math.PI + Math.PI])
338
+ * // 3.1415 or Math.PI - since it is half of 2 PI
339
+ */
340
+ module.exports.mapDomain = function mapDomain(val, [domainMin, domainMax], [rangeMin = 0, rangeMax = 1]) {
341
+ if (val < domainMin) {
342
+ return rangeMin;
343
+ } else if (val > domainMax) {
344
+ return rangeMax;
345
+ }
346
+ // domainMin / val / domainMax = rangeMin / result / rangeMax
347
+ // (val - domainMin) / (domainMax - domainMin) = (result - rangeMin) / (rangeMax - rangeMin)
348
+ // (val - domainMin) * (rangeMax - rangeMin) / (domainMax - domainMin) = result - rangeMin;
349
+ // (val - domainMin) * (rangeMax - rangeMin) / (domainMax - domainMin) + rangeMin = result
350
+ return (((val - domainMin) * (rangeMax - rangeMin)) / (domainMax - domainMin)) + rangeMin;
351
+ };
352
+
353
+ /**
354
+ * Given that a period of time is millisecondPeriod number of milliseconds long,
355
+ * determines which period of time we are currently in (timeEpoch / millisecondPeriod)
356
+ *
357
+ * This is especially handy for animations or cyclical time measuring.
358
+ *
359
+ * **NOTE: consider sending the timeEpoch relative to a separate start time**,
360
+ * it is rarely ever needed to know how many 10 second intervals occurred since 1970...
361
+ *
362
+ * Likely, we care more that the animation should have cycled 40 times since the page loaded though.
363
+ *
364
+ * @param {Integer} millisecondPeriod - Number of Milliseconds in a Period of time
365
+ * @param {Integer} [timeMilli = now] - optional time to check - in epoch milliseconds
366
+ * @param {Integer} [startMilli = null] - optional starting epoch
367
+ * @returns {Number} - (timeEpoch - startEpoch) / millisecondPeriod - number of periods
368
+ *
369
+ * @example
370
+ * const startTime = new Date().getTime();
371
+ *
372
+ * format.timePeriod(1000)
373
+ * // 164955061.3 - using the current time and epoch starting point
374
+ *
375
+ * format.timePeriod(1000, new Date().getTime(), startTime);
376
+ * // 0.0 - using the starting point instead
377
+ *
378
+ * // - wait 3 seconds
379
+ *
380
+ * format.timePeriod(10000, new Date().getTime(), startTime); // 0.3
381
+ * format.timePeriod(10000, null, startTime); // 0.3
382
+ *
383
+ * // - wait another 14 seconds
384
+ *
385
+ * format.timePeriod(10000, new Date().getTime(), startTime); // 1.7
386
+ *
387
+ * //-- wait 8 seconds
388
+ *
389
+ * format.timePeriod(10000, new Date().getTime(), startTime) // 2.5
390
+ */
391
+ module.exports.timePeriod = function mapTime(millisecondPeriod, timeMilli = null, startMilli = null) {
392
+ let updatedMilli = !timeMilli
393
+ ? new Date().getTime()
394
+ : timeMilli;
395
+
396
+ if (startMilli) {
397
+ updatedMilli -= startMilli;
398
+ }
399
+
400
+ return updatedMilli / millisecondPeriod;
401
+ };
402
+
403
+ /**
404
+ * Given that a period of time is millisecondPeriod number of milliseconds long,
405
+ * determines how far along in the CURRENT PERIOD.
406
+ *
407
+ * This is especially handy for animations or cyclical time measuring.
408
+ *
409
+ * @param {Integer} millisecondPeriod - Number of Milliseconds in a Period of time
410
+ * @param {Integer} [timeEpoch = now] - time to check - in epoch milliseconds
411
+ * @returns {Number} - percentage through the current millisecond period (0 <= x < 1)
412
+ *
413
+ * @example
414
+ * format.timePeriodPercent(10000, new Date().getTime()) // 0.3
415
+ *
416
+ * //-- wait 14 seconds
417
+ *
418
+ * format.timePeriodPercent(10000, new Date().getTime()) // 0.7
419
+ *
420
+ * //-- wait 8 seconds
421
+ *
422
+ * format.timePeriodPercent(10000, new Date().getTime()) // 0.5
423
+ */
424
+ module.exports.timePeriodPercent = function mapEpochInPeriod(millisecondPeriod, timeEpoch = new Date().getTime()) {
425
+ return (timeEpoch % millisecondPeriod) / millisecondPeriod;
426
+ };