OmniAICreator/Qiita-1.07M huggingface dataset:
ブラウザバックで「ちょっと待って」的なアラートをだすhooks


コチラでございます。

```tsx
import { useEffect } from 'react';

/**
 * 一度入力した後にリロードすると、確認ダイアログを出す。
 */
export const useOnReloadAlert = (enable: boolean = true) => {
  useEffect(() => {
    if (!enable) return;

    window.history.pushState(null, '', window.location.pathname);
    const onReload = (event: BeforeUnloadEvent) => {
      event.preventDefault();
      event.returnValue = '';
    };
    window.addEventListener('beforeunload', onReload);
    return () => {
      window.removeEventListener('beforeunload', onReload);
    };
  }, [enable]);
};
```

`enable: boolean`オプションは、特定の条件化でブラウザバックアラートを出したくないので、追加しました。

具体的なケースは、SPA上で `入力 -> プレビュー -> 完了`の画面遷移を行う場合です。
ページ遷移してしまえばいいのですが、わざわざrecoilやcontextで構築するほどでもないな〜という気持ちで、state管理で進めた結果以下の構成となり、

```tsx
type PageType = 'create' | 'preview' | 'complete';

...

  const { values, ...handlers } = useXXXForm();

  switch (pageType) {
    case 'create':
      return <CreatePage values={values} {...handlers} />;
    case 'preview':
      return (
        <PreviewPage values={values} />
      );
    case 'complete':
      return <CompletePage handleSubmit={handlers.handleSubmit} />;
  }
```

で、この場合ですと、completeから離脱する際にもhooksが発火してしまう可能性があります。
（e.g. stripeの決済ページcheckoutなど）

そういうシーンで以下のようにオプションを渡す場合にお使いください！

```tsx
const enableOnReloadAlertPages = new Set<UserPreviewPageType>(['create', 'preview']) 
useOnReloadAlert(enableOnReloadAlertPages.has(pageType));
```


不要な場合は以下で大丈夫です！

```tsx
import { useEffect } from 'react';

/**
 * 一度入力した後にリロードすると、確認ダイアログを出す。
 */
export const useOnReloadAlert = () => {
  useEffect(() => {
    window.history.pushState(null, '', window.location.pathname);
    const onReload = (event: BeforeUnloadEvent) => {
      event.preventDefault();
      event.returnValue = '';
    };
    window.addEventListener('beforeunload', onReload);
    return () => {
      window.removeEventListener('beforeunload', onReload);
    };
  }, []);
};
```
VSCodeにて仮想環境上（venv）でgitコマンドが認識されない

# VSCodeにて仮想環境上（venv）でgitコマンドがエラーになり認識されない

windows
VSCode
venv

gitはWindows版をダウンロードし、インストール済み


venv仮想環境上でgitコマンドが認識されない。
```
> git
git : 用語 'git' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記 述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行
してください。
```

## 原因
gitインストール時に、VSCodeを選択しなかったからっぽい。

## 対策
VSCodeを選択してgitの再度インストール実行。VSCode再起動で、gitコマンド通りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245425/f05d0455-a668-0605-6cb9-a91a85e21466.png)

```
> git
usage: git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [--super-prefix=<path>] [--config-env=<name>=<envvar>]
           <command> [<args>]

These are common Git commands used in various situations:
```
Codility Lesson4 PermCheck

Lesson4のPermCheckは配列Aに対して1~N(Nは任意)の範囲の値が欠落せず登場しているかを判定するというものです。
例えば長さ3の配列A,Bに対して
A = [2,1,3]は1~3の数字が欠落せず並んでいるが
B = [2,1,4]は1~4の数字のうち3が欠落していることがわかる。
このような数字が欠落しているかを判定するプログラムを今回は書いていきます。


アルゴリズムは以下の通りです。 1 配列を小さい順にソーティングしていく。
2 ソートし終わった配列に対して、配列の0番目から順番に1,2,3…と並んでいるかどうか確認していき、並んでいる場合は1を、途中で数字が飛んでいる場合は欠けているということなので0を返せばよい。


コードは以下の通りです。

    def solution(A):
        A = sorted(A)
        len_A = len(A)
        i = 0
        while i < len_A:    
            if i+1 == A[i]:
                i += 1
            else:
                break
    
        if i == len_A:
            return 1
        else:
            return 0




さて結果は。。。。？

![スクリーンショット 2022-07-02 21.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667538/43c680a5-f950-4cd5-f989-ce62cfb44267.png)

やったー、100%です！
Amazon S3 Storage Lens とは

## 勉強前イメージ

s3の中の機能なんだろうけどlensはなに？？

## 調査

### Amazon S3 Storage Lens とは

S3の利用状況を把握することができる機能です。
オブジェクトストレージの利用状況とアクティビティの傾向を可視化して
コストの効率やデータの保護に関してのベストプラクティスに向けたものが提供されます。
AWS Organizationsと連携するとアカウント全体のストレージの使用状況など管理できます。

cloudwatchのメトリクスで標準のメトリクスだと無料で使えます。
高度なメトリクスだと有料になります。

Storage Lensを見ると、アカウント個人、全体の容量がどれだけなどぱっと見で見れるような感じです。

### 作ってみる

s3からダッシュボードを作成します。

![1S3 Storage Lens dashboard - Google Chrome 2022-07-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/42d36c57-7f6d-b3ac-7bd9-9d2b1a3f66ab.png)


詳細設定をします。
ダッシュボード名やリージョン、メトリクスをどうするかなど選んで作成します。

![2S3 Storage Lens dashboard - Google Chrome 2022-07-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f0355597-ffb2-d8bc-7ddc-6eb279efff59.png)


![3S3 Storage Lens dashboard - Google Chrome 2022-07-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6a36629e-baf2-642d-5f5f-454f35158a5b.png)


最大48時間かかるそうで、結構できるまで待たないといけないみたいです。

![4S3 Storage Lens dashboard - Google Chrome 2022-07-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3c327bfe-7a1d-d7ee-614a-d22dd010754b.png)


## 勉強後イメージ

確かに何もしなくてもcloudwatchで取れる値って結構少ないよね。。。
オブジェクト数とバケットのサイズくらい

## 参考

- [Amazon S3 Storage Lens を組織単位で有効化する](https://blog.serverworks.co.jp/s3-storage-lens-with-organizations)
- [[新機能] S3 の利用状況が一目瞭然！しかも無料！「Amazon S3 Storage Lens」がリリースされました！](https://dev.classmethod.jp/articles/amazon-s3-storage-lens/)
【kotlin】Anyクラスについて

# はじめに
今回はkotlinで使われる**全てのクラスの親クラス**にあたる ”**Anyクラス**”についてまとめていきます。





# Anyクラスとは
まず、Anyクラスについてですが、前述したように　Anyクラスは**全てのクラスの親クラス**です。
実際のコードでは省略されている為　目にする事は少ないです。
ですが、どのクラスでも　継承元を辿っていくと最後に辿り着くのは必ずAnyクラスです。
なので、何度も記載する通り　**全てのクラスの親クラス**　ということになります。




# Anyクラスの中身
Anyクラスでは何をしているのか　見ていきましょう
実際のコードがこちらです

```
public open class Any {
〜コメント省略〜

    public open operator fun equals(other: Any?): Boolean
〜コメント省略〜

    public open fun hashCode(): Int
〜コメント省略〜

    public open fun toString(): String
〜コメント省略〜
}
```

Anyクラスではこの３つの関数があります
kotlinで作られた全てのクラスで自動的にAnyクラスが継承されているので、この３つの関数を使うことができます。
それぞれ見ていきましょう。

#  equals
比較のための関数で、演算子の「==」を使い比較する際などに暗黙的に呼ばれている関数になります。
比較した結果を　true もしくは、false で返します。

# hashCode

オブジェクトのハッシュコードを生成してそれを　Int つまり数字で返します。

# toString
すべて文字列化するための関数で　オブジェクトを文字列に変換します


# 終わりに
Anyクラスはkotlinを使う中でなんとなく、けど当たり前に　使っていた便利な機能が詰まったものだったと調べてわかりました。
こうして改めて一つ一つを紐解いていくと、コードの理解度が上がっていくのを実感します。
【#18 エンジニア転職学習】Git/Github基礎　ブランチ/コンフリクト

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

昨日に引き続きGit基礎に関して進めていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はGitのブランチに関する基礎を学習しました。

* ブランチの基本情報
* **ブランチ作業基礎　←Topics!!**
* マージ
* **コンフリクト　←Topics!!**

# ブランチの作業基礎、コンフリクト
### ブランチの作業基礎
ブランチを利用した作業方法の基本は下記になります
* masterブランチをリリース専用
* 開発用としてtopic別にブランチ作成

こうすることによってmasterが常に最新のリリース版として扱えるのでバグがあったとき等に対処しやすいそうです。

### コンフリクト
3種類あるマージパターンの1つで、**1つのファイルの同じ行を複数人で変更**してしまったときに、Gitが**どっちのブランチを優先したらいいのか分からなくなる**現象です。

対処法
1. `git status`でコンフリクトしているファイル確認
1. エディタで対象ファイルの修正
1. 修正後、コンフリクト記述の`<<` `==` `>>`を削除
1. 再度`git add`と`commit`を実行する

使用している教材はこちら↓


https://www.udemy.com/course/unscared_git/


# おわりに
最後までお読みいただきありがとうございました。
しばらくはGit基礎をやっていきます。
アドバイス・応援コメント等いただけますと幸いです。
【Python】Tkinterを使ったコメントを投稿してみた

# はじめに
Pythonは未だ初心者ですが、Tkinterを使ってコメントを投稿してみました。

## Tkinterをインポートする
まず初めにTkinterをインポートします。

```
>>>import tkinter
```
## コードを実行する
下記はコードの実行結果です。
```python
import tkinter
""" 投稿ボタンの生成 """
def click_btn():
    x = text_x.get('1.0', 'end -1c')
    text_y.insert(tkinter.END, x)
""" 消去ボタンの生成 """
def delete_btn():
    text_y.delete('1.0', tkinter.END)


root = tkinter.Tk()
root.title('コメント出力')
root.geometry('600x600')
"""コメント書き込み欄の生成 """
text_x = tkinter.Text(width = 50, height = 6, font = ('Times New Roman', 16))
text_x.place(x = 20, y = 350)
""" コメント投稿欄の生成 """
text_y = tkinter.Text(width = 50, height = 6, font = ('Times New Roman', 16), bg = 'lightyellow')
text_y.place(x = 20, y = 50)
btn = tkinter.Button(text = '投稿', font = ('Times New Roman', 16), command = click_btn, bg = 'lightblue')
btn.place(x = 190, y = 550)
btn = tkinter.Button(text = '消去', font = ('Times New Roman', 16), command = delete_btn, bg = 'lightgreen')
btn.place(x = 290, y = 550)

root.mainloop()
```
![tkinterコメント投稿.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2035661/d34be1ed-aa4c-6785-b1cd-2aa5c96591ff.png)

以上になります。
GA4 APIをPHPで叩こうとしたら undefined function とか言われた

https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries#php

に書いてない所で詰まるの本当に辛い。

# まずは認証を通す

認証は環境変数にクレデンシャルのjsonの場所を入れればOK。

```php
<?php
putenv("GOOGLE_APPLICATION_CREDENTIALS=/path/to/credential.json");
```

あとはGA4の管理画面の方でサービスアカウントを閲覧者としてユーザーに追加。
（Read & Analyzeは英語でも名前が変わったみたいだが、とにかく日本語では「閲覧者」権限でOK）

# 通ってるみたいだけど謎エラーが出る

```
Uncaught Error: Call to undefined function Google\Protobuf\Internal\bccomp()
```

これはbcmathが入っていないのが原因。

https://stackoverflow.com/questions/61805958/cant-figure-out-why-i-get-app-engine-flex-uncaught-error-call-to-undefined-fu

composerのやり直しとかは無しで、以下でいけた。

```bash
sudo apt install php7.4-bcmath
```

php.iniに以下を追加。

```ini
extension=bcmath
```

----

これを自分のNotionにメモろうとして、他のPHP関連のセットアップメモをうっかり上書き紛失している事に気が付いた…辛い…。
【SwiftUI】Listをカスタマイズ

# はじめに
SwiftUIでTableViewと同じような見た目を作成するにはListを使用する必要があります。
しかし、Listでは変更できない項目が多く存在します。
おそらくListはUITableViewで作成されているので、UITableViewの設定が反映されます。

それを使用して、公式のAPIでは提供されていない機能を実装します

# 背景色を変更
```swift
import SwiftUI

struct ContentView: View {
    init() {
        UITableView.appearance().backgroundColor = .red
    }
    var body: some View {
        List {
            ForEach(0..<10) { _ in
                Text("テキスト")
            }
        }
        .listStyle(.grouped)
    }
}
```

# 区切り線の色を変更
```swift
import SwiftUI

struct ContentView: View {
    init() {
        UITableView.appearance().separatorColor = .red
    }
    var body: some View {
        List {
            ForEach(0..<10) { _ in
                Text("テキスト")
            }
        }
        .listStyle(.grouped)
    }
}
```

# 区切り線の長さを変更
```swift
import SwiftUI

struct ContentView: View {
    init() {
        UITableView.appearance().separatorInset = .init(top: 0, left: 0, bottom: 0, right: 20)
    }
    var body: some View {
        List {
            ForEach(0..<10) { _ in
                Text("テキスト")
            }
        }
        .listStyle(.grouped)
    }
}
```

# バウンスの無効化
```swift
import SwiftUI

struct ContentView: View {
    init() {
        UIScrollView.appearance().bounces = false
    }
    var body: some View {
        List {
            ForEach(0..<10) { _ in
                Text("テキスト")
            }
        }
        .listStyle(.grouped)
    }
}
```

# おわり
まだあると思うので気づいたら追加します。
不便なので早く公式APIとして提供してほしいです。
Mysql2::Error: Specified key was too long; max key length is 767 bytes

オリアプを作っている際に見慣れないエラーが発生したので、どう解決したのかを書きます。

## エラー発生
サーバーを立ち上げてlocalhost:3000にアクセスしたところ、activerecord::pendingmigrationerrorというエラーが画面に表示されました。
ターミナルを確認してみると、以下のエラーが発生していました。
```
Mysql2::Error: Specified key was too long; max key length is 767 bytes
```
## 原因と解決策
エラー文によると、keyの長さの制限である767byteを超えてしまったようです。
そもそもこれまでアプリを作成した際に発生したことがなかったのでなぜ？と思い過去のアプリを確認したところ、database.ymlにある`utf8mb4`を`utf8`に変更することを忘れていました。
どうやら`utf8mb4　`だと1文字4バイトとなってしまい767バイトを超えてしまうみたいです。
```database.yml
  encoding: utf8　 #utf8mb4からutf8に変更
```
上記のように、utf8に変更することでエラー解決できました。
【nodebrew】Use of uninitialized value $b1 in numeric comparison (<=>)の解決法

# 不要になったバージョンを削除すると。。。

```console
$ nodebrew ls
v8.9.4
v12.16.3
v14.17.2
v16.15.1

// 指定のバージョンを削除
$ nodebrew clean v8.9.4

// なぜか削除されない？？！
$ nodebrew ls
v8.9.4
v12.16.3
v14.17.2
v16.15.1
```

と言う状況になりまして。。。

一回Finderから削除してみることにしました！
👇は削除後
![Screen Shot 2022-07-03 at 21.21.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/21ec14c6-5bd5-0596-5edd-7732fd0693ce.png)

# `.DS_Store`が残ったせいかエラー
Finderから削除したからか、理由はよくわかりませんが`.DS_Store`が存在しているせいでエラーが発生・・

```console
$ nodebrew ls
Use of uninitialized value $b1 in numeric comparison (<=>) at /Users/gen/.nodebrew/current/bin/nodebrew line 678.
Use of uninitialized value $a1 in numeric comparison (<=>) at /Users/gen/.nodebrew/current/bin/nodebrew line 678.
.DS_Store
v14.17.2
v16.15.1
```

下記コマンドで.DS_Storeファイルを削除するとエラーがなくなりました:relaxed:

```console
$ rm ~/.nodebrew/node/.DS_Store
```
Postgres: Power BI で利用しやすくする為の Pivot SQL

# 背景
Unpivot の反対に Pivot をしたくなったので

https://qiita.com/baku2san/items/7606a46e85d2c8ea9bf6

# 概要
Pivot が無いので、Group By して

# 詳細
## 変換前：元データ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/888ad321-863e-b62d-dbef-3109a074818a.png)

## 変換後：取得したい結果
こんな感じで Pivot したいだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/310b2f3c-01a2-fecd-3d7d-db8635849380.png)

## SQL
- GROUP BY でグルーピング
    - 条件合致するデータだけを Pivot 追加列に取得
        - MIN: 特に意味は無い。取得対象は一点あるかないか、なので、MIN 使ってるだけ
    - COALESCE で存在しない場合の値を定義。例では全部 0
``` sql: Pivot
SELECT 
    "ID",
    COALESCE(MIN(t0."SubID"), 0)::int AS  SubID,
    COALESCE(MIN(CASE WHEN "isVertical" THEN "length" END), 0)::int AS  Height,
    COALESCE(MIN(CASE WHEN NOT "isVertical" THEN "length" END), 0)::int AS  Width,
    COALESCE(MAX(t0."SubID"), 0)::int AS  SubID2
FROM sampleTable AS t0
GROUP BY "ID"
```

# あとがき
Pivot が無いと気付かず少し悩んでしまった・・

# keyword
Equivalent to pivot() in PostgreSQL
個人的にVSCode に入れておきたい拡張機能

## 個人的にVSCode に入れておきたい拡張機能

### vscode-icons
- フォルダや各ファイルもアイコンをつけてくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/e5bea0fb-b9f3-6c2b-1ef5-e1c942466181.png)


### Auto Rename Tag
- ペアになっているタグを自動的に修正してくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/18a5c0e1-18c2-d236-0cc1-342a8812e7ba.png)


### GitHub Theme
- 自分の好きなテーマに変更できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/f633864a-9395-604f-3600-fe354d902f18.png)


### Japanese Language Pack for Visual Studio Code
- 日本語にしてくれる。
　日本人なのでこれがないとまったくわからない（笑）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/26a6628e-3a7f-5096-f3ee-4c1ecec77051.png)


### Draw.io Integration
- フローチャート、プロセス図、組織図、UML、ネットワーク図などを作成できる優れたツールです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/882f1fc1-2346-ba3f-ec9d-cee25d85c32b.png)
ディープラーニングを勉強する #1

# ディープラーニングを勉強する

## はじめに
本投稿は、ディープラーニングを勉強するにあたっての備忘録である。
内容について、間違いがあればご指摘いただきたい。

## 参考書
使用する参考書は以下の通り

[ゼロから作るDeep Learning](https://www.oreilly.co.jp/books/9784873117584/ "ゼロから作るDeep Learning")

![ゼロから作るDeep Learning](https://image.yodobashi.com/product/100/000/009/002/645/163/100000009002645163_10204.jpg "ゼロから作るDeep Learning")

採用理由・・・**ぶっちぎりで一番評価が高かったから！！**

## これから
2022/7/4~ 週に2回投稿で約１か月で本参考書を一度読み切りたいと思っています。
auの通信障害について素人が調べてみた

# 背景
自分はau回線を使ってなかったけど、ニュースを見る限りかなり大規模な障害であった。
単純な興味から今回の事件について少し調べてみた。
また、通信系に使われてる技術や用語を知っておきたいなと思った。
基本的には記事のまとめという感じで軽めに読んでもらえれば。

# 事故原因
>障害原因のきっかけとなったのは、全国中継網におけるルーターの定期メンテナンス作業。
ルーターを同一機種の新しいものへ変更したところ、ルーターに何らかの不具合があり、
音声通信の一部が約15分間不通になった。この問題への対応として音声トラフィックの切り戻しを行ったが、
切り戻し後のアクセス集中により、VoLTE交換機で輻輳が発生した。[1]

**原因はメンテナンス時の機器交換の失敗。またその切り戻し対応後のアクセス集中による輻輳**
※輻輳（ふくそう）は、トラフィックが集中することにより処理が混雑すること。輻輳は混雑な状態のため、一切通信が出来なくなったわけではなく、誰かが抜けたらすぐ誰から入るという状態をイメージするとわかりやすい。

どうやら切り戻し後にアクセスが集中してしまったらしい。深夜2時頃に作業完了しており、メンテ後すぐのアクセスのようです。
メンテ終了後にアクセスが集中することは予想できるが、今回だけ大規模障害になるほどのアクセス集中なのだろうかと腑に落ちない。
と思って別の記事を見たら、もう少し詳細原因が記載してあった。
[KDDI髙橋社長が「au通信障害」謝罪、現時点で判明している経緯とは](https://k-tai.watch.impress.co.jp/docs/news/1422015.html)
中の記事を見てなるほどとなった部分がある。
一時的に接続がつながらなくなったことでセッションや情報を扱うデータベース上の中身が変な状態になっていたようだ。
**こういうトラブル時でも耐えうるデータ設計は必要だが、実際にできているかは評価しづらいし多分ほとんどのエンジニアはきちんとできていないと思う。（多分私もできていない）
後、大規模システムだと関連するシステムが多すぎて見切れないというのもある。**

~~後は勝手な憶測としてメンテナンス時の事故があったんじゃないか。
普段行わないオペレーションをやるとなった時に、何か間違えた作業でデータを破壊してしまいその復旧がうまくできなかったとか。
明らかなミスにより起こしてしまった場合はなるべく外に出したくない情報なので、うまく言い訳をするとかは全然ありえそう。~~
最初の不完全な情報だけでたてた憶測なので取り消し線にしておきます。

# VoLTE及び通信規格
今回機器交換したものはVoLTE交換機というものらしい。
>VoLTEとは、データ通信で使用される高速モバイル通信網（LTE）でパケット交換をして、音声通話も処理するという仕組みのことで、「Voice Over LTE」の略称です。日ごろスマホでサイト閲覧などをしている通信と同じところに通話のデータも乗ってくるといった意味になり、LINEやSkypeなどと同じようなIP電話と同じような仕組みになります。ただ、IP電話のデータよりもVoLTEのデータのほうが優遇されており、IP電話のデータとVoLTEのデータが同時に来たら、VoLTEを先に通すという決まりがあります。
VoLTEの技術がなかった3G回線の時代は、データ通信のネットワークと音声通信のネットワークに分かれてやりとりされていました。もっと詳しく言うと、音声は0と1で構成されるデータで音声専用のネットワーク、データは「パケット」と呼ばれるデータでデータ通信専用のネットワークを通っていたということになります。[2]

昔あったLTE回線のことだろうか。調べてみると
>VoLTE(ボルテ）とLTEの違いは「音声通話用の規格かデータ通信用の規格か」です。 VoLTE(ボルテ)は音声通話用、LTEはデータ通信用の規格になります。どちらも、使っている回線自体は変わらず用途が違うだけです。[3]

VoLTEは音声通話では今の5G時代でもスタンダードな規格のようです。現在はVoNR(Voice over New Radio)という新たな規格を実証実験中だとか。
通信回線の規格は以下が参考になりました。
[Wi-Biz通信Vol.62　【ニュース&トピックス】](https://www.wlan-business.org/archives/30234)
上記サイトの図表4を見ると、どの周波数を使用するかをメーカー毎に決めているんですね。全然知らなかった。

## 引用元
1:[au通信障害、原因は通信設備の故障による輻輳　通信規制で対処中【修正あり】](https://www.itmedia.co.jp/news/articles/2207/02/news077.html)
2:[「VoLTE交換機」や「トラヒックの輻輳」の仕組みとは？設備障害は今後も起こる？！](https://teeg.tech/voltekddi/)
3:[VoLTE（ボルテ）とは？意味やLTEの違い・通話方法などをまとめて解説！](https://naruhodo-wifi.com/volte/)

## もう少し具体的な仕組み（追記）
具体的にどういう処理になっているのか、以下のツイートが分かりやすかったです。
https://twitter.com/Tsutomu_eng/status/1543436693558411264
残り何回ペットと遊べるか知っていますか？

## 挨拶

最近は特に**動物が好き**過ぎるようで動物系Youtuberをやたらと漁っています。
好きすぎて日本最大級のペットEXPOに行ったり、
知らない土地に行くと、動物園か水族館どちらかには行ってます。
サファリパークと爬虫類館のためなら100里でも移動します。

### 自己紹介

サーバサイドエンジニア
Rubyと動物と個人開発が好きです
Twitterもフォローください👏
[@1026NT](https://twitter.com/1026NT)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/3db40e7d-3213-be1f-8650-c6ad5dff69c9.jpeg" width="100px">


### 背景

好きなアプリ
僕が好きで覚えている中で最も簡易的で広く知られているアプリです

http://seeyourfolks.com/

#### 機能

- 国を選ぶ
- 親と会う年間回数を入力する
- 母親、父親の年齢を入力する

#### 中身はシンプル

「**あなたが残り何回親を会うことができるか**」を教えてくれます。
数を見ると衝撃的、**親と相当会えてないんだな**って思わせられます。

アプリからのメッセージはこちら
```
死に対する意識を高めることが、人生をより充実させることにつながると考えています。
適切なリマインダーがあれば、大切なことに集中することができ、より良い人間になれるかもしれません。
```

**心打たれるメッセージ**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/5f80d0c1-8748-d59a-9b7d-03859867a7a9.png" width="200px">


### 僕もこんなアプリを作りたい!

https://www.ideee.tech/ideas/1185?utm_source=qiita&utm_medium=article&utm_id=playwithyourbuddy

すぐにアイデアを作成
動物好きの僕からするとペットも大事な存在なのですぐに発想が至りました。

> ちなみにこのアイデアを投稿するアプリも僕が作っています。
> みんなでOSSしたり、アイデアをブラッシュアップする場なのでぜひ使ってみてください🙇‍♂️

### 自分の経験

僕はわんちゃんを飼っていました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/fe71826b-1594-1583-1741-740b1ac2e663.png" width="200px">


小さい頃から一緒に成長してきて家族同然に考えていました。
しかし、中学生の頃体調が急変して亡くなってしまいます。

```
ぼく（中学生）：  そういえば、コロ（犬）とは物心ついた時から一緒にいてもはや家族同然だったな。。。
ぼく（中学生）：  最近は部活で忙しくてあんまり構ってやれなかったな。。
ぼく（中学生）：  こんな事ならもっと散歩してやったり遊んでやれば良かったな。。。

ぼく（現在）：  　あの頃はかなり後悔した記憶があるな。。
ぼく（現在）：  　けど、いま考えると犬の寿命って短いんだから、あの頃はとっくにおじいちゃんになってがんばってくれたんだよな。。😭
```

手遅れになって残ったのは**後悔の念**だけです。
「もっと一緒に遊んであげたかった」そんな**悔しい想いを抱く人を増やさないため**にも。
そして、一緒に遊んで欲しかった**ペットのため**にもこのアプリを作りました。

## 作ったアプリ

https://www.playwithyourbuddy.com/

[![スクリーンショット 2022-07-03 20.49.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498701/db890579-a062-b4da-fa1d-986a4a4f71b3.png)](https://www.playwithyourbuddy.com/)


### 開発背景

**技術：**
`React`
これまで熟練度が高くなく、練習のためにもReactにしました

**API:**
`DOG CEO`
かわいいイッヌの写真を種類別で出してくれます
https://dog.ceo/

**サーバ🐟**
`Vercel`
無料で簡単にデプロイできるから

**期間**
３日間
seeyourfolksみたいに「1日で作ったで〜」って書きたかったけど
慣れないReactで３日かかりました🤢

**なぜイッヌしか選べないのか**
- 原体験がイッヌだった🐶
- ネコはちょうど良いAPIがなかった
    - 日本で１番飼われているのはネコなので次はネコを実装したい
- ネコは室内で飼っていて常に遊んであげているイメージがあるから

## メッセージ

- 少しでも広まってくれることを願います。**ぜひシェア**お願いします🙇‍♂️
- ネコの画像を種類に合わせて出力APIを探しています🐱
  - 日本で１番飼われているのはネコ

### 補足

個人的に良いなと思っているサイト

https://www.pet-home.jp/dogs/

現在、`playwithyourbuddy`のサイト内で勝手におすすめする素敵なサイトを探してます。
ぜひ、社会的にペットに対して優しいサイトがあれば教えてください！
イッヌの平均寿命のデータももっと探してます🙏

参考資料
https://petreien-a.tokyo/dog/
https://www.anicom-sompo.co.jp/news/2016/news_0160531.html
マルチスレッド環境における同期制御

マルチプロセスとは違い、マルチスレッド環境ではメモリ空間を共有している。
そのため、共有リソースに対して適切な同期制御（排他制御？）を行わないと共有リソースに対する更新処理を行う際に、データの不整合が発生する可能性がある。
これらの問題の解決策として以下のような同期制御方法が存在する

## セマフォ
異なるスレッド間で共有される変数などの共有資源に対する 同時アクセス数を制限する機構

大まかにいうと、あるリソースが何個使用可能かを示す数値
あるリソースを占有するさい、セマフォの値を１減算し、リソースの開放を行う際に、セマフォの値を１加算する
セマフォの値が正の数でなければそのリソースを占有することはできない

### カウンティングセマフォ
任意個の資源を扱うセマフォ

- カウンタ値に1加算してから待機中スレッドを起こす［V操作, Up, Signal, Post］
- カウンタ値が0より大きくなるまで待機してからカウンタ値を1減算する［P操作, Down, Wait, Pend］

### バイナリセマフォ
値が0と1に制限されている（ロック/アンロック、使用可能/使用不可の意味がある）セマフォ

バイナリセマフォによって、複数スレッドから共有資源アクセスの相互排他(Mutual Exclusion)制御が実現される

後述するMutexでも実現可能
ただし、Mutexは複数スレッド間の相互排除に特化しているので、Mutexを使うのが好ましい

## Mutex
複数スレッドから共有資源へのアクセス相互排他(MUTual EXclusion)制御を実現する機構
あるタイミングにおいて共有資源へアクセス可能なスレッドがただ1つしか存在しないことを保証する

ミューテックスにより相互排他制御される対象は、共有資源としての変数やデータ構造である
**各スレッド上にて実行されるプログラムのコード区間ではない**
つまり、あるスレッドの中でリソースをロックしつつ、待機状態になった場合、そのスレッドが再び実行状態になりそのリソースに対してロックの解放を行わない限り、ロックされているリソースに対して他のスレッドがアクセスできない状態が続く

### ロック
Mutexでは、ロックされている/ロックされていない の２値状態

- 他スレッドがロック所有権を解放するまで待機し、自スレッドがロック所有権を獲得する［Lock, Acquire］
- 自スレッドが所有中のロックを解放し、同ミューテックスに対して待機中の他スレッドへ通知する［Unlock, Release］

### クリティカルセクション
あるスレッドがミューテックスのロックを所有した状態で実行するコード区間

クリティカルセクションはソースコード上に表現されているコード区間（レキシカル・スコープ）だけでなく、そのスレッドの実行パス上にある全てのコード区間（ダイナミック・スコープ）を指す
あるミューテックスのロックを所有したまま呼び出した関数のコード区間は、関数呼出元で開始したクリティカルセクションに包含される

適切な並列・並行処理設計の下では、クリティカルセクションの範囲を可能な限り狭くすべきであり、ロックを所有したまま何らかの条件が満たされるまでスレッドを待機するといった設計はダメ
この場合後述する条件変数を用いるのがよい

## 条件変数(Condition Value)
「共有資源としてのデータ構造が、特定の状態に変化するまで待機」したい状況がよくある。
例えば複数スレッド間でデータを安全に送受信する有限長のFIFO待ち行列データ構造を考えると、取出側は有効なデータが存在するまで待機、挿入側は空きができるまで待機する必要がある。

これを実現するのが条件変数であり、ミューテックスで保護されるデータ構造が、特定条件を満たすまで効率的に待機する機構 の実装を助ける

- 関連付けられたミューテックスのロックを解放し、条件変数に通知があるまで自スレッドを待機し、再びロック獲得する［Wait］
- 同じ条件変数に対して待機中のスレッド群のうち、ランダムな1スレッドに対して通知する［Notify, Signal］
- 同じ条件変数に対して待機中の全スレッドに対して通知する［NotifyAll, Broadcast］

## セマフォとMutexの違い
セマフォにはそのリソースのロック所有権という概念がない。
一方Mutexにはロック所有権という概念が存在し、ロック解放操作は、ロックを所有しているスレッドでしか行えない

# 参考記事
[マルチスレッド・プログラミングの道具箱](https://zenn.dev/yohhoy/articles/multithreading-toolbox#%F0%9F%94%93%E3%83%9F%E3%83%A5%E3%83%BC%E3%83%86%E3%83%83%E3%82%AF%E3%82%B9(mutex))
エンジニア一年目で辛かったこととその対処法

こんにちは。エンジニア二年目に突入しました。
文系から全くの未経験でWebエンジニアになり、かなり辛いことが多かったので振り返ってみます。
その時に考えていたこととその対処法を載せます。

## （辛かったこと1）実力がなさすぎるため、誰からも求められない

これが一番辛かったです。本当に誰からも話しかけられることなく、仕事がgithub（先輩エンジニア）以外から降ってくることがありませんでした。非常に簡単な修正ならできるものの、それ以外何もできないので当然と言えば当然なのです。
今まで運よく人から何かを頼まれることが多かったため、何も頼まれない状態が辛すぎました。誰かの役に立っている実感もなかったので、自分の存在意義を会社内で感じることはありませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515562/ef1b0817-caa3-618a-572e-07704c81be4c.png)

## （1への対処法）人から求められる実力をつけると決め、現状の実力のなさに悩まない

これしかありませんでした（笑）
**実力がないことが問題なので、実力をつけるしかないんですよね。**
とは言え、すぐに実力が付くわけではないので、ひたすらコーディングして実力を上げて、人から求められる時を待つしかありませんでした。現状の実力のなさに悩まないと書いてはありますが、多少は悩んでいました。
幸い二年目にしていろいろ求められる機会が増えたので良かったです。エンジニアの人数が多いわけではない会社だったことも良い方向に働きましたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515562/e3d5e642-2c69-342c-3f46-23ec8697e2e0.png)



## （辛かったこと2）コードが分からなさすぎて眠くなってしまう

良くないんですけどね。本当に分からないと眠くなっちゃうんですよ。
特にお昼ごろが一番眠かったですね。コーヒーを買って飲んだりしていたのですが、私にはあまり効果はありませんでした。お菓子も食べていたので当然ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515562/85edf922-8ece-f784-37c5-033fd90b45f7.png)

## （2への対処法）先輩へ積極的に質問する・お菓子を食べない

分からない部分はいくら悩んでも分かりません。今になって思いますが、 **めちゃくちゃ悩んでそのまま自己解決したパターンはほとんどありませんでしたね。先輩に聞くことで解決していました。**
先輩に聞くことで眠気もなくなり、問題は解決するので一石二鳥ですね。
あとはお菓子を食べないことです。本当に眠くなります（笑）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515562/95b914dd-35f3-3315-5885-b629b3a90d64.png)

先輩も優しいので子犬のような眼をして行けば答えてくださいます。

## エンジニア一年目のみなさん、頑張ってください

いつか報われます！たぶん...
AWS上にk3sクラスタ(embedded etcd利用)を構築する

初投稿になります。
工場などの現場では、耐久性・冗長性・短いダウンタイムが当然ながら求められます。かねてからこのようなエッジ領域でのk3sの利用に注目しておりましたので、k3sのクラスタを作ってみることにしました。とはいえ、自宅には全くRaspberry Piも何もありませんので、AWS上にEC2のインスタンスを複数用意して、そこにインストールすることとしました。あまりAWSに導入する例を見かけませんね、、、
検索しますと、外部データベースを一つ用意してそれを複数のマスタ(k3sで言うサーバ)が参照する形式の例をよく目にします。しかし、外部データベースそのものが単一障害点になるのではないかと思います。そこで、v1.19.5+k3s1から正式サポートとなったembedded etcdを利用する形式に挑戦してみました。
# 準備
## 用意したインスタンス
**サーバー用×3**
名前：k3s-a,k3s-b,k3s-c
インスタンスタイプ：t3.large
ストレージ：20G
AMI：Debian 11を指定
**エージェント用×1**
名前：k3s-d
インスタンスタイプ：t2.micro
ストレージ：20G
AMI：Debian 11を指定
## 留意事項など
embedded etcdを利用する関係上、サーバノードは奇数必要でお勧めは3台、と書いてあったので3台用意しました。
* エージェント用がたった1台なのは単純にケチっただけです。
* 各インスタンスは、同じサブネットに所属するように設定しておきました。
* セキュリティグループも各インスタンス同じものを設定しておきます。このセキュリティグループは、同じセキュリティグループに所属するインスタンスからは無制限にアクセスできるようにしておく必要があります(これを忘れると嵌る)
* 今回k3sはサービス化せず、コマンドラインから起動させる形にしました。オプション設定さえ理解すれば、サービス化も簡単ではないでしょうか。

# インストール
## サーバ1台目
k3s-aにログインします。
~~~
ssh -i "keyA.pem" admin@ec2-13-208-241-109.ap-northeast-3.compute.amazonaws.com
~~~
※接続先、pemファイル名は要確認。

k3sのバイナリをダウンロードします。アクセス権限の関係で、wgetにsudoを付けないとうまく動きませんでした。ダウンロードしたらchmodで権限を変えておきます。
~~~
#cd /usr/local/bin/
#sudo wget https://github.com/k3s-io/k3s/releases/download/v1.24.2%2Bk3s1/k3s
#chmod 755 ./k3s 
#CD ~
~~~
一台目のサーバを起動します。**`--cluster-init`オプションが大切なようです。**
~~~
#sudo k3s server --cluster-init &
~~~
起動した後、トークン情報を確認します。このトークン情報は、残りのサーバ、エージェントを動かす際に必要です。
~~~
#cat /var/lib/rancher/k3s/server/node-token
K102a80cd736c723e474dd3ef8d6e7574633f94947a3dc3e13fcce8f171974d8ab1::server:SECRET
~~~
もちろんIPアドレス(プライベートIPアドレス)の確認も忘れないようにします。今回は172.31.42.76でした、
## サーバ2台目、3台目
k3s-bにログインします。

サーバ一台目と同じく、バイナリのダウンロードと権限変更を行います、
~~~
#cd /usr/local/bin/
#sudo wget https://github.com/k3s-io/k3s/releases/download/v1.24.2%2Bk3s1/k3s
#chmod 755 ./k3s 
#CD ~
~~~
サーバを起動しますが、コマンドラインで一台目のサーバのIPアドレスとトークンを指定します。
~~~
#sudo k3s server  --server https://172.31.42.76:6443 --token=K102a80cd736c723e474dd3ef8d6e7574633f94947a3dc3e13fcce8f171974d8ab1::server:SECRET &
~~~
三台目も同様にします。いずれかのインスタンスで以下のコマンドを打ってみて、動作を確認しておきます。
~~~
#sudo k3s kubectl get nodes
~~~

## エージェント
エージェントもサーバ二台目、三台目とほぼ同様です。バイナリのダウンロードと権限変更を行い、
~~~
#cd /usr/local/bin/
#sudo wget https://github.com/k3s-io/k3s/releases/download/v1.24.2%2Bk3s1/k3s
#chmod 755 ./k3s 
#CD ~
~~~
エージェントを起動します。コマンドラインで一台目のサーバのIPアドレスとトークンを指定するのも同様です。
~~~
#sudo k3s agent  --server https://172.31.42.76:6443 --token=K102a80cd736c723e474dd3ef8d6e7574633f94947a3dc3e13fcce8f171974d8ab1::server:SECRET &
~~~
改めて各ノードの動作を確認しておきます。
~~~
#sudo k3s kubectl get nodes
~~~
# 終わりに
ここで力尽きました(笑)
次は、
* サービスとして各インスタンスのk3sを動かしてみたいと思います。
* Kubernetesダッシュボードを導入してみたいと思います。
SQLAlchemyにおけるcommitの誤用によるACID特性の破綻例

## 概要
誤ったcommitの使用はトランザクションのACID特性を破綻させます。
ここでは実際に誤ったcommitの使い方によるACID特性の破綻を見ていきます。

## トランザクションのACID特性が破綻する例
```commit -> rollback -> commit```
という動作を行いDBの内容がどうなるのか見ていきましょう。

```python:commit -> rollback -> commit
engine = create_engine("mysql://user:password@db/test_db")
SessionClass = sessionmaker(engine, autoflush=False, autocommit=False)
session = SessionClass()

# commitで更新内容を確定
user = User(user_id="1", name="Johndoe", email="johndoe@example.com")
session.add(user)
session.commit()

# rollbackで更新内容を戻す
session.rollback()

# 再度commitで更新内容を確定
user = User(user_id="1", name="Johndoe", email="johndoe@example.com")
session.add(user)
session.commit()
```

上記のコードを実行すると以下のようなクエリが実行されます。
```sql
INSERT INTO user (id, name, email) VALUES ('1', 'Johndoe', 'johndoe@example.com')
COMMIT
ROLLBACK
INSERT INTO user (id, name, email) VALUES ('1', 'Johndoe', 'johndoe@example.com')
ROLLBACK
```
末尾のROLLBACKは直前のINSERTが失敗したことに対しての後処理としてシステムから呼ばれています。

また、pythonの実行ターミナルでは以下のエラーが発生します。
```python
sqlalchemy.exc.IntegrityError: (MySQLdb.IntegrityError) (1062, "Duplicate entry '1' for key 'user.PRIMARY'")
```

1回目のcommitによりrollback不可な更新内容の確定が行われたため、
Primaryキーが同値のレコードをinsertするとエラーが発生します。

***

念の為にデータ更新ごとにcommitを行うという設計を行うと、
rollbackが出来なくなりACID特性を破綻させるという結果を招いてしまいます。

commitの使い方に関しては下記リンクを参照してみてください
[SQLAlchemy flushとcommitの使い方](https://qiita.com/GuriTech/items/9196bae972655d36ee21)
Djangoの導入からサーバー起動

# Djangoの導入からサーバー起動

### プロジェクトの開始
任意の場所にプロジェクトを作成する。
```python:
C:\work> django-admin startproject settings
```

### アプリの追加
作成するアプリを追加する
```python:
C:\work\プロジェクト名> django-admin startapp "アプリ名"
```
 
### 仮想環境の作成
仮想環境を作成
今回は「venv」という名前の仮想環境を作成する
```python:
C:\work\プロジェクト名> python -m venv venv
```

### 仮想環境に入る
```python:
プロジェクト名> .\venv\Scripts\activate
```


### Djangoのインストール
```python:
(venv)プロジェクト名> pip install --upgrade pip
(venv)プロジェクト名> pip install django
```

### サーバーを起動する
```python:
(venv)プロジェクト名> python manage.py runserver

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

July 03, 2022 - 20:51:51
Django version 4.0.5, using settings 'settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
```

`http://127.0.0.1:8000/`にアクセスし下記の画面が表示されれば成功している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1381697/2082a009-1edb-4177-df1f-6a497fafe295.png)
win + Rでタスクバーからのアプリ起動を卒業

## 背景
プログラミングをする際にVScodeやPostmanなどのアプリを開く機会が多いので、よく使うアプリをタスクバーに張り付けていました。でも、結局目的のアプリを起動させるためにはマウスでクリックしなきゃダメなんですよね…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/25099de4-9f0d-5149-6beb-e0fa3088fa90.png)
また、私の場合、言語ごとにフォルダを作るので、目的のフォルダを開くためにエクスプローラーも頻繁に開く機会がおおいです。

これ面倒くさいな～って思ってたので、マウスを使わずに楽にアプリを起動させ、タスクバーを卒業しようと決めました。

## 手順
1. 任意のフォルダを作る(今回はCドライブ直下にmypathというフォルダを作りました)
1. 作成したフォルダにPathを通す
1. 頻度の高いアプリ・フォルダのショートカットを配置
1. 自分が使いやすいようにショートカットの名前を変更

#### 1.任意のフォルダを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/0119d3dd-3ab8-572a-31cb-bea53f884dbf.png)

#### 2.作成したフォルダにPathを通す
検索ボックスに「環境変数を編集」と入力すると「環境変数を編集」と出るので、クリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/7fc5de6d-e3bc-0daf-673a-6d963fcae853.png)
クリックすると↓のようなウィンドウが立ち上がるので「Path」を選択して編集を押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/54174108-451e-86df-88ac-32a6ac583c5d.png)
すると、環境変数の一覧が出るので先ほど作成したフォルダの場所を追加します（今回はCドライブに追加したので「C:\mypath」となっています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/ad2ac52b-f86b-ba48-64d6-aaa1758fdeac.png)

#### 3.頻度の高いアプリ・フォルダのショートカットを配置
作成したフォルダにショートカットを配置します
アプリケーションだけでなく、使用頻度の高いフォルダのショートカットも追加します
> ショートカットは対象のフォルダを選択右クリックで「ショートカットを作成」からできます



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/90103e4e-8be7-e44a-7bbe-cba8869af562.png)

#### 4.自分が使いやすいようにショートカットの名前を変更
「win + R」でファイル名を入力し実行するので、簡単な名前に変更します
***

> デフォルトでは↓のようにショートカットが割り当てられていますが、使いづらいのでメモ帳やパワーポイントなどの独自のショートカットを割り当てます

デフォルトで用意されているショートカットの一例

| 起動するプログラム | 入力するコマンド |
|:-:|:-:|
| 電卓  | calc  |
|  コマンドプロンプト     |  cmd     |
|  Cドライブ     |    C:¥   |
|  メモ帳     |  notepad     |
|  エクセル     |    excel   |
|  パワーポイント     |  powerpnt     |

などなど
***
私はcドライブやパワポ、ワードなどのショートカットが使いづらいと感じたのでカスタマイズしてみました！
```
Cドライブ　　C:¥　    → c
パワポ　　　powerpnt　→ pp
ワード　　　winword  → word
メモ帳　　　notepad  → memo
```
         

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/977422/bc9fb077-9f4c-d180-c771-74dd7d31252a.png)

以上で作業は終わりです
「win + R 」で独自のショートカットを割り当てることでタスクバーを卒業への一歩となったのではないでしょうか…






## 今後
今回はpathを使ってアプリの起動を効率化していました。
今後はこのような処理をまとめたbatを作ってより効率化していこうと思います
単純に英語だけのwordpressページを作りたいだけなんですけど・・・

# 問題点

「多言語化」とか、「英語サイトも作って日本語サイトと相互に切り替える」とかではなくて・・・

単純に、
こういうところ↓を、英語にしたかったんですよ。
![スクリーンショット 2022-07-03 165410.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111408/51fa6eeb-23ac-fa8e-2254-2c046a664c55.jpeg)

「設定」＞「一般」のここ↓を
![スクリーンショット 2022-07-03 203331.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111408/60f2af2d-7b7b-0840-daa2-093ece9dab39.jpeg)
こう変えても、

ユーザーの「プロフィール」のここを
![スクリーンショット 2022-07-03 203421.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111408/1bdb5a74-c671-5f85-6948-5e4cb61f446b.jpeg)
こう変えてもダメだったので。

# 解決
シンプルに
https://wordpress.org/download/
からダウンロードした英語版を入れるのが一番早かったですね。
【PHP初級㉑】論理演算子1　～AかつB～

［問題］　　(参照：http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksPrimary.html)
整数値を入力させ、その値が5よりも大きく、かつ、20よりも小さければOKと表示するプログラムを作成しなさい。

# コード
```php
$a = intval(fgets(STDIN));
if($a > 5 && $a < 20){
    echo 'OK';
}
```


↓「10」と入力


# 結果
```
OK
```


☆論理演算子
＄a == ＄b && ＄c == ＄d 　→　  ＄a=＄bかつ＄c=＄d
※&&はandでも可
React18のSuspense機能を試してみる

久々の投稿で小ネタを。

React18ではSuspense機能によりコンポーネントのレンダリングに中断が行えるようになりました。
それにより、コンポーネント自体を非同期でレンダリングできるようになりました。

実際に使ってみました。

## 成果物
![Jul-03-2022 20-14-22.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651103/44141d0b-3345-6a9b-a82a-cfe7aba1da60.gif)

ソースコード：https://codesandbox.io/embed/react-suspense-sample-jw80ks?fontsize=14&hidenavigation=1&theme=dark

読み込み中はスピンスピンをスピンさせています🌀
非同期用のコンポーネントにはダミーのJSONのAPIを叩くコンポーネントを用意しました。

```App.js
import "./styles.css";
import React from 'react';
import Spinner from './Components/Spinner';
const OtherComponent = React.lazy(() => import('./Components/OtherComponent'));

export default function App() {
  return (
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

```
React.Suspenseコンポーネントを呼び出しています。
fallbackはロード中に表示させるコンポーネントです。

React.Suspenseコンポーネントタグの中に<OtherComponent />を呼び出しており、<OtherComponent />はダミーのJSONのAPIを叩くコンポーネントです。


const OtherComponent = React.lazy(() => import('./Components/OtherComponent'));

といった形でReact.lazyで読み込んでいます。


## ダミーのJSONのAPIを叩くコンポーネントの中身

```OtherComponent.jsx
import useSWR from "swr";
const fetcher = () =>
  fetch("https://dummyjson.com/products/1").then((res) => res.json());

const OtherComponent = () => {
  const { data } = useSWR("https://dummyjson.com/products/1", fetcher);

  return (
    <div>
      <h1>useSWRを使ったコンポーネントResult</h1>
      <ul>
        {data &&
          Object.entries(data).map(([key, val], index) => {
            return (
              <li key={index}>
                {key}: {val}
              </li>
            );
          })}
      </ul>
    </div>
  );
};

export default OtherComponent;

```
先の React.Suspense の中身に対して useSWR をかませてデータをフェッチしてあげることで非同期でコンポーネントの読み込みが実現できます。

コンポーネントをフォールバックと切り離せ、従来なら必要だった同一コンポーネント内での条件分岐的なJSXも記述しなくて良いのでスッキリ書けました。
freezedを用いてjsonファイルを読み込む

# 概要
flutterにおいて、immutableなクラスを生成したいという事がよくある。この際に有効な方法がfreezedパッケージを用いることである。
> https://pub.dev/packages/freezed

このパッケージで生成したimmutableなクラスに対して、ローカル（assetsディレクトリなど）に保存されているjsonファイルを読み込ませる手順を示す。実際には、APIやfirebaseから取得したjsonデータに対して用いることが多いが、今回はテスト用のローカルファイルを読み込むことにした。

# 手順
1. freezedパッケージをインストール
2. freezedクラスを作成
3. コード生成を行う
4. assetsフォルダにテスト用jsonファイルを作成
5. jsonファイルを読み込む

## freezedパッケージをインストール
次のコードを順に実行し、パッケージをインストール
```
flutter pub add freezed_annotation
flutter pub add build_runner --dev
flutter pub add freezed --dev
flutter pub add json_serializable --dev
flutter pub add json_annotation
```
## freezedクラスを作成
次のテンプレートを適宜変更する。
```dart:user.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const User._();
  const factory User({
    required String name,
  }) = _User;

  factory User.fromJson(Map<String, dynamic> json) =>
      _$UserFromJson(json);
}
```
## コード生成を行う
次のコードを実行すする。
```
flutter pub run build_runner watch
```
build_runnerを用いてコード生成を行うコードである。ただし「watch」を付けることによって変更保存時に自動でコード生成をし直すことができる。

## assetsフォルダにテスト用jsonファイルを作成
project直下にassetsフォルダを配置し、json -> test_user.jsonを作成する。
```json:test_user.json
{
  "name":"my_name"
}
```
## jsonファイルを読み込む
任意の場所で先程作成したクラスをインスタンス化する。また、ローカルにあるjsonファイルからデータを読み出し、引数に渡す。
```dart
  loadFile() async {
    var text = await rootBundle.loadString('assets/json/test_user.json');
    User testUser = User.fromJson(json.decode(text));
    print(testUser.name); // 確認用に表示
  }
```
jsonファイルがリスト形式の場合は以下のように修正する。
```dart
  loadFile() async {
    var jsonData = json.decode(await rootBundle.loadString('assets/json/test_user.json'));
    List<User> testUser =
      jsonData.map((data) => User.fromJson(data)).toList();
    print(testUser[0].name); // 確認用に表示
  }
```
# まとめ
freezedを使えばimmutableのクラスを定義することが可能なため便利である。自分はhook_riverpodsと組み合わせて状態管理を行っている。このような状態管理方法は現在主流な状態管理方法の一つであると考えている。

# 参考資料
https://pub.dev/packages/freezed

https://zenn.dev/sakusin/articles/b19e9a2c3829e0

https://qiita.com/unsoluble_sugar/items/3e0bb6760eb572bc9253
松山市の石手川ダム貯水率の変化（年間）のCSVから個々の貯水率と比較グラフ作成

https://www.matsuyama-waterworks.jp/water/graph1.html

```python
import pandas as pd

url = "https://www.matsuyama-waterworks.jp/water/data/data.csv"

df0 = pd.read_csv(
    url,
    encoding="cp932",
    header=None,
    index_col=[0, 1],
)

df0

df0.iloc[1] = df0.iloc[1].replace({"平成6年度": 1994, "令和3年度": 2021, "令和4年度": 2022})
col = df0.iloc[:2].fillna(method="ffill", axis=1).values
df0.columns = pd.MultiIndex.from_arrays(col)
df0.index.names = ["month", "day"]

df1 = df0.iloc[2:].copy()
df1

# 貯水率

df2 = df1.loc[:, "石手川ダム貯水率[%]"].astype(float)
df2.columns.name = "year"
df2["date"] = df2.index.map(lambda x: "{0[0]:02}/{0[1]:02}".format(list(map(int, x))))

df2
```
```python
import plotly.express as px

fig_wsr = px.line(df2, x="date", y=[1994, 2021, 2022], width=1200, height=500)
fig_wsr.show()

fig_wsr.write_image("dam.png")
```
![newplot(16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36151/19a81577-ca1f-3dea-6915-b7ad4b1b8f20.png)
【やってみた】初期状態のAWSアカウントのSecurity Hubスコアはなんと！！

新規作成したアカウントのSecurity Hubのスコアがいくつか見てみようと思います。

# AWSアカウントの新規作成

AWSアカウントの新規作成は、Organizationを使って作成しました。

# Security Hub有効化手順

## Configの有効化

Security Hubを使用するためにはConfigを有効化する必要があります。

1. Configの管理画面を開き、1-Clickセットアップをクリック
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/7a1b7ea5-dc74-c5fb-b34f-b68e3f7a7345.png)

1. 確認をクリック
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/3d691d59-f071-1b78-a3ee-d4b0c70a25de.png)

1. 有効化されました。
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/ec3c5ce2-6b41-e6ae-9392-dcc91f00c4a6.png)

## Security Hubの有効化

続いてSecurity Hubを有効化します。

1. Security Hubの管理画面を開き、Security Hubに移動をクリック
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/5a9f556e-9fa8-6597-49e3-752953f232b1.png)

1. セキュリティ基準は以下の3つから選択ができますが、デフォルトで選択されている「AWS 基礎セキュリティのベストプラクティス v1.0.0 を有効化」と「CIS AWS Foundations Benchmark v1.2.0 を有効化」を選択した状態で、Security Hubの有効化をクリック
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/2fb43d9b-5479-e6f1-98a5-4aeb13d6874c.png)

1. Security Hubが有効化されました。結果が表示されるまでは暫く掛かるようです。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/9d2261f3-9477-77dd-a1e1-3054376e067b.png)

# 結果確認

さて、1日経ったので、状態を確認してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/39478784-fdce-d54b-0f5d-e5282d0d1d45.png)

ということで、正解は **75%** でした！！！

意外と高いと感じませんか？これより低い場合は初期状態より悪くしているということになりますね。。。

---

# セキュリティスコア100%を目指した記事をこちらに掲載しました。

よろしければご参照ください。

[初期AWSアカウントのSecurity Hub結果とAWS 基礎セキュリティのベストプラクティスへの対処法
](https://moritalous.pages.dev/ca38862c7b86acab0f36)

[Security HubのCIS AWS Foundations Benchmarkへの対応を行いセキュリティスコア100%を達成する方法
](https://moritalous.pages.dev/0d89a2edfb984364411d)
RaspberryPiOSをインストールしたDockerコンテナでSambaを構築する

# やりたいこと

RaspberryPi OSをインストールしたDockerコンテナを用意して、sambaをインストールしてWindows用共有ディレクトリとTimemachine用共有ディレクトリを作る。


# 手順

### 1.RaspberryPi OSをインストールした

https://qiita.com/ryot0/items/3b40a0e5f227d97b7d3b


### 2.環境構築用のコンテナを準備する

```shell
docker create -it --name buildcont01 raspios:0.0.1 /bin/bash
docker start buildcont01
docker attach buildcont01
```


### 3.attachしたコンテナ内で諸々最新化する

```shell
apt update
apt upgrade
apt autoremove
apt clean
```


### 4.attachしたコンテナ内でsambaをインストールする

```shell
apt install samba
```


### 5.attachしたコンテナ内でsamba共有用のディレクトリを作る

```shell
mkdir /data
mkdir /data/share
mkdir /data/timemachine
```


### 6.attachしたコンテナ内でsambaの設定

```text:/etc/samba/smb.conf
[global]

   vfs objects = catia fruit streams_xattr
   fruit:metadata = stream
   fruit:encoding = native

   workgroup = WORKGROUP
   dos charset = CP932
   unix charset = UTF-8 
   server string = raspberry pi samba
   netbios name = RaspberryPiNetBiosName

   unix password sync = no
   security = user
   passdb backend = tdbsam 
#   passwd program = /usr/bin/passwd %u
#   passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
#   pam password change = yes

   map to guest = never 

   usershare allow guests = no 

   load printers = no 

#### [homes]セクションをすべて削除

#### [printters]セクションをすべて削除

#### [print$]セクションをすべてコメントアウト

[timemachine]
   path = /data/timemachine/root
   browsable = yes
   writable = yes
   fruit:time machine = yes
   fruit:time machine max size = 2G

[share]
   path = /data/share/root
   browsable = yes
   writable = yes
```

### 7.attachしたコンテナ内で設定が間違っていないことを確認

```shell
testparm
/sbin/smbd --foreground --no-process-group
```

これでエラーが出ないことを確認する。
エラーがなければ、一旦attachしたコンテナをexitする。


### 8.コンテナをimageとして保存する

```shell
docker commit buildcont01 raspios_samba:0.0.1
docker rm buildcont01
```


### 9.上で保存したimageからコンテナを作って起動する

```shell
docker create -t --name sambacont01  -v /data/share/main:/data/share -v /data/timemachine/main:/data/timemachine -p 139:139 -p 445:445 -e LANG=C.UTF-8 -e TZ=Asia/Tokyo raspios_samba:0.0.1 /sbin/smbd --foreground --no-process-group
docker start sambacont01
```

ちゃんと起動しているか確認

```shell
docker exec -it sambacont01 /bin/bash
ps aux
```


### 10.上でコンテナでログインした状態でsamba用のユーザを設定

```shell
pdbedit -a pi
pdbedit -L
```
初心者　MySQL8に挑戦する 1

# 環境設定で躓いた2点

 使用機種は　MacBookAir Monterey12 IntelCore15

## その一

　MySQL Community Server 8.0.29でパッケージを選ぶとき、DMGとTARではDMGを選ぶとわかっていたけれど、DMGがさらにARMとx86に分かれていて、ちょっと焦った。

### 結論　ARMはM1Mac用だそうです。ということで私はx86

## その二

　DMGのinstall wizardに頼り切ってほいほい進んでいたら、パスワードを拒否られて焦る。

　公式チュートリアルにはこう書いてある。

- shell> mysql -h host -u user -p

　そもそもhostってなんだ、と思ってもう少し先を見ると、自分のマシンがホストなら

- shell> mysql -u user -p

 悲しき初心者はここで　shell> から打ってはじかれる。そうか、要らないのか。私の場合は、

- % mysql -u user -p
- Enter password: ********

　するとAccess denied for user 'user'@'localhost'と言われる。そうか、userのところを自分に変えなければ､と思って、

- % mysql -u dongri727 -p
- Enter password: ********
 
 でも相変わらずAccess denied for user 'dongri727'@'localhost'と言われる。もしやPasswordの設定で綴り間違えたか、パスワードを変更するとか、どうやるんだ、とパニクる。パスワードの再設定とかいろいろ記事を読んでも、そもそも起動さえしてないんだから、再設定どころの話ではない。そんなときふと、こういう表記に目がとまった。

### 結論

- % mysql -u root -p
- Enter password: ********

　これで解決。おめでとう、私。

https://qiita.com/dongri727/items/86c37ef4053d7ef9c62f
Linuxのnamespace関係で必要なコマンド

# 背景
docker,k8sの勉強をしていてネットワーク関係が分からなかったので
コンテナ関係なくLinuxでnamespaceを作成してネットワークの勉強していました。
その際に必要だったコマンドをまとめました。

# Linuxコマンド
・ネームスペース追加
sudo ip netns add [ネームスペース名]

・ネームスペース確認
sudo ip netns l

・ネームスペース内に入る
sudo ip netns exec [ネームスペース名] bash

・ネットワークインターフェイスの状態を立ち上げる
sudo ip link set [ネットワークインターフェース名] up
（ネームスペース内のループバックインターフェースloはnamespaceを作成した時点ではdownの状態）

・仮想インターフェースを作成
sudo ip link add name [インターフェイス名] type veth

・仮想インターフェースをネームスペースに紐づける
sudo ip link set [インターフェイス名] netns [ネームスペース名]

・インターフェースにipを与える
sudo ip addr add [IPアドレス] dev [インターフェイス名]

# 参考
https://christina04.hatenablog.com/entry/network-namespace-with-bridge
上司や同僚にかけてもらって嬉しかった言葉をみんな聞いてくれ

# はじめに
現在リモートワークを中心に働いております。問題があったときは1on1やMtgでお話するのですが、それに比べて感謝の気持ちってあえて伝える機会が少ない気がします。

チームマネジメントと呼ぶにはおこがましい記事かもしれませんが、感謝とともに、もらった言葉が繋がっていきますようにという願いを込めて、この記事を書きます。


## ・わからないことがあって連絡すると、まず「連絡ありがとう」

こんな些細なことで？とか、きっと相手も忙しいはずなのに・・・とか連絡する前は悩んでしまったりします。そんなときに「連絡してくれてありがとう」と言葉をかけていただいて、とても安心しました。相談しやすかったです。優しい言葉をありがとうございました。

## ・作った資料に対して「前より〇〇が良くなりましたね」
牛歩ながら少しずつ、指摘をもらった点は改善して資料に反映するように心がけています。
作った資料を見ていただく度にこの言葉をいただきました。

苦労して考えた点に気づいてもらえたこと、それに対するフィードバックをいただいて、報われたような気がして嬉しかったです。

## ・「こうするともっとよくなると思う」というフィードバック
併せて、何か指摘事項があるときにこの言葉をいただきました。内心どきどきして資料を見せるのですが、よし頑張るぞ！と思えました。心が折れなかったのはこの上下セットのおかげです。ありがとうございました。

## ・頑張って書いたQiitaの記事に「よかったよ」
最初にAWSのクラウドプラクティショナーの記事を書きました。
実は下書きの時点で８ページもある超大作だったのですが、そんなの誰も読みたくないだろ！と思い直し、かなり量を減らしました。内容を削った分わかりづらくなっていないか、そもそも面白くないのでは？と悩んでいましたが、この言葉をもらって勇気がでました。ありがとうございました。

## ・引き受けた仕事に対して「対応してくれてありがとう」
うっかりやると言ったものの、ちょっと大変だった仕事がありました。この言葉をもらって、チャレンジしてよかったと思えました。この先も頑張ろうと思えました。ありがとうございました。

## ・相談すると時間を作ってアドバイスをくれる　＆　自分にない新しい視点を教えてもらえる
かけてもらった言葉という括りからは少し外れてしまうのですが。
私は心配性なので、常にいろんなことに悩んでいます。チャットに書く文章が長すぎるのでは？とか。

一人で考えてパンクしかかったときは助けを求めるのですが、いつも丁寧に話を聞いてくださり、私の中になかった視点からアドバイスをいただけています。
こんなことでも聞いてもらえてたという安心感、「そう考えればよかったのか！」という衝撃と、いつも学びが多いです。ありがとうございます。

# おわりに
何気ない言葉に見えても、言葉をかけてくれた人の気遣いだったり、優しさがベースにあるからこその言葉で、それは決して当たり前のことではないと思っています。

優しさを返していけるように、もらったものに気づける人になりたいなと思います。
最後まで読んでくださって、ありがとうございました。
OpenShift 4.10をPower Systems Virtual Serverにデプロイする（概要編）

# はじめに

OpenShift(OCP)をPower Systems Virtual Server (以降PowerVS)にデプロイする、という記事はこれまでいくつか投稿があり、非常に参考にさせていただいてます。ただ、OpenShiftやPowerVSの進化が早く、必ずしも現状について行けていない点があることに気づきました。そこで、本記事（および[「詳細編」]）では、最新のOCP 4.10を、2022年7月1日現在のPowerVS(東京/大阪リージョン)にデプロイする方法を紹介したいと思います。
本記事は、以下のページを参考にしています。

[「詳細編」]: https://qiita.com/hiroyuki_z_tanaka/items/0fc8ac5dd30cff4cc342

Installing Red Hat OpenShift Container Platform 4.x on IBM Power Systems Virtual Servers
https://developer.ibm.com/tutorials/install-ocp-on-power-vs/

Install OpenShift on PowerVS
https://github.com/ocp-power-automation/openshift-install-power

# 手順概要

OCPをPowerVSに導入する手順は、基本的に上記の"Installing Red Hat OpenShift Container Platform 4.x on IBM Power Systems Virtual Servers"の記事に従います。

手順：

1. OCP導入のためのPowerVSの準備
2. RHELとRHCOSのOVAイメージを作成して、PowerVSに登録
3. OCPをPowerVSへ展開

ただし、わたしが試したときは、「2. RHELとRHCOSのOVAイメージを作成して、PowerVSに登録」の部分について、以下の手順を変更しました。

**RHEL 8.xのイメージは、OSAとTOKでは既に準備されているので作成不要**

以前はPowerVSではRHEL 8.xのイメージは提供されていなかったのですが、現在は提供されています。OCPのデプロイ手順では、提供済みのイメージを使うことも可能です。ライセンス的に問題なければ、PowerVS提供のイメージを利用すると手間を少し減らすことができます。
なお、RHCOSのイメージはPowerVSでは提供されていないので、予め作成してインポートしておく必要があります。

**RHCOSのイメージとして4.10を使う**

OCP 4.10を導入するので、RHCOSのイメージも4.10.xを使いました。

rhcos-4.10.16-ppc64le-openstack.ppc64le.qcow2.gz
https://mirror.openshift.com/pub/openshift-v4/ppc64le/dependencies/rhcos/latest/rhcos-4.10.16-ppc64le-openstack.ppc64le.qcow2.gz

**OVAをPowerVSへインポートするとき、Webコンソールを使う**

上記のチュートリアルでは、以下のCLIを使ってICOSへアップロードしたRHCOSのOVAをPowerVSへインポートすることになっています。

~~~shell
export IBMCLOUD_API_KEY=<IBM_CLOUD_API_KEY>
pvsadm image import –pvs-instance-name <instance-name> --bucket <bucket-name> --object <object-name> --pvs-image-name <image-name> --bucket-region <region>
~~~

ただ、わたしが試した限りでは「rhcosのディストリビューションはサポートされていないよ」というエラーになってしまいました。
そこで、PowerVSのGUIで試したところ、うまくインポートすることができました。ただし、GUIでインポートを実行してから、実際にインポートが完了するまで１時間くらいかかります。その間、画面上にプログレス表示が無いので不安になります。が、インポートをキックして、しばーらくしてからリロードするとインポートが完了していました。

# 詳細編へ続く

ここまでが、OCP 4.10をPowerVSへ導入するときに参考資料と手順が異なった部分の概要です。
実際に導入したときの詳細手順や、トラブルについては[「詳細編」]でご紹介したいと思います。
EditTextで範囲選択している文字をドラッグで位置を変更させることを無効化させる方法

今回はEditTextで色々制御をしていて、範囲選択している文字をドラッグで位置を変更させることを、無効にしたかったことがあったので残しておこうと思います。


# OnDragListener
```MyDragListener.kt
class MyDragListener : View.OnDragListener {
    override fun onDrag(v: View?, event: DragEvent?): Boolean {
        return true
    }
}
```
View.OnDragListenerを継承したクラスを作成します。
こちらをreturn trueすることでドラッグ操作を無効化いたします。

ただし、範囲選択の範囲位置を調整するドラッグ操作は無効になりません。


あとは作成たクラスをEditTextに設定します。

```MainActivity.kt
binding.editText.setOnDragListener(MyDragListener())
```

これで終了です。
Elasticsearchで見る検索エンジンの仕組み(3): インデックス/トークナイズ編

##### [前回] [Elasticsearchで見る検索エンジンの仕組み(2): Kibanaインストール編](https://qiita.com/mingchun_zhao/items/7e2be29496e26fef86c8)

## はじめに

前回は、Kibanaをインストールし、クエリ実行してみました。
今回は、全文検索のインデックスとトークナイズを理解します。

## 全文検索(Full text search)とは

- 複数の文書(ファイル)から特定の文字列を検索すること
- `複数文書にまたがって`、`全文を対象とした`検索
    - `ファイル名検索`や`単一ファイル内の文字列検索`と異なる

## インデックス(Index、索引)とは

- 高速な検索を可能にするため、検索対象文書から作成した索引データ
    - 書籍索引同様、特定単語がどのページで出現したか素早く参照できる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/bf0b7134-4518-aeaf-1d0e-f315536ec001.png)
    ※ 引用元: https://ja.wikipedia.org/wiki/%E7%B4%A2%E5%BC%95

- インデクシング(Indexing)とは、事前に索引データを作成すること
    - インデクシングにより生成されるデータをインデックス(Index)と呼ぶ

- 転置インデックスの例

|単語|単語が含まれた文書ID|
|---|---|
|全文|2, 6, 7|
|検索|1, 3|
|技術|4, 6|

- grep型検索 VS. index型検索
    - 検索対象の文書数が膨大な場合
        - grep型検索は、逐次文字列検索するため時間がかかる
        - index型検索は、インデックスを用いて、文字列を高速に検索可能

## トークナイズ(単語分割)

日本語文章は単語境界を表すスペースが存在せず、
インデックス作成のため、単語分解の処理が必要。

- 方法1: 形態素解析
    - 解析用の辞書を使用し、検索対象文書を単語分解
    - 形態素解析は`単語分割`と単語の`品詞付け`の2つの処理から成り立つ
    - 例、`全文検索技術`を形態素に分解
        - `全文`(名詞)、`検索`(名詞)、`技術`(名詞)
    - 形態素解析で作成したインデックスは、検索結果が辞書品質の影響を受ける(辞書に未登録の単語が存在するなど)

- 方法2: N-Gram(Nグラム)
    - 検索対象文書を文字単位で分解し、後続`N-1`文字を含めた状態で分割
    - `N`の値が
        - 1なら`ユニグラム`(uni-gram)
        - 2なら`バイグラム`(bi-gram)
        - 3なら`トライグラム`(tri-gram)
    - 例、`全文検索技術`を2文字ずつ分割
        - `全文` `文検` `検索` `索技` `技術` `術(終端)`
    - N-Gramで作成したインデックスは、検索漏れが生じず、辞書も不要
    - 意図したものと異なる検索結果(ノイズ)が発生する可能性あり
        - `京都`で検索すると`東京都庁`がヒット
    - インデックスのサイズが肥大化

- 形態素解析とN-gramの比較

||形態素解析|N-gram|
|---|---|---|
|検索漏れ|多い|少ない|
|検索ノイズ|少ない|多い|
|インデクシング速度|遅い|速い|
|検索速度|速い|遅い|
|言語依存|辞書必要|辞書不要|
|インデックスサイズ|小さい|大きい|

## おわりに

全文検索のインデックスとトークナイズを理解しました。
次回も続きます。お楽しみに。

##### [次回] [Elasticsearchで見る検索エンジンの仕組み(4): サンプルデータでクエリ編](https://qiita.com/mingchun_zhao/items/29d4e497ecfc1d2f016a)