Liking cljdoc? Tell your friends :D

dvlopt.dsim

Idiomatic, purely-functional discrete event simulation.

A transition is pure stepwise function gradually modifying some arbitrary state map. Transitions are part of the state itself and are located under the transition-key key. They can be organized in arbitrarily nested maps. It is both common and desired for transitions to mirror the data they act upon :

{dvlopt.dsim/transition-key {:asteroids {42 {:x ... :y ...}}} :asteroids {42 {:x 450 :y 1420}}}

This pattern is so common that in this example, [:asteroids 42 :x] would be called the data-path of the :x transition of asteroid 42. Such a transition accepts 3 arguments: a state map, its data-path, and a step. It returns a new state which, although not enforced, should somehow modify the :x value of asteroid 42.

For doing so, a transition is created by providing an on-step function which also accepts 3 arguments: a state map, the data-path, and a percentage of completion. This percentage depends on the first step of the transition, how many steps it lasts, and the current step: (current-step - first-step) / n-steps.

After reaching 100%, if it was provided in the first place, the on-complete function of the transition is called. It accepts 4 arguments: the current state map, the data-path, the completion step, and the current step. It is useful when action must be taken after a transition, for instance for creating a new one. If some steps are missed or skipped, the completion step and the current step will not match. Hence it is useful to provide both. Completed transitions are removed automatically.

Cf. infinite once repeating

A poly-transition is a higher-order transition composed of several transitions. At the end of each sub-transition, the poly-transition takes care of creating the next one at the right moment. Hence, it would be easy to animate asteroid 42 to sequentially move in different directions, or to sequentially rotate in some complex manner. It is also trivial to create nested poly-transitions.

Cf. poly poly-infinite poly-repeating

Scaling a percentage to a value such as the :x position of an asteroid is facilitated by using scale and fn-scale. It is often needed for a transition to behave non-linearly. This can be simply done by modifying the percentage of completion, which is a linear progression, to be non-linear. For example, if an asteroid has to move faster and faster along the :x axis from 500 to 1000 pixels in a 100 steps starting from step 0:

(dvlopt.dsim/once 0 100 (let [scale' (dvlopt.dsim/fn-scale 500 1000)] (fn on-step [state data-path percent] (assoc-in state data-path (scale' (Math/pow percent 2))))))

The most straightforward way to add or remove transitions to a state is by using merge-transitions. A series of helpers for on-step and on-complete functions is provided. For example, improving the last example and removing the asteroid when done :

(dvlopt.dsim/once 0 100 (dsim/fn-mirror-percent (comp (dvlopt.dsim/fn-scale 500 1000) #(Math/pow % 2))) dsim/remove-pre-data)

The most basic way of moving a state to some step is done by using move. move-seq facilitates the process of iteratively moving through a sequence of steps. However, the most useful way is probably move-events which also takes into account events happening at some particular steps, each modifying the state is some way. Any non-trivial simulation involves such events.

Idiomatic, purely-functional discrete event simulation.


A transition is pure stepwise function gradually modifying some arbitrary state map. Transitions are part of the state itself
and are located under the `transition-key` key. They can be organized in arbitrarily nested maps. It is both common and desired
for transitions to mirror the data they act upon :


  {dvlopt.dsim/transition-key {:asteroids {42 {:x ...
                                               :y ...}}}
   :asteroids {42 {:x 450
                   :y 1420}}}

This pattern is so common that in this example, [:asteroids 42 :x] would be called the `data-path` of the :x transition of
asteroid 42. Such a transition accepts 3 arguments: a state map, its data-path, and a step. It returns a new state which, although
not enforced, should somehow modify the :x value of asteroid 42.

For doing so, a transition is created by providing an `on-step` function which also accepts 3 arguments: a state map, the data-path,
and a percentage of completion. This percentage depends on the first step of the transition, how many steps it lasts, and the
current step:  (current-step - first-step) / n-steps.

After reaching 100%, if it was provided in the first place, the `on-complete` function of the transition is called. It accepts
4 arguments: the current state map, the data-path, the completion step, and the current step. It is useful when action must be
taken after a transition, for instance for creating a new one. If some steps are missed or skipped, the completion step and the
current step will not match. Hence it is useful to provide both. Completed transitions are removed automatically.

  Cf. `infinite`
      `once`
      `repeating`

A poly-transition is a higher-order transition composed of several transitions. At the end of each sub-transition, the poly-transition
takes care of creating the next one at the right moment. Hence, it would be easy to animate asteroid 42 to sequentially move in
different directions, or to sequentially rotate in some complex manner. It is also trivial to create nested poly-transitions.

  Cf. `poly`
      `poly-infinite`
      `poly-repeating`


Scaling a percentage to a value such as the :x position of an asteroid is facilitated by using `scale` and `fn-scale`. It is often
needed for a transition to behave non-linearly. This can be simply done by modifying the percentage of completion, which is a linear
progression, to be non-linear. For example, if an asteroid has to move faster and faster along the :x axis from 500 to 1000 pixels in a
100 steps starting from step 0:

  (dvlopt.dsim/once 0
                    100
                    (let [scale' (dvlopt.dsim/fn-scale 500
                                                       1000)]
                      (fn on-step [state data-path percent]
                        (assoc-in state
                                  data-path
                                  (scale' (Math/pow percent
                                                    2))))))

The most straightforward way to add or remove transitions to a state is by using `merge-transitions`. A series of helpers for `on-step`
and `on-complete` functions is provided. For example, improving the last example and removing the asteroid when done :

  (dvlopt.dsim/once 0
                    100
                    (dsim/fn-mirror-percent (comp (dvlopt.dsim/fn-scale 500
                                                                        1000)
                                                  #(Math/pow %
                                                             2)))
                    dsim/remove-pre-data)


The most basic way of moving a state to some step is done by using `move`. `move-seq` facilitates the process of iteratively moving
through a sequence of steps. However, the most useful way is probably `move-events` which also takes into account events happening at
some particular steps, each modifying the state is some way. Any non-trivial simulation involves such events.
raw docstring

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close