Replay Data

Record and playback timestamped data

The Oooh platform allows for modules to be chained together in all kinds of different ways. For example your module could be played by one user to generate assets. Those assets can then be published allowing many other users to play your module again using the data created by the first user as input. To make this experience unique and interesting every time you can save ReplayData during one module run and load it during another.

ReplayData is loosely defined to be able to save any json data, either as a global property or via a timing system to help with time based event recording and playback.

Saving Data

Use a ReplayRecorder to create a ReplayData to be added to the output asset collection.

import * as o3h from "/api/o3h";

const runtime = o3h.Instance;
const assetManager = runtime.getAssetManager();

// create a timer to control the timing of replay events
const gameTimer = await runtime.createGameTimer();

// get an instance of the replayRecorder used to track data to be stored
const replayRecorder = await runtime.createReplayRecorder(gameTimer);

runtime.ready(async () => {
  // start the timer for timed based events
  gameTimer.start();
 
  // add an event of any kind to be tracked against the given time
  replayRecorder.addReplayEvent({"event": "tap", "position": {"x": 4.3, "y": -6.4}});

  // add a property that's not associated with a time stamp
  replayRecorder.addProperty("colourPicked", "blue");

  // finalize the replay recorder and get a ReplayData object
  gameTimer.stop();
  const replayData = await replayRecorder.getReplayData();

  // mark the replayData to be exported from your module
  assetManager.addToOutput("replayData", replayData);
});

Using Data

Get a ReplayData from the input asset collection and create a ReplayPlayer to access its data.

import * as o3h from "/api/o3h";

const runtime = o3h.Instance;

// retrieve the replay data that was passed into the module from a previous run
const replayData = runtime.getAssetManager().getInputAsset("replayData");
  
// create a timer to control the timing of replay events
const gameTimer = await runtime.createGameTimer();

// generates a class that can be used to access the replay data
const replayPlayer = await replayData.createReplayPlayer(gameTimer);

runtime.ready(async () => {

  // get the property saved in the replay data
  const properties = await replayPlayer.getProperties();
  const colourPicked = properties["colourPicked"];

  // subscribe to a notification that triggers at the same time as the data was recorded
  replayPlayer.timedEvent.add(onReplayEvent);

  // start triggering the replay events at the appropriate timing
  gameTimer.start();
});

function onReplayEvent(replayEvent)
{
   const data = replayEvent.Data;

   // take the action again as the timing is the same as in the recording 
}

Aggregated Data

Using the ReplayRecorder.addAggregateIncrementProperty and ReplayRecorder.addAggregateSetIfGreaterProperty functions, it is possible to track a limited set of information across all plays of your module within the same Oooh segment.

Data saved in the replay data using those functions will be aggregated across all users server side and is made available via a call to ReplayPlayer.getAggregatedProperties in subsequent runs of your module.

import * as o3h from "/api/o3h";

const runtime = o3h.Instance;
const assetManager = runtime.getAssetManager();

// retrive the replay data that was passed into the module from a previous run
const replayData = runtime.getAssetManager().getInputAsset("replayData");

// create a timer to control the timing of replay events
const gameTimer = await runtime.createGameTimer();

// generates a class that can be used to access the replay data
const replayPlayer = await replayData.createReplayPlayer(gameTimer);

// get an instance of the replayRecorder used to store the data generated in this run
const replayRecorder = await runtime.createReplayRecorder(gameTimer);

runtime.ready(async () => {

  // vote for this run
  const currentVote = 'blue';
  replayRecorder.addAggregateIncrementProperty(currentVote);

  // get votes totals for all previous runs
  const aggregatedData = await replayPlayer.getAggregatedProperties();
  const votesForBlue = aggregatedData['blue'] || 0;
  const votesForRed = aggregatedData['red'] || 0;

  // finalize the replay recorder and get a ReplayData object
  gameTimer.stop();
  const replayData = await replayRecorder.getReplayData();

  // mark the replayData to be exported from your module to record the vote from this run
  assetManager.addToOutput("replayData", replayData);
});

Note: that when running in the SDK data is aggregated across all saved outputs. However, when running in the client aggregation is only across runs within an Oooh segment (ie: all audience plays against a single creator).