Developer diary

Dev Diary #12: Time series and reading data by name

How a game engine samples a time series once per period and lets the front end read series and data by name, with its limits.

Contents

In short: In a strategy game you do not need to save a value at every step to follow a city's population or the treasury over the years. MKA Engine takes one sample at the start of each period of a time series that the game declares in its content, and the front end reads the series by its name. A wrongly declared period does not crash the engine; it shows the file, line and column of the error.

Why one sample per period, not per step?

Picture a chart of a city's population. Saving every day gives hundreds of points, but the questions a player asks are usually about the end of a month or a year: "how much did the population grow last year?" That is why a time series keeps one sample per period.

A time series is a sequence of values of one quantity recorded in order over time (NIST Engineering Statistics Handbook (opens in a new tab); Wikipedia, Time series (opens in a new tab)). Here the period follows the calendar: a day, a month or a year. The sample is taken on the first step of the period: the first step of a day, the step that holds the first day of a month, or the step that holds the first day of a year.

The rule is the same whatever the step length. If the first day of a month falls in the middle of a weekly step, that step takes the month's sample, and no second sample is taken in the same month. The tests check this for weekly steps.

What does a series declare?

The game declares a series in its content record with four facts. No code is written.

FieldMeaningExample
SourceThe numeric column to sampleA city's population column
AggregateThe total, or one sample per rowThe sum of all cities, or one line per city
PeriodDay, month or yearMonthly: the first step of each month
KeepNumber of periods kept12: the last twelve months
What a series declares

Samples older than the kept periods are deleted, so the table does not grow without limit.

The front end reads by name

A chart front end asks for a series by its name. The engine returns the samples in period order; each has a period, a table, an entity (which city, or none for a total) and a value. The front end draws the chart, the scale and the labels; the engine provides the numbers.

A single value can also be read by name. A data binding ties a name either to the value of a row in a scope or to a modifier total. For a modifier total, the engine returns the total together with the sources that make it up: which entity contributed how much. That lets the front end answer "why is this number this?" on its own screen. Modifiers (multipliers) are explained in Events and multipliers.

Where an error is shown

If the game sets a period finer than the step length, for example a daily series in a weekly game, loading stops and the error names its file, line and column. This is a mistake in the game's data, not in the engine, so the engine does not panic. A broken data binding and a keep value of zero or a fraction are refused in the same way, with their file, line and column. Two series with the same name are refused when the content loads.

What is saved

Samples are part of the world state, so they are saved. A game loaded from a save carries the same samples and the same cursor (the record of the next period to sample) as a game that ran without a break, and it goes on from there in the same way. The engine tests and the reading tests check this.

What does it cost?

  • A sample is taken once per period. Changes between two samples are not seen: a monthly series does not show what happens inside the month. If the game needs that, it picks a shorter step and period.
  • Every kept sample takes space in the save; the more periods kept and the more rows sampled, the bigger the save. We did not measure this cost.
  • This diary has no timing or memory measurement. The behavior described is verified by tests; speed and memory were not measured.

Frequently asked questions

How is a time series declared in a game?

The game's content record names the series, the numeric column to sample, whether it is a total or one sample per row, the period and how many periods are kept. No code is written.

Is a series sampled at every step?

No. It is sampled once in each period: a day, a month or a year, at the first step of that period. A weekly or monthly step still takes the sample of a period that starts in it.

How does the front end read a series?

By its name. The engine returns the samples in period order, each with its period, entity and value.

What happens to a wrong series?

The engine does not crash. Loading stops, and the error shows where the mistake is.

Sources and records

External sources: NIST Engineering Statistics Handbook, time series (opens in a new tab), Wikipedia, Time series (opens in a new tab).

Related diaries: The world in memory, Events and multipliers.

If you have questions or suggestions about this diary, write to us through the contact page. For an overview of the engine, see the MKA Engine page; for all diaries, see the Developer Diaries list.

Sources and related docs

You may also like

  • How is a strategy game's world map made?

    For MKA Engine we built a 27,357-location world map of 1337 from real data: how terrain, rivers, straits, population and location borders were made.

  • The road to a game engine

    How we started MKA Engine: reading four games, treating determinism as law, moving phase by phase with measurements, and where we are now.