OmniAICreator/Qiita-1.07M huggingface dataset:
踏み台サーバ経由でSSHサーバにVSCodeで接続する方法

リモートサーバ先のファイルをいじるとき、
「あァ！毎回winscpを開いて作業するの面倒だなァ！！:rage:」となってしまったので、
VSCodeで開けるようにした際のメモです。
簡単にできて、VSCodeの様々な機能の恩恵が得られるようになるのでぜひ試してみてください。
# Configの設定
まずリモートサーバへの接続情報を記入します。
記入先ファイルは`C:\Users\<USER_NAME>\.ssh\config`です。
よくわからない人はwinscpの接続情報と見比べてみてください。

```
#踏み台サーバ
Host jump_server 
  HostName xxx.xxx.xxx.xxx　
  Port 22
  User user_name
  IdentityFile C:\Users\<USER_NAME>\.ssh\id_rsa
  ForwardAgent yes

#踏み台からの接続先サーバ
Host stg_server
  HostName yyy.yyy.yyy.yyy
  Port 22
  User user_name
  IdentityFile C:\Users\<USER_NAME>\.ssh\id_rsa
  ProxyCommand ssh -W %h:%p stg_server
```
# VSCodeの設定
これがなければ始まらない。
VSCodeの拡張機能で`Remote - SSH`をインストールしてください。
うまくいけば左下に`><`のマークが現れます。
![InkedInked.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482062/6414ff19-e56b-6ff4-d537-77bec0e72cc2.jpeg)
表示が確認できたら、このマークを押下してください。
下記画像のようにセレクトボックスが表示されるので、`Connect to Host...`を選択してください。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482062/57205f5b-4362-339a-9b6c-9b73db2457f3.png)
選択するとconfigファイルで設定したサーバ名が表示されるので、
接続したいサーバ（ここでは`jump_server`）を選択してください。
問題なければ接続できるはずです...！
接続できない場合は、configファイルの見直しやVPN等を確認してみてください。
# 最後に
winscpではなくVSCodeから直接接続できれば、グループ検索やコードの補完など、圧倒的に便利になります！まだの方はぜひやってみてください！
GCP利用アカウントへの最小限の権限付与方法

##はじめに
最近GCP(Google Cloud Platform)を社内のメンバーだけでなく、ベンダーの方にも共有することになり、
アカウントに最低限の権限のみ付与できるように方法を調べたので忘備録として残します。

今回やりたかったことは、スケジュールドクエリの作成・編集を行える権限のアカウントへの付与になります。

##付与したい権限
スケジュールドクエリの作成・編集に必要な権限は下記になります

bigquery.jobs.create もしくは bigquery.transfers.update　→　転送を更新するための権限です
bigquery.datasets.update → データセットのメタデータを更新するための権限です

##操作手順
GCPのナビゲーションメニューの「IAMと管理」から「ロール」を選択します。
デフォルトのロール一覧画面になるのでページ上部の「ロールを作成」をクリックします。
![スクリーンショット 2021-09-29 19.27.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2102756/6bea2446-a1b9-694d-bcc9-97351ddb1ba8.png)

「ロール作成」をクリックすると下記のようなロールの詳細設定画面になるので、
「スケジュール管理」など適当なロール名を記載します。
![スクリーンショット 2021-09-29 19.35.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2102756/0fbb61ce-326b-bd5c-b351-a633d47c20e0.png)

次に「権限を追加」をクリックすると今回作成するロールに付与するロールを選択する画面になります。
![スクリーンショット 2021-09-29 19.31.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2102756/2d6a1f9c-632a-1c48-3b7e-1608c38fc3df.png)

「プロパティ名または値を入力」の欄に付与したい権限名(今回の場合はbigquery.jobs.createなど)
を入力し、選択して右下の「追加」をクリックします。

付与したい権限を全て選択したら、「作成」をクリックしてロールの作成は完了です。

![スクリーンショット 2021-09-29 19.40.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2102756/587d70f9-4e8a-1654-21e9-fd9d6016b831.png)

ロール作成後はナビゲーションメニューの「IAMと管理」の「IAM」から、
権限を付与するアカウントを選択して先程作成したロールを追加します。

以上で一通りの流れは終了です。

#おわりに
今回はスケジュールクエリ作成のために必要な権限を付与したロールの作成を行いました。
デフォルトで用意されているロールを複数個アカウントに付与することでもスケジュールクエリの作成は行えるのですが、デフォルトのロールは含まれている権限が多いため必要以上の権限を与えてしまう可能性があります。

意図しないデータの削除など事故を防ぐためにも、目的別に最低限の権限のみを付与したロールを作成し、作業を行うアカウントにロールの追加を行うことをお勧めいたします。
未経験エンジニアとして初めに知っておきたかったこと



今回は、未経験エンジニアとして就職し半年たった今、最初から知っておきたかったこと。知っておくと楽なこと・便利なことについてまとめたいと思います。

###〇使用エディタ
* VScode

###〇便利な拡張機能
1. Pasty：Ctrl+C→Pastyをクリックでコピーしたページを全て開くことができる
https://seonoblog.com/google-chrome-pasty/

2. Alt ＆Meta viewer 
https://www.pc-weblog.com/alt-meta-viewer/

23. ColorZilla ：Webページの色をワンクリックで簡単に取得できるツール
https://keisukeblog.org/colorzilla/

4. SimpleExtManager :使用したい拡張機能をチェックするだけで、オン/オフの切り替えが可能です。アドオンのグループを作成しておけば、グループごとに一括でアドオンのオン/オフが可能になります。
https://www.useful-time.com/entry/simpleextmanager

5. WhatFont 
https://soundorbis.com/whatfont/

6. OneTab：現在開いているタブをリスト化して最小化し、使用メモリを最小限に抑えることができる。
https://aprico-media.com/posts/4254

7.  Image Downloader ：画像ファイルを一括ダウンロード。
https://chromesoku.com/image-downloader/

8. Dimensions：アイコンを押下し、測りたい要素までマウスのカーソルを移動させます。すると青い線が表示され、要素の高さや幅、または距離を測ることが出来ます。
https://www.pc-weblog.com/dimensions/

9.  HTMLエラーチェッカー ：WEBページのレイアウト崩れや表示不具合の原因となる、HTMLの構文ミス（タグの閉じ忘れ）を検出
https://miya-system-works.com/blog/detail/80

10. QRcode maker:携帯でページの仕様を確認したいときに便利


###〇勉強ツール
1. Progate
1. ドットインストール
1. HTML/CSSに関する書籍
1. **デザインカンプからコーディング**（XD等のソフトを使い、デザインの完成見本からウェブページを作っていくこと）

####正直、デザインカンプからのコーディングが一番有効です!!!
初めはとっつきやすいので、Progateなどゲーム形式のものでトライしましたが、デザインカンプからのコーディングをやってから初めてページの全体像（コードの記述）を少し理解できるようになったと思います。

無料の配布や説明などたくさんあるので、ぜひ活用してみてください!!
[例]https://crestadesign.org/sd-compdistribution/#index_id3




###〇まとめ
簡単に、自身が未経験エンジニアとして最初から知っておきたかったことをまとめてみました。デザインカンプからのコーディングに関しては、自分で試行錯誤してやってみることで、タグ等を自然と覚えたように思います。まずは、好きなサイトの模写から始めるのも良いです! 未経験エンジニアとしてまだまだですが、これからも同じ界隈で頑張っている皆様の記事を参考にしながら精進していきたいと思います。
【第二回】コロナ禍だから何かできることをー　自宅療養者連絡ツール　ー

#前回までのあらすじ
[【第一回】コロナ禍だから何かできることを](https://qiita.com/STYLE-D/items/743bbecae1c52be15505)
####実装イメージ図
LINEを利用して保健所の担当者の負担を軽減するとともに、自宅療養者はいつでもつながっている安心感を持たせるためのツールイメージです。
![メイン.00_00_51_12.Still002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744261/cf85391e-aef8-5a59-0a1d-63d8e15412ce.jpeg)

##まずはLINEからデータを取得して返すまでの流れを考えよう
![システム構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744261/ac5262ba-5db6-bdc3-d7f1-6c007182fce8.jpeg)

###今回はLINEbotの設定部分の説明

まずは、LINEbotの設定するパスから。
チャンネルの設定
[LINE Developers](https://developers.line.biz/ja/)
メッセージ関連の設定
[LINE Official Account Manager](https://manager.line.biz/)

登録などはほかで詳しく説明しているため割愛します。

###チャンネルの設定
[LINE Developers](https://developers.line.biz/ja/)
重要な部分だけ抜粋

ちなみに、
LINEDevelopers（アカウント）->プロバイダ->チャンネル
の順番に枝分かれしており、
プロバイダ、チャンネルともに権限設定があります。
※プロバイダに権限を持っていると以下チャンネルの権限も持っています。


######[チャンネル作成時]
チャネルの種類は「MessagingAPI」

######[チャンネル基本設定]タブ
| 項目 |設定値|
|:-|:-|
|アプリタイプ|ボット|
|権限|PROFILE|



#####[Messaging API設定]タブ
Webhook設定

| 項目 |設定値|
|:-|:-|
|Webhook URL|<strong>wepapiの場所</strong>|
|Webhookの利用|![ONにする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/744261/5ffbc108-97c7-cb8c-2fff-6f39454c073e.png)
|
Webhook URLは次回、作成するapiのパスを指定します。
URLは<strong>https</strong>のみ有効となってます。


LINE公式アカウント機能

| 項目 |設定値|
|:-|:-|
|グループ・複数人チャットへの参加を許可する|無効|
|応答メッセージ|有効|
|あいさつメッセージ|有効|
チャネルアクセストークン

| 項目 |設定値|
|:-|:-|
|チャネルアクセストークン（長期）|<strong>ここのトークンは重要</strong>|
チャネルアクセストークンは次回、作成するapiで利用します。

#コロナ禍だから何かできることをー　自宅療養者連絡ツール　ー
[【第一回】実装イメージ図と動画](https://qiita.com/STYLE-D/items/743bbecae1c52be15505)
->>[【第二回】LINEからデータを取得して返すまでの流れ](https://qiita.com/STYLE-D/items/9e0addd8df44be8590b7)
[【第三回】LINEからデータベースまでの流れ](https://qiita.com/STYLE-D/items/345e9142948c00330e71)
[【第四回】データベースへの更新までの流れ](https://qiita.com/STYLE-D/items/8af17d7f94f5c351ede0)
[【第五回】ユーザー登録の仕組み-LINEbotの設定部分](https://qiita.com/STYLE-D/items/a745bd5faeb68caa1d7c)
[【第六回】ユーザー登録の仕組みLIFFで表示する画面の開発](https://qiita.com/STYLE-D/items/321038c8028eb9e9231f)
[【第七回】データベースの構造](https://qiita.com/STYLE-D/items/71085dc9a04042f33f0e)
[【第八回】WEB画面上でできる機能](https://qiita.com/STYLE-D/items/c32e9098a3948e8f32f2)
[【第九回】まとめ](https://qiita.com/STYLE-D/items/77eb6a8e61ae2201565f)
python初学者の備忘録　文字列型のメソッドについて

#### [←目次へ](https://qiita.com/dondondon/items/cd45224ca93e65c976cc)

:::note info
python,Qiita初心者なので、備忘録として記載していきます。
なにせ初心者なので、知識不足はご容赦ください。
知識を深めながら追記していきたいと思います。

:::
# 文字列型で使用するメソッド

`基本`

+ count()メソッド：指定した文字列が文字列に含まれている数を返す
+ startswith()メソッド：文字列の始まりが指定した文字列と一致しているかboolで返す
+ endwith()メソッド：文字列の終わりが指定した文字列と一致しているかboolで返す
+ find()メソッド：指定した文字列が何文字目から開始されるか返す
+ rfind()メソッド：指定した文字列が後ろから数えて、前から何文字目から開始されるか返す
+ capitalize()メソッド：先頭文字のみ大文字、その他はすべて小文字に変換する（センテンスケース）
+ title()メソッド：各単語の先頭文字のみ大文字、それ以外は小文字に変換する（タイトルケース）
+ upper()メソッド：すべて大文字に変換する
+ lower()メソッド：すべて小文字に変換する
+ format()メソッド：引数に指定した文字列を{}に代入する
+ index()メソッド：指定した文字列が何文字目から開始されるか返す※見つからない場合はエラーを返す
+ center()メソッド：引数の長さの中央に配置した文字列を返す
+ rjust()メソッド：引数の長さの右に配置した文字列を返す
+ ljust()メソッド：引数の長さの左に配置した文字列を返す
+ replace()メソッド：第一引数を第二引数に置き換える
+ split()メソッド：引数の値を境に分割してリストで返す
+ join()メソッド：第一引数で第二引数の文字列を連結する


##### ` count() `メソッド：指定した文字列が文字列に含まれている数を返す

```python
>>> 'Junior High School'.count('o')
2
```

##### ` startswith() `メソッド：文字列の始まりが指定した文字列と一致しているかboolで返す

```python
>>> 'Junior High School'.startswith('Ju')
True
>>> 'Junior High School'.startswith('Jum')
False
```

##### ` find() ` メソッド：指定した文字列が何文字目から開始されるか返す

```python
>>> 'Junior High School/Hi School'.find('Hi')
7
```

##### ` rfind() `メソッド：指定した文字列が後ろから数えて、前から何文字目から開始されるか返す

```python
>>> 'Junior High School/Hi School'.rfind('Hi')
19
```

##### ` capitalize() `メソッド：先頭文字のみ大文字、その他はすべて小文字に変換する（センテンスケース）

```python
>>> 'Junior High School/Hi School'.capitalize()
'Junior high school/hi school'
```

##### ` title() `メソッド：各単語の先頭文字のみ大文字、それ以外は小文字に変換する（タイトルケース）

```python
>>> 'Junior High School/Hi School'.title()
'Junior High School/Hi School'
```

##### ` upper() `メソッド：すべて大文字に変換する

```python
>>> 'Junior High School/Hi School'.upper()
'JUNIOR HIGH SCHOOL/HI SCHOOL'
```

##### ` lower() `メソッド：すべて小文字に変換する

```python
>>> 'Junior High School/Hi School'.lower()
'junior high school/hi school'
```

##### ` format() `メソッド：引数に指定した文字列を置き換えフィールド{}に代入する

:::note info
.format({} {} {},　値1, 値2, 値3)
※formatについては別項でも説明
:::

```python
>>> 'Junior High School/{}'.format('Hi School')
'junior high school/hi school'

# -- 複数の文字列を代入できる --
>>> '{} {} {}/Hi School'.format('Junior','High','School')
'Junior High School/Hi School'

# -- 引数はインデックスを指定できる --
>>> '{0} {1} {2}/Hi School'.format('Junior','High','School')
'Junior High School/Hi School'
>>> '{2} {1} {0}/Hi School'.format('Junior','High','School')
'School High Junior/Hi School'
>>> '{0} {0} {0}/Hi School'.format('Junior','High','School')
'Junior Junior Junior/Hi School'

# -- 引数は文字列を指定できる --
>>> '{name1} {name2} {name3}/Hi School'.format(name1='Junior',name2='High',name3='School')
'Junior High School/Hi School'
```
Proxy環境でWSL2+Docker

## 説明

* proxy環境でもWSL２使ってみたいひと向け
* ほぼCLIからやります
* DockerforDesktopがうまく動かせなかったので、コマンドでやる人向け
* 最後に作成した環境使って`npm install`の例があります
* 備忘録的な意味合いが多いため若干説明不足ぎみです

## WSL2

```powershell:PowerShell
# 機能有効化
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
# wsl2用の更新プログラム
$url = https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
Invoke-WebRequest $url -OutFile wsl_update_x64.msi
# 更新プログラムを手動で実行する
Start-Process wsl_update_x64.msi -Wait
rm -force wsl_update_x64.msi
# wslのバージョンを２に指定
wsl --set-default-version 2
# ディストリビューションのDL
$url = "https://wsldownload.azureedge.net/Ubuntu_2004.2020.424.0_x64.appx"
Invoke-WebRequest $url -OutFile Ubuntu2004.zip
# 展開
Expand-Archive .\Ubuntu2004.zip .\Ubuntu2004
# Ubuntu20.04の実行
.\Ubuntu2004\ubuntu2004.exe

```

* 途中でアップデートのインストーラが起動するのでインストールを完了させてください
* 上記を実行して数分待つとusername、passwordを聞かれるので適当に入力します
* その後に以下をコピペして実行します
* [proxy]のところにはProxyサーバのIPとかPortをいれてください

```bash
cat <<'EOF' >> /etc/profile.d/proxy.sh
export http_proxy="http://[proxy]"
export https_proxy="http://[proxy]"
EOF

cat <<'EOF' >> /etc/apt/apt.conf
Acquire::http::proxy "http://[proxy]";
Acquire::https::proxy "http://[proxy]";
EOF

exit

```

* もう一度ubuntuに入りなおすときは`wsl`を実行します
* `sudo apt update && sudo apt upgrade`して、エラーなく動けば完了です
* エクスプローラーからは`\\wsl$`をアドレスに入れるとubuntuを参照できます

## Docker

* 下記のファイルを作成して、ubuntuで実行してください

```dockerinstall.sh
# 必要なもののインストール
sudo apt install -y \
   apt-transport-https \
   ca-certificates \
   gnupg-agent \
   software-properties-common
# gpgキーの追加
sudo -E curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# リポジトリの追加
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
# version指定してインストール
sudo apt install docker-ce
# sudo付けないでdockerコマンド使えるようにする
sudo usermod -aG docker $USER
# install docker-compose
sudo apt install -y docker-compose

exit

```

### DockerのProxy設定

Dockerクライアントとサーバの両方に設定していきます

* docker client
* 下記を実行して終了です
* [proxy]はProxyのIP、Portをいれてください

```bash
# make .docker 
mkdir ~/.docker
# docker proxy settings
cat <<'EOF' >> ~/.docker/config.json
{ "proxies": { "default": { "httpProxy": "http://[proxy]", "httpsProxy": "http://[proxy]", "noProxy": 192.168.*,local*" } } }
EOF

```

* docker server
  * wslからexitしたら外からDockerdを起動します
  * 下記のファイルをubuntu側の~/に設置してWindowsから`wsl sudo sh ~/startdocker.sh`
  * その後に`wsl`でubuntu入ってdockerコマンドたたくと動きます
  * 注意　`wsl sudo sh ~/startdocker.sh`は起動したら一回目は必ず行う必要あり

```startdocker.sh
#!/bin/bash

export http_proxy=http://[proxy]
export https_proxy=http://[proxy]

#sudo cgroupfs-mount
sudo -bE dockerd
```

### 環境テスト

* nodejs 9.3.0で`npm install`します
* プロジェクトフォルダの一階層上に下記のファイルを置いて`docker-compose up`
* エラー出ずに全部引っ張ってこれたら成功です

```docker-compose.yml
version: '3'

services:
  node930:
    image: node:9.3.0
    ports:
     - "8080:8080"
    volumes:
      - ./[projectフォルダ]:/mnt/project
    working_dir: "/mnt/project"
    command: "npm install"
```
10年後を見据えて、小規模開発からdenoを使ってみませんか？

## 概要

<img src=https://deno.land/logo.svg width=8%> ロゴがかわいいね

[deno](https://deno.land/)とは現代のJavaScript, TypeScriptランタイムである！
どんなところが現代的かというと、node.jsと比べて以下のような特徴があります。

- デフォルトでセキュリティが保護されている。明示的に有効にしない限りはファイルやネットワーク、実験的機能にアクセスできない。
- TypeScriptをサポート。
- コードフォーマッターやテストランナーといった組み込みユーティリティ。
- 動作保証された標準ライブラリ。

※[こちらの記事](https://qiita.com/yoshii0110/items/8f13012e9f732b1cfd4c#deno%E3%82%92%E5%AE%9F%E8%A1%8C)が非常に詳しく説明してくれているのでオススメです

## denoはもう「使える」ツールだ
ここからが本編です。

denoは歴史が浅く、なんとなく「まだ実用的ではないかな」「nodeでいいかな」とお思いではないですか？
確かにライブラリがまだ揃っていなかったりでこれは一定正しいかもしれません。しかしその一方、場合によっては**denoは非常に有用なツール**として使うことができます。

ではどういった場面でdenoが輝くか？それは小規模のWebサーバ、CLIツール、バッチなどです。

### なぜ小規模開発でDenoを使うのか？

Denoはいわゆる箱から出した状態ですぐにコーディングを始めることができるからです。

CLIツールをサクッとnode.jsで書きたい時に、以下のように面倒なことが多々あるのではないかと思います。一方Denoはモダンなプログラミング環境が最初から整えられているので、設定なしですぐにコードを書き始めることができます。

- `.ts`ファイルを直接実行できない。コンパイルするか`ts-node`等のライブラリを入れる必要がある。
    - → TypeScriptサポートのランタイム。設定なしで直接実行することができる。
- TypeScript, Linter, Test Runner, Code Formatterをイチからセットアップする必要がある。
    - →最初から全部入り。`deno <command>`でLinting, テスト実行, フォーマットができる。
- ファイルR/W、HTTPリクエストといった一般的な操作もライブラリを入れる必要がある。
    - →汎用的な標準ライブラリを完備。
        - fs, io, http, crypt, hash, log, path ...などなど

もちろんnodeでも設定する時間をかければ実現できますが、本質的なプログラミングに集中できる点は現時点でのdeno最大の利点かなと思います。

### denoだと困るあれこれは？

#### オプションが長すぎる問題

前述の通り、denoはデフォルトでセキュリティが保護されています。
その一方で操作の許可をするためには毎回`--allow-net`のようにオプションをつける必要があり、いちいち入力が面倒だという問題があります。
そこでdenoに`package.json`のスクリプトランナーと同等の機能をもたらしてくれる[Velociraptor](https://github.com/jurassiscripts/velociraptor)というツールを紹介します。

```
$ deno install -qAn vr https://deno.land/x/velociraptor@1.1.0/cli.ts
```

Velociraptorは`yml/yaml`, `json`, `ts`拡張子の設定ファイルをサポートしています。トップレベルに`allow`プロパティを定義することで、全体に対してdenoのallowオプションを適用することができます。
また、配列形式にすることで`&&`に繋がなくても一連のコマンドを定義することもできます。

```scripts.yaml
allow:
  - read
  - write

scripts:
  start: deno run server.ts
  test: 
    cmd:
      - deno fmt
　　　　　　　　  - deno lint
　　　　　　　　  - deno test --allow-net
```

実行には`vr`コマンドを使用します。

```
$ vr start
```

#### husky使えない問題
githookをpackage.jsonで定義できる[husky](https://github.com/typicode/husky)というツールがあるのですが、2021年9月現在denoには対応していないようです。
コミット前のfmt設定などをgit管理できるためチームメンバーで統一できる優れたツールなのですが、実は先述のVelociraptorがgithookにも対応しています。
`gitHook`キーに実行タイミングを定義することができます。

```scripts.yaml
scripts:
  format:
    cmd:
      - deno fmt
    gitHook: pre-commit
```

設定後に`vr`コマンドを実行することでgithookがインストールされます。

```
$ vr
```

## まとめ

- denoなら設定不要ですぐにTypeScriptのコーディングを開始できる
- Velociraptorと組み合わせてnodeのいいとこ取りができる
- 将来を見据えて、今からdenoを使ってみよう

## 参考
https://blog.logrocket.com/exploring-velociraptor-deno-npm-style-script-runner/
外部ツール無しでiOS Appが生成されたファイルを取得する方法


iOS アプリの開発にあたって、アプリから生成された実機内のファイルの内容を確認する必要がある。

XCodeを起動する。ケーブルで実機と繋ぐ

以下のようにファイルをMacマシンに落とす。
iOS：Xcode → window → Devices→ Select the corresponding device → Select the corresponding app → Click the Settings button below the app list → Download Container → Right click the downloaded file 
落とされたファイルで以下の操作でパッケージ中を開く
and select Show Package Contents → AppData → Library → 

アプリの実行中にそれぞれ生成されるファイルが確認できる
【SwiftUI】UserDefaultsを使ったデータ保存まとめ


##UserDefaultsとは
端末にデータを保存することでアプリを閉じた際にもデータを復元することが可能になります。
UserDefaultsを使って端末保存するデータは、

- 少量(軽量)の情報
- プライバシー情報を含まない情報

の両方を満たす必要があります。
(両方を満たすデータはUserDefaltsを奨励)

##メリット
- データ操作が容易
- 短いコードで保存・呼び出しが可能

##注意点
UserDefaultsは暗号化されずに端末上に保存されます。
従って、プライバシー情報の保存には向いておりません。
例えば、

- ニックネーム
- 性別
- レベル

などを保存したいときに使うのがおすすめです。

##保存できるデータ型
- Data
- String
- Number（Int、Float、Double）
- Date
- Array
- Dictionary
- Bool

##基本的な使い方　(保存・呼び出し・削除)
####データを保存する
```swift
userDefaults.standard.set(保存する値, forKey: "キー") //データ保存
```

####保存したデータを呼び出す
```swift
userDefaults.standard.integer(forKey: "キー") -> 型　//保存データの呼び出し
```

####保存したデータを削除する
```swift
UserDeafaults.standard.removeObject(forKey: "キー") //削除
```
####保存したデータを一括削除する
```swift
let appDomain = Bundle.main.bundleIdentifier
UserDefaults.standard.removePersistentDomain(forName: appDomain!) //一括削除
```

##補足：保存データの呼び出し
####保存データがない場合に初期値をセットする
```swift
let value = userDefaults.standard.string(forKey: "キー") ?? "初期値"
```
####型キャスト
```swift
//Int型に変換する。変換した結果がnilの場合、0を代わりににセットする
let value = UserDefaults.standard.object(forKey: "キー") as? Int ?? 0
```

###補足：データを一括管理する
保存データを一括で管理する場合、下記のような構造体を作成します。
データを複数個保存する際は、構造体を使って管理するのが良いでしょう。
`didSet`は、値の更新時の保存処理を記載しています。

```swift
class UserData: ObservableObject {
    /// ニックネーム
    @Published var nickName: String {
        didSet {
            UserDefaults.standard.set(username, forKey: "nickname")
        }
    }
    /// 性別
    @Published var gender: String {
        didSet {
            UserDefaults.standard.set(gender, forKey: "gender")
        }
    } 
    /// 初期化処理
    init() {
        nickname = UserDefaults.standard.string(forKey: "nickname") ?? ""
        gender = UserDefaults.standard.object(forKey: "gender") ?? ""
    }
}
```
MacにPostgreSQLをインストール

##PostgreSQLとは
> PostgreSQLはオーペンソースのリレーショナルデータベー管理スシステム（RDBMS）です。Linux、MacOSといったUnix系OSはもちろんのこと、windowsにも対応しています。

###PostgreSQLをインストールする
```bash
#最新のバージョンのインストール
brew install postgresql

#バージョン指定のインストール
brew install postgresql@13
```

###バージョンの確認
```bash
# or postgresql --version
psql -V
```

###dbの初期化
```bash
initdb /usr/local/var/postgres --encoding=UTF-8 --locale=ja_JP.UTF-8
```

###サーバー起動
```bash
pg_ctl -D /usr/local/var/postgres start
```
traefikにIPアドレスの制限（ホワイトリスト）を設定する

https://qiita.com/error484/items/d5ff9da8385ea2ee720a

:::note info
上記の設定が出来ていることが前提となります。
:::

## ■docker-compose-app.yml

```docker-compose-app.yml
# 変更前
      - traefik.enable=true
      - traefik.docker.network=docker-network
      - traefik.http.middlewares.app-https-redirect.redirectscheme.scheme=https
```
```docker-compose-app.yml
# 変更後
      - traefik.enable=true
      - traefik.docker.network=docker-network
      - traefik.http.middlewares.app-https-redirect.redirectscheme.scheme=https
      # 制限の設定を追加
      # IP制限を使用する場合「testIPwhitelist」を指定します
      - traefik.http.middlewares.testIPwhitelist.ipwhitelist.sourcerange=127.0.0.1/32,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

      # 「testIPwhitelist」を使用
      - traefik.http.routers.test-app-test-secure.middlewares=testIPwhitelist
```

## ■ホワイトリストについて

上記の１ファイルを少し変更するだけで対応できます。
カンマ区切りで複数のIPアドレスの範囲を指定することができます。

:::note info
「X-Forwarded-For」を参照する必要がある場合、下記の設定が必要になります。
「traefik.http.middlewares.testIPwhitelist.ipwhitelist.ipstrategy.depth=【何番目を参照するか】」
:::

## ■関連記事
https://qiita.com/error484/items/d5ff9da8385ea2ee720a

https://qiita.com/error484/items/5c538d4f0d39fd0df5d0
python初学者の備忘録　文字列型の関数について

#### [←目次へ](https://qiita.com/dondondon/items/cd45224ca93e65c976cc)

:::note info
python,Qiita初心者なので、備忘録として記載していきます。
なにせ初心者なので、知識不足はご容赦ください。
知識を深めながら追記していきたいと思います。
:::

# 文字列型で使用する関数

`基本`

+ str()関数：引数を文字列に変換する
+ len()関数：文字長を返す
+ max()関数：最大値を返す
+ min()関数：最小値を返す
+ format()関数：指定した書式の文字列を返す

#### ` str() `関数：引数を文字列に変換する

```python
>>> str(1)
'1'
>>> str(3.14)
'3.14'
>>> str(True)
'True'
```

#### ` len() `関数：文字長を返す

```python
>>> len('English')
7
```

#### ` max() ` ：最大値を返す

```python
>>> max('English') 
's'
```

#### ` min() `関数：最小値を返す

```python
>>> min('English')
'E'
```


####`format()関数`：指定した書式の文字列を返す

:::note info
format(値,　書式指定文字列)
※formatについては別項でも説明
:::

```python
>>> format(255, '04x')
'00ff'
```
Singletonであることを保証するMonoBehaviourを作った

# 作ったもの
unityでゲームを作っているとシングルトンを使うことが良くあります。
そのため、シーンに1個のみ存在することを保証する拡張MonoBehaviourを作りました。
ご自由にお使いください。

```c#
using System;
using System.Linq;
using UnityEngine;

public class SingletonMonoBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{
    private void Start()
    {
        var result = FindObjectsOfType<T>();
        if (result.Length == 0)
        {
            throw new Exception($"{typeof(T).Name}はシーンに存在しません");
        }
        if (result.Length != 1)
        {
            result.ToList().ForEach(r => Debug.LogError(r.name));
            throw new Exception($"{typeof(T).Name}はシーンに2以上存在しています");
        }
    }

    private static T _instance;

    public static T Instance
    {
        get
        {
            if (_instance == null)
            {
                var result = FindObjectsOfType<T>();
                if (result.Length == 0)
                {
                    throw new Exception($"{typeof(T).Name}はシーンに存在しません");
                }
                if (result.Length != 1)
                {
                    result.ToList().ForEach(r => Debug.LogError(r.name));
                    throw new Exception($"{typeof(T).Name}はシーンに2以上存在しています");
                }
                _instance = result[0];
            }

            return _instance;
        }
    }
}
```

# 使用例
実装側

```c#
public class GameManager : SingletonMonoBehaviour<GameManager>
{
    private void Update()
    {
        //諸々の処理
    }

    public int GetScore()
    {
        return 100;
    }
}
```

使用側

```c#

using UnityEngine;

public class ScoreView : MonoBehaviour
{
    private void Update()
    {
        //呼び出し時にシーンにスクリプトがなければエラーを吐く
        Debug.Log("Score " + GameManager.Instance.GetScore());
    }
}
```


保証といっても、使用側が存在しなければシーンに存在しないことは検知できないですが....
python初学者の備忘録　数値型の関数について

#### [←目次へ](https://qiita.com/dondondon/items/cd45224ca93e65c976cc)

:::note info
python,Qiita初心者なので、備忘録として記載していきます。
なにせ初心者なので、知識不足はご容赦ください。
知識を深めながら追記していきたいと思います。
:::

#数値型で使用する関数

`基本`

+ int()関数：数値型に変換する
+ str()関数：文字列型に変換する
+ bool()関数：ブール型に変換する
+ round()関数：偶数への丸め

##### ` int() `関数：数値型に変換する

```python
>>> int(2.7)
2
```
:::note alert
小数点以下は切り捨てられる
:::

##### ` str() `関数：文字列型に変換する

```python
>>> str(3.0)
'3.0'
```

##### ` bool() `関数：ブール型に変換する

```python
# -- bool型になる ※詳細はブール型についての項で説明 --
>>> bool(1)
True
>>> bool(0)
False
```

##### ` round() `関数：偶数への丸め

```python
# -- 第二引数がない場合は整数を返す --
# 以下の通り想定通りの四捨五入値にならない
>>> round(0.5)
0
>>> round(1.5)
2
>>> round(2.5)
2
>>> round(3.5)
4
>>> round(4.5)
4
```

:::note alert
組み込み関数のroundは一般的な四捨五入ではなく、偶数への丸めなので注意
※端数が0.5より小さいなら切り捨て、端数が0.5より大きいならは切り上げ、端数がちょうど0.5なら切り捨てと切り上げのうち結果が偶数となる方へ丸める
※正しい四捨五入は別項で
:::
【Sphinx拡張】動画などの埋め込み

https://pypi.org/project/sphinxcontrib.embedding/

埋込み型のコンテンツを ``:emb:`コンテンツの種類<コンテンツのID>` `` という書式でrstファイルに書くとコンテンツが表示されるロールを作りました。

まだまだ作り込みが甘いαー版ですが、紹介させてください。

#１．セットアップ

インストール

```bash
pip install sphinxcontrib.embedding
```

設定

```python
 extensions = ['sphinxcontrib.embedding',]
```

書き方（Youtubeの場合）

```rst
:emb:`youtube<bJU9xdAZGQM>`
```

```rst
:emb:`yt<bJU9xdAZGQM>`
```

#２．追加機能

現在はYoutube, Vimeo, Nicovideoに対応していますが、設定で任意の埋込み型コンテンツを追加することができます。これを思いついて「面白そう」と思ったのが作った動機です。

```python
html_embedding = {'youtube': '<iframe width="560" height="315" src="https://www.youtube.com/embed/{0}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'
```

上記の例のように、IDの部分を ``{0}`` に変えて設定します。

#３．補足

今はIDを一箇所に指定することしかできませんが、次のようなことに対応するつもりです。

- 同じIDを２箇所で使う埋め込み。
- ID以外の指定。（例、Youtubeでの開始時刻）
- ロールだけでなく、ディレクティブにも対応。
    - 細かくオプションを指定するなら、ディレクティブの方が使い勝手が良さそうなので。

#以上
何か要望・アイデアがあれば教えてください。
Next.js x Typescriptでサクッと開発環境を整える

## これはなに？
Next.js x Typescriptで開発環境を作成したので備忘録として記載しました

## 作成物
https://github.com/mu-suke/nextjs-sample-app/tree/feature/add_lint

## 導入手順

### 1. projectを作成する

```shell:shell
npx create-next-app --ts $プロジェクト名
```

`--typescript` or `--ts`でtypescript用に作成されます

こんな画面が出たらokです
![スクリーンショット 2021-09-28 20.53.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/6d4132b2-5879-170e-f334-a84a1cefa0ff.png)


他にもオプションがあってfirebaseやらframer-motionをデフォルトで入れられたりするので色々と試せそう

https://github.com/vercel/next.js/tree/master/examples

### 2. 実行してみる
上の画像に従って実行してみます
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/3a856452-8892-03a4-514a-d6a3ae9e3b30.png" width=720 />

ソースコードも`.ts`or`.tsx`で作成されていることが確認できるかと思います

### 3. Lint周りを整える
ここからはマストではなく入れておくとちょっと便利だよといった機能の紹介になります

https://nextjs.org/docs/basic-features/eslint
公式ドキュメントにも書かれていますがNext.jsは11.0.0からlintコマンドが追加されました

>By default, Next.js will run ESLint for all files in the pages/, components/, and lib/ directories. However, you can specify which directories using the dirs option in the eslint config in next.config.js for production builds:

デフォルトでチェックしてくれるのはpages/,components/,lib/ の3つのようです

今回はデフォルトで入っているeslintに加えてprettierも導入していきます

```shell:
$ npm install -D prettier eslint-config-prettier
```

上記が完了したら
以下のファイルを変更します

```json:.eslintrc.json
{
  "extends": ["next/core-web-vitals", "prettier"]
}
```

以下のprettierのルールを記載するファイルを作成

```js:.prettierrc.js
module.exports = {
  singleQuote: false,
};

```

完了したら`package.json`のscriptsに以下を追記して実行できるようにします

```json
{
//~~省略~~
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'"
  },
//~~省略~~
}
```

実行

```shell
$ npm run format
```

結果を見てみると、`.prettierrc.js`で設定した通りシングルクォートからダブルに変わっていることが確認できます
![スクリーンショット 2021-09-29 17.59.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316760/96fa6b83-4a8e-b868-64db-953dbca5c333.png)


## 所感
今回はプロジェクト開発の第一歩目を記事として書いてみました

特に3は複数人で開発する際に可読性を下げずに進められるのでおすすめです


Let's enjoy coding life!
herokuでデプロイできなかった時の対処法

Railsで作成中のアプリをデプロイするためherokuを操作していたら、エラーが発生しました。
ターミナル上で　git push heroku master を実行。

```
git@heroku.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists. 
```

公開キー？に対してエラーが発生しているようです・・・多分。

いろいろ調べていたら、ここに辿り着きました。
https://devcenter.heroku.com/articles/keys

見てみると[キーを増やせばいいよ！]的な事が書かれている・・（元々公開キーは作成済みです）

一旦指示通りに　＄heroku keys:add　　をターミナル上で入力。

その後、もう一度 git push heroku master を実行すると、エラーが解消されました！！

他にもっとスマートな解決方法があるような・・まあOK。

これで解決！！と思い、本番環境で試してみると別のエラーが発生:fearful:

これは別記事で紹介します。では！
CloudFormationの更新なしでLambdaをデプロイする

特にCIでのテストをスムーズにするのに使いたいですね。

# Serverless Flamework
`serverless deploy function -f Lambda名`
https://dev.classmethod.jp/articles/serverless-deploy-aws-whats-going-on/
https://www.serverless.com/framework/docs/providers/aws/cli-reference/deploy
# CDK
`cdk deploy --hotswap`
https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/README.md


# Zappa
`zappa update`

ほかは見つけたら随時更新
【SwiftUI】ダイアログ表示

アラートを使ってダイアログ表示させます。
最も汎用的に使えるソースコードを記載しています。

##プレビュー
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034383/548132ed-36dd-dc25-0e52-44adfd92d548.png" width=30%><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2034383/639ea5f0-fc73-b619-9a2a-d957bb02f511.png" width=30%>

##ソースコード
```swift
    @State private var showAlert = false
    var body: some View {
        Button("ダイアログを表示します") {
            showAlert = true
        }
        .alert(isPresented: $showAlert) {
            Alert(
                title: Text("タイトル"),
                message: Text("サブタイトル"),
                primaryButton: .default(
                    Text("OK"),
                    action: {} //OKボタンの処理
                ),
                secondaryButton: .destructive(
                    Text("キャンセル"),
                    action: {} //キャンセルボタンの処理
                )
            )
        }
    }
```
EditorWindowを複数ウィンドウを表示させる

#初めに
EditorWindowで自分のウィンドウを表示するいつもならこんな感じ

```c#
 [MenuItem("OreOre/hogehoge")]
 static void Show() 
 {
     GetWindow<NewBehaviourScript>();
 }
```
上記のままだと、同じウィンドウをが再描画してしまうので、複数起動できない


##Unity answersで 解決
ネットで調べて解決

https://answers.unity.com/questions/980577/multiple-menuitems-multiple-editor-windows.html


CreateInstanceで呼んであげると複数起動できるみたい

### スクリプト

```c#
 [MenuItem("OreOre/hogehoge")]
static void Show()
{
    var multiplewin = CreateInstance<NewBehaviourScript>();
    multiplewin.titleContent = new GUIContent("hogehoge"); // タイトル
    multiplewin.Show();
}
```


#### 最後に

毎回、調べて出てくるのは、いいのだけど。。
黙示録になってるな。。。
なんか、新しいことすっかな。。
ScrollTriggerを使って簡単に要素固定

#ScrollTriggerとは
GSAP(GreenSock Animation Platform)から、2020年5月にリリースされた、「スクロールアニメーション」のためのプラグインであり、とても簡単な記述によって複雑なスクロールアニメーションを実現することができます。

昨今、様々なスクロールアニメーションのためのライブラリやAPIが使用されていますが、その中でも一線を画する機能を備えています。

主な特徴として以下が上げられると思います。

- アニメーションを特定の要素にリンクさせることができる
- マーカーによってデバックや作成が容易
- スクロールにリンクした動きを簡単に作成できる
- 特定のスクロール位置の間で要素を固定できるピン留め機能
- コールバックの充実

https://greensock.com/scrolltrigger/

#実装方法

```html:html
<script src="//cdn.jsdelivr.net/npm/gsap@3.7.0/dist/gsap.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/gsap@3.7.0/dist/ScrollTrigger.min.js"></script>
```
まずは上記のコードを埋め込みます。
jQueryは不要です。

```javascript:js
ScrollTrigger.create({
    trigger: ".pagenav",
    start: "top 120",
    endTrigger: ".footer",
    end: "bottom top",
    pin: true,
    pinSpacing: false,
});
```

#使い方

開始
`trigger` はアニメションを開始する時の基準とする要素のクラスです。
`start` はtrigger要素の位置を設定します。
`start: "top 120",` → triggerのtopがウィンドウの上から120pxの位置に来た時に固定するという意味です。

終了
`endTrigger` はアニメションを終了する時の基準とする要素のクラスです。
`end`はendTrigger要素の位置を設定します。
`end: "bottom top",` → endTriggerのbottomがウィンドウのtopの位置に来た時に固定解除するという意味です。

#参考サイト
https://ics.media/entry/210426/
AWS CDK の実行時に StackName を動的に指定する

# はじめに

AWS CDK のエントリーポイントを見ると、以下の様に実行するスタック名がハードコーディングされている。

```python:app.py
app = core.App()
CdkPythonStack(app, "CdkPythonStack")
```

しかし、例えば「開発環境」と「本番環境」同一のテンプレートを使って複数のスタックを構築したい場合もあると思う。 そのような場合にスタック名を動的に指定して環境構築をしたい。


# 解決策

同様の質問が StackOverflow で見つかった。

https://stackoverflow.com/questions/66983477/how-to-change-stackname-when-using-cdk-deploy

こちらでは、システムの環境変数を使って実行時に引き渡す方法を採っている。
もうちょっといい方法はないかと思って `cdk` コマンドを探したり、`app.py` に `argparse` を追加してみたが、調べた限りではコマンドラインの値をそのまま `app.py` に引き渡す方法は見当たらなかった。 そのため、上記質問の回答に倣って環境変数を使う方法で対処する。

```python:app.py
import os

STACK_NAME = os.environ.get('STACK_NAME') or 'CDKPythonStack'

app = cdk.App()
CdkPythonStack(app, 'CDKPythonStack', stack_name=STACK_NAME)
```

Python で書くとスタック生成時のパラメータとして `stack_name` を渡せばよい。 ここでは単に環境変数を使っているが、さらに踏み込んで環境変数をベースにメタファイルを読み込んで名前を決定してもよい。

```bash
# スタック名指定
$ export STACK_NAME=CustomNameStack && pipenv run cdk deploy

# スタック名未指定 (デフォルトを利用)
$ export STACK_NAME= && pipenv run cdk deploy
```

これら２つを実行することで、別名のスタックを作成できた。

![SnapCrab_NoName_2021-9-29_17-36-41_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502582/98431071-e5d7-2012-41da-213aaf738950.png)
Rails6(ActiveRecord)で今週(月曜〜日曜)の日付を指定してデータを取得する

# はじめに
今週の月曜日から日曜日の日付を指定し、データを取得する方法を実装しました。

読書を習慣化を促すアプリにて、今週の読書状況を表すためです。
調べたことをもとに自分で実装してみたので投稿します。

# 環境
- Rails 6.1.3
- Ruby 2.7.2

# 実装

`Date#prev_occurring`と`Date#next_occurring`を使用して実装します。

**<手順>**
1. 今日の曜日を取得
2. 今週の月曜日と日曜日の日付を取得し、変数`from` `to`に代入
3. 今日の曜日によって条件分岐
4. データを取得

## 1. 今日の曜日を取得

```ruby:task.rb
today = Date.today
day_of_the_week = today.wday
```
RubyのTimeクラスの`wday`メソッドを利用してます。
曜日を0を日曜日とし、6(土曜日)までの整数を返してくれます。
(日：0, 月:1, 火:2, 水:3, 木:4, 金:5, 土:6)

## 2. 今週の月曜日と日曜日の日付を取得し、変数`from` `to`に代入
```ruby:task.rb
from = today.prev_occurring(:monday)
to = today.next_occurring(:sunday)
```
`prev_occurring` で過去の今週の月曜日の日付を、
`next_occurring`で未来の今週の日曜日の日付を取得しています。

ちなみにこんな感じに返ってきます。すごい！

```console
irb(main)> today = Date.today
=> Wed, 29 Sep 2021
irb(main)> from = today.prev_occurring(:monday)
=> Mon, 27 Sep 2021
irb(main)> to = today.next_occurring(:sunday)
=> Sun, 03 Oct 2021
```

## 3. 今日の曜日によって微調整

上記だけだと、

- 今日が月曜日のとき、先週の月曜日の日付
- 今日が日曜日のとき、来週の日曜日の日付

をそれぞれ取ってきてしまいます。
必要なのはあくまで今週の日付ですので、上記2点だけ条件分岐をします。

```ruby:task.rb
if day_of_the_week == 1 # 今日が月曜日
  from = today
elsif day_of_the_week == 0 #今日が日曜日
  to = today
end
```

## 4. データを取得
`from...to`でDate型のカラムの範囲を指定できます。

 ```ruby:task.rb
tasks = Task.where(read_on: from...to)
```

# 完成

```ruby:task.rb
today = Date.today
day_of_the_week = today.wday

from = today.prev_occurring(:monday)
to = today.next_occurring(:sunday)

if day_of_the_week == 1
  from = today
elsif day_of_the_week == 0
  to = today
end

tasks = Task.where(read_on: from...to)
```

あとはデータを使って処理を書いたり、
`from...to`を使って日付ごとに処理したりできます。

以上、初投稿でした！
より良い方法等ありましたら是非コメントお願い致します。


# 参考
- `Date#prev_occurring`と`Date#next_occurring`の使い方
https://qiita.com/hotu_ta/items/4bd67c085cd46d71999b

- `Time#wday`リファレンス
https://docs.ruby-lang.org/ja/2.7.0/class/Time.html#I_WDAY
【ＰＨＰ】多次元配列のソート

```PHP
<?php

$res = [
    ['name' => '田中',  'japanese' => 83, 'math' => 57, 'science' => 43,  'social' => 72, 'english' => 78],
    ['name' => '渡部',  'japanese' => 62, 'math' => 88, 'science' => 70,  'social' => 66, 'english' => 38],
    ['name' => '品川',  'japanese' => 23, 'math' => 33, 'science' => 53,  'social' => 17, 'english' => 7],
    ['name' => '滝谷',  'japanese' => 93, 'math' => 89, 'science' => 79,  'social' => 96, 'english' => 91],
    ['name' => '川原田','japanese' => 55, 'math' => 56, 'science' => 60,  'social' => 54, 'english' => 66],
    ['name' => '一色',  'japanese' => 27, 'math' => 47, 'science' => 100, 'social' => 42, 'english' => 38],
];

function cmp($asc, $desc){
    return ($asc['japanese'] <=> $desc['japanese'] );
}
usort($res, "cmp");

var_dump($res);
?>
```

# 降順はこちら

```PHP
<?php

function cmp($asc, $desc){
    return ($desc['japanese'] <=> $asc['japanese'] );
}
usort($res, "cmp");

var_dump($res);
?>
```
Djangoでdatabaseのviewを使う方法

# なぜ使用するのか
DjangoのQuerysetでjoinや集計関数は使用することができますが、
たくさんテーブルを使用する際にはコードがとても長くなりとても読みづらくなったりします。
そこでDBビューを使用することで、より簡潔に書くことができます。

# 使用方法
##  基本のモデル
今回は以下のようなモデルを使用したいと思います！

```py:models.py
class Job(models.Model):
    name = models.CharField(max_length=200)


class Charge(models.Model):
    amount = models.DecimalField(max_digits=8, decimal_places=2)
    month = models.DateField()
    job = models.ForeignKey(Job, null=True, blank=True, on_delete=models.PROTECT)

```

migrationファイルを作成する

```bash:
python manage.py makemigrations <app_name>
```

## Viewを作成する

migrationファイルを空で作成する
`--empty`オプションをつけて実行すると空のマイグレーションファイルが作成されます。

```bash:
python manage.py makemigrations <app_name> --empty
```

作成したmigrationファイルに作成する`VIEW`を書きます。


```py:
# Generated by Django 3.1.7 on 2021-09-29 08:15

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('<app_name>', '0002_auto_20210929_0812'),
    ]

    sql = """
        CREATE OR REPLACE VIEW app_chargesummary AS
            SELECT row_number() OVER () as id,
                ci.job_id,
                ci.month
            FROM charge ci
            GROUP BY ci.job_id, ci.month;
    """

    reverse_sql = """
            DROP VIEW IF EXISTS app_chargesummary;
        """

    operations = [
        migrations.RunSQL(sql, reverse_sql),
    ]
```
RunSQLの第一引数にmigrate時に実行するSQL、第二引数にロールバックした際のSQLを書きます。

```bash:
python manage.py migrate <app_name>
```
マイグレートすることで記載したSQLが実行され、VIEWが作成されます。

## VIEWのモデルをかく

作成したVIEWに対応するモデルを記載します。
その際にMetaオプションに`managed=False`を書くことでマイグレート対象から外れ、
テーブルが作成されずに済みます。

```python:models.py
class ChargeSummary(models.Model):
    id = models.BigIntegerField(primary_key=True)
    job = models.ForeignKey(Job, on_delete=models.DO_NOTHING)
    month = models.DateField()

    class Meta:
        managed = False
        db_table = 'app_chargesummary'
```

こちらのモデルで`all()`や`filter()`などしていただき、
記載したVIEWを使用することができます。


以上になります。

# 参考記事
https://resources.rescale.com/using-database-views-in-django-orm/

https://akiyoko.hatenablog.jp/entry/2020/12/05/101431#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%83%93%E3%83%A5%E3%83%BC%E4%BD%9C%E6%88%90%E7%94%A8%E3%81%AE-DDL-%E3%82%92%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E6%9B%B8%E3%81%8F
renovateはテストが一つもないと動かないので、そういうときは extends に skipStatusChecks を入れよう（ただし場合による）

備忘録

- 本番のリポジトリにはちゃんとしたテストがある
- クローンリポジトリにはテストがない
  - オートマージの挙動を確かめたいだけなので不要という判断をした

という状況で、書き方には何も問題がなさそうだったのにオートマージが進行しないという問題が起きていた。

renovateの挙動として、テストが一つもない状態をテストの成功と判断することはしていないとのこと。

> Currently, automerge treats lack of status checks on a branch as not ready for automerge, but some repositories without tests may still want dependencies renovated.
> 
> We can't simply treat "no status checks === success" because there may be a race condition where we create a branch and no status checks exist yet. And if GitHub have some latency or a CI service is slow to set its status check then we don't want to blindly automerge.
>
> https://github.com/renovatebot/renovate/issues/351

というわけで、ただ単にオートマージの挙動を確かめたいだけの時は、`:skipStatusChecks` をextendsに入れよう。

https://docs.renovatebot.com/presets-default/#skipstatuschecks

例

```json5:renovate.json
{
  extends: [
    "config:base",
    ":automergePatch",
    ":automergeMinor",
    ":skipStatusChecks"  // これ
  ]
}
```

当然ながら、本番のリポジトリでこれを行うのは非常に危険な行為です。renovateのような依存性更新botを導入する際は、それらのバグが検知できるようなテストを用意してから行いましょう。
ABC150 C - Count Order を解いた

https://atcoder.jp/contests/abc150/tasks/abc150_c

![abc150_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/29696cdb-c5ff-da0e-9f84-851b60f96f10.png)
![abc150_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/8c76b709-5846-022f-f7e3-76438befe7c9.png)
![abc150_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/dbd4b22f-a061-93a1-3d8a-443731ac8dbe.png)
![abc150_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/967dcfb4-9f6a-b6eb-21be-f60123d538ce.png)

今回は問題が分かり易い。
いっつも忘れる、permutation どう描くんだっけ?

https://qiita.com/DaikiSuyama/items/2483a1af0af38408317b

参考にしつつ、全探索してみた。
2 < N < 8 なので助かった。

```CountOrder.py
n = int(input())
P = list(map(int,input().split()))
Q = list(map(int,input().split()))

P = "".join(list(map(lambda x:str(x),P)))
Q = "".join(list(map(lambda x:str(x),Q)))

from itertools import permutations
i = 1
dic={}
for nums in permutations(range(1,n+1)):#O(40000)
    #print(nums)
    nums = list(nums)
    nums = "".join(list(map(lambda x:str(x),nums)))#O(8)
    dic[nums] = i
    i += 1

print(abs(dic[P]-dic[Q]))#114ms
```

permutation は辞書順で出してくれる。
だから出力と、何番目に出力したのかを記録する i があれば
テーブルは簡単にできる。

後は引き算だけだ!!

***

あれから。。再チャレンジ

```abc150c.py
N = int(input())
P = list(input().split())
P = "".join(P)
Q = list(input().split())
Q = "".join(Q)
from itertools import permutations
lis = []

for i in permutations(map(str,range(1,N+1)),N):
    lis.append("".join(i))

print(abs(lis.index(P)-lis.index(Q)))#40ms
```

少しだけ深化できたかも。
なぜVue.jsのコンポーネントの分離をするのか

###機能・役割ごとでコンポーネント分離することで下記のメリットがあった。

・影響範囲が小さく、修正しやすい

・複数の箇所で使いまわせる

・役割が分かりやすくなる

・1つのファイルのコード量が減り、見やすくなる

###追伸
私自身一つのファイルにコードを長く書き、見辛くなっていて方法を探していました。
コンポーネント分離をうまく活用します。
【Heroku】Advanced SchedulerでメンテナンスモードをON/OFFする

# はじめに

HerokuのDynoのメンテナンスモードをスケジューラーからON/OFFしたいなと思って、さっそくAddonのAdvanced Schedulerを試したが、Heroku Schedulerと同様に、これで起動するOne-off Dynoにも、やはりHeroku CLIが入ってないので、昔試したやり方を備忘録として残すことにした。

# 実行方式

Advanced Schedulerの中味は、One-off Dynoを起動して登録コマンドを実行するが、Heroku CLIは使えないので、HTTPS経由でHerokuのPlatform APIを使って操作することにする。

# 予め用意するもの

Platform APIを動かすためには、それを誰が動作させるのかを示す鍵が必要である。以下のコマンドでHerokuアカウントのAuthキーをスケジューラー用に新規作成する。

```
$ heroku authorizations:create
```

作成したAuthキーのトークンを調べておく。
```
$ heroku authorizations:info {AuthキーのID}
```

# App Update

メンテナンスモードをON/OFFするため、Platform APIのApp Updateを利用する。以下のコマンドを実行してひとまずローカルの端末から動くか確認する。bodyのmaintenanceのvalueがtrueでメンテナンスON、falseでメンテナンスOFFになるので適宜変更。

```
$ curl -X PATCH https://api.heroku.com/apps/{ココにアプリケーション名} \
       -d '{"maintenance": false}' \
       -H "Content-Type: application/json" \
       -H "Accept: application/vnd.heroku+json; version=3" \
       -H "Authorization: Bearer ｛ココに予め作成しておいたキーのトークン｝"
```

# Triggerを設定する

ここまできたらあとは確認が取れたCURLのコマンドをAdvanced SchedulerのTriggerにセットすればOK。

# その他

Authキーは、自分自身のHerokuアカウントより作られたものであるため、アプリケーションから権限を剥奪されて自分のアカウントから見えなくなったアプリケーションを操作することはできないので、引き継ぎの際には注意しておく。
プロセスを停止する方法

# 目的

- 任意のプロセスを停止する方法をまとめる

# ご注意

- プロセスを停止する際に管理者権限（`$ sodo`コマンドの実行権限）が必要な場合があります。
- 本番環境などのプロセスを停止すると提供しているサービスに影響が出る可能性があります。
- しっかりと確認した上でプロセスを停止しましょう。
- 本記事を参考に作業頂きいかなる問題が発生した場合でも当方は責任を置いかねます。

# 方法

1. 下記コマンドを実行して任意のサービスのプロセスを確認する。

    ```terminal
    $ ps -le | grep サービス名
    ```

1. 下記のように出力される。

    ```
    $ ps -le | grep サービス名
    >F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    >1 S     0 XXXXX     1  0  YY   0 - ZZZZZ -      ?        00:01:05 サービス名
    ```

1. 上記の出力で`XXXXX`となっている部分がPIDといいプロセスナンバーとなっている。
1. 下記コマンドを実行して当該のプロセスを停止する。

    ```terminal
    $ sudo kill XXXXX
    ```

1. 下記コマンドを実行して何も出力されないことを確認する。

    ```terminal
    $ ps -le | grep プロセス名
    ```
Welcartの会員 と MailPoet3の購読者リストを連携する

MailPoetには標準でWooCommerceと連携する機能がありますが、
Welcartはなかったので、作ってみました。
最初は$wpdbで直接テーブルにinsertしてましたが、
ウェルカムメールが送信されないなどの問題があったので、プラグインのAPI経由で登録します。
https://github.com/mailpoet/mailpoet/tree/master/doc

```
$mailPoetIntegrator = mailPoetIntegrator::getInstance();

class mailPoetIntegrator
{
  private static $instance = [];

  private $mailpoetApi;
  const SEGMENT_PURCHASE = 【wp_mailpoet_segmentsのid】; //購入者用のメルマガリスト
  const SEGMENT_REGISTER = 【wp_mailpoet_segmentsのid】; //会員登録者のメルマガリスト

  private function __construct()
  {
    if ( ! class_exists(\MailPoet\API\API::class)) return;

    $this->mailpoetApi = \MailPoet\API\API::MP('v1');

    add_action('usces_action_after_send_ordermail_to_manager', array(&$this, 'completionPurchase'), 10, 4);
    add_action('usces_action_member_registered', array(&$this, 'registeredMember'), 10, 2);
  }

  public static function getInstance()
  {
    $class = get_called_class();
    if (!isset(self::$instance[$class]))
      self::$instance[$class] = new $class;

    return self::$instance[$class];
  }
  public final function __clone()
  {
    throw new \Exception('Clone is not allowed against' . get_class($this));
  }

  private function insertMember( $email, $first_name, $last_name, $segment_id )
  {
    try {
      $this->mailpoetApi->addSubscriber(
        array(
          'email' => $email,
          'first_name' => $first_name,
          'last_name' => $last_name
        ),
        array(
          $segment_id,
        ),
        array(
          'send_confirmation_email' => true,
          'schedule_welcome_email' => true,
          'skip_subscriber_notification' => true
        )
      );
    } catch (\Exception $e) {
      // ログ出しとかエラーメッセージを出したければここで
      return;
    }
  }

  public function completionPurchase( $res, $bcc_para, $entry, $data )
  {
  
    if( ! $email = @$entry['customer']['mailaddress1'] ){
      if( ! $email = @$entry['delivery']['mailaddress1'] ){
        $email = @$data['order_email'];
      }
    }
    if( ! $email ) return;
  
    if( ! $first_name = @$entry['customer']['name2'] ){
      if( ! $first_name = @$entry['delivery']['name2'] ){
        if( ! $first_name = @$data['order_name2'] ){
          $first_name = '';
        }
      }
    }
  
    if( ! $last_name = @$entry['customer']['name1'] ){
      if( ! $last_name = @$entry['delivery']['name1'] ){
        if( ! $last_name = @$data['order_name1'] ){
          $last_name = '';
        }
      }
    }

    $segment_id = self::SEGMENT_PURCHASE;

    $this->insertMember( $email, $first_name, $last_name, $segment_id );
  
  }

  public function registeredMember( $post_member, $user )
  {
  
    if( ! $email = @$post_member['mailaddress1'] ) return;
  
    if( ! $first_name = @$post_member['name2'] ){
      $first_name = '';
    }
  
    if( ! $last_name = @$post_member['name1'] ){
      $last_name = '';
    }

    $segment_id = self::SEGMENT_REGISTER;

    $this->insertMember( $email, $first_name, $last_name, $segment_id );

  }

}
```
switch文とif文の違い 参考サイト



https://techacademy.jp/magazine/11176


##switch文とif文の使い分け方
switch 文を使うか、if文を使うかを迷ったときには、条件がどうなっているかで使い分けます。

###if 文に向いている条件
変数の値がある特定の値よりも大きいかったり小さいさかったりなど、条件に幅がある時
条件に変数が複数使われている時
複数の条件が組み合わされている時
分岐する処理が２つしかない時

###switch 文に向いている条件
変数がある値になる時に処理を分ける。しかも、その値が３つ以上と多くの種類になっている時


https://blog.codecamp.jp/programming-php-switch-or-if
Rustでファイル分割したら、分割したモジュールの間で呼び出しが必要になった。どうするのが良いのかを書き残しておく

# 経緯
それなりにコードサイズが膨らんできたので、「[RUSTでファイル分割](https://qiita.com/CreativeGP/items/496556a825486218bdaf)」なんかを見て、ちまちまファイル分割をした。ロガーをラップするモジュール、メール通知を送信するモジュール、社内基準を満たす暗号化を施すモジュール、ファイルサーバに保存するモジュール、ディレクトリ走査をして必要なファイルを特定したりするモジュール、WEBアプリのAPIをたたくモジュール、HTMLを生成してデプロイするモジュール、などなど。まあこういう当たり前のモジュールがひととおりそろってくると、「やりたいことがサクッとできるひと」になれるわけだ。入門期の辛抱ですな。モジュールに分けるのは、「hogehoge.rs」を作ってコードをコピーして、「main.rs」に「mod hogehoge; use hogehoge;」を足すだけの簡単なお仕事だが、もうすでにご想像のように、「ファイルサーバに保存するモジュール」は「社内基準を満たす暗号化を施すモジュール」の関数を呼び出す必要がある。そこで詰まった。やり方があんまり書かれていないような気がするのだ。少なくとも、私は小一時間ハマった。なので書く。

# シンプルな例で考えてみる
下記のように、コードを書いたとする。あほみたいなprintln!の劣化ラッパーだ。

```rust:main.rs
fn main() {
    printstring("Hello, world!");
    moduser("hoge ");
}

pub fn moduser(text: &str) {
    printstring((text.to_string()+"fuga").as_str());
}

pub fn printstring(text: &str) {
    println!("{}", text);
}
```

コードがでかくなってきたので、printstringをprintモジュールにする。こんな感じだ。

```rust:main.rs
mod print;

fn main() {
    print::printstring("Hello, world!");
    moduser("hoge ");
}

pub fn moduser(text: &str) {
    print::printstring((text.to_string()+"fuga").as_str());
}
```

```rust:print.rs
pub fn printstring(text: &str) {
    println!("{}", text);
}
```

ここまではいい。とても楽ちんだ。しかし、moduser関数、つまり、すでに単一ファイルのモジュールとして切り出した関数を呼び出す関数を外だしすると、途端に悩ましくなる。

# ダメな例
まずは、ダメな例。

```rust:main.rs
mod print;
mod third;

fn main() {
    print::printstring("Hello, world!");
    third::moduser("hoge ");
}

```

```rust:print.rs
pub fn printstring(text: &str) {
    println!("{}", text);
}
```

```rust:third.rs
mod print;//→ダメ！

pub fn moduser(text: &str) {
    print::printstring((text.to_string()+"fuga").as_str());
}
```

こうすると、third.rsのコメントを入れた行で怒られる。third.rsからは、mod文でprint.rsが見えないみたいなのだ。ちゃんとわかっていないで書くけれども、main.rs, mod.rs, lib.rsと、それ以外のファイルでは、見えるモジュールの範囲が違うということなのかもしれない。その辺は別にコンパイラを読む体力はないので、詳しい人に補足してもらえると嬉しい。

# 怒られない例
正解はこれ。super::を使う。これって、知らないと何ともならんので、コードリーディング不足の初学者は必ずハマるんじゃないかと思うんだけど、世の中に説明がほとんどない。そりゃそうかもしれないけど、でも、初心者ってそういうもんだよね。

```rust:third.rs
pub fn moduser(text: &str) {
    //このようにsuper::経由でアクセスしないといけない
    super::print::printstring((text.to_string()+"fuga").as_str());
}
```

でも、このやり方だと、がっつりコードを書き換える必要が出ちゃうので、それは問題だよね。
だからこうする。

```rust:third.rs
use super::print;

pub fn moduser(text: &str) {
    print::printstring((text.to_string()+"fuga").as_str());
}
```

こうするのが正解でした。何てことはないし、多分数週間後には自分もそれをあえて説明しようとは思わなくなってるような気がするので、今のうちに書いておく。
上手にできたＰＨＰ

```PHP
<?php

$results = [
    ['name' => '田中',  'japanese' => 83, 'math' => 57, 'science' => 43,  'social' => 72, 'english' => 78],
    ['name' => '渡部',  'japanese' => 62, 'math' => 88, 'science' => 70,  'social' => 66, 'english' => 38],
    ['name' => '品川',  'japanese' => 23, 'math' => 33, 'science' => 53,  'social' => 17, 'english' => 7],
    ['name' => '滝谷',  'japanese' => 93, 'math' => 89, 'science' => 79,  'social' => 96, 'english' => 91],
    ['name' => '川原田','japanese' => 55, 'math' => 56, 'science' => 60,  'social' => 54, 'english' => 66],
    ['name' => '一色',  'japanese' => 27, 'math' => 47, 'science' => 100, 'social' => 42, 'english' => 38],
];

function cube($n){
    return ['name' => $n['name'].'さん ','total' => ($n['japanese'] + $n['math'] + $n['science'] + $n['social'] + $n['english']).'点'];
}

$output_peaple = array_map('cube', $results);



$menu =  array_reduce($output_peaple, function($accumulator, $item){
  $index = $item['name'];
    $accumulator[$index] = $item['total'];
  return $accumulator;
}, []);


arsort($menu);
$cnt = 1;
foreach ($menu as  $key => $value){

    echo $cnt++.'位：'.$key.$value.PHP_EOL;

}


```
slide shareでスライドが読めない時の対処法

自分用メモ

https://www.slideshare.net/akkuma/21-android

デベロッパーツールを起動してスライドのURLを取得。
ScriptAutoRunnerを拡張機能に追加。
以下のコードをscriptautorunnerで使用。

```
document.onkeydown = function(e) {
    var url_num = Number(location.href.replace("https://image.slidesharecdn.com/android2021public-210426074623/95/21-android-","").replace("-638.jpg?cb=1619423355",""));
 
    if (event) {
        if (event.keyCode == 13) {
            var next_num = url_num + 1;
  
            location.href = 'https://image.slidesharecdn.com/android2021public-210426074623/95/21-android-' + String(next_num) + "-638.jpg?cb=1619423355";
        } 
    }
};
```
enterを押したら次のスライドに行く。
【ＰＨＰ】多次元配列を指定したキーと値にする方法※array_columnを使う

```PHP
<?php
$cooking = [
  ["menu_id" => "10","menu_name" => "カレー","submenu_name" => "ライス","drink" => "烏龍茶"],
  ["menu_id" => "20","menu_name" => "パスタ","submenu_name" => "タバスコ","drink" => "ビール"],
  ["menu_id" => "30","menu_name" => "焼き肉","submenu_name" => "ソース","drink" => "ジンジャエール"]
];

//↓一番早い
$menu = array_column($cooking, 'menu_name', 'menu_id');

$menu = array_column($cooking, null, 'menu_id');

↓２番早い  配列操作を覚えるには丁度よい
foreach ($cooking as  $row) {
    $data[$row['menu_id']] = $row['menu_name'];
}



var_dump($menu);

```
#結果

```
array(3) {
  [10]=>
  string(9) "カレー"
  [20]=>
  string(9) "パスタ"
  [30]=>
  string(9) "焼き肉"
}




```