idle_core 0.4.0 copy "idle_core: ^0.4.0" to clipboard
idle_core: ^0.4.0 copied to clipboard

Deterministic state simulation core for Dart with fixed ticks, offline progress, replay, and versioned snapshots.

idle_core #

Deterministic state simulation core for Dart: fixed ticks, offline progression, replay, and versioned snapshots. Pure Dart, no Flutter dependency.

Design principles #

  • Determinism: reducers are pure; no wall-clock reads inside state transitions.
  • Replayability: the same actions always produce the same state.
  • Explainability: results include ticks applied, caps, and unapplied time.
  • Offline-first: long gaps are applied in capped chunks for safety.
  • Platform-agnostic: no UI, storage, network, or AI dependencies.

Out of scope #

  • UI frameworks (Flutter/Widgets) and lifecycle integration.
  • Storage adapters, encryption/signing, or cloud sync.
  • Networking, AI/LLM calls, or platform services.

Install #

dependencies:
  idle_core: ^0.3.1

Minimal usage #

import 'package:idle_core/idle_core.dart';

class SimState extends SimulationState {
  final int counter;
  final int rate;
  const SimState({required this.counter, required this.rate});

  SimState copyWith({int? counter, int? rate}) {
    return SimState(
      counter: counter ?? this.counter,
      rate: rate ?? this.rate,
    );
  }

  factory SimState.fromJson(Map<String, dynamic> json) {
    return SimState(
      counter: json['counter'] as int,
      rate: json['rate'] as int,
    );
  }

  @override
  Map<String, dynamic> toJson() => {'counter': counter, 'rate': rate};
}

SimState reducer(SimState state, SimulationAction action) {
  if (action is TickAction) {
    return state.copyWith(counter: state.counter + state.rate);
  }
  return state;
}

void main() {
  final config = SimulationConfig(dtMs: 1000);
  final engine = SimulationEngine<SimState>(
    config: config,
    reducer: reducer,
    state: const SimState(counter: 0, rate: 1),
  );
  final snapshotCodec = SnapshotCodec<SimState>(
    stateCodec: StateCodec<SimState>(
      schemaVersion: 1,
      fromJson: SimState.fromJson,
    ),
  );

  var lastObservedMs = 0;

  engine.tick(count: 5);
  final offline = engine.applyOffline(
    lastObservedMs: lastObservedMs,
    nowMs: 10 * 1000,
  );
  lastObservedMs = offline.nextLastObservedMs(lastObservedMs);
  final snapshot = snapshotCodec.encodeState(
    state: engine.state,
    lastObservedMs: lastObservedMs,
  );

  print(engine.state.toJson());
  print(snapshot);
}
final offline = engine.applyOffline(
  lastObservedMs: lastObservedMs,
  nowMs: nowMs,
);
lastObservedMs = offline.nextLastObservedMs(lastObservedMs);
final snapshot = snapshotCodec.encodeState(
  state: engine.state,
  lastObservedMs: lastObservedMs,
);

Snapshots and migrations #

final codec = StateCodec<SimState>(
  schemaVersion: 2,
  fromJson: SimState.fromJson,
  migrations: {
    0: (json) => <String, dynamic>{...json, 'rate': 1},
    1: (json) {
      final updated = Map<String, dynamic>.from(json);
      updated['counter'] = updated.remove('count') ?? 0;
      return updated;
    },
  },
);

Replay #

final result = engine.replay(actions);

API snapshot #

  • SimulationEngine, SimulationConfig
  • SimulationState, SimulationReducer
  • StateCodec, Snapshot, SnapshotCodec
  • SimulationClock, OfflineRunner
  • TickResult, OfflineResult

Contact #

If you find interest in collaborating/contribution or have questions, reach out at wonyoungchoiseoul@gmail.com.

1
likes
160
points
468
downloads

Publisher

unverified uploader

Weekly Downloads

Deterministic state simulation core for Dart with fixed ticks, offline progress, replay, and versioned snapshots.

Repository (GitHub)
View/report issues
Contributing

Documentation

API reference

License

MIT (license)

More

Packages that depend on idle_core