OmniAICreator/Qiita-1.07M huggingface dataset:
MacOSでRARファイルを簡単に開く方法

アーカイバは、ハードドライブのスペースを大幅に節約できます。 平均して、圧縮レベルは最大30〜70％になる可能性があります。 したがって、今日の記事では、多くのユーザーにとって緊急の問題、つまりMacでrarファイルを簡単かつ便利な方法で開く方法について検討します。

また、MacでRARファイルを開くために使用するプログラム（Commander One）に関する実際的な推奨事項に加えて、RAR拡張機能とは何かおよびそれを使用する理由に関する完全な情報を提供します。

RAR Macファイル拡張子とは何ですか？
-
RARはRoshalArchive Compressed fileの略で、ロシア生まれの作成者であるEugeneRoshalにちなんで名付けられました。 他のアーカイブと同様に、RARには1つ以上のファイルまたはフォルダーが含まれています。 フォルダの内容を圧縮してファイルサイズを小さくすることで、さまざまな種類のファイルの共有やダウンロードに人気があります。

ファイルを圧縮すると、ダウンロードが高速化され、ファイル共有が容易になります。 一部のRARファイルにはパスワードが設定されているか、内部のファイルを保護するために暗号化されています。 通常、画像、ドキュメント、ビデオ、ソフトウェアなど、ほぼすべての種類のファイルを圧縮できます。この形式の主な利点は、情報が「パック」形式であるため、スペースを節約できることです。 RAR形式の他の利点をリストしてみましょう。
-アーカイブの最大サイズとその中のファイルは、実質的に無制限です。
-マルチボリュームアーカイブ（複数の部分で構成される）を作成する機能。
-アーカイブの内容のパスワード保護が提供されます。
-エラー訂正のサポート。
ただし、FARは独自のアーカイブ形式であり、Macでrarを開くには、サードパーティのアプリケーションが必要です。

RARファイルとZIPファイルを使用する理由は何ですか？
-
Macやその他のコンピューターでRARを使用する主な理由は、圧縮率です。一般に、RAR形式は、ZIP形式を使用する場合よりもはるかに優れた方法でファイルを圧縮できます。これは、RARがZIPで使用されるDEFLATE圧縮方法よりも大幅に優れた効率的な圧縮アルゴリズムを使用することを意味します。 RARは、ZIPアーカイブと比較して小さいサイズのファイルもアーカイブするため、RARはZIPよりも優れた代替手段になります。

RARファイルのもう1つの優れた点は、複数の部分に分割できることです。どういう意味ですか？大きなファイルを2つ以上の異なるRARファイルに分割できます。さらに、RARはNTFSファイルシステムの属性（ストリーム、完全なACLアクセス許可、変更/アクセスなどの時間など）を格納できるため、適切な圧縮機能を備えた優れた完全バックアップツールになります。 ZIPは、単純な古いDOS属性（読み取り専用、非表示、システム）以外のこれらの属性を格納できません。

さらに、RARは信頼性の高いアーカイブをサポートしているため、アーカイブに小さなファイルが多数ある場合に圧縮率が向上します。破損したMacRARアーカイブ（たとえば、送信エラーや不良セクタが原因で破損したもの）を修復するために使用できるデータの冗長性とエラー修正方法もあります。それでも、Macのopening.rarファイルにはいわゆる「問題」があります。つまり、サードパーティのRARオープナーMacツールを使用する必要があります。
MacでRARファイルを開く方法
-
デフォルトでは、macOSでアーカイブを開くための組み込みユーティリティがあり、初期作業が簡単になります。ただし、残念ながら、より強力な.rarファイルをダウンロードしない限り、Macで.rarファイルを作成または開くことはできません。 Macオープナー。
[Commander One](https://mac.eltima.com/archiver-mac.html)
-
この.rarファイルのMacオープナーを詳しく見てみましょう。 このアプリは、圧縮と解凍の両方でさまざまなアーカイブタイプを強力にサポートします。 その助けを借りて、コンテンツを抽出せずにアーカイブを検索したり、パスワードで保護されたアーカイブを作成したり、ホットキーを使用してファイルの処理を高速化したりできます。 さらに、あるアーカイブから別のアーカイブにファイルをコピー/移動したり、ファイルを削除したり、アーカイブ内に直接フォルダーを作成したりできます。
![co.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740997/956ea6dd-19df-29ec-5f9b-bc7be0854c65.png)
Commander Oneを介してMacでRARファイルを抽出するには、アプリが非常に直感的であるため、次の簡単な手順に従います。
1. CommanderOneをダウンロードして実行します。
2.開きたいRARファイルを選択します。
3.ファイルを右クリックして、[ファイルの抽出]を選択します。
![rty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740997/020645b5-dbf8-58f7-e4bd-dbe86584c03b.png)
[The Unarchiver](https://theunarchiver.com/)
-
Mac用の便利なRARエクストラクタは、Mac AppStoreにあります。 さらに、このアプリケーションは、最も人気のあるものと最もまれなものの両方で、多くの異なるアーカイブ形式をサポートしています。 Unarchiverは、組み込みツールではなくオペレーティングシステムのシェルに統合され、より優れた機能と生産性で動作します。 ただし、それがすべての機能です。
![unarchiver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740997/781eed22-8574-5689-52e2-d21770b4ee76.png)
[Keka](https://www.keka.io/en/)
-
RARだけでなく、圧縮と解凍の両方で一般的なフォーマットのほとんどを処理できるため、macOSユーザーがよく使用するもう1つの珍しいMacプログラム。 このアプリケーションはMacApp Storeにあり、コンピュータに簡単にインストールできます。 このアーカイバの利点は、大きなファイルをボリュームに分割できることです。 パスワードを設定して圧縮ファイルを保護するオプションもあります。
![keka.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740997/b4e62d95-afd1-1559-3795-6719cfa0518f.png)
Goのポインタに関するお話

### 今回のお話
今回のお話はGoのポインタです。

Goは基本的に守備範囲外なのですが、面白かったので自分なりにまとめます。
### 目次
- ポインタとは
- ポインタのメリット
- ポインタの取得方法
- ポインタ型変数
- ポインタから変数を取得する方法
- 実際に使ってみよう

### ポインタとは
ポインタとは、メモリ上のどこに変数の値が保存されているのかを表したものになります。

いわば、変数の住所のようなものですね。

ちなみに、ポインタというのはGoの世界での呼び名であり、他の言語ではアドレスと呼ぶこともあるようです。

ポインタは基本的に16進数で表されます。

```go:ポインタの例
0xc123456789
```
### ポインタのメリット
ポインタの一番のメリットは、「スコープ外の変数を利用できる」という点です。

スコープとは、変数が利用できる範囲のことですね。

一般に、変数はその関数の外側に持ち出すことができません。
以下がその例です。

```go:スコープによる制限の例
func main(){
  a := 10
  addOne(a) // 出力：11
  println(a) // 出力：10
}

func addOne(a int){
  a++
  println(a)
}
```

func main()以下を見ると、addOneで呼び出した結果は11ですが、その後に変数aを出力すると10に戻っていますね。

func mainで定義した変数aとaddOneに渡したaは同一ではなく、あくまでコピーを渡しただけなのでこのようなことが起こります。

もし、addOneを用いてaの値を更新したければ、以下のようにする必要があります。

```go:スコープによる制限の例
func main(){
  a := 10
  a = addOne(a)
  println(a) // 出力：11
}

func addOne(a int)int{
  a++
  return a
}
```
ですが、今回のお題であるポインタを用いると、addOneメソッドの中で直接aの更新ができるようになります。

### ポインタの取得方法
では、肝心のポインタはどのように取得すればよいのでしょうか？

答えは簡単で、変数名の先頭に&をつければポインタを取得できます。

```go
name := "kenn"
println(&name) //結果：0xc123456789
```

### ポインタ型変数
ところで、Goには変数や引数を定義する際には型を明示するというルールがありました。

ポインタが代入された変数をポインタ型変数と呼ぶのですが、ポインタ型変数の型はどのように記述するのでしょうか。

実は、ポインタ型変数に関しては専用の型は用意されておらず、参照している変数の型の先頭に*をつけたものがポインタ型変数の型になります。

```go:ポインタの例
num := 10
name := "taro"
var numPtr = *int
var namePtr = *string
numPtr = &num
namePtr = &name
```
これで、ポインタを変数に入れることができるようになりました。

では、今度はポインタから変数にアクセスしてみましょう。
### ポインタから変数を取得する方法
変数名の先頭に&をつけるとポインタが取得できました。
逆に、ポインタ型変数の先頭に*をつけると変数の値が取得できます。

```go:ポインタから変数を取得
num := 10
var numPtr int*
numPtr = &num
println(*numPtr) //結果：10
```

では、これを用いて実際にスコープ外の変数にアクセスしてみましょう。
### 実際に使ってみよう
最初にお見せしたmain, addOneを以下のように書き換えます。

```go:ポインタを用いた書き換え
package main
func main(){
  a := 10
  addOne(&a)
  println(a)// 結果：11
}
func addOne(aPtr *int){
  *aPtr++
}
```
これまでのようにaddOneの結果をわざわざaに再代入することなくaの値が更新されています。
### 終わりに
以上がポインタのお話でした。

これまでに学習した言語にはない概念だったので最初は戸惑いましたが、結果的に変数のスコープに関する理解が深まったように思います。
pythonのnumpyとxarrayにおけるdeep copyの作成法


##はじめに
python の numpy を使って ndarray をコピーする場合、そのやり方によってコピー元・先のオブジェクトが束縛される場合と別のオブジェクトとなる場合があり注意が必要。代入演算子ではオブジェクトを共有して同じメモリ領域を参照するためコピー先のオブジェクトとコピー元のオブジェクトに互いに影響される。コピー先のオブジェクトをコピー元のオブジェクトとリンクさせたくない場合は深いコピー(deep copy)を行う必要がある。

一方、xarray の copy ではデフォルトで深いコピーになる。

## x が numpy の場合
Pythonの標準モジュールである copy をインポートし、copy.deepcopyを使う。

```
import copy
y = copy.deepcopy(x)
```
https://docs.python.org/ja/3/library/copy.html?highlight=copy#module-copy

## x が xarrayの場合
xarray.DataArray.copyはデフォルトで深いコピーになる。

```
y = x.copy()
```

http://xarray.pydata.org/en/stable/generated/xarray.DataArray.copy.html

## 参考HP
https://python-no-memo.blogspot.com/2020/07/numpyndarray_13.html?m=0

https://qiita.com/mytk0u0/items/231807f4136b2b1681b0
rails ActiveRecordでjsonの値を取り出す

# ActiveRecordでjsonの値を取り出す

mongoDB query embedded documentsとかを検索ワードにして調べてみました。

https://stackoverflow.com/questions/3954520/mongoid-mongodb-and-querying-embedded-documents
https://stackoverflow.com/questions/24749312/mongoid-querying-embedded-docs/24749539

階層化されているjsonデータは.でつなげば取得できそう。

今回やりたかったのはwhereでcptrans内の特定keyの値がnullでない場合のレコードだけを抽出

##Networkモデル

```
{
    _id: 1,
    cptrans: {
        _id: ObjectId('61712564a3519d0001fe97aa'),
        mcc: 440,
        mnc: 51,
        tracking_area_code: 41481,
        cell_id: '68030469',
        location_area_code: 0,
        rsrp: -66,
        rssi: -41,
        rsrq: -7,
        rssnr: 0,
        traffic_channel: 0,
        band: 18,
        radio_interface: 'LTE',
        band_width: '0',
    }
}

```
Networksモデルに上記のようなjsonデータがmongoDBに格納されている
ここからwhereでcptrans内の特定keyの値がnullでない場合のレコードだけを抽出したい場合
下記のようになる.

## 結果

rank_typeに抽出したいkeyをいれてあげる

```
Nerwork.where("cptrans.#{rank_type}" => { '$ne' => nil })
```

私はkey毎に抽出を変えたかったのでsocpeを作成し、下記のような感じで対処しました。
scopeって何それって人はこれ参考にするといいかも
https://qiita.com/ngron/items/14a39ce62c9d30bf3ac3


```
scope :rank_type, ->(rank_type) {
    case rank_type
    when :rsrp, :rsrq, :rssnr                 then where('cptrans' => { '$ne' => nil })
    when :rssi, :nr_rssi, :nr_rsrp, :nr_rsrq  then where("cptrans.#{rank_type}" => { '$ne' => nil })
    when :tx_rate                             then where('iperf' => { '$ne' => nil })
    end
  }
```


#　参考
scope
https://qiita.com/ngron/items/14a39ce62c9d30bf3ac3

mongoDBのハッシュ値の取得
https://stackoverflow.com/questions/3954520/mongoid-mongodb-and-querying-embedded-documents
https://stackoverflow.com/questions/24749312/mongoid-querying-embedded-docs/24749539
わかったつもりのχ二乗をもう一度ちゃんと理解する

統計において、母分散の区間を求めたい時などに出てくるχ二乗分布。
χ二乗検定などでクロス表を扱ったりと、ちらほら「χ二乗」には関わることがあります。

実用性において、「χ二乗分布の公式やt分布との関係性を熟知しておく必要がない」と
個人的な意見はありますが、それでも統計検定2級とかでちゃんと出てくる（そして、私は自宅で初見で解いて爆死した）ので、「しっかりと」χ二乗分布についてみていこうと思います。

# 標本分散とχ二乗分布

## 標本（不偏）分散
まずは標本（不偏）分散から。

母集団の推測を目的とするため、標本から分散を求めるには「不偏分散」を用いますが、参考書によっては当たり前のように「標本分散」と記載があったりします。
流派があるかもなんですが、ここでの標本から求める分散は以下で定義するものとします

$$ \hat{σ} = \frac{1}{n-1} \sum_{i=1}^{n}(x_i - \bar{x})^2$$

この$\hat{σ^2}$は性質として、平均的に母分散$σ^2$と等しくなる（E[$\hat{σ}^2$] = $σ^2$　これを不偏性と言います）わけですが、もちろん数回だけではバラつきます

## 修正χ二乗
まず、母分散を求めたいとか区間推定したい、という話の前に、母分散$σ^2$と$\hat{σ^2}$を使って、
$$C^2 = \frac{\hat{σ^2}}{σ^2}$$
を考えます。
この$C^2$というのは修正χ二乗と言われて、平均的には1に落ち着きます
（なぜなら不偏分散の期待値は$σ^2$なので）

しかし、いつも1ではなく、当然1よりも大きな値も小さい値（あくまで非負の範囲）も取りうることになり、これは一般的に自由度(今回ならn-1)により、グラフが変わってきます。
（自分が不慣れにkeynoteで作ったグラフなので、精緻なグラフでもなんでもないですw あくまでイメージ）
![スクリーンショット 2021-10-22 14.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/31742442-9bda-019f-51dc-6efbfa04adee.png)
しかし、この$C^2$はおそらく普通の参考書とかに出てこないです。
数値として0以上でかつ1のとき完全一致するというわかりやすいんですが、基本的には$χ^2$が使われます

## χ二乗
今、母集団（N(μ, $σ^2$)）において、n個のサンプル（$x_1, x_2,,, x_n$）とすると、$χ^2$は

$$χ^2 = \sum_{i-1}^{n}(\frac{x_i - μ}{σ})^2$$
で表現されます。（μ、σはそれぞれ母数）
これだけ書いても「あ、そーなんですね！」で会話が終わらせられるので、噛み砕いていうと、

<B>「サンプルから平均を引いて標準偏差で割ったものであり、これは標準化そのもの。
つまり、これはN(0, 1)のn個の独立な要素の平方和は$χ^2$分布をする」</B>
って感じです。
ちなみに、母数を使ったこの$χ^2$分布の自由度はnです（xiのどれもμで表したりできないので、そのままn）

この母平均μを標本平均$\bar{x}$に置き換えると、

$$χ^2 = \sum_{i-1}^{n}(\frac{x_i - \bar{x}}{σ})^2 = \frac{(n-1)\hat{σ}^2}{σ^2} = (n-1)C^2$$

となり、一般的な書籍と同じ形になりました。
この$χ^2$分布に関しては、自由度はn-1となります
（たとえば、$x_nはx_1,・・・, x_{n-1}と\bar{x}$で表現できるので、n-1）

つまり、母数を使う場合と標本平均を使う場合とでは、自由度の違う$χ^2$分布になるということです。

## χ二乗の性質
確率変数X~$χ^2(n)$のとき、
- 期待値（平均値）は$E[X] = n　$
- 分散は$V[X] = 2n$
という性質があります
（導出はχ二乗の確率密度関数の積分とかなので、割愛。
さすがにχ二乗の確率密度関数は覚えるものではないw）

## 加法性
χ二乗は分散との共通性質もあり、例えば、$χ_1^2: 自由度n_1, χ_2^2: 自由度n_2$であるとき、
$χ^2 = χ_1^2 + χ_2^2の自由度はn_1+n_2$
となります（3つ以上でもOK,χ_i^2は独立）

# t分布との関係性
χ二乗もt分布も標本から計算される数値を扱っているため、共通点を持っています。
実際導出まではしないのですが、一般的にt分布と自由度nのχ^2変数を用いて、以下のような等式が成り立つことが知られています。
$$t(n) = \frac{N(0, 1)}{\sqrt{\frac{χ^2(n)}{n}}}$$
（導出はt分布の統計量、標準正規分布の統計量を用いれば、上記で扱ってきたχ^2の組み合わせで算出できます）

# Pythonでχ二乗をプロット
我々は手計算でχ二乗をゴリゴリ計算することはほとんどないので、pythonをつかってχ二乗を扱ってみます。

まずば確率密度関数を見ます

```
import numpy as np
import matplotlib.pyplot as plt

from scipy import stats


x = np.linspace(0, 20, 100)
for df in range(1, 20, 3):
  plt.plot(x, stats.chi2.pdf(x, df), label=f'degree of freedom: {df}')
  
plt.plot(x, stats.chi2.pdf(x, 100), label='degree of freedom: 100')
plt.legend()
plt.show()
```

![スクリーンショット 2021-10-22 15.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865635/15d1ddfc-854f-6261-27ec-1bb2ee640a45.png)

検定をしたい場合はchi2_contigencyメソッドとかがありますが、今回は検定の話ではないので、省略

# 今回参考にさせていただいた記事や書籍
[2021年6月統計検定2級の問題の解説（その3）](https://bellcurve.jp/statistics/blog/22847.html)
[基本統計学](https://amzn.to/3aXULvE)
[22-1. カイ二乗分布](https://bellcurve.jp/statistics/course/9208.html)
【スクレイピングツール】scrape.doの使い方

#はじめに
過去にスクレイピング(PythonでBeautifulSoup)で収集した情報をブログに投稿するツールを作成したことがあります。
現在はスクレイピングのwebサービスもあり、スクレイピング導入における敷居も低くなったのかな？、という疑問からその代表格？である[scrape.do](https://scrape.do/pricing)を実際に触った結果をまとめていきます。

##[scrape.do](https://scrape.do/pricing)のポイント
- 高度なカスタマイズを可能とするWebスクレイピングAPI
- SPAサイトもスクレイピング可能
- リクエストごとにIPアドレスをローテーション
- JavaScriptをレンダリングし、CAPTCHAを処理可能
- ターゲットWebサイトへの失敗したリクエストを自動的に再試行
- リクエストごとに2MBの応答サイズ制限があります

##[scrape.do](https://scrape.do/pricing)の無料枠
サインアップすると、毎月1000のAPIリクエストを含む無料枠がありますので、安心して試すことができます。
※無料枠利用において、クレジットカードの登録が不要なのはGood！

##アカウント登録
私はGoogleのアカウントで登録しました。
登録は簡単でGood！
※ログイン後の画面イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192488/fb3a5334-6a43-a6d8-a9c4-2545f23e722a.png)

#利用していきます！

##今回使用するツールなどのバージョン
- Windows 10 Pro：21H1
- vscode：1.61.2
- Docker：20.10.8
- Python: 3.8.12

##環境構築
詳細なソースは[GitHub](https://github.com/hiropppp/scrape.do-python-sample/)

**イメージの作成**

```docker
docker build -t scrape_do:1.0 /mnt/c/wsl/docker/dev/scrape.do-python-sample/.devcontainer --no-cache
```

**コンテナの作成**

```docker
docker run -v /mnt/c/wsl/docker/dev/scrape.do-python-sample:/opt/python/scrape_do --name scrape_do_01 -i -t scrape_do:1.0 /bin/bash
```


##スクレイピングAPIの実行
**scrape.doのAPIレスポンスであるhtml情報を出力**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192488/eb565e7b-4502-d921-8d22-2181e685b7ea.png)

**scrape.doのAPIレスポンスのhtml情報からBeautifulSoupオブジェクトを作成して簡易的なスクレイピング結果を出力**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192488/910df315-9611-a9b4-b8bd-04713a52360a.png)

##httpのサイトはアクセスできない？
ターゲットのURLが「http:XX」の場合、「502 Bad Gateway」となりました。
httpsのサイトのみが対象のようなので、httpのサイトにアクセスしないといけない要件の場合は残念ながら利用不可かなと。
※回避策あればコメントいただきたいです！

#利用した感想
**利用しやすさ**
細かい機能は有料オプションじゃないと利用できないものが多くて試せなかったのですが、APIの実行なので総じて利用は楽でした！
**料金**
スクレイピング処理の実行回数が少なく無料枠(1000回/月)内で利用可能あれば、[scrape.do](https://scrape.do/pricing)を利用したほうがIP自動変更もしてくれるのでオススメです。
逆に実行回数が多い場合は、[bright data](https://brightdata.com/)を利用してIP自動変更をしつつリクエスト処理をしたほうが安くつくかなと。
しかし、Seleniumの代替となるJavascriptレンダリング機能は有料となるため、料金を意識するなら自前で作成したほうがよいかなと。

#今後
[bright data](https://brightdata.com/)とScrapyを利用して、スクレイピングをしていきたいです。
まずは[10分で理解する Scrapy](https://qiita.com/Chanmoro/items/f4df85eb73b18d902739)を見て進めてみます。


#参考資料
参考とさせていただきました。ありがとうございます。
[VSCodeでWSL2上のDockerコンテナ内コードをデバッグ](https://qiita.com/c60evaporator/items/fd019f5ac6eb4d612cd4)
[10分で理解する Beautiful Soup
](https://qiita.com/Chanmoro/items/db51658b073acddea4ac)
パフォーマンスが重要な場合は、文字ごとの処理を避けてください

文字列を処理するとき、文字列を文字（またはバイト）の配列として表示し、そのように処理したくなるでしょう。

文字列がASCIIであるかどうかを判別したいとします。ASCIIでは、すべての文字は128より小さいバイト値である必要があります。文字列がASCIIであることを確認するための優れたC ++ 17アプローチは、次のようになります。

```C++
bool is_ascii_branchy(const std::string_view v) {
   for (size_t i = 0; i < v.size(); i++) {
     if (uint8_t(v[i]) >= 128) {
       return false;
     }
   }
   return true;
}
```

このコードのロジックを考慮することが重要です。コンパイラーに指示しているのは、すべての文字に順番にアクセスし、それがASCII文字であるかどうかを確認し、そうでない場合はベイルアウトすることです。したがって、文字列にASCII文字が含まれていない場合は、最初の文字のみを読み取る必要があります。

文字列がほとんどASCII以外の文字で始まることを期待している場合は、高性能のコードである可能性があります。ただし、文字列がほとんど常にASCIIであると予想している場合、このコードは最適ではありません。

コンパイラーがそれを最適化できるはずだと不平を言うかもしれませんが、それはあなたが提供したコードの制約の範囲内でのみです。コンパイラーは通常、アルゴリズムを再設計することを目的としていません。

ASCII入力を期待している場合は、できるだけ少ない手順で文字列を実行する必要があります。次のコードは、プロセッサが単一の命令を使用して64ビットブロックを処理できるという事実に依存しています。

```C++
bool is_ascii_branchless(const std::string_view v) {
  uint64_t running = 0;
  size_t i = 0;
  for(; i + 8 <= v.size(); i+=8) {
    uint64_t payload;
    memcpy(&payload, v.data() + i, 8);
    running |= payload;
  }
  for(; i < v.size(); i++) {
      running |= v[i];
  }
  return (running & 0x8080808080808080) == 0;  
}
```


これは楽観的な機能です。早い段階で非ASCII文字に遭遇した場合、文字列が長いと、多くの不必要な作業を行うことになります。

あなたは2つの間のハイブリッドを試すことができます。8文字を読み、ASCIIであるかどうかを確認し、ASCIIでない場合はベイルアウトします。

```C++
bool is_ascii_hybrid(const std::string_view v) {

  size_t i = 0;
  for(; i + 8 <= v.size(); i+=8) {
    uint64_t payload;
    memcpy(&payload, v.data() + i, 8);
    if((payload & 0x8080808080808080) != 0) return false;
  }
  for(; i < v.size(); i++) {
      if((v[i] & 0x80) != 0) return false;
  }
  return true;
}
```

これらの関数はどのように比較されますか？短いASCII文字列（128文字未満）を使用して簡単なベンチマークを作成しました。文字ごとの速度は約半分です。結果はさまざまです。コンパイラを使用して、マシンでベンチマークを自由に実行してください。

|　　character-by-character　　|　　2.0GB/s　　|
|::|::|
|**optimistic**|**3.5GB/s**|
|**hybrid**|**3.4GB/s**|

いくつかの作業を行うことで、おそらくはるかに速く進むことができますが、私が意図的に小さな断片化された文字列を含むベンチマークを選択したという事実に注意してください。

英語原稿：https://lemire.me/blog/2020/07/21/avoid-character-by-character-processing-when-performance-matters/
【Python】for文で辞書(dictionary)繰り返し処理

辞書また、辞書型変数(dictionary)はkey-valueで格納されるデータです。
### 自分の定義した辞書
```python
myDict = {'John' : 180, 'Naomi': 156, 'Terry': 177, 'Stella': 160}
```

### 1. キー(key)だけ取る
#### 1.1 デフォルトでアクセス
```python  
for key in myDict:
    print(key)
"""
結果:
John
Naomi
Terry
Stella
"""
```

#### 1.2 dictionary.keys()でアクセス 
```python
for key in myDict.keys():
    print(key)
"""
結果:
John
Naomi
Terry
Stella
"""
```

### 2. 値(value)だけ取る
```python
for value in myDict.values():
    print(value)
"""
結果:
180
156
177
160
"""
```

### 3. キー、値(key, value)両方とも取る
#### 3.1 デフォルトでアクセス(1.1と一緒)
```python
for key in myDict:
    print(key, myDict[key])
"""
結果:
John 180
Naomi 156
Terry 177
Stella 160
"""
```

#### 3.2 dictionary.items()でアクセス
```python
for key, value in myDict.items():
    print(key, value)
"""
結果:
John 180
Naomi 156
Terry 177
Stella 160
"""
```

以上、簡単にメモしました。
Snowflake 特定のテーブルのカラム名一覧を取得する方法

Snowflakeで特定のテーブルのカラム名一覧を取得する方法です。

information_schemaスキーマのcolumnsテーブルを使います。

### 例
TESTという文字列が入ったテーブルにある、TESTという文字列が入ったカラムの一覧を取得します。

```sql
select distinct 
    table_name,
    column_name
from
    INFORMATION_SCHEMA.COLUMNS
where
    table_name like '%TEST%'
    and column_name like '%TEST%'
order by
    1,2;
```
【初心者奮闘録】ログイン機能をほんの少し使いこなす！（Laravel）

#はじめに
この記事は、独学開始から約３ヶ月の実務未経験者が作成したものです。
よって、スキルは非常に未熟なため、決して本記事の内容を鵜呑みにされないよう、ご注意ください。
（未熟な私が記事投稿を行なっている背景については、本文の最後にお伝えします。）

#本日の課題
コントローラー内で、ログイン者・非ログイン者で使用できるページを任意で設定する方法について、解説いたします。

###対象者
PHP及びLaravelの基礎学習を終え、アプリ開発を始められた方
ログイン機能のダウンロードは完了したが、実用方法がわからない方

###環境
PHP 8.0.11
Laravel Framework 8.64.0

##実装解説

###ベースとなるコード
下記のコードは、app/Http/Controllersディレクトリにある、GiftController.phpです。
（GiftController.phpは私が任意で作成したファイルです。）

```c#:app/Http/Controllers/GiftController.php
<?php

class GiftController extends Controller
{
```
これをベースに、条件に沿って追記していきます。

###条件①；非ログイン者を寄せ付けないアプリにする

```c#:app/Http/Controllers/GiftController.php
<?php
class GiftController extends Controller
{
    public function __construct(){
        $this->middleware("auth");
    }
```

construct関数の中身に注目してください。
$thisを用いて、'auth'ミドルウェアが呼び出されております。
これがGiftControllerクラス内に存在することにより、GiftControllerクラス内のメソッドを使用するページは、非ログイン者は閲覧ができません。
（ただし、GiftControllerクラス内のメソッドを使用していないページには、非ログイン者でもアクセスすることは可能です。）

###条件②；非ログイン者にも優しいアプリを作る

```c#:app/Http/Controllers/GiftController.php
<?php
class GiftController extends Controller
{
    public function __construct(){
        $this->middleware("auth")->except(["index","store"]);
    }
```
'auth'ミドルウェアの後ろに、exceptメソッドを追記します。
これの意味は、例外としてGiftController.php内の"index"メソッドと"store"メソッドを使用しているページのみ、非ログイン者でもアクセスを可能とします。

###おまけ

上記で紹介している'auth'ミドルウェアは、一体どこから湧いて出てきたのでしょうか？

あれは、app/Httpディレクトリ内のKernel.php内に存在します。

```c#:app/Http/Kernel.php
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
```

上記コードは、Kernel.php内の56行付近にあります。
しかし、この一行では`auth`の働きについて読み解くことができません。
さらに、Authenticateクラスについて確認していきます。

```c#:app/Http/Middlesare/Authenticate.php
class Authenticate extends Middleware
{
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('login');
        }
    }
}
```

上記のコードを簡単に解説すると、非ログイン者がページにアクセスしようとした時、例外を除き、全てログインページ（≒route('login')）に飛ばすという内容です。

#最後に
上記でもお伝えいたしましたが、私は独学開始から約３ヶ月の実務未経験者です。
そんな未熟な私が記事を投稿しようと決意した理由は、以下の通りです。
・初学者の記事が多く出回るほどに、プログラミングの学習を検討している方の背中を押せると考えたから（私自身、学習を開始するまでに初学者の記事を読み漁っておりました）
・周りに同じ境遇の仲間がいない、孤独な初学者さんの競争心を掻き立てられるのではと考えたから（学習効率を上げるためにはライバルの存在は重要）
・あるいはこのような稚拙な記事を読んだ初学者さんが「自分のレベルはこいつよりも上」と優越感を与えられるのではと考えたから（学習効率を上げるためには自信を持つことも重要）

プロのエンジニア同様、初学者にもそれなりの努めがあると、私は思います。
今後も、下手くそながらも【初学者ページ】を上げ続けて参ります。

最後まで読んでいただき、誠にありがとうございました。
Fargateスケジュールタスクがたまに実行されないことがある

## Fargateスケジュールタスクとは

Amazon EventBridgeのスケジューラを使って、ECS(Fargate)のタスクを定期実行する仕組みです。

[参考] https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/scheduled_tasks.html

## 結論

2021年10月現在、タスク起動時に環境変数をS3から取得するようにタスク定義を設定している場合は、タスクの実行に失敗することがあります。
（今後AWS側に修正してもらえる可能性はあります。）

なお、調査の余地がありますが、
VPCエンドポイント・NAT・パブリックIPの有無などの環境の違いで発生頻度に差がある可能性があります。

## 詳細

一つずつ、原因を探っていきます。

### RunTaskが実行されているか確認

#### CloudTrailにてRunTaskイベントを確認
CloudTrailをオンにしている場合、各APIの実行履歴を取得できます。
コンソール画面の場合、イベント履歴からイベント名「RunTask」でフィルターしましょう。
もしイベントが記録されている場合、タスク自体は起動されたことがわかります。
![スクリーンショット 2021-10-22 14.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466431/9ae2f123-f4a8-4546-bb97-795c0e143cb9.png)

#### CloudWatchメトリクスでInvocationを確認
EventBridgeのメトリクスで、スケジュールタスクが呼ばれていたかどうかを確認します。
こちらも、Invocationsが記録されている場合、タスク自体は起動されたことがわかります。
![スクリーンショット 2021-10-22 15.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466431/189b968a-86e3-e8e5-fa33-89626ded0c26.png)

### タスク停止理由をログに記録する
ここまで、特にアプリケーションが実行されなかった理由は見当たりませんでした。
しかし、スケジュールタスクのアプリケーションは間違いなく実行されていません。
つまり、タスクを起動したが、アプリケーションの実行前に停止したことが考えられます。

そこで、タスク停止ログを記録するためのCloudWatchLogsを作成します。

#### CloudFormationにてタスク停止ログを記録する仕組みを構築

以下のCloudFormationテンプレートを使用して仕組みを構築します。
https://github.com/aws-samples/amazon-ecs-stopped-tasks-cwlogs

以下の記事も参考にさせていただきました。(ありがとうございます！)
https://dev.classmethod.jp/articles/tsnote-ecs-how-can-i-store-the-reason-for-stopping-ecs-tasks-in-cloudwatch-logs/

### タスク停止理由にてエラーログを確認

停止ログが記録されるようになったので、実際に確認します。
すると…

```
ResourceInitializationError: failed to download env files: file download command: non empty error stream: RequestCanceled: request context canceled caused by: context deadline exceeded
```

停止理由（`stoppedReason`）にてエラーメッセージを確認できました。

タスク起動時に環境変数をS3から取得するように設定しており、稀に取得できないことがあるようです。

コンソール画面でのタスク定義箇所はこちらです。
![スクリーンショット 2021-10-22 15.16.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466431/425ff59a-1924-53d6-329b-6dc3615b411d.png)

タスク定義ファイルでいうと以下の部分が該当します。

```
"containerDefinitions": [
    {
      "dnsSearchDomains": null,
      "environmentFiles": [
        {
          "value": "arn:aws:s3:::xxxxxxxxxx/.env",
          "type": "s3"
        }
      ],

...

```

## 備考
2021年10月23日現在、以下のIssueが発行されており、続報が待たれています。
https://github.com/aws/aws-cli/issues/6470
Native File System API でテキストエディタを作る

先日公開された [vscode.dev](! vscode.dev) を触った際、なんか Native File System API というのを使えばブラウザから普通にローカルファイルを扱えると知ったので、試しにブラウザで動くテキストエディタを作ってみた。

Chromium 系のブラウザ (Chrome, Edge など) だと大体動くけど [Brave はだめ](!https://github.com/brave/brave-browser/issues/11407) らしい。http サーバーを立てずに、ローカルの HTML ファイルとして開いても動く。

注意点としては、既存ファイルを上書き保存をすると作成日が保存した時点になってしまう。

![_SS 2021-10-22 15.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40166/6af61cde-d57d-5cba-04aa-01c648f16663.png)


```html:html
<div id='filename'>名称未設定ファイル</div>
<textarea id='editor'></textarea>
<div>
	<button id='open'>開く</button>
	<button id='save'>上書き保存</button>
	<button id='saveas'>名前をつけて保存</button>
</div>
```

```css:css
#editor {
	width: 320px;
	height: 160px;
}
#filename {
	color: #888888;
}
```

```JavaScript:JS
const fileNameDiv = document.getElementById('filename')
let fileHandle

// テキストファイルだけ開けるようなオプション
const pickerOpts = {
	types: [
		{
			description: 'Texts',
			accept: {
				'text/*': ['.txt', '.text']
			}
		}
	],
	multiple: false,
}

document.getElementById('open').onclick = async () => {
	try {
		[ fileHandle ] = await window.showOpenFilePicker(pickerOpts)
		if (fileHandle.kind !== 'file') return

		fileNameDiv.textContent = fileHandle.name
		const fileData = await fileHandle.getFile()
		const content = await fileData.text()
		document.getElementById('editor').value = content
	} catch (e) {
		// ファイル選択をキャンセルした時などにここに飛ぶ
		console.error(e)
	}

}

document.getElementById('save').onclick = async () => {
	if (fileHandle.kind !== 'file') return

	const content = document.getElementById('editor').value
	const writableStream = await fileHandle.createWritable()
	await writableStream.write(content)
	await writableStream.close()
}

document.getElementById('saveas').onclick = async () => {
	try {
		const content = document.getElementById('editor').value
		fileHandle = await window.showSaveFilePicker(pickerOpts)
		if (fileHandle.kind !== 'file') return

		const writableStream = await fileHandle.createWritable()
		await writableStream.write(content)
		await writableStream.close()

		fileNameDiv.textContent = fileHandle.name

	} catch (e) {
		console.error(e)
	}
}
```
MySQLが過負荷で重い時にボトルネックになっているクエリ（プロセス）を一斉にKillして楽になる方法

DBサーバが過負荷に陥った時、ボトルネックとなっているクエリを一気に消したいことがあります。

`show processlist` で確認はできるのですが、そこから一気に消す方法について記録しておきます。
全てを消してしまうとまずいこともあるのでwhereで絞りながら一気に消します。

利用には `mysqladmin` と　`xargs` を使っています。

下記のようにして行います。

- `information_schema.processlist` から `where` を使って `select` （バージョンによってはperformance_schemaかもしれません）
- `xargs` と `mysqladmin kill` で全てkill

もちろんですが、ボトルネックの原因となっているクエリ自体を見直さないと問題の解決になりません。

## 準備

サーバ接続用の環境変数を設定しておきます。

```
export DB_HOST=mysql.example.com
export DB_USER=username
export DB_PASS=password
```

## 一覧の確認
まずはどういったプロセスが動いているか確認します。

```bash
$ mysql -h${DB_HOST} -u${DB_USER} -p${DB_PASS} -e "SELECT * FROM information_schema.processlist where command != 'Sleep'\G"

...
*************************** 1. row ***************************
     ID: 123
   USER: username
   HOST: 10.10.10.10:1010
     DB: dbname
COMMAND: Execute
   TIME: 4
  STATE: Sending data
   INFO: SELECT * from users;
...
```

## 該当クエリの調整

killしたい対象のプロセスを絞り込むようなWHERE句を書きます。下記ではusersが含まれる実行中のプロセスを抜き出しています。

```bash
$ export DB_WHERE="info like '%users%'"

$ mysql -h${DB_HOST} -u${DB_USER} -p${DB_PASS} -e "SELECT * FROM information_schema.processlist where command != 'Sleep' and ${DB_WHERE};" 

```

IDだけをうまく抜き出すようにします。パイプで渡すと出力される枠などはきれいに無くなり`xargs`に渡せるようになります。
`-N`でヘッダーが消えます。

```bash
$ mysql -h${DB_HOST} -u${DB_USER} -p${DB_PASS} -N -e "SELECT ID FROM information_schema.processlist where command != 'Sleep' and ${DB_WHERE};"  | cat
```


## kill

xargsを使ってkillします。

```bash
$ mysql -h${DB_HOST} -u${DB_USER} -p${DB_PASS} -N -e "SELECT ID FROM information_schema.processlist where command != 'Sleep' and ${DB_WHERE};"  | xargs -n 1 mysqladmin kill -h${DB_HOST} -u${DB_USER} -p${DB_PASS}
```

良いインフラライフをお送りください。
Integromatとクラウド型のRPAでチャットステータスを自動で切り替える

今回はIntegromatを使って、業務のオペレーションをちょっとだけラクにする自動化を作成してみましたので、ご紹介させて頂きます。

#自動化の背景
会社でチャットシステムを導入しており、オンラインのお客様対応を行っています。
・9:30(サポート開始時間)にチャットのステータスを手動で「オンライン」に変更します。
・17:00(サポート終了時間)にチャットのステータスを手動で「非表示」に変更します。
![zendesk.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/32b4b3c3-1a3a-6aaa-92a1-6ac7d8e925ee.png)
チャットが非表示になっていないと、お客さまからお問い合わせが来てしまいますので、必ず「非表示」に変更して業務を終了する必要があるのですが…
ここ最近、担当者がチャットをオンラインにしたまま退勤してしまうという事態が何度か発生しておりました。

こういうちょっとした作業、習慣化していても忘れるときは忘れますよね。
そこでIntegromat(iPaaS)とクラウドBOT(クラウド型のRPA)を活用して、この部分を自動化してみました。

#自動化の内容
自動化の内容はとても単純な物です。
![自動化フロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/843ffcba-32ea-021a-b5d2-c378e1c732d6.png)
1.Integromatのスケジュール設定を使用して、クラウドBOTのロボット(チャットのステータスを更新してくれるロボット)を実行する。
2.チャットワークでチャットのステータスを「非表示」に変更した事を通知する。

##今回の自動化のポイント
・Integromat、クラウドBOT共に無料の範囲で実現可能である。
・”忘れてはいけない日々のちょっとした作業”を自動処理に任せる事でヒューマンエラーを減らす。
・切り替えた事を自動で報告する。

##実際の作成手順
###事前準備:ステータス切り替え用のロボットを作成する
まずは、無料で使用できるクラウド型のRPAサービス『クラウドBOT』を使用して、チャットシステムのステータスを自動で更新してくれるロボットを作成します。

クラウドBOTにログインします。
『クラウドBOT』: https://www.c-bot.pro/
![クラウドBOT_ログイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/3ce798ec-e4e1-79c0-8f3e-b9b46ad6b578.png)

「BOTを作る」ボタンを押すと、ロボットを作成する画面が開きます。
![クラウドBOT_ロボット作成画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/c690fa3e-307f-2341-b654-2b3bda0e1e0e.png)

クラウドBOTは実際のWEB画面をクリックしながら、操作を選択していく事で簡単に自動操作ロボットを作成できます。詳しい使い方については今後別の記事で紹介したいと思います。
![チャット画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/52ebfb5f-c1ea-b9aa-984b-cbd3f5921a16.png)

今回はチャットシステムにログインし、ステータスを変更するだけのロボットですので、さくっと3分ほどで完成しました。
![ロボット作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/938db639-f571-d3fd-47a4-a0131191d710.png)


###1.Integromatのスケジュール設定を使用して、クラウドBOTのロボットを実行する。
『Integromat』:https://www.integromat.com/
IntegromatにクラウドBOTのモジュールを追加し、事前に作成した「チャットステータス更新」のロボットを選択します。
![BOTモジュール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/ba061faf-de59-467b-1a3b-06de8d8b115b.png)

スケジュール設定を使って毎日17:00に実行するようにしています。
![interval.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/37f87e16-e32e-e3f7-c041-57f870162743.png)

※スケジュール実行の機能事態はクラウドBOT側にもあるのですが、クラウドBOT側のスケジュール機能は有料プランに加入する必要があるため、今回はIntegromatを使用してロボットの実行を行いました。


###2.チャットワークでチャットのステータスを「非表示」に変更した事を通知する。
ロボットが実行した後にサポートチームで使用しているチャットワークのグループに「チャットを非表示にしました。」と通知するようにしています。
![チャットワークに通知.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459104/652dc5ad-095e-9876-0e9e-86e03d47fecc.png)


#最後に
今回紹介させて頂いたのは本当にちょっとした作業の自動化ですが、このような”気をつけなくてはいけない作業”は担当者の負担になっている事が多く、自動化すると喜ばれます。
興味のある方は是非、挑戦してみて下さい。
axiosのinterceptorsでリクエストに共通のパラメータを付与する

axiosを利用してAPIリクエストを送る際に、全リクエストに同じパラメータを付与したいパターンがありました。
リクエストを送るタイミングで個別にパラメータを追加してもよかったのですが、不毛なのでinterceptorsを利用して処理を共通化しました。

# interceptors の書き方

こんな感じで前処理を追加できます。

```javascript
import axios from 'axios'

axios.interceptors.request.use(request => {
  console.log(request.url)
  return request
})
```

詳しくは[Github](https://github.com/axios/axios#interceptors)を参照してください。

# 共通パラメータを追加する

## GET場合

```javascript
import axios from 'axios'

axios.interceptors.request.use(request => {
  const hoge = { id: xxx, value: xxx }
  request.params = {
    ...request.params,
    hoge
  }
  return request
})
```

## POSTの場合

```javascript
import axios from 'axios'

axios.interceptors.request.use(request => {
  const hoge = { id: xxx, value: xxx }
  request.data = {
    ...JSON.parse(JSON.stringify(request.data)),
    hoge
  }
  return request
})
```

## メソッドやURLで分岐させることもできる

```javascript
import axios from 'axios'

axios.interceptors.request.use(request => {
  if(request.method === 'get') {
    ...
  }
  
  if(request.url === '/hoge') {
    ...
  }
  return request
})
```
MyBatisのSQL文でforeachを回したい

####Spring BootでMyBatisを使っており、一括でSQLを回したいとき

例えばSELECTやDELETEで`IN`句を使って一括で値取得したり削除したりしたい場合ありますよね？foreachを使えばよいことは分かったのですが、`List<Integer>`とかで受けた値をそのまま`IN`句に渡したいとき、微妙に例が見つからなくて困ったので備忘録です。

```StudentMapper.kt
      interface StudentMapper {

           @DELETE(
              """
              <script>
               DELETE FROM Student
                 WHERE studentid IN
                 <foreach item="studentids" opem="("close=")" collection="studentids" separator=",">
                    #{studentids}
                 </foreach> 
              </script>
              """
           )
           fun removeStudentsByStudentId(studentids: List<Long>) {}
      }

```

MyBatisだとxmlでこういった`<select></select>`タグの中にこういったスクリプトタグで書く方法か、StringでSQL文を投げるかどっちかは見つかるのですが、SQL文の中にforeachを入れたいけど`#{something}`的な渡し方だとforeachが出来ないっぽかったのでこういったやり方になりました。

一応動きますが、無理やり感があるので、もしもっと良い方法があれば知りたいです。(MyBatisの公式doc読んでも方法分からず)
ファイルサーバーマネージャーにACLを導入する

## ゴール
社員1000人規模でも効率的に管理できるファイルサーバーのアクセス制御を実現する

https://qiita.com/hedgehog-genki/items/c32d154143f9ee6028db

このやり方だと各ユーザーごと全てにアクセス許可を逐一設定させなければならない

IT部
　山田 拓也
　田中 光治
営業部
　中村 良和
　中西 沙織
人事部
　立花 哲也
　野中 絵理
という組織図だとする。
各部署ごとにフォルダを作成して、それぞれにアクセス権を付与したい。
※人物名はこちらで生成したものなので仮名です

https://namegen.jp/

読取/書込（RW）
読取専用（RO）
何もできない

## ACL
通信アクセスを制御するためのリスト

## 解決案
①それぞれにRWとROのグループを作成する
②そのグループにそのユーザーを追加する
例えばIT山田さんにはITのRWと営業部のROを与えると
ITのフォルダにはRW、営業部のフォルダには読取専用、人事部には何もできない、ということが実現できる。

### 組織図と参加させるグループの振り分け
|所属部署|氏名|RWの権限|ROの権限|
|-|-|-|-|
|山田 拓也|IT部|IT部|営業部|
|田中 光治|IT部|IT部||
|中村 良和|営業部|営業部|人事部|
|中西 沙織|営業部|営業部||
|立花 哲也|人事部|人事部|IT部|
|野中 絵理|人事部|人事部||

## 実装していく
![スクリーンショット 2021-10-22 14.06.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/85ddfe45-65be-274e-3a23-182a5784e1cb.png)

直接Usersにユーザーを作っても良いが、ほとんどが各部署ごとにOUを作成している
さらにOUは入れ子にできるので、OUを作った方が便利

OUとユーザーを作成する

②ACL用のOUとグループを作成する
![スクリーンショット 2021-10-22 14.18.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/1aa9e2f7-1492-eccb-ad64-ce04e8c9db5a.png)

各部署ごとのRWとROのグループを作成する

③各グループに先ほど定義した要件通りに振り分ける
設定方法は2通り
1.グループから設定
グループ＞右クリック＞プロパティ＞メンバーから追加
![スクリーンショット 2021-10-22 14.21.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/92dda657-5dc3-cb8b-727e-bf20255fcc15.png)

2.ユーザーから設定
変更するユーザー＞右クリック＞プロパティ＞所属するグループから追加
![スクリーンショット 2021-10-22 14.23.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/d0426989-aaf6-8392-a151-e269229a0315.png)

④各フォルダの設定をする
※ここからは所有者ノードの端末で操作する
![スクリーンショット 2021-10-22 14.31.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/21356913-da77-502e-a536-a501b16f1a1c.png)
まずはフォルダの作成

アクセス権の設定
![スクリーンショット 2021-10-22 14.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/e3ae2739-c74a-8974-5fee-dca30e5e9acb.png)

各フォルダのプロパティ＞セキュリティから設定していく

### 確認する
適当にフォルダとファイルを作成しておく
![スクリーンショット 2021-10-22 14.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/80e18692-68d6-52ed-8a62-2eb88ebab865.png)

IT山田の場合、ITのRW、営業のROがあるため
![スクリーンショット 2021-10-22 14.40.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/343be7b0-12eb-507e-63d8-d21ba8d51f22.png)
![スクリーンショット 2021-10-22 14.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/c2b7f09c-ea19-67c5-af87-320e742e3bdc.png)

営業はアクセスできるが、テキストの編集はできない
![スクリーンショット 2021-10-22 14.41.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/0c511ef3-ed8f-2aaa-0140-5575fc5dbcab.png)

人事はアクセスできない
![スクリーンショット 2021-10-22 14.42.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/581e2c5d-4ab5-0580-8df2-b0a8945629d9.png)

### 補足
基本大企業では社員をExcelなどでDBとして保管してスクリプトを実行することで、これらの設定を自動化している（はず）
本来であればこの上でテストを実行するはず
Vue3 × tailwindcss で爆速webアプリ開発。～超絶簡単なtailwindcss の設定

#最近気づいた俺、css書けない、、、、、

ど素人の状態からwebアプリ開発を始めて早1年。
htmlもcssもよくわからない状態で現場にぶち込まれて、vueを触り始めたもんだから、まあわからん。
なんとなく、javascriptが書けるようになってきてvue.jsへの理解が進むと
少し楽しくなってきた。
その時は、UIフレームワークとしてvuetify.jsを使用していたので
まあ、ほとんどといっていいほど、cssの調整することはなかった。
あったとしても、widhtいじったり、background-color調整したり。

まあそんなんだから、マジでcssがわからない状態だった(笑)
そんな状態であるとき、ふと自分でvue.js　firebase でブログを立ち上げてみた
。まだデプロイしていないのだが、
まあ、cssがわからなすぎて、スタイルがひどい。

vuetifyでclassにスタイルを入れる記法に慣れていたので、
今更styleタグなんていじりたくもなかったし
最小限にしたかった。

そんなこんなでたどり着いたのがそう、tailwindcss


#tailwindcssのドキュメントが微妙にわかりずらくて(´;ω;｀)挫折

当初はドキュメントを見てフォルダを作成したが、これがうまくいかない。
英語なもんだから、purgeもよくわからんし、buildもうまくいっていない。

さて、前置きが長くなったがここから本題。

#vue.jsにおける正しい、tailwindcssの環境構築方法

若干公式とは外れた方法ではあるが、buildに必要なファイルはすべてはいっているので
問題なしと思われる。

まずは、普通にプロジェクトを立ち上げていく。

$vue create your-project-name

プロジェクトが立ち上がったら、
$cd your-project-name

でそのファイルパスまでいき
$vue add tailwind

これで、tailwindcssに必要なすべてのファイルが入る。
あとは、いつも通り、起動してあげればいい。
ビルドもすべてしてくれるからvue-cliチーム本当に助かる！
AWS-MFA認証のアカウントでAws\S3\S3Clientを利用するには


MFA認証が必要なAWSアカウントに対してWEB用SDKのS3Clientでアクセスする方法です。
AWSリソース間でのアクセスはRoleでの権限設定が推奨されていますが、例えばローカル開発環境からテストでS3にアクセスするとき、AWS_SESSION_TOKENの設定が必要になります。


対策はaws_session_tokenを配列に指定してオブジェクトを生成するだけです。

```php
    $s3 = new S3Client([
        'aws_access_key' =>  env('AWS_ACCESS_KEY'),
        'aws_secret_key' => env('AWS_SECRET_ACCESS_KEY'),
        'aws_session_token' => env('AWS_SESSION_TOKEN'),
        'region' =>  env('AWS_DEFAULT_REGION'),
        'version' => '2006-03-01'
    ]);
```
session tokenの取得はcliから。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/
あったらいいなと思っていたスキルマップアプリをVueとGoで作ってみた

# 作ってみたもの
作ったWebアプリは [Graphyee](https://graphyee.com) と名付けました。
技術と技術は関連しているものなので、「スキルマップをグラフ構造で表現できたら分かりやすくて面白いかな」と思いついたのが経緯です。
まだβ版としていますが、一旦使える感じになったのでノリと勢いで公開してみました。

こんな感じで [サンプル](https://graphyee.com/sample/1) は誰でも使えます。



:::note warn
サンプルは実績を入力しても保存できないのでご注意下さい。
:::



![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2201222/57ea423b-20f5-3dcf-8370-b8c19134a8d5.gif)

ユーザ認証すると、より細かい [スキルマップ](https://graphyee.com/graph/1) が使えます。



:::note info
ユーザ認証していただければ、入力した実績が保存されます。
:::




:::note warn
上記リンクからだとAuth0の認証画面へのリダイレクトにやや時間がかかりますが、そのうち認証画面が出てきます。
:::



![skillmap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2201222/bf356db7-e86d-07ef-04fe-51d92be2ad7a.gif)

https://graphyee.com

# 技術構成
せっかく作ったので、どうやって作ったかを簡単にご紹介します。
![構成図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2201222/ab335f93-309f-d8bd-51fa-f07ab34c564d.png)

### フロントエンド

- Vue 2.6.11
- Vuetify 2.4.0
- Vuex 3.6.2
- axios 0.21.1
- Cytoscape.js 3.18.1
- Auth0


VueでSPAを作り、UI周りのデザインはVuetifyを活用しました。バックエンドのAPI呼び出しはaxiosです。

Cytoscape.jsを使ってグラフ構造を実現しています。jsonでnodeとedgeを定義するとグラフが描画されます。

```json:sample_node
[{"id":"1","name":"node1"},{"id":"2","name":"node2"},{"id":"3","name":"node3"}]
```

```json:sample_edge
[{"source":"1","target":"2"},{"source":"2","target":"3"}]
```

認証機能は、アプリから切り離したかったのでAuth0で実現しています。
Silent AuthenticationやRefresh Token Rotationはこのサイトが理解しやすかったです。

https://dangerous-animal141.hatenablog.com/entry/2021/06/08/220637

### バックエンド

- Go 1.16
- Gin 1.7.1
- GORM 1.21.11

フロントエンドから呼び出されるAPIは、GoとGinで実装し、GORMでDBと接続しています。

Goはパッケージ管理の考え方がまだ模索中なのかな？って印象ですが、そこさえちゃんと理解できれば早く立ち上がるので気に入ってます。Ginも簡単なWebアプリ作るなら一瞬だったので、いい感じです。世の中にサンプルも多そうなでキャッチアップしやすい印象です。

GORMはいわゆるORMのクセみたいなのはありましたけど、普通に使う分には問題なく使えました。
最終的には、生のSQLを書きたくなるんですけどね。

https://gorm.io/ja_JP/docs/sql_builder.html

### インフラ

インフラはAWSで構築しました。コンテナ化や触ったことないサービスを使ってみようかなとも思いましたが、個人的に一番立ち上がりが早いサービスを選択しています。

ALB＋EC2＋RDSというとてもシンプルな構成です。

ここらへんを見ながら何使うか一瞬悩みましたが、また今度挑戦しようかなと思います。

https://aws.amazon.com/jp/builders-flash/202004/awsgeek-api-gateway/?awsf.filter-name=*all

# なぜ作ろうと思ったのか
IT業界で働いていて、「結局、具体的に何をどこまで経験してきて、何が不足しているのか？」を常々考えていたのが根底にあります。さらに、ある技術を網羅的に学んで仕事に活かすことが、自分にとって「塗り絵」をしていくイメージだったのも強く影響しています。

ただ、いちいち思い出して次は何しようかを考えたり、実績を誰かに伝えたりすることは中々面倒くさいのです。そこで、スキルマップを分かりやすく管理できればいいのでは？と思い立ちました。

# 使えそうな場面
例えばこんなシーンで使えるのかなと想像しています。是非、継続的に使ってみてください。
特にこれから勉強しようとしている人、勉強中の人向けに使えるのかなと想像しています。

- 学習や経験が網羅的にできているか知りたい。
- 学習や経験を計画したり、振り返ったりしたい。
- 今後どんなことを学習・経験すべきか知りたい。
- 自分や誰かの足りない部分を発見したい。

# 使ってみた方へお願い
求められるものが何なのか、今後作り続ける価値があるのか知りたいので、よろしければアドバイスいただけると嬉しいです！

https://forms.gle/fxdszFN87ZKuXoVK9

# 今後
やりたいことや検証してみたいことはたくさんあります。
もし良いフィードバックをいただけたら、下記以外にも色々試してみたいと思います。

- コンテンツがJavaだけで寂しいので追加したい。
- 認知度を向上して色々フィードバックをもらいたい。
- 誰かのスキルマップとの比較機能を付けたらありがたがられるのか。
- API Gateway＋コンテナ（Lambda/Fargate）にしたら嬉しいのか。
- Github ActionsでCI/CDしたら楽になるのか。
- ランニングコストぐらい回収できる感じにしたい。
- 課金して使える機能と課金の仕組みを入れてみたい。

# 最後に

作っていて記事になりそうなネタがあればまた投稿するので、その時にまたお会いしましょう。最後までお読みいただき、ありがとうございます！

https://graphyee.com
MySQL Workbenchで実行したSQLの履歴が消えた時

# はじめに

MySQL WorkbenchでSQLを叩いて動作確認・状況確認をしているため、SQLの履歴は以下のようになっています。

## SQLの履歴イメージ

![cap_workbench_sql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/8e2586c7-a733-26a5-19ac-fd5e9b40716a.png)


大量です。

現在は対象のDBサーバーも増えてきて、Workbench起動直後に表示される「MySQL Connections」のConnection設定数も多くなり、これまでの「Connection Name」のままではちょっと見辛くなってしましたました。

![cap_workbench_connections.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/9a600f64-cb0c-32b5-51fb-01921f78b23f.png)


そこで一旦「Connection Name」を整理して分かりやすしよう、と思い立ち「Connection Name」を変更しました。

するとなんということでしょう！！。履歴がまっさらではないですか！！

![cap_workbench_empty_sql_tab.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1236186/f26a0924-d945-b6bc-8e17-47f33c518d79.png)

・テーブル毎に開いていたSQLタブも1個。
・そのSQLタブの中のSQL(履歴)も空。


そこでConnection Nameは元に戻すことなく(変更後のままで)SQLの履歴だけ復旧したかったので、その方法を調べ、無事復旧できたのでその手順を備忘録がてらまとめようと思います。

# 環境

|種別|種類(Ver)|
|:-:|:-:|
|OS|Windows 10|
|MySQL Workbench|6.3|

# 履歴の保存場所

まずは履歴の保存場所を調べます。

```Text
C:\Users\USER\AppData\Roaming\MySQL\Workbench\sql_workspaces
```

上記のsql_workspacesフォルダに保存されているようです。
またxxxx.workspaceが確認できるかと思います。xxxxの部分がConnection Nameのようです。

※AppDataは隠しフォルダになっています。適宜表示設定を変更してください。

# 手順

以降、

|種別|Connection Name|
|:-:|:-:|
|変更前|aaa|
|変更後|bbb|

として手順を記載します。

## 1. (bbb.workspaceがまだない場合)Workbenchで変更後の「bbb」を開き、表示された「bbb」タブを閉じます。
Connection Nameをaaa->bbbに変更しただけではbbb.workspaceが作られていないため、bbb.workspaceを作るために一度「bbb」を開きます。

また作成されたbbb.workspaceにはlockファイルが確認できます。ロック状態のようで後の操作で影響が出てもいけませんので「bbb」タブを閉じます。

既に一度開いている／bbb.workspaceの存在が確認できる場合はスキップしてください。

## 2. aaa.workspace配下にあるすべてのファイルをbbb.workspaceにコピーします。
aaa.workspaceに幾つかのファイルが存在していますので、それらすべてをbbb.workspaceにコピーします。

## 3. 上記No2でコピーしたあとの未選択状態のファイルを削除します。
コピーした後、エクスプローラではコピーしたファイル群が選択状態になっており、これがaaa.workspaceからbbb.workspaceにコピーしたファイル群ですが、未選択状態のファイルが2つほど存在します。

これはおそらく上記No1でできた履歴なしのSQLタブの情報ファイルかと思いますので削除します。

xxx.workspaceにはSQLタブの情報を保存したファイルがあり、このコピー操作でbbb.workspaceのSQLタブ情報はaaa.workspaceのSQLタブ情報は置き換わったはずです。おそらく以降ずっと参照されることのないファイルかと思いますので、ここで削除しておきます。

## 4.「bbb」を開きます。
「aaa」の時に使っていたSQLが確認できます。

## 5．aaa.workspaceフォルダを削除します。
記事に引用URLとプログラムの背景を実装する

これができないと読みにくい記事を量産することになるので……
(正直n番煎じかとも思うが，自分で出来るようになる過程を記録しておいた方が良いと思い書くことにする．)

Qiita Support - 良い記事を書くためのガイドライン
https://help.qiita.com/ja/articles/qiita-article-guideline

Qiita(Increments株式会社) - Markdown記法 チートシート
https://qiita.com/Qiita/items/c686397e4a0f4f11683d

を参考に，自分の記事に章タイトル，引用URL，プログラムの背景を実装していきたいと思います．

(プログラムではなく，コードと書いた方が良いのか？)

上記Markdown記法チートシートの"Blockquotes - 引用"欄によると

> 文頭に>を置くことで引用になります。

(本当になった)
引用はこれでクリアですね．

> 引用の中に別のMarkdownを使用することも可能です。

とのことなので，さっそくこの引用の中にプログラム(コード)の黒い背景を入れてみたい……
チートシート最上段，"Code - コードの挿入"によると

>たとえば、Rubyで記述したコードをファイル名「qiita.rb」として投稿したいときは、 バッククオート を使用して以下のように投稿するとシンタックスハイライトが適用されます。
コードブロック上下に空行を挿入しないと正しく表示されないことがあります。

・黒い背景はシンタックスハイライトというらしい．
・`はバッククオートと呼ばれ，これを3つ使って囲った部分が黒くなる
ということが何とか理解できました．

ともあれコピペしてみないことには実感がつかめません．
チートシートのものを拝借して

```ruby:qiita.rb
puts 'The best way to log and share programmers knowledge.'
```

中身は

```(使用言語):(ファイル名) 多分ここが左上のグレー背景に入る
(コードの内容)
```

という構造になっているっぽい……
文面上はバッククオートを3つ使って囲んでいるのに，ビュー上では灰色背景になってしまいました．

```(使用言語):(ファイル名)
(コードの内容)
```

右上の"多分～～"を削るとうまくいきました．

チートシートによれば

>また、コードをインライン表示することも可能です。

>>` puts 'Qiita'` はプログラマのための技術情報共有サービスです。

>結果

>puts 'Qiita' はプログラマのための技術情報共有サービスです。

コピペだとうまく動いてくれず，難しい……
何を考えたかというと，右上の文章によりバッククオートが肩掛けになったので灰色背景になったと考察しました．
章タイトルの記事内リンクも作ってみたいと思いましたが，正直に言って今これ以上はわからないので，いったん今日の学習はここまでで終わっておきたいと思います．

わずかな事ですが，自分の考えた内容が画面に再現されるというのは自信に繋がりますね．
ここまでお読みいただきありがとうございました．
KMM kotlinx-serializationでクラッシュする時にやったこと

普段、iOSをやっていて、Androidは全く触っていないですが、KMMがずっと気になっていて某記事を参考に試しにやってみました。
慣れない中、クラッシュの連続で直すのが一番大変だったkotlinx-serializationでのエラーの直し方を残しておきます。
なかなかライブラリが参照されなかったり、クリーンしてようやく直ったと思ったら@ Serializablを使っているクラスが not foundでクラッシュしてしまいました。。

まず、shared内のbuild.gradleに下記を記述します。

```plugins {
    kotlin("multiplatform")
    kotlin("plugin.serialization") version "1.4.10" //これを追加
    id("com.android.library")
}
```

次にandroidApp内のbuild.gradleに下記を記述します。
```android {
    compileOptions {
        targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
        sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_8
    }
```

私の場合、以上で直りました！
慣れていない為かgradleなかなか厄介でした
bashのTIPSの個人的まとめ

## ヒアドキュメント

複数行のテキストを処理する機能
例えば以下のような形
(`EOL`の部分は任意。他に`EOS`や`EOF`などもよく使われる)

```bash
cat << EOL >> temp.txt
line1
line2
line3
EOL
```

これを使うとwhile文やfor文、変数への代入が楽になったりする。

```bash
cat << EOL | while read r
repository1
repository2
repository3
EOL
do
    echo ${r}
done
```

```bash
for r in $(cat << EOL
repository1
repository2
repository3
EOL
);
do
    echo === ${r} ===
    git -C ${r} status -sb
done
```

```bash
repositories=$(cat << EOL
repository1
repository2
repository3
EOL
)
```

### 参考リンク

- https://qiita.com/take4s5i/items/e207cee4fb04385a9952

## 変数の展開

変数が定義されていない時だけ設定したい、みたいなデフォルト引数的な処理などに使える。

具体例
`value=${1:-"empty"}`とすると、引数が空だと`empty`が設定されるし引数が渡されたらその引数が入っている。
`: ${TOOL_PATH:="/bin"}`とすると、変数(主に環境変数)が設定されていたらそれを使うし、そうでなければ`/bin`を代入する。

> TIPS:ここの`:`は何もしない命令で、単に`${TOOL_PATH:=}`とすると`${TOOL_PATH}`に設定されている値か、空であれば`/bin`がコマンドと解釈されてしまう。

### 参考リンク

- http://kodama.fubuki.info/wiki/wiki.cgi/bash/tips?lang=jp#20
    - 他にも置換などの便利機能があるので読んでみると面白いかと。

## エラーや未定義変数操作時に処理を止める

`bash`コマンドの引数で解決する。
- `-e` : エラー発生時に止める
- `-u` : 未定義変数参照時にエラーにする

実行コマンドをログに表示するための`-x`とともに、`bash -eux script.sh`というように使われることが多い。

よくあるのがファイルの先頭に書く呼び出しコマンドのところに引数を与えること。

```
#!/bin/bash -eux
errorcommand
```

> TIPS: 先頭行で`/bin/bash`と書く部分はシェルに限らずどのコマンドでも指定できる。`python`とか`php`とか。

### エラーをもみ消す

例えばキャッシュを削除するような処理で単に`rm cache`と呼び出すケースにおいて、`cache`が存在しなければエラーになる。
単にエラーになるなら`No such file or directory`と怒られるだけだが、`bash -e`と呼び出していた場合ではそこで処理が止まってしまう。
それを避けるために何もしないコマンド`:`に`||`(前のコマンドが失敗したら次のコマンドを呼び出す)でつなげることでエラーをもみ消すことができる。
上のケースでは`rm cache || :`と書く。(エラー出力ももみ消すなら`rm cache 2>/dev/null || :`)
zerotierで接続できなくなったから再起動する【Mac】

どういうわけかzerotierでアクセスできなくなった。

```
zerotier-cli peers

200 peers
<ztaddr>   <ver>  <role> <lat> <link> <lastTX> <lastRX> <path>
02a619c79x 1.6.5  LEAF      -1 RELAY
0560cee07x 1.6.5  LEAF      -1 DIRECT 409      409      192.168.11.40/22610
```

どうやらRELAYになっていると繋がらないらしい

```
#stop zerotier
sudo launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist

#start zerotier
sudo launchctl load /Library/LaunchDaemons/com.zerotier.one.plist
```

```
02a619c79x 1.6.5  LEAF       2 DIRECT 3412     3410     192.168.11.80/34340
0560cee07x 1.6.5  LEAF       3 DIRECT 1331     1319     192.168.11.40/22610
```

したら治った
伝説のif文

## これはなんですか
私が体験したホラーかサスペンス、ミステリーの類。
よく話すので、ここに晒してURLみてくださいって形にする。
当時目が血走っていたスクラムマスター兼技術主任兼アーキテクト兼レビュワーだった私がレビューしたちょっとふしぎなコード。

## 本文
原文ママだと怒られるので、ちょっと改変しています。　いうほど改変していないけど・・

こんなかんじのコードがプルリクで上がってきました。

```
  if (A==B) {
    return true;
  } else {
    return false;
  }
```

私は当時会議中でお忍びレビューしていたので、

**「おン？　そのままreturnすればええやん」**

といった旨のことをコメントで書きました。

そして改善されて出てきたコードがこちら

```
  if (A==B) {
    return A==B;
  } else {
    return A==B;
  }
```

（♪: 世にも奇妙なテーマ）

(つд⊂)ｺﾞｼｺﾞｼ
　
(；ﾟдﾟ) ・・・？？？

(つд⊂)ｺﾞｼｺﾞｼｺﾞｼｺﾞｼ

(ﾟДﾟ)ﾊｧ?

なお、その1ヶ月くらい後にこのコードを書いた彼は現場から飛びました。

正解例として、書いてほしかったコードはコチラ。

```
  return A==B;
```

まだだまだおわらんよ。

そして彼が飛ぶ日にも一波乱あったのだが・・・その話はを書くには余白が足りない。
【Swift】ナビゲーションバーの右に閉じるボタンを設置

Swiftでナビゲーションバーの右上に閉じるボタンを設置する方法。

```swift
//ボタンの実装
let next = NextViewController()
next.navigationItem.rightBarButtonItem = {
    let btn = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(self.onPressClose(_:)))
    return btn
}()
let nav = UINavigationController(rootViewController: next)
self.present(nav, animated: true, completion: nil)
```
次にボタンが押された時に処理される`onPressClose`の中身を実装。

```swift
//閉じる処理を書いた関数
@objc func onPressClose(_ sender : Any){
    self.dismiss(animated: true, completion: nil)
}
```

`barButtonSystemItem: .close`は標準で搭載されているものから選べる。

close以外の種類を選びたい方は以下の記事がおすすめ。

https://qiita.com/siropaca/items/bd35acc6b6fc039f3b6c

https://capibara1969.com/1391/

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
Lookerのグローバルフィルタの関連付け方法メモ


Lookerのグローバルフィルタを使って探索的にデータ参照する場合に便利な方法の紹介です。

※バージョンはLooker 21の新UIでの対応方法になります。


# １つのフィルタで複数テーブルの項目内容を関連づける

1) Lookerのダッシュボードを起動して、**Edit dashboard**を選択する

|![グローバルフィルタ使い方1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/df1e7c47-5a5b-d49a-7e72-e48f4956992c.png)|
|:--|


2)関連付けしたいフィルタの**Edit**を選択する

|![グローバルフィルタ使い方2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/92209ad4-d2f2-31eb-a109-1486b4dd4135.png)
|:--|

３）フィルタのEdit画面で、**Tiles To Update**を選択するとフィルタを同期可能なLookが表示されるので、**Field to Filter**で同期させたい項目を選択して、**Update**を選択する

|![グローバルフィルタ使い方3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/0d3e0b89-5376-22ed-05cc-87aefecaa87d.png)
|:--|


**これで、１つのフィルタで絞った内容が、対象Look全てに同時反映（同期）されるようになります。**


# １つのフィルタで絞った内容を他フィルタに同期連動させる

1) Lookerのダッシュボードを起動して、**Edit dashboard**を選択する

|![グローバルフィルタ使い方1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/df1e7c47-5a5b-d49a-7e72-e48f4956992c.png)|
|:--|


2)関連付けしたいフィルタの**Edit**を選択する

|![グローバルフィルタ使い方2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/92209ad4-d2f2-31eb-a109-1486b4dd4135.png)
|:--|

３）フィルタのEdit画面で、**Settings**を選択し、**Additional option**を選択して、**Select filters to update when this filter changes**にチェックを入れて、連動させたい別のフィルタを選択し、**Update**を選択する

|![グローバルフィルタ使い方4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/b133f565-4058-4a27-a610-1f4890c6e8e9.png)
|:--|

**これで、１つのフィルタで絞った内容が、他フィルタに動的反映され、２つ目以降のフィルタの選択肢が絞られるようになりました。**
HTTPセッションIDをログイン時に更新する(セッション固定攻撃対策)

---
### はじめに

**「ログイン認証に成功したらセッションIDを更新する」**というのは、セッション固定化攻撃(Session Fixation)の対策としては有名な話かと思う。
PHPの[session_regenerate_id](https://www.php.net/manual/ja/function.session-regenerate-id.php)のようなWebアプリケーション・フレームワークにセッションIDを再生成する関数が用意されていればいいのだけど、そういう関数がない場合は、どういう実装方法があるのかという点について考察した。

---
### フレームワーク提供のHTTPセッションID + 独自乱数 = HTTPセッションID

単純な話で、ログイン時に**セキュアな乱数※を生成して**、それをセッション関数/セッションオブジェクトとクッキーに同時に保存する。

セッションIDの一意性はWebアプリケーション・フレームワーク提供のセッションIDが保証しているので、自作側(上記のセキュアな乱数)には一意性の必要性はなく、推測困難性だけでよい。
なので、適当にセキュアな乱数を生成すればいい。
(セキュアな乱数が、以前の作成値とたまたま偶然にも同じ値になるかも...とかいうのは考慮しなくてよい。ということ)

以降は、このクッキーの値とセッション変数/セッションオブジェクトの値が、**ヌルでなくかつ**同一かどうかをチェック。
同一でない場合は、強制ログアウト処理(ログイン画面へリダイレクト)。
そして自作クッキーとセッション変数を破棄する。

![SessionFixsation01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182822/24cce730-62d8-47eb-c5fd-dd4f52ed8d7f.png)

※ (普通の乱数+内部状態{内部でしか使っていないユーザIDとか})をSHA2する、でもよいと思う。
※ 念のためにセキュアな乱数を、さらにSHA2で追い込んでも、よいと思う。
(セキュアな乱数がセキュアでなかった時にもSHA2しているし、SHA2の脆弱性が仮に見つかったとしても、シードがセキュアな乱数なので、ひとまず安心できると思う)
(使用しているセキュア乱数を呼ぶ関数とSHA2の脆弱性が、同時に見つかるとヤバいけど...)

---
### 余談

フレームワークによっては、

・一意性のある値(連続する番号)
・推測困難な値

という2つの別々のクッキーを吐き出して、この2つのクッキーをまとめて**「セッションID」**とするフレームワークもあるよ。

なので、2つ以上のクッキーでセッションIDを構成しても特に問題にはならないと思う。

---
### その他

他のやり方もあると思う。
そういうのはコメントに書いてほしい。

---
### 以上
C#ネット学習で得られること知りたいよね！（２／２）


:::note info
塾長
アルゴリズム（手順）を考えておかないとプログラミングできないよね。
プログラミング学習を続けるには、アルゴリズムを考えることが楽しいと思えないとだめなんだなー。
:::

:::note warn
生徒：
なんか、めんどくさそうですねー。
:::


:::note info
塾長
そう、頑張りが必要なのよな。
でも、自分で考えたアルゴリズムでプログラミングして、無事迷路を脱出できたらうれしいいよね！！！。
:::

:::note warn
生徒
難しくて頭がまとまらないかも。
:::


:::note info
塾長
アルゴリズムを整理する（頭の中を整理する）技法として「フローチャート」があるんだよ。中学校では技術でちょっと教えているみたい。当塾でも当然教えますよ！
:::



【技術者が言うアルゴリズムとは】

アルゴリズムは作成する人によりそれそれ異なります。人によって考えが異なるので当然です。

また、結果が正しければ（C#ネット学習教材では忍者が脱出できたら）正解です。

他の人と答え合わせしたり、実際に動かすことによってアルゴリズムは見直され合理的な１つになっていきます。これを最適化といいます。

長い間、学者や技術者の中で最適化されたアルゴリズムには○○法とか名前が付いています。例えば迷路を解決するアルゴリズムには、幅優先探索法（BFS)があるそうです。

 

\アルゴリズムがわかったら、以下よりC#の学習を行っていきましょう！/


https://programingo.com/csharp-2/