API: Schedules and conflict resolution

This document outlines handling conflict resolution using the API.

Find an overview of the API spec at api.aura.radio.

To learn about conflict resolution check out Timeslot Collision Detection in the User Guide.

Overview

Creating timeslots is only possible by creating/updating a schedule.

When creating/updating a schedule by giving the schedule data:

  1. Projected timeslots are matched against existing timeslots

  2. API returns an array of objects containing 2.1. the schedule’s data 2.2. projected timeslots (array of objects), including an array of found collisions (objects) and possible solutions (array)

  3. To resolve, POST/PUT the "schedule" object and the "solutions" objects to /api/v1/shows/{show_pk}/schedules/{schedule_pk}/

Create/update schedule

  • To create: POST /api/v1/shows/{show_pk}/schedules/

  • To update: PUT /api/v1/shows/{show_pk}/schedules/{schedule_pk}/

To start the conflict resolution POST/PUT the schedule object with key "schedule" containing:

Variable

Type

Meaning

byWeekday[1]

int

Weekday number: Mon = 0, Sun = 6

rrule[1], [2]

int

Recurrence rule

firstDate[1]

date

First date of schedule (e.g. “2017-01-01”)

startTime[1]

time

Start time of schedule (e.g. “16:00:00”)

endTime[1]

time

End time of schedule (e.g. “17:00:00”)

lastDate[3]

date

Last date of schedule (e.g. “2017-12-31”)

isRepetition

boolean

Whether the schedule is a repetition (default: false)

defaultPlaylistId

int

A tank ID in case the timeslot’s playlistId is empty: What is aired if a single timeslot has no content? (default: null)

show[1]

int

Show the schedule belongs to

addDaysNo

int

Add a number of days to the generated dates. This can be useful for repetitions, like “On the following day” (default: null)

addBusinessDaysOnly

boolean

Whether to add addDaysNo but skipping the weekends. E.g. if weekday is Friday, the date returned will be the next Monday (default: false)

dryrun

boolean

Whether to simulate the database changes. If true, no database changes will occur, instead a summary is returned of what would happen if dryrun was false. (default: false)

Return

After sending the schedule’s data, the response will be in the form of:

{
    /* Projected timeslots to create. Array may contain multiple objects */
    "projected": [
        {
            "hash": "201801161430002018011616000041",
            "start": "2018-01-16 14:30:00",
            "end": "2018-01-16 16:00:00",
            /* Collisions found to the projected timeslot. Array may contain multiple objects */
            "collisions": [
                {
                    "id": 607,
                    "start": "2018-01-16 14:00:00",
                    "end": "2018-01-16 15:00:00",
                    "playlistId": null,
                    "show": 2,
                    "showName": "FROzine",
                    "isRepetition": false,
                    "schedule": 42,
                    "memo": "",
                    "noteId": 1 /* A note assigned to the timeslot. May not exist */
                }
            ],
            "error": "An error message if something went wrong. If not existing or empty, there's no problem",
            /* Possible solutions to solve the conflict */
            "solutionChoices": [
                "ours-start",
                "theirs",
                "ours",
                "theirs-start"
            ]
        },
    "solutions": {
        /* Manually chosen solutions by the user (if there's a key it has to have a value):
           Key is the hash of the projected timeslot while value must be one of 'solutionChoices' */
        "201801161430002018011616000041": ""
    },
    "notes": {
        /* To reassign an existing note to a projected timeslot, give its hash as key and the note id as value (may not exist) */
        "201801161430002018011616000041": 1
    },
    "playlists": {
        /* To reassign playlists to a projected timeslot, give its hash as key and the playlist id as value (may not exist) */
        "201801161430002018011616000041": 1
    },
    /* The schedule's data is mandatory for each POST/PUT */
    "schedule": {
        "rrule": 4,
        "byWeekday": 1,
        "show": 3,
        "firstDate": "2018-01-16",
        "startTime": "14:30:00",
        "endTime": "16:00:00",
        "lastDate": "2018-06-28",
        "isRepetition": false,
        "defaultPlaylistId": null,
        "automationId": null,
        "dryrun": false
    }
}

Solutions

The "solutionChoices" array contains possible solutions to the conflict.

To solve conflicts, POST the "schedule" and "solutions" objects to /api/v1/shows/{show_p}/schedules/ or PUT to /api/v1/shows/{show_pk}/schedules/{schedule_pk}/ with "solutions" containing values of solutionChoices. Any other value will produce an error.

As long as there’s an error, the whole data structure is returned and no database changes will occur. If resolution was successful, database changes take effect and the schedule is returned.

A Schedule is only created/updated if at least one timeslot was created during the resolution process.

Maximum possible output:

"solutions": [
    "theirs",
    "ours",
    "theirs-start",
    "ours-start",
    "theirs-end",
    "ours-end",
    "theirs-both",
    "ours-both"
]

"theirs" (always possible)

  • Discard projected timeslot

  • Keep existing timeslot(s)

"ours" (always possible)

  • Create projected timeslot

  • Delete existing timeslot(s)

"theirs-start"

  • Keep existing timeslot

  • Create projected timeslot with start time of existing end

"ours-start"

  • Create projected timeslot

  • Change end of existing timeslot to projected start time

"theirs-end"

  • Keep existing timeslot

  • Create projected timeslot with end of existing start time

"ours-end"

  • Create projected timeslot

  • Change start of existing timeslot to projected end time

"theirs-both"

  • Keep existing timeslot

  • Create two projected timeslots with end of existing start and start of existing end

"ours-both"

  • Create projected timeslot

  • Split existing into two:

    • Set existing end time to projected start

    • Create another timeslot with start = projected end and end = existing end

Multiple collisions

If there’s more than one collision for a projected timeslot, only "theirs" and "ours" are currently supported as solutions.

Errors

Possible error messages are:

Fatal errors that require the schedule’s data to be corrected and the resolution to restart

  • "Until date mustn't be before start": Set correct start and until dates.

  • "Start and until dates mustn't be the same" Set correct start and until dates. (Exception: Single timeslots with recurrence rule ‘once’ may have the same dates)

  • "Numbers of conflicts and solutions don't match": There probably was a change in the schedule by another person in the meantime.

  • "This change on the timeslot is not allowed." When adding: There was a change in the schedule’s data during conflict resolution. When updating: Fields start, end, byWeekday or rrule have changed, which is not allowed.