You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3
+
4
+
name: Node.js CI
5
+
6
+
on:
7
+
push:
8
+
branches: ['main']
9
+
pull_request:
10
+
branches: ['main']
11
+
12
+
jobs:
13
+
build:
14
+
runs-on: ubuntu-latest
15
+
16
+
strategy:
17
+
matrix:
18
+
node-version: [12.x, 14.x, 16.x, 18.x]
19
+
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
A Typescript library for warping the very fabric of space-time, or for building deceitful clocks.
3
5
4
6
## Overview
5
7
6
-
#### Why should I use this library?
8
+
Do you sometimes stare at the clock, watching the minutes tick by, wondering by what trick-of-perception some minutes seem to pass more slowly than the last?
9
+
10
+
"Watched pot, not boiling", you think...
11
+
12
+
...but still...could there be...some little relativistic, Einsteinian gremlins, toiling away behind the clock face, deeply invested in and hell-bent upon your personal descent into the mouth of madness?
13
+
14
+
Probably not.
15
+
16
+
But, hey, now *you* can build your own fraudulent clock to drive others _**completely bonkers**_!
17
+
18
+
With `clockblocker`, Time is but a rubber-band, subject to your every passing whimsy.
19
+
20
+
## Why should I use this library?
21
+
22
+
First, let's assume you've got a very good (read: not evil) reason for wanting the clock to tick more slowly during a given time period.
23
+
24
+
You're building some kind of device capable of displaying the time, a la a digital clock LED display. This clock will be used by a miniature-human who, whenever they awaken past 4:00am, is incapable of returning to sleep. If the clock reads 3:59, the small person rolls right back over and goes to sleep.
25
+
26
+
In order to ensure a later arrival of 4:00am, we might wish to make the seconds start ticking ever more slowly at some point earlier in the night, to ensure that the clock doesn't actually show 4:00am until - let's say - 7:00am.
27
+
28
+
We probably want some facilities for easing-into the slowing of time, so that it isn't immediately obvious what is happening under cursory, ambient observations. Likewise, we might want to ease-back into normal time, rather than snapping immediately from 4:00am to 7:01 am.
29
+
30
+
Also, the tiny human isn't stupid, so you're gonna just have to hide all the other clocks in the house. And windows! You've gotta black-out the windows or the jig is up!
31
+
32
+
Let's be honest, you'll only be able to get away with this once a year, on Christmas morning.
7
33
8
34
---
9
35
## Install
@@ -14,7 +40,141 @@ npm install clockblocker
14
40
15
41
## Usage
16
42
43
+
```
44
+
import { Clock, ConstantTimeCompression, ConstantTimeDilation } from 'clockblocker';
45
+
46
+
const timeDilation = new ConstantTimeDilation(
47
+
{ hour: 1 }, // start at 1am, reference ("real") time
48
+
{ hours: 3 }, // Relative Time: By the time the "fake" time reads 4am...
49
+
{ hours: 6 }, // Reference Time: 6 hours of "real" time will have passed
50
+
);
51
+
52
+
// Fake clock will read: 4:00am, real clock: 7:00am
53
+
54
+
const timeCompression = new ConstantTimeCompression(
55
+
{ hour: 7 }, // start at 7am reference ("real") time
56
+
{ hours: 6 }, // Relative Time: In the time the "fake" time shows the passage of 6 hours
57
+
{ hours: 3}, // Reference Time: Only 3 hours, real time will have elapsed
58
+
),
59
+
60
+
// So, by the time 10:00am (reference) rolls-around, the clock is back to normal 1-to-1 time.
61
+
// Fake clock will read: 10:00am, real clock: 10:00am
62
+
63
+
const clock = new Clock([
64
+
timeDilation,
65
+
timeCompression
66
+
]);
67
+
```
68
+
69
+
Now, there are two properties of the clock instance that are useful
70
+
71
+
-`clock.relativeTimeInMillis` is the fraudulent time in `epochMillis`
72
+
-`clock.referenceTimeInMillis` is the "real" system clock time in `epochMillis`
73
+
74
+
Following the `clock` instance created in the prior example:
75
+
76
+
```
77
+
// At 12:00am (real clock)
78
+
clock.relativeTimeInMillis // returns epochMillis for 12:00am
79
+
clock.referenceTimeInMillis // returns epochMillis for 12:00am
80
+
81
+
// At 1:00am (real clock)
82
+
clock.relativeTimeInMillis // returns epochMillis for 1:00am
83
+
clock.referenceTimeInMillis // returns epochMillis for 1:00am
84
+
85
+
// At 2:00am (real clock)
86
+
clock.relativeTimeInMillis // returns epochMillis for 1:30am
87
+
clock.referenceTimeInMillis // returns epochMillis for 2:00am
17
88
89
+
// At 3:00am (real clock)
90
+
clock.relativeTimeInMillis // returns epochMillis for 2:00am
91
+
clock.referenceTimeInMillis // returns epochMillis for 3:00am
92
+
93
+
// At 4:00am (real clock)
94
+
clock.relativeTimeInMillis // returns epochMillis for 2:30am
95
+
clock.referenceTimeInMillis // returns epochMillis for 4:00am
96
+
97
+
// At 5:00am (real clock)
98
+
clock.relativeTimeInMillis // returns epochMillis for 3:00am
99
+
clock.referenceTimeInMillis // returns epochMillis for 5:00am
100
+
101
+
// At 6:00am (real clock)
102
+
clock.relativeTimeInMillis // returns epochMillis for 3:30am
103
+
clock.referenceTimeInMillis // returns epochMillis for 6:00am
104
+
105
+
// At 7:00am (real clock)
106
+
clock.relativeTimeInMillis // returns epochMillis for 4:00am
107
+
clock.referenceTimeInMillis // returns epochMillis for 7:00am
108
+
109
+
// At 8:00am (real clock)
110
+
clock.relativeTimeInMillis // returns epochMillis for 6:00am
111
+
clock.referenceTimeInMillis // returns epochMillis for 8:00am
112
+
113
+
// At 9:00am (real clock)
114
+
clock.relativeTimeInMillis // returns epochMillis for 8:00am
115
+
clock.referenceTimeInMillis // returns epochMillis for 9:00am
116
+
117
+
// At 10:00am (real clock) **NOW WE'RE BACK IN SYNC**
118
+
clock.relativeTimeInMillis // returns epochMillis for 10:00am
119
+
clock.referenceTimeInMillis // returns epochMillis for 10:00am
120
+
121
+
// At 11:00am (real clock)
122
+
clock.relativeTimeInMillis // returns epochMillis for 11:00am
123
+
clock.referenceTimeInMillis // returns epochMillis for 11:00am
124
+
```
125
+
## Roadmap (as of August 2022)
126
+
127
+
There are plenty of improvements I can imagine implementing, but I need some time living with the API as it currently exists before going further. This is my top-o-the-head, tip-o-the-tongue wishlist:
128
+
129
+
1. Right now, when scheduling multiple time distortions, the API requires you to know the start and reference (real-time) end times if you would like to ensure non-overlapping distortion windows. This begs for a way to "chain" `RelativeTimeDistortion` instances, or perhaps pass another distortion into the constructor, and derive the next start-time from the end of the earlier one.
130
+
2. We might want an abstraction for performing validation of the parameters in the `RelativeTimeDistortion` constructors. For example, it doesn't make a ton of sense to allow `relativeDuration` params to be smaller than `referenceDuration` params for the `ConstantTimeDilation`. Maybe there's some further refactoring that could avoid that, but I don't have any ideas on what that might look like. My intuition is that we wouldn't want to implicitly *disallow* overlapping if validation fails.
131
+
3. I want something *smoother* than the `ConstantTime*` distortions. Let's get this shit rubber-banding across Gaussian roll-offs (hoping to have a PR for that soon). Sky is the limit, though, on extending `RelativeTimeDistortion` to implement some crazy behaviors. And to that end...
132
+
4. Might need to rethink the extend `RelativeTimeDistortion` abstraction. Not yet sure whether we want to build further onto extending the class hierarchy and change that `distortTime` interface to an anonymous function that is passed-into the `RelativeTimeDistortion` instance? Maybe the function should take an `ratio` instead of direct access to protected attributes. I'm not sure yet, but I'm open to refactoring how that might work.
133
+
5. I have a vague intuition that there are further levels of abstraction to be mined in building specific, pre-defined combinations of distortions, but I see that as further out on the roadmap.
134
+
6. A case could probably be made for providing an interface for manipulating the distortions of an existing `Clock` instance, but right now, since the `referenceTime` is always based off of the underlying process' `Date.now()`, I'm content to just create new instances of `Clock`.
135
+
136
+
## API
137
+
138
+
TODO: Better docs
139
+
140
+
The most important thing is to understand the three paramters passed to an instance of `RelativeTimeDistortion`
141
+
142
+
-`referenceStartClockTime: ClockTimeDescriptor`,
143
+
-`relativeDuration: Duration`,
144
+
-`referenceDuration: Duration`,
145
+
146
+
`referenceStartClockTime` describes a (real) clock-time, at which the distortion should start, without reference to a specific date, or time-zone. Its type looks like this:
147
+
148
+
```
149
+
export interface ClockTimeDescriptor {
150
+
hour?: number;
151
+
minute?: number;
152
+
second?: number;
153
+
millisecond?: number;
154
+
}
155
+
```
156
+
157
+
`relativeDuration` describes a duration of "fake" clock-time that should appear to pass during the distortion window. Its type looks like this:
158
+
159
+
```
160
+
export interface Duration {
161
+
hours?: number;
162
+
minutes?: number;
163
+
seconds?: number;
164
+
milliseconds?: number;
165
+
}
166
+
```
167
+
168
+
`referenceDuration` describes a duration of "real" clock-time that actually will pass during the distortion window. Its type looks like this:
0 commit comments