OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxの基礎知識と基本的なコマンド

# Linuxの特徴
Linuxのプログラムにおいて、一番特徴的な部分はライセンス形式。
LinuxのプログラムにはGPL(GNU General Public License: GNU 一般公衆利用許諾)というライセンス形式が採用されている。
GPLは以下の特徴を持つフリーソフトウエアライセンス。

- プログラムを実行する自由
- ソースの改変の自由
- 利用・再配布の自由
- 改良したプログラムをリリースする自由

## カーネルとユーザランド
### カーネル
カーネルはOSの中核となる部分で、ハードウェアと直接やり取りするなど最も中心的な機能を受け持つ部分。

### ユーザランド
OSが動作するのに必要なカーネル以外の部分のこと。ファイルシステムやファイル操作コマンド、シェルなどの基本的なソフトウェア群を指す。

## シェル
Linuxにはシェルという対話型のコマンド入力環境が用意されている。
**シェルはコマンド(命令)入力を受け付けること**と**シェルスクリプトの実行**という大きく分けて2つの機能がある。
シェルスクリプトとは「コマンドの入力を自動化する」ためのもの。1つのファイルにコマンドを1行ずつ記述して作成する。作成したシェルスクリプトを実行することで、コマンドの実行を自動化するこができる。

# 基本的なコマンド

## ls
- ファイルやディレクトリの参照に使用する

### 書式
```shell
ls [オプション] [ファイル]
```
### オプション
```shell
-a .で始まる隠しファイル等も全て出力する
-l 長形式で出力する
-t 最終更新時間によって、ソートをして出力をする
-r 逆順にソートをして出力をする
```

## cat
- ファイルの内容を確認するコマンドの1つ

### 書式
```shell
cat [オプション] ファイル名
```

### オプション
```shell
-n 行番号を付加して表示する
```

## more
- ファイルの内容を確認するコマンドの1つ
    - catコマンドを使ってファイルの内容を表示するとき、行数がたくさんあると表示が流れてしまう。
    - たくさんの行があっても、画面制御を行い、スクロールを途中で止めてくれる機能をページングといい、それを実現するコマンドをページャと言う。
    - 代表的なページャとしてmoreやlessコマンドが存在する

### 書式
```shell
more ファイル名
```

ファイルを開いた後は次のようにコマンドを入力すると操作することが可能

| 項目 | 内容 |
|------------------|-------------------|
| スペース | 次のページにすすむ |
| b | 前の一画面に戻る |
| f | 次の一画面にすすむ |
| /単語 | 単語を検索する。nキーで検索結果をジャンプする |
| q | ページャコマンドを終了する |

## less
- ファイルの内容を確認するコマンドの1つ
    - 代表的なページャのコマンド

### 書式
```shell
less ファイル名
```

ファイルを開いた後は次のようにコマンドを入力すると操作することが可能

| 項目 | 内容 |
|------------------|-------------------|
| スペース | 次のページにすすむ |
| b | 前の一画面に戻る |
| f | 次の一画面にすすむ |
| ↑ | 前の行に進む |
| ↓ | 次の行に進む |
| /単語 | 単語を検索する。nキーで検索結果をジャンプする |
| q | ページャコマンドを終了する |

## touch
- ファイルのタイムスタンプの変更
    - ファイルには必ずタイムスタンプ(最終更新日)が必ず存在する。タイムスタンプはlsコマンドの-lオプションで確認できる。
    - その最終更新時間を変更するのがtouchコマンド

### 書式
```shell
touch [オプション] [ファイル名]
```

- touchコマンドを実行すると、ファイルのタイムスタンプが現在日時に変更される。
- ファイルが存在しない場合は中身が空のファイルを作成する。
RubyでLeetCodeやってみる-TwoSum

#概要
プログラミング力を上げるためにLeetCode始めました。
基本問題TwoSumの解説をRubyで行っていきます。

#Two Sum
##問題
整数の配列を与え、2つの要素の和がターゲットの値となるインデックスの組み合わせを配列で返す。

##例

```ruby
nums = [2,7,11,15]
target = 9
```

が与えられるとします。

```ruby
nums[0] + nums[1] = 2+7 = 9 
```
なので

```ruby
[0, 1]
```
を返します。

**上記を満たすようなメソッドをRubyで書くことを目標とします。**

##解法1 【Brute Force】
Brute Forceとは日本語で"強引な"という意を示します。
つまり何も考えずに解きます。

```ruby
# @param {Integer[]} nums 整数の配列
# @param {Integer} target 整数
# @return {Integer[]} 整数の配列

def two_sum(nums, target)
  (0..nums.length-1).each do |i|
    (i+1..nums.length-1).each do |j|
      return [i, j] if nums[i] + nums[j] == target #目標値となるかチェック
    end
  end
end
```
ある要素を基準にして、それ以降の要素を探索しながら和が目標値になるか見ていきます。

このコードを提出すると次のような結果になります。

```
Runtime : 4656 ms(平均)
Memory : 9.6 MB(平均)
```
平均は大体上の値になりますが、たまにタイムリミットになります。(提出物としてはアウト)

これは`each`によって平均n回×n-1回計算が行われるため計算量オーダーは*O*($n^2$)で示されます。
すなわち要素数が多くなるほど二次関数的に時間を必要とします。

##解法2 【Two-pass Hash Table】
和が目標値になる要素を探すよりも、`目標値-要素1`となる補数が存在するかを探した方が効率的になります。
そこで使われるのがハッシュです。

```ruby
# @param {Integer[]} nums 整数の配列
# @param {Integer} target 整数
# @return {Integer[]} 整数の配列

def two_sum(nums, target)
  hash = {}
  (0..nums.length-1).each do |i|
    hash.store(nums[i], i) #ハッシュを初期化
  end
  (0..nums.length-1).each do |i|
    complement = target - nums[i] #補数を用意
    return [i, hash.fetch(complement)] if hash.has_key?(complement) && hash.fetch(complement) != i #補数チェック
  end
end
```
あらかじめハッシュを用意しておき、補数となる値が格納されているか探索します。

このようにすることで`each`によるn回×n-1回の計算がn回だけになります。
よって計算量オーダーは*O*($n$)になります。
そしてこのコードを提出すると結果は次のようになります。

```
Runtime : 43 ms(平均)
Memory : 10.2 MB(平均)
```

若干メモリの使用量は増えましたが、恐ろしいほど早くなりました。

##解法3 【One-pass Hash Table】
今度は同じハッシュを使う方法でも技ありです。
一度の走査で完結します。

```ruby
# @param {Integer[]} nums 整数の配列
# @param {Integer} target 整数
# @return {Integer[]} 整数の配列

def two_sum(nums, target)
  hash = {}
  (0..nums.length-1).each do |i|
    complement = target - nums[i]
    return [hash.fetch(complement), i] if hash.has_key?(complement) #補数チェック
    hash.store(nums[i], i) #補数が存在しなかったため追加
end
```

コードの量は減りましたが読みにくくなりました。
これは条件を満たす要素が見つからなかった場合に追加していく方法です。
一度の走査で要素の追加と探索を行うためメモリの量を少し削減できます。
同じく計算量オーダーは*O*($n$)となり、提出結果は次のようになります。

```
Runtime : 48 ms(平均)
Memory : 9.9 MB(平均)
```
若干遅くなりましたがメモリの使用量が減りました。
**解法2**と比較してどちらの方法が優れているかは状況次第ですが、
**解法１**と比較するとハッシュを用いる方法がどれだけ優れているか明らかだと思います！
また、試行回数が7回ずつのため平均値の精度が高いとは言えませんが、この結果を見ると歴然ですね。

#まとめ
LeetCodeの基礎問題であるTwoSumの解説を行いました。
また、適切な解法をとることによって実行時間を大幅に短縮することが分かりました。
この１つの問題をきちんと解くだけで様々なことが学べたと思います。
これからもLeetCode続けていきたい…
AtCoder Beginner Contest に挑戦してみたら散々な成績だったので振り返る

定期開催されている ABC こと AtCoder Beginner Contest に参加してみたら、純粋な実力不足以外にも本質じゃないところで躓いたりして大変もったいないことをしてしまったので、次回の学びをより深めるためにできそうなことをメモっておきます。


参加したのは "ABC 170" です https://atcoder.jp/contests/abc170

# 入力はコマンドライン引数じゃなくて「標準入力」

はい。

A問題、 `sys.args` から入力を取り込むコードを書いていました。当然コケるのですが、思い込みのチカラで20分溶かしました。一番意義のない時間だった。

入力値は `input` で取り込みます。

```python
# 間違い
import sys

args = sys.argv

# do something ...
```

```python
# 正解. 以下は入力が2つの整数値の場合
x, y = [ int(i) for i input().split() ]

# do something ...
```

# WA(Wrong Answer) や RE(Runtime Error) で行き詰まったら、簡単なテストケースを書いてみる

いい感じに全部の条件を考慮できるケースをすべて生成するのはちょっとハードルが高いので（それが考慮できてれば多分詰まってない）、せめてローカルで動かせるテストデータ生成のコードくらいは書こうと思います。

幸い入力値の条件は明示されていますので、テストデータを生成するちょっとしたコードはすぐに書けるでしょう。それをパイプ越しに回答コードに渡してやれば多少は検証がマシになるんじゃないかと思ってます。

テストケース生成側で strerr に生成データを吐かせておけば、入力値を確認しつつ回答コードの入力の邪魔にもならないので、とりあえず次回 WA でどん詰まりしたらこれをやってみようと思います。


# WA のまま終わってしまった問題を振り返る

コンテスト中はテスト失敗の原因詳細は出ないので、もし WA のまま試行錯誤のうちに終わってしまった問題があればその振り返りをします。

ハマってるときは何が悪いのかマジでわからないので、境界条件など、ロジックやアルゴリズムに関わる考慮漏れなのか、単純に自分のケアレスミス的なものによるものだったのか、きちんと確認しないと気になって眠れません。

以下の「便利リンク集」で過去問のテストケースが掲載されてます。そこからデータを落として実際に WA だったケースを検証可能です。

https://atcoder.jp/posts/261

> [AtCoder's Testcases](https://www.dropbox.com/sh/nx3tnilzqz7df8a/AAAYlTq2tiEHl5hsESw6-yfLa?dl=0)　AtCoderの過去問のテストケースです。復習等に使用することが出来ます。非常に古いコンテストには対応しておりません。

各テストケースを観察すると、境界条件等の考え方などが見えて実案件のテストケースの開発業務にも参考になるかもしれませんね。

他の参加者の回答や公式の解説も併せて確認したいですね。解法が見えなくて苦戦した問題はそのへんでフォローしていきたいです。

# 次回以降

現時点ではプロコンにがっつりコミットするほど優先度は割かない予定です。

とはいえ、今後もABCには参加しようと思ってます。回答途中で終わってしまった問題のケアだけ振り返って、次回に臨もうと思います。繰り返していけば、そのうちにこの振り返り作業を後半の手強い問題でやれる日が来るでしょう。たぶん。
Javaの変数

## はじめに

前回コンパイラとインタープリタの違いを...と書いたが変数がの書き方が私の知っているものとだいぶ違ったので（やりたいことはわかる）今回は変数について書くことにする。

## 変数について
Javaで変数を定義するためには、
①変数にいれる値のデータ型を指定する、
②変数の名前を決める、
という2つが必要

```kane.java
//データ型　変数名
int number;

//データ型　変数名
String name;

```
データ型と変数名の間は半角スペース　※.(コロン)ではない


データ型はまず
文字列はString型   **S**は大文字
整数はint型      　**i**は小文字

## 代入は
```kane.java
//まずデータ型と変数名は定義する
String name;
//そして変数名に入れたい値は代入する 
name = "banana";
```
## 出力は
```kane.java
System.out.println();
//の()の部分に先ほどの変数名を書き込む
System.out.println(name);
```
```console:コンソール
banana
```

## がしかし
変数の値の代入は変数定義と**同時にできてしまう**。変数定義と同時に値を代入することを**変数の初期化**と呼ぶ。

```kane.java
String name = "banana";
```
## 変数の更新
変数は中身の値を変更することもできる。一度値を代入した変数に、その後再び値を代入すると、後で代入した値によって変数の中身が上書きされる。
データ型をつけるとまた定義してしまうことになるし同じ処理内で同一名の変数を定義できないためエラーを吐く。上書きするときはデータ型をつけないように注意する。

```kane.java
String name = "banana";
name = "ゴリラ";
```

```terminal:ターミナル
banana
ゴリラ
```

##自己代入
```kane.java
int number = 3;
number = number + 2;
System.out.println(number);

```

```terminal:ターミナル
5
```
このような代入を自己代入と呼びます。

自己代入にはさらに省略できて

| 基本形 | 省略形 |
|:--|:--|:--|
| x = x + 10 | x += 10 |
| x = x - 10 | x -= 10 |
| x = x * 10 | x *= 10 |
| x = x / 10 | x /= 10 |
| x = x % 10 | x %= 10 |

 1だけ足し引きする場合 
 更に省略形が存在する。 


| 基本形 | 省略形 | 更に省略 |
|:--|:--|:--|
| x = x + 1 | x += 1 | x++ |
| x = x - 1 | x -= 1 | x-- |

##数値のデータ型

int型（整数）
double型（小数）


##変数の注意点
変数名は基本的に自由に決めれるが、Javaでは決まりがあり
小文字を使い、複数の単語を使用する時は、2つ目以降の単語の頭文字を大文字にする。（キャメルケース）

```kane.java
banana 
bananaGorilla
```

##終わりに
まとまりのない感じになってしまったがこういう投稿のスキルも上がることを祈る。
Swift5のwithUnsafeBytesにて前の書き方がDeprecatedになっていたので修正方法を調べた

Swift4までData型が持つ`withUnsafeBytes`は以下の様な書き方ができた

```swift
dataBytes.withUnsafeBytes {(ptr: UnsafePointer<UInt8>) -> Void in
    ptr.advanced(by: 0)
    ptr.advanced(by: 1)
    ptr.advanced(by: 2)
}
```

しかし、Swift5でこの書き方はDeprecatedになっており、

```
'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R` instead
```

というWarningが出る。

たいていのコードは自動で直してくれるけど、これは駄目。おまけにSwiftをしばらく触っていなかったためここらへんの知識が欠落していて途方にくれたので、解決方法を探る。

とりあえず調べてみると、正しい書き方だと以下のようになる

```swift
_ = dataBytes.withUnsafeBytes { ptr in
    ...
}
```

ptrは`UnsafeRawBufferPointer`となっており、このままだとptrに対して`ptr.advanced(by: 0)`がエラーになってしまう。

そこで、UnsafeRawBufferPointerからUnsafeRawPointerを取り出し、利用する。
`baseAddress`はUnsafePointerを示し、`assumingMemoryBound`を利用して生のポインタと同じメモリに対する型付ポインタを得る。

```swift
    storeDataHeaderBytes.withUnsafeBytes{ rawPtr in
        guard let ptr = rawPtr.baseAddress?.assumingMemoryBound(to: UInt8.self) else { return }
        ptr.advanced(by: 0)
        ptr.advanced(by: 1)
        ptr.advanced(by: 2)
    }
```


これで今まで通りのコードで動くようになった。

もっと良い書き方があったら誰かコメントをいただけるとありがたいです。
Nuxt.js + Vim で補完が効かない



こちらの記事→「[Nuxt.js を IntelliJ から利用した際に、 `@` や `~` alias を解決してくれない対処](https://qiita.com/sutoh/items/54e94df1c610c0f18c85)」の vim 版です。

主に以下のような方のための記事です。

- Nuxt + vim 環境で開発している
- vim に [vls](https://github.com/vuejs/vetur/tree/master/server)(vue-language-server) が導入されている
- __タグジャンプ・補完が効かない__のでジャバスクリプトなんもわからん

# 原因

Nuxt.js の場合、 import 時の `~` や `@` はパス解決に利用される。

```javascript
import Hoge from "~/Hoge"
```

こういった記述をしている場合、パス解決のための情報を Language Server が知らないため、 `Hoge` が何者かわからない。
実際、相対パス記述に変更すればタグジャンプ・補完ができるようになります。

先の記事によると、IntelliJの場合は nuxt.config.js のパスを設定してやれば勝手に解析してくれるようですが、 [vlsのオプション](https://github.com/vuejs/vetur/blob/master/server/src/config.ts#L77) にそういったものはなく、vim の場合は難しそうでした。


# 対処方法

以下のような tsconfig.json を作成する。ディレクトリ名は適宜変えてください。
参考: [Path Mapping](https://vuejs.github.io/vetur/setup.html#path-mapping)


```json:tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./src/",
    "paths": {
      "~/*": "./src/*"
    },
    "allowJs": true
  }
}
```
DockerのコンテナにIPv6で接続すると接続元IPアドレスがコンテナネットワーク内のIPv4アドレスになる

結論としてはタイトルに書いた通りですが、調べた点とかをメモしておきます。

# 現象
ネットワーク構成はざっくりとこんな感じです。https-portalではリバースプロキシしてwebコンテナのコンテンツを返しています。

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132408/6f0b05d9-c065-8742-56ba-7c5d18278bc5.png)

このとき、webコンテナでは接続元としてグローバルIPアドレスが取得されることを想定していましたが、実際にはDockerのネットワーク(172.16.0.0/16)内のローカルアドレスが取得されていました。

# 原因
最初は以下の点を調べてみましたが、どれも原因ではなさそうでした。

* --userns-remapが原因？
  * 別の環境を用意して--userns-remapを有効にして試してみたが、正常にIPアドレスが取得できた
* --userland-proxy=trueが原因？
  * docker-proxyを使用していると接続元IPアドレスが取得できないとの情報があったため、--userland-proxy=falseにして試すも再現せず
* steveltn/https-portalでリバースプロキシさせてるのが原因？
  * そもそもhttps-portalの時点で接続元がローカルアドレスになっているので関係なさそう

最終的にはGitHubの[このコメント](https://github.com/nginx-proxy/nginx-proxy/issues/935#issuecomment-330809335)を見て、IPv6でサーバに接続していることが問題だと気づきました。

自分の環境で調べてみたところ、IPv6でコンテナへの接続が行われた場合、以下の図のように2001:db8::1(グローバルアドレス)から172.16.0.1(Dockerネットワーク上のアドレス)への変換が行われ、Docker内ではその変換されたIPv4アドレスを使用して通信をしていました。

![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132408/3d5cfc76-c3b9-a79f-07e4-e85252bebf85.png)

そのため、IPv6で接続した際に取得できる接続元IPアドレスが次のような状態になり、接続元のIPアドレスが取得できなかったようです。

* https-portalコンテナ
  * 接続元は172.16.0.1 (変換後のIPアドレス)
* webコンテナ
  * 接続元は172.16.0.2 (https-portalのIPアドレス)
  * X-Forwarded-Forは172.16.0.1 (変換後のIPアドレス)

# 対策案
## Dockerのデーモンを--ipv6を付けて起動するようにする
「docker」「ipv6」の2つで検索すると一番最初に見つかったのがこのオプションでした。

試していないのですが、調べた限りDockerのIPv6周りは「IPv6ならコンテナそれぞれに固有のIPアドレスを割り振って直接接続すればいいじゃん」という思想のようで、IPv4のようにNATされることはないみたいです[^1]。そのため、--ipv6オプションを指定しても、コンテナにIPv6アドレスの割当が行われるようになるだけで、IPv4のようにホストのIPv6アドレスに接続したらコンテナともIPv6で通信できるわけではないようです。

[^1]: 数年前にIPv6もNATして欲しいと要望が出されてはいるみたいですが、数年前に出されて未だに実装されていないことを考えると、だいぶ優先度は低そうです。

また、仮にこの方法でIPv6対応するとしても、最低でも/80(MACアドレス64bit分)のサブネットワークが必要みたいでした。自分が今使っているさくらのVPSだと、契約ごとにグローバルIPv6アドレスは1つしか付与されません[^2]。そのため、この方法は実現が難しそうでした。

[^2]: 蛇足ですが、追加料金を支払うとIPアドレスが追加で付与される、みたいなサービスもこのVPSには無いようです。

## 自分でNATする
自分でIPv6をNATすればIPv6アドレスが1つだけでも対応できそうですが、めんどくさいのと、管理が煩雑になりそうなためこれはやめておきました。[^3]

[^3]: [このあたり](http://fmscb.fumi2kick.com/mastodon/docker_ipv6.md)を参考に[robbertkl/docker-ipv6nat](https://github.com/robbertkl/docker-ipv6nat)を使えば自分ですべて構築するよりは楽に済みそうです

## Docker上ではなく、ホストにリバースプロキシを設置する
ホスト上にリバースプロキシを設置すれば、Dockerの制約は受けないので、IPv6で接続してもIPアドレスを取得できるようになると思います。恐らく、X-Forwarded-ForでIPv6アドレスを渡すようにすれば、コンテナ側でも接続元IPアドレスを取得できるようになると思います。

ただ、せっかくいろいろコンテナ化してるのに、サーバ上にコンテナ化してないサービスを置くのはなんだかなぁという気がするので、今回は見送りました。

## IPv6での接続をあきらめる
今のところはIPv6でしか通信できないなんて環境はないだろうから、早急に対処する必要もないかなあということで、今回はこの方法を取りました。

気が向いたら何らかの方法でIPv6でも見れるようにしようと思います。
SQLの様々な関数

# プログラミングの勉強日記
2020年6月15日　Progate Lv.107
SQLⅡ

##DISTINCT
　検索結果から重複するデータを除くことができる。`DISTINCT (カラム名)`として使う。SELECTで取得するカラムに使用することで重複を省いたデータを取得できる。

```sql
SELECt DISTINCT (name) FROM purchases;
```

##四則演算
　足す(+)、引く(-)、かける(*)、割る(/)ことができる。四則演算をSELECTで取得するカラムに使用することで計算後のデータを取得できる。

```sql
SELECT name, price*1.1 FROM purchases;
```

##SUM関数
　数値の合計を計算するときに使う。SELECTで取得するカラム名を使用することで集計結果を取得できる。WHEREとも併用できる。（今回の例では、田中太郎のレコードを検索して、検索したレコードの数値の合計を計算している。）

```sql
SELECT SUM(price) FROM purchases;
SELECT SUM(price) FROM purchases WHERE name="田中太郎";
```

##AVG関数
　平均を計算する。SELECTで取得するカラムに用いることで計算結果を取得できる。WHEREと併用することもできる。（今回の例では、田中太郎のレコードを検索して、検索したレコードの数値の平均を計算している。）

```sql
SELECT AVG(price) FROM purchases;
SELECT AVG(price) FROM purchases WHERE name="田中太郎";
```

##COUNT関数
　指定したカラムのデータの合計数を計算する。<font color=blue>COUNT関数でカラム名を指定した場合、nullになっているデータの数は計算されない。</font>nullのデータを含めてすべてのデータの数を計算したい場合は、COUNT関数で`*`（すべてのカラム）を指定する。WHEREを併用することもできる。（今回の例では、田中太郎のレコードを検索して、検索したレコードの数を計算している。）

```sql
SELECT COUNT(*) FROM purchases;
SELECT COUNT(*) FROM purchases WHERE name="田中太郎";
```

##MAX/MIN関数
　MAXを使うと指定したカラムのデータの中から最大のデータを取得することができる。MINを使うと最小のデータを取得できる。他の集計関数と同様にSELECTで取得したカラムに使用できる。WHEREと併用することもできる。（今回の例では、田中太郎のレコードを検索して、検索していたレコードの中でも最も大きい数値を取得している。）

```sql
SELECT MAX(price) FROM purchases;
SELECT MAX(price) FROM purchases WHERE name="田中太郎";
```

##GROUP BY 
　データをグループ化できる。集計関数を取得するFROMの後ろに`GROUP BY カラム名`を追加する。
　<font color=blue>GROUP BYを用いる場合、SELECTで使えるのはGROUP BYに指定しているカラム名と集計関数のみ。</font>
　複数のカラム名を適用させるときは、カラム名同士を`,`（コンマ）でつなげる。その場合、データの組み合わせの数だけグループができ、集計関数によって各グループごとにデータを集計できる。また、WHEREと併用することもできる。その場合は、WHEREの後に書く。

```sql
SELECT SUM(price), purchased_at 
FROM purchases 
GROUP BY purchased_at;
```

###HAVING
　GROUP BYでグループ化したデータをさらに絞り込みたいときに使う。`GROUP BY カラム名 HAVING 条件`とする。

1. 検索 WHERE
2. グループ化 GROUP BY
3. 関数 COUNT, SUM, AVG, MAX, MIN
4. HAVING 
　
　この順番で処理される。WHEREはグループ化される前のテーブルの全体を検索対象とするが、HAVINGはグループ化されたデータを検索対象とする。なので、<font color=blue>条件文で使うカラムは必ずグループ化されたテーブルのカラム名を使う。</font>
ARCore+Manomotionでお手軽ハンドトラッキングon Android

#はじめに
ARcore or ARkitと組み合わせることで簡単にAR上でハンドトラッキングが可能なManoMotion。
バージョン1.2まではYoutubeなりサイトなりに導入の解説があるのに今配布されてる最新のv1.3は構成とか色々違うし結構ちゃんと動くまでかかったので自分用のメモ用にこの記事を作成しました。
#目標
ManoMotionのサンプルを動かす
#環境
Unity 2019.3.15f1
manomotion Lite v1.3(ハンドトラッキングSDK)
Pixel 3a (Android 10)

#準備
##Manomotionのサイトに登録
[公式サイト](https://www.manomotion.com/)
SDKの使用には登録が必要です。といってもメアドと名前と用途を入力するだけ。
Get Startedを押せばProductのページに飛べる。
##ライセンスを確認
登録が済んだらいったんMyAccountのLicensesを確認。
Application Nameやらライセンスキーやらの情報が現れる。ここの値は後で使うので注意。
##SDKダウンロード
ダウンロードの選択肢は3つありますが即ダウンロードできる真ん中or左を選択。自分は真ん中をダウンロードしました。
SDKの準備はこれで完了
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/ee8eba3a-8ebf-b91d-43cb-c97128e65675.png)

#Unityで環境構築
##新規プロジェクトを作成
3Dで作成する
##必要なパッケージをインストール
必要なパッケージは以下の通り
AR Foundation
ARCore XR Plugin
Multiplayer HLAPI
XR Legacy Input Helper

あと今回特有の話ではないけどバグ探索のためにAndroid Logcatなんかも入れとけば便利ですよね。

##SDKをimport
Assets->Import Package->Custom PackageからダウンロードしたManoMotion SDKを選択してインポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/321cbd25-2765-0144-cd12-6974a0f5bd07.png)

##サンプルシーンを選択してライセンスキーを登録
今回使うサンプルシーンはプロジェクトウィンドウ内の
Assets->ManoMotion ARFoundation->Scenes->ManoMotion SDK ARFoundation Features.unity
にあります。このあたりv1.2から構成が変わっててましたね、、
シーンを開いたらヒエラルキーウィンドウ内でManoMotion Manager を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/34fd0f0c-2f49-4a27-7475-167ab3c3bf82.png)

インスペクターをウィンドウの中にManoMotion Manager->License Keyの項目があるのでそこに先ほどManoMotion公式サイトで登録した際に取得したライセンスキーを貼り付ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/9adf0d9b-cf6e-0fda-87ac-64bee65613b9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/f04792ec-2a34-c032-92b2-5542c8bfca98.png)
終わればあとはビルドするだけ！！
##ビルドセッティング
このSDKのDiscordとかのぞいたらみんなビルド環境で結構躓いていた印象、、
File->Build Settingsを開いてPlatformでAndroidを選択後にSwitch Platformを押す。
その後、Player Settingsを開く
カンパニーネームは適当でいいのでProduct Nameのところを公式サイトのLicensesページのApplication Nameを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/e1ba771b-867f-c4f4-caa8-8293a5f13259.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/188f534c-836c-7d51-5bd9-ba3d8e4cdf42.png)

その後、Other Settingsを開く。ここでの変更内容は以下の通り

・Graphics APIsからVulkanを削除
・Multithreaded Renderingのチェック外す
・PackageName -> ManoMotionの自分のアカウントページのライセンスキーに載っているものを貼り付け
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/1f24e027-2dbe-0f7b-3b9b-e7f9c6bea763.png)
・Minimum API -> Android 7.0
・target API -> Automatic
・Scripting Backend -> IL2CPP（Monoじゃないよ！！）
・Api Compatibility Level -> .NET Standard 2.0
・Target Architecture -> ARM64にチェック

※注意・・・ARCoreを使うとき必ずチェックしているXR settings-> ARCore Supportedはチェックしない

#動かす
以上のことを設定してビルドすれば動くはずです。(汚い手ですみません)
![20200614_015155_exported_25133_1592149425610.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506489/fa282f36-65e7-719f-93c1-da3fddb39a82.jpeg)
Oculus QuestでWebXRを使ったVRアプリを実機テスト。

はじめに
=====
ついに念願のOculus Questを手に入れました。
さっそくVR開発に取り組んでみようと思ったら、どうやらWebXRというものがあるそう。
Three.jsを使ったので導入は簡単でしたが、実機テストするのにひと手間かかったのでメモを残しておきます。

WebXRの制約
=====

- [Porting from WebVR to WebXR](https://developer.oculus.com/documentation/oculus-browser/browser-vr-xr/)

上の記事によると、WebXRはhttps接続下でしか動作してくれないようです。
これでは実機デバッグが難しいですね。
自分は最初、コードを書き換える->Netlifyに上げる->実機テストという手順を踏んでいたので大変面倒でした。

adbを使えばできるらしい。
=====
より詳しく調べてみると、Oculus QuestのブラウザではlocalhostへのアクセスではWebXRをhttpsなしでつかえる模様。
localhostじゃ開発PCのサーバーにアクセスできないじゃないかと思いましたが、ADBの機能を使えばできるようです。
adbはAndroid Debug BridgeといってAndroidのデバッグのためのツールですが、Oculus Questの中身がAndroidであるため使用可能です。
adbの導入方法については各自調べてください。
Android Studioが入っていればついてきていると思います。

開発者モードの有効化
=====
Oculus Questに対してadbを使うには開発者モードを有効化する必要があります。
Oculusアプリの設定から、開発者モードを有効化してください。

adbのreverseで解決。
=====
開発者モードを有効化したらQuestとPCをUSBケーブルで接続します。

```
adb devices
```

上のコマンドを実行してみましょう。
認識はされていますが、unauthorizedと出ていると思います。
Questの方を見てみると、このコンピューターからのアクセスを許可しますかといったプロンプトが出ているので許可してやってください。
unauthorizedと出なくなったはずです。

さて、準備は整ったのでOculus QuestからPCのサーバーへlocalhostでアクセスできるようにしてあげましょう。
以下のコマンドを実行してください。

```
adb reverse tcp:[サーバーのポート番号] tcp:[サーバーのポート番号]
```

PC側でサーバーを起動した状態で、Quest側のブラウザでlocalhostの指定ポートにアクセスするとサーバーで配信しているアプリが表示されるはずです。
WebXRに対応したアプリであれば、実機テストができるようになっているはずなので頑張って開発しましょう。

まとめ
=====
自分はReact Three Fiberを使って開発を行っています。
次の週末までに何かゲームをリリースできるといいんですが、開発は難航しています…

参考文献
=====
- [Porting from WebVR to WebXR](https://developer.oculus.com/documentation/oculus-browser/browser-vr-xr/)
- [How to easily test your WebVR and WebXR projects locally on your Oculus Quest](https://medium.com/@lazerwalker/how-to-easily-test-your-webvr-and-webxr-projects-locally-on-your-oculus-quest-eec26a03b7ee)
GitHub PagesとGASを経由したGoogle翻訳で翻訳ツールを作る

# 翻訳APIの用意

基本的にはこちらの記事の通り。
[Google翻訳APIを無料で作る方法](https://qiita.com/satto_sann/items/be4177360a0bc3691fdf)

## 一点だけ上の記事と異なる注意点

アクセス可能なユーザを「全ユーザー」ではなく「Anyone, even anonymous」にしないとCORSでひっかかる。

![translate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/5fb98043-48f5-e588-d95b-283c03ddf363.png)

# Webページの準備

GitHub Pages用のレポジトリを作って、htmlとかcssとかjsを用意
参照: [GitHub Pagesで静的サイトを簡単に作る](https://qiita.com/ririli/items/0e06b21cb709beae4514)

APIを叩く時は、XMLHttpRequestを使うよりも、fetchを使った方が楽っぽいです。👍　[まだXMLHttpRequestを使ってるの？　fetchのすすめ](https://qiita.com/uhyo/items/91649e260165b35fecd7)

# 現在動かしてみているページ

https://paper-support-tool.github.io/
英語論文の読み書きを楽にするために作ったもの。

- PDFから文章をコピーした時に便利な機能がいくつかある。
- Grammarlyと兼用するとさらに幸せになれる。
Android開発アプリ_準備編

# テーマ決め
下記のアイデアを出して、”オンライン飲み会の終了時間管理”アプリを選定。

- オンラインジェスチャーゲーム  ×  
  ”VS嵐”の番組で人気のジェスチェーゲームをオンラインでできたら楽しそうと思い発案。
   既存のアプリは1台のスマホを使って行うものだったので、手元のスマホにそれぞれがアプリをダウンロードして行うやり方で考えたが、iPhoneの人がいた場合そちらのアプリ開発も必要なため断念
- 複数人でゴルフに行くときの最適なゴルフ場決定 △  
  趣味のゴルフのいつも迷う問題から発案。複数人でゴルフに行くときに、みんなの移動距離ができるだけ短くなる最適なゴルフ場を決定できるアプリがあればありがたい。しかし、最近ゴルフに行っていないので意欲がわかず断念。
- オンライン飲み会の終了時間管理 〇  
 コロナの影響でオンライン飲み会を行うことが増え、みんながしみじみ感じている問題。
 既存のアプリでは、この機能をもったオンライン会議はあったが、既存のオンライン会議に+αするものはなさそうだったでそのアプローチで作成したい。

# 機能洗い出し
最低限下記の機能を持たせたい。

-  既存のオンライン会議に+α
  -  lineのグループ通話
- 飲み会の時間設定
- 終了30分前にラストオーダのメッセージを投稿する
  -  メッセージをアプリインストール者のアカウントで投稿 or LINEロボットを使う？？
- 終了時刻になったら強制的に終了させる(無理ならメッセージのみ)
  -  lineのグループ通話を終話させる

# 技術調査
機能の技術調査を下記から行った。
[LINE SDK v5.4.1 for Android]("https://developers.line.biz/ja/reference/android-sdk/reference/com/linecorp/linesdk/api/LineApiClient.html")

- アプリからlineのグループ通話にアクセス
  - LineLoginApiのAPIでログインはできそう。
- 飲み会の時間設定
  - アプリ上でユーザから設定で特に問題なし。 
- 終了30分前にラストオーダのメッセージを投稿する
  -  sendMessageToMultipleUsersのAPIで実現できそう
- メッセージをアプリインストール者のアカウントで投稿 or LINEロボットを使う？？
終了時刻になったらlineのグループ通話を終話させる(無理ならメッセージのみ)
  - sendMessageToMultipleUsersのAPIで実現できそう。とりあえずこれで実装して、そのあとグループ終話できるか試す。

 
# 今後の予定
UIはひとまずシンプル路線にして、プロトタイプを実装していく
Netlifyで無料でWebページを公開したい。（無料サーバ）

# Netlifyとは？
Netlifyは、Webホスティングサービスです。静的サイトに限りますのでDBは使えません。

# この記事でやること
タイトルのとおりです！公開した記録をここに書きます。

# 前提条件
- NetlifyでWebページを公開するには、Githubなどの対応したアカウントが必須です。（Github以外にもGitLabなどに対応。この記事ではGithubを利用する前提で話を進めます。）
- この記事では、既にGitHubにリモートリポジトリの作成と、公開できる状態のhtmlファイルがリモートリポジトリへpushされている前提で話を進めます。


# 公開手順
Netlifyへアクセスします。
https://www.netlify.com/

サインアップをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/7b4c54f6-fd40-190b-3c52-2d4f51b83aac.png)

Githubを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/4fcec93d-e519-699a-9511-1296310809bd.png)

Authorizeをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/bcdac1c4-fc4f-ae25-ad16-eee3fcaa6360.png)

New Site from git　をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/23897dc7-aa84-9b11-4e1b-110a608d8995.png)

Githubをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/c71617d9-9f06-3881-696c-732ac71e6306.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/d15058fa-269e-5317-ba71-e9e7a605482e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/a3237847-7235-cce4-371f-65f91d66d5a9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/d49837be-5cde-111d-066b-e6a0a6b1df79.png)


公開するサイトのリポジトリを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/dc725226-8456-15c4-b5ce-f2bbee2ca451.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/1809ae6e-6a97-ae76-b742-26a047168c47.png)


これでデプロイが完了しました。図の赤枠がWEBサイトのURLとなります。
ブラウザからURLへアクセスするとWebページを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/020452f7-0bab-b983-bdc5-f599c9e66c5c.png)

## memo
- Githubにpushすれば自動的に連携して更新してくれる。（netlifyへの独自デプロイとかは不要）
- 独自ドメインで運用する場合は[こちら 【Netlify】カスタムドメインを設定する](https://qiita.com/NaokiIshimura/items/64e060ccc244e38d0c15)が参考になります。（DNS設定の世界への伝播には数時間かかります。）


# デプロイに失敗する。
ディレクトリを含めてgit push するとエラーとなる。


# その他のWEBページ公開関連の無料サービス

- サーバ
    - Github Pages
        - 無料アカウントではprivate Repositryのままで公開できないのが難点。
    - Parse
        - [（Qiita）Parseを使って無料でWebサイトを公開してみよう](https://qiita.com/Ijoru/items/1735dc34d6f36b2ce987)


- 無料ドメイン
    - [無料、有料ドメイン - Freenom](http://www.freenom.com/ja/freeandpaiddomains.html)
  

- DNS
    - AWS Amazon Route53
        - 半日程度（？）ならテスト利用として無料で利用できるらしい。証明書も無料で発行できる。
青空文庫スピーカー

たぶんこれは誰も使わないと思いますが、 [青空文庫](https://www.aozora.gr.jp/) の作品を音声合成で読み上げるブックマークレットを作りました。

```
javascript: (() => { var VOICE_INDEX = 0, RATE = 5.0, VOLUME = 1.0, MIN_WAITING_TIME = 250; var ssu = new SpeechSynthesisUtterance(); ssu.lang = 'ja-JP'; ssu.rate = RATE; ssu.volume = VOLUME; var main = () => { var voices = speechSynthesis.getVoices().filter((voice) => voice.lang === 'ja-JP'); ssu.voice = voices[VOICE_INDEX]; console.info(voices); var mainText = document.querySelector('.main_text').cloneNode(true); mainText.querySelectorAll('rb, rp').forEach((node) => { node.parentNode.removeChild(node); }); var text = mainText.innerText; text = text.trim().replace(/(?:\r\n|\r)/g, '\n').replace(/。/g, '。\n').replace(/\n{2,}/g, '\n'); var lines = text.split('\n'); var speak = () => new Promise((resolve) => { ssu.onend = resolve; setTimeout(() => { speechSynthesis.speak(ssu) }, MIN_WAITING_TIME); }); var play = async () => { for (var i = 0; i < lines.length; i ++) { ssu.text = lines[i]; await speak(); } }; play(); }; speechSynthesis.getVoices().length === 0 ? speechSynthesis.onvoiceschanged = main : main(); })(); void 0;
```

ただし、いわゆる無能ボイスなので、抑揚もないし間違えもするので実用的ではありません。
Macのメジャーブラウザでは動きますが、Windowsでは試していません。また、期待通りに動かない作品もあります。とりあえず [こちらの作品](https://www.aozora.gr.jp/cards/000154/files/42343_50574.html) で試してみてはどうでしょう。

## 仕様
* ルビに対応。つまり振り仮名を優先的に読み上げます
* 「準備（したく）をする」などと括弧内で仮名を振っている文章は「じゅんびしたくをする」などと読み上げられます
* 句点に差し掛かると、いくらか間を持たせるようにしています
* フォントセットにない外字などは画像で表示されているため、無視されます

## カスタマイズ
変数をいじることでいくらかカスタマイズできます。

* `VOICE_INDEX` 声質を選択します。Macではプリインストールされている女性の声と男性の声、Google翻訳をインストールしている環境ではGoogleの用意した声を選択できると思います。それぞれ `0` `1` `2` という感じです。怪談のような作品では `1` の男性の声が合っていると思いますが、環境によっては `0` 以外を選択するとエラーになるかもしれません。  
（ちなみに開発者ツールのコンソールに選択肢を表示しているので、わかる人はそちらをご覧ください。）
* `RATE` 読み上げる速度です。
* `VOLUME` ボリュームです。
* `MIN_WAITING_TIME` 句点（ `。` ）で待機する時間です。ミリ秒で指定してください。

## 開発関係
どうも `speechSynthesis.getVoices()` の返り値が空だったり空でなかったりするので調べたところ、

* `speechSynthesis.onvoiceschanged` を待ってから `getVoices()` すると良い
* ただし Safari では `onvoiceschanged` は呼ばれない。しかし `getVoices()` は必ず成功する

という問題に出くわしました。そこでいったん `getVoices()` して、その返り値が空であれば `onvoiceschanged` を挟み、空でなければ挟まずに処理を続行するようにしています。

【その他の青空文庫用ブックマークレット】
* [青空文庫の闇堕ちブックマークレット](https://qiita.com/mimonelu/items/fac9bc98aee1ea3bf11b)
* [青空一行文庫ブックマークレット](https://qiita.com/mimonelu/items/26288a6347e958f500af)
メモ

クロージャについて勉強をしたので備忘録として残す


APIなどの通信は別スレッドとして処理するため、値が返ってくる前にメインスレッドで値をretrunしていて、空のデータが返ってきてしまうというものです

```swift

func getCat() -> String {

    var str = "初期値"
    
    //非同期処理を行う
    let dispatchQueue = DispatchQueue(label: "Dispatch Queue", attributes: [], target: nil)
    dispatchQueue.async {
        //適当にちょっと重たい処理
        for i in 0 ..< 1000{
            if(i == 999){
                str = "にゃんこ"
            }
        }
    }
    return str
}

//関数を使ってみる
print("getCat:\(getCat())")　　　　　//getCat:初期値
```
上記の例だとメインスレッドでretunrを返してしまって欲しい値が取得できない。
流れ
①dispatchQueue.asyncで分岐される
②メインスレッドでreturnされる
③呼び出し元のgetCatでは初期値として文字が出力される
④その間にもサブスレで処理が動いている
そういう時にcompletionを使用する

```swift

func getCat(_ after:@escaping (String) -> ()){
    var str = "初期値"
    
    //非同期処理を行う
    let dispatchQueue = DispatchQueue(label: "Dispatch Queue", attributes: [], target: nil)
    dispatchQueue.async {
        for i in 0 ..< 1000{
            if(i == 999){
                str = "にゃんこ"
            }
        }
        after(str)
    }
    print("先にこっちが呼ばれる\(str)")   //str = "初期値" のまま
}

//関数を使ってみる
getCat({ str in
    print("getCat:\(str)")         //getCat:にゃんこ
})
```

返り値はcompletionとしていてクロージャーないで完結しているのでさメインスレッドで先に値を返してしまう
可能性がありません。
completionで処理が完了するのを待機してます。
終わったらcompletionとして値を返して
呼び出しもので使用したい値が取得できている
流れ
①dispatchQueue.asyncでスレッドが分岐する
②メインスレッドでprintが呼ばれる
③クロージャー内でafterが処理の完了を待機している
④処理が終わったらafterを返り値として呼び出し元に帰ってきて欲しい値がつかえるようになる

API実行時のURLSessionは非同期で実行されるのでその中での返り値が必要な時などに有効

URLSessionまで処理はメインスレッドとして返り値が戻ってくるが
それ以後の処理ではサブスレで帰ってくるので
戻り値でインジケータ非表示にする処理があるのであればメインスレッドで囲ってあげる必要がある
SSL/TLSについて調べたことまとめ

「SSL/TLSってなんやねん」ってなったので少し調べてまとめた。

## SSL
SSL(Secure Socket Layer)は暗号化と認証の機能を提供するプロトコル。具体的には、改竄の検出、デジタル証明書を使って、サーバ/クライアント認証を行う。

## TLS
TLS（Transport Layer Security）はSSLの後継のプロトコル。それぞれは独立したプロトコルであるが、同列に扱われることも多く、その場合SSL/TLSと表記されることが多い。Qiita(qiita.com）ではTLS１.２が使われている。

以下に、SSL/TLSに則ったクライアントとサーバーの通信の手順に従って、まとめた。

### 1. サーバーは公開鍵の正当性を証明するために、認証局に登録申請を行う
サーバーは認証局に対して、公開鍵を提出し、証明書の発行を依頼する。

#### 認証局（CA,Certificate Authority)
* デジタル証明書を発行する実体である。
* 証明書の発行サービスに課金する商用CAは多い。政府などではCAを独自に立てていることもある。

##### ルート認証局
* 自分の正当性を自身で証明し、他の認証局へ証明書を発行する最上位の認証局。このためルート認証局として認められるためには厳しい審査を受ける必要がある。

##### 中間認証局
* ルート認証局等上位の認証局より信頼を受ける事で、自身の正当性を証明する。
* 中間認証局の中には、ルート認証局に繋がれている中間認証局に「信頼を受ける」と言う「信頼の連鎖」で繋がれている場合もある。

#### PKI(Public Key Infrastructure)
* 公開鍵基盤とも呼ばれる公開鍵暗号方式を利用した認証および、盗聴防止基盤のこと。

PKIによって第三者期間である認証局(CA)が、デジタル署名を利用したデジタル証明書を発行し、公開鍵が正当な送信者のものであることを保証する。

### 2. 認証局がサーバーに対して、デジタル証明書を発行する
* 認証局は提出された申請書類に基づいて、公開鍵の所有者の本人性を審査し、証明書を発行する。
* デジタル証明書には、公開鍵、所有者の情報などとともに認証局のデジタル署名が付加されている


**ここからは実際にHTTP通信が行われる流れ**


### 3. クライアントがサーバーに接続すると、サーバは認証局の署名付き証明書を返信する


### 4. クライアントは証明書が本物であることを確認する
* クライアントは、証明書を認証局の公開鍵で復号し、デジタル証明書内の情報と認証局の署名を確認する

#### 利用される暗号の種類
* Qiita(qiita.com)では公開鍵暗号の一つであるRSAが利用されている。(ブラウザのアドレスバーの鍵マークから確認)
* これ以外にもサポートされている公開鍵暗号はある。

証明書が正当なものであると確認すると、以下の作業に移る。

### 5. クライアントは乱数を発生させ、サーバの公開鍵で暗号化してサーバーに送る
* この乱数は実際にHTTP通信を行う際の鍵を作ることに利用される。


### 6. サーバーは秘密鍵で、暗号化された乱数を復号する。
* 公開鍵暗号方式を利用して、サーバーは自身の秘密鍵で乱数の復号を行う。


### 7. サーバとクライアントで共通鍵を使って暗号化通信を行う。
* サーバとクライアントの双方で、マスターシークレット（MS)と呼ばれる鍵を生成し、このMSから生成した共通鍵を使って暗号化通信を行う。
* サーバーとクライアントが実際のデータの送受信を行う際には、共通鍵暗号を利用する。
* このとき、この乱数から2種類の鍵を生成し、「クライアント→サーバ」と「サーバー→クライアント」で異なる鍵を用いる。

## まとめ
ざっくりだが、以上の手順を経てHTTP通信が開始される。細かいことはこれから勉強しなければ。
SQL 第2版 ゼロからはじめるデータベース操作を一通り読んでみて

## はじめに
今回SQL 第2版 ゼロからはじめるデータベース操作という本を読みました。

####本の紹介
> プログラミング学習シリーズ『SQL ゼロからはじめるデータベース操作』は、「データベースやSQLがはじめて」という初心者を対象に、プロのデータベース（DB）エンジニアである著者がSQLの基礎とコツをやさしく丁寧に教える入門書です。
DB／テーブルの構造から、データを検索したり更新したりする構文、よく使う関数、テーブルの結合など、SQLによるデータベース操作の基本を学習していきます。WHERE句、GROUP BY句、HAVING句やサブクエリなど、SQLを使いこなすためのポイントとなる機能や、初心者にとって理解が難しい部分は、豊富な図とサンプルプログラムでかみくだいて解説しています。
また、標準SQLをベースに、各種DB（Oracle、SQL Server、DB2、PostgreSQL、MySQL）での違いや、初心者がハマりやすいポイント、基礎ノウハウについてもしっかり解説。
第2版では、解説・サンプルコードを最新DBのSQLに対応したほか、（PostgreSQLを例に）アプリケーションプログラムからSQLを実行する方法の解説章を新設。SQLの書き方だけはなく、アプリケーションでの利用方法までフォローします。
データベースを扱うアプリを作りたいが何から学習すれば良いかわからない、きちんとSQLを書けるようになりたい、現場で通用する基礎を身につけたい、という方におすすめの1冊です。https://www.shoeisha.co.jp/book/detail/9784798144450

今回はこの本を読んだ感想を述べます。

とその前に、なぜこの本を読もうかと思ったのか?

また、なぜDBについて勉強しようと思ったのか？

こちらは、現在 Ruby On Rails でのWebアプリケーション開発業務に携わっています。

開発経験が乏しいのですが、プロジェクトに積極的にアサインしていただいて本当に感謝です。

その中で、絞り込みの検索をかける実装をしたときに、Rubyのコードだけでは難しく、SQLを書く必要がでました。

そのときSQLについては[プロゲート](https://prog-8.com/languages/sql)で2週くらいやった程度でした。

プロゲートはとても初心者に対して優しく、とっつきにくいプログラミング言語でもすごく優しく分かりやすいサービスなので、当時の自分には丁度良かったのです。

ただ、自分でデータを作って動かしているというよりかは、用意されたものを順番にやっていくだけなので、あまり壁にぶつからず、しっかり覚えたという感じではなかったです。

なので業務で問題が発生したときに、全く太刀打ちできませんでした。

その時に、大尊敬している会社の先輩から「もう少しSQLの知識を身につけたほうがいいんじゃない?」と言われ、素直にSQLを学んでみたいと思いました！！

だって、「もしかしたらそのSQLを理解できるようになったら、その先輩に少しでも近づけるんでしょう？？」と思ったからです。

それで色々Qiitaの記事や、DBの書籍などを色々調べた結果、この本に出会いました。

## 実際にやってみて

まずDBにはオラクル、MySQL、PostgreSQLなど色々あるんだな〜と思いました。(そこからっ！！笑)

また業務でもコードとログをしっかり見て、何のデータを取り出そうとしているのかや、何をしようとしているのかがかなり見やすくなりました。

この部分はこの本を読んでかなり大きいと思いました。

今ではログを見るのが楽しいとさえ思えます。(笑)

また、PostgreSQLをインストールするところも良い点だなと思いもいました。

会社ではMySQLを使ってますが(汗)

理由は慣れないデータベースを一から構築することで、壁にぶつかりながら、その度に色々調べ、一からデータベースというものを触る間隔を味わえたからです。

入りとしてはプロゲートは最高なのですが、実感が薄いというネックがありました。

今回は本当に実感を持って、データベースと向き合えて良かったです。

## 今後は

こちらの本のミック氏が書いている、「[達人に学ぶDB設計 徹底指南書](https://www.shoeisha.co.jp/book/detail/9784798124704
)」もかなり高評価なので、こちらの書籍をすでに購入しました。

ただし、やはり基本がおろそかになるのは良くないので、本書で復習も進めていこうと思います。

特に、viewの部分やサブクエリの部分がまだ難しいので、そちらも早くマスターしたいです。

## 目次
本書でどのようなことを学べるのか目次を書きます。

また別のブログにて、実際のコードをまとめました。

ただあくまでも一覧なので、詳しい内容は本書を手に取ってみてください。

第0章　[イントロダクション―SQL学習環境を作ろう](https://qiita.com/nyan_tech_24/items/bdccf05ef7a0619b3c44)
第1章　[データベースとSQL](https://qiita.com/nyan_tech_24/private/7eef20128e227418c94d)
第2章　[検索の基本](https://qiita.com/nyan_tech_24/private/e8e22b928936b1605409)
第3章　[集約と並べ替え](https://qiita.com/nyan_tech_24/private/cad6ac5d8e63ad317403)
第4章　[データの更新](https://qiita.com/nyan_tech_24/private/9ad6e33d914dd341a764)
第5章　[複雑な問い合わせ](https://qiita.com/nyan_tech_24/private/739aff1edfc4239ca98c)
第6章　[関数、述語、CASE式](https://qiita.com/nyan_tech_24/private/0dcbd1617b6af4284284)
第7章　[集合演算](https://qiita.com/nyan_tech_24/private/206a634e184f7a43750d)
第8章　[SQLによる高度な処理](https://qiita.com/nyan_tech_24/private/c115682de69aa1ee2941)
第9章 アプリケーションからデータベースへ接続する
付録　練習問題の解答
[Scratch3.0×ev3×WeDo2.0]   ev3のモーターをリモコンとして使い、WeDo2.0のモーターを制御する

この記事はev3でWeDo2.0を操作してみたい人のための記事です。
今回はev3のモーターをダイヤル式のリモコンとして使い、WeDo2.0のモーターを遠隔操作してみます。


#目次
0 . 用意するもの
1 . スクラッチとev3をつなげよう
2 . スクラッチとWeDo2.0をつなげよう
3 . プログラムをつくろう

#0.用意するもの
◯ パソコン(スクラッチ)
◯ モーターが1つついたev3
◯ WeDo2.0のモーター１つ




#1.スクラッチとev3をつなげよう
わからなければ[前回の記事](https://qiita.com/masterkeaton12/items/0decbcce73e4f04354c4)をみてください！


#2.スクラッチとWeDo2.0をつなげよう
わからなければ[以前の記事](https://qiita.com/masterkeaton12/items/df4634deb84b23b3aeb3)をみてください！



#3.プログラムをつくろう
###◯ev3のモーターの回転角をWeDo2.0のモーターパワーにするプログラム

#####Step1 : ev3のモーターの回転角を取得する
**ある時点でのモーターの回転角**
と
**その0.5秒秒後のモーターの回転角**
を取得してその差分をとると、
0.5秒間でどれだけ回転したかがわかる。
![スクリーンショット 2020-06-15 0.41.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654004/e122b424-7b1e-fa23-83fe-1897d42ea0e0.png)


#####Step2 : 回転角に応じて場合分けする
**3 < 回転角 の場合** : 回転角(の2倍)をパワーにしてこちら向きに回転させる
**-3 < 回転角 <= 3 の場合** : ほぼ回っていないとみなして回転を停止する。
**回転角 <= -3 の場合** : 回転角(の2倍)をパワーにしてあちら向きに回転させる

![スクリーンショット 2020-06-15 0.03.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654004/328f7a3c-49fa-edfa-629a-65c8018e8e08.png)

**フレームの幅や、モーターの回転角を何倍にするかは自分で調整してみてください！！**







#最後に

読んで頂きありがとうございました！！
今回はev3からスクラッチを経由してWeDo2.0の操作をしました。
逆に、WeDo2.0のチルトセンサなどで、ev3のクルマやロボットアームなどを動かすことももちろん可能です！
ぜひ色々なチャレンジをしてみてください！

より良い記事にしていきたいので
　◯こうした方がわかりやすい
　◯ここがわかりにくい
　◯ここが間違っている
　◯ここをもっと説明して欲しい
などのご意見、ご指摘のほどよろしくお願い致します。
Reactで桁数チェックを実装してみた

##はじめに
Reactを使って桁数チェックサンプルを作ってみました。
このサンプルは言い換えると、"独自のイベント(チェック機能)をコンポーネントに組み込む"
ということになります。サンプルコードを記載してますが、忙しい方は
次項の前提がそろっていればコピペで動作確認もできます。

##前提
・Node.jsをインストールしている
・npm(パッケージ管理ツール)でプロジェクトを作成している
(npm init react-app プロジェクト名)
・プロジェクト作成後に/public/index.htmlと/src/index.jsは編集していない
(=プロジェクト作成初期状態である)

##サンプルで実現できること
テキストボックスに6文字以上入力しようとした
場合にアラート表示される

##コードサンプル
/src/App.js

```react

import React, { Component } from 'react';
import Rect from './Rect';
import './App.css';

class App extends Component {

  //css用のプロパティは何でも構いません
  msgStyle = {
    fontSize: "20pt",
    color: "#900",
    margin: "20px 0px",
    padding: "5px",
  }

  //イベント(alertError)をバインドしておく
  constructor(props) {
    super(props);
    this.state = {
      message: "type your message"
    };
    this.alertError = this.alertError.bind(this);
  }

  //桁数チェックに引っかかった時に呼び出される
  alertError(event) {
    alert(event.target.value + "は長すぎます(最大5文字)");
  }

  //初期表示のレンダリング
  render() {
    return <div>
      <h2>{this.state.message}</h2>
      <Message maxlength="5" digitError={this.alertError} />
    </div>;
  }
}

class Message extends Component {
  
  //css用のプロパティは何でも構いません
  inputStyle = {
    fontSize: "12px",
    padding: "5px"
  }

  //イベント(doCheck)をバインドしておく
  constructor(props) {
    super(props);
    this.doCheck = this.doCheck.bind(this);
  }

  //桁数のチェックを実行
  doCheck(e) {
    if (e.target.value.length > this.props.maxlength) {
      this.props.digitError(e);
      e.target.value = e.target.value.substr(0, this.props.maxlength);
    }
  }

  //Appコンポーネントから呼び出される
  render() {
    return <input type="text" style={this.inputStyle} onChange={this.doCheck}/>
  }
}

export default App;
```

##コードサンプルを順に見ていく

①コンポーネントタグで子コンポーネントの呼び出しをしています。
Messageコンポーネントの属性値(maxlength,alertError関数)がpropsオブジェクトで渡されます。

```react

  //初期表示のレンダリング
  render() {
    return <div>
      <h2>{this.state.message}</h2>
      <Message maxlength="5" digitError={this.alertError} />
    </div>;
  }
```

②イベントハンドラ(onChange属性)には値を関数で渡します。ここでは、
同じコンポーネント内に定義しているdoCheck関数を渡してます。
※JSXではイベント属性をキャメルケースで書きます

```react
  //Appコンポーネントから呼び出される
  render() {
    return <input type="text" style={this.inputStyle} onChange={this.doCheck}/>
  }
```

③引数のeはイベントオブジェクトを指してます。
サンプルでいうと、②で見たinputタグのことです。
入力したテキスト値が最大値を超えた場合、親コンポーネントに定義した
digitError関数を呼び出します。

```react
  //桁数のチェックを実行
  doCheck(e) {
    if (e.target.value.length > this.props.maxlength) {
      this.props.digitError(e);
      e.target.value = e.target.value.substr(0, this.props.maxlength);
    }
  }
```

④引数は③で見たイベントオブジェクトを受け取ります。
ここではシンプルにアラート表示だけしてます。

```react
  //桁数チェックに引っかかった時に呼び出される
  alertError(event) {
    alert(event.target.value + "は長すぎます(最大5文字)");
  }
```

##まとめ
通常のjsだと簡単に書けますが、Reactを使うとなると急に難しくなった感じがしますね。
「JSXのイベントハンドラで関数呼び出しをして処理をする」これだけ分かればいいかと思います。
今回のイベント処理はあくまで1例です、他にも書き方はたくさんあります。
私自身Reactは勉強中なので、色々と試していこうと思います。
ABC170の復習

AtCoder、2回目参戦。
そして、**記念すべきQiita初投稿！**（ぱちぱちぱち）
昨日の初回参戦の反省をnoteに投稿したらめちゃくちゃ反応薄くて、これは畑違いだなと思ったのでQitta作りました。なんならMarkDownちゃんと書くのも初めてです。

AtCoderの反省と復習の記事を上げていこうと思います。

昨日の東京海上日動のコンテストは、

- A：3文字どこから取ってもいいのにわざわざ乱数を発生させる
- B：longをintで置いてオーバーフロー
- C：計算量の考慮の概念を初めて知る

となかなか散々な結果だったのですが、今日は一応Cまで通せました。Dでやっぱり躓いた、計算量……。（といいつつWAも出てる。うーん。）
とりあえずA～Dの反省。

# A問題：Five Variables
０になってるところのindexを抜き出しましょうね～、というもの。
5回ループで回して==0のときにbreakした。

# **B問題：Crane and Turtle**
つるかめ～。
最初の方針は連立方程式解いて、それぞれの解が0以上の整数になるかのチェック。
整数チェックの実装が分からなくて調べた。
**doubleで置いたものをintにキャスト→前後で値が変わらなければ整数**、で実装した。
なるほど。これからも使いそう。
ただ、どこかが上手くいってなかったのか一つだけWAが取れなかった。

ので結局全探索。上限が100だったから全然余裕でしたね（多分）
けどこの段階で45分経過。方程式どこが間違ってたんだろ……。
見切り付けて、別の方針で潔く実装するのも大事ってことを教訓にします。

#C問題：Forbidden Test
解説PDF～！w

-  for文のカウンタiを絶対値にして、x-i,x+1を計算  
- 数列のlistに含まれてなかったらbreakで抜ける

って実装にした。
カウンタの制約を考えるのが面倒でとりあえず1000にしてしまったけど、xが0~100ってことは最大でも51？にしとけばいいのでしょうか。
拾い忘れると怖いのでとりあえず大きくしとけ精神、どこかで痛い目見そう～。
最初、カウンタの初期値を1にしてしまっていて、一度WAを出してしまいました。絶対値0でもよいんですもんね。問題文をちゃんと読もう。

# D問題：Not Disible
素数の列挙をすればよいのは分かった。けど、愚直に実装しすぎて実行に時間がかかるやつ。
そもそもいくつかWA出てたから駄目なんですけどね………。
素数の列挙では、エラトステネスのふるいという考え方があるらしい。後で調べよう。。。

解説配信での実装は、

- 0埋めした配列を用意しておいて、**数列の要素の倍数のところに++していく（倍数チェック！）**

- 2以上のときはなにかしらで割り切れるので、その個数を数える

というもの。なるほどなあ。
ただ、計算量抑えるための細かい実装はよくわかってないので要復習。

ちなみに、実際に出した実装は、

- 配列をリストに入れ直してsort、昇順でfor文回す
- 割る方の数が割られる数の1/2を超えたらbreakする

これ、同じ数字が複数あるときのこと考えられてないじゃん……。こりゃWA出るわけだな。
お名前.com同士でドメインを譲渡（移管）するには

ホームページ業者が取得・管理していたドメインを、自社で引き取ることになった。
双方とも `お名前.com` を使っていたため、**お名前ID付け替え**でドメインを譲渡する手続きを採ったので手順を残す。

# 空アカウントの作成
https://account.onamae.com から移管用の空アカウントを作成する。
空アカウントの**お名前ID**と**パスワード**を先方にお伝えし、会員情報設定の**お名前ID付け替え**より、対象ドメインについて、空アカウントのお名前IDに付け替えていただく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/0ea87964-f4d5-b2e8-fc16-b758f789c6d4.png)
自動更新設定中のドメインは付け替えできないため、事前に解除してもらうこと。
先方に依頼することはこれだけだ。

# 空アカウントでログイン
空アカウントでログインすると、所有ドメインが追加されているのが確認できるだろう。
これを再度、本来の運用アカウントに付け替える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/10decf06-5747-02ff-f1c1-93640a7c382b.png)
このように空アカウントを経由することで、パスワードを開示せずとも安全にドメインを受け渡すことができる。
もう空アカウントは必要ないので、速やかに削除（解約）した方が良いだろう。

# 本来の運用アカウントでログイン
付け替え時に自動更新が解除されているので、必要に応じて自動更新を再設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/250688d5-ac69-68f9-f5f2-0755e2f6b27b.png)

# 登録者名義の変更
以前の登録者情報が残っているので、フォームから名義を修正し、申請する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/b0a1f674-0309-9029-dd6e-e537da93be29.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/cd8b6986-6cf2-360b-77e0-d26646393a54.png)

以下のようなメールがシステム管理担当者宛に届くので、記載のURLにアクセスし、承認ボタンをクリックする。

```:メール
ドメイン名..................：example.com
承認期限日..................：2020年6月9日
───────────────────────────────────
お名前.comをご利用いただき、まことにありがとうございます。

上記ドメイン名の登録者名義変更につきまして、ドメイン登録者様の
承認手続きをお願いいたします。上記承認期限日までにお手続きいただけない
場合は本登録者名義変更は自動的にキャンセルとなります。

1. 下記URLへアクセスしてください。
https://transfer-domain.jp/domain/xxxxxxxxxxxx

2.詳細をご確認の上、『承認』ボタンまたは『否認』ボタンをクリックしてください。
```

# Whois情報の変更
Whois情報も忘れずに変更しておこう。
Whois情報に不備がある場合、登録抹消や使用停止の対象となることがある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/00e471bf-64ba-1250-a574-5b2abb08ecd1.png)

# メールアドレスの有効性認証
Whois情報に設定されているメールアドレス宛に、以下のようなメールが届く。
期日までにURLへアクセスし、認証を完了すること。

```:メール
本メールはICANNのWhois情報正確性確認方針に基づき、レジストラより
ドメイン名の登録者（Registrant）にご登録いただいているメールアドレスへ
送信しております。

ドメイン登録者情報のメールアドレスとして情報が正しい場合は、期日までに
以下URLへアクセスしてください。

対応期日：2020年6月16日 22:05
https://www.onamae.com/domain/xxxxxxxxxxxx
ドメイン情報認証のお手続きが期限内に行われない場合、該当ドメイン
を利用したホームページの閲覧や、メールの送受信ができなくなります
ので、必ずお手続きをお願いいたします。
```

以上で移管は終わり。
これで Microsoft 365 等のドメイン追加も自社のタイミングで行なえる。

# お名前.com 公式サイト情報
- [ドメインサービスのご契約について](https://www.onamae.com/guide/p/32)
- [お名前IDを付け替えた場合に付け替え先に引き継がれる情報を教えてください](https://help.onamae.com/answer/7896)
[rspec] ユーザーモデルのemailのテストが通らない(case_sensitive: false)

##前提

```Rails 6.0.3.1```
```ruby 2.6.3```
```RSpec 3.6```

##一意性のテストにて
メールアドレスのバリデーションを```RSpec```でテストをしていました。
以下がバリデーションです。


```


validates :email, presence: true,
 length: { maximum: 255 },
 format: { with: VALID_EMAIL_REGEX },
 uniqueness: { case_sensitive: false }

```

今回引っ掛かったのが、ここ。

```app/models/user.rb

 uniqueness: { case_sensitive: false }

```

下記が、メールアドレスの一意性を確かめるテスト内容になります。

```spec/models/user_spec.rb
it "is invalid if email is not uniqueness  " do
   duplicate_user = @user.dup
   duplicate_user.email = @user.email.upcase
   @user.save!
   expect(duplicate_user).to be_invalid
end

 it "confirm email is saved in lowercase" do
   @user.email = "Test@examplE.coM"
   @user.save!
   expect(@user.reload.email).to eq 'test@example.com'
end  
  
```


###そもそもcase_sensitive: falseをきちんと理解していなかった



[Active Record バリデーション](https://railsguides.jp/active_record_validations.html)
リファレンスを参照してみると、
 ***"大文字小文字の違いを確認する制約をかけるかどうかも定義"***
とありました。
ちなみにデフォルトでは、```true```となっていますが、一部のデータべースでは大文字小文字を区別しない設定となっているため、rails側でオプションとして```case_sensitive: false```を指定してあげるということみたいです。

##エラーをみてみる

```terminal
Failures:

  1) User email confirm email is saved in lowercase
     Failure/Error: expect(@user.reload.email).to eq 'test@example.com'
     
       expected: "test@example.com"
            got: "Test@examplE.coM"
     
       (compared using ==)
     # ./spec/models/user_spec.rb:91:in `block (3 levels) in <main>'
     # -e:1:in `<main>'

Finished in 3.27 seconds (files took 2.25 seconds to load)
33 examples, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:88 # User email confirm email is saved in lowercase
```

期待していたのは、```"test@example.com"```ですが、得られた結果は``` got: "Test@examplE.coM"```だよと言っています。

要は、**大文字が混ざっていても、それを小文字に変換する処理が起きていない状態**ですね。

そのため、```小文字に変換する処理```を追記してあげます。

```app/models/user.rb

class User < ApplicationRecord
#追記
  before_save { email.downcase! }

VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

#中略

validates :email, presence: true,
 length: { maximum: 255 },
 format: { with: VALID_EMAIL_REGEX },
 uniqueness: { case_sensitive: false }

#中略

```

```terminal

% bin/rspec

Running via Spring preloader in process 66678
.................................

Finished in 3.21 seconds (files took 2.7 seconds to load)
33 examples, 0 failures
```
無事パスしました！！！！
【iOS, Swift】画像リサイズ処理の速度

iOSDC 2019 発表資料 の下記にて画像リサイズの処理速度の検証が書かれていたので、自分でも検証してみました。
ただそれだけです。

[画像処理におけるUIImageとCGImageとCIImageの効果的な使い分け](https://speakerdeck.com/kotetuco/uiimage-and-ciimage-for-image-processing)



## 処理速度計測の準備

```swift
func measure <T> (_ f: @autoclosure () -> T) -> (result: T, duration: String) {
    let startTime = CFAbsoluteTimeGetCurrent()
    let result = f()
    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    return (result, "経過時間は \(timeElapsed) 秒です")
}
```



## 対象画像

1920 × 1280

![sea-5237374_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138735/997167cc-928d-f5b8-1c27-80dcb0a8173f.jpeg)


## 計測対象

### UIImageのリサイズ処理

```swift
extension UIImage {

    public func resize(to size: CGSize) -> UIImage {
        let format = UIGraphicsImageRendererFormat()
        format.scale = 1
        let renderer = UIGraphicsImageRenderer(size: size, format: format)
        
        let image = renderer.image {_ in
            let newRect = CGRect(origin: .zero, size: size)
            self.draw(in: newRect)
        }
        return image
   }
}
```



### CIImageのリサイズ処理

```swift
extension CIImage {

   func resizeAffine(scaleX: CGFloat, scaleY: CGFloat) -> CIImage? {
         let matrix = CGAffineTransform(scaleX: scaleX, y: scaleY)
        return base.transformed(by: matrix)
    }

    func resizeLanczos(to scale: CGFloat) -> CIImage? {
        guard let filter = CIFilter(name: "CILanczosScaleTransform") else {
            return nil
        }
        
        filter.setDefaults()
        filter.setValue(self, forKey: kCIInputImageKey)
        filter.setValue(scale, forKey: kCIInputScaleKey)
        return filter.outputImage
   }
    
   func resizeBicubic(to scale: CGFloat) -> CIImage? {
         guard let filter = CIFilter(name: "CIBicubicScaleTransform") else {
             return nil
         }
         
         filter.setDefaults()
         filter.setValue(self, forKey: kCIInputImageKey)
         filter.setValue(scale, forKey: kCIInputScaleKey)
         return filter.outputImage
    }
}
```



## 計測

```swift
struct DemoImageResize {
    
    static func demoImageResize() {
        let image = UIImage(named: "sea.jpg")!
        let res1 = measure(image.ex.resize(to: CGSize(width: image.size.width*2, height: image.size.height*2)))
        print(res1.duration)
        
        let ciimage = CIImage(image: image)!
        let res2 = measure(ciimage.ex.resizeLanczos(to: 2))
        print(res2.duration)
        let res3 = measure(ciimage.ex.resizeBicubic(to: 2))
        print(res3.duration)
    }
}
```



## 結果

確かにCIImageを利用するほうが早く、特にアフィン変換が速い。

```
// UIImage
0.24390900135040283 秒
// CIImage (Affine) 
0.0000209808349609375 秒
// CIImage (Lanczos)
0.0028940439224243164 秒
// CIImage (Bicubic)
0.0014100074768066406 秒
```
Node.jsでIFTTTのWebhooksを使う（requestモジュール利用）

## Node.jsでIFTTTに連携する

前回までのお話。

 - [Raspberry piにNode.jsをインストールする](https://qiita.com/takashi53/items/69d4395c70d76ddbb0ab)
 - [Node.jsでrequestモジュールを使ってHTTPリクエストを実行する](https://qiita.com/takashi53/items/76c5987b73b76ba9ea96)

## 今回はIFTTTを使ってGoogle スプレッドシートにデータを書き込む

IFTTTの設定は、端折ります。（また別途）

### IFTTTのWebhooksのデータ送信のポイント

- 送信できるデータは最大3つ
- POSTメソッドを使う
- データはJSON形式

### Webhooksのシークレットキーをメモする

Webhooks　→ Documentation を開き、シークレットキーをメモしてください。

![IFTTT-000.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/d6f42caa-3896-c1ff-aaf3-ede9ac3fdf1a.png)

▼このキーをメモする。

![IFTTT-000-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/d6c433c6-a28c-30df-dec4-85c4725be5d6.png)


## Node.jsのソースコードは、こんな感じです。

requestモジュールを利用して、POSTメソッドを実行します。

```js
var webclient = require("request");

var ifttt_event = "Record"; //イベント名
var ifttt_secret_key = "あなたのキーを書く"; //キー
var IFTTT_URL_GoogleSheets = 'https://maker.ifttt.com/trigger/' + ifttt_event + '/with/key/' + ifttt_secret_key;

//書き込むデータ
var p1 = 'データ1';
var p2 = 'データ2';
var p3 = 'データ3';

webclient.post({
  url: IFTTT_URL_GoogleSheets,
  headers: {
    "content-type": "application/json"
  },
  body: JSON.stringify({'value1':p1, 'value2':p2, 'value3':p3})
}, function (error, response, body){
  console.log(body);
});

```

## 実行してみます

```shell-session
pi@raspberrypi:~/myapp $ node webhook.js
Congratulations! You've fired the Record event
```

データ送信できたようです。

## Google sheetを確認しよう

Googleドライブを見てみると、無事に書き込みできていました！

![sheet.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299557/72431258-068e-be87-1737-ee63e822470d.png)


## まとめ

今回は、IFTTTのWebhooksを利用して、Google スプレッドシートにデータを書き込みました。

- IFTTTのWebhooksを設定する
- Webhooksのシークレットキーをメモする
- POSTメソッドで、JSON形式でデータを送信する
railsでアプリを作る時【備忘録】

#①まずターミナルでrails new
  ``` ruby
 rails new [アプリ名][オプション]
  ```
　今回私はデータベースを指定しました

```
rails new [アプリ名]-d mysql
```

#②rails db:create
 　データベースの作成　
　　この後にテーブルやカラムを追加します。

#③git hubでローカルとリポジトリを接続
　
　○順序
　・GitHub desktopでローカルのファイルを管理する
　　これはdesktopでaddなんとかで設定する

　・つづいて、GitHubにリモートリポジトリを作る
　　作成したらそこでhttpのリンクがあるからそれをコピーして
　　ターミナルで下記のように打つ（httpからはコピペ）
 
```
 git remote add origin https://github.com/ta1ka2shi3/redchaps.git
 ```

　

#④必要なgemのインストール

```
gem 'pry-rails'
gem 'pry-byebug'
gem 'font-awesome-sass'
gem 'haml-rails'
gem 'better_errors'  /エラー見やすくするやつ
gem 'binding_of_caller'
```

※私が作成したものを基準にしております。



#⑤まずトップページ表示させるため

```
rails g controller [コントローラー名] 
```

コントローラー作って、indexメソッドを作った。あとビューも
Routeの設定も忘れずに


### 最後に
　これは私の個人アプリに並行して投稿しておりますので、またまとまったら更新するかもしれません。