OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter で Firebase Crashlytics を使おうとすると ネットワークエラーが発生する問題

結構ハマったので共有します。
# 概要
FlutterでFirebaseのCrashlyticsを使おうと、手順通りに設定していったのに、下記のエラーがでて疎通できない問題についてです。

```
[Fabric] failed to download settings Error Domain=FABNetworkError Code=-5 "(null)" UserInfo={status_code=403, type=2, request_id=, content_type=application/json; charset=utf-8}
```
Crashlyticsの画面も疎通待ちのまま更新されません。。。
![Screen Shot 2020-05-22 at 7.28.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315258/50e6f861-c910-5b11-020c-a79a0a5eb804.png)



# やったこと
まずは、FlutterとFirebase自体を接続します。
1. Firebase consoleでプロジェクトを作成し、iOS向けのアプリ追加ウィザードを進めます。
2. 途中で GoogleService-Info.plist をDLできるのでXcodeのRunner/Runnerに設置します。（このファイルがiOSとFirebaseの接続情報となります）
3. ウィザードの最後に接続待ちとなるので、Flutterをビルドすると接続が完了となります。

次に、Firebase Crashlyticsの接続をします。
1. Firebase consoleでCrashlyticsを開いてSDK追加し疎通待ちの状態にします。
2. https://pub.dev/packages/firebase_crashlytics のiOS Integrationに従って設定します。
3. Flutterをビルドすると疎通が完了するハズです。が、疎通できません。。。

海外サイト等を調べてみると以下のような解決アプローチは載っていましたが、すべて該当しませんでした。。。

- pubspec.yaml のロード順を変更する  
firebase_coreよりも後にfirebase_crashlyticsを書くこと
- XcodeのInfo.plistに手書きでAPI Keyを追加する（旧式のやりかた？）
- XcodeのRunScriptのInput Filesに以下を追加（Xcode 10のみ）  \$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)

# 解決策
半ばあきらめつつも調べていると、1つのIssueを見つけました。
https://github.com/FirebaseExtended/flutterfire/issues/1592
同じようなアプローチだなぁと思いつつ、最後の方を見てみると「実機でテストするとうまくいきました」と書いてある！

もしやと思いつつさっそく、実機でテストしたところ疎通できました！
Crashlyticsの画面も疎通完了しました！
![Screen Shot 2020-05-22 at 7.39.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315258/f8483761-6b83-10c4-f35f-d7f5a0506f83.png)

解決できてよかったです。
その後、クラッシュデータを送信してみたのですが、これもシミュレーターからはうまく届かず、実機からであればデータが届き、Firebase Crashlyticsでも確認できました。
超初心者の40代おじさんの為の5G（第5世代移動通信システム）

四十代の技術を持っていないおっさんが
会社の技術戦略を考えることになって
慌てて、技術を調べるシリーズ




## 特徴
- 超高速通信

- 多数同時接続
  - 1平方キロメートルあたり100万台のセンサー接続を実現

- 超低遅延
  - 通信の遅延を1ms以内に抑えるためにはサーバを近くに置く必要あり
  - 広域での実現には膨大なインフラ整備が必要
   - 屋内施設やスタジアム、イベント会場が当面の適用先

## トピック
- スマート社会の準備が整うのは2022-2023年頃
- ２０２０年　商用5G開始

## ローカル5G
- 企業や自治体が独自で構築
- 同収益化するか、が課題
  - ローカル5Gで受益化ではなく、サービス次第

## 調べること
- 総務省
USB切替機

以前秋葉原で処分品を280円で買ってきた、ArvelのUSB切替機を調べてみました。

![写真（2020-05-22 7.05）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/74f334a3-88f7-4140-a07d-70f0534ec4aa.jpeg)

購入したものは2回路のもので2台のホスト間でデバイスを切り替えて使えるようにするものです。4回路の製品もあったようです。

中に使われているチップはUSBのDevice DescriptorからActionStarという台湾の会社の製品のようです。

![スクリーンショット（2020-05-22 6.41.47）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/55db964b-3ca4-043f-f517-fdf413852a63.png)

VID,PIDは0x2101,0x0201です。

接続されてるホストにはデバイスが見え、接続されてないホストには切替機が見える仕様になっています。接続されてない方からしかコントロールできません。

Windows 7に付属のソフトをインストールして切り替えをwiresharkでusbスヌープしてみました。切り替えはHIDのSET_REPORTを使っていました。

```
No.     Time           Source                Destination           Protocol Length Info
     15 5.803210       host                  1.2.0                 USBHID   38     SET_REPORT Request

Frame 15: 38 bytes on wire (304 bits), 38 bytes captured (304 bits) on interface wireshark_extcap1040, id 0
USB URB
    [Source: host]
    [Destination: 1.2.0]
    USBPcap pseudoheader length: 28
    IRP ID: 0xfffffa8007164010
    IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
    URB Function: URB_FUNCTION_CLASS_INTERFACE (0x001b)
    IRP information: 0x00, Direction: FDO -> PDO
    URB bus id: 1
    Device address: 2
    Endpoint: 0x00, Direction: OUT
    URB transfer type: URB_CONTROL (0x02)
    Packet Data Length: 10
    [Response in: 16]
    Control transfer stage: Setup (0)
    [bInterfaceClass: HID (0x03)]
Setup Data
    bmRequestType: 0x21
    bRequest: SET_REPORT (0x09)
    wValue: 0x0200
    wIndex: 0
    wLength: 2
    bRequest: 9
    wValue: 0x0200
    wIndex: 0 (0x0000)
    wLength: 2
    Data Fragment: 0200

No.     Time           Source                Destination           Protocol Length Info
     16 5.803210       1.2.0                 host                  USBHID   28     SET_REPORT Response

Frame 16: 28 bytes on wire (224 bits), 28 bytes captured (224 bits) on interface wireshark_extcap1040, id 0
USB URB
    [Source: 1.2.0]
    [Destination: host]
    USBPcap pseudoheader length: 28
    IRP ID: 0xfffffa8007164010
    IRP USBD_STATUS: USBD_STATUS_SUCCESS (0x00000000)
    URB Function: URB_FUNCTION_CONTROL_TRANSFER (0x0008)
    IRP information: 0x01, Direction: PDO -> FDO
    URB bus id: 1
    Device address: 2
    Endpoint: 0x00, Direction: OUT
    URB transfer type: URB_CONTROL (0x02)
    Packet Data Length: 0
    [Request in: 15]
    [Time from request: 0.000000000 seconds]
    Control transfer stage: Complete (3)
    [bInterfaceClass: HID (0x03)]
```

[KLabさんのIRリモコン用のコード](https://github.com/mkttanabe/BtoIrRemocon/blob/master/BtoIrRemoconMac.c)をVID/PIDを書き換えて、以下で切り替え出来ました。いつもお世話になります。(\_o\_)

```c
        buf[0] = 0x00;
        buf[1] = 0x02;
        buf[2] = 0x00;
        WriteToDevice(refDevice, buf, DEVICE_BUFSIZE);
```

切り替えるとカチカチ音がするので、リレーが入ってるのかもしれません。

何か面白い使い方が思いついたら使ってみようと思います。
カスタマイズに優れたYouTrackでタスク管理はじめました

タスク管理やプロジェクト管理にどんなツールを導入していますか？
私はOKRクラウドの「[banto](https://banto.jp/)」の開発に携わっており、
[banto](https://banto.jp/)開発チームでは新たにYouTrackを導入しました。
今までは [backlog](https://backlog.com/ja/) でタスク管理をしていたのですが、
YouTrackでチームにどんぴしゃの管理方法を実現できました。
[banto](https://banto.jp/)チームでのYouTrackを使った事例を3点ほど紹介致します。

## YouTrackとは
 [JetBrains](https://www.jetbrains.com/ja-jp/) から出ているプロジェクト管理ツールが [YouTrack](https://www.jetbrains.com/ja-jp/youtrack/) です。
日本ではあまり馴染みの無いツールですが、世界中で45,000社以上で使われている実績があります。
このツールの特徴はなんと言ってもカスタマイズ性です。

## どんなタスク管理方法ができるか
[banto](https://banto.jp/)チームでは下記フローでYouTrackを活用して、
日々のタスク管理からリリース機能の管理をしております。
事例としては下記三点になります。
**1. タスクの優先順位を決めるマトリクス図**
**2. 各自のタスクの進捗状況を見るカンバンボード**
**3. リリースボード**

### 1. タスクの優先順位を決めるマトリクス図
<img width="1822" alt="スクリーンショット 2020-05-17 18.49.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638832/40950522-04a8-4ede-e064-d1b4ecc7180a.png">
こちらはX軸：概算工数、Y軸：要望指数のマトリクスになっています。
表の右側に行くほど工数が長くなり上に行くほど要望が多い機能である事を示します。

このボードを作った背景として[banto](https://banto.jp/)の開発ではセールスも開発も一緒に、
あーだこーだ言いながら着手するタスクを決めています。
セールスチームがこのタスクのチケットは最近お客様からよく言われるからチケットを上にずらそう、
開発チームがこのタスクは工数が意外と掛かるからチケットを右側にずらそう。
こんな意見をどんどんドロッグ＆ドロップしてチケットの位置を変更して、
どのチケットを実行するのかをチーム全体の意見を含めた形で結論がつけやすくなります。
WEB上のホワイトボードみたいに機能してくれるので、
リモートで離れていてもストレスなくタスク決めの議論が出来るようになりました。
そしてこちらで取り組みを決めたタスクは自動的に次のボードにチケットが移行します。

###2. 各自のタスクの進捗状況を見るカンバンボード
<img width="1823" alt="スクリーンショット 2020-05-17 20.19.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638832/db342eac-93cc-f071-72af-93e4b539c10e.png">
こちらはX軸：進行状況、Y軸：担当者のカンバンボードになっています。
[Trello](https://trello.com/ja)に近いタスク管理方法ですが、
表の右側に行くほどタスクが進行しており担当者別にタスクの進行状況を認識できます。
そしてこのボードの進行状況で「完了」に割り振られたタスクは自動的に次のボードにチケットが移行します。

###3. リリースボード
<img width="1821" alt="スクリーンショット 2020-05-17 20.33.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638832/b4a0cfb2-cc01-1e47-8550-832395a95d48.png">
こちらはX軸：分類、Y軸：リリースバージョンのマトリクスになっています。
バージョン毎にどんな機能をリリースしたのかが一目瞭然になりました。
ここまでチケットが来たらチケットの移動は終わりです。

## チームに合うカスタマイズを
2020年5月17日時点で、ユーザー数が10名までなら無料プランで導入できる嬉しい価格設定になっています。
そして[banto](https://banto.jp/)チームのカスタマイズ例も全て無料プランで実現出来ました。
チームによってタスク管理ツールにもとめるニーズは様々なはずです。
カスタマイズに優れたYouTrackなら今まで満足するツールが無かったチームにも満足できる解決策が作れるでしょう。
PHP デバイスサイズにより埋め込みサイトのwidthをコントロール


Get browser width using php
https://stackoverflow.com/questions/23239157/get-browser-width-using-php
サイト参照デバイスをJavaScriptにて取得しphp側に返す。

```
<?php
session_start();
if(isset($_POST['width'])){
   $_SESSION['screen_size'] = array();
   $_SESSION['screen_size']['width'] = intval($_POST['width']);
   $_SESSION['screen_size']['height'] = intval($_POST['height']);
}



if(!isset($_SESSION['screen_size'])){
?>
<html>
<head>
<script>
function getSize(){
document.getElementById('inp_width').value=screen.width;
document.getElementById('inp_height').value=screen.height;
document.getElementById('form_size').submit();
}
</script>
</head>
<body onload='getSize()'>
<form method='post' id='form_size'>
<input type='hidden' name='width' id='inp_width'/>
<input type='hidden' name='height' id='inp_height'/>
</form>
</body>
</html>


<?php
}else{
    var_dump($_SESSION['screen_size']);
}
暇なので『RPAツール』を作る #1

# はじめに
皆さん、初めまして。enp（えん）と申します。pは飾りです。
この記事は今から『RPAツール』を作ろうとする人の進捗報告になります。
RPAやRPAツールの作り方が書いてあるものではございませんので、ご了承ください。
今回は『どのようなRPAツールを作るのか』『そもそもRPAって何？』というところをお話しできればと思います。　

# RPAって一体なんぞや？
さて、今からRPAツールを作っていくのですが、
### <font color=#ff0000>RPAってなんじゃらほいほいほ～い！</font>
という方もいらっしゃると思いますので、かる～く説明させて頂きます。本当に軽く説明するだけなので、詳しく知りたい方は他をあたってください。

__RPA__とは簡単に言うと__Excelでいうマクロのようなもの__です。
__自動でPC作業をやってくれるヤツ__です。
### 以上！
はい、簡単に説明しました。
内容は非常にふざけていますが、実際7割ぐらい説明していると思います。（あくまでも個人の意見です）

しかし、皆様はお気づきでしょうか？
<font color=#ff0000>__私が作るのは『RPAツール』であって『RPA』ではありません。__</font>
では、『RPAツール』とは何でしょうか？

# RPAツールって何？
前の項目では、RPAについて二行で説明しました。ですが、『RPA』と私が作る『RPAツール』は違います。この項目ではRPAツールについて説明します。

__RPAツール__とは一言でいうと__RPAを作るヤツ__です。

RPAと言うには簡単ですが、『何をやってもらうか』は自分で設定しなければなりません。RPAさんに『こんな仕事あるんだけど......どう？』と頼む必要がある訳です。
そんな時に使うのがRPAツール、今回私が作るものになります。

分かって頂けたでしょうか？
何言ってるのか分かんなかった人は『RPA作るヤツ作るんだなぁ、コイツ』ぐらいで大丈夫です。
さて、次の項目では私の作るRPAツールについてご説明します。
構想段階で粗削りもいいところですが、期待せずご覧になって頂ければ幸いです。

# ぼくがかんがえたさいきょうのRPAツール
前の項目ではRPAツールって何？　というところを説明しました。この項目ではようやく私の作るRPAツールについて語ろうと思います。

私が作ろうとしているRPAツールは以下の要件を満たすものになります。

- GUIであること
- プログラムの知識がなくともRPAを実装できる・作れる
- RPAの並列作業ができる*
- 実装したRPAを起動しながら他の作業が出来る*

この四点です。その他の機能については既存のRPAツールと同じか、劣ってしまう可能性があります。
*があるものは仮です。今の段階では出来ると考えていますが、実際のところどうなるかは分かりません。
仕様が変わったらまた記事を書こうと思います。

以上が『ぼくがかんがえたさいきょうのRPAツール』です。
既存のものもあるかと思いますが、スキルアップのための開発ですので問題ないでしょう。

# 最後に
中身の薄い記事にお付き合い頂きありがとうございます。
これからは進捗報告という形で更新出来たらいいなと考えております。
多分、次の記事は『開発環境』などの紹介だと思いますので、よろしくお願いいたします。
以上、enpがお送りいたしました。
Core Data を使用する既存のアプリに CloudKit 機能を追加

`Core Data` テクノロジーを使用するアプリをお持ちの場合は、`CloudKit` サポートを簡単に追加できます。

`CloudKit` を利用すれば、データベースに保存されたデータをユーザーのデバイス間で同期させることができます。

`CoreData + CloudKit` 機能は、デフォルトで、ユーザーの情報をプライベートデータベースに保存します。つまり、ユーザーが他のデバイス上で同じApple IDを使ってサインインした場合にのみ保存されたユーザーの情報にアクセスできます。

## ステップ 1. Xcodeプロジェクト設定で必要な機能をオンにする。“iCloud”の"CloudKit”をオンにする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/aaf99b44-81d2-ce1b-0ca3-91bc9b27414a.png)

「CloudKit」をオンにします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/9a2971f3-b149-49bb-edf3-6ada2127b9b9.png)

既存の"Containers"のトグルボタンをどれかひとつクリックするか、プラスアイコンをクリックして新規"Container"を加える。

### 新規"Container"を加える:

追加ボタンをクリックします

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3633353333302f39613239373166332d623134392d343962622d656466332d3661646132313237623962392e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/891c2b7f-bfac-4a8f-787a-67006722f81e.png)

新しい「Container」の名前を入力してください

<img width="450" alt="Screen Shot 2020-05-12 at 1.06.19 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/bde5384a-e306-91e7-39bf-6b7d124aa054.png">

## ステップ 2.  `Core Data` の設定で `CloudKit` サポートをオンにします

### データベースモデルを変更

1. まず、`. xcdatamodeld` ファイルを開きます
2. `Configuration` タブで構成を選択します:

<img width="771" alt="Screen Shot 2020-05-21 at 16.28.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/a3031fb2-5309-a72e-64c0-7b37cef04ac8.png">

3. 画面の右側で、クリックし、`CloudKit` で使用をオンにします (Used with CloudKit)

<img width="264" alt="Screen Shot 2020-05-21 at 16.29.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/1ae1e71a-506c-1d1f-8434-11753b9443d0.png">

### コード内のクラウドコンテナにアクセスする

そして、すべての`NSPersistentContainer`を`NSPersistentCloudKitContainer`に置き換えます。`AppDelegate.swift`ファイルに1つある可能性があります。

元の:

```swift
let container = NSPersistentContainer(name: "CoreDataDemo")
```

新:

```swift
let container = NSPersistentCloudKitContainer(name: "CoreDataDemo")
```

## ステップ 3.  テストとデプロイ

1. クラウドデータベースを設定する必要がないことに注意してください。データベース構造は自動的に `CloudKit` の開発サーバーにデプロイされます。次に、しばらくの間アプリを使用し、`Core Data` データが生成されていることを確認する必要があります。

2. このステップは重要です！次に`CloudKit`のオンラインポータル http://icloud.developer.apple.com へ行き、あなたのアプリを左側から見つけて、開発データベースをプロダクションにデプロイします。これを忘れると、App Storeからあなたのアプリをダウンロードした実際のユーザーが、データをクラウドに同期できなくなります。

***最後にはiCloudの開発用データベースを本番環境にデプロイする必要があります。***

<img width="1013" alt="Screen Shot 2020-05-11 at 4.32.00 PM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/82288f3a-2f0f-23cd-e1ba-c8ca51002883.png">

---


CloudKitとCore Dataを使用する際の注意点については、こちらの記事もご覧ください。


https://qiita.com/MaShunzhe/items/f3e1b439bb0233be615a


---

:relaxed: [Twitter @MszPro](https://twitter.com/MszPro)

:sunny: [私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。](http://mszpro.com/ioskiji/)
<img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">
controller を間違えて生成してしまったら

rails tutorial 3章　「ほぼ静的なページの作成」　にてcontrollerを生成する際にcontroller名を間違えて生成してしまいました。
その時の対処法です。

正
controller Static_Pages_controller.rb
アクション　home help

誤
controller Static_controller.rb
アクション　Pages home help


#原因
controllerを生成する際にコマンドラインで
rails g controller Static Pages home help
としてしまった為、Pages がアクションとして認識されてしまったんですね、、、

#対処
rails destroy controller Static Pages home help
これで間違えて生成したcontrollerは削除できました。

再度
rails g controller StaticPages home help
で正しいcontrollerを生成


ちなみに
rails g controller Static_Pages home help
でも同じStatic_Pagesコントローラーが生成されます。
10⁹⁹⁴²⁰⁶⁷ は 8 桁である

この記事は下記の記事の続編ともいうべきものです。
[桁数は Math.log10(x).floor + 1 でいいのか - Qiita](https://qiita.com/scivola/items/beb3f2883b046d0256d1#comment-5716d002682cd3a72db6)

さて，$10^{9942067}$ は 10 進で何桁の数だろうか[^ans]。

[^ans]: もちろん計算するまでもなく 9942068 桁である。

Ruby なら簡単さ。

```irb
irb(main):001:0> (10 ** 9942067).to_s.length
(irb):1: warning: in a**b, b may be too big
=> 8
```

え？　は，8 桁ぁ？　ど，どういうこと？

しかも何か変な警告が出てるし。つか，この警告がヒントか。要するにデカすぎてちゃんと計算できてないってこと？　でもエラーじゃないしな。

いっそ `.to_s.length` を取って実行してみるか。
いや待てよ，もし巨大整数が表示されようとしたらターミナルがしばらく操作不能になりそうだしな。
えーい，やっちまえ。

```irb
irb(main):001:0> 10 ** 9942067
(irb):1: warning: in a**b, b may be too big
=> Infinity
```

へ？　Float::INFINITY ってこと？
整数の整数乗なのに「浮動小数点数の正の無限大」になると？

あの，もしかして答えの「8」って，`Infinity` の文字数ですかい？

```rb
irb(main):002:0> Float::INFINITY.to_s
=> "Infinity"
```

やっぱし。

ちなみに，指数が 1 小さい $10^{9942066}$ は `10 ** 9942066` で計算できる。
このあたり，Ruby のバージョンにもよるそう。この記事は Ruby 2.7.1 に基づいている。

`**` は，結果が巨大すぎる整数になりそうなとき，計算を放棄して警告を出したうえで `Float::INFINITY` を返す，という仕様だそうです。
なので，実際的なプログラムで本当にそんな事態が起こりそうなときは，計算結果を `finite?` で確認したうえで使う必要がありそう。

なお，$10^{9942067}$ を本当に計算したければ `10 ** 9942066 * 10` で計算できる。
初心者によるプログラミング学習ログ 323日目

#100日チャレンジの323日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
323日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>　323日目　1h<br>・ポートフォリオ作成<br><br>調べているうちに寝落ちしててほぼすすまず！<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1263563802118811648?ref_src=twsrc%5Etfw">May 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Kotlin】内容の重複したファイルを削除する【Java】

# やりたいこと
あるディレクトリの中に内容の重複したファイルが大量に有る時、1つだけ残して重複したものを削除します。

## やり方
ファイル全体を比較すると処理コストが高くて大変です。

そこで今回はファイルのハッシュ（ダイジェスト）を比較することとし、以下の方針で実装しました。

1. ファイルのハッシュを取ってダイジェストを取得
2. ダイジェストが`Set`に既存かチェック
3. 存在していれば削除
4. 存在していなければ`Set`に`add`

# サンプルコード
とりあえず動くサンプルは以下の通りです。

```kotlin
import java.io.File
import java.security.MessageDigest

val sha256 : MessageDigest = MessageDigest.getInstance("SHA-256")

fun getDigest(bytes: ByteArray): List<Byte> = sha256.digest(bytes).asList()

fun getFiles(pathToDir: String): List<File> = File(pathToDir).listFiles()?.asList() ?: emptyList()

fun main() {
    val files = getFiles(/* 処理対象ディレクトリのパス */)

    val set = HashSet<List<Byte>>()
    var count = 0

    files.forEach {
        val digest = getDigest(it.readBytes())

        if (!set.add(digest)) {
            if (it.delete()) {
                println("Deleted:\t${it.name}")
                count++
            } else {
                println("Fail delete:\t${it.name}")
            }
        }
    }

    println("\n\n$count deleted.")
}
```

## 実行結果
<details><summary>折り畳み</summary><div>

```bash
Deleted:	43_3のコピー.gif
Deleted:	46_3のコピー2.gif
Deleted:	70_1のコピー2.gif
Deleted:	94_1のコピー.gif
Deleted:	50_3のコピー2.gif
Deleted:	66_1のコピー.gif
Deleted:	95_1のコピー.jpg
Deleted:	58_3のコピー.gif
Deleted:	63_1のコピー.gif
Deleted:	32_1のコピー.jpg
Deleted:	55_3のコピー.gif
Deleted:	62_3のコピー.gif
Deleted:	49_3のコピー.gif
Deleted:	9_1のコピー2.gif
Deleted:	47_3のコピー.gif
Deleted:	96_1のコピー.jpg
Deleted:	71_1のコピー.gif
Deleted:	52_3のコピー2.gif
Deleted:	64_1のコピー2.gif
Deleted:	61_3のコピー.gif
Deleted:	56_3のコピー.gif
Deleted:	60_3のコピー2.gif
Deleted:	31_1のコピー.jpg
Deleted:	57_3のコピー2.gif
Deleted:	98_1のコピー2.jpg
Deleted:	34_1のコピー.jpg
Deleted:	68_1のコピー.gif
Deleted:	53_3のコピー.gif
Deleted:	42_3のコピー.gif
Deleted:	74_1のコピー2.gif
Deleted:	30_1のコピー.gif
Deleted:	36_1のコピー2.gif
Deleted:	65_1のコピー.gif
Deleted:	100_1のコピー.jpg
Deleted:	37_1のコピー.gif
Deleted:	35_1のコピー2.gif
Deleted:	45_3のコピー.gif
Deleted:	99_1のコピー.jpg
Deleted:	87_1のコピー2.jpg
Deleted:	33_1のコピー.jpg
Deleted:	73_1のコピー.gif
Deleted:	1_7のコピー.jpg
Deleted:	48_3のコピー.gif
Deleted:	54_3のコピー2.gif
Deleted:	51_3のコピー.gif
Deleted:	67_1のコピー.gif
Deleted:	93_1のコピー2.gif
Deleted:	44_3のコピー2.gif
Deleted:	72_1のコピー2.gif
Deleted:	97_1のコピー2.jpg


50 deleted.
```
</div></details>

## 解説
### ハッシュの取り方
`java.security.MessageDigest`を利用しました。
これは特にライブラリ等を導入せず`Java`標準で使えます。

今回はテキトーに`SHA-256`を指定しましたが、「極限まで重複を回避したいぜ！」という場合は`SHA-512`を指定してあげればいいと思います。

- [MessageDigest \(Java Platform SE 8 \)](https://docs.oracle.com/javase/jp/8/docs/api/java/security/MessageDigest.html)
- [標準アルゴリズム名のドキュメント](https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/StandardNames.html#MessageDigest)

### 重複管理
恐らく`HashSet`を使うのが一番簡単かつコストも低いと思います。
また、`ByteArray`では`equals`周りに不安があるため、ここでは`List`に変換して取り扱っています。
【PHP】クラスとインスタンスについて

#クラスとインスタンスの関係性

クラスが**テンプレートの原本**でインスタンスが**テンプレートを利用して作成された**もの

##クラスとインスタンスの関係性の例（ポケモンのゲームで例える）
▼クラス
![ss_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640569/9840c813-1dab-7192-2e1b-c887ae752ce6.jpeg)

▼インスタンス
<img width="245" alt="スクリーンショット 2020-05-22 3.22.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640569/701890ce-694b-9595-fcf9-d603f910791c.png">

こんな感じで
一回一回手動でコードを入力しなくても良いようにテンプレートを作成してそこへ数値を入れることができるようになっています。


##コードで書くとこんな感じ
```
<?php
//こうげき,ぼうぎょ,すばやさ,とくしゅが空欄のポケモンのステータス原本
class Pokemon{
public $attack;
public $defense;
public $speed;
public $Special;
}

//こうげき,ぼうぎょ,すばやさ,とくしゅが空欄のポケモンが生成
$myu = new Pokemon();
//こうげき,ぼうぎょ,すばやさ,とくしゅに[16]の値を飛ばす
$myu -> attack = 16;
$myu -> defense = 16;
$myu -> speed = 16;
$myu -> special = 16;
//こうげき,ぼうぎょ,すばやさ,とくしゅに[16]を表示
echo 　"こうげき" $myu -> attack.'<br>';
echo 　"ぼうぎょ" $myu -> defense.'<br>';
echo 　"すばやさ" $myu -> speed.'<br>';
echo 　"とくしゅ" $myu -> special.'<br>';

?>
```

###解説
■記述ルール
class＋クラス名{クラスの中身(プロパティや関数など)}…クラスの生成
public＋$プロパティ名…プロパティ
$変数名 = new クラス名()…クラス生成
インスタンス->プロパティ名…クラスのプロパティにアクセスする
LaravelでS3を操作する時はアクセスキー&シークレットキーではなくIAMロールを使うこと

LaravelからS3を使用する際はStorageファサードでS3を操作することが多いと思う。
その際に私がググった限りでは、ほとんどがアクセスキーとシークレットキーをソースコードにべた書きしているケースばかりだった。
しかし、こちらはアンチパターンなので、ec2で上記を行う場合はIAMロールを使用して、アクセスキー等はAWS側に隠ぺいしてもおう。

ec2にIAMロールを割り当てる手順は転がっているので、ここでは割愛。

# Laravel側

config/filesystems.php

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
        ],

.env

        AWS_ACCESS_KEY_ID=
        AWS_SECRET_ACCESS_KEY=
        AWS_DEFAULT_REGION=ap-northeast-1
        AWS_BUCKET=<<バケット名>>
-------------------------------------------
こう記載すると403エラーでS3にアクセスできなくなるので、必ず上記のように空にすること
.env

        AWS_ACCESS_KEY_ID=null
        AWS_SECRET_ACCESS_KEY=null

# 開発環境はec2じゃなくてローカルだよ～という人
その場合はキーを記載しましょう

.env

        AWS_ACCESS_KEY_ID=<<アクセスキー>>
        AWS_SECRET_ACCESS_KEY=<<シークレットキー>>
        AWS_DEFAULT_REGION=ap-northeast-1
        AWS_BUCKET=<<バケット名>>

#ちなみに①
IAMロール割り当てはインスタンス内部でアクセスキー等をちゃんと持っている。
Laravelはfilesystems.phpのkeyとsecretが空だったときは、こちらを読み込むようになっているので、接続できるということですね。

aws configure list

              Name                    Value             Type    Location
              ----                    -----             ----    --------
           profile                <not set>             None    None
        access_key     ****************XXXX         iam-role    
        secret_key     ****************XXXX         iam-role    
#ちなみに②
S3はaws-sdk-phpを使用かつ上記をすることでIAMロール割り当てで接続できるが、
他のAWSリソースの中には、aws-sdk-phpではダメでaws-sdk-php-laravelを使用しないと接続できないものがあるらしい。
C#でstaticが何か分からずに詰まってしまったので備忘録

初投稿です。Unity初心者の私がstaticが何者なのか分からなくなったので忘れないように記しておきます。
間違っていたら指摘していただけると嬉しいです

#Staticとは何ぞ？
Staticは<b>静的</b>と訳されています
クラスのメンバーを定義する時に下記のようにstaticを付けることで
`static 型名　フィールド名` (例: static float Sin)
その変数は静的変数・静的メソッドになります

#静的って何だよ
静的とは、静的メンバー(クラスやオブジェクトの持つ変数や関数)の宣言に使用します。
静的メンバーは、特定のオブジェクトではなく、型自体に属するメンバーです。
少なくとも
・静的である=>動かなく値は固定=>(constのような)定数
<b>という事ではないです。</b>自分は脳内でこのように勝手に変換してしまってハマっていました。


#じゃあ何をやっているの？

<b>staticはそのクラスが持つ変数やメソッドで有ることを示します。</b>
動かせないお弁当箱を置いておくようなもので中身を見たり中身を入れ替えたり出来ます。

いちいちインスタンスを取得してからアクセスしていましたが、
インスタンスを取得せずアクセスできるようになります。


#静的クラス
下記のようにstaticを付けることでstaticとして宣言され、staticメソッドのみが含まれます
`public static class Math`

``` C#
public static class Math //静的クラス
{
    public static readonly float PI = 3.14f;
    public static float CircumferenceLength(float diameter) 
    {
        return diameter * PI; //直径から円周を返す雑メソッド
    }

    //static(静的クラスでは)が無いのでエラー
    //静的クラスでインスタンスのメンバーを宣言することはできません。と言われる
    public /*static*/ int Abs(float val) 
    {
        return (int)Mathf.Abs(val); //絶対値にしてintで返すメソッド、なおエラーを吐く
    }
}
```

#静的フィールドとメソッド
この例では、新しい従業員の名前と ID を読み取り、従業員数のカウンターを 1 つインクリメントして、新しい従業員の情報と従業員数を表示します。

``` NAKAMA_Manager.cs

using UnityEngine;

public class NAKAMA_Manager : MonoBehaviour
{
    public void Start()
    {
        var employee1 = new Employee("一般人", 5);
        Employee.AddEmployee();
        Debug.Log($"NAME: {employee1.name}");
        Debug.Log($"HP: {employee1.hp}");
        Debug.Log($"Employee数: {Employee.employeeCounter}"); //Employeeクラスにアクセス

        var employee2 = new Employee("パチュリー", 30000);
        Employee.AddEmployee();
        Debug.Log($"NAME: {employee2.name}");
        Debug.Log($"HP: {employee2.hp}");
        Debug.Log($"Employee数: {Employee.employeeCounter}"); 
    }
}

public class Employee //従業員
{
    public string name; //インスタンスされる度(newされる度)に生成される変数)
    public int hp; //インスタンスされる度(newされる度)に生成される変数)

    public Employee(string name, int hp)
    {
        this.name = name;
        this.hp = hp;
    }

    public static int employeeCounter; //クラスが持つ変数
    public static int AddEmployee() 
    {
        employeeCounter++;
        return employeeCounter;
    }
}
```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308814/6e37b40d-6e23-8900-eefa-29d46ae44c5b.png)


#まとめ
・クラスのメンバーを定義する時にstaticを付けると静的宣言、静的メソッドになる
・静的メンバーは、特定のオブジェクトではなく、型自体に属する
・インスタンスを取得せずともアクセスできるようになる

##参考にしたサイト
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/static
【JavaScript】オブジェクトを格納した配列から特定のオブジェクトを取得する

# Array.prototype.find()を使用する

【構文】
`arr.find(callback(element[, index[, array]])[, thisArg])`

Array.prototype.find() - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/find

```js
// 下記の配列から特定のidを持つ要素（オブジェクト）を取り出す。
const members = [
  {id: 1, name: "tanaka", age: 30},
  {id: 2, name: "suzuki", age: 28},
  {id: 3, name: "sato", age: 24},
];

const getMemberById = (id) => {
  return members.find(member => member.id === id);
};

console.log(getMemberById(1)); // {id: 1, name: "tanaka", age: 30}
console.log(getMemberById(2)); // {id: 2, name: "suzuki", age: 28}
console.log(getMemberById(3)); // {id: 3, name: "sato", age: 24}
```

## 構文についての補足

構文内の`callback`関数には配列の要素一つ一つが引数に渡るので、マッチさせたい条件を記述します。
上記サンプルの場合、`callback`関数の引数には各オブジェクトが渡され、指定した`getMemberById(n)`で渡した数値と、各オブジェクトのidプロパティの値がマッチするまで、`callback`関数を繰り返し実行します。

## 戻り値

`Array.prototype.find()`の戻り値は最初に条件にマッチした要素なので、同じ条件の要素が２つ以上あった場合、以降は無視されます。条件に一致した要素がなければ、`undefined`を返します。

## まとめ

ReactやVue.jsでは、最初に述べたオブジェクトが格納された配列を扱う機会が多いと思いますので、
`Array.prototype.find()`の使用頻度も高いのではと思います。
Githubのユーザーネームを変更してみた

## 経緯

エンジニアになりたての頃、Githubに適当なユーザーネームで登録してしまって、後から変更したくなることってありますよね。（私だけ？）

## セッティングページからさっそく変更してみましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122790/306c4a13-3cfe-5971-54a3-86f399ede55e.png)
↑ここですね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122790/5c5816a1-217e-7d33-4b00-7e1e3182141a.png)
↑めっちゃ脅してくる笑

簡単に訳すと、

*以下を読まないと、予想もしない悪いことが起こるかもしれないよ！*

- *旧プロフィールページの（新プロフィールページへの）リダイレクトは設定しないよ*
- *Pagesサイトのリダイレクトは設定しないよ*
- *リポジトリのリダイレクトは設定するよ（webとgitアクセス）*
- *リネーム完了には数分かかるかもよ*

OKOK。understandしたので変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122790/14c9ab00-ed00-9885-0591-53a60fa4b395.png)
新しいユーザーネームを入力し、「Change my username」をクリック！
実際には数分もかからず、20秒くらいで完了しました。

変更してから気付いたのですが、ユーザーネーム変更に伴うサイドエフェクトの詳しい説明は↓のページに記載されていました。ちゃんと読んでから変更しましょう。
https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/changing-your-github-username

この中で気になる記載がありました。

> If the new owner of your old username creates a repository with the same name as your repository, that will override the redirect entry and your redirect will stop working. Because of this possibility, we recommend you update all existing remote repository URLs after changing your username. For more information, see "[Changing a remote's URL.](https://help.github.com/en/github/using-git/changing-a-remotes-url)"

訳すと、

*旧ユーザーネームの新しい所有者があなたのリポジトリと同じ名前のリポジトリを作成した場合、そのリポジトリはリダイレクトエントリを上書きしてしまい、リダイレクトは動作しなくなります。このため、ユーザーネームを変更した後は既存のリモートリポジトリのURLをすべて更新することをお勧めします。詳細は"[リモートのURLを変更する](https://help.github.com/en/github/using-git/changing-a-remotes-url)"を参照してください。*
<br>

ユーザネーム変更の際、リポジトリのリダイレクト設定は自動でしてくれるので、リモートリポジトリのURLを自分で更新する必要はないと思っていましたが、上記の記載を見ると更新したほうが良さそうですね。

リモートリポジトリのURL更新は以下のコマンドで変更できます。

```bash
git remote set-url origin <new url>
```

これで快適なGithubライフを送れますね。
TwitterじゃんけんBotでツイートが出来なくなるバグについて（ネタ）

こんにちは。すずともです。
前回、TwitterじゃんけんBotの作り方を説明しました。

[TwitterじゃんけんBot作ってみた：すずともBot①](https://qiita.com/SuzuTomo2001/items/41a71e6ca7b4999a895e)

今回は、このBotの盲点について書きたいと思います。

---
（2020年6月6日追記）
この既知の問題に関しては対処済みです(o^―^o)ﾆｺ

---
#バグの起こし方
Botのバグを起こすのは簡単です。
ただ、自分じゃできないので別の人(または別のアカウント)にやってもらってください。

その方法とは...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255360/a5fafb92-faa9-3ce5-8529-fcc744b0c437.png)

これだけ！

#あなたもツイ廃！
この@ツイートを受け取ると、一つ一つの「✊」に対して、リプライが送られます！
このツイートだと、✊が130個ぐらい？

そして、実はこのリプライ、TLに流れちゃうみたいです(o^―^o)ﾆｺ

リプライといえば、TLに流す方法、流さない方法などいろいろあるみたいですが、Botで作成したリプライはTLに流れます。
TLに流さない方法もあるかもしれないので、また調べておきます。


というわけで、一気に130ツイート。ツイ廃デビュー(^▽^)/


#ツイ廃デビューの後には
無事、ツイ廃デビューおめでとうございます🎊

そして、ツイ廃デビューの後には、また素晴らしいイベントが待ち構えているようです。

その名も...
**[「ツイート制限！」](https://help.twitter.com/ja/rules-and-policies/twitter-limits)**

はい。リンク先を見ればわかりますね。

Twitterでは一日のツイートを2400件と制限されているようです。
しかも、30分単位のリミットに分けられているそうなので、計算すると、

50ツイート／30分

です！

さぁて、この制限はいつ解除されるのでしょうかねぇ（ツイート制限中にて記事を書いてます）


#リツイート
さて、先ほどの害悪ツイート、リツイートすると、それにも反応して"くれます"。
なので、リツイートされるたびに130リプ...

試しに自分でリツイートしても反応するらしく、僕の場合は、害悪ツイート(ツイートした人は悪くないですごめんなさい)を、それを別の人はリツイートして、そこまでは制限大丈夫でした。

追い打ちをかけたのが、自分によるリツイート。これで制限かかりましたね笑


結局制限ってどうするとかかるのか分かんないや…

#さいごに
このBotを使えば、自分をツイ廃に、さらにツイート制限まで行うことができます！

僕に恨みでもある方はこの害悪ツイートを定期的に送ってくれれば僕がツイートできなくなりますので、試しにやってみてください(o^―^o)ﾆｺ

ただ一つ、害悪ツイートされると僕のフォロワーの方々のTLを埋めることになるのでその辺りは…ね？

#サービスの再起動
すずともはまったく懲りてないのでサービスの再起動をかける予定です。
(予定というのは、今起動してもAPI認証の時点で弾かれる可能性があるからです)

というのも、ツイート制限にかかった後もBotはツイートをしようとするので、エラーレスポンスが帰ってきてそこでプログラムが終わってしまうようです。
本来ならばその辺りにも対応したプログラムを書かないといけないのですが、そのあたりはめんどくさかったのでまた今度。

```
$ sudo systemctl restart jankenTwitter
```

として、ほとぼりが冷めたら再起動してあげましょう！
enumerate関数を利用してリストのindexを取得してみた

# indexが振られていない時に活用できるenumerate関数
enumerate関数を効果的に利用できる場面はどのようなときかを考えていたところ、ちょうど競技プログラミングで以下のような課題が出題されたので、まさに使いどころだと思った。

# 問題
学生のテストと欠席回数のデータが学籍番号順に与えられたとき、成績が合格点以上になっている学生の学籍番号を順に出力するプログラムを作成してください。学籍番号は 1 から順に与えられます。
学生の成績はテストの点数から 欠席回数 × 5 点 を引いた点数とする

# 入力値

> N M
a_1 b_1
a_2 b_2
a_3 b_3
…

N：学生の人数
M：合格最低点
a_n：テストの得点
b_n：欠席回数

# enumerate関数を利用してindexを取得する
もしかしたら他にも良い方法があるかもしれないが、enumerate関数を活用して回答を出力してみる。
enumerate関数を使うと、forループの中でリストの要素とインデックスが同時に取得できる。

```python
# man:学生の人数、score:最低合格点
# まずはmapによりそれぞれの数値を入力値から取得する。
man , score = map(int , input().split())

# 空のリストを準備
li = []

# リストへmapにて取得した要素(得点と欠席回数の要素を持つペア)をループで追加する
for i in range(man):
    li.append(list(map(int , input().split())))

# enumerate関数を用いて、取得したリストのindex(学籍番号)と同時にリストの要素を取得
# 要素の中の数値を計算することで、分岐によりindexを出力する
for num , scr in enumerate(li):
    if (scr[0] - scr[1]*5) >= score:
        print(num + 1)
    elif ((scr[0] - scr[1]*5) < score) and score == 0:
        print(num + 1)
```
Alexa(Amazon Echo)をコマンドラインから自由に喋らせる方法

コマンドラインを使うと Alexa (Amazon Echo) を自由に喋らせることができます。
本記事では `alexa_remote_control` を使用します。

ちなみに、コマンドラインを使わない方法は以下のようなものがあります。

1. **定型アクション** → トリガーが「時刻、指定フレーズ、スマートホーム、アラーム停止時」しかなく限定的
2. **Node-red** → https://dream-soft.mydns.jp/blog/developper/smarthome/2019/10/362/
3. **自作スキル** → スキルを起動していない状態でも通知は送れるが(黄LED)、ユーザーが「通知を読んで」と言うまで読み上げないので却下

`cron` を使うと時報などもできます：
[Alexaの時報をスキル・定型アクションなしで実現する方法 - Qiita](https://qiita.com/shge/items/eb0f1c01a8d15490a986)

# ダウンロード
https://github.com/thorsten-gehrig/alexa-remote-control

`alexa_remote_control.sh` を適当な場所に保存して、`chmod` で実行権限を与えます。
`brew install jq` (Mac) などで `jq` をインストールします。

Plain バージョン (`alexa_remote_control_plain.sh`) は `jq` が必要ありません。

> There's also a "plain" version, which lacks some functionality (-z, -i, -p, -P, -S and no radio station names and no routines) but doesn't require 'jq' for JSON processing.

2段階認証を使う場合には、`brew install oath-toolkit` (Mac) で oathtool をインストールしておきます。

# セットアップ

`SET_EMAIL`: Amazon メールアドレス
`SET_PASSWORD`: Amazon パスワード
`SET_MFA_SECRET`: Amazon の2段階認証設定ページ → アプリを追加 → QRコードをスキャンできない場合のコード
`SET_LANGUAGE`: ja-JP または en-US など
`SET_TTS_LOCALE`: ja-JP または en-US など
`SET_AMAZON='amazon.co.jp'`
`SET_ALEXA='alexa.amazon.co.jp'`

`SET_OATHTOOL=`: `oathtool`コマンドの場所

※ Windows からログインがありましたというメールが来ることがあります。気になる方は `SET_BROWSER` で UA を変更してください。

:warning: Mac の場合は `gsed`, `ggrep` が必要なことがあります。必要に応じてコードを書き換えてください。
:warning: パスワードなどをコードにべた書きは良くないので気をつけましょう。

# 実行

```sh
./alexa_remote_control.sh -e "speak:こんにちは!"
```
「こんにちは！」と再生されれば成功です！

#### エラーが表示される場合

- ブラウザで `https://alexa.amazon.co.jp` からは音楽を再生できますか？
- `gsed`, `ggrep` は導入していますか？

# その他コマンド

#### ヘルプ

```sh
./alexa_remote_control.sh -h
```

#### ベルを再生

```sh
./alexa_remote_control.sh -e "sound:bell_02"
```

#### 指定の呼びかけに対する反応

```sh
./alexa_remote_control.sh -e "textcommand:今日は何の日"
```

#### 音量を％で指定（0-100）

```sh
./alexa_remote_control.sh -e "vol:15"
```

#### 英語で発話

```sh
./alexa_remote_control.sh -e speak:"<lang xml:lang='en-US'><voice name='Joanna'>Hello</voice></lang>"
```
男声：Matthew

#### ささやき声

```sh
./alexa_remote_control.sh -e speak:"<amazon:effect name='whispered'>こんにちは</amazon:effect>"
```

#### 会話風

```sh
./alexa_remote_control.sh -e speak:"<amazon:domain name='conversational'>こんにちは</amazon:domain>"
```

#### ニュース風

```sh
./alexa_remote_control.sh -e speak:"<amazon:domain name='news'>こんにちは</amazon:domain>"
```

#### 強調

```sh
./alexa_remote_control.sh -e speak:"<emphasis level='moderate'>こんにちは</emphasis>"
```
`strong`/`moderate`/`reduced`

#### 感情のこもった定型文

```sh
./alexa_remote_control.sh -e speak:"<say-as interpret-as='interjection'>うふふ</say-as>"
```

https://developer.amazon.com/ja-JP/docs/alexa/custom-skills/speechcon-reference-interjections-japanese.html#supported-speechcons

#### 声の音量、高さ、速さ

```sh
./alexa_remote_control.sh -e speak:"<prosody pitch='high'>高い声です</prosody>"
```
`rate`: `x-slow、slow、medium、fast、x-fast`
`pitch`: `x-low、low、medium、high、x-high`
`volume`: `silent、x-soft、soft、medium、loud、x-loud`
ベイズの定理について語りましょうよ（メモ兼）

ベイズの定理について語っていこう

条件付確率である
条件も確率で表されるということを覚える。
P(Y|x)　　＝　P(Y|X)P /P(Y)
Xが起こった条件下で起こる確率　(X、Yの順番は関係ない)


P(X,Y) / P(x)　－＞　P(X|Y)＝P(X|Y)P /P(Y) 
　　　　　　　　　X とYを交換
　　　　　　　　ー＞　P(X|Y) =P(Y|X)P(X) /P(Y)－ベイズの定理
　　　　　　　　　P(X|Y) =P(Y|X)P(X)を代入


Xが原因でYを結果と考えると、
P(X|Y) =P(Y|X)P(X) /P(Y)

結果の条件化で原因が起こる確率は（＝P(X|Y) ）、
結果の確立分の原因の確率×原因条件下の結果の確率で表される(P(Y|X)P(X) /P(Y))。

人を脳死させる日本語。

わかりやすくする努力↓
X＝彼女あり確率、　Y=幸せである確率
幸せであるの条件化で彼女ありの起こる確率は（＝P(X|Y) ）、
彼女ある確立分の幸せである確率×彼女あり条件下の幸せである確率で表される(P(Y|X)P(X) /P(Y))。

文系の限界をここに見たよ、ベン図とか数式てすばらしい。


罹患率で考える。

陰性・陽性　　と　罹患　非罹患

罹患率　0.01％
　　　　陽性　陰性
罹患　　98％　2％
非罹患　20％　80％

陽性だと診断された場合、本当にり患している確率は？

P(罹患｜陽性)　＝　P(陽性｜罹患)　x　P(罹患)　/ P(陽性)

罹患条件下で陽性の確率　＝0.98　
罹患率　＝0.0001
陽性である確率　＝　0.0001 x 0.98 + 0.9999 x 0.20
               = 0.200078

P(罹患｜陽性)　 = 0.98 x 0.0001 / 0.200078
               = 0.00048981

0.05%　陽性だと診断されても罹患してる確率低すぎ　
ー＞再検査しましょ。

事前確率(0.01%)　＋＝情報　＝＞　事後確率(0.05%)

確率を新たな情報によって更新するのがベイズの定理である。
Rails 6のdevelopment環境でhttpsを使う

# はじめに
この記事はRails6をしばらく使用し、ハマった部分、忘れたくないことを将来の自分のためにメモとして残し、公開することで同じようなことをRails6で実現しようとしている方のお役に立てたら、うれしいなと思い書いています。

この記事を読んで「助かったぜ！」、「それは間違ってるぜ！」や「もっとこうした方がいいぜ！」
がありましたら、お知らせ頂ければと思います。

# 実現したこと
- Rails 6.0.3.1のdevelopment環境で`webpack-dev-server`と`puma`の起動を`foreman`で同時に起動し`https`を使う

# なんでdevelopment環境でhttpsを使う必要があるの？
development環境で`rails s`を実行してRailsアプリ(Server)を起動するとデフォルトでは`http`で起動することになります。
ところが、どこかのサービスが提供しているAPIを叩く際、**エンドポイントURLをhttpsで指定しなければならない場合がほとんど**なのでdevelopmentでAPIを叩いて連携し、目的の情報を正しく取得、加工、表示、できているのかを確認できません。

# なんでwebpack-dev-serverを使うの？
Rails6ではデフォルトでJavaScriptの管理がWebpacker環境となりますので`rails s`だけだと、ページが表示されるまでに時間がかかり不便なので`webpack-dev-server`を利用することでファイルが更新されたら勝手にコンパイルしてくれるようにし、開発効率を上げるためです。

# なんでforemanを使うの？
Railsアプリを起動する度に`rails s`と`webpack-dev-server`のコマンドを打つ必要があり、これまた面倒です。
そこで登場するのが`foreman`です。

# 要するに
- ムダなことに時間をとられたくない
- 人生(命)を削られたくない
- コンピュータを自由自在に操るのが生き甲斐なのに、Rails6のデフォルトだとコンピュータに操られてるみたいで屈辱的なので絶対に許せない

ってことです

# SSL証明書どうするの問題の解決
**Railsの開発環境でhttpsを使う**
https://qiita.com/itkrt2y/items/2837a45061b9a3b711b7
という記事を参考にさせて頂きました。@itkrt2y さん、ありがとうございます！

ただし、Rails6では1箇所だけエラーを引き起こす箇所がありました。
エラー内容
`NameError: uninitialized constant #<Class:#<Puma::DSL:0x00007f9070276ea8>>::Rails`

該当箇所(1行目のところが原因です)

```config/puma.rb
if Rails.env.development?
```

なので下記のように修正することでエラーを回避しました。

```config/puma.rb
if ENV['RAILS_ENV']=='development'
```

これで`rails s`を実行します。
すると、`config/certs/`配下に`localhost.key`と`localhost.cert`が生成されます。

# webpack-dev-serverのhttpsを有効化
developmentのdev_serverのhttpsをtrueに変更。下記コードの一番最後の行のところです。

```config/webpacker.yml
evelopment:
  <<: *default
  compile: true

  # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
  check_yarn_integrity: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: true
```

# foremanを使ってラクになる
**foreman で アプリケーションを動かす。**
https://qiita.com/7kaji/items/6a59977d2ad85604e7fd
という記事を参考にさせて頂きました。 @7kajis さん、ありがとうございます！

#### インストール

```
$ gem install foreman
```
#### 設定
下記の設定ではportを443にしていますが、必要に応じて8443などに変更してください。

```ruby:Procfile
rails: rails s -b 'ssl://0.0.0.0:443?key=config/certs/localhost.key&cert=config/certs/localhost.cert'
webpack: bin/webpack-dev-server --https
```

# 起動!
下記のコマンドを実行し、Railsアプリを起動します。 https://localhost/ にアクセスし、ページが表示されれば成功です。

```
foreman start
```

はぁ〜ラクチン。幸せだなぁ。
Windows10でnpm install -g が権限不足で失敗した際の対策

## 初めに
firebase cliをWindowsでインストールしようとした際、少し嵌ったのでメモとして残します。公式通りだと私の環境では上手くいかなかったので少しアレンジしています。
お利口なやり方ではないかも知れませんのでご指摘歓迎です。

公式を参考にしました。
https://firebase.google.com/docs/cli?hl=ja#npm
https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally

## 手順
コマンドプロンプトでbashが扱える前提です。

### 1.npm install -gの新しいインストール先を作成

```
mkdir C:\Users\[ユーザ名]\.npm-global
```

### 2.作成したディレクトリをnpmが参照するように設定

```
npm config set prefix 'C:\Users\[ユーザ名]\.npm-global'
```

### 3.`C:\Users\[ユーザ名]\.profile`でファイルを作成し、以下を記述

```bash:.profile
export PATH=~/.npm-global/bin:$PATH
```

### 4.システムに新しい変数を読み込ませる

4の手順まで実施し、npmのグローバルインストールで権限不足で怒られなくなりました。

```
bash C:\Users\[ユーザ名]\.profile
```

### 5.環境変数に`.npm-global`のパスを追加
アレンジ部分です。公式はこの工程が無くても`firebaseコマンド`が実行できると書いてあったのですが、どうしても`firebaseコマンド`のパスが通らず、試行錯誤した結果、環境変数に追加するパワープレーで解決できました。

```
C:\Users\[ユーザ名]\.npm-global
```

### 6.npm installでfirebase cliをインストール

```
npm install -g firebase-tools
```

これで晴れて`firebaseコマンド`が実行できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285286/de460d03-a89c-33f4-5f0c-4c226e374257.png)

## 最後に
環境変数に追加したのは苦肉の策というか、他に正しい方法があったのだろうなともやもやします。。
[Flutter]BOTTOM OVERFLOWED BY ** PIXELSへの対処法

# 問題
Flutterでキーボードを出したときに、**BOTTOM OVERFLOWED BY N PIXELS** と警告が出ることがある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135663/18b7a2d6-3f74-2fda-1687-f2591180097e.png)

# 解決策
Scaffoldに **resizeToAvoidBottomPadding:false** を記載する。

```dart

Scaffold(
 resizeToAvoidBottomPadding: false,
 body: ...)

```
resizeToAvoidBottomPaddingはデフォルトはtrueになっており、キーボードを出したときに画面の要素を隠さないようにリサイズしてくれるのだが、隠しきれなかったときにこのような警告が出る。
falseにすることで、要素は固定したままキーボードを重ねて表示する。

# 参考
https://stackoverflow.com/questions/51972371/bottom-overflow-by-30px
https://api.flutter.dev/flutter/material/Scaffold/resizeToAvoidBottomInset.html
elsarticle.cls利用時のBounding Box問題

Texで論文を書く際に、以下のようなelsarticle.clsというクラスを使用する機会がありました。([Elsevier](https://www.elsevier.com/__data/assets/pdf_file/0008/56843/elsdoc-1.pdf)が提供する論文投稿に適したフォーマット)

```tex
\documentclass[preprint,5p,fleqn,sort&compress,number,times,twocolumn]{elsarticle}
```
この時に発生していた、pdfなどのBounding Boxが自動読み込みされない問題について触れています。
使用していたのはTexLive2019で、platex2pdfでコンパイルしていました。
#発生していた問題
問題としてはコンパイル時に、

```tex
LaTeX Error: Cannot determine size of graphic in ../figure/Figure1.pdf (no Bo
undingBox).
```
のようなエラーが出るという単純なものです。
このエラーログ自体は、挿入したいファイルのbounding boxが分からないというエラーです。解決策としては、確かTexLive2015以降のversionだと、プリアンブルで

```tex
\usepackage{graphicx}[dvipdfmx]
```
というようにパッケージを導入することで、自動でbounding boxがファイルから読み込まれて上手くいきます。従って、普段Texで文章を書くときは、おまじないのように上記のパッケージを書いています。
しかし、どうもelsarticleのクラスは上述のパッケージと衝突し、この方法では上手くコンパイルできないようです。
#解決策
##×良くない方
とりあえず、調べてもいまいち良い解決策が見つからなかったので手動でBounding Boxを書いていました。
ちなみに、Bounding Boxは単なるピクセルサイズじゃないんで、extractbbのコマンドを使って調べてました。(面倒くさいんでお勧めしないです)

##◎良い方
結論だけいうと、コードの先頭に"\PassOptionsToPackage{dvipdfmx}{graphicx}"を一文追加するだけで治りました。

```tex
%修正前
\documentclass[preprint,5p,fleqn,sort&compress,number,times,twocolumn]{elsarticle}
\usepackage{graphicx}[dvipdfmx]
```

```tex
%修正後
\PassOptionsToPackage{dvipdfmx}{graphicx}
\documentclass[preprint,5p,fleqn,sort&compress,number,times,twocolumn]{elsarticle}
\usepackage{graphicx}[dvipdfmx]
```

#最後に
正直"\PassOptionsToPackage"が何をしているのかが良く分からないんで勉強中ですが、packegeのoption関係を調べれば分かるんですかね？
ご存知の方がいれば、治る理由が知りたいですね。
【Python 3】14行で素因数分解

意外とPythonの標準ライブラリに素因数分解ってないんですね。
Counterを使ってシンプルに書いてみました。上から14行で。

```prime_factorization.py
from math import sqrt
from collections import Counter

def prime_factorization(n):
    counter = Counter()
    for i in range(2, int(sqrt(n)) + 1):
        while n % i == 0:
            n //= i
            counter[i] += 1

    if n != 1:
        counter[n] += 1

    return list(counter.items())

def prime_factors(n):
    return set(map(lambda x: x[0], prime_factorization(n)))

if __name__ == '__main__':
    # 2020 = 2^2 * 5^1 * 101^1
    print(prime_factorization(2020)) # => [(2, 2), (5, 1), (101, 1)]
    print(prime_factors(2020)) # => {2, 101, 5}
    # 1の場合はからのリストを返す
    print(prime_factorization(1)) # => []

```

# 参考
[Pythonで高速素因数分解〜競プロ用〜](https://qiita.com/snow67675476/items/e87ddb9285e27ea555f8)
【AWS】W-A(AWS Well-Architected Framework)とは？

# はじめに
現在、AWS-SAAを学習しております。
今回は、W-A(AWS Well-Architected Framework)についての内容をアウトプットしていきたいと思います。
(ざっくりとしたメモレベルになります。)

# W-A(AWS Well-Architected Framework)とは？

クラウド最適化への課題と不安に対する解決方法として整理されたクラウド活用のベストプラクティス集になります。

**いわゆる、クラウドに関するノウハウが集まったフレームワーク集です。**

具体的には

- サービス開始から10年以上の経験によって作られたノウハウがベースになっている
- 常に進化し続けている
- クラウド活用の設計原則、質問と回答形式(チェックリスト)をまとめたベストプラクティス集

になります。


# フレームワーク(5つの柱)

- 運用上の優秀性
- セキュリティ
- 信頼性
- パフォーマンス効率
- コスト最適化

## 運用上の優秀性

**「いかに安全に効率よく運用していくか？」**というフレームワークになります。

- ビジネス価値を提供するためのシステムの実行とモニタリング
- 継続的に運用プロセスと手順を改善すること

話題としては、「日常業務をうまく管理するための定義」「イベントへの対応」等です。


## セキュリティ

**AWS上に構築されたシステムを守ることにフォーカスしているフレームワークになります。**

話題としては、「データの機密性」や「権限管理」等になります。


## 信頼性

**「障害の防止」「障害からの迅速な復旧」**にフォーカスしているフレームワーク。

例えば、

- インフラストラクチャまたはサービスの中断からの復旧のための能力
- 需要に合わせて動的にコンピューティングリソースを取得する能力

などです。


## パフォーマンス効率

**コンピューティングリソースの効率的な使用**にフォーカスしているフレームワーク。

例えば、

- ワークロードへの需要に応じた適切なリソースタイプの選択
- パフォーマンスモニタリング

等が話題としてあります。

## コスト最適化

**不要なコストの回避**に焦点を当てているフレームワーク。

例えば、

- 最適なリソースタイプが選択されているか？
- 費用が発生する箇所を把握できているか？

等が話題としてあります。

# まとめ

- W-A(AWS Well-Architected Framework) 
クラウド活用のためのベストプラクティス集

- 運用上の優秀
いかに継続的に運用プロセスと手順を改善できるのか？に焦点を当てたフレームワーク  

- セキュリティ
システムを保護することに焦点を当てたフレームワーク

- 信頼性
「障害防止」「障害からの迅速な復旧」に焦点を当てたフレームワーク

- パフォーマンス効率
効率的にコンピューティングリソースを利用することに焦点を当てたフレームワーク

- コスト最適化
不要なコストの管理に焦点を当てたフレームワーク

# 参考

**書籍**
[この１冊で合格！　AWS認定ソリューションアーキテクト - アソシエイト テキスト&問題集](https://www.amazon.co.jp/gp/product/B07VFFX6V1/ref=ppx_yo_dt_b_d_asin_title_o00?ie=UTF8&psc=1)

**AWS公式**
[AWS Well-Architected](https://aws.amazon.com/jp/architecture/well-architected/)
【Golang】カスタムエラー

#【Golang】カスタムエラー
Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。 基礎〜応用まで。

```
//カスタムエラー
//Stringer同様errorもある。
//interface3の使い方

/*Errorメソッドを持つ型をまとめている
type error interface {
    Error() string
}
*/

package main 

import (
	"fmt"
)

//4
//カスタムエラーの名前
type UserNotFound struct {
	Username string
}


//5
//特殊メソッド
//エラーの出力を変える
//ポインタ型で指定する。
func (e *UserNotFound) Error() string {
	//これが出力される
	return fmt.Sprintf("User not found: %v.\n", e.Username)
}

//2
//エラーを返す関数
//返り値をエラー型にする
func MyFunc() error {
	ok := false
	if !ok {
		//3
		//エラーを返す
		//エラーを定義する時は、&をつける
		//&はなくても実行はできるが、ルールとしてつける。
		//エラーハンドリングでバグの原因になる
		//アドレスで比較する
		return &UserNotFound{Username: "mike"}
	}
	return nil
}

func main() {
	//&UserNotFound{Username: "mike"}で&をつける理由
	e1 := &UserNotFound{"mike"}
	e2 := &UserNotFound{"mike"}
	fmt.Println(e1 == e2)
	//>>false
	//&がなければTrueになる
	//e1とe2は違うという事。異なるエラー。アドレスで比較しないと同じエラーになってしまう。


	//1
	//もしエラーが帰ってきたらエラーを出力
	//エラーじゃなかったらnilを返す
	err := MyFunc()
	if err != nil {
		fmt.Println(err)
	}
}
```
最小 PWA を探ってみた

# はじめに

PWA について、Android 版 Chrome が「インストールしますか？」と尋ねてくる最小の内容って何なのか、試してみました。
（オフライン動作は目指していません。）


# 結論

|項目|内容|
|---|---|
|icon|１つでＯＫ|
|Service Worker|fetch イベントのリスナーのみでＯＫ|
|fetch リスナー|空でＯＫ|


# サンプル

```manifest.json
{
  "name": "minimum",
  "display": "standalone",
  "start_url": "https://foo.bar/index.html",
  "icons": [
    {
      "type": "image/png",
      "src": "assets/images/icon-512.png",
      "sizes": "512x512"
    }
  ]
}
```

`manifest.json` の項目は Chrome のバージョンによって増減があるかと思います。上記は 81.0.4044.117 で確認しました。
アイコンは大は小を兼ねる発想で 512x512 にしておきました。


```index.html
<html>
  <head>
    <title>minimum</title>
    <link rel='manifest' href='manifest.json' />
    <link rel='icon'     href='assets/images/icon-512.png' />
  </head>
  <body>
    <center>
      <img src='assets/images/icon-512.png' />
    </center>

    <script>
      if ( 'serviceWorker' in navigator ) {
        navigator.serviceWorker.register('service-worker.js')
          .then(function() {
            console.log('ServiceWorker was registered.');
          });
      }
    </script>
  </body>
</html>
```

favicon は必須じゃないですし body も真っ白でもいいと思いますが、せっかくモノがあるので書いておきました。
逆に `register()` に `catch()` 書いたほうがいいですね。


```service-worker.js
self.addEventListener('fetch', function(event) {});
```

install イベントは予めキャッシュにファイルを入れておく機会として利用できますが、利用しなくても別に問題ないです。
activate イベントは古い世代のキャッシュを削除する機会として利用できますが、利用しなくても別に問題ないです。

いずれも fetch が正しく機能するために必要なら利用すればいい、という感じでしょうか。


# おわりに

行儀が良いとは言えないですが、「ホームにアイコン設置」が目的ならば、最小の内容でも十分かと思います。
常用漢字やJIS漢字って、いくつあるの？

# 漢字っていくつあるの？
　ということでWikipediaで調べてみた！

# 常用漢字
　常用漢字は、小学校、中学校で習う漢字です。現在は2136字です。

## 常用漢字の移り変わり
年度|漢字数|棒グラフ|名称
---|---|---|---
1923年|1962字|███████████████⎸|常用漢字表
1931年|1858字|██████████████▎|常用漢字表
1942年|2528字|███████████████████▍|標準漢字表※
1946年|1850字|██████████████▏|当用漢字
1981年|1945字|██████████████▉|常用漢字表
2010年|2136字|████████████████▍|改定常用漢字表

※常用漢字1134字、準常用漢字1320字、特別漢字74字

# JIS漢字
 JISで定義でしている漢字コード

## JIS漢字数
区分け|JIS<br>その1|JIS<br>その２|漢字数|棒グラフ
---|---|---|---|---
JIS第１水準|JIS X 0208|JIS X 0213|2965字|█████████████████▍
JIS第２水準|JIS X 0208|JIS X 0213|3390字|███████████████████▉
JIS第３水準||JIS X 0213|1259字|███████▍
JIS第４水準||JIS X 0213|2436字|██████████████▎

### 注意事項
- 「JIS X 0213」は「JIS X 0208」を含んでます。「JIS X 0213」を見ましょう。
- 常用漢字 ≠ JIS第1水準。
- 常用漢字は、JIS第1水準～JIS第3水準に分散している
【kotlin】buttonでテキスト表示

###Kotlinのコード
```
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

        var helloText : TextView = findViewById (R.id.textView1)
        var helloButton : Button = findViewById(R.id.button1)
        helloButton.setOnClickListener {
            helloText.text = "Hello"
        }
    }
}
```
###シミュレーター
ボタンを押すと下記のようにHelloが表示
<img width="301" alt="スクリーンショット 2020-05-21 23.32.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627010/19876e4e-5008-1ad5-c09b-522599dec5b8.png">
kotlinの勉強をするにあたり、簡単なアプリを一つ作ろうと思い作ってみました。



【雑談】
前の投稿からもう一週間程が経ってしまいました。
swiftで作ったアプリを一つリリースさせたくその作業で投稿が空いてしまいました。
この前Apple様から許可がおり無事リリースすることができました。
ApppleStoreで見た時に一人で感動してました。笑
今度紹介できたらなと思います。
【Unity】ドコモAIエージェントAPI SpeakSDKをAudioSource経由で音声出力する

# はじめに

こちらの記事を参考にリップシンク（口パク）をしようとしていたところ、SpeakSDKの仕様変更にぶつかりました。この記事では最新の`speak-unity-sdk v1.14.5`でリップシンクを行う方法を紹介したいと思います。
[ドコモAIエージェントAPIを使ってキャラクターと会話する](https://qiita.com/broken55/items/5cdda8366aa2b6fa6fc0)


# 環境

- Windows 10 Home
- Untiy 2019.3.13f1（推奨バージョンは2019.3.2f1）
- speak-unity-sdk v1.14.5

# 状況

初めの記事のバージョンではUnityの`AudioSource`上から出力されていた音声が、DLLなどネイティブプラグイン側から直接出力される仕様になっていました。こうなるとUnity側には音が流れない状態になるため`AudioListener`で音を拾うことができないという状況が発生していました。

しかし、`v1.14.5`で下記の変更が入ったため、その方法を紹介します。

> AudioSouceで合成音声が利用できるように機能追加

引用元：https://github.com/docomoDeveloperSupport/speak-unity-sdk/releases/tag/v1.14.5

# SpeakSDKをAudioSource経由で音声出力する方法

サンプルのソースコードを元に紹介します。Editor上での動かし方はこちらの記事を参照してください。
[【Unity】ドコモAIエージェントAPI SpeakSDKのサンプルをEditor上で実行する - Qiita](https://qiita.com/nkjzm/items/bdff6d7986144197439e)

AudioSource経由で音声出力する方法は[公式ユーザーガイドPDF](https://github.com/docomoDeveloperSupport/speak-unity-sdk/blob/master/speak_unity_sdk_users_guide.pdf)の27ページ目辺りの6.3章で説明されています。具体的には初期化のタイミングで`SetAudioSource()`を呼び出せばいいそうです。

サンプルの[SpeakSDKManager.cs](https://github.com/docomoDeveloperSupport/speak-unity-sample/blob/master/sample_app/SpeakSampleApp/Assets/Scripts/SpeakSDKManager.cs)の場合、`InitializeSpeakSDK()`に下記の2行を追加してください。

```.cs
    private void InitializeSpeakSDK()
    {
        Speak.Instance().SetURL("wss://spf-v2.sebastien.ai/talk");
        Speak.Instance().SetDeviceToken("c0ed13a0-0069-4c81-8dcb-397cdf60c9fa");

        // 以下の2行を追加
        var audioSource = GetComponent<AudioSource>();
        Speak.Instance().SetAudioSource(audioSource);

        // Callback.
        Speak.Instance().SetOnTextOut(OnTextOut);
        Speak.Instance().SetOnMetaOut(OnMetaOut);
    }
```

また、`SpeakSDKManager`がアタッチされているオブジェクトに`AudioSource`コンポーネントを追加しておいてください。

これで、最初の記事の方法でリップシンクができるようになりました。

# おまけ：SDKをアップデートする際の注意点

Unityでは一度でもスクリプトからNative Pluginをロードすると、Unityを再起動するまでUnloadされない仕様になっています。そのため、ロード済みの状態で.unitypackageを適用しようとすると、dllの上書きがされません。アップデート前にプロジェクトを再起動することで解決します。

参考：[【Unity】Macで使えるNative Pluginを作る（OpenCV編） - おもちゃラボ](http://nn-hokuson.hatenablog.com/entry/2017/05/12/201453#%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%AE%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AB%E3%81%AF%E6%B3%A8%E6%84%8F%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%A7%E3%81%99)

また、dllをアップデートするとEditorで使えるようにする設定もリセットされるのでご注意ください。
[【Unity】ドコモAIエージェントAPI SpeakSDKのサンプルをEditor上で実行する - Qiita](https://qiita.com/nkjzm/items/bdff6d7986144197439e)

# 謝辞

この記事を作成するにあたり、[AIセバスちゃんさん (@SebasAi)](https://twitter.com/SebasAi) にアドバイスをいただきました。ありがとうございました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">XR Kaigiの講演のスライドです！！<br>「音声対話エンジンを使った中の人がいないバーチャルキャラクターとその先の未来」<a href="https://twitter.com/hashtag/XRKaigi?src=hash&amp;ref_src=twsrc%5Etfw">#XRKaigi</a><a href="https://t.co/ilYDlldAvA">https://t.co/ilYDlldAvA</a></p>&mdash; AIセバスちゃん (@SebasAi) <a href="https://twitter.com/SebasAi/status/1202870099981422592?ref_src=twsrc%5Etfw">December 6, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に

宣伝ですが、 月額制のメンターサービスで初心者向けの開発サポートをしています。分からないことがあれば是非こちらで質問してください！　
https://menta.work/plan/1115