OmniAICreator/Qiita-1.07M huggingface dataset:
7つのアクションのみによる検索機能

##7つのアクションのみで検索機能を実装
今回はモデル名をTweet、Comment、Userとします。
【例】今回はtweetsのindexアクションに記述します。

```app/views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :get, class: "XXXX") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "YYYY" %>
  <%= form.submit "検索", class: "ZZZZ" %>
<% end %>
〜省略〜
```
##ディレクトリ::searchesコントローラーを作成
searches_controller.rbは、ユーザーを検索するのか投稿を検索するのか明示されていないため分からなくなります。区別できるように今回はtweetsディレクトリを用意し、そこにsearches_controller.rbを作成します。
ターミナル

```
rails g controller tweets::searches
```
【例】app/controllers/tweets/searches_controller.rb

```
class Tweets::SearchesController < ApplicationController

end
```
Tweets::の部分は、名前空間またはnamespaceと呼ばれるます。
##名前空間(namespace)
名前の集合を分割することを名前空間と呼びます。名前空間を用いることで、同様のクラス名を名付けたクラスであってもそれらを区別することができます。
今回の場合、tweetsディレクトリの配下にsearches_controller.rbを作成し、Tweets::という名前空間が付けられたため、く「tweet投稿を検索するコントローラー」ということです。
例えば、Usersディレクトリも作成したとしてSearchesControllerが同じクラス名になりますが、Users::とTweets::で名前空間によって違いが明確になります。
##namespaceメソッド
名前空間で生成されたコントローラーへのルーティングを設定する際に使用します。
名前空間を利用するとcontrollersディレクトリ直下にさらに新規ディレクトリを作成し、そこへコントローラーを生成した状態になっているため、通常の記述ではルーティングが設定できないためです。
【例】

```config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  root to: 'tweets#index'
  namespace :tweets do
    resources :searches, only: :index
  end
  resources :tweets do
    resources :comments, only: :create
  end
  resources :users, only: :show
end
```
上記のようにnamespace :ディレクトリ名 do ~ endと囲む形でルーティングを記述すると、そのディレクトリ内のコントローラーのアクションを指定できます。
必ずnamespaceメソッドの記述は、resources :tweets doよりも上の行に書きます。
もし下の行に書くと、先にtweetsのshowアクション（tweets/:id）が読み込まれ、実際に検索した時にエラーが出てします。
##検索フォームの送信先
【例】

```app/views/tweets/index.html.erb
<%= form_with(url: tweets_searches_path, local: true, method: :get, class: "XXXX") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "YYYY" %>
  <%= form.submit "検索", class: "ZZZZ" %>
<% end %>
〜省略〜
```
tweets_searches_pathでパス指定します。
##コントローラーに定義
【例】今回はindexアクションに定義します。

```app/controllers/tweets/searches_controller.rb
class Tweets::SearchesController < ApplicationController
  def index
    @tweets = Tweet.search(params[:keyword])
  end
end
```
##検索結果画面のビューの作成
【例】

```app/views/tweets/searches/index.html.erb
<%= form_with(url: tweets_searches_path, local: true, method: :get, class: "XXXX") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "YYYY" %>
  <%= form.submit "検索", class: "ZZZZ" %>
<% end %>
〜省略〜
```
上記の記述で7つのアクションで検索機能ができました。
ホームポジションを崩さずに矢印キー（↑←↓→）を入力できるようにしてみた （コーディング）


私はコーディングや編曲をする際によく矢印キーを使うのですが

その際にいつも
「ああ矢印キーを押すときにホームポジション崩れるの嫌だなあ。。。。」

と感じていたので、矢印キーとして機能するショートカット用のコードを書きました！！

具体的には、Functionとwasdそれぞれの組み合わせで、上左下右を入力できます。
FPSゲームのWASDと同じノリですね。

下の方に詳しく書きますが、当コードはKarabinerというキーボードカスタマイズソフト上で機能します。各々書き換えて使ってください！



（ちなみに、システム環境設定の’キーボード’で、’キーのリピート’を最速、’リピート入力認識までの時間’を最短に設定しておくと、矢印キーがすいすい機能するので、おすすめです。）




#コード
function+w : 矢印キー（上）
function+a : 矢印キー（左）
function+s : 矢印キー（下）
function+d : 矢印キー（右）


上記のショートカットなどが以下のコードで作れます。

```json:Fn+wasdtoArrowKeys.json
{
  "title": "fn + wasd to Arrow Keys Vim",
  "rules": [
    {
      "description": "fn+ wasd to arrow keys Vim",
      "manipulators": [
        {
          "from": {
            "key_code": "w",
            "modifiers": {
              "mandatory": [
                "fn"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "up_arrow"
            }
          ],
          "type": "basic"
        },
        {
          "from": {
            "key_code": "a",
            "modifiers": {
              "mandatory": [
                "fn"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "left_arrow"
            }
          ],
          "type": "basic"
        },
        {
          "from": {
            "key_code": "s",
            "modifiers": {
              "mandatory": [
                "fn"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "down_arrow"
            }
          ],
          "type": "basic"
        },
        {
          "from": {
            "key_code": "d",
            "modifiers": {
              "mandatory": [
                "fn"
              ],
              "optional": [
                "any"
              ]
            }
          },
          "to": [
            {
              "key_code": "right_arrow"
            }
          ],
          "type": "basic"
        }
      ]
    }
  ]
}

```



#使い方
1. Karabinerをダウンロードする
https://pqrs.org/osx/karabiner/

2. 上記のコード、またはそれを書き換えたものを、以下のフォルダに保存する
`/Users/ユーザ名/.config/karabiner/assets/complex_modification`

3. Karabiner上で有効化する
メニューからPreferenceを選択
↓
Complex Modificationsを選んで、左下のaddを選択
↓
上で保存したショートカットが選べる様になっているので、Enableを選択して有効化する
↓
終わり

#おまけ
ちなみに私はこのKarabinerを使って、

・英数キーを、全角/半角キー（押すと英数かなが入れ替わる）に変更
・controlをenterに、かなキーをdeleteに変更
・CapsLockをcontrolに変更

という感じにキーを再配置したり、
ショートカットでLINEやChromeを開けるようにしたりしています。
https://qiita.com/naototomita/items/d22b165af13255eefbe5
Sipeed Lichee Zeroをネットに繋ぐ

#インターネットに繋ぎたい
このデバイス中のOSはDebianベースのようでaptコマンドも入っていた。なのでインターネットに接続してアップデートしたい。

ただこのデバイスデフォルトの状態だとイーサーネットもwifiも無いのでネットには繋げられない。
繋げる方法として考えられるのがUSBの仮想イーサーネットをLinuxのPC使ってブリッジするかUSBのwifiドングルを使うのか二通り。

ブリッジでの方法は最初wifiが上手く繋がらなかったので1回やったが非常に面倒くさかった。


#wifiドングル
Linuxでドライバが当たりやすい事で有名な2種類を試してみた。
左がバッファローのWLI-UC-GNM
右がPLANEXのGW-USNANO2A
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599350/d02cd5ff-952f-6e62-c2a6-e8d41058b7c9.png)
結果としてWLI-UC-GNMはネットワークデバイスとして認識しませんでしたがGW-USNANO2Aはwlan0として認識しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599350/72c24c1b-9b65-bc3c-0d9d-1a380766c575.png)

USBにドングルを繋ぐとUSBから給電できないので5Vをピンヘッダから給電して動かす。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599350/046510e4-7c5a-4cd3-60ca-e61e39a6a249.png)


#wifiの設定
###wifi設定ファイルの作成・追記
ドングルが認識されているのでwifiの設定をします。
まず次のコマンドでwifiの設定の雛形を生成
```root@LicheePi:~# wpa_passphrase "Your_SSID" Your_passwd```
おそらくこういう感じで出力されているはず。
セキュリティ上、生のパスワードは削除しておいた方がいいかも。(#の部分)
network={
ssid="${your ssid}"
\#psk="${your password}"
psk=${key}
}

上記のコマンドで出力された内容を、/etc/wpa_supplicant/wpa_supplicant.confに追記、無ければ作成します。
```root@LicheePi:~# vim /etc/wpa_supplicant/wpa_supplicant.conf```

新規作成した場合は下記の内容をファイルの先頭に書き込んでその後に設定を書き込む。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP


###wifi設定ファイルを登録
```root@LicheePi:~# vim /etc/network/interfaces```
この行を追加
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

※wlan0の個所は環境によって変わるかもしれないのでその場合は変更

その後再起動すると繋がった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599350/fa194cfa-09ff-ae3d-0ab4-96561d7a8426.png)


ここまで来たらapt updatteでアップデート出来る。

あとついでだがこのデバイスのOSデフォルトだとタイムゾーンが香港になっていた。
そのままでは何かと不便なので日本時間に変更する
```root@LicheePi:~# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
このコマンドを打つと即座にタイムゾーンが切り替わる。



###続き
[Sipeed Lichee ZeroでLチカとか(GPIO操作)](https://qiita.com/17_kitano/items/aecf3f7dfb0d376f4347)
vue-cliで作ったプロジェクトでconsole.log()を許可する

## 白学ラン風紀委員長、eslint

vue-cliのデフォルト設定でプロジェクトを作ると有効になるeslintパイセン。
間違っているところを厳しく指摘してくれるJavaScript界の風紀委員長ですね。
しかし彼は融通というものを知らないので、決められたルールは必ず守らせようとプロジェクトの中であればどんな些細なコードでも指摘してきます。
デバッグがてらちょっとconsole.logしようものなら絶対にbuildさせてくれません。
ちょっとでいいから許していただきたく、ルールを書き換えることにしましょう。

## package.jsonでルールが指定できる 

eslintのルールはpackage.jsonの```eslintConfig```内で設定することができます。

```json:package.json
"rules": {
  "no-console": 0
},
```

これでconsole.logを書いても追いかけてくることはなくなりました。めでたしめでたし。

## package.json全体で見ると

上記のように書かれていることが多い設定箇所ですが、npmやりはじめたばっかりマンだといまいちピンときません。
ファイルの場所から丁寧に書いてみると、以下になります。

編集するpackage.jsonはプロジェクト直下にあります。

```terminal:ファイルパス
mockup // vue-cliで作成したプロジェクト
├.gitignore
├babel.config.js
├node_modules
├package.json // <----- 編集するファイルはこれ
├public
├README.md
├src
└yarn.lock
```

ルールを記述する場所は```eslintConfig```の中の```rules```です。

```json:package.json
{
  "name": "mockup",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.4",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.2.0",
    "@vue/cli-plugin-eslint": "^4.2.0",
    "@vue/cli-service": "^4.2.0",
    "babel-eslint": "^10.0.3",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.1.2",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {} // <---- 編集する場所はここ
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

```

編集するとこんな感じになります。

```json:package.json
{
  "name": "mockup",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.4",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^4.2.0",
    "@vue/cli-plugin-eslint": "^4.2.0",
    "@vue/cli-service": "^4.2.0",
    "babel-eslint": "^10.0.3",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.1.2",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {
      "no-console": 0
    },
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

```

それではよきconsole.logライフを～。
カレントディレクトリのパスをクリップボードにコピーする方法(mac)


ターミナルで`/Users/user-name/sample/foo-bar`のようなカレントディレクトリにいる場合に、もう一つ同じパスでターミナルを開いて同じカレントディレクトリを開きたい場合に、該当のディレクトリのパスをクリップボードにコピーして楽をする。

コピーしたいディレクトリで下記コマンドを実行し

```sh
pwd | pbcopy
```

別のターミナルを開き 
cd と打った後にcmd+vでクリップボードの中身をペーストするとカレントディレクトリのパスが表示される

```sh
cd /Users/user-name/sample/foo-bar
```

------

## pwd | pbcopy このコマンドを分解して解説

```sh
pwd | pbcopy
```

`pwd` 現在いるディレクトリを(標準出力に)表示する

`|` 出力(標準出力)される内容を次のコマンドの入力(標準入力)にわたす

`pdcopy` macにおいて、標準入力からクリップボードにコピーする
WordPressのREST APIで一気に大量の記事を取得したい

# はじめに
WordPressのREST APIで一気に大量の記事を取得したいことがあったので、そのときの対処法をメモしておきます。
だいたいは10件、20件ずつ取ると思うので、あまり普通の使い方の場合には当てはまらないと思いますが...

[REST APIの公式ドキュメント](https://developer.wordpress.org/rest-api/)

みなさんよくお使いになる`get_posts`関数では、全件を取得する場合は、`posts_per_page`に`-1`を入れればOKですが、WP-REST-APIではそうはいきません。
WP-REST-APIだと、`per_page`というパラメーターになりますが、2020年3月現在、最大100件までしか取得できず、100以上の数値を入れるとエラーとなります。

今回はページネーション機能を利用して、100件以上ある場合もすべて取得したいと思います。

# コード
※Vue.jsで書いてあったコードをjavascript, jQueryで書き換えたので、動作確認はしてません。
※固定ページを取得しています。

``` js

var nowPage = 1
var totalPage = 1

init()

async function init() {
    while(1) {
        count++

        await getAllPages()

        nowPage++

        //トータルのページ数より多くなったら、終わり
        if(nowPage > totalPage) {
            break
        }
    }
}

async function getAllPages() {
    await $.ajax({
        url: 'your-url/wp-json/wp/v2/pages', //投稿を取得したい場合は、postsにしてください
        type: 'GET',
        data: {
            per_page: 50,
            page: nowPage,
        }
    }).done( (data, status, xhr) => {
        //トータルのページ数を取得
        totalPage = parseInt(xhr.getResponseHeader('x-wp-totalpages'))

        //なんか処理
    })
    .fail( (data) => {
        console.log(data)
    })
}

```

# ハマったところ
今回、100件以上ある固定ページを50件ずつ取得しようとしたのですが、デフォルトだと、並び順は作成日時の降順になっています。
固定ページの自動生成をして、一気に作ったページの場合は、日時が重複していたので、ちょうどページの変わり目に重複した日時の記事が来たときに、２件取得される記事と１件も取得されない記事がありました。

そういう場合は、IDの昇順にするなどして対応してもらえれば回避できます。
MySQL server has gone away の時は wait_timeout

*connect_timeout と毎回間違えるのでメモ・・・*

バッチ処理などで下記のエラーが出て MySQL との接続が切れた場合。

```
HY000 2013 MySQL server has gone away
```

タイムアウト系の設定で関係があるのは **wait_timout**

# 設定値の確認

```sql
show global variables like 'wait_timeout';
```

```
MariaDB [(none)]> show global variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 10    |
+---------------+-------+
1 row in set (0.01 sec)
```

# 設定変更

```sql
set global wait_timeout = 120;
```

global つけるとサーバー自体の設定が変わってしまうので、スクリプト内でだけ変更したいとかなら、global なしで。

```sql
set wait_timeout = 120;
```

pdo ならこんな感じ。

```php
$pdo->query("set wait_timeout = 120");
```

pdo は `mysqli::ping()` 的な再接続系のメソッドが無いので、自作する必要があるところが残念。
NGINXでNGINXにしたら404したけど？


# 始まり

「404だ。」簡単な設定しかしていないはずなのになぜ？
ドキュメントルートにアクセスできないなんて初歩的すぎる！
恥ずかしながら３時間くらいかかってようやく解決しました。

# 環境

- Windows 10
- Nginx 1.16.1

# そもそもWindowsだから起きた問題

Windowsでは逆スラッシュ「＼」=円マーク「￥」がディレクトリセパレーターです。
調べると、スラッシュ「／」でも動作する場面が多いようですが、大抵は見かけるのは円マークです。
Linux系では「スラッシュ」が当たり前です。
このセパレーターの違いが１因でした。

# パスをWindowsっぽく書いた

nginxはもともとLinux向けのソフトウェアというのもあって、
スラッシュで各種設定を行っても動作するらしいです。

そんなことは知らない私は、Windows的にバックスラッシュで設定をしてしまいました。

# 異常な設定

これがその異常な設定です。

```conf:/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        listen       443 ssl;
	server_name  192.168.30.123 test.domain.local;

        ssl_certificate      C:\ssl\server.crt; # ここに円マークを使用している

        ssl_certificate_key  C:\ssl\server.key; # ここに円マークを使用している

        location / {
            proxy_pass http://127.0.0.1:8080/;
        }
        location /test {
            alias e:\nginx; # ここに円マークを使用している

            index index.html;
       }
    }
}
```

# エラーログ

`:/logs/error.log
2020/03/09 13:58:56 [crit] 900#5188: *11 CreateFile() "e:

ginx/index.html" failed (123: The filename, directory name, or volume label syntax is incorrect), client: 192.168.0.18, server: 192.168.30.123, request: "GET /index.html HTTP/1.1", host: "test.domain.local"
`"e:ginx/index.html" failed` とあります。
これをみて即座に、`"e:`と`ginx/index.html" failed`の間に改行があるのがお判りいただけたでしょうか？

# 重なった偶然

- Windows形式のパスで書いたこと
- フォルダ名がNginxであったこと
- ssl_certificateの設定はWindows形式でも問題なかったこと
- エスケープシーケンスなんて忘れていたこと

# 結論

セパレーターをスラッシュにすればエスケープシーケンスは忘れても良さそうです。

# 正常な設定

というわけで以下のような設定にしました。

```conf:/conf/nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        listen       443 ssl;
	server_name  192.168.30.123 test.domain.local;

        ssl_certificate      C:/ssl/server.crt;
        ssl_certificate_key  C:/ssl/server.key;

        location / {
            proxy_pass http://127.0.0.1:8080/;
        }
        location /test {
            alias e:/nginx;
            index index.html;
       }
    }
}
```

# 2023年7月追記

そもそもWindowsでNginxを使うのは、おすすめできません。
どうしても必要な場合は、WSL2を使うことをおすすめします。

**Excelsior!**
class_name

## class_nameとは
アソシエーションのオプションの一つで、関連づけするモデルの名前を変えたいときに使用します。
通常

```ruby:post.rb
class Pweet < ActiveRecord::Base

belongs_to :user
has_many :comments

end
```

と表記することでuser、commentsと関連づけすることができますが

class_nameを使用すると

```ruby:post.rb
class Post < ActiveRecord::Base

belongs_to :owner, class_name: 'User'
has_many :comments

end
```
と表記することでuserの内容のままownerと関連づけることが可能です。
macOSでLaravelの環境構築でつまずいた

macOSでLaravelの開発環境を構築した時に、引っかかった箇所とその解決方法です。
いくつかのサイトやQiitaの記事を参考にしたので、同じようなパターンでハマった人がいたら参考にしてみてください。

##使用環境
- macOS Catalina
- PHP version 7.3.8
- composer version 1.9.2
- Laravel installer 3.0.1

##やったこと
下記を書いている方と奇跡的に開発環境が同じだったので、書かれている内容を踏襲して実行しました。
[macOS CatalinaにしてからLaravelの環境設定が詰まった](https://qiita.com/michimoy/items/73834c07f425a55ee552)

一通り良さそうなのでLaravelのプロジェクトを作ってみる

```
$ laravel new sampleApp
```

エラー

```
[InvalidArgumentException]                                
  Script "post-install-cmd" is not defined in this package
```

composerのアップデートの問題らしいので以下を実行

```
$ composer global update
```

できた！

```
$ laravel new laravelApp
Crafting application...
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock 
~
~
Package manifest generated successfully.
Application ready! Build something amazing.
```
##参考サイト
- [macOS CatalinaにしてからLaravelの環境設定が詰まった](https://qiita.com/michimoy/items/73834c07f425a55ee552)
- [【Larvel】Larvelに入門してみた。プロジェクト作成まで](https://jitaku-server.com/?p=201)
d3.jsでforceSimulation その２

#概要

d3.jsでforceSimulationやってみた。
v5で、やって見た。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/3836c0e9-f7bf-a892-ffad-fd095dae7541.png)



#成果物

https://embed.plnkr.co/plunk/vg71nYCi2xvlPtOS


以上。
Cloud Storageで特定のバケットのみ閲覧させる方法

# はじめに
- ここでは、Cloud Storageにおいて、特定のバケットのみ閲覧させる方法についてまとめる。

# バケットレべルでの設定
1.  GCS Web UI で、制限したいバケット名の一番右にあるメニューをクリックし、[バケットの権限を編集] を選択。
1.  [メンバーを追加] をクリックし、登録したいアカウントを入力し、役割に以下の２つを付与 。   
    - ストレージのオブジェクト作成者  
    - ストレージのオブジェクト閲覧者  

※上記の２つ役割で、特定バケット内でのオブジェクト作成のみが可能になる。
※オブジェクトの削除なども行いたい場合には、登録した２つの代わりにストレージのオブジェクト管理者のみを役割として付与する。



#  IAM レベルでの設定
1. Cloud IAM上で左のメニュー内の[役割]をクリック。
2.  [役割を作成]をクリックし[権限を追加]で、storage.buckets.listを選択し、[追加]をクリック。  
（storage.buckets.listの権限はストレージ管理者の中にある）
3.   IAM に戻り、上の方に表示されている[追加]をクリックし、登録したいアカウントを[新しいメンバー]に入力。
5.  以下の役割を付与。  
    - プロジェクトの参照者   
    - 2で作成したカスタム役割 (Customの項目内に、名付けた名前で表示される)   

※上記の２つ役割で、特定バケットのみアクセス、オブジェクトの作成等が可能になる。 
 **※ ストレージのオブジェクト作成者やストレージ のオブジェクト閲覧者の役割を付与してしまうと、設定した権限がバケットすべてに継承され、他のバケットもアクセス可能になるので気をつけること。** 



# ポイント
- 今回の設定に関するポイントは以下の通り。
    - IAMレベルではリソース(GCS)に対する権限を設定。
        - リソース(GCS)へのアクセスできるか？
        - バケット一覧を表示できるか？
    - バケットレベルではバケット個別に対する操作権限を設定。
        - オブジェクトを閲覧できるか？
        - オブジェクトを作成できるか？
        - オブジェクトを削除をできるか？
- IAMレベルで全体を設定し、バケットレベルで個別に設定するということを意識する。
C言語　素数を求める試し割り法のコード

100までの素数を出力するコード

```c
#include <stdio.h>
void prime(void){
    int i,j,flag;
    
    i = 2;
    while(i <= 100){
        flag = 0;
        j = 2;
        while(j < i){
            if(i % j == 0){
                flag = 1;
                break;
            }
            j++;
        }
        if(flag == 0){
            printf("%d\n", i);
        }
        i++;
    }
}

int main()
{
    prime();
    return 0;
}
```
UnityにおけるDropdownリストの使い方

### UnityのUIの使い方の備忘録
UnityにおいてDropdownリストの作成を行い、リストにおいて選ばれているものをログにおいて表示を行います。[参照URL](https://xr-hub.com/archives/12118)

### 方法について
まず、UIからDropdownを追加します。Dropdownリストの中のオプションについてはInspectorの下の方に存在している。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199067/ad262f69-77ee-8936-961e-3e05fe6f5706.png)
このオプションに追加及び削除を行うことが出来ます。また、選択されているものにはvalueという値がつけられています。選択されているオプションの値が画像上部のvalueの値が変更されます。

### 変更された際のコードについて
```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class Decision_ELEVATOR : MonoBehaviour {

    [SerializeField] private Dropdown choiceMethod;
    [SerializeField] private Dropdown choiceMovie;

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
        

    }

    public void OnClick()
    {
        Debug.Log("choiceMethod : " + choiceMethod.value + "choiceMovie : " + choiceMovie.value);

        if (choiceMovie.value == 0)
        {
            Debug.Log("choiceMovie : 0");
        }
        //DropdownのValueが1のとき（青が選択されているとき）
        else if (choiceMovie.value == 1)
        {
            Debug.Log("choiceMovie : 1");
        }
        //DropdownのValueが2のとき（黄が選択されているとき）
        else if (choiceMovie.value == 2)
        {
            Debug.Log("choiceMovie : 2");
        }
        if (choiceMethod.value == 0)
        {
            Debug.Log("choiceMethod : 0");
        }
        //DropdownのValueが1のとき（青が選択されているとき）
        else if (choiceMethod.value == 1)
        {
            Debug.Log("choiceMethod : 1");
        }

    }
}

```
ボタンの作成を行い、このスクリプトを追加します。その後作成してあるDropdownをInspectorにおいて追加を行います。

これによって、ボタンを押すことでログにどのオプションが選ばれているかということを表示することが出来ます。
【メモ】SQLの定期実行

SQLを定期実行する。覚えられないためメモ。
環境：RHEL6.5
ORACLE：
#1.SQLを定期的に等間隔で実行する
while true; do
	echo "@select.sql"
  sleep 5 ;
done | sqlplus / as sysasm

#2.CronでSQL実行の予約

####test.sh
\#!/bin/bash -l
export ORACLE_SID=＊＊＊
sqlplus / as sysdba @/home/oracle/test.sql

####test.sql
spool /home/oracle/sysdate_test.txt app
select TO_CHAR(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') from dual;
exit

##クーロン登録(実行ユーザーでcrontab -e)
	# m h day mon dow user  command
	*/10 * * * * /home/oracle/test.sh 1>/dev/null 2>/dev/null

service crond status
VirtualBox+Vagrant+MySQL環境構築

駆け出しデータサイエンティストのNishです
業務のためにSQLの自主練をする必要があったので、CentOS7の仮想マシンにMySQLを導入してみました
MySQLのインストールから、MySQLサーバの動作確認までの作業を記事にまとめました

# 仮想マシン作成
仮想マシンを作成する記事は以前に書いたので、詳しくはそちらを参照頂けると
[VirtualBoxのインストール](https://qiita.com/Nish1729/items/d92ff401cb3161d768e9)

[VirtualBox + Vagrantで環境構築しよう](https://qiita.com/Nish1729/items/b8b19fd59161f6a67534)

作業ディレクトリを作成

```
$ cd ~/Documents/
$ mkdir workspace
$ cd workspace
```
作業ディレクトリで仮想マシンを作成して起動・ログイン

```
$ vagrant box add centos/7
$ vagrant init centos/7
$ vagrant up
$ vagrant ssh
```

# MySQLをインストール

リポジトリ情報を最新にupdate

```
$ sudo yum update -y
```

MySQLはyumコマンドでインストールします
どうやら、公式のリポジトリにはMySQLがないようなので、
MySQLが公式に用意しているパッケージを導入する必要があります
以下のコマンドを実行しましょう

```
$ sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-2.noarch.rpm
```

さて、MySQLをインストールしましょう

```
$ sudo yum install -y mysql-community-server
```

# MySQLの動作確認
MySQLがインストールされたので、動作確認を行います

## MySQLサーバの起動/停止
MySQLサーバの起動/停止や、状態の確認はsystemctlコマンドを用いて行います

MySQLサーバの起動/停止は以下のコマンドで実行出来ます

```
$ sudo systemctl start mysqld # 起動
$ sudo systemctl stop mysqld # 停止
```

MySQLサーバの状態を確認するには、以下のコマンドを実行します

```
$ sudo systemctl status mysqld
```

仮想マシンの起動と同時にMySQLサーバを起動するように設定しておくと、
いちいち起動コマンドを打つ必要がなくなるので、設定することをオススメします
設定するには、以下のコマンドを１回打つだけです

```
$ sudo systemctl enable mysqld
```

# MySQLにログイン

MySQLをインストールして、サーバを起動することができました
SQLの自主練をするためのDBやTableを作成したいのですが、その前にMySQLにログインする操作が必要です
初期状態ではrootユーザしかいないので、rootでログインします

```
$ sudo mysql -u root -p # ユーザをrootに指定して、パスワードでログインするコマンド
```
↑のコマンドを打ち、パスワードを入力する必要があります
パスワードはMySQLが自動で作成するログファイルに書き込まれているので、それを確認

```
cat /var/log/mysqld.log | grep root
```
mysql.dに書き込まれたパスワードを確認したら、ログインしましょう
ようやく、DBやTableの作成が可能な状態になりました

# 参考記事

[CentOS7にMySQLをインストールして初期設定するまで](https://qiita.com/nooboolean/items/7efc5c35b2e95637d8c1)

こちらの記事をかなり参考にさせていただきました
僕が書いた記事より情報量が多いかつ分かりやすいので、こちらも目を通して見て下さい
(1年前の記事でMySQLのバージョンが違ったりするので、少し注意が必要かも)
AWS SWF(Simple Workflow)とは

# SWF(Simple Workflow)とは
マネージド型のタスクコーディネータ
商品の発注/請求処理のワークフロー（処理の流れ）のような、重複が許されない、厳密に一回限り順序性が求められる処理のコーディネータとしての利用に適している。
#SWFの要素
<img width="1354" alt="スクリーンショット 2020-03-09 14.45.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522222/08bbf2b5-c5d6-c7d3-b1d9-c440add951e2.png">

##①ワークフロースターター
SWFを起動し、ワークフロー開始の起点となるアプリケーション。
例えば、顧客の注文を起点に動作するワークフローだと注文を受けるアプリケーションがワークフロースターターになる。

##②SWF
ワークフロースターター、もしくはワーカー・Lambdaタスクから受け取った情報を元に決定タスクを作成し、ディサイダーへ渡す。

ディサイダーから受け取った次に実行するタスクの情報からタスクの実行命令を出す。

決定タスク ワークフローの実行状態を伝えるもの。 ワークフロー履歴等を保持する。
ワークフロー履歴
ワークフローが実行されてから発生したイベントの実行記録。
各タスクが実行状態を持たずに決定タスクに持たせることでワークフロースターターやタスクなどのアプリケーションをステートレスに保つことが可能。
##③ディサイダー
SWFから受け取った決定タスクを元に次に実行するタスクを決定する。
SWFを使用するユーザ自信がプログラミングして作成する必要があります。

##④タスク
SWFから呼び出されて実行される処理。
アクティビティタスクとLambdaタスクに分類される

１アクティビティタスク
ユーザが作成した任意のプログラム・処理を実行するタスク。 SWFから直接実行されるのではなく、ワーカーと呼ばれるプロセス・スレッドから実行される。 ワーカーは SWFを使用するユーザ自信がプログラミングして作成する必要があります。
【Svelte】SvelteでPugとSassを使いたいので対応しました【Pug+Sass】


## 概要
[前回](https://qiita.com/hisayuki/items/0ca740968ea34806efa3)に引き続き、Svelteの環境構築です。
今回はPugとSassを使えるようにしました。

## 手順
### 追加パッケージ

```
yarn add -D node-sass sass pug
```

実際にやる手順としてはこれだけです。

## PugやSassでApp.svelteを書く
### CSS部分をApp.scssにする

今は`App.svelte`にCSSがベタで書かれているので、外に書き出します。

```html:App.svelte
<script lang="ts">
	export let name: String;
</script>

<main>
	<h1>Hello {name}!</h1>
	<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

<style>
	main {
		text-align: center;
		padding: 1em;
		max-width: 240px;
		margin: 0 auto;
	}
	h1 {
		color: #ff3e00;
		text-transform: uppercase;
		font-size: 4em;
		font-weight: 100;
	}
	@media (min-width: 640px) {
		main {
			max-width: none;
		}
	}
</style>
```

`<style>`の中身をとりあえず同じディレクトリに`App.scss`というファイルで書き出します。
今はSCSS記法になってないですが、とりあえずOKです。

```sass:App.scss
	main {
		text-align: center;
		padding: 1em;
		max-width: 240px;
		margin: 0 auto;
	}
	h1 {
		color: #ff3e00;
		text-transform: uppercase;
		font-size: 4em;
		font-weight: 100;
	}
	@media (min-width: 640px) {
		main {
			max-width: none;
		}
	}
```

あとは`<style>`タグの`src`に`App.scss`を指定します。
これで少しスッキリしました。

```html:App.svelte
<script lang="ts">
	export let name: String;
</script>

<main>
	<h1>Hello {name}!</h1>
	<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

<style src="./App.scss">
```

### HTML部分をPug記法にする

`<template lang="pug">`というタグを書き、その中にHTMLの中身をPug記法で書きます。

```html:App.svelte
<script>
	export let name: String;
</script>
<template lang="pug">
- var cssName = "./App.scss"
style(src=cssName)
main
    h1 Hello {name}!
    p Visit the
	|
	|
	a(href="https://svelte.dev/tutorial") Svelte tutorial
	|
	| to learn how to build Svelte apps.
</template>
```

こんな感じで書けます。
Pug記法そのものについては本題ではないので、割愛します。

## 注意点
### Pug
#### HTML内の記法変更
`{#...}{/...}`などの本来の[Svelte]の記法が使えない
そのため、専用のmixinが用意されている
専用Mixin：`+if(), +else(), +elseif(), +each(), +await(), +then(), +catch(), +debug()`

```pug:pug
 ul
   +if('posts && posts.length > 1')
     +each('posts as post')
       li
         a(rel="prefetch" href="blog/{post.slug}") {post.title}
     +else()
       span No posts :boom:
```

#### attributesの記法変更
Pugは、要素属性内のすべてをHTMLにエンコードします。
そのため、`attr="{foo && bar}"`このような記述を`attr="foo &amp;&amp; bar"`に変えてしまいます
(`{`が外れたり、記号が文字コード化されてしまう)

これを防ぐために、`=`ではなくエンコードを防ぐ`!=`を使います。

```html:html
 <input class="new-todo" placeholder="what needs to be done?" on:keydown="{event => event.which === 13 && addTask(event.target)}">
```

上記のようなサンプルコードをPugで書く場合、こうなります。

##### before
```pug:pug
 input(class="new-todo",placeholder="what needs to be done?", on:keydown="{event => event.which === 13 && addTask(event.target)}")
```

#####after（`on:keydown`を`!=`に変更）
```pug:pug
 input(class="new-todo",placeholder="what needs to be done?", on:keydown!="{event => event.which === 13 && addTask(event.target)}")
```

## まとめ
とりあえずここまでで、製造とかしていくうちに別の注意点とかが出てきたら追記します。
調べてて色んな情報があるのですが、`sveltePreprocessor`が結構優秀なのであまり追加でやることがなくなってます。

多分、`sveltePreprocessor`の設定方法とかを書いたほうがいい気がしてきました・・・
Pub/Sub 用の Functions のコードを Github で管理する

## 手順
### 1. Github のリポジトリに Functions のコードを準備する
サンプルコードは Pub/Sub で公開されたメッセージと属性を出力するだけの単純な関数。

```go:example/function.go
package example

import (
	"context"
	"encoding/json"
	"log"

	"cloud.google.com/go/pubsub"
)

// User JSONデコード用の構造体.
type User struct {
	Name string `json:"name"`
}

// HelloPubSub Pub/Subからトリガーされる関数.
func HelloPubSub(ctx context.Context, m *pubsub.Message) error {

	// メッセージの出力
	var user User
	if err := json.Unmarshal(m.Data, &user); err != nil {
		log.Fatal(err)
	}
	log.Println("Hello,", user.Name)

	// 属性の出力
	if len(m.Attributes) > 0 {
		for k, v := range m.Attributes {
			log.Println("key:", k)
			log.Println("value:", v)
		}
	}
	return nil
}

```

同じ階層に go.mod も必要。

```example/go.mod
module github.com/mt-village/cloud-func-exampl

go 1.11

require cloud.google.com/go/pubsub v1.3.0
```

サンプルはこちら > [mt-village/cloud-func-example](https://github.com/mt-village/cloud-func-exampl)

### 2. GCP のリポジトリに同期する
[Cloud Source Repositories](https://source.cloud.google.com/) の「リポジトリの追加」から作成した Github リポジトリを接続。
接続されたリポジトリは `github_mt-village_cloud-func-example` のような名前になる。
これで Github 側に入った変更が GCP 側のリポジトリにも同期されるようになる。

### 3. Pub/Sub のトピックを作成する
[Cloud Pub/Sub](https://console.cloud.google.com/cloudpubsub) の「トピックを作成」から新規トピックを作成。
<img width="511" alt="cloud-pubsub-new.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175940/51931bb9-acd1-41b0-79a3-e96211007cce.png">

### 4. Function を作成する
[Cloud Functions](https://console.cloud.google.com/functions) の「関数を作成」から上記で作成したトピックやリポジトリを選択して新規 Function を作成。
![cloud-functions-new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175940/49198c67-f38f-9a4a-c03c-7ba453ab49b5.png)

## 完成
テスト用のメッセージを公開。
<img width="974" alt="cloud-pubsub-message-new.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175940/a64a11b7-b48b-cd05-a739-cf445cee4e42.png">

Functions のログを見ると、期待通りの動作をしていることが確認できる。
<img width="892" alt="cloud-functions-log.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175940/ebf8f15b-3c9e-7368-3dd0-20255d6794ec.png">

リポジトリの変更を自動で検知して関数を再デプロイ、というのはやってくれないので、コードを変更したら関数の編集から手動でデプロイボタンを押す必要がある。(自動にして欲しい)

## 参考記事
- [Pub/SubトリガーのCloud FunctionsをGoで作るときはpubsub.Messageを使おう](https://qiita.com/kshibata101/items/a787c59297eddd033ff0)
AWS Layer 作成スクリプト for python

LambdaのDockerコンテナでPIP実行してZIP化。それをAWS Lambda Layerとして発行するスクリプトです。

- 要Dokerインストール（lambci/lambdaイメージ内でPIPします）
- 事前にAWS Configureしてください。
- 以下のソースコードをファイル保存（publish.sh)し、実行権限を付与。```chmod +x publish.sh```
- パラメータ指定して実行（param1=layer-name, param2=lib-name, param3=lib-version, param4=python-version）
    - ```./publish.sh requests-python37 requests 2.22.0 python3.7```
- 同じLayer-nameを指定して再実行すると、新しいlayer-versionが作成されます。

作りが雑ですが、一応動きます。。。手元の環境を汚したくない時にどうぞ。

```bash
# 
# Require: docker installed.
# Require: aws config for publishing lambda layer
# 
# 1. in container, pip install python liblary and zip,
# 2. publish to aws layer
#
# Usage: param1=layer-name, param2=lib-name, param3=lib-version, param4=python-version
#  ex ```./publish.sh requests-python37 requests 2.23.0 python3.7```

layername=$1 # requests-python37
lib=$2       # requests
ver=$3       # 2.23.0
env=$4       # python3.7

zip=$lib-$ver-$env.zip # requests-2.23.0-python3.8.zip
echo packing: $zip

# Prepare
mkdir -p build
rm -rf build/* # Clean up

# pip and zip in docker.
docker run --rm -it  \
    --volume `pwd`/build:/tmp/build  \
    --workdir /tmp/build \
    lambci/lambda:build-$env \
    bash -c "pip3 install $lib==$ver -t /tmp/build/python && zip -qr $zip python/ && rm -rf /tmp/build/python && chown -R `id -u`:`id -g` ./*"

echo packed : build/$zip

aws lambda publish-layer-version \
    --layer-name $layername \
    --zip-file fileb://`pwd`/build/$zip \
    --description $zip \
    --compatible-runtimes $env
```
djoser

# djoser & django設定

# curl テスト

① token取得

```sh
curl http://192.168.99.100:8000/api/auth/jwt/create -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"email":"xx@xx.jp","password":"password"}'

{"refresh":"xxxxxxx","access":"xxxxxxx"}%
```

② accessトークンを指定してユーザ取得

```sh
curl -LX GET http://192.168.99.100:8000/api/auth/users/me/ -H 'Authorization: JWT xxxxxxx'

{"id":3,"email":"xx@xx.jp"}%
```

## django 側 ######################################################

-- 必要  
djangorestframework-jwt==1.11.0  
djangorestframework-simplejwt==4.4.0  
djoser==2.0.3  


-- settings.py  

```settings.py  
INSTALLED_APPS = [
	....
	
    'rest_framework',
    'rest_framework.authtoken',
    'djoser',


# AUTH_HEADER_TYPESは 「Bearer」を指定


SIMPLE_JWT = {
    #トークンをBearerに設定
    'AUTH_HEADER_TYPES': ('Bearer',),
    #トークンの持続時間の設定
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=60)
}

REST_FRAMEWORK = {
	....
	
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication'
    ],
}
```



-- url.py  

```url.py
urlpatterns = [
	....
    # djoser
    path('api/auth/', include('djoser.urls')),
    path('api/auth/', include('djoser.urls.jwt')),

```

## nuxt 側  

--- 必要  
@nuxtjs/auth  


--- nuxt.config.js  

```nuxt.config.js  
  modules: [
	....
    '@nuxtjs/auth',
	...
  ],
  
  .....
  
  auth: {
    redirect: {
      login: '/login',   // 未ログイン時に認証ルートへアクセスした際のリダイレクトURL
      logout: '/login',  // ログアウト時のリダイレクトURL
      callback: false,   // Oauth認証等で必要となる コールバックルート
      home: '/',         // ログイン後のリダイレクトURL
    },
    strategies: {
      local: {
        endpoints: {
          login: { url: 'api/auth/jwt/create/', method: 'post', propertyName: 'access' },
          user: { url: 'api/auth/users/me/', method: 'get', propertyName: false },
          logout: false,
        },
      }
    }
  },
  // 全ページ甩ログイン
  router: {
    middleware: ['auth']
  },
  // 除外は各ページで
```
 
 
-- login.vue  

```js:login.vue  
<button  @click="login">ログイン</button>
....


export default {
  
  auth: false,
  //ログイン状態であればリダイレクトする
  middleware({ store, redirect }) {
    if(store.$auth.loggedIn) {
      redirect('/');
    }
  },

....

  methods: {


    async login() {
        try {
          await this.$auth.loginWith('local', { data: this.form });
          // ここでホームへリダイレクトする前に行いたい処理
　　　　　　// もしリダイレクトを任意のタイミングで行う場合は nuxt.config.js
          // home: falseにする
          this.$router.replace({ path: '/' }); // 任意のタイミングでリダイレクト
        } catch(error) {
          console.log(error);
        }
    }
  },
```

# 参考
https://reffect.co.jp/vue/nuxt-js-auth-setting-with-backend  
https://qiita.com/itouuuuuuuuu/items/1dc6401022e0d771c757
paizaさん家でC#の腕試ししていたら標準入力で転倒した解決策

コード入力欄のテンプレートで4行目くらいにある
```var line_input = System.Console.ReadLine();```
この標準入力に引っかかりまくったぷろぐらんまも多いと思う。

標準入力ってなかなか使わないから面白いくらい引っかかった。
この程度の内容書くために調べていたら4時間くらい使った、奥深い標準入力。
中の人はここまで引っかかったのを多分~~ほくそ笑んでいる~~そんなつもりはないと思う。


毎回こういう詰まらないことで引っかかって時間食うのもアホみたいだから
こういうことをしたいときはこう、をざらっと書いておく。

## 標準入力の前提知識
* コンソールから入力された値は数字でもstring型
* ただし1文字だとchar型

## よくある罠
for文でぐるぐる回した結果を1行にして出力する場合は
テンプレートを下記のように書き換える必要がある。

```
for(int i = 0; i < line_input.Length; i++)
{
    System.Console.Write();
}
```
> 出力結果例
> 2016 3 19

デフォルトでWriteLineだから地味に引っかかる。  

以下パターン別対策、小難しいのは使わない方針で。
(using足すとLINQとか使えるけど、使って良いのかな)

### 半角スペースで分けているパターン
Dランクに多い気がする。
> 入力値
> 1 2 3 4 5

#### 半角スペースを区切りに配列化
```
System.Console.Read().Trim().Split(' ');
```
> 出力結果
> 1 2 3 4 5
※そのままコンソール出力するとSystem.String[]になる

#### 半角スペースを別の文字列に変換
```
System.Console.ReadLine().Replace(" ","YES");
```
> 出力結果
> 1YES2YES3YES4YES5

### 改行して分けているパターン
Cランクから出てくる気がする。
> 入力値
> 1 2 3 4 5
> 6 7 8

#### 改行したあとの値も必要の場合
```
// 取得方法を変える
var line_input = System.Console.In.ReadToEnd();
System.Console.WriteLine(line_input);
```
> 出力結果
> 1 2 3 4 5
> 6 7 8

#### 改行コードと空白がいらない場合
```
var line_input = System.Console.In.ReadToEnd().Replace(" ", "").Replace("\n", "");
```
> 出力結果
> 出力結果 > 12345678

<b>↑追記</b>
こんなことしなくても普通にReadLineを二つ宣言すればとってくれた、泣いた

```
var line1 = System.Console.ReadLine().Trim();
var line2 = System.Console.ReadLine().Trim();
```
> 出力値
> 1 2 3 4 5
> 6 7 8

<b>↑追記</b>
入力値の行数が不定の場合は、こう対処するらしい
いよいよReadToEndの立場がなくなってきた…

```
// timesは行数が入力値で与えられているのを取得する
var times = int.Parse(Console.ReadLine());
for (var i = 0; i < times; i++)
{
    // for文ぐるぐるで標準入力ピコピコして配列に入れ込んでいる
    string[] inputs = Console.ReadLine().Split(' ');
}
```

#### 入力値がいくつやってくるかわからない
for文でぐるぐる回そうにも数がわからないことがある。
そういうときはwhile無限ループを使用する。

```
while(true)
{
    // ここで配列化とか何やらしようとすると例外発生する
    var input = System.Console.ReadLine();

    // とってみたもののnullだったら無限ループを抜ける
    if(input == null)
    {
        break;
    }

    // とりあえず配列に入れてみる
    var inputs = input.Split(' ');
}
```

以上。
string→int、char→intの変換は割愛。
jQueryでよく使うメソッドまとめ

# メソッドを使うとき一番最初に使うであろう簡単なメソッドをご紹介

## 親子要素を特定する

### find

```html

<div class="parent">
  <div class="child">こんにちは</div>
</div>
<script>
  //子要素を取得できる
  $('.parent').find('.child').text();
</script>

```

### parents

```html

<div class="parent">
  <div class="child">こんにちは</div>
</div>
<script>
  //親以上の要素を取得できる(要素指定)
  //親はparentメソッドを使用
  $('.child').parents('.parent').html();
</script>

```

## 要素の設定値を取得、設定する

### attr

```html

<div class="hello" name='hello'>こんにちは</div>
<script>
  //要素の属性を取得できる
  $('.hello').attr('name');
  //要素の属性を設定できる
  $('.hello').attr('name','goodMorning');
</script>

```

### val

```html

<input type="text" class="hello"value="こんにちは">
<script>
  //inputタグの入力値を取得できる
  $('.hello').val();
  //inputタグの入力値を設定できる
  $('.hello').val('こんばんは');

</script>

```

## 要素に追加する

### on

```html
<div class="hello">こんにちは</div>
<script>
  //イベントを登録できる
  $('.hello').on('click',function(){
    //クリックした時の処理をここに書く
  });
</script>

```

### css

```html
<div class="hello">こんにちは</div>
<script>
  //CSSを反映する
  $('.hello').css("color", "red");
</script>

```
コントローラ毎に適用するレイアウトを変える

## 読み込むレイアウトファイルの変更

通常コントローラが読み込まれた際にはapplication.cssが読み込まれて、レイアウトが適用されるが
コントローラに

```ruby
layout 'xxx'
```
を記述することでxxxのレイアウトファイルを適用することができる。
これを利用することでコントローラ毎にヘッダーやフッダーを変更したりすることが可能となる。
React の環境構築

#目的
macOS上に React の開発環境を構築する

#環境情報
##OSバージョン
macOS Catalina(10.15.4)

#node.js & npm を install
以下にアクセスして ダウンロード & インストールを行う
<font color="red"><b>※catalinaでは v12 は使用できないため v13 以上を使用すること</b></font>
https://nodejs.org/ja/
<img width="740" alt="スクリーンショット 2020-03-09 13.37.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596550/352f8e37-1f66-bdd8-3a2c-4f9267dfa99b.png">

npm install 時に permisson denied となってしまうため npm のデフォルトのディレクトリの権限を変更する

```bash
sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
```

#[デモ]雛形を生成して起動確認をする
雛形を生成

```bash
npx create-react-app my-app
```

my-app を起動

```bash
cd ./my_app
npm start
```

以下の画面が表示されれば成功
<img width="619" alt="スクリーンショット 2020-03-10 11.17.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596550/34c2c923-b386-cc02-7576-3eac5de908bd.png">

#Chrome に React Devtools を追加する
ブラウザで React のコンポーネントツリーを調べることができる、 React Devtools を、以下のサイトから Chrome に追加する
https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja
![スクリーンショット 2020-03-10 15.57.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596550/1698d204-afed-eb1b-4b15-cab430f24f88.png)

「file://」のURLにも対応させるため chrome の 「設定」 => 「拡張機能」 => 「React Developer Tools の 詳細」 を選択し
<b>「ファイルの URL へのアクセスを許可する」</b> を有効にする
![スクリーンショット 2020-03-10 16.05.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596550/389aaea6-ca0f-e0f7-9237-bbb1accd20c1.png)

Chrome の Devtools に 「Component」, 「Profiler」 タブが追加される
![スクリーンショット 2020-03-10 16.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596550/705b27fe-ef64-f796-dc2f-aa0486305e49.png)
AWS　SQS(Simple Queue Service)　について

#SQS(Simple Queue Service)
SQSとは
フルマネージド型メッセージキュー型サービス。
プロセス間通信などのスレッド間通信に使われるコンポーネントで制御やデータを伝達するポーリング型キューサービス

＊基本的には256KBまでの軽いデータしか利用できず、60秒から14日間メッセージを保持する

##メッセージキュー(MQ)の基本
アプリケーションは、開発、デプロイ、管理がより簡単に行える、独立した小さな構成要素に分解されています。メッセージキューは、この分散アプリケーションに対して通信や調整を行います。メッセージキューは、分解したアプリケーションのコーディングを大幅に簡素化すると同時に、パフォーマンスや信頼性、拡張性を高めることができる。
<img width="757" alt="スクリーンショット 2020-03-09 13.43.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522222/1358162c-860b-b785-bcf4-d5cd41597408.png">

メッセージキューは、1 つのシステムのさまざまな部分で、通信やオペレーション処理を非同期で実行できるようにします。メッセージキューは、一時的にメッセージを格納する軽量バッファと、ソフトウェアコンポーネントがキューに接続するエンドポイントを提供して、メッセージを送受信できるようにします。メッセージは、通常は小規模で、リクエスト、返信、エラーメッセージ、または単純な情報などの場合があります。メッセージを送信するには、プロデューサーというコンポーネントがキューにメッセージを追加します。コンシューマーという別のコンポーネントがメッセージを受信して処理するまで、メッセージはキューに保存されます。



##ポーリングとは
- 複数のプログラム間通信に対し、一定のタイミングの問い合わせがあった場合に送受信処理を行う通信方式
- 一旦中継所に通信内容を貯めておいて、受信側のタイミングが良いときに通信を行う
##コンポーネントの疎結合
コンポーネント間の相互依存を減らした構成とすることで、1つのコンポーネント変更や障害の影響を削減する

##密結合の問題
密結合したアーキテクチャは障害や修正に弱く、不具合が発生しやすい
<img width="414" alt="スクリーンショット 2020-03-09 13.31.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522222/50bc5970-4ea7-a52a-9e07-ca6880188635.png">


### 【密結合はデメリットが多い】
 1インスタンスの障害の影響が全体に及びやすい
 1つの修正対応で他インスタンスへの影響を多く考慮しなければならない
 負荷対応やスケーリングなども容易にできない
 システム構成の追加・変更が難し

### 【解決策】
キューなどのコネクターを利用した疎結合な呼び出し方法の採用

##疎結合化
<img width="414" alt="スクリーンショット 2020-03-09 13.31.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522222/d5260e81-9689-4b3f-4a61-fedfa79ed9ba.png">

#キューの種類
###標準(スタンダード)キュー
標準キューは「順番通りに処理」と「1回だけのメッセージング」を“なるべく”実施する処理
メッセージ配信順序を保証せず、同一のメッセージが２回配信される可能性がある

###FIFOキュー
その名の通り最初に入ったキューを最初に処理する順番を守るキューイングを実施
秒あたりの処理件数は標準(スタンダード)キューに劣る

#SQSの機能

| 機能 | 特徴 |
|:-:|:-:|
|  Short Poling | キューが空の場合でも即時にリターンする  |
|  Long Poling |キューが空の場合はタイムアウトまで待つ   | 
|  デッドレターキュー |　ずっと残ったメッセージを別キューに移動し、正常に処理できなかったメッセージを隔離できる 　　|
|  Visibility timeout(可視性タイムアウト) |新しいメッセージを指定時間見えなくする   |
三段論法でPHPは語れない

皆さんは三段論法という <b>絶対法則</b> をご存知だろうか？


# 【三段論法とは】

> 大前提（主に普遍的な法則）と小前提（個別の単なる事実）から結論を導き出す推論方法。
> 簡潔に説明すると以下のような論法である。
> 
> AはBである。
> ↓
> BはCである。
> ↓
> よってAはCである。
> 
> 「A」と「C」という元々直接的には関係しない事柄を、両方と関連性のある「B」という事柄を用いて論理的に結びつけることができる。
> 三段論法の有名な例としては以下の文が挙げられる。
> 
> ソクラテスは人間である。
> ↓
> 全ての人間は死すべきものである。
> ↓
> ゆえにソクラテスは死すべきものである。
> 
> 
> 上述の説明に当てはめると、「ソクラテス」はA、「人間」はB、「死すべきもの」はCに該当する。
> 「ソクラテスは人間である」という小前提と「全ての人間は死すべきものである」という大前提により、「ソクラテスは死すべきものである」という結論が導き出されたのである。

https://dic.nicovideo.jp/a/%E4%B8%89%E6%AE%B5%E8%AB%96%E6%B3%95 より引用

# 【PHPではどうか？】

まず以下のコードとその実行結果を見ていただきたい。

```php
<?php
var_dump(NULL == 0);
var_dump(0 == "0");
```

```
$ php syllogism.php 
bool(true)
bool(true)
```

なるほどなるほど。 `NULL` == `0` が真。`0` == `"0"` が真。ならば三段論法的に、`NULL` == `"0"`　も真だろう。

```php
<?php
var_dump(NULL == 0);
var_dump(0 == "0");
var_dump(NULL == "0");

```

```
$ php syllogism.php 
bool(true)
bool(true)
bool(false)
```

ファ！？ :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking: :thinking:

# 【補足】

* PHPに限らず、変数には値の他に型という性質を持っているため単純に三段論法で語ることはできません。
* 緩やかな比較をしていると、こういう落とし穴にハマる可能性があるので、厳密な比較をするようにしましょう。
cowitter で verify 処理

cowitterを使っている。

こちらが自動でツイートするプログラムを組んでいる場合、
相手が連携を解除しするとバグる。

ということで、ツイッターアカウントの token が有効かどうかを調べる。

token がおかしいと以下のエラーが出て強制終了してしまう。

```

Bad Authentication data.

```


こんな感じで返り値を変更。

```/var/www/html/mama-rich.net/vendor/mpyw/cowitter/src/Helpers/ResponseBodyDecoder.php

protected function handleJsonAndXml()
{

//略

    return  $code;
//        throw new HttpException(implode("\n", $messages), $code, $this->response);
}


```


であとは

```

//    ツイッターアカウントが有効かどうか調べる
//  account/verify_credentials
    public function verify()
    {
        $tmp = $this->client->get("account/verify_credentials");

        $res = true;
        if($tmp == '215'){
            $res = false;
        }

        return $res;
    }

```

って感じでアカウントが有効か調べれる。
rakeタスク

## rakeタスクとは
railsに標準装備されているrake routesなどコマンドライン上でアプリケーションの機能を実行するもの
自分でオリジナルのrakeタスクを作成することもできる。
定期的に実行したい機能などをrakeタスクとして作成しておくことで効率的な運用が可能になる。
定期的に実行したい処理はlib/tasks以下のディレクトリに作成することが多い

## rakeタスクの実行
以下のコードはユーザーが入店したかどうかを判断する"enter_flag"というカラムを全てfalseにするrakeタスクである。

```ruby:lib/tasks/user_chacker.rb
namespace :user do
  desc "ユーザーの入店情報をリセットする"
  task reset_entered_flag: :environment do
    User.update_all(entered_flag: false)
  end
end
```

このrakeタスクを実行するにはターミナル上で

```:ターミナル
rake user:reset_entered_flag
```
と打ち込む
rake [namespeceの名前]:[taskの名前]のように記述して実行します。
毎日・毎週特定の曜日・３日おきなど、特定の周期でrakeタスクを自動実行したい場合は、
wheneverというgemを組み合わせて実行する。
Dockerでsmokeping構築

ネットワークに繋がっている機器のパケロスやRTTを計測するために、古くから利用されているsmokeping。<br>

dockerでsmokepingをしている日本語の事例がググっても1件で、自分とは違うdockerイメージを使用していたので、自分で構築した手法を記す。docker初心者向けに記載したつもり。


## docker-ceのインストール
dockerを使ったことがない人は、まず、docker-ceおよびdocker-composeのインストールをする。
docker-ceのインストールは公式に従って実施。

* [Ubuntuの場合](https://docs.docker.com/install/linux/docker-ce/ubuntu/)

docker-composeはpipで実施すると楽だが、他の方法もある。

```sh
pip install docker-compose
```

dockerはデフォルトではrootでのみ実行可能なので、現ユーザでログインできるようにする。

```sh
# dockerグループ作成
sudo groupadd docker

# 現ユーザをdockerグループに所属させる
sudo gpasswd -a $USER docker

# dockerデーモンの再起動
sudo systemctl restart docker

# exit（exitせずに、sourceとかシェルに新たに入るだけだと反映されない）
exit
```

## smokepingの構築
dockerhubからsearchをして、どのイメージがいいか探してみる。

```sh
$ docker search --filter "stars=10" smokeping
NAME                    DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
linuxserver/smokeping   A Smokeping container, brought to you by Lin…   80                                      [OK]
dperson/smokeping                                                       57                                      [OK]
```

linuxserver/smokepingはalpineを使っていて、dperson/smokepingはdebianなので、軽量だと思われるlinuxserver/smokepingを使う。STARも多いし。
使い方はdockerhubに書いてあるので、dockerhubを見て構築できる人は、この記事のここ以降を読む必要なし。
[https://hub.docker.com/r/linuxserver/smokeping/](https://hub.docker.com/r/linuxserver/smokeping/)


pullして確認する。

```sh
# pull
$ docker pull linuxserver/smokeping

# 確認
$ docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
linuxserver/smokeping             latest              fee9f5aa7700        3 days ago          104MB
```

docker-compose.ymlを作成する。
まずは、動かすユーザのPUIDとPGUIDを確認する。

```sh
# user名がuserの場合
$ id $USER
uid=1001(user) gid=1001(user) groups=1001(user)
```

docker-compose.ymlを実際に書く。

```yaml
version: "2"
services:
  smokeping:
    image: linuxserver/smokeping
    container_name: smokeping
    environment:
      - PUID=<上記で確認した数値>
      - PGID=<上記で確認した数値>
      - TZ=Asia/Tokyo
    volumes:
      - <smokepingのconfigを保存したいディレクトリ>:/config
      - <smokepingのdataを保存したいディレクトリ>:/data
    ports:
      - <アクセスするポート番号。80でも問題ない>:80
    mem_limit: 4096m
    restart: unless-stopped
```
unless-stoppedがあるので、dockerを再起動した際に、自動で起動される。

一度起動して、すぐに落とす。docker-compose.ymlと同じディレクトリで下記を実行。

```sh
# 起動
$ docker-compose up -d

# 確認
$ docker-compose ps
  Name      Command   State   Ports
-----------------------------------
smokeping   /init     Up

# 落とす
$ docker-compose down
```

docker-compose.ymlで記載したconfigディレクトリ内に以下に下記ファイルが作られているはずなので、変更する。
詳しくは、ここを参考にするとよい。
[https://oss.oetiker.ch/smokeping/index.en.html](https://oss.oetiker.ch/smokeping/index.en.html)

```General
*** General ***

owner    = <name>
contact  = <mail_address>
```

```Targets
*** Targets ***

probe = FPing

menu = Top
title = Network Latency Grapher
remark = Welcome to the SmokePing website. \

+ TestParent
menu = TestParent
title = TestParent

++ TestChild
menu = TestChild
title = TestChild
host = 192.0.2.1
```

最後にもう1回起動して完了。

```sh
docker-compose up -d
```

ブラウザで、docker-compose.ymlで設定したポートにアクセスすれば、smokepingの結果が確認できる。
fluent-bitを利用したログデータのIIJ IOTサービスに蓄積

Fluent Bitは、Treasure Data社が開発したリソースの乏しい組み込み環境でも動作するログ転送プログラムです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336280/d28ee097-45b2-1ab6-82ff-7b0086938571.png)

今回は、IIJ IOTサービスを利用して、ラズパイのログデータを蓄積する方法を説明します。
システム構成は、以下の通りです
![fluent-bit-iij-iot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336280/45b2246c-58aa-156d-0a5b-ccefc97249a0.png)

## USBドングルでモバイルアクセスのセットアップ
メーカーのマニュアルを参照して行います
http://www.pixela.co.jp/products/network/pixelamobile/apn/pix_mt100.html
APNの情報など、以下のページを参照して行います
https://manual.iij.jp/iot/doc/14158761.html
## fluent-bitのインストール
### サーバGPGキーの追加
```
wget -qO - https://packages.fluentbit.io/fluentbit.key | sudo apt-key add -
```
### OSのバージョンの確認
```
pi@raspberrypi:~ $ cat /etc/issue
Raspbian GNU/Linux 9 \n \l
```
### ソースリストの更新
```
sudo su -
Raspbian 9 (Stretch)の場合
echo "deb https://packages.fluentbit.io/raspbian/stretch stretch main" >> /etc/apt/sources.list

Raspbian 8 (Jessie)の場合
echo "deb https://packages.fluentbit.io/raspbian/jessie jessie main" >> /etc/apt/sources.list
```
### aptデータベースの更新
```
sudo apt-get update
```
### パッケージのインストール
```
sudo apt-get install td-agent-bit
```
### コンフィグの編集
```
sudo vim /etc/td-agent-bit/td-agent-bit.conf
[INPUT]
    Name                tail
    Path                /tmp/in_syslog
[OUTPUT]
    Name  http
    Match *
    Host gw.iot.iij.jp
    Port 80
    URI  /v1
    Format json
## TCP方式で送信する場合
[OUTPUT]
    Name  tcp
    Match *
    Host gw.iot.iij.jp
    Port 19921
    Format json
```
### サービスの起動
```
sudo systemctl start td-agent-bit
```
## IIJ IOTサービスの設定
コンパネで送信デバイスのデータストレージをONに設定します
![デバイス設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336280/af8f52dc-dc2a-5b5c-db25-69e0a9e3dc0b.png)
コンパネでデータ保存設定を行います
![データ保存設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336280/049161a7-7ba2-25ee-59a5-4c4bc4eba4ab.png)
## ロガーツールでメッセージを送信
```
sudo logger -u /tmp/in_syslog test_message
```

## 結果の確認
IIJ IOTサービス仕様では、10分に一回ファイルに格納されるため、ファイル生成するまで最大10分待ちます
![ファイル確認.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336280/24653347-6fcb-9c1b-a25d-895fb46869d9.png)
最新のファイルをダウンロードして中身を確認します

```
[{"date":1583760967.000000,"pri":"13","time":"Mar  9 13:36:07","ident":"pi","message":"test_message"}]
```
以上、fluent-bitを利用したログデータのIIJ IOTサービスに蓄積の手順でした。