Salesforce Live Agent ハンズオン

こんにちは。mp_hskです。

今日は会社の勉強会で行った、Salesforce Service Cloudの機能、

Live Agentのハンズオンを紹介したいと思います。

ハンズオン時の手順に従い、Lightningではなくクラッシックの画面で行います。

What is Live Agent?

Live Agentとは、コーポレートサイトにアクセスしたエンドユーザーと

Salesforce上のユーザー間でリアルタイムチャットができる機能です。

リアルタイムチャットによって、エンドユーザーはカスタマーサポートの

ユーザーにより簡単に、素早く問い合わせが行えます。

ユーザーの準備

まずはSalesforceの開発者アカウントにログインし、クラッシックモードに切替ます。

ユーザーアイコンをクリックして Salesforce Classicに切り替えを押せばOKです。

クラッシックモードに切り替わったら次に、

設定→ユーザ管理→自分ユーザーを選び、Live Agentユーザーをチェックします。

f:id:mp_hsk:20170717214405p:plain

f:id:mp_hsk:20170717214650p:plain

次にプロファイルでサンプルコンソールを使えるようにします。

設定→ユーザの管理→プロファイルでシステム管理者を編集し、

サンプルコンソールを使えるようにします。

f:id:mp_hsk:20170717215126p:plain

編集画面でサンプルコンソールを参照可能に設定します。

f:id:mp_hsk:20170717215322p:plain

Live Agent設定

では Live Agent そのものの設定に移ります。

まず、設定のクイック検索にLive Agent と入力し、Live Agentの基本設定を開きます。

編集画面で Live Agentの有効化 にチェックを入れて保存します。

f:id:mp_hsk:20170717220042p:plain

次に、設定のクイック検索にLive Agent と入力し、スキルを開きます。

新規作成ボタンを押すと下記の画面が出るため

  • 名前とAPI参照名に適当な名前(英字)を入力
  • ユーザーの割り当てで先ほど設定変更したユーザーを追加

して保存します。

f:id:mp_hsk:20170717220804p:plain

次に、設定のクイック検索にLive Agent と入力し、[チャット]ボタンと招待を開きます。新規作成ボタンを押すと下記の画面が出るため

  • 種別をチャットボタンを選択
  • 名前とAPI参照名に適当な名前を入力(英字)
  • 言語、カスタムエージェント名、自動挨拶は好みのものを入れる(ハンズオンしたときは英語だったので画像では英語になっています)
  • ルーティング種別を選択肢に設定
  • 選択可能なスキルに先ほど作成したスキルを追加

以上の設定を行って保存します。

f:id:mp_hsk:20170717221803p:plain

次に、設定のクイック検索にLive Agent と入力し、リリースを開きます。

新規作成ボタンを押すと下記の画面が出るため

  • Live Chat リリース名、API参照名、ウィンドウタイトルを適当に入力(英字)
  • 訪問者にトランスクリプトの保存を許可する にチェック

して保存します。

f:id:mp_hsk:20170717222246p:plain

 

次はクライアント側の設定です。

さっき作ったチャットボタンとリリースの画面を開き、自分で作成したものを選ぶと

HTMLとスクリプトが自動で生成されています。

チャットボタン

f:id:mp_hsk:20170717222744p:plain

リリース

f:id:mp_hsk:20170717222925p:plain

このHTMLとスクリプトを適当なテキストファイルに張り付け、.htmlで保存して

HTMLファイルを作ります。

また、チャットボタンのHTMLコメント

<!-- オンラインチャットコンテンツ --> 前部分に online

<!-- オフラインチャットコンテンツ -->   前部分に     offline 

という記述を入れておきます。

これで作業は完了です。

動かしてみる

先ほど作ったHTMLをブラウザで開くと

offline と表示されると思います。

f:id:mp_hsk:20170717223644p:plain

この状態では通話はできないので、

セールスフォース側でサンプルコンソールを開きます。

開き方は 右上のアイコンからサンプルコンソールを選択するだけです。

f:id:mp_hsk:20170717224024p:plain

サンプルコンソールを開いたら、右下の Live Agent を開き、

状態を オンライン に変更します。

f:id:mp_hsk:20170717224308p:plain

この状態でもう一度さっき作ったHTMLを開くと online と表示が変わります。

f:id:mp_hsk:20170717224425p:plain

オンラインのリンクを開くと、下記の画面が出てセールスフォース側へコールします。

コールされた側はサンプルコンソールに着信が来ます。

f:id:mp_hsk:20170717224934p:plain

コールされた側が承諾を押せばチャットで会話ができます。

また、コールを承諾した時点で、ケース(セールスフォールの顧客問い合わせを管理するオブジェクト)が自動的に作成されます。

f:id:mp_hsk:20170717225335p:plain

ハンズオン終了!

まとめ

Salesforce  Service Cloud に搭載されたLive Agent を使えば、

自社にコーポレートサイト内でリアルタイムチャットによる顧客との

コミュニケーションが取れます。

最近こんな感じのチャットできるサイトが増えてきたので、自分または

興味を持っているお客様がいるエンジニアさんは試してみてはいかがでしょう?

なお、このハンズオンではやっていませんがチャット画面やボタンのデザインを

変えたり、モバイルアプリへの対応もできるみたいです。

 

将来的には bot と連携して、AIである程度自動返信してくれる機能とかつくと

夢が膨らむなぁ。

 

Heroku ハンズオン Heroku ConnectでForce.comの取引先データを表示してみる

こんにちは。mp_hskです。

昨日の続き。今日は前作ったForce.comの取引先オブジェクトを

Herokuのアプリ上で表示でしてみる実験。

(やり直しが効かなかった部分があるため今回スクリーンショットが少し不親切ですがご容赦ください)

準備

作ったHeroku アカウントにログインして、Heroku Connect のアドオンを入れておく

下の画像の Find more addons から探してDemo版をインストールすればOK

f:id:mp_hsk:20170705172859p:plain

Heroku Connect側の設定

アドオンを入れたらHeroku Connect のリンクをクリックする。

そうすると新しい設定を追加するボタンが出てくるのでクリック。

したらば、DBのスキーマ名を選ばせる画面が出てくるので

自分で作ったHerokuアプリのDBスキーマ名を入れる。

スキーマ名はローカルのコマンドラインで以下のコマンドを打てば調べられる

heroku config

このコマンドで出てきたDATABASE_URLのけつの部分がスキーマ名。

 

スキーマ名を入れたら次はSales Foceへの認証画面が出てくるので自分のアカウントでログインする。

 

次にMappingの作成をする。

Mapping の設定は下の画面のCreate Mappingからできる。

f:id:mp_hsk:20170705174052p:plain

開くとSales Force側のオブジェクトを選ぶ画面が出てくるので取引先オブジェクトを選ぶ。(下のスクショだとすでに作成済みなのでハイライトされてるが、最初に作る場合はクイック検索の窓から絞り込みが可能)

f:id:mp_hsk:20170705174339p:plain

 

オブジェクトを選ぶと細かい設定画面が出てくるので、とりあえずデフォルトの設定にプラスしてName Jusho__cを同期するように設定してSave。

これでHeroku Connect側の設定は完了。

f:id:mp_hsk:20170705174800p:plain

アプリケーション側のソース追加

次にアプリ側を作る。

以下のソースをサンプルアプリのsrc/main/java/com/example/Main.java に追加。

@RequestMapping("/torihikisakilist")
String torihikisakilist(Map<String, Object> model){
try (Connection connection = dataSource.getConnection()) {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM スキーマ名.Torihikisaki__c");

ArrayList<String> output = new ArrayList<String>();
while (rs.next()) {
output.add(rs.getString("Name") + "," + rs.getString("Jusho__c"));
}

model.put("records", output);
return "torihikisakilist";
} catch (Exception e) {
model.put("message", e.getMessage());
return "error";
}
}

また、src/main/resource/templatesにtorihikisakilist.htmlを新規作成

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'torihikisakilist')}">

<body>
<div class="container">
<h1>Database Output</h1>
<ul th:each="record : ${records}">
<li th:text="${record}"/>
</ul>
</div>
</body>
</html> 

 追加した後は下記コマンドでデプロイすればOK

git add .

git commit -m "Heroku Connect Test"

git push heroku master 

結果

以下のForce.com側の取引先データが

f:id:mp_hsk:20170705175613p:plain

無事Heroku側のアプリ http://アプリケーションのID.herokuapp.com/torihikisakilist

に取引先オブジェクトの内容が表示されました。

f:id:mp_hsk:20170705175929p:plain

まとめ

今回はHeroku Connectを使ってForce.comとHerokuのアプリを連携させましたが

思った以上に簡単に行うことができました。

もう少し凝ったことをやるときは調査が必要ですが、ハンズオンとしては簡単なので

皆さんも試してみてはどうでしょうか?

 

ツッコミあればお待ちしてます。

Heroku で Java ハンズオン

最近暑いですね。社会復帰したmp_hskです。

今日はこれから仕事で使うことになった Heroku について

公式サイトのハンズオンを行ったので雑感などを少々。

What Heroku??

Herokuとは、Sales Force社が提供している Webアプリケーションを開発・運用するために必要な機能を持つPaaS(Platform as a Service)。ざっくり言うと、

  • 複数の言語をサポートしているコンテナ型の軽量webアプリケーション実行基
  • ソース管理にGitを使っており、デフォルトでgit pushをフックしてデプロイをしてくれる
  • 他にもDevOpsをサポートするためのツールが充実
  • コンテナのスケールアウトも簡単にできる
  • Addonによる拡張機能が充実
  • Sales Forceとの連携が簡単にできる

始めるには?

基本的にはHerokuのアカウントを入手した後で、Getting Startedから公式サイトの手順に従えば、ちょっとしたwebアプリケーションのデプロイ・実行までできる。

Heroku | Sign up

上記のリンクをクリックして、有効なメールアドレスとその他情報を適当に入れ、

送られてきたメールのリンクをクリックすればアカウント作成はOK。

アカウントは無料で利用でき、有料Addonを入れるか、コンテナを複数起動しなければ無料で利用可能。

最初にログインしたらGUIアプリケーションの作成ができ、作成したアプリのアクセスすると対応する言語のハンズオンが出てきてくれる。下記はJavaのハンズオンページ

f:id:mp_hsk:20170704213857p:plain

ハンズオンのざっくり解説

基本的にはページに書いてある通りやればできるが英語なのでざっくり解説しておく

  1. Heroku Toolbelt(コマンドラインツール)をインストールし、コマンドラインからHerokuにログインする
  2. JDK 8, Maven 3,(書いてないけどGitクライアント)をローカルにインストールしておく
  3. Herokuで作成したアプリケーションのソースリポジトリをgit cloneする
  4. heroku createコマンドでアプリを作り、pushするとアプリがデプロイされる。また、heroku ps:scale=1 でコンテナ起動。(heroku openはアプリのURLをブラウザで開くコマンド)
  5. ログをtailしてみる
  6. Procファイルの内容(herokuの実行コマンド)を確認する(だけで修正はなし)
  7. heroku ps:scale=0でコンテナを止めてみる
  8. pom.xmlの内容を修正し、mavenビルドする
  9. アプリをローカルコンテナで動かしてみる
  10. Main.javaを修正してリモートにpushする
  11. papertailアドオンを入れる。(これはクレカをアカウントに登録してないとできなかったので飛ばしたが、情報さえ登録しておけばアドオン自体は無料っぽい)
  12. heroku run bush でリモートのコンテナで作業をしてみる
  13. 環境変数を設定し、アプリから参照してみる
  14. postgresqlのアドオンを入れてDBアクセスしてみる

という感じ。コマンドそのまま打てば大体できるので特に困ることはない

雑感

動きも軽いし、デプロイもgit pushだけでできるので手軽で便利!

また、コマンドラインツールを使えば結構色々できる。

(なお、同じことがweb画面のダッシュボードからGUIでもできるっぽい)

AWSのEC2よりスタートの敷居が低いので初心者にもお勧めできそう。

なお、もう少し詳しいハンズオンがしたい場合は、以下のサイトの動画を視聴すればいろいろ勉強になる。

http://dotinstall.com/lessons/basic_heroku

 

次回はforce.comとの連携もやってみよう。

JJUGナイトセミナー「JavaエンジニアのためのJava(再)入門セミナー」へ行ってきた

おばんです。mp_hskです。

本日はJJUG(日本Javaユーザーグループ)主催の勉強会、

JavaエンジニアのためのJava(再)入門セミナー」へ行ってきたのでレポートします。

※セミナーの資料は後日公開されるらしいので公開されたらコメントに貼ります

From Old Java To Modern Java

お話の内容としては、古いJava(1.4)から最新のJava 8 までに追加された

新文法について、ソースコードの例を見ながら勉強した。

例のソースコードの内容としては

  • CSVファイルを全件リードし、DTOのリストに詰め替える
  • DTOを渡してCSVファイルの末尾に追加書き込みする
Java 1.4 → Java SE 5.0
  • StringBufferからStringBuilderへの切り替え(スレッドを気にしない環境での性能向上)
  • Listにジェネリクスを使って無駄なキャストを書かないようにする
  • 拡張for分を使ってリストのシーケンシャルアクセスを楽に
  • アノテーションを使ってコンパイラに警告をださせる(@override)

この辺はさすがに自分も知ってた

Java 5.0 → Java 7
  • 複数種類のexceptionのcatch句をまとめる構文が便利
  • ダイアモンド演算子 <> を使えばジェネリクス記法における右辺の型指定を省略できるので積極的に使おう
  • FilesクラスでBufferdReaderとかBufferdWriterなどのIOストリーム系のインスタンス生成が簡単に書けるようになった
  • try with resources(try句の中にファイルオープンなどの処理を書く)で finally句でのクローズが不要になる 

この章では特に try with resourceが大事らしい。C#のusing句で同じことができるけど

Javaにも実装されてたのは知らなかったので覚えておこう。

Java 7 → Java 8
  •  Stringにjoinメソッドができた!
  • Local Date などDate系のクラスが充実した
  • ほかにもちょこちょこ有用なAPIが増えてる

この章では、Java 8 の大きな変更だった Stream APIと Lambda式にはあえて触れずに

ほかにも細かいところ色々変わってるよって紹介でした。

 

以外と知らなかったことが多くて良いセッションでした。

数値計算をたしなむ

このセッションは基本的には、

正確性の求められる計算は BigDecimal 使おうねって話でした。

元金融畑の自分としては目新しい内容はありませんでしたが、

BigDecimalのコンストラクタにはStringかLong渡さないと、丸め後の数値からインスタンス生成されるから意味ねーって話は、昔これでバグ作った経験があるのでニヤリときました。

Stream API入門

Java 8 で追加された Stream APIとLambda式に関するセッションでした。

Lambda式についてはこちらでも書きましたね。

ブログをはじめてみようか(ラムダ式) - mp_hskのブログ

 

Stream APIというのは、(現状では)主にコレクション操作に使うAPI

C#LINQみたいなもんだと理解しました。

使い方は

  1. stream メソッドで streamを作る
  2. 中間操作でstreamを操作する
  3. 終端操作で操作結果を得る

中間操作は以下のようなことができ、1個のstreamに何回もできる

  • フィルターをかけて必要な要素にのみ処理する
  • mapメソッドで要素を置き換える

終端操作は以下のようなことができ、1個のstreamに1回だけ実行できる

  • 操作結果はListやMap,Setインスタンスとして取り出す
  • 操作結果に対して、シーケンシャルに特定の処理を行う(foreach)
  • 操作結果の合計値や平均値を取得する

JavaのStreamは複数の要素に対して一括処理ができなかったり、分岐処理ができなかったりする。

 

セッションの最後で、なぜこれを学ぶべきかということを言っていた。

現状ではほぼコレクションの操作のみなのでぶっちゃけifとforで書いた方が楽な場合も多いが、今後はStreamの内容が固定のデータではない Hot Stream(Httpリクエストとか)を並列でさばいていくためのものに拡張されていくため、考え方を覚えておくといいとのこと。

 

このセッションのStreamAPIは知らなかったし、JavaのLambda式がStream API

ための新文法だったという小話も聞けたので良かった。

 

全体的な感想

web業界に行ってからしばらくPHPばっかりでJavaを触ってなかったけど

(業界移って2年しかたってないのに)結構自分が知ってる頃と変わっていることに驚いた。

7月からまたSIerに戻り、Javaに触れる機会も多くなるため、今後登Java 9なども

含めて新しい機能についてキャッチアップしていくべきだなと思った。

みさきまぐろきっぷで日帰り旅行に行ってきた

こんにちは。7月まで無職のmp_hskです。今回も与太話です。

 

今日は無職期間を利用して、友人からお勧めされた京急電鉄のお得な切符、

”みさきまぐろきっぷ” で日帰り旅行行ってきました。

 

11:00ごろ、品川駅の券売機で切符を購入。(3,090円)

f:id:mp_hsk:20170622174416j:plain

快特で一時間ほどで三崎口駅に到着!以外と近いね

f:id:mp_hsk:20170622174516j:plain

お昼時だったので早速マグロを食べに行こう!

今回選んだのは、三崎口からバスで5分ほど、引橋から歩いていける寿司屋さん

寿司割烹 豊魚 さんの鉄火チラシをいただきました。

f:id:mp_hsk:20170622174820j:plain

新鮮なマグロがこれでもかと、酢飯の上に盛られていました。

味もボリュームも大満足です。お味噌汁も海老出汁が効いててうまい。

 

そのあとバスで油壷に異動し荒井浜海水浴場を少し散歩してきました。

林道を抜けて

f:id:mp_hsk:20170622175115j:plain

海だー!!!!!!!!!!!!!!!!!!!!!!!!!!!

f:id:mp_hsk:20170622175148j:plain

磯野くぼみにカニとか小魚いました。

f:id:mp_hsk:20170622175315j:plain

散歩して汗かいたので、ホテル観潮荘で温泉はいってきました。

そんなに広くなかったけど露天風呂は海を見ながら入れて景色サイコーでした。

泉質はナトリウム系で、そんなにきつくないので肌の弱い人でも大丈夫そう。

f:id:mp_hsk:20170622175518j:plain

温泉でリラックスしたらあとは電車で帰るだけ。

 

以上の行程は全部切符代にふくまれています。

うまいマグロ食べて、温泉でリラックスして、移動費込みで3090円は確かにお得だ。

近辺に住んでいる方は一度試してみてはいかがでしょうか?

Pythonに標準装備されている統合開発環境 IDLEが思ったより高機能だった

こんにちは。mp_hskです。

今日は、Python勉強中に知った標準装備の統合開発環境 "IDLE"が

思ったより便利だったので機能紹介をします。

なお、バージョンは Python 3.6.1 付随のものです。

起動方法

IDLEの起動方法は、windows版の場合

スタート→すべてのプログラム→Python3.6→IDLE

起動するとこんな感じのプロンプトが立ち上がる。

f:id:mp_hsk:20170614122732p:plain

対話式プログラミング

上記で立ち上がったコンソールは対話式でプログラミングが実行できる。

また、計算結果や変数などを print関数書かなくてもデフォルトでプリントしてくれる。

また、文字列やキーワードのハイライトもしてくれる。

f:id:mp_hsk:20170614123642p:plain

別だしでファイルを作る + エディット系機能

File → New File で別窓が開いて上記と同じ様な環境でコードが書ける。

色々エディット機能もあるよ。

  • Format → Comment Out Region でドラックしている行をコメントアウト
  • Format → Indent Regionでドラックしている行をインデント
  • Undo, Redi, 置換や検索などの標準的なエディタ機能ももちろん健在
  • ctlr + space でオート補完機能もある

f:id:mp_hsk:20170614125005p:plain

実行・デバッグ

作ったプログラムは Run → Run Moduleで実行できる。

(実行結果は別ウィンドウが開く)

また、実行結果であがったコンソールのほうの、 Debug → Debuggerでデバッガが開く

f:id:mp_hsk:20170614125200p:plain

デバッガを開いた状態でもう一回 実行をするとデバッグモードで実行できる。

デバッグモードではStepでステップ実行したり、確保されているオブジェクト

の内容を参照したりすることができる。

f:id:mp_hsk:20170614125626p:plain

ファイルエディタ側でブレークポイントを指定することも可能

f:id:mp_hsk:20170614125948p:plain

まとめ

今回はPython標準の統合開発環境である IDLE について紹介したが、

標準装備の割りにはそれなりに充実したツールなので、

お勉強でPythonをさわる人はひとまずこれでやってみれば開発がぐっと楽になると思う

この記事が自分のようなPython初心者の助けになればうれしいなぁ。

 

ツッコミあればお待ちしてます。

Froce.comで作ったアプリケーションにVisualforceで作った独自画面を足してみる

こんにちは。mp_hskです。

今日は下記ブログ記事の続きです。

Force.com で 出張申請システムを作ってみる - mp_hskのブログ

上記で作った取引先オブジェクトを一括登録する独自画面を

実装していきたいと思います。

まずざっくり用語解説

作る前に要素について少し解説します。

Visualforceは基本MVCモデルで設計されており、

  • View → Visualforce ページ
  • Controller → Apexのコントローラークラス
  • Model → Apex のモデルクラス

という構成になっています。

今回は簡単な画面なんでModelはなしで View ←→ Controllerで作ります。

Visualforce ページのコーディング

設定→開発者コンソール→File→New →Visualforce Pageでページを作ります

■AccountAdd.vfp(ファイル名)

<apex:page controller="MyCustomCtrl">
  <apex:sectionHeader title="取引先の一括登録" />
  <apex:form >
    <apex:pageBlock title="取引先情報">
      <apex:dataList value="{!acts}" var="ad">
        <apex:pageBlockSection title="Account Information">
           <apex:inputField value="{!ad.name}"/>
        </apex:pageBlockSection>
     </apex:dataList>
     <apex:commandButton value="一括登録" action="{!save}" />
    </apex:pageBlock>
  </apex:form>
</apex:page>

これもざっくり解説すると

  • <apex:page> → ルートタグ+コントローラー紐付け
  • <apex:sectionHeader> → ページのヘッダータグ
  • <apex:form > → HTMLのformタグと同じ
  • <apex:pageBlock> → HTMLのdivタグみたいなモンで背景などのスタイルをデフォルトで入れてくれる
  • <apex:dataList> → ループのタグで valueに指定した変数の要素数分ループでHTMLを生成
  • <apex:pageBlockSection>→ これもHTMLのdivタグみたいなモン
  • <apex:inputField> → HTML のinputタグみたいなモン
  • <apex:commandButton>→HTMLのbuttonタグみたいなもん

処理内容としては、MyCustomCtrlの acts プロパティに指定されたリスト数分、入力用のテキストボックスを作る感じのプログラム。

コントローラーのコーディング

設定→開発者コンソール→File→New →Apex Classでコントローラーを作ります

public class MyCustomCtrl {

  public List<Torihikisaki__c> acts{ get; set; }

  public MyCustomCtrl(){
    acts = new List<Torihikisaki__c>();
    for(Integer i = 0;i < 3;i++){
      acts.add(New Torihikisaki__c());
    }
  }

  public void save(){
    insert acts;
  }
}

これもざっくり解説すると

  • Torihikisaki__cオブジェクトのリストをプロパティにもつ
  • コンストラクタでプロパティに空のTorihikisaki__cオブジェクトを3つセット
  • saveメソッドでプロパティのTorihikisaki__cオブジェクトを永続化

申請業務アプリに作ったページへ遷移するタブを作成

設定→クイック検索で "タブ"を検索 → タブ を選び

Visualforceタブを新規作成する(名前とスタイルは適当に)

f:id:mp_hsk:20170609172612p:plain

作ったら基本デフォルトで申請業務にタブが追加されるが、もし追加されなかったら

アプリケーションマネージャ→申請業務→編集→項目を選択 のタブ

で追加することができます。

作った画面を使ってみる

作った画面はこちらのように取引先名を3つ入力できる感じになる

f:id:mp_hsk:20170609172958p:plain

この状態で一括登録ボタンをクリックして、取引先タブに移動すると

f:id:mp_hsk:20170609173112p:plain

入力した3つの取引先が無事登録されてる。やっ↑た↑ぜ↓

学習のまとめ

今回は以下の点を学習した。

  1. Visualforce Pageを使った独自ページの実装
  2. ページに対してコントローラーを作成し独自処理を実装

Visualforceのタグは紹介した以外にも豊富にあるし、Apexはかなり柔軟に

プログラミングできるので、カスタマイズもこれでいけそう。

ただ、柔軟すぎて色々出来てしまう分、折角Saasを使ってるのに

構築コストがフルスクラッチと同じ!ってなことにならないように

標準でできることをもっと覚えてバランスよく利用できるように

これからは勉強していきたいと思った(小並感)

 

 

以上で紹介した書籍の内容はほぼ網羅したけど、Apexは色々できそうだから

なれるためにもう一回自分で何か書いてみようかな??