sof-cycle 0.1.16 → 0.1.18

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 231dc1ad6fc3d374cd70a0684f1d67206ccc7bec0335d1510b03f219a1a8fc5d
4
- data.tar.gz: f0d524a077e23d84544833cae34d8d0695817bc10f092ffc84c560371edaffa9
3
+ metadata.gz: 735c721cc8acf74603c4bea6a29c9e5149f68fa94455dd6ea15a48ecebb6602a
4
+ data.tar.gz: 5061cac902fee01a91d225f7ac85774a3b16269ece1a576c317a9a5f78ec4204
5
5
  SHA512:
6
- metadata.gz: 54c7a1a4f2a1960050e282ce5209c327f3b6c16b18ed9c5c1696564f7a99b30dbfbded433bf9a60a1f8ebf4ddac6d1d98b44d42413327fb7b5caf9152e6267d1
7
- data.tar.gz: 4cf103728536a77b00dadfea353f616882d095468ca5c3c02e6d838736d4ecdb0e0fb7f67da980632443eb9270ba2d4714b20e44bddd8b38189c7242af02ab6b
6
+ metadata.gz: 85940a5323238358158ec9dc9a9a45218563aab918471fcc6c1bcc0322ae67a070ef743cdf6cc5210adda942be61606c951c8ce12ffb85f51105f6d9f9c34d3a
7
+ data.tar.gz: 8e564766036e7e95321c3c86cbc57a65d3e316dfa1cb00e76007884525b3afc4defb4bb8ce0cc95e004031af4c56b892da99b7f62c01a31911c9e722d60ad001
data/CHANGELOG.md CHANGED
@@ -5,10 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.1.16] - 2026-10-08
8
+ ## [0.1.18] - 2026-10-22
9
9
 
10
10
  ### Added
11
11
 
12
- - `Cycle#activated_by(date)` returns the cycle anchored on that date, or itself when already active
12
+ - `Cycle#in_force_by(dates)` anchors a dormant End-of or Interval cycle on the latest date once the dates meet its volume, then resets it by them
13
13
 
14
- ## [0.1.15] - 2026-07-27
14
+ ## [0.1.17] - 2026-10-20
15
+
16
+ ### Changed
17
+
18
+ - `Cycle#reset_by` re-anchors the window on the date that meets the cycle's volume, and later dates count toward the new window
@@ -0,0 +1 @@
1
+ a2fb7da5b2f320e581a7473ce5e534841d7b6daff56f2bdc3023d439ea4566df96c87edd4cf116348f4cac4a16db140b1edb5b45098cee73bcd63d7cb566baf5
@@ -0,0 +1 @@
1
+ 79734e3566bc1e21c2e6399531ec538e9207aa5e7426103cf126f36c2f020a04b618b83ceaf1ece2b12506c6d353e2c1f7e359e0bd3216ccf33e214b916b7f1d
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SOF
4
4
  class Cycle
5
- VERSION = "0.1.16"
5
+ VERSION = "0.1.18"
6
6
  end
7
7
  end
data/lib/sof/cycle.rb CHANGED
@@ -310,10 +310,12 @@ module SOF
310
310
  # consuming app.
311
311
  #
312
312
  # Dates on or before the current anchor are ignored: a back-dated act
313
- # must not drag a forward-running window backwards. Every other kind
314
- # returns itself — a lookback window already slides, a calendar window is
315
- # pinned to the calendar, a one-shot window does not repeat, and an
316
- # un-anchored one has no window to move until it is activated.
313
+ # must not drag a forward-running window backwards. The window re-anchors
314
+ # on the date that meets its volume; later dates count toward the new
315
+ # window. Every other kind returns itself — a lookback window already
316
+ # slides, a calendar window is pinned to the calendar, a one-shot window
317
+ # does not repeat, and an un-anchored one has no window to move until it
318
+ # is activated.
317
319
  #
318
320
  # @param dates [Array<Date, Time, nil>] the acts that satisfy this cycle
319
321
  # @return [Cycle] the reset cycle, or self when nothing resets it
@@ -344,6 +346,25 @@ module SOF
344
346
  Cycle.for(activated_notation(date))
345
347
  end
346
348
 
349
+ # The cycle in force given the dates that satisfy it: a dormant E or I
350
+ # cycle anchors on the latest date once they meet its volume, then
351
+ # `reset_by` moves it.
352
+ #
353
+ # @param dates [Array<Date, Time, nil>] the acts that satisfy this cycle
354
+ # @return [Cycle] the cycle in force, or self when nothing brings it in
355
+ #
356
+ # @example
357
+ # Cycle.for("V2E12M").in_force_by([Date.new(2026, 3, 20), Date.new(2026, 5, 2)])
358
+ # # => Cycle.for("V2E12MF2026-05-02")
359
+ def in_force_by(dates)
360
+ return self unless recurring? && dormant_capable?
361
+
362
+ days = Array(dates).filter_map { it&.to_date }
363
+ return self if from_date.nil? && days.size < volume
364
+
365
+ activated_by(days.max).reset_by(days)
366
+ end
367
+
347
368
  # From the supplied anchor date, are there enough in-window completions to
348
369
  # satisfy the cycle?
349
370
  #
@@ -397,10 +418,19 @@ module SOF
397
418
 
398
419
  private
399
420
 
400
- # The latest date that moves this cycle's window forward, or nil.
401
421
  def reset_date(dates)
402
- anchored_on = from_date.to_date
403
- Array(dates).filter_map { it&.to_date }.select { it > anchored_on }.max
422
+ anchor = from_date.to_date
423
+ reset = nil
424
+ counted = 0
425
+ Array(dates).filter_map { it&.to_date }.sort.each do |date|
426
+ next unless date > anchor
427
+ counted += 1
428
+ next if counted < volume
429
+
430
+ anchor = reset = date
431
+ counted = 0
432
+ end
433
+ reset
404
434
  end
405
435
  end
406
436
  end
@@ -26,6 +26,12 @@ module SOF
26
26
  # activated, not by the acts that satisfy it.
27
27
  def reset_by(...) = self
28
28
 
29
+ # Short of the volume it stays the wrapper, not the bare cycle.
30
+ def in_force_by(dates)
31
+ in_force = cycle.in_force_by(dates)
32
+ in_force.active? ? in_force : self
33
+ end
34
+
29
35
  def expiration_of(...) = nil
30
36
 
31
37
  def satisfied_by?(...) = false
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sof-cycle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.16
4
+ version: 0.1.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
@@ -58,6 +58,8 @@ files:
58
58
  - checksums/sof-cycle-0.1.13.gem.sha512
59
59
  - checksums/sof-cycle-0.1.14.gem.sha512
60
60
  - checksums/sof-cycle-0.1.15.gem.sha512
61
+ - checksums/sof-cycle-0.1.16.gem.sha512
62
+ - checksums/sof-cycle-0.1.17.gem.sha512
61
63
  - checksums/sof-cycle-0.1.2.gem.sha512
62
64
  - checksums/sof-cycle-0.1.3.gem.sha512
63
65
  - checksums/sof-cycle-0.1.4.gem.sha512