Amazon Web Services ブログ

強化された Amazon Location Service による新機能と開発者体験

この記事は株式会社 MIERUNE の代表取締役 CEO である Yasunori Kirimoto に寄稿頂いた「New features and developer experience with enhanced Amazon Location Service」をソリューションアーキテクトの稲田が翻訳したものです。

地理空間アプリケーションを構築するには、地理空間データを扱うための専門知識と、システムの設計および開発のスキルが必要です。また、大量の地理空間データを収集および管理し、アプリケーションで効果的に利用するスキルも必要とされます。このプロセスは非常に手間がかかる可能性がありますが、その複雑さは Amazon Location Service を活用することで大幅に軽減できます。

Amazon Location Service では、API から高精度の地理空間データをすばやく取得できるため、開発者はアプリケーションの構築に集中できます。さらに、Amazon Location Service が従来の機能に加えて新機能が追加されました。Amazon Location Service の新機能を紹介し、アプリケーションでその機能を活用する方法をご紹介します。

Amazon Location Service の新機能のリリース

最大の変更点は、個別のリソース作成が不要になったことです。つまり、ユーザーは個々のリソース (Place Index、Map、Route Calculator など) を作成する必要がなくなり、API キーを設定するだけで、すぐに Amazon Location Service を使い始められます。

さらに、Maps、Places、Routes API に大幅な機能強化と新機能が追加されました。Maps API は、追加のスタイルと新しい静的マップ機能で更新されました。Places API は、新しい検索と地理コーディング機能で強化されました。最後に、Routes API は、Snap to Road、Waypoint Optimization、および追加の移動モードなどの新機能で更新されました。

API キーの作成

API キーを作成するには、AWS マネジメントコンソールまたは AWS Cloud Control API を利用できます。この例では、コンソールを使用します。Amazon Location Service コンソールに移動し、Manage resources の下にある API keys を選択します。Create API key を選択してください。

Image showing the Amazon Location Service console, specifically API Key actions such as Create API Key. The Create API key buttons have squares around them to alert readers to their location within the image.

図 1 – Amazon Location Service コンソール – API キーコンソール

デモのために、API キーを LasVegasMaps と名付け、以下のアクションを選択します。

  • GetStaticMap
  • GetTile
  • Geocode
  • GetPlace
  • SearchNearby
  • SearchText
  • CalculateIsolines
  • SnapToRoads
Image showing the API Key creation process and selecting the "Actions" that the API Key is authorized to perform.

図 2 – API キーアクションの選択

スクロールダウンすると、有効期限の設定や参照元の設定など、追加オプションがあります。これらはオプションですが、本番環境のアプリケーションには強くお勧めします。今回はこのデモのためこれらはデフォルトのままにしています。

Image showing additional options for API Keys including Expiration time, Referers and Tags.

図 3 – 追加の API キーオプション

Create API Key を選択してください。

API キーを作成したので、次はアプリケーションで使用するための値を取得する必要があります。Show API key value を選択し、値を安全な場所にコピーしてください。

Image showing a completed API Key, with the option to Show API Key Value for usage in our application. The Show API Key Value button has a square around it to alert readers to its location within the image.v

図 4 – API キーコンソールで、API キーの値を表示する

新しい Maps API

まず、GetStyleDescriptor と GetStaticMap について詳しく説明して紹介します。

地図アプリケーションの基盤となる GetStyleDescriptor の構築

GetStyleDescriptor を使用すると、マップスタイル情報を取得し、マップアプリケーションの基盤を迅速に構築できます。この機能は、様々な地理空間ソリューションやアプリケーション基盤に使用できます。新バージョンでは、異なるアプリケーション向けに目的に合わせて設計された拡張マップスタイルを提供しており、様々なレベルの地図詳細を持つダークモードとライトモードを提供しています。

MapLibre GL JS を使用してこれらのマップスタイルを活用する方法を紹介します。MapLibre GL JS と Amazon Location Service API キーを使用して、非常にシンプルな HTML ページを作成します。

simpleMap.html という名前の新しい HTML ファイルを作成し、以下のコードをファイルに貼り付けてください。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon Location Service Map</title>

    <!-- MapLibre GL CSS -->
    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />

    <style>
        body {
            margin: 0;
        }
        #map {
            height: 100vh; /* Full viewport height */
        }
    </style>
</head>

<body>
    <!-- Map container -->
    <div id="map"></div>

    <!-- JavaScript dependencies -->
    <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>

    <script>
        // Configuration
        const region = "<AWS Region>"; // Replace with your AWS region
        const mapApiKey = "<Your API Key>"; // Replace with your Amazon Location Service API key

        async function initializeMap() {
            // Initialize the map
            const map = new maplibregl.Map({
                container: "map", // HTML element ID where the map will be rendered
                center: [-115.1473824627421, 36.17071351509272], // Initial map center coordinates (Las Vegas)
                zoom: 12, // Initial zoom level
                style: `https://maps.geo.${region}.amazonaws.com/v2/styles/Standard/descriptor?&color-scheme=Light&variant=Default&key=${mapApiKey}`, // Map style URL
            });

            // Add navigation controls to the map
            map.addControl(new maplibregl.NavigationControl(), "top-left");
        }

        // Call the function to initialize the map
        initializeMap();
    </script>
</body>
</html>

この HTML ページをブラウザで開いてください。ラスベガスの地図が表示されるはずです。この地図の鍵は、前のコードで設定したスタイル URL です。この URL では、明るい色のスタンダードスタイルマップを要求しています。政治的な見解など、追加のパラメータも指定できます。

Image showing the Las Vegas Metro area with a light color scheme.

図 5 – ラスベガス(ネバダ州)を中心とした地図

GetStaticMap を使用して静的地図画像を作成する

GetStaticMap を使用すると、指定した座標、ズームレベル、イメージサイズに基づいて静的な地図画像を作成できます。この機能は、印刷物やメディアの投稿に地図画像を含めるのに役立ちます。この機能にはさまざまなパラメータがあり、他のデータ (ポイント、ライン、ポリゴンなど) を重ね合わせることもできます。基本的な例を示します。使用する AWS リージョンと新しく作成した API キーに合わせて URL を編集してください。指定した場所の静的な地図画像を表示するには、以下の URL を Web ブラウザのアドレスバーに貼り付けてください。

https://maps.geo.<Your AWS Region>.amazonaws.com/v2/static/map?center=-115.170,36.122&zoom=15&width=1024&height=1024&key=<Your API Key>

図 6 – ラスベガスストリップを表示する静的地図画像

新しい Places API

次に、SearchText と SearchNearby を紹介します。

SearchText による特定の POI データの検索

SearchText を使用すると、ユーザーは特定の目的地(POI)データを検索して表示することができます。この機能は、ユーザーが特定の場所や施設をすばやく検索できるように設計されています。ユーザーは指定されたパラメータで POST リクエストを送信し、候補地点データを含むレスポンスを受け取ることができます。そのデータを地図上に視覚化する例を紹介します。

searchText.html という名前の新しい HTML ファイルを作成し、以下のコードをファイルに貼り付けてください。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon Location Service – Search Text</title>

    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />
    <style>
      body {
        margin: 0;
      }
      #map {
        height: 100vh;
      }
    </style>
  </head>

  <body>
    <!-- map container -->
    <div id="map"></div>
    <!-- JavaScript dependencies -->
    <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>
    <!-- Import the Amazon Location Client -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1"></script>
    <!-- Import the utility library -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-datatypes@1"></script>
    <script>
      // Configuration
      // Set the AWS region for Amazon Location Service
      const region = "<AWS Region>";
      // API key for authenticating requests
      const mapApiKey = "<Amazon Location Service API Key>";
    
      async function initializeMap() {
        // Create an authentication helper using the API key
        const authHelper = await amazonLocationClient.withAPIKey(mapApiKey, region);
        
        // Initialize the Amazon Location Service Places client
        const client = new amazonLocationClient.places.GeoPlacesClient(
          authHelper.getClientConfig()
        );
    
        // Define search parameters for coffee shops
        const SearchTextInput = {
          BiasPosition: [-115.170, 36.122], // Las Vegas coordinates
          MaxResults: 25,
          QueryText: "Coffee Shops"
        }
    
        // Perform the search using Amazon Location Service
        const searchResults = await client.send(
          new amazonLocationClient.places.SearchTextCommand(SearchTextInput)
        )
    
        // Initialize the map
        const map = new maplibregl.Map({
          container: "map",
          center: [-115.170, 36.122], // Las Vegas coordinates
          zoom: 14,
          style: `https://maps.geo.${region}.amazonaws.com/v2/styles/Standard/descriptor?&color-scheme=Light&variant=Default&key=${mapApiKey}`,
        });
    
        // Add navigation controls to the map
        map.addControl(new maplibregl.NavigationControl(), "top-left");
    
        // When the map is loaded, add search results as a layer
        map.on("load", () => {
          // Convert search results into a GeoJSON FeatureCollection
          const featureCollection = amazonLocationDataConverter.searchTextResponseToFeatureCollection(searchResults);
    
          // Add a data source containing GeoJSON from the search results
          map.addSource("place-index-results", {
            type: "geojson",
            data: featureCollection,
          });
    
          // Add a new layer to visualize the points
          map.addLayer({
            id: "place-index-results",
            type: "circle",
            source: "place-index-results",
            paint: {
              "circle-radius": 8,
              "circle-color": "#0080ff",
            },
          });
    
          // Add click event listener for the search result points
          map.on('click', 'place-index-results', (e) => {
            if (e.features.length > 0) {
              const feature = e.features[0];
              const coordinates = feature.geometry.coordinates.slice();
              
              // Create a formatted HTML string with the feature's properties
              const properties = feature.properties;
              let description = '<h3>' + (properties['Title'] || 'Unnamed Location') + '</h3>';
              description += '<p>Address: ' + (properties['Address.Label'] || 'N/A') + '</p>';
    
              // Create and display a popup with the location information
              new maplibregl.Popup()
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(map);
            }
          });
          map.on('mouseenter', 'place-index-results', () => {
            map.getCanvas().style.cursor = 'pointer';
          });
          map.on('mouseleave', 'place-index-results', () => {
            map.getCanvas().style.cursor = '';
          });
        });
      }
    
      // Call the function to initialize the map
      initializeMap();
    </script>
  </body>
</html>

HTML ファイルをブラウザで開くと、ラスベガス(ネバダ州)のベネチアン・リゾートを中心としたコーヒーショップのマップが表示されます(図7)。

Image showing multiple dots on a map representing coffee shops on the Las Vegas strip.

図 7 – SearchText API の結果を表示した地図

SearchNearby を使用して指定された場所の周辺の POI データを検索する

SearchNearby を使用すると、指定された場所の近くにある POI データを取得できます。この機能は、ユーザーが周辺の店舗や観光スポットを検索するのに便利です。ユーザーは指定されたパラメータを含む POST リクエストを送信し、候補地点データを含むレスポンスを受け取ることができます。そのデータを地図上に可視化する例を示します。

searchNearby.html という名前の新しい HTML ファイルを作成し、以下のコードをファイルに貼り付けてください。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon Location Service – Search Nearby</title>

    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />
    <style>
      body {
        margin: 0;
      }
      #map {
        height: 100vh;
      }
    </style>
  </head>

  <body>
    <!-- map container -->
    <div id="map"></div>
    <!-- JavaScript dependencies -->
    <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>
    <!-- Import the Amazon Location Client -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1"></script>
    <!-- Import the utility library -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-datatypes@1"></script>
    <script>
      // Configuration
      
      // Set the AWS region for Amazon Location Service
      const region = "<AWS Region>";
      // API key for authenticating map requests
      const mapApiKey = "<Amazon Location Service API Key>";
    
      async function initializeMap() {
        // Create an authentication helper using the API key
        const authHelper = await amazonLocationClient.withAPIKey(mapApiKey, region);
        
        // Initialize the Amazon Location Service Places client
        const client = new amazonLocationClient.places.GeoPlacesClient(
          authHelper.getClientConfig()
        );
    
        // Define search parameters for nearby casinos and hotels
        const SearchNearbyInput = {
          QueryPosition: [-115.170, 36.122], // Las Vegas coordinates
          MaxResults: 25,
          Filter: {
            IncludeCategories: [
              "casino",
              "hotel"
            ]
          }
        }
    
        // Perform the nearby search using Amazon Location Service
        const searchResults = await client.send(
          new amazonLocationClient.places.SearchNearbyCommand(SearchNearbyInput)
        )
    
        // Initialize the map
        const map = new maplibregl.Map({
          container: "map",
          center: [-115.170, 36.122], // Las Vegas coordinates
          zoom: 15,
          style: `https://maps.geo.${region}.amazonaws.com/v2/styles/Standard/descriptor?&color-scheme=Light&variant=Default&key=${mapApiKey}`,
        });
    
        // Add navigation controls to the map
        map.addControl(new maplibregl.NavigationControl(), "top-left");
    
        // When the map is loaded, add search results as a layer
        map.on("load", () => {
          // Convert search results into a GeoJSON FeatureCollection
          const featureCollection = amazonLocationDataConverter.searchNearbyResponseToFeatureCollection(searchResults);
    
          // Add a data source containing GeoJSON from the search results
          map.addSource("place-index-results", {
            type: "geojson",
            data: featureCollection,
          });
        
          // Add a new layer to visualize the points
          map.addLayer({
            id: "place-index-results",
            type: "circle",
            source: "place-index-results",
            paint: {
              "circle-radius": 8,
              "circle-color": "#0080ff",
            },
          });
    
          // Add click event listener for the search result points
          map.on('click', 'place-index-results', (e) => {
            if (e.features.length > 0) {
              const feature = e.features[0];
              const coordinates = feature.geometry.coordinates.slice();
              
              // Create a formatted HTML string with the feature's properties
              const properties = feature.properties;
              let description = '<h3>' + (properties['Title'] || 'Unnamed Location') + '</h3>';
              description += '<p>Address: ' + (properties['Address.Label'] || 'N/A') + '</p>';
    
              // Create and display a popup with the location information
              new maplibregl.Popup()
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(map);
            }
          });
          map.on('mouseenter', 'place-index-results', () => {
            map.getCanvas().style.cursor = 'pointer';
          });
          map.on('mouseleave', 'place-index-results', () => {
            map.getCanvas().style.cursor = '';
          });
        });
      }
    
      // Call the function to initialize the map
      initializeMap();
    </script>
  </body>
</html>
Image showing multiple dots on a map representing casinos and hotels centered around the Venetian Resort in Las Vegas, NV.

図 8 – SearchNearby API の結果を表示した地図

新しい Routes API

最後に、新しい CalculateIsolines と SnapToRoads について説明します。

CalculateIsolines で指定した場所から到達可能な範囲を見つける

CalculateIsolines は、指定したポイントから到達可能な範囲を取得できます。Isolines のユースケースには、配達可能エリアの特定や不動産の立地評価などがあります。ユーザーは指定したパラメータで POST リクエストを送信し、到達可能なエリアを示すポリゴンデータを含むレスポンスを受け取ることができます。そのデータを地図上に可視化する例を紹介します。

calculateIsolines.html という名前の新しい HTML ファイルを作成し、以下のコードをファイルに貼り付けてください

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon Location Service - Isolines</title>

    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />
    <style>
      body {
        margin: 0;
      }
      #map {
        height: 100vh;
      }
    </style>
  </head>

  <body>
    <!-- map container -->
    <div id="map"></div>
    <!-- JavaScript dependencies -->
    <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>
    <!-- Import the Amazon Location Client -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1"></script>
    <!-- Import the utility library -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-datatypes@1"></script>
    <script>
      // Configuration
      
      // Set the AWS region for the Amazon Location Service
      const region = "<AWS Region>";
      // API key for authenticating map requests
      const mapApiKey = "<Amazon Location Service API Key";
    
      async function initializeMap() {
        // Create an authentication helper using the API key
        const authHelper = await amazonLocationClient.withAPIKey(mapApiKey, region);
        
        // Initialize the Amazon Location Service Routes client
        const client = new amazonLocationClient.routes.GeoRoutesClient(
          authHelper.getClientConfig()
        );
    
        // Define parameters for calculating isolines
        const IsolinesInput = {
          Origin: [-115.17015436843275, 36.12122662193694], // Starting point coordinates
          Thresholds: {
            Time: [
              300, 600, 900 // Time thresholds in seconds
            ]
          },
          TravelMode: "Pedestrian" // Travel mode for isoline calculation
        }
    
        // Calculate isolines using Amazon Location Service
        const routeResults = await client.send(
          new amazonLocationClient.routes.CalculateIsolinesCommand(IsolinesInput)
        )
    
        // Initialize the map
        const map = new maplibregl.Map({
          container: "map",
          center: [-115.16766776735061, 36.12177195550658], // Map center coordinates
          zoom: 15,
          style: `https://maps.geo.${region}.amazonaws.com/v2/styles/Standard/descriptor?&color-scheme=Light&variant=Default&key=${mapApiKey}`,
        });
    
        // Add navigation controls to the map
        map.addControl(new maplibregl.NavigationControl(), "top-left");
    
        // Add a marker at the origin point
        const marker = new maplibregl.Marker()
          .setLngLat([-115.17015436843275, 36.12122662193694])
          .addTo(map)
    
        // When the map is loaded, add isolines as layers
        map.on("load", () => {
          // Convert isoline results into a GeoJSON FeatureCollection
          const featureCollection = amazonLocationDataConverter.calculateIsolinesResponseToFeatureCollection(routeResults);
    
          // Add a data source containing GeoJSON from the isoline results
          map.addSource("isolines", {
            type: "geojson",
            data: featureCollection
          });
    
          // Add a fill layer to visualize the isoline areas
          map.addLayer({
            'id': 'isolines-fill-900',
            'type': 'fill',
            'source': 'isolines',
            'filter': ['==', ['get', 'TimeThreshold'], 900],
            'paint': {
              'fill-color': '#0000ff',
              'fill-opacity': 0.5
            }
          });

          // Add a layer for 600m (10)
          map.addLayer({
            'id': 'isolines-fill-600',
            'type': 'fill',
            'source': 'isolines',
            'filter': ['==', ['get', 'TimeThreshold'], 600],
            'paint': {
              'fill-color': '#00ff00',
              'fill-opacity': .5
            }
          });

          // Add a layer for 300m (5)
          map.addLayer({
            'id': 'isolines-fill-300',
            'type': 'fill',
            'source': 'isolines',
            'filter': ['==', ['get', 'TimeThreshold'], 300],
            'paint': {
              'fill-color': '#f10000',
              'fill-opacity': 0.5
            }
          });
    
          // Add an outline layer to highlight the isoline boundaries
          map.addLayer({
            'id': 'isolines-outline',
            'type': 'line',
            'source': 'isolines',
            'paint': {
              'line-color': '#000000',
              'line-width': 2
            }
          });
        });
      }
    
      // Call the function to initialize the map
      initializeMap();
    </script>
  </body>
</html>

HTMLファイルをブラウザで開くと、次の地図(図9)が表示されます。この地図は、ベネチアン・リゾートからの徒歩圏内の距離を 5 分、15 分、30 分の時間枠で示しています。

HTMLファイルをブラウザで開くと、次の地図(図9)が表示されます。この地図は、ベネチアン・リゾートからの徒歩圏内の距離を 5 分、15 分、30 分の時間枠で示しています。

Image showing walking distances using the CalculateIsolines API from the Venetian resort in 5, 10, and 15 minute intervals. Five minutes is represented in brown, 10 in green and 15 in purple.

図 9 – ベネチアンリゾートからの徒歩距離を表示した地図

SnapToRoads による位置補正されたルートデータの取得

SnapToRoads を使用すると、GPS データやその他の位置データを最寄りの道路にスナップし、位置補正後の線データを取得することができます。この機能は、車両追跡や交通分析の精度を向上させるのに非常に役立ちます。ユーザーは指定されたパラメータを含む POST リクエストを送信し、位置補正された線データを含むレスポンスを受け取ることができます。処理前と処理後のデータを地図上で視覚化する例を示します。

snapToRoad.html という名前の新しい HTML ファイルを作成し、以下のコードをファイルに貼り付けてください。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Amazon Location Service - Snap to Roads</title>

    <!-- MapLibre GL CSS -->
    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />

    <style>
        body {
            margin: 0;
        }
        #map {
            height: 100vh; /* Full viewport height */
        }
    </style>
</head>

HTML ファイルをブラウザで開くと、以下の地図(図10)が表示されます。青い線は GPS トレースを表し、赤い線は道路にスナップされたバージョンを表しています。

Image showing a curvy blue line representing a GPS trace and a corrected (red line) route on a map.

図 10 – GPS トレースに基づいて修正されたルートを表示した地図

クリーンアップ

このデモで作成された Amazon Location Service リソースは API キーのみでした。API キーを削除するには、Amazon Location Service コンソールに移動し、作成した API キーを選択して、Deactivate を選択します。キーの無効化を確認し、Delete を選択します。標準の 90 日間の無効化期間を無視してキーを強制的を選択してください

まとめ

Amazon Location Service は新しい機能によりさらに柔軟性が向上しました。このアップデートにより、以前は必要だったリソース作成が不要になり、API キーを設定するだけで様々な API を使用できるようになりました。これにより、ユーザーは地理空間アプリケーションを迅速かつスムーズに構築できます。

注目すべき新機能には、Maps API の GetStyleDescriptor と GetStaticMap、Places API の SearchText と SearchNearby、Routes API の CalculateIsolines と SnapToRoads があります。

Maps API では、GetStyleDescriptor を使用して様々なマップスタイルを取得し、アプリケーションに適用できます。また、GetStaticMap は指定した座標とズームレベルに基づいて静的な地図画像を生成できます。Places API では SearchText を使用して POI データを検索でき、SearchNearby は特定の場所の周辺にある POI を見つけることができます。Routes API では、CalculateIsolines を使用して指定したポイントからの到達可能性を計算し、SnapToRoads は GPS データを修正して正確な経路データを取得できます。

これらの新機能により、アプリケーション開発者は地理空間データをより効果的に活用し、ユーザーエクスペリエンスを大幅に向上させることができます。ビジネスの加速化に役立つ方法の詳細については、AWS の担当者にお問い合わせください。

参考資料

Yasunori Kirimoto

Yasunori Kirimoto は、AWS DevTools Hero であり、株式会社 MIERUNE の共同創業者兼 CEO です。GIS(地理情報システム)とFOSS4G(Free and Open Source Software for Geospatial)を専門としています。20 年以上の経験と地理空間データおよびアプリケーションに関する幅広い知識を持っています。