OmniAICreator/Qiita-1.07M huggingface dataset:
Power Query で is not null の条件を使う

#M言語はなかなか使わないので細かいところの情報が少ない
ということ、多々あると思います。
ググってもあまり情報が出てこないのでQiitaします。
##Power Query を使っているとカスタム列を追加することも多々あります
条件列で満足できなくなってくるとカスタム列を使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573860/aabfdaf0-5f0c-5900-7f7c-635b5b132252.png)
目的が達成されるのであれば、どっちを使っても良いのですが、カスタム列のほうが何となく色々できそうだと使ってしまいます。そしてハマります。（難しいことを使用とするなと言うMSからのメッセージだと思っています）
##M言語のif文
###”nullではないとき”の表記
```
if [column1] <> null
then "null じゃない"
```
###”nullのとき”の表記
```
if [column1] = null
then "null です"
```
と、Excel関数同様に = か <> を使って書きます。
###確認の仕方
条件列を使って、条件を記述してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573860/ddc36e4f-9f85-1023-439e-b1e9ebd07447.png)
関数バーをオンにして、関数を確認します。（詳細エディタからでも良いです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573860/24d19072-9540-eb1c-63c4-c28214910c52.png)
↑↑こういう感じで記載されているのが確認できます。
この方法を使えば、基本的な条件の記述方法が確認できます。
##if文の基本
言語/関数によって書き方が微妙に変わってくるので、どこかにメモっておきましょう。
###Excel
```
IF(条件,条件に合うならこれ,条件に合わないならこれ)
e.g. IF(A1>100,”大きい”,”小さい”)
```
**注意点**
• 特になし
###M言語(Power Query) ver.
```
if 条件
then 条件に合うならこれ
else 条件に合わないならこれ
```
**注意点**
• 小文字を使う（if）
• end は不要
###DAX関数(Power BI) ver.
```
if(条件,条件に合うならこれ,条件に合わないならこれ)
```
**注意点**
• 基本Excelと同じ
• if でもIF でも良い
###Alteryx ver.
```
if 条件
then 条件に合うならこれ
else 条件に合わないならこれ
endif
```
**注意点**
• ifでもIFでも良い
• endif が必要（endではない）
###Tableau ver.
```
if 条件
then 条件に合うならこれ
else 条件に合わないならこれ
end
```
**注意点**
• ifでもIFでも良い
• end が必要(endif ではない)
GKE環境でPHPを動かす時にxdebugの設定（remote_connect_back）でハマった話

# 事象

- GKE環境を構築
- PHP + Apacheのコンテナ（pod）を作成
- Serviceをポート転送（port forwarding）しての動作確認は正常に動く
- Ingressに設定したLB経由だと動かない（タイムアウトする）
- ログには特に何も出ない
- LBとPHPの間に、プロキシのservice（今回はnginx）を挟んだ場合は動く


# 原因

php.iniのxDebugの設定が原因でした。

具体的には

```
xdebug.remote_connect_back=1
```

これが原因でした。

https://qiita.com/castaneai/items/d5fdf577a348012ed8af#%E5%BF%9C%E7%94%A8%E7%B7%A8%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%82%92%E3%81%A4%E3%81%AA%E3%81%90%E3%81%AB%E3%81%AF


> 1 にするとPHPにアクセスした側の IP アドレスに自動的につなぎにいってくれる	

とのことで、LB->PHPのpod の場合、LBに対してつなぎに行こうとして、LB側はそんな接続は許可していないのでタイムアウトしていた、と思われます。

ローカルで動いていた設定をとりあえず、GKE環境に持っていったのですが、ログに情報が何も出ないため、原因にたどり着くのに時間がかかりました。（怪しそうな設定をコメントアウトしてたどり着きました）
AWSの学習日記

<h1> はじめに </h1>
AWSについて学習しているので、学習した内容をアウトプットするのを主目的として始めていきます。
Qiitaの使い勝手が良ければ、目的達成した以降も書き続けるかもしれないが、とりあえずはAWSの学習内容にフォーカスしてブログ感覚で学習内容をアウトプットしていきます。

<h1> これから書こうと思っていること </h1> 
AWSの学習と言っても範囲が広いと思うので、もう少し範囲を絞っておくと、AWS 認定 Cloud Practitioner試験(以下、AWSCPという)合格に向けて必要な知識の学習をしている。
ということで、この試験に向けて勉強したことを書き記していく。
これらを踏まえて、以下の2点を主に書き記していくと予想している
<ul>
    <li> AWSのサービスに関すること
    <li> 勉強していて分からないIT単語
</ul>

<h3> AWSのサービスに関すること </h3>
書く内容をもう少し具体的に言うと、「AWS サービス一覧」と検索すると以下のような画面がAmazonサイト内に出てくる。
![AWS_seriviceListpng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766879/0951309c-bceb-1175-5a60-09fdda52c918.png)

この中の例えば、コンピューティング製品をクリックすると以下のようにコンピューティング製品の中からさらにサービスを選択させる画面になる。
![AWS_service_computingList.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1766879/39df2dc2-264c-ca42-2415-c64400c9e576.png)

AWSCPではこれらサービスの違いを知っておく必要があるので、このようなサービスの違い、比較などがメインになると考えている。
コンピューティングだけでもかなりの量だが、他にもストレージ、コンテナ、マネジメントとガバナンスなど広い製品の様々なサービスについて問われるので、学習した内容を自分の言葉で言語化したり、表にまとめて視覚的に整理することができたらなと考えている。

<h3> 勉強していて分からないIT用語 </h3>
筆者は新卒でIT企業に入社したが、大学では別の学問を専攻していたので、普通のエンジニアが知っている用語を知らないというのが平気である。
この勉強を通じて少しでも減らしていこうとQiitaにも書き記そうと思う。
【Git】チームから学ぶGitの使い方　Gitを使用する理由編

####My Profile
プログラミング学習歴②ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。　



#対象者

* Gitを使って開発を進める理由を知りたい方


#目的

* Gitの理解を深める

#実際の手順と実例
###1.バージョン管理ができる
それぞれのディレクトリごとに管理して開発を進めたらどれが最新の状態になっているのかわかりませんよね。

そんなとき、Gitでローカルリポジトリにコミットしておけば一目瞭然でだれがどこを編集したかまでわかる！！！


###2.データのバックアップが取れる
　ファイルごとの単位で前の状態に戻すことが可能です。

私もcloud９で開発中に何かしらの不具合で編集データ吹っ飛んだけどGitのおかげで助かりました。笑


###3.複数人で同時作業が可能
分離型バージョン管理システムといい
同じファイルを複数人メンバーが管理し取り扱うことが可能です！



次の記事ではチームのgitの作り方を書いていきます！
基本情報技術者試験　データベース編③

#初めに
[前回](https://qiita.com/reo0612/items/aaffd13da71fcb6c77e9)の続きです。

#トランザクション管理と排他制御
DBは複数の人が共有し、貯め込んだデータを出し入れできる便利なものです。
しかし、ユーザーが好き勝手にデータを操作できてしまうと大変なことになります。
![スクリーンショット 2021-07-16 14.38.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743730/e65c3bd6-4e70-fdb4-0eff-84fbd45bd126.png)
例えば、店員が「ハサミ」を同時に客に売ったとして「在庫数」を更新しようとします。
本来であれば、「在庫数」は`3->2`になり、`2->1`になるのが普通です。

ですが片方の処理中にもう一方が読み書きしているため、「在庫数が３」のままで表示されてしまいます。

結局、後から更新した店員には前の店員の更新が反映されていないので
「ハサミの在庫数」はおかしなままで放置といったとんでもない事が起きてしまいます。

他にも「`更新作業中に別の人によってデータが削除されてしまった`」など
誰も彼もが好き勝手に操作していると、データの不整合を引き起こしてしまいます。

そうした問題からDBを守るのが`トランザクション管理`と`排他制御`です。

##トランザクション
`一連の処理をまとめたもの`を`トランザクション`と呼びます。
先ほどの例で出てきた店員が「在庫数を確認する」->「在庫数の更新」の流れがそうです。

このトランザクション単位で更新処理を管理します。

##排他制御
`処理中のデータをロックし、他の人が読み書きできないようにする機能`を`排他制御`と呼びます。

つまり、トランザクションの間に使用するデータをロックしておけば
誰かに割り込まれてデータの不整合が生じるということが無くなるという訳です。

ロックする方法には2種類あり、

・`共有ロック`：他のユーザーは`データを読むことはできますが、書くことは出来ません`

・`専有ロック`：他のユーザーは`データの読み書きが出来ません`

といった特徴があります。

ロック機能は非常に便利な機能ですが`注意`しないといけない場合があリます。

例えば、AとBのデータがあったとして

・トランザクション１では、Aにアクセスしていて更新のためにロック
・トランザクション２では、Bにアクセスしていて更新のためにロック

していたとします。

この場合、お互いが更新のためにロックしているので
どちらも違うデータにはアクセスできません。

つまり、「`お互いがお互いのロック状態を永遠に待ち続ける`」といった事が引き起こされてしまいます。

これを`デッドロック`と呼びます。

こうなってしまったら、いずれか一方のトランザクションを
`強制的にキャンセル`しなければいけないので気を付ける必要があります。

##トランザクションに求められるACID特性
DBMS(データベース管理システム)では、トランザクション処理に対して
次の４つの特性(`ACID特性`)が必須とされています。

#####◯`Atomicity(原子性)`
トランザクションの処理結果が

・`全て実行されるか`
・`まったく実行されないか`

のいずれかで終了し、中途半端に一部だけ実行されるようなことは許しません。

なので、あくまでも全ての処理が正常に終わった時のみ、その内容がDBに反映されます。

#####◯`Consistency(一貫性)`
DBの内容が`矛盾のない状態であること`が重要です。

なのでトランザクションの処理結果が、矛盾を生じるような事になってはいけません。

#####◯`Isolation(隔離性)`
順番に実行した場合でも複数実行した場合でも`処理結果が一致すること`が重要です。

つまり、排他処理(ロック機能)をきちんとやって相互に影響させないようにしないといけません。

#####◯`Durability(耐久性)`
正常に終了したトランザクションの処理結果は`障害が発生してもDBから消失しないこと`が重要です。

何らかの復旧作業が保証されていないといけません。

##ストアドプロシージャ
`ストアドプロシージャ`とはDBMSの機能の一つであり、`DBを操作する一連の処理手順(SQL文)をコンパイルしてまとめ、DBMS側に保存した戻り値のない関数`です。

ユーザー側は指定するだけで`即実行可能`です。

・ちまちまとSQL文を流す必要がないので`ネットワークの負荷が軽減`できる
・即実行可能な形式なので`処理速度の向上`が見込める
・保存も実行もDBMS側の機能なので`呼び出し側の環境を気にせず、同じように利用可能`

といったメリットがあります。

#おわりに
今回はここまでです。

間違っている部分や気になるところがあれば
コメントして下さると有り難いです。
マイグレーションファイルをdownせずに削除してしまった

注：初学者のためメモ的な扱いで書いています。
間違っている事があればコメントで教えてください。



今回手順を覚えるために
一度作成した全てのデータをファインダーから
右クリックでファイル事全て削除して
新しくrails newで作り直してしまった

再度同じ手順で行った際に過去のマイグレーションファイルがdbのデータ上に残ったまま
新たにもう一つ作った物と２つ出来てしまった。

```sh
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210716030715  ********** NO FILE **********
  down    20210716052228  Create users
____________________________________
```


********** NO FILE **********というファイルで、
up状態のファイルを削除したい
- 削除したいファイルのマイグレーションIDを確認する
- 削除したマイグレーションファイル名と同名のファイルを作成する
- downさせて、作成したマイグレーションファイルを削除する
をしてもup状態がdownにならず削除出来ない。
参考：[【Rails】マイグレーションファイルを削除する](https://qiita.com/beanbeenzou/items/e8886071ab1e1cf7a9c0)

なぜか？

rails君は俺は消してないしこれ残してあるけど....
え？また同じもの作るの？
はいよ〜〜って感じに２個目作りました〜と作成

__________________________________＿_____

問題→ファイルをゴミ箱に入れて削除した❌

しかし
rails上では消す作業をしていないから
db上にはまだそのファイルは残っている

しっかりと消したファイルを戻して
そのファイルを削除する作業が必要
**[マイグレーションファイルはDBの歴史]**

もう覚えてないよ.....


そんな時に助けてくれるコマンドが

`rails db:migrate:reset`

`rails db:dropとrails db:createとrails db:migrate`
を一気に行ってくれるコマンド


>Dropped database 'session_login_development'
Dropped database 'session_login_test'
Created database 'session_login_development'
Created database 'session_login_test'

全て消してくれて新しく作り直してくれる
便利なコマンド....。

注意点は、一人で開発してる分には大丈夫

チーム開発の際はしっかりとめんどくさい方法で
作った事、消した事も記録させて新しい物を
作り直さなければいけない。
React Hooksの10種類を理解する（Basic: useEffect）

# React Hooksの10種類を理解する（Basic: useEffect）
## useEffectの基本

- 「DOMの書き換え（mutation）」「データ購読（subscriptions）」「timer」「logging」などの副作用（side effects） においては、UIにまつわるバグや非整合性を引き起こす原因となる。そのため、関数component本体（React Render Phase）で描写することはできない。そのような場合に使用するのが`useEffect`になる。
- `useEffect`に渡された関数は、renderが画面に描写された後に動作する。
- `componentDidMount`と`componentDidUpdate`の2つの機能を持ったhookである。

### effectの初期化（cleanup）

```javascript
useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    subscription.unsubscribe();
  };
});
```

- 上記の例では、更新がされるたびに新しいsubscriptionが作成されることになる。
- 前回のeffectは、次回のeffectが実行される前にcleanupされる。

### 条件付きで`useEffect`を実行

```javascript
useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);
```

- 上記の例だと、`useEffect`の第2引数として、`[props.source]`が設定されている。こうすることによって、`props.source`が更新されたときのみ`useEffect`を実行するようになる。
- 空配列（`[]`）の場合、mount時にeffectが実行され、unmount時にcleanupされるが、更新時には実行されないことになる。

## reference

- [フック API リファレンス](https://ja.reactjs.org/docs/hooks-reference.html)
- [すごいReactフック8選](https://qiita.com/baby-degu/items/52dbb382bbaf6c43e2db)
Tensor演算に便利なEinopsとPyTorchのeinsum

画像認識向けにTensor演算をする機会が増えてくると、以下が便利

- [Einops](http://einops.rocks/): 次元ごとに切ったり貼ったりがパッと出来る
- [einsum](https://pytorch.org/docs/stable/generated/torch.einsum.html): 次元方向にかけたり足したりがパっと出来る

実行速度に関しては、いろいろと言われているモノのの、この便利さは後でサクっと読めるのが良い。そんなわけで、忘れないように、便利機能のおさらいと、有難い解説記事をまとめてみる。

##Einops
Einopsの便利さに関しては、上に貼ったオフィシャルサイトにある動画が、一番わかりやすいと思う。
[【einops】テンソル演算と画像処理 -NumPy, JAX, PyTorch, TensorFlowに対応した可読性の良いコードを書く-【超入門・超実践】](https://cpp-learning.com/einops/)
こちらに、日本語の細かい解説記事あり。

お気に入りは軸をくっつけたり、順番変えたりできる[rearrange](http://einops.rocks/1-einops-basics/)。
Normalizeするために、軸をちょっと入れ替えたり、Batchと何かをくっつけてから、元に戻すとかが簡単。しかも、読みやすい！

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/75cb4792-44f4-2753-7a2b-18d5137301a2.png)
##einsum

アインシュタインの縮約記法なんて、かっこいい名前がついているけれど、ようはTensor計算を簡単にする関数。物理屋さんでないと分かりにくい表記なので、コンピューター屋さんは、for loopで書き直すと分かりやすい。

おススメの解説YouTubeビデオ
[Einsum Is All You Need: NumPy, PyTorch and TensorFlow](https://www.youtube.com/watch?v=pkVwUVEHmfI)
そして、この頃はやりのAttentionやTransformerをeinsumとEinopsを使ってサクっと書く解説記事がこちら。
[Understanding einsum for Deep learning: implement a transformer with multi-head self-attention from scratch](https://theaisummer.com/einsum-attention/)

基本的には、こんな感じで書く。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/371969fb-94b8-360c-bac6-e58a2a1e7fe9.png)

入力のTensorの数は任意。ルールは

1. 入力の同じ文字はelementwiseに掛け合わせる
1. 出力にない文字は全elementを足し合わせる（出力がない場合は全て足される）
1. 出力の順番は指定できる（1，2なしで、転置などの軸の入れ替えが出来る）
　

行列計算
M = AB
をeinsumで書いてみると
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/33ac5d70-ae1c-75c8-eed5-83d3ee552e04.png" width="75%"> 
これをfor loopで書き下してみる。
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/82b4d947-554f-399d-6a48-c021b912b1d9.png)
こんな感じで、考えるとeinsumも怖くない。
これで、この頃、よく使われているバッチ事の演算も簡単に書ける！
ECS exec 利用手順

***本記事は、AWS ECS on Fargateへ ECS execを利用してシェルログインを行う手順を記載する。***

# ECS execについて
ECS execは、ECSクラスター上で起動している ECSインスタンス / Fargate に対してコンテナ内でコマンドを実行したり、シェルを取得する事が出来る機能。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/eea22e76-bd6b-8fc1-bbf7-b092661db23b.png)


# 前提条件
- ECS Exec は対象が Linux コンテナでのみサポートされる。
- AWS Management Console からの実行は不可能でAWS CLI から行う必要がある。
  また、AWS CLI バージョン 1.19.28 以上 または バージョン 2.1.31 以上でないと、コマンドが実行できないため注意が必要。
- Systems Manager の Session Managerを利用して、実行中のコンテナとの接続を確立するため、インターフェイス Amazon VPC エンドポイントを作成する必要がある。
- EC2にて利用する場合、2021年 1月 20日以降にリリースされた Amazon ECS 最適化済みの AMI 、エージェントバージョン 1.50.2 以上で使用する必要がある。
  Fargateにて利用する場合は、プラットフォームバージョン 1.4.0 以上を使用する必要がある。

# 手順

## IAMロール
ECS Exec を使用するためには、ECSタスクロールに SSMエージェントとSSMサービス間の通信に必要な権限をコンテナに付与する必要がある。
ECS Exec で使用するコンテナのタスクロールに、以下の IAM ポリシーを追加する。

```
{
   "Version": "2012-10-17",
   "Statement": [
       {
       "Effect": "Allow",
       "Action": [
            "ssmmessages:CreateControlChannel",
            "ssmmessages:CreateDataChannel",
            "ssmmessages:OpenControlChannel",
            "ssmmessages:OpenDataChannel"
       ],
      "Resource": "*"
      }
   ]
}
```


## ECS on Fargate
ECS クラスター / サービス / タスク定義は既に作成している前提

***既に使用しているタスクに対して ECS Execを有効する事は出来ない。***
そのため、サービスに設定されている "enableExecuteCommand" という ECS Execを有効にする設定の変更を行う必要がある。
enableExecuteCommandはデフォルトで falseとなっている。

```
aws ecs describe-services --cluster <cluster-name> --service <service-name>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/99ad4d6a-5b4a-5b44-11ea-a258111392ec.png)

サービスの更新を行い、 enableExecuteCommandを tureに変更する。

```
aws ecs update-service --cluster <cluster-name> --service <service-name> --enable-execute-command 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/8ec9e6bb-1734-0482-bcb0-66d47cbbd7f4.png)


enableExecuteCommandが trueになっている状態から起動をしないとタスクは有効にならない。

```
aws ecs describe-tasks --cluster <cluster-name> --tasks <task-ID>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/278566e1-0e91-3588-7bb4-c1c0ac4e174e.png)

サービスが更新された状態でタスクを起動して、enableExecuteCommandが有効になっているか確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/f0f43c56-3e47-d9ca-cd10-1a7be54a21cd.png)

この状態で ECS Execが使用可能となるため、ecs execute-commandを実行してシェルログインを行う。
ecs execute-commandでは --interactive / --commandオプションが必須であり、 --commandでは、コンテナで実行するコマンドを指定する。

```
aws ecs execute-command --cluster <cluster-name> --task <task-ID> --container <container-name> --command "<command>" --interactive
```

コンテナに対してシェルログインを行う場合は、 --command "/bin/bash" を指定して、実行すると、セッションがスタートし、ログインが可能となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597898/0ae24f2f-e504-7f66-12a8-64165f5afc83.png)
Expoで制作したReactNativeアプリをPWA対応Webビルドする必要最小限の手順

# Expo-ReactNative を PWAサイトにする
この記事は、Expoの準備から、WEBサイトをビルドして、SPAにすることと、PWA対応にすることの最低限の作業を記載しています。
細かいことは別記事がたっぷりあるのでお任せ。

あくまで必要最小限を知ることを目的にしています。

# Expo作成開始

```bash
expo init AppNameWoIretene
```

カレントにフォルダができる

# 頑張って作る
割愛

# ローカルデバッグする
```bash
npm start
```
Metro Blender が起動して、Androidエミュレータ起動したり、ブラウザ起動させたりできる
しかも修正がリアルタイムにエミュレータに反映されて、開発しやすいのなんのって・・・・

# WEBビルドする
作成したソースコードをそのままサーバにアップロードするわけではなく、ちゃんとビルドするってのが、Javascriptっぽっくないなぁと思う。
経験にもよるだろうけど。

```bash
expo build:web
```

カレントに出来上がる `web-build` ディレクトリ以下をサーバにアップロードすれば、SPAサイトの出来上がり。
でもこれだけだと、PWAに対応はしていても、実際にはインストールができない

# PWA 対応する
手順はこちら
https://github.com/expo/fyi/blob/master/enabling-web-service-workers.md

## 開始コマンド
```bash
expo customize:web
# 色々選択肢が出るけど以下を選択(スペース押下)してエンター
(*) webpack.config.js
```
`npm install --save-dev @expo/webpack-config` が実行される

少しすると、カレントディレクトリに `webpack.config.js` が作成される。

## webpack.config.js を編集
デフォルトの記述をちょっと修正する

```webpack.config.js
const createExpoWebpackConfigAsync = require('@expo/webpack-config');

module.exports = async function (env, argv) {
///////////////////////////////これを削除
//  const config = await createExpoWebpackConfigAsync(env, argv);
///////////////////////////////以下に修正
// 上流から受け取った env に offline:true のキーバリューセットを追加している　要は offline 使うよ、って追加しているだけ
    const config = await createExpoWebpackConfigAsync(
        {
            ...env,
            offline: true,
        },
        argv
    );
///////////////////////////////ここまで
  // Customize the config before returning it.
  return config;
};
```

## 続けてもう一度ビルド

```bash
expo build:web
```

これだけで、PWAが有効になる。
カレントに出来上がる `web-build` ディレクトリ以下をサーバにアップロードすれば、PWAサイトの出来上がり。

細かいことは別記事にお任せします。
Setup npm 

<h1>If you want to use global path with npm, not local.</h1>
1. Install npm 
2. `npm install -g {modules}`
    - Sometimes it gets permission error

    -> Comfirm path with `npm -g list`
    -> change the permission of the directory 
**WARNING**: If the displayed path is just /usr, switch to Option 2 or you will mess up your permissions.
    -> ```sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}```

3. try to run the module
    ` {module} --version` 
    - when it gets an error `{module} command not found`

    try to run:
    `export PATH=(npm config get prefix)/{lib/node_modules,bin,share}:$PATH > ~/.profile`
    `source ~/.profile`
Make sure there is a path in `.profile`

It will work.


<h3> Referrence </h3>
https://superuser.com/questions/1081769/after-npm-install-g-command-still-not-found
AWS 認定試験での失敗談 (PSIオンライン)

#失敗談からの学び (結論)
結論から先に申し上げますと、PSI のオンライン試験を受けるときには、**パスポートなどのご自身の名前が英語表記された身分証明書が必要**となりますのでご留意くださいmm

#前提
AWS の認定試験は PSI とピアソンVUE の 2 つのテスト配信プロバイダー経由で受けることができます。
今回諸事情があり PSI のオンライン試験を受けることにしました。

#テスト前の懸念
PSI で試験を受ける場合、面接官とのやり取りは全て英語になります。
英語であること自体はあまり重要視していなかったのですが、私の持つ唯一の英語表記の身分証明書であるパスポートがコロナ禍で有効期限切れになっていることに一抹の不安を感じました。
面接官とのやり取りが全て英語ということは、身分証明書も英語表記である必要があるのでは？という考えです。
ただ、パスポートの再取得・・・非常に面倒くさい。コロナ禍で次いつ海外旅行に行けるかもわからないですしね。

#PSI の試験要項を確認する
以下のように記載がありました。

```
Required Identification Documents

For admission – Bring 2 forms of personal identification. If you are taking your exam via Web Delivery or Kiosk, note that only one Primary ID is required. Primary ID must display name, photograph and signature. Secondary ID should show name and signature. Examples include:
Primary ID Forms (valid and current):

    Government-issued Driver's license
    U.S. Department of State Driver's License
    National/State/Country Identification Card
    Passport
    Passport cards
    Military ID

Secondary ID Forms (valid and current):

    Debit/ATM Card
    Credit Card
    Any form of ID on the primary list.
```

上記を私は自分に都合よく解釈し、「Government-issued Driver's license(=>免許証)」「National/State/Country Identification Card(=>マイナンバーカード)」があるので、英語表記の身分証明書がなくてもいいだろうと考えました。

#さあ試験当日
オンラインで試験会場に接続し、試験官とやり取りを進めると、やはり英語表記の身分証明書がないかを聞かれます。
色々頑張って協議したのですが、やはり英語表記の身分証明書がないと NG とのことで試験が受けられなくなってしまいました。。ｼｮﾎﾞｰﾝ

#最後に・・・
不安がよぎっていたので事前に問い合わせを行なっておけばミスを防げていたのですが、問い合わせも英語だったことが心理的ハードルを上げてしまい、結果横着をしてしまいました。
試験のリファンドやリスケ等ができるかは試験官とのチャットでは結論が出ず、メールにて問い合わせを行いました。(望み薄。これも含めのお勉強代金ですかね。。)
リファンド等の結果が出たらまた報告したいと思います。
・Rubyでのクォーテーションの使い分けについて

#Rubyでのクォーテーションの使い分けについて

1.''(シングルクォーテーション)の場合
-中の文字列が展開されません(そのまま出力されます)

2.""(ダブルクォーテーション)の場合
-中の式が展開されて表示されます
myCheatSheet

##### 仕切り線
```
<!--◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆-->
<!--➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖-->
```


##### トグル
```
<details><summary>  </summary><div>

</div></details>
```


##### コンテンツ
```
<!--➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖-->
<details><summary>  </summary><div>

+ 
</div>
</details>
```


##### リンク
```
+ []()

```
Railsで架空のCafeのHPを作ってみよう!【6日目】『複数形がないコントローラ』編

#概要
基本Railsの記法に則り書いていきます！
１から全ての説明ではなく
その中であれ？どうやるの？と
疑問に思った点や実装に困った箇所を
ピックアップして紹介していきます♩

#設定と準備
・Rails
・HTML
・CSS
・Javascript(jQuery)

↑上記の言語とフレームワークを使い
架空(自分で考えたテキトーなもの)のCafeの
HPを作っていこうと思います！

#6日目の作業内容:round_pushpin:
・テーブルの追加とそれに伴うコントローラーの作成

#6日目の気になった箇所:zap:
複数形がない単語のコントローラーって
命名規則とかあったりするの？

#仮説:pushpin:

コントローラは複数形でつけるのが好ましいとされます。

今回の場合**news**という単語でコントローラを実装したいが
この単語には複数形が存在しない。
この場合、そのままの単語でコントローラを作るのは
今後の実装において弊害があるのではないかと思った。

#結論:star:

そのままの単語で実装して問題なし！

今回の場合

```
% rails g controller news
```

あくまで複数形にするのは好ましいだけなので
実装自体に全く問題はです。

補足になりますが違かったのは

```
menus       GET    /menus(.:format)  menus#index
            POST   /menus(.:format)  menus#create
                                  
news_index  POST   /news(.:format)   news#create
```

このように同じアクションで比較した時のpathが少し違う程度でした。
複数形で実装したmenuモデルのmenusコントローラと
単数形で実装したnewsモデルのnewsコントローラの比較です。
createアクションを比較して頂けると違いがわかるかと思います。
Kotlinで再帰的ジェネリクスのJavaクラスインスタンスを生成する

# SNMPエージェントを作ろうとしてたら
```SubRequest.java
public interface SubRequest<N extends SubRequest<N>> {
```

　あれ？　これどうやってインスタンス作るんだ？

```Kotlin
// 普通はこうだがraw型は使えない
val req = object : SubRequest<SubRequest> {
// 同じ理由でこれも書けない
val req = object : SubRequest {
// AnyだとはSubRequestの継承だと断定できないから使えない
val req = object : SubRequest<Any> {
```

# どうやらラップして回避するしかなさそう

```kotlin
interface SubRequestWrapper : SubRequest<SubRequestWrapper>

// OK
val req = object : SubRequestWrapper {
    override fun hasError(): Boolean = false
```

　これが正しいやり方なのかは分からないんだけど、取り合えず回避はできた。
　これ以外になさそうに見えるが果たして。
[Rails] Basic認証の導入法

##はじめに

ポートフォリオ作成中、投稿機能などが存在していて、むやみやたらにいたずらされても困るので、Basic認証を導入しました。そこまで難しくはないので、よかったら参考にしてください。Railsアプリに導入した方法です。

*※なお、このBasic認証は、安全性の観点から完全に信頼できる方法ではないので、ポートフォリオなど最悪悪さをされても深刻な被害のないようなものにだけ実装することをお勧めします。*

##Basic認証とは

Basic認証はHTTP通信の規格に備え付けられているユーザー認証の仕組みです。
ユーザーとパスワードを開発者が設定しておき、webアプリケーションのurlに飛んだ時にそのユーザー名とパスワードが求められるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1552346/213e9ef6-79c8-e5b5-1831-1612bf89685b.png)

##Basic認証の導入
Basic認証を導入するには**authenticate_or_request_with_http_basicメソッド**というメソッドを使用します。
変数名やメソッド名を名付けるのが下手くそな私がいうのもおかしいですが、このメソッドの名前は絶対ミスってると個人的には思っています。 笑

このメソッドを使ってブロックを作り、その中でusernameとpasswordを設定します。
こんな感じ↓

```ruby
# 'admin'というユーザー名と、'password'というパスワードでBasic認証できるように設定
authenticate_or_request_with_http_basic do |username, password|
  username == 'admin' && password == 'password'
end
```

このログインの要求は全てのコントローラーに対しても行いたいのでapplication_controllerに記述します。

```ruby:app/controllers/application/controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth


  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == 'admin' && password == '2222'
    end
  end
end
```

このように一連の処理を定義してbefore_actionで呼び出すように設定しておきます。
今回はusernameはadmin、passwordは2222 にしていますが、もちろん任意のもので構いません。
**ここでgitでpushしないでください！！　**

これでローカル環境で見てみるとBasic認証が導入されているはずです。
しかしながら、コードの中にusernameとpasswordの中身が書かれているとgithubから簡単に答え見られてしまうので、環境変数に設定します。

環境変数はOSがcatalina以降であれば「.zshrc」のなかに記載します。
OSがMojave以前の場合「.bash_profile」のなかに記載します。このファイルは普段は見ることができないですが、ターミナルでvimコマンドを使うことで開き、編集することが可能です。

ターミナルで実際に下記のように打ち込みコマンドを実行します。

```terminal:ターミナル（macOS,Catalina以降の場合）
% vim ~/.zshrc
```


```terminal:ターミナル(macOS,Mojaveの場合)
$ vim ~/.bash_profile
```

実行したら```~```がたくさん出てきます。これでファイルを開けました。
そこで「iキー」を押すと、一番下に```INSERT```と表示されます。
その状態で編集可能です。

それでは、下記の文章を書き込みます。↓

```zsh
export BASIC_AUTH_USER='admin'
export BASIC_AUTH_PASSWORD='2222'
```

もし他に記述があれば、消さずにその下から記述を始めてください。
完了したら、「escキー」を押して、 「:wq」と入力します。
入力後、「Enterキー」を押して終了します。

最後にsourceコマンドという、先ほどの記述した内容を実行するコマンドを実行して環境変数の設定は完了です。

```terminal:ターミナル（macOS,Catalina以降の場合）
% source ~/.zshrc
```

```terminal:ターミナル(macOS,Mojaveの場合)
$ source ~/.bash_profile
```

さて、ここからはまたapplication_controllerの方に戻りまして、先ほどの記述を編集します。
basic_authメソッドを下記のように編集します。

```ruby:app/controllers/application_controller.rb
#　省略

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]  # 環境変数を読み込む記述に変更
    end
  end
```

これでコードを見られてもusernameとpasswordの中身が漏洩しません。pushしても安心です。
ブラウザで再度確認して変わらず導入できていれば成功です。

もしBasic認証が出てこなかったら、シークレットウィンドウで試してください。

##最後に
これはあくまでローカル環境でのBasic認証となります。本番環境では、どこにデプロイしたかによって設定の仕方も変わってきますので、今後記事にかけたらなと思っています。
WebRTCのNS(noise suppression)処理

# 1.概要
WebRTCで雑音抑圧処理用の関数は基本下記になります：

WebRtcNs_Create

WebRtcNs_Init

WebRtcNs_set_policy

WebRtcNs_Analyze

WebRtcNs_Process

WebRtcNs_Free

初期化と最後のフリーを除いて、中心の処理は下記の二つになります：

WebRtcNs_Analyze

WebRtcNs_Process

# 2.雑音抑圧の基本アルゴリズム
## 2.1 雑音抑圧の実行関数
WebRtcNs_Processで呼び出されたWebRtcNs_ProcessCore

## 2.2 処理ロジック
1.インプットした音声データ(RTP payload)により、音声コンテキストを更新する

2.音声データに対して、高速フーリエ変換(FFT)を行う

3.音声データをWienerフィルタに入力し、雑音抑圧を行う(ComputeDdBasedWienerFilter)

4.音声データに対して、逆高速フーリエ変換(IFFT)を行う

※波形調整関連の処理は省略

## 2.3 Wienerフィルタの実現コード
```c
static void ComputeDdBasedWienerFilter(const NoiseSuppressionC* self, const float* magn, float* theFilter) 
{
  size_t i;
  float snrPrior, previousEstimateStsa, currentEstimateStsa;

  for (i = 0; i < self->magnLen; i++) {
    // Previous estimate: based on previous frame with gain filter.
    previousEstimateStsa = self->magnPrevProcess[i] /
                           (self->noisePrev[i] + 0.0001f) * self->smooth[i];
    // Post and prior SNR.
    currentEstimateStsa = 0.f;
    if (magn[i] > self->noise[i]) {
      currentEstimateStsa = magn[i] / (self->noise[i] + 0.0001f) - 1.f;
    }
    // DD estimate is sum of two terms: current estimate and previous estimate.
    // Directed decision update of |snrPrior|.
    snrPrior = DD_PR_SNR * previousEstimateStsa +
               (1.f - DD_PR_SNR) * currentEstimateStsa;
    // Gain filter.
    theFilter[i] = snrPrior / (self->overdrive + snrPrior);
  }  // End of loop over frequencies.
}

```

# 3.雑音抑圧の効果
## 3.1 雑音抑圧無し
![雑音抑圧無し](https://user-images.githubusercontent.com/87515148/125900179-94fc6f3c-c53e-44e5-a5fa-a975284b4091.jpg)

## 3.2 雑音抑圧あり
雑音抑圧無しと比較して、下の波形では、明らかにノイズが抑制されています。

一番下の波形図の黒い枠のところはフィルタの学習フェーズであり、赤い枠のところは作業フェーズです。

通話開始時や音声が著しく変化する場合、フィルタの学習にはある程度の時間がかかり、この時の雑音抑圧効果は比較的弱いことがわかります。これは、Wienerフィルタの性質とも一致しています。

![雑音抑圧あり](https://user-images.githubusercontent.com/87515148/125900189-deb90f35-71dd-493a-833d-08eb061862dd.jpg)
ADX2スクリプトで原音再生

# 内容
[pyaudio](https://people.csail.mit.edu/hubert/pyaudio/)を利用するとオーディオの解析とかできそうなので
とりあえず選択したウェーブフォームの元波形を再生するものを作ってみた

環境：CRI Atom Craft 3.45.00

# pyaudioのインストール
windowsでpython3.8を使っているのですが、pyaudioがインストールできなくて、
[これ](https://stackoverflow.com/questions/53866104/pyaudio-failed-to-install-windows-10/53866322)
を参考にインストールした。

[pipwin](https://pypi.org/project/pipwin/)
何か非公式なものみたいだけど・・・とりあえず動いた


# スクリプト
``` PlayWav.py
# --Description:[tatmos][Preview]選択したオブジェクトの原音を再生

import pyaudio
import wave
import time
import cri.atomcraft.project as acproject
import cri.atomcraft.debug as acdebug

p = pyaudio.PyAudio()

#--------
#AUDIOのDEVICEを列挙
#hostAPICount = p.get_host_api_count()
#for cnt in range(hostAPICount):
#    print(a.get_host_api_info_by_index(cnt))

#音を鳴らすDEVICEを指定
DEVICE_INDEX = 0

#--------

#選択中のマテリアルまたはウェーブフォームリージョンまたはキューを得る
selectedMaterials = acproject.get_selected_objects("Material")["data"]
selectedWaveformRegions = acproject.get_selected_objects("WaveformRegion")["data"]
selectedCues = acproject.get_selected_objects("Cue")["data"]

selectedMaterial = None

if len(selectedMaterials) > 0:
    selectedMaterial = selectedMaterials[0]
if len(selectedCues) > 0:
    selectedWaveformRegions = acproject.find_objects(selectedCues[0],"WaveformRegion")["data"]
if len(selectedWaveformRegions) > 0:
    selectedMaterial = acproject.get_value(selectedWaveformRegions[0], "LinkMaterial")["data"]

if not selectedMaterial:
    acdebug.warning("再生するマテリアルまたはウェーブフォームリージョンまたはキューを選択してください。")
    sys.exit()

print(acproject.get_value(selectedMaterial, "Name")["data"])

input_path = acproject.get_value(selectedMaterial, "SrcFileAbsolutePath")["data"]

if not input_path:
    acdebug.warning("マテリアルのパスがみつかりません。")
    sys.exit()

print("Path:" + str(input_path))

#--------
#ファイルを開く
wf = wave.open(input_path, "rb")


def callback(in_data, frame_count, time_info, status):
    data = wf.readframes(frame_count)
    return (data, pyaudio.paContinue)

#ストリームの作成
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                input_device_index = DEVICE_INDEX,
                output=True,
                stream_callback=callback)

#再生
stream.start_stream()
print("再生中 ... " + input_path)

#再生終わりまで待つ
while stream.is_active():
    time.sleep(0.1)

print("done.")
stream.stop_stream()
stream.close()
p.terminate()
wf.close()
```
【Swift】TextFieldが空欄だったらボタン無効化

よくある「テキストを入力→追加ボタンを押す→データの追加」という動作。
アプリの誤操作を防止するために、つけたくなったのが
「TextFieldが空欄なら追加ボタンが押せない」という機能。作り方を残しておきます。

## 実装方法

### TextFieldと追加ボタン作成
```swift
@IBOutlet weak var newContentsTextField: UITextField!
@IBOutlet weak var addButton: UIButton!
```

### TextFieldの「Editing Changed」接続

StoryboardのTextFieldを右クリック
オブジェクトが変更されたときに呼ばれる「Editing Changed」をViewControllerに接続

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643790/c37735a8-91f2-9e4a-5dc2-abb00f959dbc.png)

```swift
@IBAction func textEditingDidChanged(_ sender: Any) {

}
```

[https://developer.apple.com/documentation/uikit/uicontrol/event/1618241-editingchanged](https://developer.apple.com/documentation/uikit/uicontrol/event/1618241-editingchanged)

### TextFieldの変更処理を追加

TextFieldが空欄の時「ボタンの無効化」「半透明」にします。

```swift
 private func updateTextFieldButton() {
  if newContentsTextField.text == "" {
      addButton.isEnabled = false
      addButton.layer.opacity = 0.4
  } else {
      addButton.isEnabled = true
      addButton.layer.opacity = 1
  }
}
```

### viewDidLoadとEditing Changedに追加

画面読み込み時とTextFieldの変更時に空欄かどうか判定

```swift
@IBAction func textEditingDidChanged(_ sender: Any) {
   updateTextFieldButton()
}

override func viewDidLoad() {
    super.viewDidLoad()
    updateTextFieldButton()
}
```

## 全体のコード

```swift
@IBOutlet weak var newContentsTextField: UITextField!
@IBOutlet weak var addButton: UIButton!

@IBAction func textEditingDidChanged(_ sender: Any) {
    updateTextFieldButton()
}

override func viewDidLoad() {
    super.viewDidLoad()
    updateTextFieldButton()
}
    
private func updateTextFieldButton() {
  if newContentsTextField.text == "" {
      addButton.isEnabled = false
      addButton.layer.opacity = 0.4
  } else {
      addButton.isEnabled = true
      addButton.layer.opacity = 1
  }
}
```
OpenCV を使う Windowsのコマンドラインツールを作る

# 環境
+ Windows 10 HOME 64bit  ver.20H2, OS build 19042.1083
+ Microsoft Visual Studio Community version 16.9.6
+ OpenCV ver.4.5.3
+ コンソールアプリ

# 手順
VS2019はインストール済みとする。OpenCVのダウンロードから、コンソールアプリを実行するまでの手順を以下に記す。

### OpenCVダウンロード
[GitHubのリリースフォルダ](https://github.com/opencv/opencv/releases)からダウンロード。
2021年7月16日現在最新の `opencv-4.5.3-vc14_vc15.exe` をダウンロードした。
### exeファイル実行
`opencv-4.5.3-vc14_vc15.exe`(ver.によりファイル名は異なる)を実行後できたフォルダ `opencv` を適当な場所に移動する。
この例では opencvを `d:\opencv-4.5.3` に移動する。
###環境変数設定
https://docs.opencv.org/4.5.3/d3/d52/tutorial_windows_install.html#tutorial_windows_install_path

に沿って環境変数を設定する。

この例では管理者コマンドプロンプトで `setx -m OPENCV_DIR D:\opencv-4.5.3\build\x64\vc15` を実行した。

###VS2019プロジェクトの設定
VS2019でC++/windows/コンソール のHello Worldアプリ　新規プロジェクトで作成。

[このOpenCVのtutorial](https://docs.opencv.org/4.5.3/dd/d6e/tutorial_windows_visual_studio_opencv.html)に沿って以下、プロパティにフォルダやライブラリファイルを設定する。

+ プロジェクトを右クリックしプロパティを選択

+ 追加のインクルードディレクトリにOpenCV のインクルードファイルフォルダを指定。
![2021-07-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/d661a836-21c7-c005-614b-6147f8ced0ac.png)

+ 追加のライブラリディレクトリを指定。
![2021-07-16 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/aa2127e3-36ff-5d76-96b3-6da598df68b2.png)

+ 構成をDebugにしてデバッグ用ライブラリを指定
![スクリーンショット 2021-07-16 134548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/60313170-0327-e1c1-642e-56c953371322.png)

+ 構成をReleaseにしてリリース用ライブラリを指定
![スクリーンショット 2021-07-16 134807.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131546/085888f1-702e-e949-b044-891dd5e84476.png)

###ビルド＆実行
[このOpenCVのtutorial](https://docs.opencv.org/4.5.3/dd/d6e/tutorial_windows_visual_studio_opencv.html)に記載のコードをビルド＆実行してみる。ファイル名は ご自分の環境に合わせて適当に。

```main.cpp
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
    if( argc != 2)
    {
     cout <<" Usage: " << argv[0] << " ImageToLoadAndDisplay" << endl;
     return -1;
    }
    Mat image;
    image = imread(argv[1], IMREAD_COLOR); // Read the file
    if( image.empty() ) // Check for invalid input
    {
        cout << "Could not open or find the image" << std::endl ;
        return -1;
    }
    namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
    imshow( "Display window", image ); // Show our image inside it.
    waitKey(0); // Wait for a keystroke in the window
    return 0;
}
```

コマンドライン引数に画像ファイル名を与えると、ウィンドウに表示した。
日本語入力が出来なくなった時の対処法


##前置き
<b>※本記事ではWindows10でMicrosoft IMEを使用している場合に限ります。</b>



こんにちは。
自分は日頃仕事では社内のシステムの運用保守、ヘルプデスク業務を行ってます。

なので営業部の方などからPCについての問い合わせやトラブルも受けたりもしてます。
その中でメモ的に残しておきたかったので記事にします。

##内容
ある日、営業部の方から
「<b>PCが突然日本語入力が出来なくなったんですけど…</b>」と問い合わせがありました。

PCの状態を確認したところ、
タスクバー右下のIMEの設定は<b>「あ」</b>となっており、日本語入力可能な状態ですが、
メールソフトやメモやGoogle検索窓などにいくら入力しても<b>「aaaa」</b>となり、
日本語入力ができない状態でした。

営業部の方曰く、事象は度々発生し、PCを再起動すると直るとのこと。
毎度再起動はかなり面倒くさいですよね。。

<b>調べてみるとWindows10の20H2、2004のバージョンで同様の問題が発生することがあるよう。</b>
その際の対処法について記事にします。

##対処法
①タスクバー右下のIMEの設定の「あ」もしくは「A」を右クリックします。
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/0912c05c-48ed-88e0-929b-f0fcda9a34b9.jpeg)
②設定をクリックします。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/a0c9756e-e344-9335-a600-84bf2d9b21b9.jpeg)

③[全般]をクリックします。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/88512f87-c6f9-9bef-afbe-6411e6986bf9.jpeg)

④一番下の[互換性]の「以前のバージョンのMicrosoft IMEを使う」をオンにします。
![互換.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1739387/c0b5f04e-d1d2-d364-9165-4062ce8a38b3.jpeg)

これで文字を入力すると日本語入力ができるようになります。
少しでもお役に立てれば幸いです～！
rails アプリ作成 rails6(準備編)

初学者のためメモみたいな感じです。
間違ってるところあればコメントで指摘してください！

0.githubにリポジトリ作成

1.rails new
```
rails _6.1.4_ new session_login -d postgresql
```
                    |ver.|             | ファイル名|

2.ディレクトリに移動

```
$ cd session_login

```

~/workspace/session_login (master) $ のようにディレクトリを移動したこと確認!!

忘れないように、githubと紐付けもしとく。
git add .
git commit -m"メッセージ"
git push


3.データベースの作成

rails db:createを実行することによって、config/database.ymlの設定に従って、データベースを作成する！

```
$ rails db:create

```

ターミナルのログでは、以下のようにデータベースが作成される

```
Created database 'session_login_development'
Created database 'session_login_test'

```

4.Webサーバを起動する

Webサーバを起動して、アクセス。

```
$ rails s

```

localhost:3000にアクセスする


ブラウザを開いてlocalhost:3000にアクセス。Ruby on Railsでサーバーを起動してデフォルトページが表示されれば成功!!


これでアプリケーション作成準備ができた！

```
rails _6.1.4_ new session_login -d postgresql のコマンドを実行することで、Ruby on Railsバージョン6.1.4のアプリを、session_loginという名前で、postgresqlを使用して作成できる。
```
セミナー後のフォローメールについて考える

とある外資系のオンラインセミナーを申し込んだところ、フォローアップのメールがきました。ここまでは普通の話しなのですが。。。。
# 担当者個人名で（おそらく申込者全員BCC)でToに担当者名を設定しているメール到着
↑の様なメールがとどきました。確かに、イベント管理システムが送ってくるメールは味気なく開封率が下がるので、個人的なメールを装ってメール配信することで、開封率を向上したいというような意図もあるのでしょう。気持ちはわかります。
# 驚いたのはオプトアウトに関する記述無し
確かに、自己のメールアドレスを公表してのメールは、オプトインの例外になる可能性があるので、法律違反にはならないでしょう。この方法は、抜け道とは言える可能性はありますが、大きなデメリットがあります。
# オプトアウトできないから、その個人アドレスからのメールを迷惑メール設定せざる終えない
ということになります。セミナーフォローアップメールのつもりで送った個人を装ったメールをスパム扱いにされてしまうとどうなるでしょうか？万が一、そのあと一緒に仕事をする機会ができたとしたらメールが届かないことになってしまいますよね。
更に、万が一、その個人メールアドレスはなく、ドメイン全体で、スパム扱いにされてしまったら、同僚からのメールも、すべてスパム扱いになります。将来的なビジネスチャンスに大きな影響があるということです。
# ただしくオプトアウトさせる手段を提供しないのは大きなリスク
になることは頭にいれておいたほうがよいでしょう。
[Rails] Rspec  WrongScopeErrorの解決方法

Rspecを学習したので初めてテストを書いてみてテストを走らせたところ以下のようなエラーが出ました。

```ruby:ターミナル 
Failure/Error:
       raise WrongScopeError,
             "`#{name}` is not available from within an example (e.g. an " \
             "`it` block) or from constructs that run in the scope of an " \
             "example (e.g. `before`, `let`, etc). It is only available " \
             "on an example group (e.g. a `describe` or `context` block)."

       `name` is not available from within an example (e.g. an `it` block) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc). It is only available on an example group (e.g. a `describe` or `context` block)

```
`name`に心当たりがない‥

### 解決策
色々調べてみると`rspec-rails`のversionが低いことが原因らしい
なので最新versionをインストールすれば解決！

```ruby:Gemfile
gem "rspec-rails", "~> 4.0.2"
```

意外と詰まったので同じエラーで詰まっている人は参考にしてみてください！
[Rails]param is missing or the value is empty: show

railsで開発時にエラーがでたのでメモを残します。
#解決策
上記のようなエラーが出たため調べました。

https://qiita.com/Takka_Log/items/32dae78d7e3892e7b051

上記のサイトを参考にして解決しました。
このサイトによると```params.require(:collect)```の部分が不要であると書かれていたため、pramsの記述を変更したところ解決しました。
#まとめ
今回は、このような方法で解決しました。

https://morelia.tokyo/error/param-is-missing-or-the-value-is-empty/

しかし、上記のサイトでは、form_withにモデルを関連付けしていなかったことがエラー内容となっているので、今後はまずform_withの記述内容について正しいのか確認したい。
料金が安いのは, EC2をオンデマンドでつけたり消したり vs リザーブドでつけっぱなし どっちなのか

# はじめに

A 「EC2でシステムの運用するけど, つけっぱなしの必要はないからオンデマンドでつけたり消したりしよう」
A 「Eipも必要だから紐付けておこう」
B 「それなら年契約で事前に払ってつけっぱなしのほうが安いんじゃね?」

ということで, オンデマンドでつけたり消したりするのと, 年契約でつけっぱなしにするのとでどちらが安いのか調査しました

## 計算してみる

### t3a.micro の場合 (Eip無し)

オンデマンド: 0.0122*24*30 = 8.784
1年契約: 63/12 = 5.25
3年契約: 121/36 ≒ 3.36

|t3a.micro|料金|
|-|-|
|オンデマンド|8.784$|
|1年契約|5.25$|
|3年契約|3.36$|

つまり, **40%以上の時間起動するなら3年契約の方が安く**, **60%以上の時間起動するなら1年契約のほうが安い**!!

起動に待たされる時間や手間を考えると, なにか事情でもない限りもっと短い起動時間でも年契約するほうが良いです 

### 他のインスタンス

どのインスタンスも似たような割引額です.

1年契約: 36~42%削減 -> **60%以上起動**しているなら1年契約がだいたい安い
3年契約: 56~64%削減 -> **40%以上起動**しているなら3年契約がだいたい安い

## Eipが絡む場合 (t3a.micro)

インスタンスが大きくなるとEipの料金が誤差になってくるので, 小さいもので調査しました.
Eipが絡む場合を試算してみます. 平均1日n時間起動していたとすると, 月あたりのオンデマンドの料金は

EC2: 0.0122 * 24 * 30 * n / 24 = 0.366n
Eip: 0.005 * 24 * 30 * (24 - n) / 24 = 3.6 - 0.15n

です. Eipは紐付いているEC2インスタンスが起動していて, かつそのEC2インスタンスが1つのEipしかアタッチされていない場合のみ無課金で, それ以外は0.005USD/hがかかります. 安いですが, 対象インスタンスが小さいと無視できません.

### VS 3年契約

3年契約の場合, t3a.microは約0.0046$/h, Eipより安いです.

つまり, t3a.microなら**起動時間に関わらず3年契約のほうが安い**です. Eipが必要なら3年契約でつけっぱなしが必ず安くなります.

### VS 1年契約

グラフで見てみます.

![スクリーンショット 2021-07-16 142416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765956/10e0c507-b38e-9b4a-6f39-27d72332acc2.png)

おおよそ7.5時間(31%くらい)起動するなら, 1年契約の方が安くなります.

## おわりに

リザーブドインスタンスの購入はここ
![スクリーンショット 2021-07-16 142929.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1765956/2fe8f835-aebb-f149-bd69-7156909f4622.png)


年契約の割引率はびっくりするくらい大きいので, 普段遣いでもできるだけ年契約すると財布に優しくなります!
【UiPath】フローにパスワードを付ける

# はじめに

この投稿はRPA ツールの「UiPath」で、フローの実行時にパスワード制限をかける という投稿です。


UiPathのコミュニティ「UiPath Friends」が企画する「UiPathブログ発信チャレンジ2021サマー」の 16日目の投稿でもあります。

企画の内容は [**こちら**](https://note.com/shumpei_w/n/n651cbdbec4e8) 。カレンダーのURLは [**こちら**](http://u0u1.net/sUwZ) です。

https://twitter.com/ShumpeiWatanabe/status/1405168150736359427?s=20


# WinActorのシナリオパスワード

WinActorには「シナリオパスワード」という機能があり、ロボット処理の「閲覧・編集・実行」操作を制限することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/48518582-680b-5ba3-7b74-3dff2b96835e.png)

```
作成したシナリオファイルに、シナリオパスワードを設定することで、編集・閲覧・実行の操作をすること
が制限できます。このシナリオパスワードは、「シナリオ編集パスワード」「シナリオ閲覧パスワード」
「シナリオ実行パスワード」などセキュリティのレベルごとに設定することも可能です。シナリオには機密
情報が含まれる場合もあるため、適切なパスワードを設定することで、機密情報を開示する範囲を限定する
ことができます。

参考）https://www.scsk.jp/sp/winactor/feature/security/
```

これをUiPathで実現してみます。


# 閲覧パスワード

UiPathでは、作成したフローはStudio上でパブリッシュすることで「.nupkg」というファイルに出力され、閲覧はできなくなります。ただし、この「.nupkg」ファイルは、拡張子をZipに変えて展開すると中身を見ることが出来るので、一手間加えれば見ることが出来ます。
その他に閲覧を制限する方法はないので、残念ながら現状では **UiPathでは閲覧パスワードの制限をかけることは出来ない** となります。

https://docs.microsoft.com/ja-jp/nuget/what-is-nuget

ただ、閲覧できないことによるデメリットもありそうなので、逆に「制限がなくても良い」と思います。
　`例）エラーで動かなくなった。担当者不在で、閲覧パスワードも分からないし、修正も出来ないぃ！`


# 編集パスワード

UiPathでは、パブリッシュ時に「証明書」を付けることで、所有者以外の人が改変していないコードであることを保証できます。
UiRobot側で「署名の確認」を強制し、信頼できる作成者を設定に追加することで、正規のコードであることを確認させる仕組みがありますが、実行ロボット側にも設定が必要であり、プロジェクトに署名なしの依存関係が含まれていると、依存関係の解決が妨げられる場合があり、簡単には導入できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/aa7ac3f1-ca8e-a6d7-2774-aa598fce9a24.png)

https://docs.uipath.com/studio/lang-ja/docs/signing-packages


# 実行パスワード

UiPathでは、作成したフローの実行を制限する機能はありません。なので独自に実装してみます。
機能的には以下のようなものを作成します。

- 1）実行時にパスワードを入力させる（設定ファイルの値と照合する）
- 2）実行マシンの名前が想定通りかをチェックする（設定ファイルの値と照合する）

ただし、コードを編集して「パスワード照合処理」を除去すれば突破できますし、ロジックを理解して設定値を変えれば突破できるため、完全な制限ではありません。（パフォーマンス：みせかけ的な機能実装です）


## 1）実行時にパスワードを入力させる

実行時に入力ダイアログを表示し、パスワードを入力してもらいます。
入力されたパスワードと設定ファイルの値を比較して、一致しなければ「例外をスロー」して処理終了します。

設定ファイルにパスワードをそのまま書いても良いですが、パスワードがそのまま設定ファイルに書かれているのではつまらないので、、設定ファイルには「パスワードのハッシュ値」を記載し、入力パスワードのハッシュ値と比較します。（ハッシュにすると元の文字列を隠蔽できます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/17410c4d-2741-eaac-43e0-860f36db7592.png)

ハッシュ値を求めるために、Cryptographyアクティビティを使用しています。

https://docs.uipath.com/activities/lang-ja/docs/about-the-cryptography-activities-pack

設定ファイルに書くハッシュ値は、試しにダイアログで値を入力してみて、ログに出力されたハッシュ値を設定すればいいと思います。

実行すると下記のような入力ダイアログが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/a013daef-69d7-628b-aab2-e5192044aa44.png)

確認しやすいように、以下にxaml形式でアップしました。

https://github.com/miyag/UiPath.ReusableCode/blob/master/SenarioPassword/CheckPassword_Execute.xaml

## 2）実行マシンの名前が想定通りかをチェックする

環境変数から実行マシン名を取得し、設定ファイルの値を比較して、一致しなければ「例外をスロー」して処理終了します。
こちらも設定ファイルには「ハッシュ値」を設定しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/61e34151-94b1-e9fe-5b8f-bf6ec7a99916.png)
確認しやすいように、以下にxaml形式でアップしました。

https://github.com/miyag/UiPath.ReusableCode/blob/master/SenarioPassword/CheckPassword_MachineName.xaml

# おわりに

いかがでしたでしょうか？UiPathでパスワード制限をする際に、参考になれば幸いです。

この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
[Android]RoomのDaoのメソッドでBooleanを返す

Android の Room において、Dao のメソッドで Boolean を返したい場合のメモです。

手順としては以下のようになります。

1. Dao のメソッドで戻り値を Boolean に設定する
2. `@Query` 内に SELECT 文を記述する。この際に戻り値で false として返したい場合は0、true として返したい場合は0以外の数値を返すような SELECT 文を記述する

上記の 2 で記述する SELECT 文ではクエリの内容にもよりますが `EXISTS` をよく使うかと思います。

## ケース1

例えば以下の例では `books` という本の情報を保存するテーブルから `bookId` に一致するレコードがあるかどうかを検証し、あれば戻り値で true が返され、そうでなければ false が返されます。

```kotlin
@Dao
interface BookDao {
    // bookId で指定された本が保存されているかどうかチェック
    @Query("SELECT EXISTS(SELECT 1 FROM books WHERE id = :bookId LIMIT 1)")
    fun hasBook(bookId: Int): Boolean
}
```

## ケース2

Room では Dao のメソッドの戻り値を Kotlin Coroutines の `Flow` や RxJava の `Flowable` などにすることも可能です。

https://developer.android.com/training/data-storage/room/async-queries

この場合、対象のテーブルのレコードに変更があると `Flow` や `Flowable` を通じて、変更後の値が通知されるようになります。

以下の例では、戻り値を `Flow<Boolean>` に設定してテーブル内のレコードの変化に応じて値が通知されるようにしています。

```kotlin
@Dao
interface BookDao {
    // 全ての本が読めるかどうかチェック
    @Query("SELECT NOT EXISTS(SELECT 1 FROM books WHERE readable = 0)")
    fun areAllBooksReadable(): Flow<Boolean>
}
```

これによって、例えば全ての本が読める場合は画面上でボタンを表示し、そうでない場合はボタンを非表示にしたい、といったケースが以下のように簡単に記述できたりします。

```kotlin
val button: Button = ...

lifecycleScope.launch {
    bookDao.areAllBooksReadable()
        .collectLatest { readable ->
            // 全ての本が読める場合はボタンを表示、そうでない場合は非表示にする
            button.isVisible = readable
        }
}
```
勇者と王様と企業のセキュリティ

# これはなに
企業のセキュリティをドラクエと比較して、セキュリティの立ち位置をなんとなく理解する。
(LT向けに作ったネタを文字だけにしているのでわかりにくい感じも)

# ドラクエをベースに考える
###勇者の目的
勇者の目的はなにか。「魔王を倒すこと」？
「魔王を倒すこと」は手段で、きっと目的は「世界を平和にすること」。

###王様の目的
「魔王を倒して平和を取り戻してくれ」
とこんぼうとたびびとのふくと 50G で勇者にアウトソースした王様の目的は、「国を繫栄させること」。

###目的は国を繫栄させること
目的が満たせるなら、魔王を倒す必要もなく、

- 静観する
- 魔族と手を組む

ということも手段の選択肢としてありなはず。(たいてい裏切られるけど)


# 企業にマッピングする
###セキュリティチームや情シスの目的
セキュリティチームや情シスの目的はなにか。「セキュリティ事故をなくすこと」？
「セキュリティ事故をなくすこと」は手段で、きっと目的は「会社を平和にすること」。

###社長の目的
「セキュリティ事故をなくして、健全な会社にしてくれ」
とセキュリティチームや情シスに依頼した社長の目的は、「会社を繫栄させること」。

###目的は会社を繫栄させること
目的が満たせるなら、セキュリティ事故をなくす必要もなく、

- 静観する
- ~~クラッカーと手を組む~~

ということも手段の選択肢としてありなはず。

# まとめ
情シスやセキュリティチームにいると、「すべてのセキュリティリスクに対策すること」が目的になってきてしまうことがある。
そうなると、「経営陣が予算を出してくれなくて何もできないー」といったモヤモヤが生まれてしまう。

モヤモヤの正体は「現場と経営陣の目的の違い」ということを理解しておくと、心の平和が取り戻せる。
(経営陣から見るとセキュリティリスクはビジネスリスクの一要素でしかない。)

ここらへんについては、[CISSP のドメイン1](https://japan.isc2.org/cissp_gaiyou.html#cissp-01) で体系的に習得することができる。
[Unity] スクリプトでCanvasに子のオブジェクトを生成する方法

######説明
スクリプトからCanvasに子のオブジェクトを生成する方法です。Imageの例です。ボタン等でも同じはずです。



```cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MoveControl : MonoBehaviour
{

    public Canvas canvas;

    // Start is called before the first frame update
    void Start()
    {
        GameObject g = new GameObject();
        g.AddComponent<RectTransform>();
        g.AddComponent<Image>();

        g.transform.SetParent(canvas.transform, false);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void Move_Update()
    {

    }
}

```
朝の定時報告とか出席確認とかを自動化したい！

こんにちわ、無職のエンジニア志望の稲沢と申します。
みなさん、テレワークやオンライン授業となって朝の報告や、出席などめんどくさいことをしなくてはいけなくなってはいませんか？
私は無職なので一切そういう煩わしさはないですが、働いている皆さんはそういうことがあると思います。

今回は題名にもあるとおり、朝の定時報告とか出席確認とかを自動化していこうと思います。
＊あくまで私の仮想での感覚のため、本投稿の書かれた事項は、自己学習を目的としたものであり、サボりの勧誘を目的としたものではありません。 最終的な決定は、自分の判断でお願いいたします。自己責任でおねがいします。一切責任は取れません。

#こんなフォームを自動入力
![スクリーンショット 2021-07-16 13.39.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764631/e74ae19c-40a4-db74-2e25-bae77c6b4010.png)
このようなgoogleフォームを自動入力させていきます。(どんなフォームであってもできますが。。。)

https://twitter.com/sskei11/status/1415905868000813057?s=20

こんな感じになります

##まずは事前準備

今回はPython3を使ってプログラムを動かしていくのでまずはPython3をインストールしましょう
詳しくは

https://qiita.com/ms-rock/items/72b8f1abc661c539bb09


で見てもらえば簡単にインストールできると思います。
当然ですがコマンドプロンプトやターミナルでインストールもできますが、その方法でやる人はすでにPythonなどはインストールずみだと思うので詳しく書かなくても大丈夫でしょう()

次に今回使うパッケージです。
今回はseleniumとwebドライバーのchoromedriverを使っていきます。

seleniumのインストールはターミナル（コマンドプロンプト）に

```
pip install selenium
```
で終わりです。
chromedriver　は自分でダウンロードしてきていれることも可能ですが、いちいちパスやらをつなぐのも面倒だし、初心者にはわからないと思うので、ターミナル（コマンドプロンプト）に

```
pip install import chromedriver_binary
```

と書いてやればインストールされます。
（注）もしのちにプログラムを実行した際にエラーが出た場合、クロームのバージョンとドライバーのバージョンが違っている可能性もあるのでその場合はクロームの設定からクロームについてを確認し、バージョンを合わせてください
この記事が参考になります。

https://qiita.com/tat_aka/items/009775dc0896f9e60bd9


##いよいよプログラムを作成していく

詳しくは説明するほどでもないので全部コードを載せちゃいます

```python:sample.py
import chromedriver_binary
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options # オプションを使うために必要

option = Options()                    # オプションを用意     
driver = webdriver.Chrome()   # Chromeを準備
driver.get('https://docs.google.com/forms/d/e/1FAIpQLSdyNm_orMGtWjkIItREL9YrVaufiVrkJh9TvymnolPWfDjFzw/viewform') #ここのurlに自分のフォームを入れてあげる
time.sleep(2)

#１問目　ラジオボタンの場合
FirstQ =  driver.find_element_by_id('i5') #１問目はid = i5 or i8
#人によってlabelのIDは違うのでChromeの開発者ツールを使ってlabelのIDを調べてあげる必要があります。
FirstQ.click()#ラジオボタンをONにする（つまりクリックする）
time.sleep(2)

#2問目　ラジオボタンの場合
SecondQ = driver.find_element_by_id('i15') #2問目はid = i15 or i18 or i21 or i24 or i27 
SecondQ.click()#ラジオボタンをONにする（つまりクリックする）
time.sleep(2)

#3問目(文字を挿入バージョン)
ThirdQ = driver.find_element_by_xpath("//input[@jsname='YPqjbf']")
#フォームのidがないのでjsnameを検索し、その内容を取得
ThirdQ.send_keys("111") #変数.send_key("文字列")で文字を入力できる

#送信ボタンを押す
submit = driver.find_element_by_xpath("//div[@jsname='M2UYVd']")
#buttonのIDを入れたかったのですが、今回はなかったので上と同様にjsnameを検索してその内容を変数に入れてます
submit.click()

time.sleep(2)
driver.quit()#開いたChromeを閉じる

```
フォームのIDの確認などはF12を押すかその他のツールからデベロッパーツールを選択するとホームページの中身が見れます。

皆さんのフォームでは少し違うと思うのでIDの変数や、URLなどを変化させる必要がありますが、大まかにはこれでできると思います！


今回はグーグルフォームの自動化の方法でしたが、新しい技術を学んでいくのは面白かったです。

もっとこうしたほうがいいよ！等ありましたらコメントでお願いします

###追記、朝に自動化するコードを忘れていました。

仮に朝九時に実行するとします
まず、pythonのパスを確認し、

```
which python3
```
これで出てきたパスをコピーし、

ターミナルで　crontab -e　と入力し

0 9 * * 1,2,3,4,5 /Users/bin/python3 /desktop/sample.py
と入力します。
User/...が先ほどコピーしたパスで、半角スペース開けて、 /desktop...というのが先ほど作ったパイソンのファイルのパスになります。

これで平日毎朝九時に自動で実行されます。

祝日等で辞めたい時はcrontab -e でコードを開き、
```
 #0 9 * * 1,2,3,4,5 /Users/bin/python3 /desktop/sample.py
 #を先頭につけてやり、再起動することで実行されなくなります


以上になります。初めて自動でChromeをうごかせるとたのし〜
【Swift】合計から平均を算出する方法

しゅんやです。

なんかSNSとかやってると、星でクチコミ機能が表示されてる事があると思います。

その時に、星が半分とか4分の3程度に割れてたりして、んでその横に「3.8」とか「4.2」とかの数字が書かれてることもあると思います。

あれは、出されたクチコミの合計から算出した「平均点」を表示してるわけです。

ちなみにあの星は、口コミライブラリである「Cosmos」を用いられているのですが、それを使ってやるとややこしくなると思うので、今回はただ合計から平均を出す方法をやって行きたいと思います。

ではいきましょう！

<h1>
はじめに
</h1>

まずはテキトーな数字たちを配列に入れます。

```php
import UIKit

class AverageViewController: UIViewController {

    //
    var averageArray = [5,2,1,3,4,3,1,2,4,1,4,1,4,5,1,2,2,1,6,3]

        override func viewDidLoad() {
        super.viewDidLoad()

      }

   }
```

次に、それらを全部足します。
(初めからすでに合計を出しておけば良いのですが、ここでは敢えて足し算します)


```php
import UIKit

class AverageViewController: UIViewController {

    var averageArray = [5,2,1,3,4,3,1,2,4,1,4,1,4,5,1,2,2,1,6,3]

        override func viewDidLoad() {
        super.viewDidLoad()

　　　　　//追加
　　　　　let total = Double(averageArray.reduce(0,+))//55

      }

   }
```
次に、配列の中身にある数は何個かを定義します。

```php
import UIKit

class AverageViewController: UIViewController {

    var averageArray = [5,2,1,3,4,3,1,2,4,1,4,1,4,5,1,2,2,1,6,3]

        override func viewDidLoad() {
        super.viewDidLoad()

　　　　　let total = Double(averageArray.reduce(0,+))//55

　　　　　//追加
　　　　　let arrayCount = Double(averageArray.count)//20

      }

   }
```
そして、割り算で平均を出します。

```php
import UIKit

class AverageViewController: UIViewController {

    var averageArray = [5,2,1,3,4,3,1,2,4,1,4,1,4,5,1,2,2,1,6,3]

        override func viewDidLoad() {
        super.viewDidLoad()

　　　　　let total = Double(averageArray.reduce(0,+))//55

　　　　　let arrayCount = Double(averageArray.count)//20

　　　　　//追加
　　　　　let average = total/arrayCount//27.5

      }

   }
```
そして最後に、四捨五入をします。

```php
import UIKit

class AverageViewController: UIViewController {

    var averageArray = [5,2,1,3,4,3,1,2,4,1,4,1,4,5,1,2,2,1,6,3]

        override func viewDidLoad() {
        super.viewDidLoad()

　　　　　let total = Double(averageArray.reduce(0,+))//55

　　　　　let arrayCount = Double(averageArray.count)//20

　　　　　let average = total/arrayCount//27.5

　　　　　//追加
        let rounds = round(average*10)/10//28

        //結果
        print(rounds)

      }

   }
```

<h1>
最後に
</h1>
お疲れ様でした。