OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScript 配列関係のコード集

JavaScriptの配列関係のコード集です。何かを作っていたときの副産物の塊です。

# 最後の要素を取得する
```js
const array1 = ["a", "b", "c", "d"]
array1.slice(-1)[0]
// "d"
```

# 最初の要素を特別扱いして二次元配列→2要素配列の配列[[a, b, c, ...], [d, e, f, ...], ...]→[[a, b], [a, c], [d, e], [d, e], ...]

```js:slice
const items = [
	["2020/05/31", "A", "B", "C"],
	["2020/05/31", "D", "E", "F"],
	["2020/06/01", "G", "H", "I"],
];
items.flatMap(raw => raw.slice(1).map(item => [raw[0], item ]));
```

```js:分割代入と可変長引数
const items = [
    ["2020/05/31", "A", "B", "C"],
    ["2020/05/31", "D", "E", "F"],
    ["2020/06/01", "G", "H", "I"],
];
items.flatMap(([first, ...others]) => others.map(other => [first, other]));
```

```js:出力
/*
(9) […]
0: Array [ "2020/05/31", "A" ]
1: Array [ "2020/05/31", "B" ]
2: Array [ "2020/05/31", "C" ]
3: Array [ "2020/05/31", "D" ]
4: Array [ "2020/05/31", "E" ]
5: Array [ "2020/05/31", "F" ]
6: Array [ "2020/06/01", "G" ]
7: Array [ "2020/06/01", "H" ]
8: Array [ "2020/06/01", "I" ]
length: 9
*/
```

# 最初の要素を特別扱いして二次元配列→2要素配列の配列[[a, b, c, ...], [d, e, f, ...], ...]→[[b,a], [c, a], [e, a], [e, a], ...]

```js:flatMapとslice
items.flatMap(raw => raw.slice(1).map(item => [item, raw[0]]));
```

```js:分割代入と可変長引数
items.flatMap(([first, ...others]) => others.map(other => [other, first]));
```

```js:出力
/*
(9) […]
0: Array [ "A", "2020/05/31" ]
1: Array [ "B", "2020/05/31" ]
2: Array [ "C", "2020/05/31" ]
3: Array [ "D", "2020/05/31" ]
4: Array [ "E", "2020/05/31" ]
​5: Array [ "F", "2020/05/31" ]
6: Array [ "G", "2020/06/01" ]
​7: Array [ "H", "2020/06/01" ]
​8: Array [ "I", "2020/06/01" ]
length: 9
*/
```

# 最初の要素を特別扱いして二次元配列→2要素オブジェクトの配列[[a, b, c, ...], [d, e, f, ...], ...]→[{key1:a, key2:b}, {key1:a, key2:c}, {key1:d, key2:e}, {key1:d, key2:e}, ...]

```js:slice
const items = [
	["2020/05/31", "A", "B", "C"],
	["2020/05/31", "D", "E", "F"],
	["2020/06/01", "G", "H", "I"],
];

items.flatMap(raw => raw.slice(1).map(item => ({key1: raw[0], key2: item})));
```

```js:分割代入と可変長引数
const items = [
	["2020/05/31", "A", "B", "C"],
	["2020/05/31", "D", "E", "F"],
	["2020/06/01", "G", "H", "I"],
];

items.flatMap(([first, ...others]) => others.map(other => ({key1: first, key2: other})));
```

```js:出力
/*
(9) […]
0: Object { key1: "2020/05/31", key2: "A" }
1: Object { key1: "2020/05/31", key2: "B" }
2: Object { key1: "2020/05/31", key2: "C" }
3: Object { key1: "2020/05/31", key2: "D" }
4: Object { key1: "2020/05/31", key2: "E" }
5: Object { key1: "2020/05/31", key2: "F" }
6: Object { key1: "2020/06/01", key2: "G" }
7: Object { key1: "2020/06/01", key2: "H" }
8: Object { key1: "2020/06/01", key2: "I" }
length: 9
*/
```

- ラムダ式でオブジェクトリテラルを使うとき、直接`() => {...}`とすると関数と誤解されてエラーが発生します。`() => {return {...};}`または`() => ({...})`で対処できます。
C# 変数と宣言

##C# 変数

**変数とは？**
数値や文字などを格納しておく箱のようなもの。
（それに名前を付けた物）

**宣言の書き方**

| 宣言方法 | 例 |  |
|----|----|----|
| 2つの変数の宣言 | int a; int b; | int a,b; |
| 一つの変数の宣言と代入 | int a; a = 2; | int a= 2; |
| 二つの変数の宣言と代入 | int a;int b; | a = 1; b = 2; |


**変数の宣言における命名規則について**
>(Microsoftからの引用になります！)
>フィールド名には Pascal 形式を使用してください。
>フィールドの名前には、名詞や名詞句を使用してください。
>フィールド名にはプリフィックスを使用しないでください。 
>たとえば、静的フィールドと非静的フィールドを区別するために、g_ や s_ を使用しないでください

**※Pascal形式とは！**
・それぞれの単語の頭は大文字
・単語の間に「-(ハイフン)」や「_(アンダースコア)」は使わない

**変数の型**
・値型と参照型がある
**値型**
　・単純型
　・列挙型
　・構造体の型
　・null許容値型
　・ダブル値型
**参照型**
　・クラス型
　・インターフェイス型
　・配列型
　・デリゲート型

※変数の型は別途記載したいと思う。
(各型について調べたが結構量が多い為、細かく分類します)

**参考資料**
・Microsoft Build
・Wikipedia
・C#の絵本
WindowsをMacのキーボード配置に変更する

# 概要

windowsでMacと同様のkey設定をする

- `ctrl`や`alt`の位置を`command`や`option`keyに合わせるような配置に設定したい
- `Ctrl+F,B,N,P`でカーソルを上下左右移動をできるようにしたい

PowerToysとAutoHotkeyを使う

- Microsoft PowerToys
    - 公式でkey設定ができる`keybord Manager`を含むツールを公開している
- AutoHotkey
    - keyの入れ替えや、key同時押し時のショートカット登録ができる

# Microsoft PowerToys

githubで公開されており、[こちら](https://github.com/microsoft/PowerToys/releases/)から最新の`PowerToysSetup-xxx.exe`をダウンロードしてインストールすれば使える

起動したら`Keyboard Manager`からkey設定が可能。かなり便利で設定も簡単。しかし、`Ctrl+F,B,N,P`でカーソルを上下左右移動をするようにショートカット設定すると`Ctrl+F+B`のような同時押しになってしまった場合に移動できなくなってしまうため、key配置のみを設定し、カーソル移動のショートカットはAutoHotKeyに委ねる。

![スクリーンショット 2021-11-04 003911.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/cbc46e0a-1ddd-9453-d2ce-83be5b1c349e.png)

![スクリーンショット 2021-11-04 011727.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/089efae8-e6d4-e703-479b-7b877f97105f.png)

![スクリーンショット 2021-11-04 011853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449626/2c77dee6-f469-84fc-82b2-03ed1f29ff0c.png)


# AutoHotkey

`Ctrl+F,B,N,P`の設定を行う。

ダウンロードは[こちら](https://www.autohotkey.com/)から

AutoHotKey.ahkファイルをつくって編集 https://github.com/ktanoooo/keyboard_setup/blob/main/AutoHotKey/myAutoHotKey.ahk
保存してダブルクリックで適用完了

keyの参考: http://ahkwiki.net/KeyList
SQLで時間差を算出する

データが作成された日と更新日との差を取得するために、エラーメッセージが出たときの備忘録。

## エラーが出たコード
時間差を算出するには`TIMEDIFF`がよいということで、下記のコードで実行。

```
SELECT DATEDIFF(DAY, createTimestamp, updateTimestamp) AS DiffDate
```
このときのデータの型は`DATETIME`で長さは6と定義したもので、値は`2019-08-02 12:53:33.172000`になります。
しかし、上記コードでは`Error Code: 1582 Incorrect parameter count in the call to native function 'DATEDIFF'`のエラー発生。

## 解決策
[こちらのサイト](https://stackoverflow.com/questions/30671286/incorrect-parameter-count-in-the-call-to-native-function-datediff/30676411)でも同じ様な悩みを持った人がいたようです。
`DATEDIFF`では2つのパラーメターしか許可されず、日数で返却されるようです。

下記のコードで無事解決出来ました。

```
SELECT DATEDIFF(createTimestamp, updateTimestamp) AS DiffDate; 
```

他サイトで、上記3つのパラメータがとれるときと取れない時の違いが分からない点に不安を残しつつ、そのうち解決していきます。

[追記] コメント欄でエラー原因を教えてもらいました。RDBの混同によるものでした。
Docker Portainerでコンテナ追加時のVolumeMapping(for Windows)

#

#結論
hostがwindowsの場合、パスを次のように指定する。

CドライブのDockerShareフォルダを指定する場合

```
/host_mnt/c/DockerShare
```

#画面キャプチャ
<img width="1152" alt="PortainerAddContainerWindows.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613697/eba43d1d-31f5-4c20-ae43-674ca2dc36f2.png">
はじめてのThree.js 9章 日記

[はじめてのthree.js](https://www.amazon.co.jp/dp/4873117704)

#新たに知った知識
- 複数のモデルをアニメーションするの意外と簡単

```javascript


        function render() {
            stats.update();
            // rotate the cube around its axes
            cube.rotation.x += controls.rotationSpeed;
            cube.rotation.y += controls.rotationSpeed;
            cube.rotation.z += controls.rotationSpeed;

            // bounce the sphere up and down
            step += controls.bouncingSpeed;
            sphere.position.x = 20 + (10 * (Math.cos(step)));
            sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));

            // scale the cylinder

            scalingStep += controls.scalingSpeed;
            var scaleX = Math.abs(Math.sin(scalingStep / 4));
            var scaleY = Math.abs(Math.cos(scalingStep / 5));
            var scaleZ = Math.abs(Math.sin(scalingStep / 7));
            cylinder.scale.set(scaleX, scaleY, scaleZ);

            // render using requestAnimationFrame
            renderer.render(scene, camera);
            requestAnimationFrame(render);

        }
```
- tweeningでイージングなどがつけれる
- trackball control
- three.clockオブジェクトで時間通りに動く
- morphtargetinfluenceは２つのオブジェクトをスムーズに変形移行させてくれる

```javascript
        // create a cube
        var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
        var cubeMaterial = new THREE.MeshLambertMaterial({morphTargets: true, color: 0xff0000});

        // define morphtargets, we'll use the vertices from these geometries
        var cubeTarget1 = new THREE.BoxGeometry(2, 10, 2);
        var cubeTarget2 = new THREE.BoxGeometry(8, 2, 8);

        // define morphtargets and compute the morphnormal
        cubeGeometry.morphTargets[0] = {name: 't1', vertices: cubeTarget2.vertices};
        cubeGeometry.morphTargets[1] = {name: 't2', vertices: cubeTarget1.vertices};
```

#気づいたこと
- flycontrolとfirstpersoncontrolは結構酔う

#wow moment
- 

#まだ解決していない点
- animationmixerの役割



[10章はこちら](https://qiita.com/asadsexyimp/items/94de297ba0818bf6e4f7)
Swift StoryboradでStack Viewを使う

# はじめに
StoryboardにてStack Viewの使い方備忘

# 環境
- Xcode 11.5
- Swift 5

# 実施手順

## 1. Stack Viewを配置する
<img width="869" alt="１.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412123/a4531d34-254d-005a-2819-db2fb081e483.png">

## 2. Stack Viewに制約を追加する
<img width="1024" alt="２.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412123/13df21be-92de-03c8-1cac-6fbf8467a516.png">

## 3. Stack Viewにアイテムを追加する
<img width="870" alt="３.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412123/8e098a4f-cdd1-ec81-4eef-94376ecb5a6b.png">
ridgepoleを導入してMigrations are pendingエラー

### はじめに
先日、RSpecを実行するとこのようなエラーが出ました。

```zsh
Migrations are pending. To resolve this issue, run:
        rails db:migrate RAILS_ENV=test
No examples found.
```

マイグレートしろと言われている。。。
`ridgepole`を使っているのに。。。

### 試したこと
- schemafileに間違いがないか確認
- `ridgepole`コマンドを再度実行
- DBを消して、再度作成する

これらを実施しても治りませんでした。

### 原因&解決方法
原因を探っていると、migrationファイルを発見しました。

```zsh
rails g model --skip-migration
```
を忘れていた！！！

このmigrationファイルを消してRSpecを実行してみると、今度はちゃんと動きました。

### 教訓
- `ridgepole`を使う時は--skip-migrationを忘れない
- こまめにコミットしたりテストを動かしたりしてエラーがないか確認する
【学習メモ】accepts_nested_attributes_for fields_for form_withメソッド

#趣旨
現役フルスタックエンジニアの方より、極力一次情報で不明点を確認し都度拾いながら学習しようというアドバイスを基に、APIやそれに近いものをGoogle翻訳かけながら理解した。その内容のアウトプット・備忘録として投稿する。

#accepts_nested_attributes_for
```ruby

accepts_nested_attributes_for(*attr_names)
```

【概要】
指定されたassociationの属性ライターを定義する

【例】

```ruby

accepts_nested_attributes_for :avatar, reject_if: proc { |attributes| attributes['name'].blank? }
```

【オプション】
:allow_destroy、:reject_if、:limit、:update_only

#fields_for
```ruby
fields_for(record_name, record_object = nil, fields_options = {}, &block)
```

【概要】
・form_for,form_withなどの特定のModelオブジェクトの周りにscopeを作成するが、フォームタグ自体は生成しない
・つまり、同じフォーム（＝同じ画面のフォーム）で別途（＝次の行に）追加するモデルオブジェクトを追加する時に使う
・form_for,form_with（これらをFormBuilderという）でメソッドを呼び出してモデルオブジェクトに関連づけられたフィールドを生成可能

【例】

```ruby
<%= form_for @person do |person_form| %>
  Name: <%= person_form.text_field :name %>
  Admin: <%= person_form.check_box :admin %>
<% end %> #この場合、FormBuilderは、「person_form」変数として生成される
```

【※理解するために調べた言葉】
・FormBuilder（オブジェクト）：特定のモデルオブジェクトに関連付けられており、モデルオブジェクトに関連付けられたフィールドを生成するというもの
・パス：コンピュータ内で特定のファイル（資源）の所在・位置を示すもの
・Prefix：パスが入った変数のようなもので、resourcesメソッドを使ってルーティングを定義すると自動で作成される
・Verb：HTTPメソッドでといい、URI Patternのパスにどのhttpリクエストでアクセスするかを示す
・URI Pattern：ルーティングのパス
Controller#Action：httpリクエストでパスが送られた際に処理が行われるコントローラとアクションを表し、#左がコントローラ名、右がアクション名を示す


#form_with
```ruby
form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
```
【概要】
URLscope、またはモデルの混在に基づいてフォームタグを生成するもの

【例】
①

```ruby
<%= form_with scope: :person do |form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>

  <%= text_area :person, :biography %>
  <%= check_box_tag "person[admin]", "1", @person.company.admin? %>

  <%= form.submit %>
<% end %>
```
②

```ruby
<%= form_with(model: @post, url: super_posts_path) %>
<%= form_with(model: @post, scope: :article) %>
<%= form_with(model: @post, format: :json) %>
<%= form_with(model: @post, authenticity_token: false) %> # Disables the token.
```

【オプション】
:model、:url、:method、:format、:scope、:namespace、:authenticity_token、:local、:skip_enforcing_utf8、:builder、:class、:data、:html


##参考
【Ruby on Rails API】　
https://api.rubyonrails.org/

【Rails fields_for のドキュメントを和訳しました。】
https://qiita.com/shunsuke227ono/items/401f2f547c34e3c333aa

【has_manyで関連づけられたモデルも一括保存する方法】
https://logicoffee.hatenablog.com/entry/2018/08/10/215450

【【Rails】rake routesコマンドの使い方をマスターしよう！】
https://pikawaka.com/rails/rake_routes#Prefix%E3%81%A8%E3%81%AF%EF%BC%9F
Capistrano自動デプロイ設定時（初回）に出たエラー「Mysql2::Error: Table 'users' already exists」の解決方法



#### アプリを本番環境に上げる際にCapistranoを導入しようとしたら、下記のエラーが出ました。


#### Mysql2::Error: Table 'users' already exists: CREATE TABLE 'users'

「ユーザーズテープルすでにあるよ」と怒られているようです。
<br>
#### 状況を整理

・手動デプロイは上手くいっている。
・Capistranoの【初回デプロイ】（つまりまだ一回も成功していない）でエラーが出た。
・MySQLやusersテーブルについて言及されているので、マイグレーション系のエラーである。

どうやら、本番環境下のマイグレーション関係で問題が起きている模様。

<br>
#### 解決法
結論、
ローカル環境で修正したマイグレーションが本番環境で反映されてませんでした。

[ec2-user@ip<Elastic IP> <リポジトリ名>]　以下で下記コマンドを打って解決

①DBを削除する

```ruby:ターミナル
RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop　
```
（Railsバージョンによって異なる模様。参考記事参照）
<br>

②DBをcreateする

```ruby:ターミナル
rails db:create RAILS_ENV=production

```
<br>
③DBをmigrateする

```ruby:ターミナル
rails db:migrate RAILS_ENV=production
```
<br>
■ちなみに、①DBを削除するCapistranoの自動デプロイが成功した後であれば、データベースが「current」に入っていると思われるので「current」で削除を行う模様です（試していません）

■参考記事
[Rails5以降の本番環境でデータベースをresetする方法！](https://qiita.com/wacker8818/items/72d933f036ca0b75d124)

<br>
デプロイは難しいですね。ですがコーディングと同様にエラーのたびに理解が深まるので知識が積み重なってく感じがすきです。頑張りましょ〜
C++ Visual Studio 2019でBoost C++ Librariesのヘッダーファイルを使う（Windows）

# まえがき
Windows環境のVisual Studio 2019でBoost C++ Librariesのヘッダーファイルを使う方法です。ここではライブラリ（.libファイル）は作成しません。

# すべてのC++プロジェクトにBoostを追加する

1. [Boost C++ Librariesのウェブサイト](https://www.boost.org/)から欲しいバージョンの圧縮ファイルをダウンロードする。
  1. 例えば1.73.0なら[https://www.boost.org/users/history/version_1_73_0.html](https://www.boost.org/users/history/version_1_73_0.html)の「boost_1_73_0.7z」または「boost_1_73_0.zip」。
1. ダウンロードした圧縮ファイルを適当な場所に展開する。
1. プロパティ マネージャを表示する。
  1. 適当なC++プロジェクトを作成して、メニューバーから「表示→その他のウィンドウ→プロパティ マネージャ(N)」をクリックする。
  1. 既に表示されていれば左右上下の「プロパティ マネージャ」をクリックする。
1. 適当なプロジェクトの名前をダブルクリックして開く。
1. 「Debug | Win32」または「Release | Win32」をダブルクリックして開く。
1. 「Microsoft.Cpp.Win32.user」をダブルクリックして開く。
1. 「VC++ディレクトリ」をクリックする。
1. 「インクルードディレクトリ」にBoostのインストール場所を追加する。
1. 「Debug | x64」または「Release | x64」をダブルクリックして開く。
1. 「Microsoft.Cpp.Win32.user」をダブルクリックして開き、同様にインストール場所を追加する。
1. **Visual Studioを再起動する。**
WindowsでElixirやるならWSL2+Docker+VSCode

@takasehideki さんに触発されて、Elixir/Nervesなんもわからんけど触り始めたわけですが、Ubuntuで開発されているようで、、、Windowsユーザーにはあまり優しくない感じ。
色々入れてWindowsの中を荒らしたくないなーと思っていたわけですが、WSL2が正式リリースされてWSL2 + Docker + VSCodeでステキ環境が作れるようだったので、試してみました。

# 大まかな流れ

1. WSL2を使えるようにする
2. Dockerを使えるようにする
3. Elixirのdevcontainerを用意する
4. VSCodeでdevcontainerを起動する

レッツ・トライ！

# WSL2を使えるようにする

Windows 10をバージョン2004にアップグレードしてから、WSL2を有効にしてください。

## Windows 10 バージョン2004

ネットにたくさん情報があるので、ググってやってください。
わたしは[ここ](https://www.microsoft.com/ja-jp/software-download/windows10)の**今すぐアップデート**でやりました。

`winver`コマンドで、**バージョン 2004**と表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/1aac185f-b321-754c-a373-41b372d8bfa7.png)

## WSL2

ネットにたくさん情報があるので、ググってやってください。
わたしは[ここ](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)の、
**Windows Subsystem for Linux のインストール**
**WSL 2 に更新する**
をやりました。

# Dockerを使えるようにする

Docker Desktopをインストールしてください。
わたしは[ここ](https://hub.docker.com/editions/community/docker-ce-desktop-windows)の**Get Docker Desktop for Windows(stable)**でやりました。インストール画面の`Enable WSL 2 Windows Features`のチェックを忘れずに。

Docker Desktopを起動しておき、`wsl -l -v`コマンドでdocker-desktopがVERSION 2と表示されればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/0b0b9dae-740e-19b3-37a2-07164eb8524c.png)

# Elixirのdevcontainerを用意する

**.devcontainer**フォルダを作って、そこに**Dockerfile**と**devcontainer.json**を作成してください。

```:Dockerfile
FROM elixir:1.9.4
```
```json:devcontainer.json
{
	"name": "Elixir",
	"dockerFile": "Dockerfile",
	"settings": {
		"terminal.integrated.shell.linux": "bash"
	}
}
```

# VSCodeでdevcontainerを起動する

Remote Development拡張を入れたVSCodeの**Remote-Container: Open Folder in Container**で、**.devcontainer**のあるフォルダを開いてください。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/3045323f-2a67-53cf-0ba0-c84f3d4afd98.png)

すると、Docker Hubからコンテナをわさわさとダウンロードして、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/8fc8df80-dd21-7231-53fa-c2ede5147ed0.png)

DockerでElixir環境が起動して、VSCodeから操作できるようになります！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/8ef94f6a-9f03-e625-4fc3-38db17d9fa89.png)

# 最後に

VSCodeでなんとなく使えてしまう快適環境ではありますが、、、Dockerについてはちゃんと理解しておかないと痛い目にあう可能性があると思う。
やりたいのはサクっとElixir/Nerves開発環境なので、Dockerfileを書かねばー。





おしまい
wsl2でffmpegを使う


# 環境
wsl2 Ubuntu 20.04 Latest

# install

```bash

sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install ffmpeg
```

ソース
https://www.reddit.com/r/Windows10/comments/5006is/want_to_install_ffmpeg_under_bash_for_windows/

# 使い方
今回はmp4 -> gifです

```bash
ffmpeg -i hoge.mp4 -s 1920x1080 hoge.gif
```

-sで サイズ指定しています
-rで フレームレート指定もできるっぽい
qiitaに上げる時、10Mb 超えるとサーバーからエラー返ってくるのでよく使う

![error]()
errors: {size: ["must be less than 10 MB"]}

# 詳しそうなサイト
https://homehack.nl/create-animated-gifs-from-mp4-with-ffmpeg/

# 関数化

```bash
function video-to-gif () {                                                                                                                                                                                         
    only_file_name=$(basename $@ .mp4)
    only_dir_name=$(dirname $@)
    ffmpeg -i $only_dir_name/$only_file_name.mp4 -s 1920x1080　$only_dir_name/$only_file_name.gif
}
```

携帯動画変換くん思い出した
vimiumに出戻りした(動画でわかりやすく)


vimiumのvisualモードは開始位置が指定できなくて嫌だったが、できたので共有(キャレットモードという)
|がよく書いてありますが、orの意味です

# :tangerine: 青果物

```:Excluded-URLs-and-keys
https?://mail.google.com/*
https?://us-east-1.console.aws.amazon.com/*
```

```:Custom-key-mappings
unmapAll                                    #デフォルトの設定を解除する
map ? showHelp                              #ヘルプを表示
map j scrollDown                            #下に移動
map k scrollUp                              #上に移動
map h goBack                                #戻る
map l goForward                             #進む
map H previousTab                           #左のタブに移動
map L nextTab                               #右のタブに移動
map gg scrollToTop                          #最上部に移動
map G scrollToBottom                        #最下部に移動
map t createTab                             #新しいタブを開く
map nn removeTab                            #タブを閉じる
map N restoreTab                            #閉じたタブを復元
map p openCopiedUrlInNewTab                 #コピーした文字列、URLを別タブで開く
map yy copyCurrentUrl                       #現在のページのURLをコピー
map d scrollPageDown                        #画面半分下に移動
map u scrollPageUp                          #画面半分上に移動
map f LinkHints.activateMode                #イージーモーション？
map F LinkHints.activateModeToOpenInNewTab  #イージーモーション別タブ？
map v  enterVisualMode                      # ビジュアルモード
map <a-h> moveTabLeft                       # タブを左へ
map <a-l> moveTabRight                      # タブを右へ
map <a-H> moveTabLeft count=99              # タブを左端へ
map <a-L> moveTabRight count=99             # タブを右端へ
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/5ca3cb83-2290-406f-cf76-e418b98cc06b.png)

# できること
## 1. ビジュアルモード
![2020-05-31-19-52-56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/ea49ceda-ac9e-0864-ac1a-bd95f0524971.gif)

youtube
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/t8aEUKdqQq4/0.jpg)](http://www.youtube.com/watch?v=t8aEUKdqQq4)

### やっていること
1. v: ヴィジュアルモード
2. c: キャレットモード
3. jkhl: カーソルを移動
4. v: ヴィジュアルモード
5. o: カーソルを開始位置へ移動
6. jkhl: カーソルを移動
7. /: 文字を検索
8. enter: 検索する文字列を確定
9. n|N: 該当の文字列を移動
10. v: ビジュアルモード
ビジュアルモードに入った状態でキャレットモードに入ることにより、カーソル開始位置を指定できる

## 2. 左右のタブに移動 & タブを左右へ移動
![2020-05-31-20-35-01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253014/21c27e5b-85a7-b631-b505-f0848d1f1424.gif)

youtube
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/BCEOxJH_nmY/0.jpg)](http://www.youtube.com/watch?v=BCEOxJH_nmY)

### やっていること
1. H|L: 左右のタブに移動
2. alt + H|alt + L: タブを左右端へ移動
3. alt + h|alt + l: タブを左右へ移動

# vimium
https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en
# vimium visual modeについて
https://github.com/philc/vimium/wiki/Visual-Mode

ずっとvimmiumだと思ってた
【マークアップ 】デザインボタン

# 概要
ボタンに少しデザインを付けることで、サイトがカッコ良くなる〜:laughing:
と思い実装しました！

今回紹介するのは、立体的に見えて押し込み式のボタンとなります:bulb:

# 実装
```HTML:views/index.html.haml
.btn
  .new__dispaly--commit
  = f.submit "Submit", class:"commit-btn"
```

```scss:index.scss
  .btn {
    input.commit-btn {
      display: inline-block;
      position: relative;
      padding: 0.5em 1.4em;
      text-decoration: none;
      background: #1d4d8b;/*ボタン色*/
      color: $white;
      border-bottom: solid 5px #123158;/*ボタンの下　色*/
      border-right: solid 5px #5375bd;/*ボタンの右　色*/
    }
    input.commit-btn:before {
      content: " ";
      position: absolute;
      bottom: -5px;
      left: -1px;
      width: 0;
      height: 0;
      border-width: 0 6px 6px 0px;
      border-style: solid;
      border-color: transparent;
      border-bottom-color: $white;
      }
    input.commit-btn:after {
      content: " ";
      position: absolute;
      top: -1px;
      right: -5px;
      width: 0;
      height: 0;
      border-width: 0px 6px 6px 0px;
      border-style: solid;
      border-color: white;
      border-bottom-color: transparent;
    }
    input.commit-btn:active {
      /*ボタンを押したとき*/
      border:none;
      -webkit-transform: translate(6px,6px);
      transform: translate(6px,6px);
    }
    input.commit-btn:active:after, input.commit-btnt:active:before {
      content: none;/*ボタンを押すと線が消える*/
    }
  }
```

# 実装結果
### ボタン：静止画像
<img width="155" alt="スクリーンショット 2020-05-31 20.57.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/a8bcbd91-cfce-d169-102f-1136587b40c1.png">

### ボタン：動画　
※Gyazoで撮影していますので、タイミングによっては見れないかもしれません:cry:

https://gyazo.com/d5c37521452af8a951b69bf658ac2f53

# 感想
HamlとScssで簡単実装できました！
皆様もぜひ活用してください:laughing:

# 参考
https://saruwakakun.com/html-css/reference/buttons
【Sequelize5.x】sequelizeでGROUP_CONCAT関数を使ってみた

## 初めに
自分が実際にGROUP_CONCATを使用したときは2つのテーブルを結合した状態だったので、同じ状況でまとめたいと思います。結合していない状態でも使用できると思いますが、微妙に書き方が変わるので適宜読み替えて実装してください。

## 実装

### 
usersテーブルとtasksテーブルがあるとします。

```js:models/users.js
module.exports = (sequelize, DataTypes) => {
  const users = sequelize.define('users', {
    name: DataTypes.STRING
  }, {});
  users.associate = function(models) {
    users.hasMany(models.tasks, {
      foreignKey: 'userId'
    });
  };
  return users;
};
```

```js:models/tasks.js
module.exports = (sequelize, DataTypes) => {
  const tasks = sequelize.define('tasks', {
    task: DataTypes.STRING,
    userId: DataTypes.INTEGER
  }, {});
  tasks.associate = function(models) {
    tasks.belongsTo(models.users, {
      foreignKey: 'userId'
    });
  };
  return tasks;
};
```

2つのテーブルを結合し、以下のようなクエリを発行するとします。

```SQL:MySQL

SELECT users.id, name, GROUP_CONCAT(task) AS task_list
FROM users
LEFT JOIN tasks
ON users.id = tasks.user_id 
GROUP BY users.id
```



sequelizeでは、sumやcountを使用する時と同様に`sequelize.fn()`を使います。

```js:sequelize
users.findAll({
  raw: true,
  include: [{
    model: tasks,
    attributes: [
      [sequelize.fn('GROUP_CONCAT', sequelize.literal('task')), 'task_list'],
    ],
  }],
  attricutes: [
    'users.id',
    'name'
  ],
  group: ['users.id'],
});
```

取得してきた結果は以下のようになります。

| id | name   | task_list                       |
|:---|:-------|:--------------------------------|
| 1  | taro   | 牛乳を買う、掃除する、風呂に入る、勉強する |
| 2  | jiro   | 服を買う、掃除する、洗濯する            |
| 3  | saburo | 掃除する、風呂に入る、洗濯する          |
| 4  | siro   | 服を買う、勉強する                   |
| 5  | goro   | 牛乳を買う                         |
| 6  | rokuro | 服を買う、掃除する、風呂に入る、洗濯する   |


自分の実装時には、task_listがカンマ区切りになることや、並び順の整合性が取れないことが不都合だったので、SEPARATORやORDER BYを付与してみたいと思います。

```SQL:MySQL

SELECT users.id, name, GROUP_CONCAT(task ORDER BY task.id ASC SEPARATOR '@') AS task_list
FROM users
LEFT JOIN tasks
ON users.id = tasks.user_id 
GROUP BY users.id
```

`sequelize.fn()`にSEPARATORやORDER BYをそのまま記述することができます。`sequelize.literal()`内が長くなってしまうので、定数化してしまうのもいいと思います。

```js:sequelize
users.findAll({
  raw: true,
  include: [{
    model: tasks,
    attributes: [
      [sequelize.fn('GROUP_CONCAT',
        sequelize.literal('task ORDER BY tasks.id ASC SEPARATOR "@"')),
      'task_list'],
    ],
  }],
  attricutes: [
    'users.id',
    'name'
  ],
  group: ['users.id'],
});
```

取得してきた結果は以下のようになります。

| id | name   | task_list                       |
|:---|:-------|:--------------------------------|
| 1  | taro   | 牛乳を買う@掃除する@風呂に入る@勉強する |
| 2  | jiro   | 服を買う@掃除する@洗濯する            |
| 3  | saburo | 掃除する@風呂に入る@洗濯する          |
| 4  | siro   | 服を買う@勉強する                   |
| 5  | goro   | 牛乳を買う                         |
| 6  | rokuro | 服を買う@掃除する@風呂に入る@洗濯する   |

## まとめ
GROUP_CONCAT関数が使えるか、sequelizeの公式にも載っていなかった（載っていたらすみません。。）のでわかりませんでしたが、sequelize.fn()でMySQLのクエリは大体実行できそうですね。まだ使用したことがないクエリを発行するときはとりあえずsequelize.fn()で試してみようと思います。
リーン・スタートアップのまとめ（自分用）

#はじめに
以前エリック・リースの『リーン・スタートアップ』を読んで、その後様々なところで「リーン・スタートアップとは」という説明を読んだり聞いたりしました。
その中で「ちょっと違うかも？」と感じたりすることがあったので、自分なりにリーン・スタートアップについてまとめてみたいと思います。

間違いについては指摘歓迎です。

#リーンスタートアップとは
日本では2012年に書籍『リーン・スタートアップ　ムダのない起業プロセスでイノベーションを生みだす』が出版されました。

「リーン・スタートアップ」を一言で言うと、「不確実な世界でビジョンの実現に向けてムダなく進むための考え方」です。

##ビジョン
最初にビジョンがあることが前提です。「ビジョンの実現に向けて進む」ためには「ビジョン」が必要です。

ビジョン-戦略-戦術を三角形で表すと、「ビジョンは一番下」です。

あくまでビジョンがあっての戦略-戦術です。ビジョンが変われば、進み方を変えることで対応できるかもしれませんが、それが無理であれば土台のビジョンから作り直す必要があります。

##ムダ
「リーン」とはムダがないことです。
ムダなことはやめましょう。というか、スタートアップはお金がなくなったらその時点で終わりなので、ムダなことをしている余裕は無い！

##不確実
スタートアップは「不確実な世界」で進んでいく必要があるため、全てが実験と言えます。
実験とは、仮説を立て、実験を行い、結果を検証して学びを得ることです。
※「実験」と「仮説検証」の関係がちゃんと理解しきれていないかも。

#ムダをなくす
ここからは「ムダをなくす」という観点で説明していきます。

##使われないものを作るムダ
「すばらしいものを考えた！　みんながこれを使って幸せになれる！　そして私は億万長者だ！」
・・・本当ですか？

最初に検証すべき仮説に「価値仮説」と「成長仮説」があります。

###価値仮説
プロダクト(サービス)は何かの課題を解決します。
課題は、それ自身だけで存在するものではなく、「それを課題として困っている人」がいて初めて課題となります。

作ろうとしているものは「誰」の「どんな課題」を解決するのでしょうか。
その「誰」は「課題」の解決を本当に必要としていますか。

「課題」は「誰」とセットです。
どちらかが無い場合、作ったものはそもそも使われません。

###成長仮説
スタートアップは成長しなくなった時点で終わりです。

「作ったものを100人買ってくれた。でもその後は誰も買ってくれない」
これはビジネスとしては失敗です。

どうやって「使いたい/買いたい/お金を払ってもいい」と思ってくれるのか。
広告で知ってもらう。魅力的なアイテムに課金してもらう。

どうやってプロダクトに価値を感じ、「お金を払う価値がある」と考えてもらうのか。そのような人をどうやって増やしていくのか。これがないと成長できません。
これはビジネスモデルに近いかもしれません。

##不確実な世界で学びを得られないムダ
世界は不確実です。

「この機能を追加すればユーザはもっと増えるはず」
でもユーザが増えなかったら、作った労力はムダになります。

だから小さく実験しましょう。

###構築-計測-学習サイクル
構築(build)-計測(measure)-学習(learn)サイクルはリーン・スタートアップでよく出てくる言葉です。

この中で一番大事なのは「学習」です。つまり「学習」できなかったら、そのサイクルはムダです。

このサイクルは計画と実行の2段階に分かれています。

まずは計画段階について。
最初は「学習」です。仮説を立て、その仮説が検証されたらどのような学びが得られるかを考えます。次につながらない学びを得るための作業はムダです。
次は「計測」です。仮説を検証するための実験に必要なものを考えます。「どういう方法で実験し」「結果をどのように計測/判断する」のか。その方法は学びを得られるものですか。学びが得られないものはムダです。
最後に「構築」です。計測して学びを得るために最小限のものを考えます。目的は学びを得ることなので、学びを得られないものはそもそもムダです。さらに学びを得るのに必要なこと以上を作り込むのもムダです。「とりあえず作ってみたら意外と分かることがあった」というのは結果オーライに見えますが、そういうのは実験とは言えません。

ここまでできたら実行段階です。
最初は「構築」。計測して学びを得られる最小限のものを作りましょう。これをMVPと言います。
次は「計測」。最小限の努力で結果を得ましょう。
最後に「学習」。わかった事を次に活かしましょう。想定外のことが分かった場合、良い学びを得ています。それを知らなかったらムダなものを作ろうとしていたはずです。ここで仮説を正しく検証することが正しい道を進むための一歩です。

###MVP
MVPは「MVP(Minimum Viable Product, 実用最小限の製品」の略です。

構築-計測-学習サイクルで「学習」できるための最小限のもの。
「計測」や「学習」ができないものは、そもそもMVPになっていません。
目的は「学習」なので、それ以上のことを作り込むのはムダです。

「学習」したいことはそれぞれの時点で違うので、MVPも各時点で作り込みのレベルは異なります。ただ、MVPと言った時には「学習」の観点で実用最小限ということです。

##成長できないムダ
「ユーザは増えてはいる。でもこのスピードは成長していると言えるのだろうか？」

成長できないスタートアップはそのままずるずるとただ延命しているだけになります。
飛べない豚は、ただの豚だ！

という訳ではありませんが、いつかこのままでよいのかを考える時期が来ます。
そのとき、戦略を変えることをピボットと言います。

###ピボット
ピボットは、バスケットボールで片足を軸にして方向を変えるあれです。
重要なのは片足を軸にすること。片足とは今までやってきた事業やその中で得た学びです。だからこそ学びが重要になります。
今までの全てを捨てて別の方向に行くのはピボットとは言いません。

###革新会計
※このあたりはあやふやです。
「ユーザは増えてはいる」

でも10人増えているのは、100人登録したけど90人退会しているからかもしれない。

表向きの指標ではなく、現実を見る指標を使おうというのが革新会計という考え方です。
表向きの指標は「虚栄の評価基準」かもしれません。

#おわりに
リーン・スタートアップの話をしていると、なんか目的を忘れてるんじゃないかと思ったりするので書いてみました。一部を切りとって、さらに個人的な考えを入れています。

リーン・スタートアップに興味がある人はぜひ書籍『リーン・スタートアップ』を読んでみてください。著者の10年にわたるスタートアップ経験での失敗などが書いてあって面白いですよ。
Slackのリマインダーで月末日を指定できない件

Slackにはリマインダーの機能があります。

```
/remind me at 9:30AM on 20th of every month to "某店の特売日"
```

Slackで上記のように入力すると、毎月20日の9:30にSlackbotから「某店の特売日」というリマインダーメッセージが届きます。

チャンネルにリマインダーを設定することもできるので、月次の予定を入れて多くの人にアナウンスすることも可能です。

## リマインダーで月末日を指定する表現はない

しかし、この機能で月末日を指定するシンプルな表現はありません（2020年5月現在）。

「last day of every month」といった入力を理解してくれたらいいんですが、残念ながら未実装です。

世界には同じことに挑戦してあきらめた人がたくさんいるようです。

- [slack \- Slackbot how to set a reminder for last wednesday of the month or last day of the month \- Super User](https://superuser.com/questions/1037708/slackbot-how-to-set-a-reminder-for-last-wednesday-of-the-month-or-last-day-of-th)

上記ページでは 「あきらめてIFTTTで実現した」 「ワークアラウンドとして毎月28日に設定してはどうか」という悲しい結論になっています。

## リマインダーで月末日の指定をする方法（根性編）

どうしても月末にリマインダーを設定したい場合、下記のようにリマインダーを12個設定するしかないと思います。これでも4年に1回うるう年の2月に1日早くリマインドされるバグがあります。

```
/remind me at 9:30AM on January 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on February 28th every year to “経費精算わすれずに！”
/remind me at 9:30AM on March 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on April 30th every year to “経費精算わすれずに！”
/remind me at 9:30AM on May 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on June 30th every year to “経費精算わすれずに！”
/remind me at 9:30AM on July 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on August 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on September 30th every year to “経費精算わすれずに！”
/remind me at 9:30AM on October 31st every year to “経費精算わすれずに！”
/remind me at 9:30AM on November 30th every year to “経費精算わすれずに！”
/remind me at 9:30AM on December 31st every year to “経費精算わすれずに！”
```

ちなみに、下記のように書くと30日しかない月の翌月1日に発動してウザいです。

```
/remind me at 9:30AM on 31st of every month to "経費精算わすれずに！"
```

## グチ

月の最終日くらいサクッと実装してほしいですね…。上記の例であれば各月の最終営業日を設定したい気がするので、さらに複雑な表現まで対応してもらえると最高ですね。

Slackさん、よろしくお願いします（見てないと思うけど）。

## （追記）月末日の19時から24時までならリマインダーを設定できる

こういうハックは好きです🤣
日本では19時以降しか使えないんですけど、欧米なら割と実用的なのでは（真顔）

https://scrapbox.io/morisin/Slack_%E3%81%AE%E5%85%AC%E5%BC%8F%E3%83%AA%E3%83%9E%E3%82%A4%E3%83%B3%E3%83%80%E3%81%A0%E3%81%91%E3%81%A7%E6%9C%88%E6%9C%AB%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
Salesforce でデータ分析する方法まとめ

# はじめに
はじめて投稿します！TuQ です。

最近携わった案件で、クライアントから Salesforce（以下、Sf）上でデータ分析をしたいと相談を受けました。
相談を受けたはいいものの、Sf でのデータ分析って経験が浅く、どんな方法があるのか、あまり知りませんでした。。。

そこで、色々と調べたり、考えてみたものをまとめました！

# Salesforce でのデータ分析方法
Sf でデータ分析をする場合、以下の方法が考えられるかなと思います。

1. 1オブジェクトに複数種類のデータを登録し、レポートで分析
2. 複数オブジェクトを跨ぐ場合は、結合レポートで分析
3. 複数オブジェクトのデータを 1オブジェクトに集約し、レポートで分析
4. ダッシュボードで分析
5. 分析ツールやアプリを入れる

以下、さらに各方法のメリデメ等をまとめていきます！

### 1. 1オブジェクトに複数種類のデータを登録し、レポートで分析
![Qiita Sf データ分析図解 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646407/4842673f-c1c3-d39d-9e64-297677caec2e.jpeg)
Sf 標準を活かした最も簡単で便利な方法。
注意する点として…

- 1レポート上では単純な分析しかできない。  
例えば、データの比較や相関関係を分析する場合、2種類のデータを同じグラフ内に表示できる程度です。  
具体的には、収入と支出の金額比較、商談の金額と件数の相関関係など。
- 複数種類のデータのオブジェクトを分けるべきか、1つにすべきかの判断が難しい。  
今後の拡張性を取るなら 1データ 1オブジェクトに分けた方がいいし、分析にしか利用しないなら 1オブジェクトにまとめて保持でもいい。  
※上記については、別記事で判断のポイント等を書ければと思っています。

### 2. 複数オブジェクトを跨ぐ場合は、結合レポートで分析
複数のオブジェクトを跨いだ分析をしたい場合は、結合レポートを利用します。
例えば、取引先に紐づく請求データと支払いデータを比較して収支差を見るなどです。
![Qiita Sf データ分析図解 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646407/ae740ee1-17bc-c904-3b98-bdac71bb3142.jpeg)
注意する点として…  

- 結合レポートは、通常のレポートと比べて制限が強いです。  
例えば、マトリックス（表）形式でレポートを表示できない等です。  
※制限についての詳細は[こちら](https://help.salesforce.com/articleView?id=reports_unavailable_with_joined_reports.htm&type=5
)をご覧ください。
- また、使い勝手も通常のレポートと比べると、あまり良いとは言えません。  
例えば、2020年5月でレポートのデータを絞りたい場合、請求日や支払い日など各オブジェクトの日付項目を各々レポート条件に加えて、1つずつ日付を絞らないといけません。  
つまり、請求日と支払い日等を一括で絞ることができません。

### 3. 複数オブジェクトのデータを 1オブジェクトに集約し、レポートで分析
何らの理由でオブジェクトを分けたが、結合レポートでなく、通常のレポートで分析したい場合に有効な方法。
各オブジェクトのデータをバッチ処理で 1オブジェクトに集約して、レポートで分析します。
![Qiita Sf データ分析図解 3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646407/29785c7f-5ba3-0ab8-44eb-4337c5a6a530.jpeg)
バッチ処理の実装が必要ですが、1バッチ 2000件以下なら、レポート分析スナップショットを使って標準でも実装可能かと思います。
注意する点として…

- 集約データを保持するため、その分データ使用量を消費する。  
Sf はデータストレージが豊富とは言えない場合が多いので、定期的に削除せず、集約データを保持し続ける場合は、今後も含めデータ使用量に問題がないか確認が必要。

### 4. ダッシュボードで分析
ダッシュボードは、簡単に言うと、複数のレポート（グラフ）をまとめて一か所（一画面）で見るための機能です。

よって、レポートのソース元であるオブジェクトにより、グラフの表現が決まってしまいます。

つまり、今まで書いてきた通り、複数種類のデータを 1つのグラフ内で表示したいなら、1オブジェクトに複数種類のデータを保持しておく必要があります。
![Qiita Sf データ分析図解 4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646407/56e7fd56-282c-d683-d948-e30c2adaec9d.jpeg)
ただ、ダッシュボードは、検索条件で複数のレポートを一括で絞り込むことが可能です。

例えば、ダッシュボード上で請求のグラフと支払いのグラフが分かれて表示されていた場合、請求日を 2020年5月で絞った場合、支払い日も 2020年5月で絞られます。

ゆえに、ダッシュボード上で、2020年5月の請求と支払いのグラフを比較することが可能となります。
※結合レポートもダッシュボード上に表示可能ですが、検索条件で一括では絞り込まれません。

### 5. 分析ツールやアプリを入れる
1つのグラフで 3種類以上のデータの比較や相関関係を表示したいなど、Sf 標準ではできない高度な分析をしたい場合は、分析ツールやアプリを入れることを検討します。

例えば、Einstein Analytics や Tableau、MotionBoard（AppExchange）などでしょうか。
このあたりは、名前を聞いたことがあるくらいで、どんなことができるのかは具体的に書けないのですが。。。

なお、分析機能を個別開発するというのも選択肢としてはありますが、実際は避けた方がいいと私は思います。

理由は、実装の難易度が高く、分析方法が変更となった場合の改修に時間がかかるためです。
それなら、ランニングコストはかかりますが、最初から分析ツールやアプリを入れた方がいいと思います。

# さいごに
いかがでしたでしょうか？

レポート・ダッシュボードは、Sf でも人気な標準機能の 1つ。
レポート・ダッシュボードのデモを見たクライアントは、Sf で色んなデータ分析が出来そうと期待が高まりやすい印象です。

ただ、標準機能である以上、高度なことは難しいので、クライアントが何のためにどんなレポート（グラフ）やダッシュボードを参照したいのか、要件定義を通じて明確にし、最適なソリューションを提供できるようになりたいですね。

本記事がその一助となれれば、幸いです！
【vue.js】Maximum call stack size exceededがでた

コンポーネントを無限ループで呼ぶなどをしているとこのエラーがでるようです。

ただこういったケースでなくてもエラーが出ることがありました。
僕の場合は結構な量のイラストをインラインのSVGとしてvueのコンポーネントに貼り付けて呼び出したらなりました。

1つのvueファイルはmaxのサイズがあるみたいですね！
SVGをなんとか軽量化するか、更にファイル分けるで対策しました。
JavaScript Mapの覚書き

JavaScriptの`Map`の目的、初期化方法、簡単な使い方。

# Mapの目的
`Object`よりもキーと値の紐付け（マップ）を表すのに適切なオブジェクトを提供することです。[MDNのMap](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map)が詳しいです。

# Mapの初期化
デフォルトコンストラクタ`Map()`で作成して`set`で個別に代入することもできますが、配列リテラルでも初期化できます。

```js:配列リテラルによる初期化
'use strict'
new Map([[0, 0], ["a", "a"], [0.1, 0.1]])
// Map(3) { 0 → 0, a → "a", 0.1 → 0.1 }
```

# `Map`の高階関数による処理

`Map`の要素を取得するメソッドは`entries()`、`keys()`、`values()`ですが、いずれもイテレーターを返します。現状ではイテレーターは`filter`や`map`のような高階関数を実装しないため、一度`Array`に変換してから高階関数を適用する必要があります。

## キーがある型の要素からなる`Map`を作成する

`typeof k === "string"`の`string`を目的の型に置換して別の型でも適用できます。

```js:string型の場合
'use strict'
const m = new Map([[0, 0], ["a", "a"], [0.1, 0.1]])
new Map([...m.entries()].filter(([k, v]) => typeof k === "string"))
// Map { a → "a" }
```

## 値がある型の要素からなる`Map`を作成する

`typeof entry[1] === "string"`の`string`を目的の型に置換して別の型でも適用できます。

```js:string型の場合
'use strict'
const m = new Map([[0, 0], ["a", "a"], [0.1, 0.1]])
new Map([...m.entries()].filter(([k, v]) => typeof v === "string"))
// Map { a → "a" }
```

## 値を文字列へ変換した`Map`を作成する

```js
'use strict'
const m = new Map([[0, 0], ["a", "a"], [0.1, 0.1]])
new Map([...m.entries()].map(([k, v]) => [k, v?.toString()]))
// Map(3) { 0 → "0", a → "a", 0.1 → "0.1" }
```

`v?.toString()`の`?.`は値が`undefined`の場合の例外を防ぐために必要です。

## 値がundefinedの要素を除外した`Map`を作成する

```js
'use strict'
// Map(4) { 0 → 0, a → "a", 0.1 → 0.1, undefined → undefined }
const m = new Map([[0, 0], ["a", "a"], [0.1, 0.1], ["undefined", undefined]])
new Map([...m.entries()].filter(([k, v]) => v !== undefined))
// Map(3) { 0 → 0, a → "a", 0.1 → 0.1 }
```

## この投稿の方針

- 辞書の要素は分割代入する。「entry => ...」→「([k, v]) => ...」
- 配列はスプレッド構文で作成する。「Array.from(...)」→「[...x]」
【Ruby】paizaで頻出メソッドまとめてみた

#参考文献

- [【Ruby】getsとgets.chompの違いは改行にあり！](https://qiita.com/Take-st/items/26f29a6dea622d1e7e8d)
- [【Ruby】getsの使い方](https://qiita.com/aamonaamon9/items/7de49e4881ee07e24248)
- [paiza 開発日誌](https://paiza.hatenablog.com/entry/2019/09/20/%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82Ruby%E3%81%A7%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E3%81%91%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB)
- [Railsで簡単に英単語を複数形にする方法](https://qiita.com/narikei/items/023dbf1385e798836ae8)
- [Ruby　標準入力から値を受け取る方法](https://qiita.com/Hayate_0807/items/2e9705091b181a104621)

#入力メソッド

```
//入力値:文字列　改行：あり
input = gets

//入力値：文字列　改行：なし
input = gets.chomp

//入力値：数値   改行：あり
input = gets.to_i

//入力値：数値　 改行：なし
input = gets.chomp.to_i
```


# 配列メソッド

- [Ruby　標準入力から値を受け取る方法](https://qiita.com/Hayate_0807/items/2e9705091b181a104621)


```
//入力値を配列に格納　※数値　
input = gets.split.map(&:to_i)

//分割して配列に格納
a,b,c = gets.split(" ").map &:to_i

//入力値を順番に格納
a = readlines.map &:to_i


//複数行 && 複数要素の格納  ※文字列
lines = []
while line = gets
    lines << line.chomp.split(' ')
end


//複数行 && 複数要素の格納  ※数値
lines = []
while line = gets
    lines << line.chomp.split(' ').map(&:to_i)
end
```

# timesメソッド + 配列

```
//繰り返し回数
n = 5
//配列の設定
sample = []

//繰り返し回数分、配列に格納
n.times do
  sample.push(gets.chomp.split(" ").map &:to_i)
end
```

# eachメソッド + 配列

```
//入力値取得
sample = readlines.map &:to_i

//変数宣言
n = 5

//eachメソッド
sample.each do |i|
 if n < 10
    n += 1
 else
    puts "sample"
 end
end
```

# その他

```
//絶対値取得
n = 5
sample = n.abs


//単数形→複数形
sample = "post".pluralize
puts sample
```
機械学習・分類関係テクニック

#ロジスティック回帰

```python
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
X = data.data
y = 1 - data.target
# ラベルの0と1を反転

X = X[:, :10]
from sklearn.linear_model import LogisticRegression
model_lor = LogisticRegression(max_iter=1000)
model_lor.fit(X, y)
y_pred = model_lor.predict(X)
```

#混合行列
・2行×2列の行列が表示
・実データと予測データの行列が作成される
・左上が(0, 0)、右下が(1, 1)

```python
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y, y_pred)
print(cm)
```

#正解率
・予測結果全体に対し、正しく予測できたものの割合

```python
from sklearn.metrics import accuracy_score
accuracy_score(y, y_pred)
```

#適合率
・ポジティブと予測したものに対し、正しくポジティブと予測できたものの割合
　(右列側)

```python
from sklearn.metrics import precision_score
precision_score(y, y_pred)
```

#再現率
・実際にポジティブのものに対し、正しくポジティブと予測できたものの割合
　(下行側)

```python

from sklearn.metrics import f1_score
f1_score(y, y_pred)
```

#F値
・再現率と適合率の調和平均
・適合率と再現率はトレードオフの関係

```python
from sklearn.metrics import f1_score
f1_score(y, y_pred)
```

#予測確率
・0に分類されるか、1に分類されるかを0-1の連続値で表す手法(足したら1に等しくなる)
・scilit-learnはデフォルトで0.5が閾値に設定されている

```python

#model_lor.predict_proba(X)

import numpy as np
y_pred2 = (model_lor.predict_proba(X)[:, 1]>0.1).astype(np.int)
print(confusion_matrix(y, y_pred2))

print(accuracy_score(y, y_pred2))
print(recall_score(y, y_pred2))
```

#ROC曲線・AUC(要勉強)
・AUC:Area Under the Curve
・ROC:Recceiver Operating Characteristic
・AUCはROC曲線の下側面積
・ROC曲線・・・
　横軸：偽陽性率(False Positive Rate)、FP
　縦軸：真陽性率(True Positive Rate)、TP


```python

from sklearn.metrics import roc_curve
probas = model_lor.predict_proba(X)
fpr, tpr, thresholds = roc_curve(y, probas[:, 1])

%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

fig, ax = plt.subplots()
fig.set_size_inches(4.8, 5)

ax.step(fpr, tpr, 'gray')
ax.fill_between(fpr, tpr, 0, color='skyblue', alpha=0.8)
ax.set_xlabel('False Positive Rate')
ax.set_ylabel('True Positive Rate')
ax.set_facecolor('xkcd:white')
plt.show()

from sklearn.metrics import roc_auc_score
roc_auc_score(y, probas[:, 1])
```
A2019のAPI経由でBotを実行させるときに任意の値を引き渡す


＃A2019 での基本的なAPIの使い方については以下を参考にしてください。
[A2019でAPI＜基本の4選＞](https://qiita.com/stig/items/55aec0ffb81cb1bac2d7)

**A2019 では V11 から API の仕様が変わっています。**そこで、V11 では **botVariables** で指定していた値の引き渡しですが、A2019 ではどう指定すれば良いかを自身のメモ用も兼ねて。ちなみに、何が実装されているかはドキュメントサイトかSwagger（http://a2019Url/swagger/ ）にて基本的なところは確認できます。

まずは、BotDeploy（/v3/automations/deploy）時に、以下を追加してください。
この意味は（正直）不明なのですが、これを入れないと引き渡してくれない...

```JSON
  "runWithRdp": false,
```

次に引き渡したい値の指定の仕方はこちらです。
こちらで指定した値は、実行時には Bot 側の変数にセットされますので、あらかじめ API を実行する前に変数を作成しておく必要があります。

```JSON
    "string1": {         <--変数名
      "type": "STRING",  <--変数タイプ
      "string": "TEST"   <--引き渡したい値
    },
```

例ではStringですが、もちろん、他の型も指定可能です（全部は試していませんが...）。変数を設定する際は必ず、”入力として使用”をチェックしてください。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639355/ce634c29-002a-9abb-c062-7dc2ef1bcca6.png width=70%>

変数にさえ入ってしまえば、あとは自由自在に Bot 内で扱えますね。
サンプルとしては以下の感じです（一部抜粋）。

```JSON
{
  "fileId": "23282",
  "runWithRdp": false,
  "botInput": {
    "sInputString1": {
      "type": "STRING",
      "string": "rgdfg"
    },
    "string1": {
      "type": "STRING",
      "string": "TEST"
    },
    "bBooleanInput": {
      "type": "BOOLEAN",
      "boolean": true
```

（2020.06.03）変数設定時の”入力として使用”チェックボックスに関する記述を追記。
ESP32をAWS IoTにつなぐ3つの方法

ESP32をAWS IoTにつなぐ方法です。
自分用のメモです。

### Arduino+外部ライブラリー（MQTT+ArduinoJson）

簡単度：★★★★★

一般的なArduinoのライブラリー（MQTTとArduinoJson）を使って実現します。

参考
 https://github.com/aws-samples/aws-iot-esp32-arduino-examples
 https://aws.amazon.com/jp/blogs/compute/building-an-aws-iot-core-device-using-aws-serverless-and-an-esp32/

### Arduino+AWS製ライブラリー

期待度：★★★★★

aws-samplesのリポジトリ内で開発されています。Amazon iot C-SDKに存在しないGreengrass部分を開発しているようです。
名前がGreengrassとなっていますが、AWS IoTと直接やり取りすることもできます。

参考
 https://github.com/aws-samples/arduino-aws-greengrass-iot

### FreeRTOS

本気度：★★★★★

お手軽ではありませんが、AWS謹製でございます。おそらく新機能も一番早いでしょう

https://aws.amazon.com/jp/freertos/
Rails6にWebpackでjQueryとBootstrapを導入する方法

##はじめに
Rails6からWebpackが標準で導入されることになりました。
それに伴いBootstrapとjQueryの導入方法が変わったので手順をまとめました。


##インストール
以下のコマンドでインストールします。
正常にインストールされたかは`package.json`で確認できます。

```:ターミナル
$ yarn add bootstrap jquery popper.js
```

##BootstrapとjQueryの導入
下記を追加します
`require("jquery")`
`import 'bootstrap'`
`import '../src/application.scss' `

```app/javascript/packs/application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("jquery")                         //追加


// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

import 'bootstrap'                        //追加
import '../src/application.scss'          //追加
```


ここから--ここまでを下記に追加します。

```config/webpack/evironment.js

const { environment } = require('@rails/webpacker')

//ここから
const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)
//ここまで追加

module.exports = environment
```

app/javascript下にsrcを作成し、その中にapplication.scssを作成

```app/javascript/src/application.scss
@import '~bootstrap/scss/bootstrap';     //追加
```

##動作確認
正しく導入されたかを確認するために下記のファイルを作成しました。

```rb:demo.html.erb
<div class="container">
  <h1>Bootstrap</h1>
  <a class="btn btn-primary" href="#" role="button">Link</a>
  <button class="btn btn-primary" type="submit">Button</button>
  <input class="btn btn-primary" type="button" value="Input">
  <input class="btn btn-primary" type="submit" value="Submit">
  <input class="btn btn-primary" type="reset" value="Reset">

  <h1>jQuery</h1>
  <p id="hoge">赤色になるよ</p>
  <script>
    $("#hoge").css("color","red")
  </script>
</div>
```
<導入前>

|![スクリーンショット 2020-05-31 20.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497683/36236f18-d70f-1b52-92f3-0384255ad1e1.png)|
|:-:|


<導入後>
正しく導入された場合、ボタンが青色になり(Bootstrap)、文字が赤色になります。(jQuery)

|![スクリーンショット 2020-05-31 20.16.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497683/820074b1-9132-01cd-3da4-81259e8ccf5f.png)|
|:-:|

##おわりに
以上で導入は完了です!!
iOSでお気に入りの写真以外を一括削除する

こんにちは。
今回はiOSのカメラロールで、お気に入りの写真以外を一括削除するショートカットを作ったので紹介します。
ちなみにちょっといじると選択したフォルダ以外の写真を一括削除することもできます。

#目次
1. 完成形
2. 必要なアプリ
3. ざっくりな流れと説明
4. できあがり
5. あとがき

#1.完成形
###[お気に入りの写真以外を一括削除](https://www.icloud.com/shortcuts/04fe114f6ebf47cc8f2a2d8926105e2a)

ちなみに、実行すると本当に削除して良いか最初に尋ねられます。(なんか怖いから)
これは仕様なのですが、前述とは別に削除を実行する際も再度尋ねられます。
まぁボタン一つ押したら全部消えちゃうのも怖いですし確認はあった方がいいかなと個人的に思ってます。


ショートカットが開けない時は、
**iPhoneの設定→ショートカット→信頼されていないショートカットを許可**
にチェックを入れると開けるようになります。(※自己責任でお願いします)

また、そのチェックさえ入れられない時は、一度ショートカットアプリでなんらかのショートカットを実行するとチェックを入れられるようになります。

#2.必要なアプリ

- [ショートカット](https://apps.apple.com/jp/app/id1462947752)
- [Twitter](https://apps.apple.com/jp/app/id333903271)

#3. ざっくりな流れと説明
細かいところまで説明するとめちゃくちゃ長くなりそうなのでとりあえずスクショを貼っておきます。

最初は写真と動画をまとめて消したかったんですが、いい方法が思いつかなかったので写真と動画は別々に削除するようにしています。

また、タイトルでは「一括削除」と書いていますが、厳密には300件ずつ自動で削除する感じになっています。
また、先ほど「300件ずつ自動で削除」と書いていますが、厳密には300件ずつ手動で削除か否かを選択していきます。(苦ではない)
![イメージ 5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588777/0c3a7c5a-2ff5-8e11-578c-bcf388960742.png)
![イメージ 6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588777/34317b67-faec-61b7-ff83-c794f20452c4.png)


1. 変数nに300を設定しているのは、後で写真を削除する時に本当に一括で選択して削除しようとすると、仕様でエラーが出るからです。(たぶんメモリエラー的な。)
2. 「**すべての写真を検索(条件)**」で以下に当てはまるアイテムを指定しています。
 - 写真・動画のうち写真のみ
 - よく使う項目ではない(<font color="red">=お気に入りではない</font>)
 - 非表示ではない<br><br>
 ちなみにここで写真を指定した理由は、ただ単にアイテムの数を取得したいからであり、ここで指定した写真をそのまま削除するわけではありません。
3. 「**次の場合に写真を検索 の 項目 の数を数える**」らへんでは、後に繰り返し処理を行う際のループ数を決定しています。
4. 繰り返しの中の 「**すべての写真 を検索(条件)**」では、(最新のものから)写真を300件選んで、次のアクションでそれを削除しています。<br>
上記の繰り返し処理をして、すべてのお気に入り以外の写真を分割で削除します。
5. お次は動画です。<br>
しかしやることはほとんど変わりないので説明は省きます。
ちなみに変数mが50なのは、ファイルサイズが写真よりも大きいと考え、エラーにならないようにしています。
6. 終わり！

<br>
####なんかエラー出るんだけど
n,mも300件,50件と設定していますが、一つ当たりのファイルサイズが大きいとこれでもエラーが出る場合があります。その時はn,mの値を減らしてみましょう。

####最初の確認は必要ない
最初のアラートを消してください。

####間違えて実行して写真消しちゃった
カメラロールには「最近削除した項目」という項目があるのでそこから復元してください。

#4. できあがり
完成したら、ホーム画面からでもウィジェットからでも実行できるようになるはずです。(たぶん)(そんなに実行の頻度高くないだろうからいらなさそう)

#5. あとがき
ショートカットアプリが楽しくていろいろ試してみてます。
JavaScriptを活かしてできることもあるみたいですが、JSはあまり詳しくなくて歯痒さがあります。

無駄なところは多々ありますがご愛嬌と言うことで・・・
重大なミスやさすがにこうした方がいいとかがあればぜひ教えてください。

ではまた！
【PHP（Laravel）】ControllerからViewにデータを渡す２つの方法

## 概要
1. ビューメソッドを使用してデータを渡すビューを指定する。
2. データを渡す。（方法２つ）


## 1.ビューメソッドを使用してビューを指定する
例）articlesコントローラーのindexファイルを指定する

````
return view('articles.index')
````

## 2.データを渡す。（方法２つ）

データが入った変数 $articles をビューに渡す。

1.Withメソッドでデータを渡す。

````
return view('articles.index')->with(['articles' => $articles]);
````
2.Compact関数でデータを渡す。

````
return view('articles.index', compact('articles'));
````
vagrant でgit pushできない

## エラー内容
```
$ git push origin master
Permission denied (publickey). fatal: Could not read from remote repository.  Please make sure you have the correct access rights and the repository exists.
```
## 解決策
### vagrant 環境でgitの秘密鍵が設定されていないから。
まず、ローカルで

```
cd .ssh
cp id_rsa ~/Document/work/vagrant
```
仮想環境で

```
mv id_rsa ~/.ssh
```
これでOK!
初めてC#を学習する方へのおすすめサイト

数あるプログラミング言語。
初めての学習でC#を選んだけど、どうやって進めていくか迷っている方へおすすめのサイトをまとめました。

# 初めてならば動画やシステムで学べるサイトが一番
私は初めての言語はC言語でした。
書籍を購入して、頭から順番に読み進めながら問題に挑戦するという、王道ともいうべき進め方でした。

昨今ではWebサイトの充実により、書籍でなくても入門しやすくなっています。
HTML/CSS/JavaScript/Java/Goはすべてサイト学習しました。

そんなサイト学習での定番サイトと言えば

- [ドットインストール](https://dotinstall.com/)
- [Progate](https://prog-8.com/)

が有名です。(Web関連の言語が多いです。)

C#はというと

- [ドットインストール](https://dotinstall.com/)ではPREMIUM(有料会員向け)のみ
- [Progate](https://prog-8.com/)では掲載無し

となっています。
初めての言語学習で、いきなり有料会員登録というのも抵抗があるかと思います。

そこで、C#の動画学習サイトとしては、[paizaラーニング](https://paiza.jp/works/)がおすすめです。

## C#の初期学習はpaizaラーニングがおすすめ
[paizaラーニング](https://paiza.jp/works/)も[ドットインストール](https://dotinstall.com/)/[Progate](https://prog-8.com/)のように一部有料会員向けで構成される動画学習サイトですが、
C#は(2020/05/31現在)<b>完全無料</b>で公開されています。

内容としては

- C#入門編1: プログラミングを学ぶ
- C#入門編2: 条件によって処理を変えてみよう
- C#入門編3: ループ処理を学ぶ
- C#入門編4: 配列の基礎
- C#入門編5: 多次元配列を理解しよう
- C#入門編6: メソッドを理解しよう
- C#入門編7: クラスを理解しよう
- C#入門編8: さらにクラスを理解しよう
- C#入門編9: Dictionaryの基礎
- C#入門編10: 例外処理を理解しよう

と、全10レッスンで構成され、各章6～11チャプターで構成されています。
全くプログラミングしたことない方でも入門できる難易度で構成されているのでおすすめです。

C#以外で言語学習したことがある方は各レッスン/チャプターの演習問題だけトライすることで
誤答だったり、曖昧だった箇所のみ解説を聞くことでスムーズに学習できると思います。

また[paizaラーニング](https://paiza.jp/works/)ではブラウザ上でコーディングできるので開発環境はいりません。
※PC上で環境を作りたい方は以下を参考にしてみてください。
[Windows10+VSCode+.NET CoreでC#開発環境を作ろう！](https://qiita.com/mekemeke421/items/102b76fdb1c2eb879901)

# 知識がついたら練習あるのみ
一通り知識がついたら、実際にプログラミングすることが上達にはかかせません。
その為には問題・回答がスムーズにできるサイトを利用するのがおすすめです。

そのなかでもおすすめなのはプログラミングコンテストで有名な[AtCoder](https://atcoder.jp/?lang=ja)の練習サイトである[AtCoder Problems](https://kenkoooo.com/atcoder/#/)です。

数多くの問題を、こちらもサイト上でプログラミング・提出することができ、
正解・不正解をその場で確認できます。

はじめはA問題：灰グレード、B問題:灰グレードを選んで挑戦すると良いでしょう。
基本である入力・出力を中心にアルゴリズムも学ぶことができます。

AtCoderはC++における解説ページが多いですが、人気なため学習のたすけとなるサイトも多いので、詰まった時にも助けになるケースは多いです。

# まとめ
今回は初学者向けのサイトを紹介しました。
C#はWindowsアプリケーションだけでなくMac/LinuxやCloudなどのバックエンドでも利用が増えている言語です。
是非、学習してみてください。
AWSの各サービスの説明が15文字程度シンプルすぎて妙にわかりやすかった件

（備忘録）
サービスが増えすぎてAWSやAzure全体像が分かりにくくなってきている今、
各サービスに対し極めてシンプルな説明が喜ばれる時代になってきている気がした。

【日本語】
https://gigazine.net/news/20200528-aws-one-line-explanation/

【英語 / English Simple Explanation of AWS Services】
https://adayinthelifeof.nl/2020/05/20/aws.html

【Azureとの対比日本語】
https://docs.microsoft.com/ja-jp/azure/architecture/aws-professional/services

【Azureとの対比英語 AWS vs. Azure Comparison】
https://docs.microsoft.com/en-us/azure/architecture/aws-professional/services