OmniAICreator/Qiita-1.07M huggingface dataset:
UIPickerView　復習

#今回の内容
<img width="150" alt="49A6E005-5949-4824-A94F-1C846C098D91_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/94dd9cc3-5034-b9ee-98ad-2715210f21d3.jpeg">

#コードと簡単解説

## UIPickerViewとUILabel作成

```Swift:
import UIKit

class ViewController: UIViewController {

    let pickerViewContents = ["January","February","March","April","May","June","July","August","September","October","November","December"]
    
    let pickerResultLabel = UILabel()
        
    override func viewDidLoad() {
        super.viewDidLoad()
        
        pickerResultLabel.frame = CGRect(x: view.frame.minX, y: view.frame.maxY * 0.3, width: view.frame.width, height: view.frame.size.height / 5)
        pickerResultLabel.textColor = .black
        view.addSubview(pickerResultLabel)
        
        let pickerView = {() -> UIPickerView in
            
            let picker = UIPickerView(frame: CGRect(x: view.frame.minX, y: view.frame.maxY * 0.75, width: view.frame.width, height: self.view.frame.size.height / 7.5))
            pickerResultLabel.textAlignment = .center
            picker.backgroundColor = .lightGray
            
            return picker
        }()
        
        view.addSubview(pickerView)
        
        pickerView.delegate = self
        pickerView.dataSource = self
    }

}
```

## UIPickerViewDelegateとUIPickerViewDataSource

* `func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {}` では、選択肢の名前を設定

* `func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {}`では、選択肢の高さを設定  

* `func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {}`では、選択肢が選択された時の処理

* `func numberOfComponents(in pickerView: UIPickerView) -> Int {}`では、選択肢の列の数を設定

* `func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {}`では、選択肢の数を設定

```Swift:
extension ViewController:UIPickerViewDelegate{
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        
        return pickerViewContents[row]
    }
    
    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        
        return 75
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        
        pickerResultLabel.text = pickerViewContents[row]
    }
}

extension ViewController:UIPickerViewDataSource{
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
          
        return pickerViewContents.count
    }

}
```


# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
sedのデバッガ「sedsed」を使ってみる



## 概要

sed のデバッガとして sedsed というものが存在する模様.
使ってみたので書き出しておく.

・[ja.stackoverflow.com -- sedの処理を追えるようデバッグプリントを出したい](https://ja.stackoverflow.com/questions/33019/sed%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E8%BF%BD%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%83%97%E3%83%AA%E3%83%B3%E3%83%88%E3%82%92%E5%87%BA%E3%81%97%E3%81%9F%E3%81%84)

:::note info
sed 4.6 からは「--debug」というオプションがある模様

https://unix.stackexchange.com/questions/492871/any-way-to-have-a-verbose-mode-or-debug-mode-with-sed
:::


## 手順

### 1. pip でインストールする

```bash
$ pip install sedsed
```

### 2. sed スクリプトを書く

コードの内容は頻出の「連続する空行を 1行に束ねる」というものである.

ここでの要点は以下である.

・「sed」を「sedsed」に置き換える.
・「--debug」オプションを付ける.
・AnsiColor コードは煩いので「--nocolor」として無効にする.
・コード内の「EOL」〜「EOL」が sed に与えるデータである.

#### a.sh

```bash
#!/bin/bash
sedsed --debug --nocolor '
/^$/{
N
/^\n$/D
}
' <<EOL
aaaa
bbbb



cccc
EOL
```

#### 通常 sed (sedsed不使用) 時の a.sh の実行結果

次のように連続する空行 3行が、1行にまとめられている.

```
aaaa
bbbb

cccc
```

### 3. デバッグ実行する

デバッグログが出る.
読み辛いと思うが、一応デバッグログの見方を後述した.

```bash
$ ./a.sh
PATT:aaaa$
HOLD:$
COMM:/^$/ {
PATT:aaaa$
HOLD:$
aaaa
PATT:bbbb$
HOLD:$
COMM:/^$/ {
PATT:bbbb$
HOLD:$
bbbb
PATT:$
HOLD:$
COMM:/^$/ {
COMM:N
PATT:\n$
HOLD:$
COMM:/^\n$/ D
PATT:$
HOLD:$
COMM:/^$/ {
COMM:N
PATT:\n$
HOLD:$
COMM:/^\n$/ D
PATT:$
HOLD:$
COMM:/^$/ {
COMM:N
PATT:\ncccc$
HOLD:$
COMM:/^\n$/ D
PATT:\ncccc$
HOLD:$
COMM:}
PATT:\ncccc$
HOLD:$

cccc

```

### 4. デバッグログの見方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/591e8dca-c7a7-2832-dc72-228c5facde8c.png)

　

sed を使う際は、紙に パターンスペースと ホールドスペース を書き出していたので助かる.

[aureliojargas さん](https://github.com/aureliojargas/sedsed) に感謝.

　



以上.
KeyError:  Trait not registered: "　　" referenced within 　調べる→ナニコレ⇨全角を疑うこと


<h2>モデルのテスト作成中　</h2>
<h2>KeyError:  Trait not registered: "　　" referenced within 調べても全然でてこない?????</h2>

```
Failure/Error: @ostomy = build(:ostomy)

KeyError:
 Trait not registered: "　　" referenced within "ostomy" definition
````
<h2>Ans全角が４つも入っていた。。。</h2>
<p>全角入ってるんじゃないですかね?って考えられるのすごい。というか冷静に考えられるの素晴らし過ぎる</p>
TestCafeでテストに失敗したときにスクリーンショットを撮りたい

こんにちは。asatoです。
[前回](https://qiita.com/at-946/items/695ac534bb3c0fc73a55)、[spaces.bz](https://spaces.bz)というプロダクトの開発でTestCafeでテストを自動化している話をしました。

実際に開発をしていると、「え？そんなところで？」と思うようなところでテストがFailになることもあります。
TestCafeのエラーメッセージはとてもわかりやすいのですが、「そんなわけないよ！実際に画面見せろよ！」となることもありますよね。

この記事では、TestCafeでテストに失敗したときに自動でスクリーンショットを保存できるようにします！

# `-s takeOnFails=true`オプションをつけるだけ
ま、以上なんですが...

公式サイトだと、こちらに書かれております。

https://testcafe.io/documentation/402639/reference/command-line-interface#takeonfails

便利すぎやしませんか...TestCafeさん...

TestCafeの起動時に

```
$ testcafe chrome:headless -s takeOnFails=true
```

のように記載すればOKです。

# package.jsonに追記する
僕たちはNuxtで開発をしており、テストは`yarn test`コマンドで起動するようにしています。

```json:package.json
{
  "script": {
    ...略...
    "test": "testcafe chrome:headless",
    ...略...
  },
}
```

と記載していました。ここを、

```diff:package.json
- "test": "testcafe chrome:headless",
+ "test": "testcafe chrome:headless -s takeOnFails=true",
```

と書き換えるのみです。

# スクリーンショットはどこへ...？
スクリーンショットはプロジェクトのルートディレクトリに`screenshots`ディレクトリが自動で作成され、その中にテストケースごとのディレクトリが作られて保存されます。
テストケースのディレクトリには番号が振られているので、複数のテストが失敗したときでもどのテストがどのスクリーンショットなのかわかりやすいです。

[`path`オプション](https://testcafe.io/documentation/402639/reference/command-line-interface#path)を使えば、ディレクトリの場所を変えることもできるみたいですが、特にルートディレクトリにディレクトリが作成されても困っていないので指定していません。

ただ、screenshotはGitHubなどのGitサービスにあげる必要がないものなので、`.gitignore`でGitの対象から外してます。

```text:.gitignore
screenshots
```

また、新しいテストを始めるときに、古いテストのスクリーンショットが残っているとわけがわからなくなってしまうので、`package.json`で`testcafe`実行前に`screenshots`ディレクトリを削除するようにしています。

```diff:package.json
- "test": "testcafe chrome:headless -s takeOnFails=true"
+ "test": "rm -rf ./screenshots && testcafe chrome:headless -s takeOnFails=true"
```

これでステキな自動テストライフを過ごせます！🎁

# 番外編：失敗時のスクリーンショットじゃわからない...
ときもあります！なんかエラー画面が出てるだけで終わり...その直前の画面が見たい...
そんなときはテストコード内で自分でスクリーンショットを撮ることもできます！

```js
test('take a screenshot', async t => {
  await t
    .typeText('#input', 'hello')
    .takeScreenshot()
    .click('#button')
    .expect(...).eql(...)
})
```
こんな感じで、`#button`をクリックしたあとにテストが失敗してるんだけど、スクリーンショットがエラー画面でなんだかわからない...というときは、`takeScreenshot()`を使ってあげれば`#button`をクリックする直前の画面をスクリーンショットできます！
これも特に指定しなければ`./screenshots`ディレクトリの中のテストケースのディレクトリ内に、テスト失敗のスクリーンショットと分けて格納されます。
`takeScreenshot()`もパスや全画面を対象にするかを選択できますので、気になる方は公式サイトを御覧ください。

https://testcafe.io/documentation/402675/reference/test-api/testcontroller/takescreenshot

# まとめ
前回に引き続き、TestCafeについてお話しました！
テスト時のスクリーンショットは、自作しなかったりしなくてはいけないテストフレームワークもあったりするので、TestCafeはかなり手軽だなーと思います。
みなさんにステキなテストライフが訪れますように！🤞

[spaces.bz](https://spaces.bz)も応援よろしくおねがいします！🎉

https://spaces.bz
【Gradle】bomを生成する/利用する

# 概要

Gradle利用時に、独自のbomを生成したり、生成したbomを利用する方法をまとめます。
ここではBOMのpublish先としてlocal repositoryを使用します。

## 動作環境

- Gradle : 7.0.2

# 1. BOMを生成する

BOMをlocal repositoryにあげるための最低限のbuild.gradleがこちらです

```groovy:build.gradle
plugins {
    id 'java-platform' // BOM生成に必要なプラグイン
    id 'maven-publish' // maven publishに必要なプラグイン
}

group = 'rhirabay'
version = '0.0.1'

// 利用アプリケーションにデフォルトで依存を追加するために必要
// ※使用しないライブラリも依存に追加されてしまうので、注意
// javaPlatform {
//     allowDependencies()
// }

repositories {
    mavenCentral()
}

dependencies {
    // constraintsでくくることで、ライブラリとバージョンの組み合わせを制約として定義できる
    constraints {
        api 'org.projectlombok:lombok:1.18.20'
    }
}

// mavenにuploadする設定
publishing {
    publications {
        mavenJava(MavenPublication) {
            artifactId = 'my-bom'
            from components.javaPlatform
        }
    }
}
```

以下のコマンドでlocal repositoryにuploadする

```bash
./gradlew publishToMavenLocal
```

# 2. BOMを利用する

```groovy:build.gradle
dependencies {
    // BOMは「platform」でくくる
    implementation platform('rhirabay:my-bom:+')

    // BOMに定義してあるライブラリはバージョンを記載しなくて良い
    // バージョンを記載すると記載されたバージョンが優先される
    compileOnly('org.projectlombok:lombok')
}
```

`rhirabay:my-bom:+`のように最新のバージョンを使用するようにしておけば、
buildし直すだけでBOMの更新を反映することができます！

> `0.0.+`のようにmajar / minor バージョンまでを指定しておいた方が安全な気がします

# なぜBOMが必要なの？

扱っているリポジトリ（アプリケーション）が１つの場合はBOM管理をしたところで管理するものが増えるだけ。。
なので大前提として複数のリポジトリがあるものとします。

複数のリポジトリがあると

- 脆弱性対応
- ライブラリのEOL

などによって一括でバージョンを更新しなければならない場面があります。
そんな時BOM管理をしていれば
BOMでライブラリのバージョン更新すれば、アプリケーションはbuildし直すだけで良くなります！
static let とは？　数行で解説

#static let に用いられる「static」とは
型のインスタンスではなく、
型自身に結びついているプロパティである。

同じstructからできた、インスタンス間で
同じプロパティの値を保持することが可能である。

スタティックプロパティは、宣言時に必ず初期値をもたせる必要がある。
持っていなければ、エラーが生じる。


##注意点は二点
・最初の宣言時に値を持たせる必要性がある。
・型自身に結びついているので、

```
構造体.スタティックプロパティ
```

で呼び出しが可能


###勉強したことをすぐ忘れるので、記しておきます。
AtCoderログ：0116 - ABC 149 C

# 問題

https://atcoder.jp/contests/abc149/tasks/abc149_c

## 問題文
> $X$ 以上の素数のうち、最小のものを求めよ。

## 制約
> ・$2 \le X \le 10^5$

## 収録されている問題セット
- [AtCoder Problems Boot camp for beginners Easy 100](https://kenkoooo.com/atcoder/#/training/Boot%20camp%20for%20Beginners/1) [#021]

# 回答
## 回答1 (AC)
自然数 $x$ が素数であるとは、$x$ が $1$ と $x$ 以外の自然数では割り切れないということです。そこで $x$ に対して $i=2,3,\dots,x-1$ で割り切れるかどうかを確認し、割り切れた場合には $x$ を1増加させる、という戦略が考えられます。コードは以下のようになりました。

```C++:abc149c-1.cpp
#include <bits/stdc++.h>
using namespace std;

int main(){
  int x;
  cin >> x;

  int i;
  while ( true ) {
    for ( i=2; i<x; i++ ) {
      if ( x%i==0 ) {
        break;
      }
    }
    if ( i==x ) {
      cout << x << endl;
      break;
    }
    x += 1;
  }
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc149/tasks/abc149_c/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2020/01/01/024215)
素数を生成する関数を利用していました。

## [AtCoder の解説](https://atcoder.jp/contests/abc149/tasks/abc149_c/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/abc149/editorial.pdf)
回答2と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0115 - ABC 116 B](https://qiita.com/drafts/8ea9ea5e1a1a48f142e8/edit)
SIer系業務経歴書出力 サーバレスWebアプリをSPA + REST APIで作ってみた。

##説明
自分はSIerに努めています。
Excelで作成した業務経歴書を使い、今までどんな仕事をしてきたかという面談を行うのですが、
最近の流行？技術勉強がてら、Excelを利用せずともWeb(SPA + REST API)で業務経歴書出力が出来るアプリケーションを作って見ました。

[サイト：https://poc-s3-business-history-bk.s3-ap-northeast-1.amazonaws.com/index.html](https://poc-s3-business-history-bk.s3-ap-northeast-1.amazonaws.com/index.html)

お試しログインアカウント(データ登録可)
ユーザID:  bizoto@nekochan.fr
パスワード：Ztest@987+

##構成図

下記のような、シンプルな構成です
![構成図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/4169401e-ab2d-8e1e-6f9c-5fbed5fb48cc.jpeg)

###他の利用技術
Python   v3.8
Angular v11
VSCode
Serverless Framework v2 (構築は全てこれで作成)

##画面イメージ
  ![画面イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/ce9a19e8-e1b0-424f-61fb-b5e3857c7d90.jpeg)

##PDFイメージ
  (1) イニシャル＋企業名なし
![印刷イメージ_イニシャル＋企業名なし.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/280a9cad-3434-8d0f-9c11-4ec3bbeebda1.jpeg)
　(2)  実名＋企業名あり
![印刷イメージ_実名＋企業名あり.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/4833027b-2e66-3cce-df07-80217d1cf6ca.jpeg)

##配慮した箇所
1. 面談時などに利用しやすいように
   PDF出力タイミングで下記項目内容の切替が可能
　・名前を実名とイニシャルの切替
　・社名表示、非表示の切替
![特徴1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/c73aaa4d-331e-518f-b1bf-022cdd4de591.jpeg)
![特徴1_社名.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/daa1ca68-acfb-f8ad-70e9-ec65ac309648.jpeg)

2. 右上の出力日が指定でき、出力日基準で年齢計算を自動で行います。
![特徴3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538267/e004c73c-a6f6-d53b-ca35-ea32791edfd4.jpeg)

3. 業務経歴年数の自動計算や、技術のサマリ表の表示
   ・得意技術、アピールポイントの明確化
　　(技術は、一番年数の多いもの順にソートされます)

4. 出力するPDFファイルは、サーバに保存しません
   ・S3に一時保存されていて他の人に見えちゃうなどの心配はないです。
   ・こちら側の理由としては容量で課金されちゃうので保存したくないです。

5. Webアプリケーションなのでその場でちゃちゃっと修正して再出力可能です。

## 一旦、なんとなく動作するレベルまで終えて
1. 技術的にはPythonを少々というレベルから今回の開発を行ったため、AWSの勉強、TypeScript, Angular, Cognitoの勉強などにとても大変でした。ただ最近はGoogleで検索すると、やりたい事がすぐ見つかる有難い世の中なのでそれなりに時間短縮は出来たと思いますが、本当に技術が身に付いたかと言われると・・・です。
2.  Angularの非同期制御まわりがいまいちな気がしていますが、ちょっとこっちを直すとあっちがうごかなくなったり微妙なバランスを保っているため、修正はそれなりの覚悟がいるためちょっと躊躇しています。
3. 1人で利用するならこれで大丈夫だと思いますが、まだ拡張したい所もあります。
   企業として利用する場合、権限で全員のユーザを閲覧したりPDF化出来たりする機能が足らないです。
   それはそんな事を希望する企業が本当に現れたら本気で考えようと思います。

## 最後に
 誰かがこの経歴書を利用して良案件に参画したり、良い転職に巡り合えたら幸いです。

## 参考サイト
[[Angular] base64 文字列をバイナリに戻してダウンロードする] (https://qiita.com/ksh-fthr/items/b3e3afb7f8e51759a1ed)
などなど
peclが中々インストールできなかったMac

# phpインストールしなおしても入らなかった
phpが既に入っていても`brew`で入れ直さないとだめ、という記事を見て実施。
すごく時間かけて`php@7.3`をインストールしなおしましたが結局peclは入らず。

# これで解決

```
$ brew link --force php@7.3
$ pecl install --force xdebug
$ brew unlink php@7.3
```
# 上のでエラーが出たら
peclインストール（２行目コマンド）でエラーが出ました。

```
ERROR: failed to mkdir /usr/local/Cellar/php@7.3/7.3.30/pecl/20180731
```
シンボリックリンクを貼ってますが、元の方の該当ディレクトリがないよってことらしいので作成してあげます。

```
$ mkdir -p /usr/local/lib/php/pecl/yyyyMMdd
$ pecl install --force xdebug
$ brew unlink php@7.3
```
これでOK！
Dartでint型Listの昇順/降順ソート

### 確認環境
- OS: Windows 10 Pro
- Dart: 2.7.2[^1]

### 昇順ソート

`sort()`メソッドを使うとデフォルトで昇順ソートされる

```dart
final list1 = [4, 1, 2, 3];
list1.sort();
print(list1); // -> [1, 2, 3, 4]
```

### 降順ソート

#### 素直にComparetorを使うパターン

`sort()`メソッドのデフォルトが、`a.compareTo(b)`の結果(-1,0,1)で大小比較しているので、それに-1を掛けたものをComparetorとして渡してあげれば逆順になる

```dart
final list2 = [4, 1, 2, 3];
list2.sort((a,b) => -1 * a.compareTo(b));
print(list2); // -> [4, 3, 2, 1]
```


#### 昇順ソート後にreverseするパターン

昇順ソート後に`reversed`の値を取得することでも逆順のリストが得られる(無駄なことしてる感はあるけど)[^2]

```dart
final list3 = [4, 1, 2, 3];
list3.sort();
print(list3.reversed.toList()); // -> [4, 3, 2, 1]
```

ちなみに`sort()`は値を書き換えるけど`reversed`は書き換えない

```dart
print(list3);                   // -> [1, 2, 3, 4] 
```

### 参考

[sort method \- List class \- dart:core library \- Dart API](https://api.dart.dev/stable/2.7.2/dart-core/List/sort.html)

[^1]: 確認時点の最新(2.14.2)のドキュメントもそれほど中身変わってなかったので問題なく動くとは思う -> [sort method \- List class \- dart:core library \- Dart API](https://api.dart.dev/stable/2.14.2/dart-core/List/sort.html)

[^2]: compareToが分かりづらいと思ってしまう人間なので、逆順にする程度の単純なソートであればむしろこっちの方がぱっと見で何してるのか分かりやすいと個人的には思ってしまう。(見易さだけで言えば)
イントロスペクションについて（オブジェクトの調査)

**pythonの本を読んでいたら、イントロスペクションという単語が急に出てきたので、ネットで調べたものをまとました。**
#イントロスペクションの意味
英語ではintrospectionと書かれ、日本語で「内省」と訳されます。あまり生活にはなじみのない単語ですが、辞書を引いてみると内省は「自分自身の思考や振る舞いについて深く考えること」と書かれています。

プログラミング言語においてのintrospectionは、**プログラムの実行時にオブジェクトの性質や型を調べること**です。
プログラミング言語で書かれたオブジェクトについて内省することだと私は解釈しています。
イントロスペクションは多くのプログラミング言語に実装されています。
#リフレクション(reflection)との違い
似たような意味としてリフレクションが存在します。
リフレクションは、プログラムの実行時にオブジェクトの値、メタデータ、性質、関数を操作することです
#例(python)
pythonは全てがオブジェクトなので、イントロスペクション機能を持つ関数を使うことで多くの事を調べることができます。
イントロスペクション機能を持つ関数の中で最も強力なのがdir()です。

``` .py
class Sample():
    def __init__(self, number):
        self.value = number
    def tenfold(self):
        return self.value * 10
a = Sample(10)
print(dir(a))
```
```  出力.py
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', 
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
 '__str__', '__subclasshook__', '__weakref__', 'tenfold', 'value']
#dir()はオブジェクトの有効な属性のリストを返した

```
またdir()の他にも、type()やisinstance()はそのオブジェクトの型が何なのか調べることができ、hasattr()はオブジェクトの属性を調べることができます。
よって、上に挙げた関数もイントロスペクションの機能を持つ関数であると言えます。
#文献(これを見た方が速い)
Pythonで最も役立つ5つのイントロスペクション関数
使用しているタイプについて詳しく知るための関数
https://ichi.pro/python-de-mottomo-yakudatsu-5-tsu-no-intorosupekushon-kansu-123716058980097
Python / 内省的(introspective)とはどういうことか
https://hanepjiv.blogspot.com/2014/11/python-introspective.html
https://en.wikipedia.org/wiki/Type_introspection
#最後に
始めて投稿したので、指摘などがあれば遠慮なくしてください。
この記事に反応があればさらに追記したいと思います
健康診断の値eGFRをExcelを使ってクレアチニン値から計算する

# eGFRとは
eGFRとは腎臓の働きを調べる値です。
多くの医療施設で腎臓の機能を表す値ととして使われています。

eGFRは血液生化学検査のクレアチニンの値と年齢性別を使って計算します。

## 計算式
男性
eGFR = 194 * Cr^-1.094 * Age^-0.287

女性
eGFR = 194 * Cr^-1.094 * Age^-0.287 * 0.739

で計算します。詳細は 日本腎臓学会の以下の資料を参照。
https://jsn.or.jp/guideline/pdf/CKDguide2012.pdf

## Excelで計算する

|   |  A  |  B  |  C  |  D  |
| ---- | ---- | ---- | ---- | ---- |
| 1 |  年齢  |  クレアチニン  |  性別  |  eGFR  |
| 2 |  54 |  0.74  |  1  |=194*POWER(B2,-1.094)*POWER(A2,-0.287)*IF(C2=2,0.739,1)  |

* 性別は 1=男性、2=女性

## エクセルをgithubに置きました
https://github.com/sugie/egfr_excel


## メモ

クレアチニンは筋肉で作られる老廃物。腎臓の糸球体で濾過されて尿として排泄される。腎臓の働きが弱くなると排泄されるクレアチニンの量が減ってeGFRの値が小さくなる。

詳細は共和キリンのウェブに詳しい説明があった。
https://www.kyowakirin.co.jp/ckd/check/check.html
visual studioでQt環境構築

#目的
C++でGUIをいじりたい→Qt環境を構築しよう→visual studioで構築したい

#Qtのインストール
①[インストーラーのダウンロード](https://www.qt.io/download-open-source?hsCtaTracking=9f6a2170-a938-42df-a8e2-a9f0b1d6cdce%7C6cb0de4f-9bb5-4778-ab02-bfb62735f3e5)

②アカウントの登録
③Componentの取得
以下のものを取得しました。現在最新のQt6.1.3のMSVC 2019 64-bitはなぜかbuildエラーになるのでバージョンを下げました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/f8eaf91e-2dab-4315-0a44-79dee1e375e7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/d11d4d52-96c7-afa7-4666-113d19ce7943.png)


#visual studio側の準備
Qt visual studio Toolsを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/0eed1d6d-c253-7a6f-c4ae-a10a7212b425.png)

拡張機能→Qt VSTools→Qt Versionsでqmake.exeのパスを入力します。これでビルドできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/caa3c6d5-aaf3-43cd-bc04-59c499dbaf05.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/0b35f25c-31ce-0152-9821-f12e1652daec.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/083eebde-c028-0f53-b06b-8cffe9ee5625.png)


#Qtプロジェクトの作成
Qt Widgets Applicationを選択→QWidgetを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/5044ca00-2848-162f-0902-43938a3b0e9e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/ccd00e42-391a-2dc2-2cf8-779471a9000f.png)

.uiファイルを選択してウィジットボックスから好きなWidgetを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/812db6fb-8058-a90a-eff3-cfea72ae4203.png)

closeボタンを押したときに動作する関数を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/babdd93c-d0ac-4989-cd9b-5c7b0c47c140.png)

ビルドして実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/3c34b97c-0392-2cd0-e8c0-119c5400a321.png)

おわり
SQLのインデックスの仕組みについて

今までカラムにインデックスを盲目的に貼っているだけだったが、ひょんなことからその仕組みが気になったのでまとめた

# インデックスとは
## ググってみて出てきたもの
インデックスとは、データの検索速度を向上させるために、どの行がどこにあるかを示した索引のこと
　うーん😔　わかりにくい
## 実際に何やってるの？？
あるカラムに対して、辞書順、数値順にデータを整理している

整理前のDB
![スクリーンショット 2021-09-18 21.16.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617092/5032aad3-d69b-9848-c1bb-9335e0258a83.png)

整理後のDB(nameにインデックスを貼った)
![スクリーンショット 2021-09-18 21.17.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617092/6bf5cf5b-4e31-d511-bd44-3ecef9081595.png)

nameが辞書順になっている！

## 気になったこと
辞書順になっててももし極端な話zから始まるものを探そうとしたらO(N)かかってしまい、Nによってはパフォーマンスが悪くなるのでは？？

## 気になったことへの解決
結論　インデックスを貼られたカラムのデータ構造はBTree もしくはB+Tree構造になっており、探索にかかる計算量はO(logN)になりかなり計算スピードが抑えられる！！

## Btreeとは？？
このような木の構造をしているデータ構造のこと　木構造については[こちら](https://e-words.jp/w/%E6%9C%A8%E6%A7%8B%E9%80%A0.html)
![20200512105138.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617092/7370f370-42a8-48f8-8e84-61c231ed9e43.png)

探索の際にまず中央の数字を見て、その数より検索対象の数が大きければ右の木に、小さければ左の木にとどんどん検索対象を小さくできる。よってデータ構造をBTreeやB+Treeにしておけば、計算量がO(logN)とかなり抑えられ、非常に効率的に探索できるようになるというわけ

### 補足　BtreeとB+Treeの違い
 - B+Treeは末端の場所（リーフノードと言います）に全ての要素が集結している。ので範囲検索が早い


 - また、リーフノード以外のノードはデータの実態を持っておらず実際のデータを持っているのは末端のリーフノードのみという違いがある。

MongoDBはBtreeを採用しており、MySQLのinnnerDBはB+Treeを採用しているという違いもある
[OutSystems]GetEntryEspaceName/Id()の動作を確認する

OutSystemsで、Actionの呼び出し元を取得する方法として、組み込み関数のGetEntryEspaceNameとGetEntryEspaceIdというものがあります。

関数名が示唆する通り、ユーザーのリクエストの起点となるモジュールの名前やIDを返すものです。
残念ながら、起点となるモジュールと関数呼び出しの間に別のモジュールが挟まる場合、中間のモジュールを知ることはできないようです。

# 確認環境
Personal Environment(Version 11.13.0 (Build 31107))
Service Studio (Version 11.12.0)

# まとめ
組み込み関数のGetEntryEspaceName/GetEntryEspaceIdは、ユーザーがリクエストを直接行うモジュールの名前/Idを返す。間に別のモジュールのServer Actionを経由しても同じ。

ただし、間にService ActionやREST APIを挟んだ場合は、そちらのモジュールの名前/Idを返す。


# 確認するAPIについて
Built-in Functionに含まれる以下のAPIを試してみます。
[ドキュメント - Built-in Functions > Environment](https://success.outsystems.com/ja-jp/Documentation/11/Reference/OutSystems_Language/Logic/Built-in_Functions/Environment#GetEntryEspaceName)

## GetEntryEspaceName
> Webリクエストを処理しているモジュールの名前を返します。

と言う仕様です。リクエストの起点となるモジュールのNameプロパティの値が帰ってくる。

## GetEntryEspaceId
> Webリクエストを処理しているモジュールの識別子を返します。

が仕様。リクエストの起点となるモジュールのIdが返ってくる。このIdは（System)モジュール > Espace EntiryのIdプロパティの値。

## APIを呼び出すActionの実装 (テスト用Action）
以上のAPIを以下の式で利用し、結果を返すActionを実装。
2つのAPIを順番に呼び、結果を改行で区切る形で整形しています。

```
"GetEntryEspaceId(): " + GetEntryEspaceId() + NewLine() +
"GetEntryEspaceName(): " + GetEntryEspaceName()
```

# 基本：ユーザーがリクエストした画面のモジュールが返る
Reactive Web Appの画面でリクエストして、Producerモジュールで関数呼び出しをすると、画面が所属しているモジュールの名前とIdが取れます。

以下の構成のモジュールを作って動作確認してみました。
各四角形がモジュールを示しています。結果として、いずれの場合でもConsumerモジュールの値が返ってきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/75c22455-b7a6-9ad6-b0e3-8f84a8d5f981.png)

## ①別モジュールのServer Action経由でテスト用Actionを呼ぶ場合
（Screen Action > Producer1モジュールのServer Action > Producer2モジュールのテスト用Action）
結果。Screen Actionが所属するモジュール名/Idが返ってきている。

```
GetEntryEspaceId(): 224
GetEntryEspaceName(): Consumer
```

## ②同モジュールのServer Action・別モジュールのServer Action経由でテスト用Actionを呼ぶ場合
（Screen Action > Consumerモジュールの別のServer Action > Producer1モジュールのServer Action > Producer2モジュールのテスト用Action）
結果は以下の通り。Screen Actionが所属するモジュール名/Idが返ってきている。

```
GetEntryEspaceId(): 224
GetEntryEspaceName(): Consumer
```

## ③別モジュールのClient Action経由でテスト用Actionを呼ぶ場合
（Screen Action > Producer1モジュールのClient Action > Producer2モジュールのテスト用Action）
結果。Screen Actionが所属するモジュール名/Idが返ってきている。ここはちょっと意外ですね。Webリクエストとのことなので、Server Action呼び出しになる部分が返ってくるかと思いきや、最初のConsumerモジュールの部分が返ってきました。

```
GetEntryEspaceId(): 224
GetEntryEspaceName(): Consumer
```

# Service Actionを経由する場合
①と同じパターンで、Producer1のServer Actionの代わりにService Actionを経由させてみます。
この場合、Service Actionは、内部的にREST APIなので、Service Action呼び出しの部分が呼び出しの起点とみなされるのではないかという考えから。

以下が結果。想定通り、Service Actionが起点とみなされ、Service Actionが所属するモジュールが返ってきています。呼び出し元のReactive Web Appでないことに注意が必要です。

```
GetEntryEspaceId(): 587
GetEntryEspaceName(): Producer1
```

# Expose REST APIを経由する場合
①と同じパターンで、Producer1のServer Actionの代わりにExpose REST APIを経由させてみます。Service Actionと同じ結果になることが想定されます。

以下が結果。想定通り、Expose REST APIが起点とみなされ、REST APIが所属するモジュールが返ってきています。呼び出し元のReactive Web Appでないことに注意が必要です。

```
GetEntryEspaceId(): 587
GetEntryEspaceName(): Producer1
```
【Rails】scaffoldについて

# はじめに
これまでの学習では

```ruby
rails g model 
rails g controller
```

を使用し、モデル、コントローラーを作成していました。
rails tutorialを復習する中で、
scaffoldを再度使用したので、備忘録として。

# やったこと

いつもの上記コマンドを

```ruby
rails g scaffold
```

に置き換えて実行。

今回はUserモデルと関連するコントローラーなどを作成。

```ruby
rails g scaffold User name:string email:string
```

を実行。

そして作成されたファイルが

```ruby
      invoke  active_record
      create    db/migrate/[作成日時]_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      create      test/system/users_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      create      app/views/users/_user.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss
```

ビューまでしっかりと作成されました。

# 終わりに
とても便利に見えるscaffoldですが、不要なものまで作成されてしまうなと感じました。
確実に使う場合は良いですが、私の場合は今まで通りmodel, controllerを作成した方が
ファイルがスッキリするのかなといった印象です。
もっと便利な使い方があるかもしれないので、もう少し調べていこうと思います。

# 参考
scaffoldの使用方法について参考にさせていただきました。

https://udemy.benesse.co.jp/development/system/scaffold.html
【devise】サインイン・サインアップ後マイページに遷移する方法

#deviseでサインイン・サインアップ後マイページに遷移する方法
###遷移先を指定する方法
サインインの際は`application_controller.rb`で、サインアップの際は`registrations_controller.rb`でコードを記述します。

```application_controller.rb
class ApplicationController < ActionController::Base

#サインイン後の遷移先を指定する方法
  def after_sign_in_path_for(resource)
    ○○_path　#遷移先のパス
  end

end
```

```registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController

#サインアップ後の遷移先を指定する方法
  def after_sign_up_path_for(resource)
    ○○_path　#遷移先のパス
  end

end
```

###サインアップ後マイページに遷移するように設定する
```registrations_controller.rb

  def after_sign_up_path_for(resource)
    user_path(current_user.id)
  end
```
`user_path`の後に`(current_user.id)`と記述することで、現在ログインしているユーザーのマイページへ飛ぶようになります。

```
user_path(current_user.id)
```
Yahoo!のキーフレーズ抽出API(v2)のPHPサンプルプログラム

Yahooが提供するキーフレーズ抽出APIがありますが、つい最近V2にバージョンアップされました。このAPIを利用されている方も多いと思いますが、2022年1月末に廃止予定とのことで早急に移行しないとなりませんが、V1にあったPHPのサンプルプログラムがV2ではPythonのみとなっています。

いろいろ試行錯誤してサンプルプログラムを作りましたので公表します。
すでに利用している人向けのドキュメントですので「どうやったら利用できるか？」などの基本的な話はここでは取り扱いません。

# ソース

```PHP
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <?php

    $appId = "your app key";
    $url = "https://jlp.yahooapis.jp/KeyphraseService/V2/extract";
    $word = "秋葉原から国立競技場に行くには末広町駅から東京メトロ銀座線に乗車して外苑前駅で降ります";

    $headers = [
        "Content-Type: application/json",
        "User-Agent: Yahoo AppID: ".$appId,
    ];
    
    $data = array(
        "id" => "1234-1",
        "jsonrpc" => "2.0",
        "method" => "jlp.keyphraseservice.extract",
        "params" => array(
        "q" => $word
        )
    );
    $data = json_encode($data);

    //XMLの解析
    $curl = curl_init($url);
    $options = array(
        // HEADER
        CURLOPT_HTTPHEADER => $headers,
        // Method
        CURLOPT_POST => true, // POST
        // body
        CURLOPT_POSTFIELDS => $data,
        // 変数に保存。これがないと即時出力
        CURLOPT_RETURNTRANSFER => true,
        // header出力
        CURLOPT_HEADER => true, 
    );
    
    //set options
    curl_setopt_array($curl, $options);
    //取得
    $response = curl_exec($curl);

    //ヘッダー取得
    $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); 
    //ヘッダー切り出し
    $header = substr($response, 0, $header_size);
    //BODY切り出し
    $body = substr($response, $header_size);
    //JSONに変換
    $body = json_decode($body); 

    curl_close($curl);
    print_r($body->result->phrases);

?>
</body>
</html>
```
#リンク
 + [【重要】かな漢字変換・ルビ振り・校正支援・キーフレーズ抽出API V2 リリースのお知らせ
](https://developer.yahoo.co.jp/changelog/2021-09-09-jlp.html)
 + [キーフレーズ抽出（V2） - Yahoo!デベロッパーネットワーク](https://developer.yahoo.co.jp/webapi/jlp/keyphrase/v2/extract.html)
コンパイルが必要な言語とは？

# はじめに
Javaしか知らない自分が、C#でコーディング始めてふと思いました。
あれ、C#って事前にコンパイル必要だよね？
じゃあほかのプログラミング言語はどうなんだろ？
と気になったので調べました。

# そもそもなぜコンパイルが必要か
人間が書いたソースコードはコンピューターには分からないのでそのままだと実行できません。
そこでコンピュータが解釈できる機械語に変換する＝コンパイルする必要があります。

# コンパイルが必要な言語は？
プログラミング言語はコンパイルが必要です。
勘違いしていたのですが、マークアップ言語はプログラミング言語ではありません。
例えばHTMLはコードをブラウザが解釈し、WEBページを表示させています。

### マークアップ言語
* コンパイルは不要。
* 代表的な言語：HTML、XML、XHTML

# プログラミング言語
コンパイラ言語、インタプリタ言語などがあります。
これらは事前コンパイルの要否に違いがあります。

### コンパイラ言語

* 実行をする前に、一括ですべてのコードを機械語もしくは中間言語に変換が必要。
* 事前にコンパイルを行うため、実行時の処理速度は他の形式の言語と比較して速い。
* 代表的な言語：Java、C#、C / C++

### インタプリタ言語
* 事前コンパイルが不要で、実行時にコードを一行ずつ機械語に変換する。
* 実行時にコンパイルするので、コンパイラ言語に比べると処理速度が遅い。
* 代表的な言語：Ruby、JavaScript、Python

### スクリプト言語
* 簡単に書ける、簡単に実行できる、などの扱いやすさで定義されている
* インタプリタ言語が多い。
* コンパイラ言語を含むことがあるので、インタプリタ言語とイコールではない。
* 代表的な言語：PHP、Ruby、JavaScript、Python

# おわりに
スクリプト言語の分類がいまいちわからなかったです。
新しい言語がどんどん出てくる中で、単純に分類できるものでもなくなっていると感じました。
【Vue.js】mapヘルパーの使い方まとめ

#はじめに
Vuexのmapヘルパーについて、使い方をまとめます。
mapヘルパーに関する記事はいくつかあります。
しかし、引数を渡したり、jsファイルをモジュールに分割している場合の記述方法について、確りまとめられた記事がなかったため、本記事を作成しています。

#mapヘルパーを使用するメリット
mapヘルパーを使用することにより、コードがすっきりとして可読性が向上し、効率の良い記述が可能です。

mapヘルパーは4種類存在します。
①mapState
②mapGetters
③mapMutations
④mapActions

この内、①mapState、③mapMutationsは下記の理由により、使用することはあまりないかと思います。

①mapState・・・stateを直接参照することは非推奨である。あまり使用するべきではない。
③mapMutations・・・mutationsはactionsから呼び出すのが望ましい。

#mapActions
<br />
**「index.js」のactions内の関数を呼び出す。**

```javascript
import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(["increment", "incrementBy"]),
  },
};
```
<br />
**「hoge.js」のactions内の関数を呼び出す。**

```javascript
import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions('hoge', ["increment", "incrementBy"]),
    ...mapActions(['decrement'])//index.jsのactionsを呼び出す。
    ...mapActions('hoge/hoge', ['decreamentBy'),//hogeディレクトリのhoge.jsのactionsを呼び出す。
  },
};
```
<br />
**「hoge.js」のactions内の関数に引数を渡す。**
　※関数名に注意！

```javascript
import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions("hoge", ["incrementActions", "incrementByActions"]),
    increament() {
      this.increamentActions(引数);
    },
    //オブジェクトも渡せる
    incrementBy() {
      this.incrementByActions({
        a:1
        b:2
      })
    }
  },
};
```

#mapGetters
<br />
**「index.js」のgettersの値を参照する。**

```javascript
import { mapGetters } from 'vuex'
export default {
 computed: {
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
    ])
  }
}
```

<br />
**「hoge.js」のgettersの値を参照する。**

```javascript
import { mapGetters } from 'vuex'
export default {
   computed: {
    ...mapGetters('hoge', [
      'doneTodosCount',
      'anotherGetter',
    ]),
    ...mapGetters('hoge', ['notDoneTodosCount'])//hoge.jsのgettersを参照
    ...mapGetters('hoge/hoge', ['hogeGetter'])//hogeディレクトリのhoge.jsのgettersを参照
  }
}
```

#メリット
mapヘルパーを使っていて、いいな！と思ったのは、モジュールのファイル名が変更した際、一括で変更できる点です。

```javascript
import { mapActions } from 'vuex'
export default {
  methods: {
    //...mapActions('hoge', ["increment", "incrementBy"]),
    //モジュールのファイル名が「hogehoge.js」に変更すると、、
    ...mapActions('hogehoge', ["increment", "incrementBy"])
    //モジュールのディレクトリ構造が変わっても、、
    ...mapActions('hoge/hoge/hoge', ["increment", "incrementBy"])
  },
};
```

#最後に
間違いを発見された方は、お手数ですがコメントにてお知らせ下さい。
HTMLにYouTubeの動画を埋め込む方法

# 概要
HTMLファイルにYouTubeの動画を埋め込む方法です。簡単な方法で実装します。
(APIなどは使用せずにHTMLファイルに動画を埋め込みます。)

# 手順
## 1.貼り付けたいYouTubeの動画を開きます。
![スクリーンショット 2021-09-18 19.51.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/24c9cc5c-9a3c-bc40-f3d5-0488afc05a2d.png)

## 2.動画の下にある`共有`をクリックします。
![スクリーンショット 2021-09-18 19.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/2313cb10-805f-e4f1-5b85-1044e5be7047.png)

## 3.画像のような小窓が開くので`埋め込む`をクリックします。
（開始時刻を指定したい場合は下の`開始位置`にチェックを入れてください）
![スクリーンショット 2021-09-18 19.53.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/0b2c184e-838a-bc43-c339-320147b42cd8.png)

## 4.遷移先の右下にあるコピーをクリックしてください。
![スクリーンショット 2021-09-18 20.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/83adb9da-906a-1872-ad24-4f3838b53596.png)

## 5.動画を表示したいHTMLファイルにコピーしたコードを貼り付けます。
![スクリーンショット 2021-09-18 20.06.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/5309873d-6ca6-1b6c-1834-99796e278f03.png)

## 6.HTMLを開いて確認します。
![スクリーンショット 2021-09-18 20.07.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/c4b52395-277a-5b2f-c119-ec744975b696.png)


# まとめ
HTMLファイルにYouTubeの動画を埋め込むことができました。
ABC127 C - Prison に怒られた気がした

https://atcoder.jp/contests/abc127/tasks/abc127_c

![abc127_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/ce56feba-4453-e650-9460-f42ae3854fd0.png)
![abc127_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/992000c1-84b8-f05b-086f-fdc2630251c5.png)
![abc127_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/797a09d6-a9fe-99ba-9313-0b3b2773a717.png)
![abc127_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/eedd3251-4f75-1d1f-b38c-98670cc2d936.png)

踏む踏む。
つまり L1 - R1 ~ LM - RM 間で共通項が何個あるか聞かれている気がした。

サクッと書いて WA.

```Prison.py
N,M = map(int,input().split())
L = []
R = []
 
for _ in range(M):
    l,r = map(int,input().split())
    L.append(l)
    R.append(r)
 
st = max(L)
ed = min(R)
 
print(ed-st+1)
```

ん～、何で??

例えば L1, R1 がクソ**大きい**値だったとする。
L2,R2 がクソ**小さい**値だった場合。
冒頭の記述だと**マイナスの場合が出てこないか？**

```Prison.py
N,M = map(int,input().split())
L = []
R = []
 
for _ in range(M):
    l,r = map(int,input().split())
    L.append(l)
    R.append(r)
 
st = max(L)
ed = min(R)
 
print(max(ed-st+1,0))# マイナスが出た場合、0 を最大値として取るように修正
```

ちゃんとエッジケースは考えなよ、イージーだね。。。って怒られた気がした。
Paiza スキルチェックで必要な基礎知識をまとめてみた

#記事内容
Rubyの基礎を学ぶため、以前から気になっていたPaizaでRuby入門を学習。
その後、学んだ知識を試すべくスキルチェック問題に挑戦したときに感じた最低限必要な知識をまとめてみました！

#前提
言語：Ruby

##標準入力・出力について
まず最初に立ちはだかる**標準入力**についてご説明します。

**標準入力**とは、シンプルに言うと`値を受け取る`ことです。
**標準出力**とは、`受け取った値を画面に出力する`ことでです。

**ruby**では`getsメソッド`を使用することで、入力された要素を受け取ることができます。

```ruby
foo # 入力された要素

line = gets # 入力された要素を受け取り、line変数に格納
puts line

出力結果
foo 
```

上記のプログラムでは、入力された要素をgetsメソッドで受け取り、受け取った要素をputsメソッドで出力しています。

**スキルチェック**では**予め入力されている要素**を`getsメソッド`で受け取っていく形になり、その要素をもとに問題を解ていきます。

また、文字列以外にも**「数値」**や**「一行に複数の要素が存在する場合」****「複数行にわたる要素が存在する場合」**など、様々な条件があり、それぞれ受け取り方も異なります。

前置きが長くなりましたが、**要素の受け取り方**を**条件別**に解説していきます。

#文字列編

###１行 && 複数要素の場合

```ruby
foo bar # 入力された要素

line = gets.split # 入力された要素を受け取り、line変数に格納
p line

出力結果
["foo","bar"]
```
`split`・・・指定した区切り文字で対象となる文字列を分割して配列にするメソッド

splitメソッドを使用して、入力された文字列の**空白部分で分割**し、**配列**で返しています。
※引数に`半角スペース(' ')`を指定しても動作は一緒です。


###複数行の場合

```ruby
foo # １行目の要素
bar # ２行目の要素

line = readlines # 入力された要素を受け取り、line変数に格納
count = line.length # 配列の要素数(2)を取得

count.times do |i|
  line[i] = line[i].chomp　# 改行を取り除く
end
 
p line

出力結果
["foo","bar"] 
```

`readlines`・・・**複数行の文字列**を、**１行の配列**として返してくれるメソッド

`length`・・・**「文字列の長さ」**と**「配列の要素数」**を返してくれるメソッド
※ 今回の場合、`readlinesメソッド`を使用して配列として取得したため、**後者**が適用されています。

`chomp`・・・文字列の末尾についた**改行**を取り除き、新しい文字列を返してくれるメソッド
※ `chompメソッド`を使用しないと文字列の末尾に**改行\n**が入ってしまいます。

```ruby
["paiza\n", "paiza\n"]
```

###上記のコードを簡略化した場合

```ruby
line = readlines.map(&:chomp) # オブジェクト.map(&:メソッド名)

出力結果
["foo","bar"] # 出力結果は一緒
```
`map`・・・**配列の要素の数**だけ繰り返し処理を実行し、**戻り値を配列に返してくれるメソッド

今回の場合、各要素にchompメソッドを適用するため、省略記法を使用しております。

```ruby
line = readlines.map{ |i| i.chomp } # 省略前
```

###複数行 && 複数要素の場合

```ruby
foo bar   # １行目の要素
hoge hoge # ２行目の要素

array = [] # 空の配列を作成
while line = gets 
  array.push(line.chomp.split) # 配列に要素を追加
end

p array

出力結果
[["foo","bar"],["hoge", "hoge"]] # 出力結果
```
`push`・・・**配列の末尾**に引数を要素として**追加**するメソッド

まず、入力された要素を格納するため、**空の配列**を作成しています。

次に、**while文**で入力された要素を`line変数`に代入し、`pushメソッド`を使用して**空の配列に要素を追加**しています。
※ 条件式を`line = gets`とすることで入力された**要素の数**だけ繰り返し処理されます。

##数値編
`getsメソッド`は「get string」の略で、名前からも分かるように**入力された文字列を取得**します。
そのため、数値が入力された場合は、`to_iメソッド`を使用して**文字列から数値へと変換**する必要があります。

それ以外は、`先ほどの文字列とほぼ同じ方法で要素を受け取ることができます。`

```ruby
10 # 入力されている要素

line = gets.to_i　# 数値に変換
puts line

出力結果
10
```
###１行 && 複数要素の場合

```ruby
10 20 # 入力されている要素

line = gets.split.map(&:to_i) 

p line

出力結果
[10, 20] # 出力結果
```

###複数行の場合

```ruby
10 # １行目の要素
20 # ２行目の要素

line = readlines.map(&:to_i)
p line

出力結果
[10, 20] # 出力結果
```

###複数行 && 複数要素の場合

```ruby
10 20 # １行目の要素
30 40 # ２行目の要素

array = []
while line = gets
  array.push(line.split.map(&:to_i))
end

p array

出力結果
[[10, 20],[30,40]] # 出力結果
```


#最後に
恥ずかしながらpaizaで学習するまで標準入力という概念を知りませんでした、、笑

そのため、最初は戸惑いましたが、要素の受け取り方さえ分かればこっちのものです！
また、問題文がややこしく書かれているため、まず、**入力例**と**出力例**を確認し、その後、問題文を確認してみると内容が理解しやすいと個人的には感じました。

それでは、自分はこれからBランクを目指す旅に出発します✨

間違っている箇所や分かりづらい箇所が多々あるかと思います。
その際は、気軽にコメントいただけれると幸いです。

最後までご覧いただき、ありがとうございました!
MyBatis アノテーション内でwhere句のinに複数値を渡す

## MyBatisのアノテーション内で特定のカラムに対して複数条件で検索させたい
### 方法
アノテーション内でscriptタグを書けば動的SQLの構文を利用できるようになります。
また以下では、検索条件に一つも選択されていないときは、そもそもreserve_statusの絞り込みを実施しないように`<if test='reserveStatus.size != 0'> ` で制御しています。
※強引にin句に文字列で` ('a','b')` みたいに文字列で変数を渡しても動作しないのでforeachを使うこと。

```kotlin
    @Select("""
      <script>
        SELECT
          cr.id
        FROM
          course_reserves cr
        <where>
          cr.deleted_at is null
          <if test='reserveStatus.size != 0'> 
            AND 
              reserve_status in 
            <foreach item="status" collection="reserveStatus" open="(" separator="," close=")">
              #{status}
            </foreach>
          </if>
        </where>
      </script>
    """)
    fun searchCourseReserves(@Param(value = "reserveStatus") reserveStatus: List<String>): List<CourseReserveList>
```

@Paramなしでこれはうまくいっていたが、うまくいかないいケースもあったので明示的に指定していた方がよさそう。

参考
https://mybatis.org/mybatis-3/ja/dynamic-sql.html
Cloud Storage for Firebase フォルダごと削除する

# 方法
現状フォルダごと削除する機能はないので、リストを取得してループを回す。
フォルダ配下のファイルがすべて消えるとフォルダも削除される。

```
//　削除するフォルダへの参照を作成
var listRef = storageRef.child('files/uid');

// フォルダ配下のアイテムをすべて取得
listRef.listAll().then( (res) => {
  res.items.forEach( (itemRef) =>  {
    //　削除
    itemRef.delete()
  });

```

# 参考
https://firebase.google.com/docs/storage/web/delete-files?hl=ja
https://firebase.google.com/docs/storage/web/list-files?hl=ja
10音ハーモニカ(C)の楽譜から複音ハーモニカの楽譜に変換するサクラエディタマクロ

<h3>10音ハーモニカ(C)の楽譜から複音ハーモニカの楽譜に変換するサクラエディタマクロ</h3>

10音ハーモニカで書かれた簡易的な楽譜から複音ハーモニカの数字楽譜
に変換するサクラエディタマクロを作成しました.

githubURL:https://github.com/NanjoMiyako/tenHpToMultiHp

10音ハーモニカの楽譜形式(入力形式)
1b:1番を吹く
1s:1番を吸う
2b:2番を吹く
2s:2番を吸う
...以下同様にして10b, 10sまで続く.

複音ハーモニカの楽譜形式(出力形式)
1+(1オクターブ上のド)
2++(2オクターブ上のレ)
3-(1オクターブ下のミ)
以下同様で数字は1～7(ド～シ)です

またついでに
複音ハーモニカの簡易テキスト楽譜形式として
以下を考えました

\#:半音上げる
1#→ド#

/:八分音符
/2→レの八分音符

//:16分音符
//3→ミの16音符

<hr>
参考にしたサイト
<a href="http://sakura.qp.land.to/SakuraMacro/reference/find/S_ReplaceAll.html">S_ReplaceAll</a>
<a href="https://hosopro.blogspot.com/2017/03/sakura-editor-macro-replace.html">【サクラエディタ】置換マクロを使ってみた - ほそぼそプログラミング日記</a>
<a href="https://proengineer.internous.co.jp/content/columnfeature/5479">サクラエディタでキーマクロやjsマクロを新規作成する方法とその使い方 | サービス | プロエンジニア</a>
ABC124 C - Coloring Colorfully から学んだ

https://atcoder.jp/contests/abc124/tasks/abc124_c

![abc124_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/792077c0-8e1a-c59a-3e71-edc9e7e8d01a.png)
![abc124_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/15a9b6b1-b131-5b8c-a6c5-8a78319d0031.png)
![abc124_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/ce6277fc-6bf4-f06c-0666-273027fa0545.png)

シンプルに "0" から始めた場合、 "1" から始めた場合、
交互になってない箇所をカウントして比較する。最小を output すれば良いはずです。

```ColoringColorfully.py
S = input()

cntst0 = 0 #"0"start の場合
for i in range(len(S)): # 計算量 O(N)
    if i%2 == 0 and S[i] != "0":
        cntst0 += 1
    elif i%2 != 0 and S[i] != "1":
        cntst0 += 1

cntst1 = 0 #"1"start の場合
for j in range(len(S)):# 計算量 O(N)
    if j%2 == 0 and S[j] != "1":
        cntst1 += 1
    elif j%2 != 0 and S[j] != "0":
        cntst1 += 1

print(min(cntst0,cntst1))#計算量 O(2)

#合計計算量 O(2N+2)
```

極解を見つけた。

```abc124c.py
S = input()
cnt = S[0::2].count("1") + S[1::2].count("0")
print(min(cnt,len(S)-cnt))

#000 の場合
#cnt = 0 + 1 = 1
#len(S)-cnt = 2
#ans = min(1,2)

```

っと言う事らしい。んー、自分には少し早いようだ。
Python で OpenWeather API へアクセスして気象情報を取得する 

## Goals

* OpenWeather API へ Python からアクセスできるようになる
* 取得した JSON データを整形して出力できるようになる

## Back ground

仕事で Python を書く機会がありそうなので、 
Python の素振りがてら、API を叩くコードを書いてみようと思いました。 

## OpenWeather

OpenWeather は気象情報を閲覧するモバイルアプリなどを公開しているサービスです。 
別途、 API も無料で (※) 公開されているため、そちらを今回は利用します。 
https://openweathermap.org/

※ 確認はしていませんが、この手の API は商用利用等では有料となる可能性があるため、よく確認の上使用してください。 

## API の仕様

今回は現在の気象データを取得するため、以下の API を使用します。 
[Current weather data](https://openweathermap.org/current)

## API Key の取得

API へアクセスするために Key の取得が必要です。 
OpwnWeather のサイトで、サインアップして取得してください。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143910/82f1547e-26eb-ab4d-51b6-3666532dd28a.png)

## API へアクセスして JSON のデータを dump するコード

以下のコードで API へアクセスして JSON のデータを dump することができます。 
外部パッケージとして `requests` が必要なため、 `$ pip install requests` でインストールしてください。 

```python
import requests
import json


cityName = "Tokyo"
ApiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # 各自で取得した Key を設定する
api = "http://api.openweathermap.org/data/2.5/weather?units=metric&q={city}&APPID={key}"
url = api.format(city=cityName, key=ApiKey)

response = requests.get(url)
data = response.json()
jsonText = json.dumps(data, indent=4)

print(jsonText)
```
上記のスクリプトを実行すると、以下のようなデータが得られます。 
体感温度など、詳細なデータが得られて便利そうですね。 

```
{
    "coord": {
        "lon": 139.6917,
        "lat": 35.6895
    },
    "weather": [
        {
            "id": 803,
            "main": "Clouds",
            "description": "broken clouds",
            "icon": "04n"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 24.57,
        "feels_like": 25.48,
        "temp_min": 23.22,
        "temp_max": 25.7,
        "pressure": 1006,
        "humidity": 92
    },
    "visibility": 10000,
    "wind": {
        "speed": 3.6,
        "deg": 180
    },
    "clouds": {
        "all": 75
    },
    "dt": 1631960824,
    "sys": {
        "type": 2,
        "id": 2038398,
        "country": "JP",
        "sunrise": 1631910354,
        "sunset": 1631954715
    },
    "timezone": 32400,
    "id": 1850144,
    "name": "Tokyo",
    "cod": 200
}
```

## Round up

今回の記事のまとめは以下です。

* Open Weather API で、詳細な気象データが無料で取得できる
* Python からは、 `requests` package で簡単に API へアクセスしてデータを取得できる

## References

参照情報は以下の通りです。

* https://openweathermap.org/
MySQL のクエリ処理速度早くしたい

#はじめに

Laravel ✖️ Lambda ✖️ API Gateway ✖️ RDS MySQL
によるアプリケーションで、30万レコード以上あるテーブルを同じく3以上の他テーブルたち（それぞれ数万行ある）と結合して読み込む際に、処理速度のアップで四苦八苦したので記録として残します。

APIGateway を使っており、30秒以内にレスポンスを返す必要がありました。



## バージョン

MySQL 5.7

# 調べてわかったこと試したこと

## キーワード大文字小文字で処理速度が変わる？

**少なくともMySQLでは変わりません。**

https://style.potepan.com/articles/26070.html#SQL

この記事では変わると書かれてありますが。。これは他のDBエンジンのことだと思ってます。

## Nested Loop Join を知る
2つのテーブルを結合させるときに使うJOIN
その際の結合方法が数種類あるらしいです。
処理速度を上げたいときに理解必須の仕組みです。

- merge join
- hash join
- nested loop join <--- MySQLは基本これ

https://enterprisezine.jp/article/detail/3520



MySQL 8.0.20 ではハッシュジョインが追加されたみたいですね。

https://qiita.com/hmatsu47/items/e9d3d4396fea42c8960e

### n ✖️ m　を最小値にする

https://qiita.com/yuku_t/items/208be188eef17699c7a5


要は、Nested Loop Join (NLJ)とは、結合されるたびにイテレートされるということ。
駆動表のレコード数(n)、内部表でマッチするのレコード数(m)
つまりJOINされると n ✖️ m 回内部的な処理が走ります。

mは条件次第(JOIN `hoge` ON `ここの記述`)で処理の事前にレコード数を減らせます。

この回数を小さくするには、n が小さくするもしくはnの処理を早くする必要があります。


## インデックスを知る

https://qiita.com/katsukii/items/3409e3c3c96580d37c2b

私の場合はINDEXには大きな問題ないと判断したので、INDEXについて深掘りするのは省略しますが、

- **演算されたカラムのインデックスは働かない**
- **INDEX使うか使わないか、複数ある場合等、割とMySQLが判断している部分がある**

等に注意しながら、SQL書きました。

どのカラムのINDEXが使われるかを調べるときに使うのが、後述にある**EXPLAIN**です。


## Explainを知る

## Explainとは
「MySQL EXPLAIN とは」で出てきた最初の記事を貼っておきます。

https://thinkit.co.jp/article/9658

**実行計画であり実行結果が必ずそうなるとは限らないということ**

これといった具体例提示できませんが、一応これは忘れないようにします。

### filtered 

先述したindexの使い方がおそらく一番大事なのだとは思うが、今回私が特に大きく改善できたのはこの値
**filtered**

filteredは、検索条件によって絞り込まれるレコードの割合です。

explain したら出てくるカラムですが、この数値がかなり悪かった。

- 結合条件を増やす
- joinする順番を変える

を行って、filtered を100に近づけていきました。




## キャッシュ

## クエリキャッシュ
この記事見ていけるかもって思ったけど
MySQL 5.7から非推奨でしたので却下
https://qiita.com/tonyfactory/items/a00e4bf25b6a132dfce7


#おわりに

上記色々試してみて、確かに速度は上がりましたが、期待していたレベルまでは改善しませんでした。

あと試せるのは下記かなぁと

- 実行結果がそのまま格納されている別テーブルを作成する。レコードの追加や更新は、定時に自動でバッチ処理を走らせて更新する。
- Amazon ElastiCache などのキャッシュを上手く使う

どちらにしても今回のこの機能の使用頻度やテーブルの更新頻度等を鑑みる必要がありますね。

## 参考記事
https://style.potepan.com/articles/26070.html#SQL

https://enterprisezine.jp/article/detail/3520

https://nishinatoshiharu.com/explain_overview/

https://qiita.com/ichi_zamurai/items/fdbe3872a505c22ee431

https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/implement-sqltuning/
【JavaScript】letとconst（とvar）の使い方について

#はじめに
JavaScriptの基本中の基本ですが、letやconst、varの使い方を簡単にまとめていきます。

#varについて
JavaScriptは、元来、変数を定義するときには`var`しかありませんでした。
しかし、ES6で新しく`let`と`consｔ`が追加されたことにより、それ以降は`let`と`consｔ`が使われるようになっています。
したがって、`var`はもう使わないと考えて良いでしょう。

#letとconstの違い
###`let`は上書きできるが、`const`は上書きできない！！
たとえば、以下のようなコードがあったとします。

```JavaScript:JavaScript
//let
let name = 'Yamada';
name = 'Suzuki';
console.log('hello　' + name);
```
この場合、`let`は上書きできるので、`hello Suzuki`と出力されます。
次に、以下のようなコードがあったとします。

```JavaScript:JavaScript
//const
const name = 'Yamada';
name = 'Suzuki';
console.log('hello　' + name);
```

この場合、`const`は上書きできないので、エラーが発生します。

#まとめ
基本的には、`const`を使い、再代入が必要な場合のみ`let`を使いましょう。
STM32F303を使た、MbedでHALのLチカ


目的
やってみたかった
容量的メリットなし

PA4(10ピン)をLチカする。



```c++



#include "mbed.h"

//DigitalOut myled(PB_3);

int main() {

  __HAL_RCC_GPIOB_CLK_ENABLE();
    
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  
    
    while(1) {
        //myled = 1;
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);
        wait(0.2);
        //myled = 0;
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);
        wait(0.2);
    }
}




```
リーダブルコードまとめ

#リーダブルコード読みました
プログラマ、エンジニアが読むべき本として第一に上がる有名な本「リーダブルコード」（日本語訳版）を１周読みましたので重要だと思ったものを自身への備忘録としてまとめます。
sampleコードはswiftで書いてます。
![51MgH8Jmr3L._SX352_BO1,204,203,200_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/57c901c9-fe07-1cb3-29c1-9a534c0a20d7.jpeg)


#おばあちゃんがわかる様に説明できなければ、それは本当に理解したとは言えない。
![keirou_obaachan_smile2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/4f34d3fa-0c04-b90c-e231-385385ce5df2.png)

別業種ですが、入社１年目で先輩から同じことを言われました。
全ての業界に当てはまる名言だと思います。
おばあちゃんに説明する前に後述するラバーダッキング法を実践するのが良いでしょう。

#明確な単語を選ぶ(p.12)
```swift:sample
let size :Int = 30
```
例えば上記のコードは何の"size"なのかわからない。
"height","width"などの単語の方が情報量が多く何のサイズなのかがわかる。


#bool値の名前はtrueなのかfalseかを明確にする(p.33)
```swift:sample
if checkError == true {
    //処理
}else{} 
```

上記例ではcheckErrorがtrueとはチェックをした状態がtrueなのかチェックをしていない状態がtrueなのかがわかりません。

isCheckedなどのbool値が良いでしょうか。

#列は整列するとタイプミスを見つけやすい。(p.48)
```swift:sample
button1 .isHidden = true
button2 .lsHidden = true
button3 .isHidden = true
```
2つ目の行でタイプミスしています。整列すると一目瞭然ですね。

#限界値を含める時はmax,minを使う(p.31)
```swift:sample
let maxSize :Int = 100
let minSize :Int = 0
```

#スコープが大きい変数には長い名前をつける(p.22)
長期出張よりも1泊だけの時の方が荷物は少ない。
それと同じで、スコープが短い場合は短い名前でも良い。
（スコープが短いと全ての情報が見える）

しかし、スコープが長い場合が全容が見えないので、名前に十分な情報を詰め込まなければならない。
![business_syucchou_woman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/8f125cef-ed5e-e12f-7de9-4cad4bbbc216.png)




#正しいスタイルよりも一貫性の方が大事(p.53)
表題の通りです。

#コメントについて

###コメントすべきでないこと(p.57)
```swift:sample
//Accountクラスの作成
class Account {
    let id :Int 
}

//インスタンス化
let account = Account()
```

上記のコメントはクラス化、インスタンス化することはすぐ下の行を見れば明々白白であるのでコメントを記述することに意味がない。

###コメントは何もないよりは書いた方がマシ(p.67)
プログラマの多くはコメントをうまく書くの難しいと感じ、コメントを書きたがらない。これをライターズブロックという。しかし。コメントはないよりあったほうが良いのである。


###コードの欠陥に名前をつける(p.61)
欠陥を文書かすることを恥ずかしがってはいけない。
改善が必要な時は以下のような記法でコメントする。

TODO : あとで手をつける
FIXME : 既知の不具合がある
HACK : あまり綺麗じゃない解決策
XXX : 危険

#条件式の引数の並び順(p.84)
```swift:sample
if width >= 20 
//左側に調査対象(変化する）の式、右側に比較対象の式（あまり変化しない）を配置する。
```


#行数を短くするより、他の人が読む時間を短くする
これ私は一番大事だなと感じました。
そもそもプログラマーは数秒を自動化するために何十時間もコードを書くものですよね。
今、手間をかけて総合的には後から楽する。この考えが重要かと思います。

#変数が絶えず変更されると、値を追うのが難しくなる。(p.123)
表題の通りです。
変数は一度だけ書き込むのをこの著者は提案しています。
そうでない場合でも変更箇所はできるだけ少なくするべきです。


#ラバーダッキング法
![furo_ducky.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/51f245bb-7fd8-186d-0d9c-59d8efa47539.png)
Rubber Duckつまりアヒルのおもちゃに対して声を出して説明する方法です。
馬鹿馬鹿しいと思う人もいるかもしれませんが、誰か（アヒルでも）に対して声に出して説明すると言うことは、自分の頭の中にある抽象的で断片的な情報を具体化してまとめる過程が存在するので非常に効果があることなのです。


#ライブラリを再利用する

ソフトウェアエンジニアは一日に書く平均的な出荷用のコードはたった10行だそうです。

大切なのは、この10行は膨大なコードの中から、デバック・修正・文書化・最適化・テストされた結果の10行だと言うことです。
この過程を得たライブラリの再利用は、時間の節約及びコードを少なくすることができるのです。

#まとめ
正直、"当たり前のことが当たり前に書いてある"本であると感じました。
しかしこの当たり前を確実に毎回実行することが大切なのでしょう。