コンポーネントの条件付きインフレート(APL for Audio)



コンポーネントの条件付きインフレート(APL for Audio)

コンポーネントの条件付きインフレートは、APLドキュメントのどのコンポーネントをレンダリングするかを決定します。たとえば、APLドキュメントmainTemplateプロパティはitemsプロパティ内のコンポーネントの配列を受け取りますが、レンダリングするのは1つのコンポーネントだけです。コンポーネントの条件付きインフレートが、どのコンポーネントをレンダリングするかを決定します。コンポーネントの条件付きインフレートアルゴリズムでは、コンポーネントの配列、プリミティブコンポーネントのwhenプロパティ、データバインディングを組み合わせて簡潔な条件式を作成できます。

条件付きインフレートのシナリオ

条件付きインフレートの動作はシナリオによって異なります。

  • 1つの子のみ:Alexaは、コンポーネント候補の配列から1つのコンポーネントのみをレンダリングします。
  • 1つの配列:Alexaは、コンポーネントの配列からコンポーネントの一部をレンダリングします。
  • データ配列:Alexaは、データ配列を使ってコンポーネントのセットをレンダリングします。

以降のセクションでは、これらの各シナリオについて詳しく説明します。

1つの子のみのインフレート

1つの子のみのインフレートでは、Alexaはコンポーネントの配列から最大1つの子コンポーネントをレンダリングします。たとえば、APLドキュメントmainTemplateitems配列に複数のコンポーネントがある場合でも、Alexaがレンダリングするのは配列の1つのコンポーネントのみとなります。

使用場所

コンポーネントの配列を持つitemsを受け取って、1つの子のみをインフレートするコンポーネントで使用されます。たとえば次のようなコンポーネントです。

  • ドキュメントのmainTemplate.itemsプロパティ
  • Selector

アルゴリズム

コンポーネントの配列を受け取ったら、各コンポーネントのwhenプロパティを順番に評価します。whenプロパティの評価結果がtrueになった最初のコンポーネントをレンダリングします。配列のコンポーネントにwhenプロパティがtrueに評価されるものがない場合、コンポーネントはインフレートされません。コンポーネントでwhenプロパティが省略されている場合、デフォルトのtrueとなります。

データバインディング

デフォルトでは、1つの子のみのインフレートにバインドされる追加のプロパティはありません。Selectorコンポーネントの場合、dataプロパティを設定すると、データバインディングコンテキストがdataindexlengthの各プロパティに基づいて拡張されます。詳細については、Selectorコンポーネントを参照してください。

以下は、Selectorコンポーネントの例です。Selectorがレンダリングするのは1つの子コンポーネントのみですが、itemsプロパティではコンポーネントの配列を受け取ります。

クリップボードにコピーされました。

{
  "type": "Selector",
  "items": [
    {
      "when": "${payload.myData.userDefinedList.length > 1}",
      "type": "Speech",
      "contentType": "PlainText",
      "content": "userDefinedListに項目が複数ある場合はこう言ってください。"
    },
    {
      "type": "Speech",
      "contentType": "PlainText",
      "content": "userDefinedListに項目が1つしかないか、まったくない場合はこう言ってください。"
    }
  ]
}

Alexaは、payload.myData.userDefinedListで定義される配列に複数の項目がある場合、最初のSpeechコンポーネントをレンダリングします。Alexaは、配列に項目がない場合や1つの項目のみの場合、2番目のSpeechコンポーネントをレンダリングします。whenプロパティが指定されていない場合はデフォルトのtrueとなるため、この例では、最初のコンポーネントがスキップされた場合は2番目のSpeechが常にレンダリングされます。

たとえば、以下のデータソースでは、Selectorが「userDefinedListに項目が複数ある場合はこう言ってください」の音声を使ってオーディオクリップを作成します。

クリップボードにコピーされました。

{
  "myData": {
    "userDefinedList": [
      "項目1",
      "項目2",
      "項目3"
    ]
  }
}

以下のもう1つのデータソースでは、「userDefinedListに項目が1つしかないか、まったくない場合はこう言ってください。」の音声を使ってオーディオクリップを作成します。

クリップボードにコピーされました。

{
  "myData": {
    "userDefinedList": [
      "項目1"
    ]
  }
}

1つの配列のインフレート

1つの配列のインフレートでは、Alexaは、コンポーネントの配列からコンポーネントの一部をレンダリングします。たとえば、Sequencerコンポーネントは、itemsプロパティでコンポーネントの配列を受け取ります。Alexaは、配列のすべての項目か、項目の一部をレンダリングします。

種類の異なる項目をまとめてレンダリングする場合、項目の1つの配列を使います。

使用場所

dataプロパティが設定されていない場合、次の複数の子コンポーネントで使用します。

アルゴリズム

配列内の各コンポーネントのwhenプロパティを評価します。whenプロパティがtrueに評価されると、Alexaはそのコンポーネントをレンダリングする子の配列に追加します。

データバインディング

indexlengthの値がバインドされます。詳細については、コンポーネントの子要素の拡張を参照してください。

以下は、複数コンポーネントを順番にレンダリングするSequencerコンポーネントの例です。この例では、dataプロパティが省略されているため、コンポーネントは1つの配列アプローチを使ってitems内のすべてのコンポーネントを評価し、レンダリングするサブセットを選択します。

クリップボードにコピーされました。

{
  "type": "Sequencer",
  "items": [
    {
      "type": "Speech",
      "content": "ハローワールド。"
    },
    {
      "type": "Speech",
      "when": "${environment.aplVersion}",
      "content": "画面で今日のあいさつをチェックしましょう!"
    }
  ]
}

environment.aplVersionプロパティは、デバイスでサポートされているAPLのバージョンを返します。画面のないデバイスやAPLをサポートしていない画面付きデバイスの場合は、nullを返します。つまり、この例では次のようになります。

  • デバイスに画面がある場合、Sequencerは両方のコンポーネントをレンダリングし、ユーザーには「ハローワールド。 画面で今日のあいさつをチェックしましょう!」と再生されます。
  • 画面のないデバイスの場合、Sequencerは1つ目のコンポーネントのみをレンダリングして2つ目は無視するため、ユーザーには「ハローワールド。」のみが再生されます。

データ配列のインフレート

データ配列のインフレートでは、Alexaはデータの配列を使ってコンポーネントのセットをインフレートします。この方法は、複数の子コンポーネントでdataプロパティが設定されている場合に使用できます。

連結したいデータの配列がある場合は、このデータ配列アプローチを使用します。レンダリングするコンポーネントのセットを定義すると、Alexaは、dataの各項目についてそのコンポーネントセットをレンダリングします。

使用場所

dataプロパティが設定された、次の複数の子コンポーネントで使用します。

アルゴリズム

data配列の各要素は、データバインディングコンテキストの変数"data"に、順番にバインドされます。バインドされた各要素について、Alexaは1つの子のアルゴリズムを使って、レンダリングする1つのコンポーネントを見つけます。

データバインディング

dataindexlengthの各値がバインドされます。詳細については、コンポーネントの子要素の拡張を参照してください。

以下は、dataプロパティにレシピの手順を表す文字列の配列を設定したSequencerコンポーネントの例です。コンポーネントではitemに1つのコンポーネントがあり、data変数を使ってdata配列からのコンテンツをレンダリングします。

クリップボードにコピーされました。

 {
  "type": "Sequencer",
  "item": {
    "type": "Speech",
    "content": "${index+1}. ${data}"
  },
  "data": "${payload.recipeData.steps}"
}

この例では、次のデータソースを使ってデータの配列をdataプロパティに提供します。

クリップボードにコピーされました。

{
  "recipeData": {
    "steps": [
      "オーブンを180℃に予熱します。",
      "バターと砂糖をミキサーでなめらかになるまで混ぜ合わせます。",
      "バターと砂糖を混ぜたものに卵を一度に1つずつ加えて、なめらかになるまでかき混ぜます。",
      "別のボールに...."
    ]
  }
}

Alexaは、data内の各文字列について、1回に1つずつSpeechコンポーネントを評価します。whenプロパティがtrueに評価されると、Alexaはそのコンポーネントをレンダリングします。この例では、whenプロパティがデフォルトのtrueに評価されるため、Alexaは、コンポーネントを4回(1回にdataの文字列を1つずつ)レンダリングします。ユーザーには4つの文字列すべてが1つずつ順に読み上げられます。

以下は、when文を使ってSequencerコンポーネントをネストし、種類の異なるデータのセットをインフレートする複雑な例です。

クリップボードにコピーされました。

{
  "type": "Sequencer",
  "items": [
    {
      "when": "${data.opening}",
      "type": "Speech",
      "content": "${data.opening}"
    },
    {
      "type": "Sequencer",
      "items": [
        {
          "type": "Speech",
          "content": "${data.speech1}"
        },
        {
          "type": "Speech",
          "content": "${data.speech2}"
        }
      ]
    }
  ],
  "data": "${payload.speechData}"
}

この例では、次のデータソースを使ってデータの配列をdataプロパティに提供します。

クリップボードにコピーされました。

{
  "speechData": [
    {
      "opening": "スピーチを開始します。"
    },
    {
      "speech1": "1つ目のスピーチです。",
      "speech2": "2つ目のスピーチです。"
    }
  ]
}

Alexaは、data内の2つの項目のそれぞれについて、Sequencerを1回ずつ評価します。

  • 最初の項目は、openingプロパティを持つオブジェクトです。${data.opening}trueのため、Alexaは最初のSpeechコンポーネントを選択します。data.speech1data.speech2の値がどちらも空のため、2つのSpeechコンポーネントを持つネストされたSequencerは、事実上無視されます。
  • 2つ目の項目は、speech1speech2のプロパティを持つオブジェクトです。${data.opening}falseのため、Alexaは最初のSpeechコンポーネントを無視します。ネストされたSequencerは子コンポーネントの1つの配列を使ってインフレートされるため、Alexaは両方のSpeechコンポーネントをレンダリングします。

最終結果は、「スピーチを開始します。1つ目のスピーチです。2つ目のスピーチです。」となります。