Google Maps Platformで地図を出してみた

技術者ブログと題して社員が日ごろ取り組んでいる学習内容を紹介します。
今回はWEBデザインをテーマにしている第0ユニットです。
本記事ではGoogle Maps Platformを使ってみたので紹介していきます。

Google Maps Platformとは

Google Maps Platformを使用することで、Google Mapの機能をウェブサイトやアプリに埋め込むことができます。
Google Maps Platformの詳細は公式ページで紹介されています。
https://mapsplatform.google.com

事前準備

Google Maps Platformを使うためには事前に、Googleアカウントを作成し支払いの設定をしておく必要があります。
支払いの設定はGoogle Cloudから設定することができます。
https://cloud.google.com/

APIキー取得

Google Maps APIを使用するには、APIキーを取得を取得しておく必要があります。
APIキーの取得は「有効なAPIとサービス」から行います。

「Maps JavaScript API」を選択します。

「鍵と認証情報」APIキーからAPIキーを取得することができます。

MAPの表示

地図の表示

APIは「Dynamic Library Import」、「NPM js-api-loader パッケージ」の方法で利用することができます。
利用方法の詳細は公式のガイド参照してください
Maps JavaScript API を読み込む


下記は地図を出すサンプルソースです。

<!DOCTYPE html>
<!--
 @license
 Copyright 2019 Google LLC. All Rights Reserved.
 SPDX-License-Identifier: Apache-2.0
-->
<html>
  <head>
    <title>Add Map</title>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    http://js/map.js
  </head>
  <body>
    <h3>My Google Maps Demo</h3>
    <!--The div element for the map -->
    <div id="map"></div>

    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "{APIキー}", v: "beta"});</script>
        
    <script>
      // Initialize and add the map
      let map;
      
      async function initMap() {
      
          // Request needed libraries.
          //@ts-ignore
          const { Map } = await google.maps.importLibrary("maps");
          const { AdvancedMarkerElement } = await google.maps.importLibrary("marker")
      
      
          // 地図の初期設定
          map = new Map(document.getElementById("map"), {
              zoom: 18,
              center: position1,
              mapId: "DEMO_MAP_ID",
          });
      
          // ピンの地点を設定
          const position1 = { lat: 35.165455654239224, lng: 136.90517107048055 };
          const position2 = { lat: 35.16480168326663, lng: 136.90544465580453 };

          // 地図にピンを設定する
          const marker = new AdvancedMarkerElement({
              map: map,
              position: position1,
              title: "ナディアパーク",
          });
      
          const marker2 = new AdvancedMarkerElement({
              map: map,
              position: position2,
              title: "矢場公園",
          });
      }

      initMap();
    </script>
  </body>
</html>

地図のAPIは下記の部分で読み込んでいます。
サンプルでは「Dynamic Library Import」でAPIを読み込んでいます。

script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))}) ({key: "{APIキー}", v: "beta"});</script>

地図の表示は下記の部分で表示を行っています

      // GoogleMapの読み込み
         const { Map } = await google.maps.importLibrary("maps");
          const { AdvancedMarkerElement } = await google.maps.importLibrary("marker")
      
      
          // 地図の初期設定
          map = new Map(document.getElementById("map"), {
              zoom: 18,
              center: position1,
              mapId: "DEMO_MAP_ID",
          });

また、下記のようにピンを複数設定することで、地図に複数のピンを立てることもできます。

// ピンの地点を設定
          const position1 = { lat: 35.165455654239224, lng: 136.90517107048055 };
          const position2 = { lat: 35.16480168326663, lng: 136.90544465580453 };

          // 地図にピンを設定する
          const marker = new AdvancedMarkerElement({
              map: map,
              position: position1,
              title: "ナディアパーク",
          });
      
          const marker2 = new AdvancedMarkerElement({
              map: map,
              position: position2,
              title: "矢場公園",
          });

今回はGoogle Maps Platformを使って地図を表示したり、
地図にピンを立てる方法をまとめました。

次回の第0ユニットの技術者ブログもお楽しみに!

技術者ブログ – 社内サーバファイルの自動バックアップ

技術者ブログとして日ごろ取り組んでいる学習内容をご紹介します。

今回はインフラをテーマにしている第3ユニットです。

今回は、社内サーバのファイルを自動でバックアップする方法となります。

普通にバックアップするならば、外付けのディスクに毎日ファイルをコピーすればよいのですが、 ランサムウェア対策として、2つの外付けディスクに交互にバックアップすることにしました。

最初は、外付けディスクを毎日手作業で、サーバにつないでバックアップしていたのですが、 なんとか自動化できないかと考え、パワーシェルによるスクリプトにして、 毎日スケジュール実行することができるようになりました。

事前作業

あらかじめ2つのディスクを接続し、UドライブとWドライブの名前にしておきますが、 認識できないように、ドライブは無効としておきます。

Uドライブのみドライブ設定している
Wドライブは認識していない

バックアップするドライブを切り替えるパワーシェル抜粋

以下のようなパワーシェルを用意し、ドライブを切り替えファイルをバックアップします。

###########################################################################################
# 定数宣言
###########################################################################################
$DiskNumber_U = 9   #バックアップ先のディスク番号1(Uドライブ)
$DiskNumber_W = 10  #バックアップ先のディスク番号2(Wドライブ)
$DriveNumber_U = 2  #バックアップ先のパーティション番号1(Uドライブ)
$DriveNumber_W = 2  #バックアップ先のパーティション番号2(Wドライブ)
$CopyPath_U = "U:\" # バックアップ先のパス文字(U)
$CopyPath_W = "W:\" # バックアップ先のパス文字(W)

###########################################################################################
# バックアップするドライブを切り替える
#   Uドライブ、Wドライブ
###########################################################################################
    if ( (Get-Partition -DiskNumber $DiskNumber_U -PartitionNumber $DriveNumber_U).DriveLetter -eq "U" )
    {
        # Uドライブを未設定、Wドライブを設定に変更
        Set-Partition -DiskNumber $DiskNumber_U -PartitionNumber $DriveNumber_U -IsHidden $True
        Set-Partition -DiskNumber $DiskNumber_W -PartitionNumber $DriveNumber_W -IsHidden $False
    } else {
        # Uドライブを設定、Wドライブを未設定に変更
        Set-Partition -DiskNumber $DiskNumber_U -PartitionNumber $DriveNumber_U -IsHidden $False
        Set-Partition -DiskNumber $DiskNumber_W -PartitionNumber $DriveNumber_W -IsHidden $True
    }

###########################################################################################
# バックアップ先のドライブのフォルダをすべて削除
###########################################################################################
try {
    Get-ChildItem -Path $CopyPath_U | Remove-Item -Recurse
}Catch{
    Get-ChildItem -Path $CopyPath_W | Remove-Item -Recurse
}

###########################################################################################
# ファイルコピー
###########################################################################################
    try {
        Copy-Item $ExportPath $CopyPath_U -Force -Recurse
    }Catch{
        Copy-Item $ExportPath $CopyPath_W -Force -Recurse
    }

以上となります。

次回の技術者ブログをお楽しみに。

Leveraging JavaScript in Outsystems

As an engineer blog, I would like to introduce the learning content that I am working on on a daily basis.
This is the second unit with the theme of low-code development.

This time’s theme: “Using JavaScript in Outsystems”

In our second unit, we regularly use Outsystems for low-code development.
Outsystems provides tools that allow you to develop intuitively by dragging and dropping parts without having to code as much as possible.

However, if you want to implement details such as the UI part as you want, there may be cases where the properties provided by Outsystems are not enough.
In such a case, you may be able to implement your ideal by using JavaScript. This time I will introduce one such example.

今回やりたいこと

This time, I would like to change the UI of DataGrid in Outsystems using JavaScript.
Specifically, we will introduce the following contents.
・Cancel the DataGrid’s default setting of coloring every other row.
・Color a specific column of DataGrid with your favorite color

How to use DataGrid
How to use the OutSystems Data Grid

DataGridのデフォルト色付け設定を解除する

First, we will change the coloring of every other row of the grid, which is set by DataGrid by default.

Normally, if no settings are made, every other row of the grid will be colored automatically, as shown below.
We will change this using JavaScript.

It’s hard to see because the color is so light, but you can see that the 2nd and 4th lines are colored gray.

First, prepare a ClientAction (DataGridOnInitialize) for displaying the DataGrid in the screen element where the grid is located, and add an Input parameter called GridWidgetId.

Next, in the Event item of the DataGrid property to which you want to apply JavaScript, set the ClientAction you created earlier to Handler.
At this time, also set the GridWidgetId added with the Input parameter.

Set the following JavaScript in the ClientAction you created last.
(When defining a variable in JavaScript, the Input parameter GridWidgetId is specified.)

//Get the Grid information created on the screen var grid = GridAPI.GridManager.GetGridById($parameters.GridWidgetId).provider; //Abolish coloring for each row grid.alternatingRowStep = 0;

I was able to cancel the setting where every other line was colored gray.

Color only specified columns of DataGrid

Next, we will use JavaScript to color only specific columns of the grid.
I would like to color only the Name and Age columns in the grid above in gray to make it easier to visually understand that they are non-editable columns.

This time, we will implement it by first coloring the entire grid gray, and then making only the editable Email column white.

First, write the following CSS in the Style Sheet of the screen.

.wj-cell{
background: lightgray;
}

.rowcolor{
background-color: white;
}

Next, add the following code to the JavaScript in ClientAction to complete the process.

//Set format for the acquired Grid
grid.itemFormatter = function(panel,r,c,cell){
//Color the Email column (3rd column) with white
  if(c === 2 ){
//Add class definition to cell
wijmo.addClass(cell,’rowcolor’);
}
};

You can now color only the specified columns!

Summary

As you can see, OutSystems provides a variety of properties, but I found that you can implement them the way you want by using JavaScript.
It felt like I was able to reach out to a specific area of concern, and I felt that the scope of development was expanding.

Why not consider using JavaScript if you cannot achieve the desired results using Outsystems properties alone?

In the second unit, we will continue to develop blogs for engineers using low-code tools such as OutSystems, so please look forward to it.

SpringBoot3 組み込みJettyで動かしてみた

こんにちは第0ユニットのチキンキウイです。
SpringBoot3がリリースされていたので、今回は組み込みサーバーを変更して
動かしてみようと思います。

環境

  • SpringBoot3.0.6
  • Java17
  • Gradle 7.6.1

設定内容

SpringBoot3を組み込みJettyで動作させるには「build.gradle」に以下に設定を追加すことで実現できます。

ext['jakarta-servlet.version'] = '5.0.0'

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    modules {
        module("org.springframework.boot:spring-boot-starter-tomcat") {
            replacedBy("org.springframework.boot:spring-boot-starter-jetty", "Use jetty instead of tomcat")
        }
    }
    implementation 'org.springframework.boot:spring-boot-starter-jetty'
    providedRuntime 'org.springframework.boot:spring-boot-starter-jetty'
}

動かしてみた

ここからは実際にプロジェクトを作成し実際に動かしていきます。

SpringBootプロジェクトの作成

[ファイル>新規作成>その他]からウィザードを開き
新規のspringスタータープロジェクトを作成します。

build.gradleの変更

プロジェクトを作成したら「build.gradle」を開きJettyの変更を追加します。

「build.gradle」変更後は「Gradleプロジェクトのリフレッシュ」を実行してください。

動かしてみた

プロジェクトのリフレッシュが完了したらプロジェクトを実行してみます。
実行してログに「Jetty started」が表示されていればJettyで起動しています。

画像に alt 属性が指定されていません。ファイル名: image-3-1024x401.png

まとめ

今回はSprinngBoot3でJettyサーバーを動かしてみました。
SpringBoot3の情報はまだまだ少ないので、参考の一つにでもなれば幸いです。

参考

GitHub Document how to downgrade dependencies to use embedded Jetty 11
https://github.com/spring-projects/spring-boot/issues/33044#issuecomment-1326332014

技術者ブログ:Oracle Databaseのアップグレード

技術者ブログとして日ごろ取り組んでいる学習内容をご紹介します。

インフラをテーマにしている第3ユニットです。

今回は、Oracle Databaseのアップグレードについて

あるシステムの全面的な更新の一環として、Oracle Databaseのアップグレードを担当しました。具体的には、古くなった12cのデータベースからメタデータ(表を始めとした、DB上のオブジェクトの定義)と行データ(各表で登録されている項目)をエクスポートして、同じ状態の19cのデータベースを作成することになりました。

開発環境が用意されていたため、新しいDBの構築は複数回リハーサルできましたが、12cのDBからのエクスポートは、DBに余計な影響を与えないために、回数を抑えることにしました。

そのため、一回エクスポートしたら、何回も使えるDMPファイルを出力するOracle Data Pump(データポンプ)というツールを使いました。

作業の流れ

各ステップを個別の監視できるために、アップグレードを以下のような流れで行いました。

  • データポンプで12cのDBからメタデータと行データをエクスポート
  • 12cの設定を確認しながら、同じ設定の19cの空っぽのDBを作成
  • 19cのDBにエクスポートしたメタデータと行データをインポート
  • 19cのDBの全体的な確認

上記の流れで、アップグレードできましたが、リハーサルの中で幾つかの問題に遭遇して、解決・回避の方法を調査することになりました。その問題を一つ、以下に紹介したいと思います。

シークエンス問題とその回避

データベースに登録される行の自動採番を使う表がある場合、そのシークエンス(順序)の状態(次に割り振られる番号)をそのまま継続する必要があります。そうしないと、データベースが同じ番号を再び割り振ろうとして、エラーが生じる恐れがあります。

自動採番を使う表の存在を、SQL Developerなどで確認できます。表作成のSQLを参照すると、「GENERATED ALWAYS/ BY DEFAULT AS IDENTITY」という定義が見られます。

自動採番が設定されているテーブル 
引用:https://stackoverflow.com/questions/49239177/sequences-vs-identity-columns-in-oracle

新しいDBへインポートする際に、メタデータと行データを同時にインポートすると、シークエンスが自動的に継続されますが、メタデータと行データを別々にインポートすれば、シークエンスが「1」からリスタートされて、手動で調整しなければならなくなります。

そのために、メタデータと行データの同時インポートをお勧めします。

次回の技術者ブログもお楽しみに。

技術者ブログ – ハードディスク完全消去方法

技術者ブログとして日ごろ取り組んでいる学習内容をご紹介します。
今回はインフラをテーマにしている第3ユニットです。

使用しているパソコンを捨てる時や、 仕事で使用しているパソコンを別のプロジェクトに移動させる時に ハードディスクのデータをすべて完全に消去する必要があります。

無料で使用できるソフトとして、今までは「DESTROY」というソフトがあったのですが、 最近のパソコンでは使用できなくなっていたので、 代替案を調べてみました。

※以下の作業を行うと、大事なデータも削除してしまうので、十分に注意して作業を行ってください。

結論

USBからUbuntuを起動してshredコマンドを使用すればよいとわかりました

手順

1.UbuntuインストールUSBを作ります

・UbuntuのISOイメージをダウンロードします。
・「Rufus」にて、ダウンロードしたISOイメージから、UbuntuインストールUSBを作成します

Rufus
Rufus

参考)Ubuntu:https://ubuntu.com/download/desktop Rufus:https://rufus.ie/ja/

2.パソコンの起動時、BIOSにてUSB優先にして起動します

Ubuntu起動中に、「Try Ubuntu without installing」を選択してそのまま起動してください

Ubuntu起動画面

Ubuntuデスクトップが起動されます

3.「Terminal」を開きます

Terminal画面

4.「fdisk」コマンドを使用して、ディスク一覧を確認します

sudo fdisk -l

5.「shred」コマンドを使用して、データを消去します

sudo shred -v -z -n 1 /dev/sdb

[ /dev/sdb ] の部分に、fdiskで調べた消去したいディスクを指定します。

●オプションの説明
・-v: 途中の進捗状況をターミナルに表示する
・-z: 最後に、オール0で上書きする
・-n 1: ランダム上書き1回する

以上で完了です。

次回の技術者ブログをお楽しみに。

技術者ブログ(3) – AWS のご紹介(Amazon Web Services)

技術者ブログと題して社員が日ごろ取り組んでいる学習内容を紹介します。
第3回は、クラウドをテーマにしている第3ユニットです。

今回のテーマ
『 AWS について』

AWSとは、 Amazon Web Servicesの略称で、Amazon.comから提供されているクラウドコンピューティングサービスです。クラウドの分野では世界1位のシェアを誇ります。


Amazon 社内のビジネス課題を解決するために生まれた IT インフラストラクチャのノウハウをもとに、2006 年、アマゾン ウェブ サービス(AWS)はウェブサービスという形態で、企業を対象に IT インフラストラクチャサービスの提供を開始しました。

引用
https://aws.amazon.com/jp/about-aws/

AWSでできること

AWSでは、インターネット経由でコンソール画面にアクセスすることで様々な機能を利用することができます。

AWSコンソール画面(サービス一覧)

代表的な機能を以下に挙げます。

  • Elastic Compute Cloud(EC2):AWSが提供する仮想サーバ です。
    LinuxやWindows 等様々なOSの仮想サーバ実行環境を利用することができます。
  • Simple Storage Service (S3):インターネット経由で利用できるストレージサービスです。高い堅牢性を実現しています。
  • Relational Database Service(RDS):リレーショナルデータベース構築サービスです。Oracle、MySQL、PostgreSQL等のデータベースを利用することができます。

AWSの料金について

AWSはサービス利用に応じて料金がかかる従量課金制となっています。
例えば、EC2では使用するインスタンス(仮想サーバ環境)とインスタンスの起動時間により料金が決まります。時間課金(オンデマンド)の他に、リザーブドという長期契約割引といったオプションもあります。
また、AWSでは「簡易見積ツール」を利用することで、月額金額を見積もることができます。

今後は、AWSの様々な機能について掘り下げてご紹介していきたいと思います。

技術者ブログ(1) – PythonとOpenCVで顔を認識する


Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118

Notice: A non well formed numeric value encountered in /export/sd215/www/jp/r/e/gmoserver/2/9/sd0971329/dandelions.co.jp/blog/wordpress-4.9.8-ja-jetpack_webfont-undernavicontrol/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119

技術者ブログと題して社員が日ごろ取り組んでいる学習内容を紹介します。
第1回は、AIをテーマにしている第1ユニットです。

今回のテーマ
『画像の中から顔を判別する』

使用する言語 – Python

機械学習向けのライブラリなど環境が充実しており情報も集めやすいです。

使ったもの – OpenCV

OpenCV(正式名称: Open Source Computer Vision Library)は、オープンソースのコンピューター・ビジョン・ライブラリです。コンピューターで画像や動画を処理するのに必要な、さまざま機能が実装されており、BSDライセンスで配布されていることから学術用途だけでなく商用目的でも利用できます。加えて、マルチプラットフォーム対応されているため、幅広い場面で利用されていることが特徴です。

引用
https://www.buildinsider.net/small/opencv/001


OpenCVには画像の特徴から判断するためのライブラリがあらかじめ用意されています。(カスケード型分類器とか言ったりするらしい)

今回はそれを利用し、用意した画像から顔を認識させ、顔の部分だけ切り出した画像を出力するプログラムを作成します。

ソースコード(抜粋)

トライ&エラーの過程は省略させていただき、実際に作った内容をざっくりと書きます。

openCVのインポート

カスケード型分類器に使用する分類器のデータ(xmlファイル)を読み込み

カスケード型分類器に使用する分類器のデータ(xmlファイル)を読み込みます。
今回は顔と目検出を行いたいため、上記2つのファイルを指定します。

カスケード型分類器を使用して画像ファイルから顔部分を検出する

顔検出を行います。検出に成功した場合は画像のサイズが出力されます。

検出部分を切り出して画像保存


実際にやってみた

  

この画像を指定してプログラムを実行すると…

   ↓

顔だけ認識された画像が生成されました!

  作ってみた感想

検索すると沢山の情報がでてきて、案外簡単につくることができました。
実際にソースを書く部分より、PythonやOpenCVのインストールなどの環境構築のほうが苦戦したかもしれません。
みなさんも興味があれば挑戦してみてください。

ここから切り出した画像を使い、誰の顔か判定する仕組みを作ってみたりしましたが、この先の話はまた次の機会に書きたいと思います。