OmniAICreator/Qiita-1.07M huggingface dataset:
vagrant up でエラー

#症状
以下のエラーを吐く

```
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos6'...
Progress: 90%There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["import", "/path/.vagrant.d/boxes/centos6/0/virtualbox/box.ovf", "--vsys", "0", "--vmname", "centos65-x86_64_1588595215899_51257", "--vsys", "0", "--unit", "9", "--disk", "/path/VirtualBox VMs/centos65-x86_64_1588595215899_51257/box-disk1.vmdk"]

Stderr: 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interpreting /Users/Nozomi/.vagrant.d/boxes/centos6/0/virtualbox/box.ovf...
OK.
0%...
Progress state: NS_ERROR_INVALID_ARG
VBoxManage: error: Appliance import failed
VBoxManage: error: Code NS_ERROR_INVALID_ARG (0x80070057) - Invalid argument value (extended info not available)
VBoxManage: error: Context: "RTEXITCODE handleImportAppliance(HandlerArg *)" at line 1118 of file VBoxManageAppliance.cpp
```

#原因
Virtual Boxの参照フォルダが間違っていました。
PCを買い替えた際にユーザー名を変更しており、設定を引き継いだVirtual Boxが原因でした。

#対処法
設定からMachine Folderを変更する。
<img width="553" alt="Screen Shot 2020-05-04 at 21.37.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248276/87b80f61-5ac5-5527-1ef8-777198232155.png">

##感想
そのくらい自動でやってくれても.....
初 LAPACK！で DGELS (QR 分解もしくは LQ 分解)による最小二乗法を実装してみた

# LAPACK インストール

## HomeBrew (macOS)

```bash
$ brew install lapack
```

そのあと，次の環境変数にそれぞれ追加します。

```bash
CFLAGS = $CFLAGS -I/usr/local/opt/lapack/include
CPPFLAGS = $CPPFLAGS -I/usr/local/opt/lapack/include
LDFLAGS = $LDFLAGS -L/usr/local/opt/lapack/lib
```

## apt (Ubuntu)

```bash
$ apt install liblapack-dev
```

環境変数はメモし忘れました。

# 最小二乗法プログラム

```c:lsm.c
#include <stdlib.h>
#include <stdio.h>
#ifdef __linux__
  #include <lapacke.h>
#else
  #include <lapack.h>
#endif

void dgels(char *trans, 
  lapack_int *m, lapack_int *n, lapack_int *nrhs,
  double *a, lapack_int *lda,
  double *b, lapack_int *ldb,
  double *work, lapack_int *lwork,
  lapack_int *info )
{
  LAPACK_dgels(trans, m, n, nrhs, a, lda, b, ldb, work, lwork, info);
}

extern void print_matrix(char *description, int m, int n, double *a, int lda);

int max(const int m, const int n)
{
  if (m > n) {
    return m;
  } else {
    return n;
  }
}

int min(const int m, const int n)
{
  if (m < n) {
    return m;
  } else {
    return n;
  }
}

int main() {
  char *trans = "No transpose";
  int m = 5;
  int n = 2;
  int nrhs = 1;

  int lda = max(1, m);
  int ldb = max(max(1, m), n);
  int lwork = max(1, min(m, n) + max(min(m, n), nrhs));
  int info;

  // double work[max(1, lwork)];
  double *work;
  work = (double *)malloc(sizeof(double) * max(1, lwork));

  // double a[m * n];
  double *a;
  a = (double *)malloc(sizeof(double) * m * n);

  // double b[m];
  double *b;
  b = (double *)malloc(sizeof(double) * m);

  a[0] = 1;
  a[1] = 1;
  a[2] = 1;
  a[3] = 1;
  a[4] = 1;

  a[5] = 50.0;
  a[6] = 60.0;
  a[7] = 70.0;
  a[8] = 80.0;
  a[9] = 90.0;

  b[0] = 40.0;
  b[1] = 70.0;
  b[2] = 90.0;
  b[3] = 60.0;
  b[4] = 100.0;

  print_matrix("a" , m, n, a, lda);
  print_matrix("b" , m, 1, b, ldb);

  dgels( "No transpose", &m, &n, &nrhs, 
    a, &lda, b, &ldb, work, &lwork,
    &info );

  if(info > 0) {
    /*
     * a の三角因子の info で示される対角要素が 0 であるため，
     * a は最大階数を持たない。
     * すなわち最小二乗法は計算できない。
     */
    exit(1);
  }

  // print_matrix("a" , m, n, a, lda);
  print_matrix("the least squares", n, nrhs, b, ldb);

  return 0;
}

void print_matrix(char* description, int m, int n, double* a, int lda)
{
  int i, j;
  printf("\n %s\n", description);
  for(i = 0; i < m; i++) {
    for(j = 0; j < n; j++) {
      printf(" %6.2f", a[i + j * lda]);
    }
    printf("\n");
  }
}
```

# コンパイル方法

```bash
$ cc $CFLAGS lsm.c -o lsm $LDFLAGS -llapack
```

# 実行方法

```bash
$ ./lsm
```

# 実行結果

```

 a
   1.00  50.00
   1.00  60.00
   1.00  70.00
   1.00  80.00
   1.00  90.00

 b
  40.00
  70.00
  90.00
  60.00
 100.00

 the least squares
  -5.00
   1.10
```

`y = ax + b` に対して，`a = 1.10, b = -5.00` ということです。

計算速度とかは求めていません。

# 参考文献

最初に見つけた DGELS のプログラム例です。

* https://software.intel.com/sites/products/documentation/doclib/mkl_sa/11/mkl_lapack_examples/dgels_ex.c.htm

最初に見つけた DGELS で最小二乗法をしているプログラム例です。ただし三次元でした。

* http://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=772

最終的なデータはここから取りました。

* https://sci-pursuit.com/math/statistics/least-square-method.html
【Git】Gitの基本操作と基本コマンド2

前回の[【Git】Gitの基本操作と基本コマンド](https://qiita.com/soehina/items/5679bea71fde183d074f)の続きになります。

#リモート情報の確認
```
git remote
origin
```
詳細情報を表示。

```
git remote -v
origin  https://github.com/hukushima/gitpr.git (fetch)
origin  https://github.com/hukushima/gitpr.git (push)
```

##リモートリポジトリの複数登録
```
git remote add リモート名 リポジトリURL
```
originとは別のリポジトリを追加。

例

```
#github上でリポジトリを作成。
git remote add bak https://github.com/hukushima/git_bak.git

#追加できているか確認
git remote
bak
origin

#master情報をpush
git push -u bak master
```

##fetchコマンド
fetchコマンドを使ってリモートリポジトリからローカルリポジトリに情報を取得する。
※取得するだけで反映されるわけではない。

```
git fetch リモート名
```

例

```
git fetch origin
```

##mergeコマンド
fetchで取得したリモートリポジトリの情報を反映する。

```
git merge リモート名/ブランチ名
```

例

```
git merge origin/master
```

##pullコマンド
リモートから情報を取得してマージまで一気に済ませたい時に使う。
fetchとmerge同時にできる。

```
git pull origin master

#省略可
git pull
```
一気に済ませるから楽だけど、危険でもあるのであまり使わないイメージ。

##git remote show コマンド
git remote コマンドより詳細な情報が確認できる。

```
git remote show リモート名
```

例

```
git remote show origin
```

##リモート名の変更
```
git remote rename 旧名 新名
```

##リモート名の削除
```
git remote rm リモート名
```

#ブランチ
並行して複数機能を開発するためにある。
分岐して開発していくためのもの。
コミットを指し示すもの。

masterブランチはリリース専用ブランチにするのが基本。

##HEAD
現在作業しているブランチを指し示すもの。

##ブランチの新規追加
ブランチを新しく作成する。

```
git branch ブランチ名
```

##ブランチ一覧
```
git branch
#リモートのブランチも確認
git branch -a
```
ブランチがどのコミットを指しているか確認する。

```
git log --decorate
```

##ブランチを切り替える
```
git cheackout ブランチ名
```

#マージ
他の人の変更内容を取り込む。

```
git merge ブランチ名
```
```
git merge リモート名/ブランチ名
```

##コンフリクト
複数人で同じ箇所を変更してしまった場合、どれを優先させるべきかわからない状態。

###解決方法
変更が被った箇所が以下のように表示される。

```
HEADが変更した部分
<<<<<<HEAD
=====
他の人が変更した部分
>>>>>>otherbranch
```
どちらかの変更を削除してファイルを綺麗にする。

そもそもコンフリクトを起こさないのが一番なので、
mergeする前にcommitなどをして変更中の状態を無くしておくよう心がける。

##ブランチ名の変更
```
git branch -m ブランチ名
```

##ブランチの削除
```
git branch -d ブランチ名
```

#まとめ
次回に続きます。
AtCoderの楽しさ

# 記事の概要
最近、競技プログラミングなるものにドはまりしています。本記事では、競技プログラミングのコンテうとを運営しているサイト「[AtCoder](https://atcoder.jp)」の楽しさについて私の思うところを書いていこうと思います。自分語り多いです。
「そもそも競技プログラミングって？」や、「AtCoderってこんなサイトだよ！」みたいな説明は割愛します。以下の記事を参考にして下さい。↓↓
[レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【初級編：競プロを始めよう】](https://qiita.com/drken/items/fd4e5e3630d0f5859067)


# 筆者の自己紹介
大学の数学科を卒業して、現在社会人5年目。職業はSIerです。業務でプログラミングをしていたのは4年目まで。最近はチーム運営や客先調整などの仕事に終止しています。~~本当はプログラミングがしたい。~~
AtCoder歴は2ヶ月ちょい。現在茶色コーダーです。

# おことわり
私が業務で構築しているシステムに限らず、世間一般のWebシステムに於いて、競技プログラミングの知識や技術が活きることはそんなにありません。（もちろん複雑なアルゴリズムが必要なシステムも当然あります）
本記事では「何かに役立つ！」ではなく、ただ「楽しい！」というところに焦点を当て紹介します。まぁ、なんやかんやいろいろ勉強になること多いけど・・・。
<font color="red">(2021年1月追記)</font>
競技プログラミングは業務にあまり活きないと書いていますが、、ソース書く量が必然的に増えて経験量だったり、ざっとした計算量の見積もりなどに非常に役立っています。あとちょっとした業務ツールなどもプログラミングでやってしまおうという気持ちが生まれる（できるかはまた別）ので、業務にも非常に有用なように思います。

# 本題
筆者の考えるAtCoderの楽しさについて語っていきます。

## １．プログラミングが純粋に楽しい
そもそも私がSEになろうと思ったきっかけは数学科のプログラミングの授業で素数を小さい順に表示するという簡単なプログラムを作成した際の感動でした。
数学的に一般項がわかっていない素数をあんなに短いコードで（エラトステネスの篩ですね）簡単に表現できて、本気で感動したことを覚えています。

それが社会人になると可読性、保守性・・・。。さらにはフレームワークの制限・・・。
いや、大事ですよ！？もちろん。そこはとっても大事。でもたまに作る保守性も可読性もガン無視したその場限りのツール作るときって、とっても楽しいんですよね。
ただただその場の問題を解くだけのプログラミング。
それができるのが競技プログラミングです。

## ２．数学も楽しい
前述の通り。私は数学科を卒業しています。ですがまぁ学部生の数学科卒なんてたかがしれていまして。。。高校生までは数学の神童（言い過ぎました）とまで言われていましたが（言われてません）、大学の数学はなんというか歯が立たず、結局酒やサークル、バイトに溺れる大学生活を送りました。
競技プログラミングの問題では、高校までの数学でもなんども触れたものを目にします。
ユークリッドの互除法、合同式、組み合わせ、etc...

やっぱり数学って楽しいんですよね。競技プログラミングきっかけで数学も勉強し直してるというか、あんなに学んだ数学を実際に使うのって、こんなに楽しいんだって思ってます。おかげで数学の学習意欲も湧いてます。

## ３．レートが上がるのが楽しい
人間はやはりレベルとかレートとかランクとかあると上げたくなるもので、私もその術中に見事にハマりました。自分の成長が実感できて、毎週毎週レートが上がるのが楽しくて仕方ありません。また競技プログラミングサイトでは色でレートを表現していることが多く、レートによって「○色コーダー」などと読んだり呼ばれたりします。**目標がわかりやすく、モチベーションに繋がります。**ちなみに私の目下の目標は緑色コーダーです。水色にまで慣れたら万々歳。

## ４．まわりの友人や知り合いと一緒にやると楽しい
**「レベルアップ × 誰かと一緒にやる」**ってなんであんなに楽しいんでしょうね。相手が自分よりレートが高いと「追いつきたい」と思いますし。またスタートが一緒なら「一緒にレート上げようぜ！！」ができます。これもモチベーションとなりますね。
なにより楽しいのがコンテスト後の「お疲れー」「どうだった？」とか、「あの問題こうやって解けばいいのね！」とか「俺はこうやって解いたよ」などという感想戦だと思っております。
さらに職場の先輩と「昨日どうでした？」などといった話も超楽しいですね。

## ５．世界中の人達と戦える！
コンテストは大抵毎週末行われ、世界中のあらゆるレベルの人達が参戦してきます。その人達と100分間を戦い抜いて順位や、他人の書いたコードを参照するのも楽しいです。（他人のコード見ると勉強にもなるし。）


## とくに３と４がおすすめです
**「レベルアップ × 誰かと一緒にやる」**は最強です。これに尽きます。

# 脱線
「楽しい」だけでなく・・・

- アルゴリズム力があがる
- 就活に役立つ（場合がある）

など、「役立つ」ことも一応たくさんあります。


# 終わりに
この記事を読んだみなさんも試しにAtCoderを初めてみませんか！？
<b>競プロたのしい〜〜〜〜!!!!!!!!!!!!!!!!!!!</b>
50倍高速なi18n(多言語)対応をLisan.jsでしてみる with React

こんにちは、UIデザイナ兼フロントエンジニアの[ロモット](https://twitter.com/romotco)です。
[Lisan.js](https://lisanjs.com/)という **超高速をうたう国際化ライブラリ** を試してみました。

## 概要

フロントエンドJSにおいて
他の国際化ライブラリよりも **50倍高速** かつ **軽量** だとうたう [Lisan.js](https://lisanjs.com/) を使ってみます。
プラグインを使用することでローカライゼーション(l10n)も行うことが可能なようです。

**create-react-app** で作成したReactアプリを前提にしています。

- Lisan.jsをインストールする
- React(JSX)でも使えるようにしてみる
- 開発中に辞書を更新されるようにする

## インストール

### yarnの場合
```
yarn add lisan // 本体
yarn add lisan-cli -D // 開発/デプロイ用クライアント
```

## 環境設定

開発中にLisanの辞書更新で自動更新される＆ビルド時に辞書がコンパイルされるようにします。

### ディレクトリの作成

辞書ファイルを置く場所と出力先を用意します。
`makedir`などや普通にディレクトリ作成。
今回はcreate-react-appベースなので以下のようにします。

`入力元: src/translations`
`出力先: public/dictionaries/`

Gitを使用しているなら`.gitignore`で出力先を含めないようにします。

```
# dependencies
/node_modules
...
# dictionaries
/public/dictionaries
```

### 環境設定ファイル(.lisanrc)の用意

プロジェクトのルートディレクトリに.lisanrcを置きます。

`.lisanrc`

```
{
  "compile": {
    "inputDir": "src/translations", // 辞書ファイルのディレクトリ
    "outputDir": "public/dictionaries", // 出力先ディレクトリ
    "returnArray": true
  }
}
```

### スクリプトの用意

`package.json`に以下を追加します(環境にあわせて適宜変更してください)

```
"scripts": {
  "lisan:compile": "lisan compile",
  "start": "yarn run lisan:compile -w & yarn run react-scripts start", // 開発時に辞書もwatch
  "build": "yarn run lisan:compile & react-scripts build", // ビルド時に辞書をコンパイル
  ...
}

```

## 辞書ファイルの用意

必要なディレクトリにJSON5形式(コメント可JSON)の辞書ファイルを置きます。

 **日本語辞書**
`src/translations/ja/main.json`

```
{
  "locale": "ja",
  "entries": {
    "hello.world": "ハローワールド",
    "hello.person": "ハロー ${person}"
  }
}
```

**英語辞書**
`src/translations/en/main.json`

```
{
  "locale": "en",
  "entries": {
    "hello.world": "Hello World",
    "hello.person": "Hello ${person}"
  }
}
```

## Reactで表示してみる

`App.js`

```
import React, { useEffect, useState } from "react";
import { lisan, t } from "lisan";
...

function App() {
  const [loaded, setLoaded] = useState(false); // ロード中
  const [language, setLanguage] = useState("ja"); // ロケール

  // stateのlanguageが変更された場合にロケールを変更する
  useEffect(() => {
    updateLanguage(language);
  }, [language]);

  // ロケールの変更
  const updateLanguage = (lang) => {
    lisan.setLocaleName(lang);

    import(`../../public/dictionaries/${lang}/main`).then((dict) => {
      lisan.add(dict);
      setLoaded(true); // ロード終了
      setLanguage(lang); // language変更
    });
  };

  let user = {
    name: 'ユーザーさん'
  }
  return (
    <>
      {/* ハローワールド */}
      <p>{t("hello.world")}</p>
      {/* ハローユーザーさん */}
      <p>{t("hello.person", {
        person: <strong>{user.name}</strong>,
      })}</p>
    </>
  )
};

```

## で、本当に高速なの？


公式にある[単純な正規表現での置き換えとの比較ベンチマーク](https://github.com/lisanjs/benchmark)を実行してみましたが、
手元のMacBookProだと **30倍程度高速** なようです。

たしかに高速なようですが、他ライブラリとの比較までは行っていません。
公式では実際のi18nライブラリでは単純な正規表現よりも複雑になるため **50倍程度高速** と主張しているようです。

なにかの参考になれば幸いです。
golangでの組み合わせ問題で並列処理と単純な二重配列を利用した際の速度比較

#はじめに
Atcoderなどの練習用に、色々なアルゴリズムをgolangで書く練習をしているなかで、組み合わせ問題(combination)を解くさいに、どのような方法が良いかを調べていました。
その中で参考にしたサイト(https://qiita.com/kokardy/items/a18b574d548c212e58e6) ではgolangらしく並列処理を利用してコードが紹介されていました。
自分の理解のためにも、これを素直に二重配列を利用したものに書き換えてベンチマークをしてみました。
参考もとのコードの速さが際立っていたので備忘録を含めて書いておきます。
この解析はMacBookPro go1.14.2で測定しました。

#参考にした並列処理のコード
参照元: https://qiita.com/kokardy/items/a18b574d548c212e58e6

```
func Combinations(list Replacer, select_num int, repeatable bool, buf int) (c chan Replacer) {
    c = make(chan Replacer, buf)
    index := make([]int, list.Len(), list.Len())
    for i := 0; i < list.Len(); i++ {
        index[i] = i
    }
    var comb_generator func([]int, int, int) chan []int
    if repeatable {
        comb_generator = repeated_combinations
    } else {
        comb_generator = combinations
    }
　　 go func() {
        defer close(c)
        for comb := range comb_generator(index, select_num, buf) {
            c <- list.Replace(comb)
        }
    }()
    return
}
```

#二重配列を利用したコード

```
func combination(list []string, select_num int) [][]string {
        combi := make([][]string, 0)
        switch {
        case select_num == 0:
                return [][]string{{}}
        case select_num == len(list):
                return [][]string{list}
        case len(list) < select_num:
                return nil
        default:
                for i := 0; i < len(list); i++ {
                        subCombi := combination(list[i+1:], select_num-1)
                        for _, subList := range subCombi {
                                newCombi := append([]string{list[i]}, subList...)
                                combi = append(combi, newCombi)
                        }
                }
                return combi
        }
}
```

#Benchmark結果
1000個のint配列を作ってbenchmarkを取ってみました。
圧倒的に速度。。。おおよそ1000倍早いとは。。

```
h0801Toby001:bench toby$ go test -bench . -benchmem
goos: darwin
goarch: amd64
BenchmarkArrayCombination-4   	       6	 170055299 ns/op	135015690 B/op	 2008002 allocs/op
BenchmarkChanCombination-4    	  124047	     10958 ns/op	    2362 B/op	      39 allocs/op
PASS
ok  	_/Users/toby/Dropbox/Documents/program/atcoder/test/bench	4.781s
```

#所感
二重配列の処理は、毎回帰ってくるたびにsliceにappendしているのがとにかく重そうです。
channelに入れるだけだと軽いのかな。
二重配列の場合でも、事前に必要なだけsliceを確保していおくと早いのかな。
IAMロールの信頼ポリシーでロールセッション名を制限する

## はじめに
2020/4/21 に IAMロールの信頼ポリシーで利用可能な AWS STS の条件キーに
`sts：RoleSessionName` が追加されました。

**IAM ロールを使用して実行されたアクションを担当する ID を簡単に特定**
https://aws.amazon.com/jp/about-aws/whats-new/2020/04/now-easily-identify-the-identity-responsible-for-the-actions-performed-using-iam-roles/

この条件キーを 信頼ポリシーの Condition に記述することで
AssumeRole でロールを引き受ける際に設定する必要のあるロールセッション名指定できます。

## 何が嬉しいか
ロールセッション名とは AssumeRole 時にオプションで指定可能な文字列です。
この値は CloudTrail にも記載されるため、セッションの識別に使用できます。

条件キー `sts：RoleSessionName` によりロールセッション名を強制できるため
例えば以下のような信頼ポリシーを記述することで、AssumeRole を行ったIAM ユーザー名を
確実に CloudTrail の証跡に残すことができます。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Principal": {
                "AWS": "arn:aws:iam::0123456789012:root"
            },
            "Condition": {
                "StringLike": {
                    "sts:RoleSessionName": "${aws:username}"
                }
            }
        }
    ]
}
```

## やってみる
test_user という IAM ユーザーが 同一アカウント内で IAMTEST_ROLE という
ロールに切り替えるというケースで考えます。

IAMTEST_ROLE の信頼ポリシーを前述のように書き換えて保存します。
Principal のアカウントID は 実際のものに変更してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/1ee59e48-6690-7427-0175-c23b4f4682ab.png)

AWSCLI で検証してみます。
default プロファイルに test_user のアクセスキー/シークレットアクセスキーを設定します。

```shell-session
$ aws configure
AWS Access Key ID [None]: AKIAXXXXXXXXXEXAMPLE
AWS Secret Access Key [None]: xxxxxxxxxxxxx/xxxxxxx/xxxxxxxxEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

~/.aws/config に テスト用のプロファイルを iamtest と iamtest2 という名前で追加します。

```
[profile iamtest]
region = ap-northeast-1
role_arn = arn:aws:iam::0123456789012:role/IAMTEST_ROLE
role_session_name = hogehoge
source_profile = default

[profile iamtest2]
region = ap-northeast-1
role_arn = arn:aws:iam::0123456789012:role/IAMTEST_ROLE
role_session_name = test_user
source_profile = default
```

`--profile iamtest` では ロールセッション名が呼び出し元の IAM ユーザーと
一致しない (role_session_name = hogehoge) ため、AccessDenied になります。

```shell-session
$ aws sts get-caller-identity --profile iamtest
An error occurred (AccessDenied) when calling the AssumeRole operation: User:
arn:aws:iam::0123456789012:user/test_users is not authorized to perform: 
sts:AssumeRole on resource: arn:aws:iam::0123456789012:role/IAMTEST_ROLE
```

`--profile iamtest2` ではロールセッション名が呼び出し元の IAM ユーザーと
一致する (role_session_name = test_user) ため、get-caller-identity の結果が返ります。

```shell-session
$ aws sts get-caller-identity --profile iamtest2
{
    "UserId": "AROAXXXXXXXXXXXXXXXXX:test_user",
    "Account": "0123456789012",
    "Arn": "arn:aws:sts::0123456789012:assumed-role/IAMTEST_ROLE/test_user"
}
```

ちなみに マネージドコンソールからのスイッチロールの場合、ロールセッション名は自動的に
IAM ユーザー名に設定されるため、今回の例では問題なくスイッチできます。

## 参考
**IAM and AWS STS Condition Context Keys**
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-sts

簡単ですが以上です。
参考になれば幸いです。
Raspberry pi 4 に Ubuntu MATE を gdm3 でインストールする

[Ubuntu 20.04 LTS Server を Raspberry Pi 4 にインストール](https://qiita.com/azumabashi/items/182f365cf7405156788c) ではGUIインストールの手前までをやってみました。

ここでは Ubuntu MATE をインストールしてみます。
作業日：2020年5月4日

次のコマンドを実行します。

```
sudo apt install ubuntu-mate-desktop
```

途中でディスプレイマネージャ gdm3、lightdm のいずれを選択するか聞いてきます。
gdm3 を選択しておきました。

インストールが完了したら再起動します。

```
sudo shutdown -r
```
GUIが起動しました。
パスワードを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/5efe69d2-9a56-31a5-781a-ca043fadfbbe.png)

デスクトップが表示されます。左上の Activities をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/03dc75a0-4577-88e4-a270-88646a60ec06.png)

Show Applications をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/c0314948-cc97-d59a-14c6-bd8fb7607735.png)

各種メニューが出てきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/a682c42f-773b-5166-e14d-5646034d65c2.png)
私的Rust学習メモ2(Enum Struct エラー制御など)

# RustのEnum
Javaなどの言語におけるEnumというよりは、
Haskellにおける代数的データ型やTypescriptのDiscriminated Unionのような使い方をする
(それぞれの要素が別の型を持つことができる)

## matchによる分岐
Enumによって処理を切り替える場合はmatchを使う

```rust
enum Hoge {
    Fuga(i32),
    Piyo(String),
}

fn hoge_func(hoge:Hoge) -> (){
    match hoge{
        Hoge::Fuga(i) => println!("FugaValue:{}",i),
        Hoge::Piyo(s) => println!("HogeValue:{}",s)
    }
}
```
なお、rustのmatchは文ではなく式なので値を返すこともできる。

## 標準のenum
javaのOpriontalに相当するOptionや例外処理に利用するResultもenumである。

# Structs
* Object指向言語におけるObjectのような構造化データを保存するもの
* structはフィールドが全てCopy可能でも所有権が絡む。(自分でCopy可にしない限り)

## Structの初期化
基本的に、全フィールドを指定する必要あり。
変数名とフィールド名が一致している場合は省略可能。
`..`でjavscriptのスプレッド構文のように展開することも可能。

``` rust
struct Hoge {
    hoge:i32,
    count:u32
}

let h = Hoge{
      hoge:5,
      count:1
};

let count = 3;

let h2 = Hoge{
  count,
  ..h
}

```

structのフィールドの値として値を指定することは変数の代入と同様の動作なので、
所有権のかかわる変数の場合はstructのフィールド側に所有権が移行する。

### Structの生成とスコープの問題
structのフィールドはデフォルトでprivate(同一モジュールのみからアクセス可能)である。
よって、一つでもpublicではない(pubがついていない)フィールドがあるstructはモジュール外から生成できなくなる。
このようなケースではStructを返すメソッド(selfなし)を定義しておく。
(Object指向言語におけるConstructorのようなもの)

## メソッド
Structに紐づく関数を定義できる。
オブジェクト指向言語におけるメソッドのようなもの。
第一引数はselfで呼び出し元となるStructを取る。
selfの部分は、`self,&self,&mut self`が使えるが、基本的に`&self` か `&mut self`のはず。
(メソッドに所有権を持っていかれると困るケースがほとんどのはず）。
メソッド定義でmutかどうかの使い分けができるため、
structがImmutableかどうかも変数宣言時にmutをつけるかどうかで制御できる。
(mut借用ができない場合、自分のフィールドを書き換えるメソッドは呼べない)

``` rust

impl Hoge{
  fn hoge_method(&self){
    
  }
}

```

### Associated Functions/関係関数
第一引数をselfにしないとAssociatedFunctionになる。
Object指向におけるstaticメソッドのような奴。

コンストラクタなどに利用できる。
標準だと`String::from("hoge")`とか。

# Package クレート　モジュール
## Package
ビルドの単位。tomlファイルを持つ。
1つ以上のクレートを束ねる。

## クレート
依存性管理で使われる単位。
複数のmoduleを木構造で持つ根本。

## モジュール
クレートに木構造でぶら下がる。
スコープの単位。

段階ごとに分けて書く場合ディレクトリかファイル名を合わせる。

# エラー制御
## panic!
検知したからと言ってどうしようもない例外の時に投げる。
古いJavaの非検査例外のような感じ。

## ResultEnum
Result型はOkかErrorを取る。
検査例外とかGoのエラー制御のような雰囲気。

Enumなのでmatchで分岐してもいいが、専用の記法やメソッドが用意されている。

### unwrap/unwrap_or_else
ResultからOKという前提で値を取り出す。
実際Errorだった場合、unwrapはpanicを投げ、
or_elseの場合指定した処理を実行する。

### Result型が戻り値の関数中での?
関数の戻り値がResult型の場合、内部では？で
jsのOptional chainingのようなことができる。

```rust
some_return_result()?.method_uses_ok_value()
```
試験に出るAWS:SAAでしょう 第５夜

今回、本の方の１章文が長いので
ここでは分割して記事を書いていきます
いよいよ大事な箇所に突入した感じですね

現在（2020.05）どうでしょうが安く観られるそうですが
みましたか？　DVDを貸してくれますか？

# 受験生諸君(自分)!!

[これ↓](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/479739739X/ref=sr_1_1?adgrpid=54919691884&dchild=1&gclid=EAIaIQobChMIvaDenJqw6AIVhqmWCh3eZA7YEAAYAiAAEgKc0fD_BwE&hvadid=338533795365&hvdev=c&hvlocphy=1009301&hvnetw=g&hvqmt=b&hvrand=758814098125985146&hvtargid=kwd-475022447197&hydadcr=4072_10899412&jp-ad-ap=0&keywords=aws+%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88&qid=1584953072&sr=8-1)をもとに勉強しています
![51DY+M37OIL._SX352_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/e2f66413-a969-0d5c-f127-69d3cdfb9b9c.jpeg)

# 第5夜はこれを覚えよう！

### ストレージサービスの分類とストレージのタイプ
- 5つのストレージサービス、　　　、　　　　、　　　　、　　　　、　　　　、がある
- 　　　はデータを物理的なディスクにブロック単位で管理する　　　　　ストレージ
- 　　　はブロックストレージ上にファイルシステムを構成して、ファイル単位で管理する　　　　　ストレージ
- 　　　と、　　　　は、ファイルに任意のメタデータを追加してオブジェクトとして管理する　　　　　　ストレージ

### EBS
- AWSが提供する　　　　ストレージサービス
- EC2の　　　として利用したり、　　　　　として複数のEBSをEC2にアタッチできる
- RDSの　　　　　にも使用する

### EBSのボリュームタイプ
- EBSボリュームタイプは　　　　で２種類、　　　　タイプで２種類ある

### 汎用SDD（gp2）
- EBSの中で最も一般的、EC2の　　　　　　　　　タイプ

### プロビジョンドIOPS（io1）
- EBSの中で最も高性能、RDSやEC2で　　　　　　を構成する場合や、高い　　　が求められるときに利用する

### スループット最適化HDD（st1）
- 　　　　に対する処理や　　　　処理のインプット用ファイルなど、　　　　を高速で読み取るときなどに利用する

### Cold HDDｍ（sc1）
- 最も低コストで利用頻度は少ないため、　　　　領域の用途に適している

### ベースライン性能とバースト性能
- 　　　　以外はストレージの容量に応じて　　　　　がある
- 処理量の　　　　　　　　なバースト性能があるが、一時的な処理として、これに頼ってはいけない



---

この記事（問題）を書きながらUdemyという動画勉強サイトで
[AWSのSAA講座](https://www.udemy.com/course/aws-associate/)を見ていますが、そちらは本当にわかりやすくて
初学者に優しい言い回しをしてくれるので大変助かっています

この記事に貼ってある本を買って読んでみて
理解が及びにくいとろこをUdemyの講座で補っている感じです


**第5夜の答えは第6夜で！！**

## 第4夜の答えはこちら！

### AWSにおける運用サービス
- Amazon CloudWatchは、定期的にAWSリソースの状態を取得し、問題があれば知らせる仕組み
- AWS CloudTrailは、AWSリソースの作成や、マネジメントコンソールへのログインを監視する

### CloudWatch
- 定期的にAWSリソースを取得している状態をメトリクスと呼ぶ
- あらかじめ定義しているメトリクスを標準メトリクスと呼ぶ
- 独自の定義はカスタムメトリクスと呼ぶ

### CloudWatch Logs
- アプリケーションログやApacheログをモニタリングするサービス
- CloudWatch Logsを利用するには、独自のエージェントをインストールする必要がある
- CloudWatch Logsを使うことでアプリケーションレイヤーの監視もできる

### CloudWatch Events
- 独自のトリガーをイベントソースと呼ぶ
- 後続アクションをターゲットと呼ぶ
- この２つの組み合わせを定義するサービスがCloudWatch Events

### CloudTrail
- AWSに関するログを自動的に取得するサービス

### CloudTrailで取得できるログの種類
-管理イベント：マネジメントコンソールへのログインなど、デフォルトで有効
-データイベント：S3バケットデータ操作、Lamda関数の実行など、デフォルトで無効

### CloudTrailにおける、CloudWatch Logsとの連携
- 何か問題が発生したときに各ユーザーの操作を追跡することができる
- CloudWatch Logsとの連携機能
- 事前に不正な操作を登録しておけば検知することができる
RailsでBootstrapのdropdownが使えない

## 開発環境
```
Rails 6.0.2
ubuntu(WSL)
Bootstrap 4
```
前提として、cssファイルは読み込まれているものとします。

### 想定エラー
クリックしてもメニューがでてこない。
ターミナルにエラーは出てこない状態。

### 原因
- ブラウザにjavascriptが読み込まれていない
- HTMLのコードが間違っている

今回は上の場合を想定しています。

## 解決策
### jqueryを使えるようにする
Gemfileに以下を追加します。
追加後にターミナルに`bundle`を入力してください。

```Gemfile
gem 'jquery-rails'
```


### ブラウザにjavascriptを読み込ませる
```application.html.slim
= javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
```

### プリコンパイルするファイルを設定

```config/initializers/assets.rb 
Rails.application.config.assets.precompile += %w( application.js )
```
### マニフェストファイルの記述

```app/assets/javascripts/application.js
//= require jquery
//= require rails-ujs
//= require popper
//= require turbolinks
//= require_tree .
//= require bootstrap
//= require activestorage

```

上記のこと全て行っても、以下のエラーが出た場合

```
ActionView::Template::Error (Asset `application.js` w
as not declared to be precompiled in production.
Declare links to your assets in `app/assets/config/mash
nifest.js`.
```
ターミナルに`rake assets:precompile`を入力したら成功すると思います。

### 参考文献
- [Bootstrap4移行ガイド](https://cccabinet.jpn.org/bootstrap4/components/dropdowns)
- [[Rails5エラー] AssetNotPrecompiled Asset was not declared to be precompiled in production.](https://normalblog.net/system/rails5-assetnotprecompiled/)
Jupyter Notebook のフォント変更 (for mac) *初心者向け

Jupyter notebookを使って来たのですが、なぜかコードのデフォルトフォントが等幅フォントじゃないんですよね。
今までデフォルトのまま使って来ていましたが、普通にめんどいです。

プログラミング初心者向けに、説明しようと思います。
(かなり初心者向けに書いております。上級者の方にとってはかなりイライラする書き方かと思われます。ご承知ください。)

## 1.はじめに
Jupyter notebookのテーマのインストールをオススメしています。
気にしない方はすっ飛ばしてください。

ターミナル上でこのコードでインストールします。
(ちなみにxxxの部分には自分のコンピュータの名前が入っているはずです)

```
xxx% pip install jupyterthemes
```

利用可能なテーマ

```
xxx% jt -l
Available Themes: 
   chesterish
   grade3
   gruvboxd
   gruvboxl
   monokai
   oceans16
   onedork
   solarizedd
   solarizedl
```
Googleで検索すればどんなテーマなのか出てくると思うので、お好きなテーマを見つけてください。私はoceans16が好きなので、これで設定します。

```
xxx% jt -t oceans16
```
これで、テーマが変わったはずです。

##2. フォント変更
フォントの管理は、.jupyter/custom/custom.cssというところでしています。
これをemacsなどで開いて、直接変更します。

```
xxx% emacs .jupyter/custom/custom.css
```
ここでは等幅フォントに変えたいので、monospaceのところを変更したいですね。
emacsには置換機能があるので、それを使いましょう。
esc+shift+5 (つまりM+%)を押すとQuery-replace:と聞かれるので、font-family: monospace, monospace;を入力し、
その後に出てくるQuery-replace int with: font-family: monospace, monospace; のところに、font-family: XXX, monospace;と入力です。
ここでのXXXはお好きなフォントをさします。私はデフォルトから入っているMonacoを採用しました。

```.jupyter/custom/custom.css
(M+%)
Query-replace: font-family: monospace, monospace;
Query-replace int with: font-family: monospace, monospace; font-family: Monaco, monospace;
```
この後は、変更しますか？みたいなことを聞かれ続けるので、yを押すだけです。
最後に、control+x(C+x)を押してからcontrol+s(C+s)でセーブし、control+c(C+c)で閉じてください。

Jupyter notebookを開くと、フォントが等幅のMonacoになっているはずです！


##参考
http://shu87.hateblo.jp/entry/2017/08/30/003224
https://qiita.com/damyarou/items/5c319f5def57c6e36a37
Pythonのheapqにリストを入れたときの挙動

競技プログラミングやっててPythonでDijkstraを実装しようとした時、heapqに("頂点名",距離)みたいなのを突っ込んで距離でソートしてほしかったのですが、その時の挙動がちょっと不安だったので確かめただけのメモ記事です。

カスタム演算子みたいなのが突っ込めるのかなぁ…とも思いましたが、そこ自作するとたいてい遅くなるのでできるだけ避けたい気持ちで調べました。

heapqの仕様というかPythonの比較演算子の仕様だとは思うんですが、せっかくなのでまとめておきます。


# 結論
heapqにリストを突っ込むと、
**第一要素の昇順→第２要素の昇順**というふうに評価される。要素同士の評価は独立に行われるっぽいので数字と文字列を混ぜても大丈夫。

要は、

```
[[1,4],[2,0],[0,1],[0,3]]
↓
[[0,1],[0,3],[1,4],[2,0]]
```

みたいな感じになります。

# 検証1

```python

import heapq
import random
a = []
heapq.heapify(a)

for i in range(5):
    heapq.heappush(a,[random.randint(0,10) for i in range(2)])

while a:
    print(heapq.heappop(a))
```

```
[0, 10]
[2, 7]
[2, 7]
[2, 10]
[5, 0]
```

# 検証2

```python

for i in range(5):
    heapq.heappush(a,[random.randint(0,10),chr(random.randint(97,97+26))])

while a:
    print(heapq.heappop(a))
```

```
[0, 'k']
[4, 'd']
[4, 'l']
[5, 'c']
[7, 'o']
```

以上。Pythonくんはやっぱりなんやかんやいい感じにしてくれることが多くて好きですが、たまに事故るので好きじゃないです(矛盾)
開発者用のWindows環境を用意したい

緊急事態宣言に合わせ、プロジェクトメンバーが家で作業することになり、個人PCで操作するわけにもいかないので、全メンバーに会社支給PCが用意される事になった。

今更だが、こういうアプリをインストールし、環境設定をした。
必要に応じ追加していくだろうが、今のところこんな感じ。

本当はAnsible等で再現できる仕組みを作りたかったが、レジストリを調べるのも大変だし、時間もなかったので、普通にいろいろクリックしてインストールさせる事に。今度時間があったら仕組みを作ろう。


#アプリのインストール
##Java
#### Azul OpenJDK 8
Oracleは避けた。

##ネットワーク
#### Tera Term
定番のターミナル。
#### WinSCP
定番のscpクライアント。
#### UltraVNC
定番のVNCクライアント。他のVNCより動作が軽いらしい。
#### MobaXterm
X Windowを簡単に使用できるターミナル。

##アーカイバ
特に説明は不要か。
#### 7zip
#### WinRAR

##コミュニケーション
客先、社内チームによって連携方法がバラバラなため、いろいろ入れておく。
#### Slack
#### Zoom
#### Microsoft Teams

##エディタ
#### Atom Editor

##その他
#### Adobe Acrobat Reader DC
#### VMware Workstation Player
#### ChgKey
レジストリ変更でキーボードのキーアサインを変更する。後述のWindowsの変更の中で必要。
#### cygwin x8664 (with openssh, vim)
なぜかsshやvimが標準で入らない。
#### Myricaフォント
プログラマ向けの、0とO（ゼロとオー）等を読み間違えにくくしたフォント。いくつかそのようなフォントがあるが、その中でパイプ（縦棒）も工夫してあるものを選択。

	
#Windows（等）の設定変更
##タスクバー
#### 上へ移動
下にあると、アプリのメニューとタスクバーの間でマウスポインタを画面の上下を行ったり来たりさせないといけないので不便。

##メモ帳
#### 右端で折り返す

##Explorer
#### 全てのフォルダーを表示
#### タイトルバーに完全なパスを表示
#### 隠しファイル・フォルダ・ドライブを表示
#### 暗号化や圧縮されたNTFSファイルをカラー表示
#### 空のドライブも表示
#### 登録されている拡張子も表示
#### 保護されたオペレーティングシステムファイルも表示

##マウス
#### ポインタの速度を最速に
#### タッチパッドを無効化（タイプ時にポインタが飛ぶのはみんな嫌いだよね？）
#### Ctrlキーを押すとポインタの位置を表示

##NFSクライアント
#### 有効化

##地域
### 書式の変更
#### 時刻（短い）＝HH:mm
#### 時刻（長い）＝HH:mm:ss
#### 日付（短い）＝yyyy-MM-dd （ANSI書式）
#### 日付（長い）＝yyyy-MM-dd （本当は日付と時間を両方指定したかったが、Windowsが許可しないようだ）
### IME
Lで始まるものは、lkaを除き、ラ行の文字に変更（例：laは「ぁ」から「ら」に、lwaは「ゎ」から「るゎ」に。

## Officeのオートコレクト
全Officeアプリのオートコレクトを、全て無効化する。

##キーボードのキー変更
#### ひらがなカタカナキーを右ALTキーに変更
端末に右ALTキーがないので、片手でCTRL-ALT-DELが打てるようにするため。
#### F1をESCに変更
急ぎでEscキーを押したつもりが、ヘルプ画面がゆっくり立ち上がると、イラっとするよね。
#### Insertをスペースに変更
使わないし、悪ささせたくないため、無難なキーに変更。
ffmpegでmp4動画を29分間ごとに分割する

#方法
動画を29分間ずつ分割する方法を下記に記載します。
29分間の理由は、ニコニコ動画のアップロード制約上、30分以上は品質が下がる恐れがあるためです。
よって、29分(1740秒)と指定します。

```bash:test.sh
ffmpeg -i input.mp4 -c copy -f segment -flags +global_header -segment_format_options movflags=+faststart -reset_timestamps 1 -segment_time 1740 output%02d.mp4
````
SwiftUIでNavigationVarとListの組み合わせ

[SwiftUIでNavigationView](https://qiita.com/Hyperbolic_____/items/d991520d7b74fb33cce3)と[SwiftUIでList](https://qiita.com/Hyperbolic_____/items/d2d8f047828e33fc7089)の組み合わせです。

##リストを表示する


UIKitでのNavigationViewとtableViewの組み合わせをSwiftUIで行います。

<img width="250" alt="スクリーンショット 2020-05-04 17.55.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/297a06cd-d4f1-3c6c-a87d-56971770051f.png"> <img width="250" alt="スクリーンショット 2020-05-04 18.16.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549093/5b8840d3-b633-892c-7d58-ff263bab7523.png">


UIKitでお馴染みのNavigationVarをSwiftUIで作成します。

```swift
import SwiftUI

struct FirstView: View {
    var Array = ["あ行","か行","さ行","た行","な行","は行"]
    var body: some View {
        
        NavigationView {
            List {
                ForEach(Array, id: \.self) { i in
                    NavigationLink(destination: SecondView())  {
                        Text(i)
                    }
                }
            }
            .navigationBarTitle("遷移前")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        FirstView()
    }
}
```

キーとなるのは`NavigationLink()`で遷移先のViewを指定しているところです。

```swift
import SwiftUI

struct SecondView: View {
    var body: some View {
            Text("遷移先")
    }
}

struct SecondView_Previews: PreviewProvider {
    static var previews: some View {
        SecondView()
    }
}
```

ただ遷移するだけであれば上のコーデ行うことができます。
リセットCSSでuser agent stylesheetが消せない時の解決方法

#どういう状況
YUI 3.5.0 - reset.cssを使用したけれど、ブラウザ初期に設定されているCSSを一部消せませんでした（下記のもの）

```php:user_agent_stylesheet(この表示はgoogleの検証画面にあります)
li {
    display: list-item;
    text-align: -webkit-match-parent;
}
```

#解決方法
各項目について、_reset.scssにinherit属性を追加することにより解決できました。

```php:src/public/resources/sass/_reset.scss
li{
  text-align:inherit;
  display:inherit;
}
```

#参考
http://www.366service.com/jp/qa/5bb8b0bd7ede8b67b1b3f610dfaabe35

#後日談
打ち消せた項目でもbootstrapとして効いている場合は、結局打ち消した項目の再設定が不可能だったため、cssファイルを分けて、app.cssを読み込まないで該当ファイル(例： user.css など）だけを読み込ませることでうまくいきました。

何かの参考にしていただければと思います。
JS 定義されていないundefinedを条件分岐

##きっかけ
わかりにくいタイトルですが、生JSで作成物を作っていて、条件分岐でundefinedエラーが出てしまい、どうしようかと考えていたら、そのままundefinedを使用できるtypeofという演算子。
他の言語で似たような演算子はあったが、今まで使ったことなかった。


```

typeof 定義されていないオブジェクト 
 
#返される値　　
undefined

```

なのでこういった風に使いました。

```
if (typeof 定義されていないオブジェクト !== 'undefined'){
  オブジェクトが定義されていた場合の処理
}
```


##typeof演算子
データ型を返す。引き渡された値の型の確認に使う。他にもnullやBoolean(真偽値)など、さまざまなデータ型を返すため色々なパターンの条件分岐などにも使えたりする。


##まとめ
色々書くことはあるけれど、終わらなくなってしまうので今回はここまで。
GitHub Desktopを使ってリポジトリをクローンする

# 必要なもの
- GitHubアカウント
- <a href="https://desktop.github.com/">GitHub Desktop</a>

# 自分で作成したリポジトリをクローン
GitHub Desktopを起動したら左上の「current repository」のプルダウンから「Clone Repository」をクリック
<img width="524" alt="スクリーンショット 2020-05-04 20.04.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/fa5434d6-58a5-1885-ef07-f55a876cf3f2.png">

「Your Repository」に既に作成されている自分のリポジトリがあるので、選択をして「Clone」をクリック
<img width="535" alt="スクリーンショット 2020-05-04 20.06.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/8eae8851-ee2c-aa11-ef25-cf2f5f908e69.png">

## Your Repository に表示されていない場合
今、ログインしているアカウントを確認してください
メニューから GitHub DeskTop > Preferences > Accounts で確認できます。

<img width="608" alt="スクリーンショット 2020-05-04 20.34.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/bac07903-58cc-705e-0b6b-ba8cf70ef180.png">

# 他人が作成したリポジトリをクローン
<a href="https://github.com/">WebブラウザのGitHub</a> にアクセスして参考にしたい方のリポジトリ、あるいはチームメンバーのリポジトリを探します。(共同で作業するリポジトリを見つける際など）アクセスをしたら「Clone or Download」の赤枠部分をクリックしてURLをコピーします
<img width="1676" alt="スクリーンショット 2020-05-04 20.13.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/8c450750-bcc7-3aaa-a903-644540ba2b0d.png">

GitHub Desktopに戻り Clone Repository のURLタブ か先ほどコピーしたURLを入力し、Cloneする
<img width="527" alt="スクリーンショット 2020-05-04 20.13.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/3374ba57-b6d7-5267-1aff-7fc87b1085a3.png">

あとはFinder(windowsの場合はエクスプローラー)から実際にリポジトリがクローンされたか確認します。（今回は「practice-volume1」というリポジトリをクローンしました）
<img width="766" alt="スクリーンショット 2020-05-04 20.17.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602057/d775d2cb-105b-224c-bb7c-c2b74dd2c2c8.png">
[WIP] きのこ本を勝手に電子書籍(epub)化

# [WIP] きのこ本を勝手に電子書籍(epub)化

## はじめに

* いわゆる「きのこ本」とよばれる書籍があります。「プログラマが知るべき97のこと」とかのシリーズものです。
* これらの書籍は CC-by-3.0 などでライセンスされているため、著作者名を明記することで、自由に使用することができます（改変もＯＫ。商用もＯＫ）
* そこで、きのこ本を勝手に電子書籍(epub)化してみました。紙の書籍は持っていますが、電子書籍は持ち運びが便利ですよね。

https://github.com/yoshi389111/kinokobooks

* その際の作業メモとか思ったことなどを残しておきます。主に「プログラマが知るべき97のこと」での作業がメインです、それ以外の書籍についても含まれているかも。
* 後で追記するかも。

## データの入力

書籍の各コラムは自由に使えるのですが、紙の書籍のデータを電子データにしないと電子書籍にできないのでデータの入力が必要です。

といっても、実は「きのこ本」の非公式データは、ネットワーク上にいくつかあるみたいで、今回は以下のサイトの内容を使わせていただきました。

* [https://プログラマが知るべき97のこと.com/](https://プログラマが知るべき97のこと.com/)

（ほかにも、wikisource にもあるみたいですが、上記ページのコピーのように見えました）

ただしいろいろとチェックしてみると、結構抜けがあったり、誤字（入力ミスや OCR 誤り）などがありそうなので、手元の紙の書籍と見比べてこまごまと修正しました。

自分で全部作業するよりはかなり省力化できていますが、それなりに手間がかかりました。目が痛い。

## 電子書籍化の方法

まず、最終形の電子書籍のフォーマットとして、一般的だと思われる epub 形式にしようと決めました。

変換するツールとしては `pandoc` を利用することにしました。
これは epub 以外の形式として html などにも変換できると良いと思ったためです。

そして、入力ファイルは pandoc の独自拡張のマークダウン形式としました。
マークダウンにしたのは、そこまで複雑な構造はないだろうし、十分だと思ったためです。
しかし、実際に作業すると意外と困ることが多かったです。
複数言語が混じっているとか、テーブル構造がマークダウンで書けないケースがあるとか、ルビがあったり。
もしかしたら、入力フォーマットを html として、意味的なマークアップをする（装飾的なマークアップをしない）ほうがよかったのかもしれません。

（見た目は、 pandoc で html -> html 変換をして、出力テンプレート側で装飾すれば良いのではないかと思いました）

## 画像データ

「プログラマが知るべき97のこと」の、45 番目のコラムに画像がついていました。

英語版の wiki を探して（既に存在していなかったので、 Internet Archive で掘り起こしました）、元の画像そのものは手に入りましたが、そのまま使うのはどうかと思ったので、自力で作り直してみました。

その際、拡大縮小されても大丈夫なように SVG でつくってみました。

しかし、いくつかの電子書籍リーダーで表示してみたところ、サイズがうまく表示されなかったり（リーダー毎に表示サイズが変わっていたり）しました。
結局 PNG に変換して使用しています。

まだ、しばらくは SVG の対応は難しいのかもしれません（確認したのは 1 年ぐらいまえなので、最近は改善しているのかもしれません）。

## 文字や表の色

同様にコラムには表が含まれているものもありました。

その際、普通にテーブルを作り、CSS で色を指定してしまっていました。

しばらくはそれで問題ないと思っていたのですが、電子書籍リーダーによっては、紙面の色や文字の色を変えられるものがありました（夜間モードやカスタマイズなど）。

そうすると、固定で色を指定していると、うまく表示されないことがありました（CSS で表の枠線を黒指定してあり、夜間モードで背景が黒になると、枠線が見えなくなる）。

基本的には、色はデフォルトの背景色と前景色を使うべきで、CSS では変えるべきではないようです。

## 表紙について

「きのこ本」はオライリー発行の本なので、非公式版の電子書籍もなんとなくオライリー風の表紙画像にしたいと思いました。

オライリー本の多くは、表紙が動物の細密画（？）っぽい感じのものが多いと思います。
そこで動物は避けて、それ以外のものをなんとなく細密画っぽい感じにして使用することにしました。

たとえば非公式版「プログラマが知るべき97のこと」の表紙は、 Wikipedia の「シイタケ」の項から画像を借用し、加工しました。
この画像は CC-by-2.0（表示 2.0 一般）でライセンスされています。

* File:Shiitakegrowing.jpg
    * Author frankenstoen from Portland, Oregon
    * This file is licensed under the Creative Commons Attribution 2.0 Generic license.
    * https://creativecommons.org/licenses/by/2.0/

加工には `gimp` （かなり古いバージョンだったはず）を使用しました。
細密画っぽい感じにするには、試行錯誤をしてとりあえず完成しました（なんとなく今一つですが）。
しかし、後から考えると何度も処理できるように（別の画像も同じように処理できるように）、コマンドラインで加工する仕掛けを作ったほうが良かったかもしれません。

また、表紙のイメージカラーは「色覚多様性」対応や白黒表示を考慮して、オライリー発行の書籍とは少し色をかえてみました。
たった三色（黒、白ともう１色）なのに、かなり大変でした。
もしかしたら、書籍のタイトルは袋文字にして見やすくしたほうが良かったかもしれません。

## その他の「きのこ本」

いわゆる「きのこ本」は現状、全部で 5 冊あります。

* 「プログラマが知るべき97のこと」
* 「ソフトウェアアーキテクトが知るべき97のこと」
* 「プロジェクト・マネジャーの知るべき97のこと」
* 「ゲームクリエイターが知るべき97のこと」
* 「ゲームクリエイターが知るべき97のこと 2」

もし見てみたかったら、GitHub までどうぞ。

https://github.com/yoshi389111/kinokobooks

誤字・脱字などあったら、プルリクください。
機械学習 混合行列について

○この記事の要点
2,3回勉強しているのに、混合行列が覚えられません。
覚えるためにコードとともにアウトプットします。

#○ソースコード(Python)

```ruby:混合行列のテスト用
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
import numpy as np

# 乳がんデータのダウンロード
data = load_breast_cancer()
X = data.data
# ラベルの0と1を反転（データセットは0が悪性、1が良性だが、0を良性、1を悪性と扱いたい）
y = 1 - data.target
X = X[:, :10]

# ロジスティック回帰モデル
model = LogisticRegression()
# 学習
model.fit(X, y)
# 予測
predict = model.predict(X)
# 混合行列の表示用インスタンス
cm = confusion_matrix(y, predict)
```


#混合行列
```ruby:結果
print(cm)
[[337  20]
 [ 30 182]]
```
左上から右へ順にTN、FP、FN、TP
TN：実際にはネガティブのデータを正しくネガティブと予測したもの
　　今回の例だと、良性のデータを正しく良性と予測したもの
FP：実際にはネガティブのデータを間違えてポジティブと予測したもの
　　今回の例だと、良性のデータを間違えて悪性と予測したもの
FN：実際にはポジティブのデータを間違えてネガティブと予測したもの
　　今回の例だと、悪性のデータを間違えて良性と予測したもの
TP：実際にはポジティブのデータを正しくポジティブと予測したもの
　　今回の例だと、悪性のデータを正しく悪性と予測したもの
がんの予測としては、FN（悪性のデータを間違えて良性と予測したもの）はやばい。

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

```math
正解率 = (TP + TN) / (TP + TN + FP + FN)
```
```ruby:正解率
accuracy_score(y, predict)
0.9121265377855887
```

# 適合率 
ボジティブと予測したものに対し、正しくポジティブと予測できたものの割合

```math
適合率 = TP / (TP + FP)
```
```ruby:適合率
precision_score(y, predict)
0.900990099009901
```

# 再現率 
ボジティブのものに対し、正しくポジティブと予測できたものの割合

```math
再現率 = TP / (TP + FN)
```
```ruby:再現率
recall_score(y, predict)
0.8584905660377359
```

# F値
適合率と再現率の両方の傾向を反映させた値

```math
F値 = 2×(適合率×再現率)/(適合率+再現率)
```
```ruby:F値
f1_score(y, predict)
0.8792270531400966
```

■感想
・毎回定義を読むたび納得するのだが、しばらくすると忘れる。。。
・実際に使う時にパッと出てくるようにしないと。。。
SwiftUI 4泊5日の旅（3日目：実装例① GridLayout）

# はじめに
[前回](https://qiita.com/knagauchi/items/24d2b1ab8718270aef92)まではSwiftUIの基礎でしたが、今日から3日間は汎用的に使えそうなレイアウトを作っていきます。

# グリッドレイアウト
今日はタイル状の見た目です。フォトギャラリーなんかでよくあるやつです。
<img width="565" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277107/5b40216a-c356-e1a5-178e-562dbcc3f4ce.png">

```Swift:ContentView.swift
import SwiftUI

// 表示モデル
struct Cell: Identifiable {
    let id = UUID()
    let imageName: String
}

// 配列を数個ずつ区切る拡張関数
extension Array {
    func chunk(into columnCount:Int) -> [[Element]] {
        var chunkedArray = [[Element]]()
        for index in 0...self.count {
            if index % columnCount == 0 && index != 0 {
                chunkedArray.append(Array(self[index - columnCount..<index]))
            } else if(index == self.count) {
                chunkedArray.append(Array(self[index - (index % columnCount)..<index]))
            }
        }
        return chunkedArray
    }
}

// 本体
struct ContentView: View {
    var body: some View {
        let cells = [Cell](repeating: Cell(imageName: "tonionagauzzi"), count: 20)
        let chunkedCells = cells.chunk(into: 4)
        return List {
            ForEach(0..<chunkedCells.count) { index in
                HStack {
                    ForEach(chunkedCells[index]) { cell in
                        Image(cell.imageName)
                            .resizable()
                            .scaledToFit()
                    }
                }
            }
        }
        .edgesIgnoringSafeArea([.leading, .trailing])
        .padding(EdgeInsets.init(top: 0, leading: -20, bottom: 0, trailing: -20))
    }
}

// プレビュー
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

```
配列の要素数を変えても↓いい感じの見た目に調整してくれます。
<img width="640" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277107/9e09417f-b14a-f452-ff19-315673cd0335.gif">

これでコード量は50行に満たないので、UIKitでゴリゴリ作るより間違いなく早いですね。
Xib、Storyboardよりバージョン管理しやすいのも特長です。
とはいえネストが深いと1階層変えるだけでとんでもないDiffになるので、バージョン管理の悩みは尽きませんが…

ちなみに[QGrid](https://github.com/Q-Mobile/QGrid)とかを使うと、もっと綺麗なレイアウトを簡単に作れます。

# 最後に
[次回](https://qiita.com/knagauchi/items/b62d8fc272ca6ec65f92)はもっと複雑なレイアウトを、同じくらい短いコードで実現するのが目標です。
やっと追いついた。今日も心の中では旅を満喫しています。
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277107/209190e9-24bc-0f6e-3cd5-5eaedb5a9f1e.jpeg">
お昼は山形の冷たい肉そばをいただきました😋
<img width="480" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277107/e54391ad-9e1a-f5d9-69d0-c4ae86cd7a8d.jpeg">
夜は仙台名物牛タン。乾杯！[Prost](https://www.oktober-fest.jp/song.html)！！(🏎)
※写真は2017年GW旅行のものです
AppSyncをクライアントで動かす（mutation編）

# はじめに

今日は[GWアドベントカレンダー](https://gw-advent.9wick.com/calendars/2020/89)の６日目です。[昨日](https://qiita.com/ufoo68/items/6c4ee4ffebf20fbd7d36)はquery（`allItem`）を実装したので今日はmatation（`addItem`）を実装してアイテムの追加ボタンをつくります。

# 実装

といってもクソ簡単です。`addItem`はクエリ変数が必要となるので、昨日の`API.graphql()`を以下のように拡張させます。

```javascript
await API.graphql(graphqlOperation(addItem, { item: { data: 'hogehoge' } }))
```

単純に横にオブジェクトを追加するだけです。クエリ変数の書き方ですが、[最初](https://qiita.com/ufoo68/items/cff4e8c2ead1f62ed2a9)に書いたスキーマ↓より、

```graphql
input ItemInput {
    data: String!
}

type Mutation {
    addItem(item: ItemInput!): Item
}
```

`addItem`は`item`という`ItemInput`型の引数を必要としています。なのでフィールド名を`item`に合わせます。その中の値を`ItemInput`に合わせたいので`data`というフィールドを持つオブジェクトの値にします。
最終的に全体のコードはこんな感じになりました。

```javascript
import React, { useState } from 'react'
import { useEffectAsync } from '@availity/hooks'
import { API, graphqlOperation } from 'aws-amplify'
import { allItem } from './graphql/queries'
import { addItem } from './graphql/mutations'

const App = () => {
  const [item, setItem] = useState([{
    id: '',
    data: '',
  }])
  const [inputItem, setInputItem] = useState({
    data: '',
  })
  useEffectAsync(async () => {
    const result = await API.graphql(graphqlOperation(allItem))
    setItem(result.data.allItem)
  })

  return (
    <div>
      <input value={inputItem.data} onChange={(e) => setInputItem({ data: e.target.value})} />
      <button onClick={
        async () => await API.graphql(graphqlOperation(addItem, { item: inputItem }))
      }>
        add
      </button>
      <ul>
        {item.map(i =>
          <li>
            {i.data}
          </li>
        )}
      </ul>
    </div>
  )
}

export default App
```

雑な実装ですが、hooksの範囲だけで簡単にAPIの実装（queryとmutation）ができました。こちらで[デモ](https://test.d6sgz8hb3xkri.amplifyapp.com/)を試すことができます。また、全体のコードは[こちら](https://github.com/ufoo68/appsync-client)で公開しています。

# さいごに

基本的にクライアントからのAPIの操作にはレスポンスから任意のデータに組み替える実装が必要になりますが、GraphQLを用いると必要に応じてクエリを書くだけでいいので実装が複雑にならないのがいいですね。
本当は次に`subscription`を実装して追加したアイテムをリアルタイムに反映させるようにしようと思っていたのですが、それをせずともレンダリングが走っているのか、毎回`useEffect`が実行されてアイテムの追加がリアルタイムで反映されているみたいですね。。。
明日が最後なのでなんかAppSyncでもう少しネタがあるか探すことにします。
Swift MkMapViewで地図アプリ作成してみた(23) ルートを探索する

#記事一覧
[Swift MkMapViewで地図アプリ作成してみた（記事一覧）](https://qiita.com/rain_00_00_09/items/3151b3faf2303fe78312)

#ルートを探索する

ルートを探索した結果、ポリラインが取得できるので、線を引く。
また、地図をルート全体が表示できるスケールに変更する。

```swift:ルートを探索する
// 探索結果のポリライン
var routePolyLine: MKPolyline!

// ルート探索
public func routeSearch() {
    // 出発地（現在位置）
    let sourcePlaceMark = MKPlacemark(coordinate: mapView.userLocation.coordinate)
    // 目的地（tapRoutePoint）
    let destinationPlaceMark = MKPlacemark(coordinate: tapRoutePoint)

    // 出発地と目的地をMKDirectionsのリクエストに設定する
    let directionRequest = MKDirections.Request()
    directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
    directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)

    // 徒歩のルートを設定する
    directionRequest.transportType = .walking
    
    // ルート探索を実行する
    let directions = MKDirections(request: directionRequest)
    directions.calculate { (response, error) in
        // エラーの場合
        guard let directionResonse = response else {
            if let error = error {
                print("we have error getting directions==\(error.localizedDescription)")
            }
            return
        }
        // 成功の場合、mainスレッドで処理する
        DispatchQueue.main.async {
            // 探索結果のポリラインの線を引く
            let route = directionResonse.routes[0]
            self.routePolyLine = route.polyline
            self.routePolyLine.subtitle = "route"
            self.mapView.addOverlay(self.routePolyLine)
                
            // 地図をルート全体が表示できるスケールに変更する
            let rect = route.polyline.boundingMapRect
            self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
        }
    }
}
```

#addOverlayで塗り潰す線の太さと色を設定する

ルート線の場合は、太さ6、緑色の線を引く。

```swift:addOverlayで塗り潰す線の太さと色を設定する
    // addOverlayした際に呼ばれるデリゲートメソッド
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        // rendererを生成.
        let myPolyLineRendere: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
        
        if ("route" == overlay.subtitle) { // subtitleで指定した文字列
            // 線の太さを指定.
            myPolyLineRendere.lineWidth = 6
            // 線の色を指定.
            myPolyLineRendere.strokeColor = UIColor.green
        }
        else {
            // 線の太さを指定.
            myPolyLineRendere.lineWidth = 5
            // 線の色を指定.
            myPolyLineRendere.strokeColor = UIColor.blue
        }

        return myPolyLineRendere
    }
```
Herokuのコンテナ を利用してデプロイしたけどエラーになったOTL

#HerokuのContainer Registryを利用してデプロイしたけど、エラーになった
デプロイ環境で安くできる環境探してたら、Herokuがコンテナを利用してデプロイできることを知ったので利用してみることに！
ローカル環境もdockerを利用していたので、めっちゃ便利と思いデプロイしたけどなんかエラーになった。。。。
いつかのためにメモしておきます。。。。
というかTeratailにも質問したけど知っている人がいなかったので、知っている方がいれば教えて欲しいです笑

##エラー内容
apacheが起動できないというエラーが出てしまう。。。

``` 
AH00543: httpd: bad user name apache
```
なんで？？？ローカルではapacheユーザー存在してたんだが、、、、
コンテナのメリットってdockerが利用できればどこでも利用できるポータビリティ性のはずでは？？？
同じイメージを利用しているのになんか、環境に差が出てしまっているだが、、、(愚痴っぽくなってしまいました。すみません。)
確かにhttpd.confに以下を記述しているのでapacheユーザがないとエラーになるのはわかる

```httpd.conf
User apache
Group apache
```

## apacheユーザーがほんとにないのか確認
```
 cat /etc/passwd | grep apache

```
確かになかった。。。
それではグループは？

```
 cat /etc/group | grep apache

```
グループもない。
それじゃ作るかと思い、Dockerfile内を以下に変更

```dockerfile:dockerfile

FROM alpine:3.10

## Packageインストール
RUN apk add --update --no-cache php7 php7-pdo_mysql php7-openssl php7-curl php7-json php7-mbstring \
    php7-apache2 php7-pdo_odbc php7-pdo_mysql php7-gd php7-pecl-apcu php7-mysqli php7-fpm php7-intl php7-phar php7-dom php7-xml php7-simplexml php7-tokenizer php7-xmlwriter php7-session apache2

COPY ./docker/app/php.ini /usr/local/lib/php.ini

## composerをインストール
COPY --from=composer /usr/bin/composer /usr/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /usr/bin/composer
ENV PATH $PATH:/composer/vendor/bin

COPY ./sample /var/www/html/sample/
WORKDIR /var/www/html/sample/
RUN composer install --no-interaction
RUN chmod -R a+w ./logs/error.log
COPY ./docker/app/httpd.conf /etc/apache2/httpd.conf

## apacheユーザー作成コマンドを追記
CMD adduser -S apache  

CMD ["httpd", "-D", "FOREGROUND"]

```

herokuにデプロイしてみた 

```:herokuコンソール
State changed from crashed to starting
AH00543: httpd: bad user name apache
```
なんかエラー出ている
そしてまた、apacheユーザーが無いエラーも出ている

apacheユーザーは作成されていないらしい。。。。
なぜかというと、herokuではルートユーザーで実行されないのが原因らしい。
herokuではデプロイ先の環境にコマンドを実行できる画面があるが、そこで確認したらrootユーザーですか？的なエラーになった。

ちょっと他の方法でapacheを起動できないか模索中です。。。。
#追記1
##とりあえずの解決方法
問題点をまとめると 
1. apacheを起動できない問題
2. apacheユーザーとapacheグループが存在しないかつユーザーを追加できない問題
3. ポート番号がheroku側は指定することができない

上記3点の問題があった、上記の問題を解決するための方法が以下になります。
今回の問題点はapacheユーザーがapacheを実行するという設定にしていたが原因であることでした。
herokuの側にデプロイするとapacheユーザーがなかった。ローカルでは存在していたため、気づかなかったが。
そして、heroku側でユーザーを追加することができないようです。
`adduser apache`をDockerfileに記述しても、実行されないため、apache実行するユーザーを変更しないかぎり実行できないという。。。。
セキュリティ的にできないようになっているのか
そのため、apacheの実行ユーザーをhttpd.confのデフォルトの`doemon`に変更することで、エラーを回避できた！
問題点3に関しては、解決してくださっていた先人がいたので、以下のリンク先の対応方法で解決できました!!
内容はランタイムの $PORT 環境変数をhttpd.confにsedコマンドで書き換えちゃうというもの。
[Heroku で Apache HTTP Server コンテナをそのまま動かそうとすると crash するのを解決したメモ](https://qiita.com/xsgk/items/d304e2907beafbf692f2)

##所感
herokuのdocker利用してデプロイはちょっと考慮しないといけないことが多いのが不便、、、
実際apacheの実行ユーザーがdoemonで良いのかかなり疑問笑
趣味のものなので、問題無いので気にしないですが。
エラーに対応しながら書いた記事なので、まとまってないですが誰かの助けになれば嬉しいです。
【Rails】ブラウザによるフォームのバリデーション機能を無効にしたい

フォームに全角で入力したメールアドレスを半角のものに正規化する機能を実装して確認してみたところ、ブラウザ側のバリデーション機能が先に作動して画像のようになりました。
<img width="700" alt="スクリーンショット 2020-05-04 19.41.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578186/510c6496-b7d4-0cf0-aedc-344c6692389c.png">

今回ブラウザ側のバリデーションは不要なので、

ビューファイルのフォーム（form_with）にブラウザ側のバリデーションを無効にする設定（novalidate）を記載しました。

```
<%= form_with model: @staff_member, html: { novalidate: true }, url: [ :admin, @staff_member ] do |f| %>
```

novalidateの設定を書き加えることでブラウザによるバリデーションを無効にするそうです。

バリデーションのエラーの表示をオリジナルのものにしたい場合に有効かもしれません。

ちなみに上記の内容はとあるRailsの書籍で紹介されていた正規化表現の項目を学習中に遭遇した出来事なのですが、サンプルコードにnovalidateの部分の記載はなく、ブラウザのバリデーションについても言及が無かったので他の読者の方がどのよう対応されているのか気になるところです。