OmniAICreator/Qiita-1.07M huggingface dataset:
'= で始まるセルを含むセルの転記

友人からこんな相談が来たので少し掘り下げてみた。

お題はこんなのを含むセルを転記するマクロを作りたいとのこと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/45f0f3f3-58ca-f4b4-dc5c-154d43f3b537.png)

`=`で始まると関数扱いされるので転記後変になったり、転記途中でエラーになる

コピーを単一セルで実行するとエラーにならないが、範囲選択だとエラーになるみたい。



そもそも`=`で始まるの使うなよって話だけどひとまず作ってみた。

## まずは処理時間まとめ

2列10000行のデータを処理した際の時間で比較

||処理時間|備考|
|---:|---|---|
|案1|18.58984|転記後のセルの値が`'=aaaaa=`になるので<br>転記後に編集しても問題ない。|
|案2|11.78516|転記後のセルの値が`=aaaaa=`になるので<br>転記後に編集してそのまま`'`なしで終わるとエラーになる|
|案3|0.451172|転記後のセルの値が`'=aaaaa=`になるので<br>転記後に編集しても問題ない。|

出力結果もエラーなしでダントツで速いとかもう案1,2いらないじゃんだけど、範囲まるっと転記なのか抜粋転記なのかとかどんなものを作ろうとしているかもわからないので、とりあえず過程も列挙した。


## 案1
``` vb 
Sub 数式扱いされるセルを含む転記1()
  Application.ScreenUpdating = False
  Dim Arr1
  
  Arr1 = Range("A1").CurrentRegion
  
  Dim r, c
  r = UBound(Arr1, 1)
  c = UBound(Arr1, 2)
  
  Dim i, j, buf
  For i = 1 To r
    For j = 1 To c
      With Range("F1").Cells(i, j)
        buf = Arr1(i, j)
        If buf Like "=*" Then
          .Value = "'" & buf
        Else
          .Value = buf
        End If
      End With
    Next
  Next
  Application.ScreenUpdating = True
End Sub

```

`if`で場合分けしてるのが無骨だが、転記後のセルの値が`'=aaaaa=`になるので転記後に編集しても問題ない。

ちなみに処理時間は案2の1.5～2倍くらいかかる



## 案2


``` vb
Sub 数式扱いされるセルを含む転記2()
  
  Application.ScreenUpdating = False
  Dim Rng1 As Range, Rng2 As Range
  
  Set Rng1 = Range("A1").CurrentRegion
  Set Rng2 = Range("F1")

  Dim r, c
  r = UBound(Rng1.Value2, 1)
  c = UBound(Rng1.Value2, 2)
  
  Dim i, j, buf
  For i = 1 To r
    For j = 1 To c
      Rng2.Cells(i, j) = Rng1(i, j)
    Next
  Next
  Application.ScreenUpdating = True
  
End Sub
```

ただし転記後のセルの値が`=aaaaa=`になるので転記後に編集してそのまま`'`なしで終わるとエラーになる

## 案3
もはや繰り返し処理せずに単純に`copy`メソッドでやっつけるパターン

``` vb
Sub 数式扱いされるセルを含む転記3()
  
  Application.ScreenUpdating = False
  Dim Rng1 As Range, Rng2 As Range
  
  Set Rng1 = Range("A1").CurrentRegion
  Set Rng2 = Range("F1")
  
  Rng1.Copy Rng2
  
  Application.ScreenUpdating = True
  
End Sub
```


## おまけ　処理時間測定

https://www.sejuku.net/blog/69319

から拝借

`  'メイン処理
  Call 数式扱いされるセルを含む転記3
`
のところに測定したいプロシージャ名を入れて実行するだけ

``` vb
Sub 時間計測()
  Dim startTime As Double
  Dim endTime As Double
  Dim processTime As Double
  Dim i As Long
 
  '開始時間取得
  startTime = Timer
 
  'メイン処理
  Call 数式扱いされるセルを含む転記3
  
  '終了時間取得
  endTime = Timer
 
  '処理時間表示
  processTime = endTime - startTime
  Debug.Print "処理時間：" & processTime
  

End Sub
```
Ubuntu+Python3(任意のバージョン)の実行環境を構築するDockerfile

# この記事は
他人と同じ実行環境を構築するために、Ubuntuイメージをベースとして、任意バージョンのPython3環境を構築したかったので、勉強も兼ねていろいろ試してみた。[前も同じようなこと](https://qiita.com/ntatsuya/items/d7354e27783c0f0ee61c)をやりましたが、こちらの内容の方が汎用性が高そうなのでまとめます。
同じような状況の方の参考になれば幸いです。もっと良い方法があればぜひ教えていただきたいです。
Python3の実行環境をDockerで立ち上げるだけなら、公式の[Pythonイメージ](https://hub.docker.com/_/python)を使用するのが簡単だと思います。

# 実行環境
Docker version 20.10.5

# Dokerfile
以下のDockerfileからイメージをbuildする。今回はUbuntu20.04のイメージを使用し、Python3.9.5をインストールする。このあたりは、適宜自分の構築したい環境にあわせて変更してください。

```Dockerfile:Dockerfile
FROM ubuntu:20.04

# 必要そうなものをinstall
RUN apt-get update && apt-get install -y --no-install-recommends wget build-essential libreadline-dev \ 
libncursesw5-dev libssl-dev libsqlite3-dev libgdbm-dev libbz2-dev liblzma-dev zlib1g-dev uuid-dev libffi-dev libdb-dev

#任意バージョンのpython install
RUN wget --no-check-certificate https://www.python.org/ftp/python/3.9.5/Python-3.9.5.tgz \
&& tar -xf Python-3.9.5.tgz \
&& cd Python-3.9.5 \
&& ./configure --enable-optimizations\
&& make \
&& make install

#サイズ削減のため不要なものは削除
RUN apt-get autoremove -y

#必要なpythonパッケージをpipでインストール
#RUN pip3 install --upgrade pip && pip3 install --no-cache-dir jupyterlab

#requirements.txtなら以下のように
#RUN pip3 install -r ./requirements.txt
```
上のDockerfileと同じディレクトリで

```
docker build .
```
でbuildする。
## 簡単な説明
`FROM ubuntu:20.04`でUbuntuのベースイメージを引っ張ってくる。
そのあとは必要なパッケージ群をintall、ここはあまり自信がない、余計なものが多いかもしれないです。
Python3のインストール自体は`apt-get install python3 pip`でインストールが簡単だけど、任意のバージョンを扱いづらかったので、[Pythonの公式サイト](https://www.python.org/downloads/)から`.tgz`をダウンロードしてきて、それを展開してインストールする。
あとは、自分が必要なパッケージをpipでinstallなどして使ってください。

# 参考
https://qiita.com/yniji/items/8e392103a6f2a4152606
https://docs.python.org/ja/3/using/unix.html
Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)エラーの解決方法

#Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
capistranoでのデプロイ時に

```
Caused by:
SSHKit::Command::Failed: rake exit status: 1
rake stdout: Nothing written
rake stderr: rake aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
```
上記のエラーが出た。

MySQLサーバーと接続するタイミングで接続ができなくエラーが出た模様。

解決策としてはMySQLサーバーを再起動させることにより解決できる場合が多い。

```console:EC2コンソール
$ sudo systemctl restart mysqld.service
```
上記のコマンドでMySQLサーバーを再起動させてから

```console:ローカル
$ bundle exec cap production deploy
```
capistranoで自動デプロイできるようになる
ReactプロジェクトにおけるCSSの扱い方についての自分の意見


ReactプロジェクトにおけるCSSの扱い方について自分の意見をまとめます。

- 想定読者は、CSSやReactを使ってアプリケーションを作ったことのある方です。

## Reactプロジェクトの問題: UI要素の再利用方法が複数存在する

Reactにおいては、UI要素の再利用方法が複数存在する問題がある。

1. CSSを使ったUI要素の再利用。これは、基本的には一度作ったCSSクラスを様々なHTML要素に付与することである。例えば「Button」クラスを様々な要素に付与して使う。

2. Reactコンポーネントを作ることによるUI要素の再利用。例えば「Button」コンポーネントを作り、それをいろいろな画面で使う。

この二つの考え方(CSS、React)はどちらも正しい方法だが、混ぜて使うと問題が生じる。ボタンのデザインを再利用するためにCSSクラスを再利用すべきか、コンポーネントを作って再利用すべきか迷いが生じる。書き方が一つに定まらず、実装を遅くする。

## どちらの方法が良いか

Reactコンポーネントは、Reactプロジェクトにおいて必ず使うものである。そのため、CSSクラスによる再利用を志向しても必ずReactコンポーネントによる再利用と混ざる。CSSクラスのみに寄せきれない。一方、CSSクラスの再利用を全くせずReactコンポーネントのみを再利用することは可能である。

そのため、Reactコンポーネントを再利用するという方に寄せるのが良いと考える。

## tailwindcssの考え方

[tailwindcss](https://tailwindcss.com/)は、Reactコンポーネントの再利用に寄せる方向でこの問題を解決している。tailwindcssでは、あらかじめ用意されたユーティリティCSSクラスをHTML要素に適用してスタイリングする。スタイリングしたHTML要素を複数の場所で使いたくなった時は、React（やVue）のコンポーネントとして切り出すことによって再利用する。


重要なのはCSSクラスを開発者が書かないことだ。アプリケーションレベルの再利用の単位は必ずReactコンポーネントになり、CSSクラスを自分で書いてそれを再利用することは基本的にしない。これによって、再利用の方法が「Reactコンポーネントとして書く」という一つにまとまり、迷いが生じない。

ただ、tailwindcssを使うかどうかは意見の分かれるところではある。とはいえ、この考え方自体はtailwindcssを使わなくても使える。

## 結論

tailwindcssの考え方を参考にして、

- 再利用の単位は常にReactコンポーネントとする。
- CSSクラスの再利用は基本的に行わない。
    - 特に、アプリケーション特有のCSSクラスを書いてそれを再利用することには極めて慎重になる。
    - ただし、ごく一般的なユーティリティCSSクラス（tailwindcssで定義しているような粒度のもの）を定義することは許容される。
- コンポーネントの内部においてどのようなCSSソリューションを使うかは自由（素のCSS、BEM、SCSS、CSS-Modules、Styled-component、tailwindcss　なんでもよい。自分のプロジェクトの性質に応じて選択する）。

 
という考え方をとる。

以上
Cisco Packet Tracerのインストール手順

## Cisco Packet Tracer とは何か
公式サイト
https://www.netacad.com/courses/packet-tracer

Ciscoが開発したネットワークシミュレーションツールのことです。
通常ネットワーク機器を使った構築をするのは未経験者からすると大変なことです。
この Packet Tracer を使用するとソフトウェアの内部のみで仮想的なネットワークを構築することができます。
ネットワークについて学びたい方にとってはとてもありがたいツールとなってます。

## インストール手順
### Cisco Networking Academyのアカウント登録
まずは以下のURLへアクセスします。
https://www.netacad.com/courses/packet-tracer
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/3b867a69-8f51-edaf-41bf-7a85b198e9ea.png)

下の方に行くと[Learn More]があるのでクリックし、
Pocket TracerのIntroductionページへ入ります。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/b6943c14-77c8-dcdf-5d7e-865900bb11a6.png)

次に下の方に[Sign up today!]があります。
マウスオーバーすると[English]と出てくるのでクリックします。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/e89b115f-e48a-28ce-5df0-e652839a4178.png)

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/a44e1eb3-8c7c-b369-c24e-3bc977a05728.png)

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/97571673-fc11-0152-3d72-1ca0ef9ebaa0.png)

ここでCisco Networking Academyのアカウント登録を行います。
必要な箇所に必要な個人情報を入力してください。
最後に[Create Account]をクリックすると
登録したメールアドレス宛にメールが来ますので確認します。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/4eba1505-c51c-b94e-30b3-00fb7cf9520d.png)

以下の[Activate account]をクリックします。
![mail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/d7c166ee-98c2-d43f-d03f-d9e797c035a3.png)

クリックするとパスワード登録の画面に遷移します。
（こちら、キャプチャを取り忘れました。）
記憶を辿ると

- パスワードの登録
- ネットワークエンジニアの経験年数
- 生年月日

この辺りを入力した覚えがあります。
量は全然ありませんので、簡単かと思います。

これでアカウント登録は完了です。

### Cisco Packet Tracerのダウンロード
アカウント登録が完了すると、Cisco Netwaok Academyにログインした状態になっているはずです。
そうでない場合は右上の[Sign In]からログインしてください。
以下のキャプチャに従ってインストーラをダウンロードします。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/e849f2dd-dd26-881e-56a3-c4d69ff4ada6.png)

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/5b438ef6-51f7-bcae-c1e3-09d93c32640c.png)

### インストール
ダウンロードしたインストーラからインストールを開始します。
インストーラに従えば問題なくインストールできると思います。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/6e3d4ffe-2577-2e72-d31e-ac5c2dd2d4e4.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/c84cd302-ae26-50ab-6f5d-0557d7a8ba70.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/23f9c9f8-d4f4-4fbb-b1bf-fd23761c3d16.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/fa36851e-5efc-2b03-a45d-7095b992a0a4.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/8c2576c1-7b28-2780-8ead-095387abcd50.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/7003eaa8-8048-e3c0-d214-15bb3ffdfd6f.png)

## 終わり
これでインストールが完了したはずです。
Cisco Packet Tracerを立ち上げると以下のような感じです。
ログインが必要かと思いますので、
登録したメールアドレスとパスワードを入れて使用してください。
![Packet Tracer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1479145/09455cfe-7bdb-f084-75bb-682010496ee3.png)
レムが可愛すぎたので全画面キャプチャにしました。（許してください）
使い方については私も勉強中ですので、追って投稿したいと考えています。
お付き合いいただきありがとうございました。
Qiitaのプロフィール画像をアップロードすると「ファイルPaperclip::Errors::NotIdentifiedByImageMagickError」と表示される 

##初期アイコンがダサい問題
GoogleアカウントをQiitaに紐づけたら、初期アイコンがGoogleアカウントと同じアイコン
（単色背景に白抜きで名前が表示されているだけのもの）だった。
さすがにダサかったので早速アイコン画像を設定することに。

使用するのはこの画像。
![プロフィール画像.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532684/7578c3ec-d6ed-d4da-bd21-2af775222157.jpeg)
かわいい。


##プロフィール画像を変更する
マイページ ▶ プロフィールを編集する ▶ アカウント ▶ 画像アップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532684/ca22d1a1-a716-810c-c209-a6a3a4956041.png)
「ファイルを選択」から、使用したい画像を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532684/54621d6c-6e71-9b8e-4667-54bab8b696a6.png)


##登録できない！
「新しい画像をアップロードする」を押してみると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532684/f522869b-814b-e401-2f0e-8bc23c5737be.png)
<font color="Red">**ファイルPaperclip::Errors::NotIdentifiedByImageMagickError**</font>

どうやらうまく設定できていないっぽい。

ファイルサイズは5.48MBなので問題ないはずだけど、
画像の大きさが 6000px × 4000px で大きすぎたのかな…？

3000px × 3000px に縮小して再チャレンジ。
![新しいビットマップ イメージ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1532684/e1f37dcb-ca85-aab8-77cf-bbfc649f2734.jpeg)
できた！
【SwiftUI】AVFoundationでText to Speech

#きっかけ

時間を読み上げる時報アプリの影響を受けて
とりあえずiPhoneに喋らせてみよう！となりました

#コードを小出しに

###まずはインポート

```swift:import
// とりあえずインポート
import SwiftUI
import AVFoundation
```
###喋るための設定

```swift
        // 何を喋らせるか設定
        let utterance = AVSpeechUtterance(string: "こんにちは")
        // 喋る言語の設定
        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        // 喋るスピードの設定 個人的に0.5くらいが普通と感じます
        utterance.rate = 0.5
        // よくわからんが設定！
        let synthesizer = AVSpeechSynthesizer()
        // 発話
        synthesizer.speak(utterance)
```

###でもボタンに仕込むの面倒だからfuncに放り込んだ

```swift
    // アンダーバーが肝らしいが使いこなせてません
    func text2speech(_ text: String) {
        let utterance = AVSpeechUtterance(string: text)
        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        utterance.rate = 0.5
        let synthesizer = AVSpeechSynthesizer()
        synthesizer.speak(utterance)
    }
```

###変数の設定

```swift
    // @Stateで変数の変化に対応
    @State private var text: String = ""
```

###喋らせたい言葉をTextFieldへ

```swift
// $マークが必須
TextField("入力してね", text: $text)
    .padding(30)
```

###ボタンの設定

```swift
// 手抜きボタン！
Button("発話") {
    // テキストフィールドから受け取った言葉をtextToSpeechへ
    text2speech(text)
}
// ボタンを押しやすいように大型化
.font(.largeTitle)
.padding()
.background(Color.blue)
.foregroundColor(.white)
```

###全体像

```swift
import SwiftUI
import AVFoundation

struct ContentView: View {
    @State private var text: String = ""
    
    var body: some View {
        // 上下に並ぶようにVStackで囲います
        VStack {
            Spacer()
            TextField("入力してね", text: $text)
                .padding(30)
            Button("発話") {
                text2speech(text)
            }
            .font(.largeTitle)
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            Spacer()
        }
    }
    
    func text2speech(_ text: String) {
        let utterance = AVSpeechUtterance(string: text)
        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        utterance.rate = 0.5
        let synthesizer = AVSpeechSynthesizer()
        synthesizer.speak(utterance)
    }
}
```

#最後に

ネットで検索してもあまり出てこないのね
Speech to Textの方はいくらでも出てきましたが
Text to Speechは少ないですね（特に日本語記事！）

#実際のところ
シミュレーターでは喋ってくれたのですが
~~実機にインストールしようとしても失敗しちゃうんですよね…
なんでだろ~~

#環境

MacBook pro 2014 Mid Big Sur
Xcode 12.5
iPhone 12 Pro iOS 14.5.1

#お願いします

~~インストールできない理由がわかる方居たら助けてください
よろしくお願いします~~

```swift
Communication with Apple failed.
Your maximum App ID limit has been reached.
You may create up to 10 App IDs every 7 days.
```

だそうです…
繰り返し処理の基礎

次の仕様を満たすアプリケーションを作成。

仕様
-
①「[0]:カロリーを表示する、[1]:終了する」という選択肢が表示され、数字を入力することができる
② 0を入力すると「500kcal」と表示され、上記条件①が繰り返し実行される。
③ 1を入力するとアプリケーションが終了する


 while
-
条件によって繰り返し処理を行う場合はwhileを使用。
以下のように使用します。

```rb
while 条件式 do
  処理するアクション
end
```

もしプログラムを終了させず同じ処理を繰り返すループ処理を行う場合は、以下のようにします。

```rb
while true do    
  処理するアクション
end
```
```rb:実装コード
while true do
  puts "[0]:カロリーを表示する"
  puts "[1]:終了する"
  input = gets.to_i

  if input == 0
    puts "500kcal"
  elsif input == 1
    exit
  end
end
```

while true doとすることでdo以下の処理を繰り返します。4行目で値を入力します。その結果が、0の場合は500kcalを表示し、1を入力した場合はexitによりRubyプログラムの実行を即座に終了できます。
【php】合計が初めて1000を超えた時に、合計値と最後に足した値を出力せよ

初めて合計値が1000を超えた時、

合計値を出力してください。
最後に足した値を出力してください。

```php
<?php

$total = 0; 
$i = 0;

while($total<=1000){
   $i++;
   $total = $total + $i;
}

//計算結果
print "合計値：".$total."\n";

//forで回った回数
print "最後に足した数：".$i."\n";
?>
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/5b80ce85-56db-06a9-08c3-e9423d75468d.png)
配列に格納された数値の合計値を算出するプログラムの実装 


概要
-
配列に格納された3つの数値の合計を算出するプログラムを実装。次の要件を満たすlone_sumメソッドを実装。

配列に格納された3つの数値の合計を出力する
ただし、同じ数値が2つ以上含まれている場合、その数値は合計する要素に含めない
雛形
-

```rb
def lone_sum(ary)
  # 処理を記述
end
```
```rb:呼び出し例
lone_sum([1, 2, 3])
出力例
lone_sum([1, 2, 3]) → 6
lone_sum([3, 2, 3]) → 2
lone_sum([3, 3, 3]) → 0
```
```rb
def lone_sum(ary)
  # 配列から、重複しない要素のみ取り出す
  uniq_nums = []
  ary.each do |num|
    count = 0
    ary.each do |i|
      if num == i
        count += 1
      end
    end
    if count < 2
      uniq_nums << num
    end
  end


  # uniq_nums配列内の合計
  sum = 0
  uniq_nums.each do |unique_num|
    sum += unique_num
  end
  puts sum
end
```

```rb:呼び出し例
lone_sum([1, 2, 3])
```


3〜14行目で重複しない値のみ取り出す処理を、17〜20行目で重複しない値のみになった配列内の合計を求める処理を行っています。以下具体的に見てみます。

たとえば、lone_sum([3, 2, 3])でメソッドを呼び出した場合を考えてみます。

この場合、4行目で最初にnum=3となります。その後6行目でi=3, 2, 3となり、それぞれに対してnum=iとなったとき、つまり重複したときにcountが増えるようになっています。
そして、11行目では重複した値が1つのときだけ、uniq_nums配列に値を追加しています。num=3のときはcount=2となるので、uniq_nums配列に値は追加されません。
これを後2回繰り返した結果、uniq_nums配列には2だけが追加されます。

そして17行目以下でuniq_nums配列内の合計を求めます。
この場合はsum = sum + 2、つまりsum = 0 + 2となります。
その結果、合計は2と出力されます。
【Python】ロギングのベタープラクティス

# 実装

同じ階層に`main.py`と`logger.py`があるとします。

```python:logger.py
import logging
import logging.handlers


def set_logger():
    logger = logging.getLogger()

    streamHandler = logging.StreamHandler()
    fileHandler = logging.handlers.RotatingFileHandler(
        "./logs/app.log", maxBytes=1000000, backupCount=5, encoding="utf-8"
    )

    formatter = logging.Formatter(
        '%(asctime)s| %(levelname)-5s | %(name)s.%(funcName)s.%(lineno)d | %(message)s'
    )

    streamHandler.setFormatter(formatter)
    fileHandler.setFormatter(formatter)

    logger.setLevel(logging.DEBUG)
    streamHandler.setLevel(logging.INFO)
    fileHandler.setLevel(logging.DEBUG)

    logger.addHandler(streamHandler)
    logger.addHandler(fileHandler)

    return logger

```

```python:main.py
# 最初に定義
from logger import set_logger

if __name__ == "__main__":
    set_logger()

    ...
    ..
    .
```

各モジュールでの使用例

```python
import logging


logger = logging.getLogger(__name__)


logger.debug("debug")
logger.info("info")
logger.warning("warn")
logger.error("error")
logger.critical("critical")
```

# 結果

```bash:コンソール
$ python /app/tmp/main.py 
2024-10-25 13:22:45,521| INFO  | functions.apicall_vad.54 | done: ./tmp/target.wav
2024-10-25 13:22:45,523| INFO  | functions._clear_dir.241 | done: clear ./tmp_splitted_wav
2024-10-25 13:22:45,526| INFO  | functions.split_wav_by_vad.132 | done: ./tmp_splitted_wav/0.wav
2024-10-25 13:22:45,527| INFO  | functions.split_wav_by_vad.132 | done: ./tmp_splitted_wav/1.wav
```

```txt:app.log
2024-10-25 13:23:01,511| INFO  | functions.apicall_asr.98 | done: ./tmp_combined_wav/2.wav
2024-10-25 13:23:07,337| DEBUG | functions.apicall_asr.89 | _json_data= {'data': ["brabrabra"], 'errors': []}
```
PythonでYAMLの検証をする

手前味噌ですが、pre-commitで使えるhooksを作りました。
もしよければご利用ください。

https://github.com/k-ogawa-1988/yamale-pre-commit

# JSON SchemaはあるのにYAML Schemaは？

と思って探してみると、以下の記事を見つけました。

https://json-schema-everywhere.github.io/yaml

ここにリストアップされているもので、Pythonで使えそうなものは以下でした。

| 名前 | 最終更新日(master/main) | 感想 |
|:-|-:|:-|
| [Kwalify](http://www.kuwata-lab.com/kwalify/) [(GitHub?)](https://github.com/yaml/kwalify) | 2009年12月1日 | 2009年！？ |
| [Rx](http://rx.codesimply.com/) [(GitHub)](https://github.com/rjbs/rx) | 2015年12月18日 | ホームページに時代を感じる… |
| Yamale [(PyPi)](https://pypi.org/project/yamale/) | 2021年4月25日 | ロゴがあるのね、やる気満々やん |

さすがに古いものを使うのはどうかと思ったので、Yamaleを使うことにしました。

# インストール

PyYAML（Yamaleのデフォルト）を使いたい場合は

```bash
pip install pyyaml yamale
```

ruamelを使いたい場合は

```bash
pip install ruamel yamale
```

# Yamale式、スキーマファイル

スキーマ自体もYAMLで書いていきます。
オプション `--schema` が未指定の場合、検証するYAMLファイルと同じディレクトリにある `schema.yaml` が参照されるようです。

https://github.com/23andMe/Yamale#validators

サンプルにあるものがそのまま参考になりそうです。

# 実行してみる

CLIとAPI、どちらも使えるようになっていますが、ひとまずCLIで動かしてみます。

```bash
yamale
```

オプションが必要な場合があると思うので日本語訳してみました。

```
usage: yamale [-h] [-s SCHEMA] [-n CPU_NUM] [-p PARSER] [--no-strict] [PATH]

yaml ファイルを検証します。

positional arguments:
  PATH                  検証するフォルダ。未指定だとカレントディレクトリ。

optional arguments:
  -h, --help            このヘルプを表示
  -s SCHEMA, --schema SCHEMA
                        スキーマのファイル名。未指定だとschema.yaml。
  -n CPU_NUM, --cpu-num CPU_NUM
                        CPUの使用数。デフォルトは4。
  -p PARSER, --parser PARSER
                        ファイルをロードするのに使用するYAMLのライブラリ。 "ruamel" か
                        "pyyaml" (デフォルト) が選択肢。
  --no-strict           厳密モードを無効化。スキーマに指定されていないデータが存在しても受け入れます。
```

ファイルに問題がなければ戻り値が0になります。

# pre-commitと組み合わせる

みんな大好き [pre-commit](https://pre-commit.com/) と組み合わせたかったのですが、いろいろファイルを用意しないといけなかったので、hooksを自作しました。

https://github.com/k-ogawa-1988/yamale-pre-commit

```yaml
repos:
  - repo: https://github.com/k-ogawa-1988/yamale-pre-commit
    rev: v0.0.2  # 2021年5月24日現在
    hooks:
      - id: yamale-validate
```
 
オプションはなしでも問題ないはずです。

仕事用のリポジトリにも使ってみましたがちゃんと機能しているようです。

## スキーマファイルにエラーがある場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143240/ad5ee9d9-10db-91ee-43c0-8496ad68ca03.png)


## データファイルにエラーがある場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143240/2c64877e-b65a-fa06-03a8-bb99e09c7139.png)


## 正常終了

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143240/1e885697-622f-39d9-86ac-0196389ae42e.png)
クラスとインスタンスを使って実装しよう③


以下のプログラムを実行するとエラーが起きます。
①エラーが起きた原因
②正しいソースコード


```rb:実行したプログラム
class Student
  def set_name(name)
    @name = name
  end

  def self.introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce
```

①エラーが起きた原因
-
Studentクラスのメソッドintroduceがインスタンスメソッドではなくクラスメソッドになってしまっていること（メソッドの定義にself.がついている）。

```rb:②正しいソースコード
class Student
  def set_name(name)
    @name = name
  end

  def introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce
```


クラスメソッドとインスタンスメソッドを間違えたことによりエラーが起きた問題。

問題文のソースコードでは、introduceメソッドはdef self.introduceと定義されており、クラスメソッドになっています。
※クラスメソッドはメソッド名の先頭にself.をつけたメソッドです。

```rb:問題のソースコード
def self.introduce
  puts "私の名前は#{@name}です。"
end
```

最後の行では、このクラスメソッドintroduceをインスタンスが呼び出してしまっています。クラスメソッドはインスタンスからは呼び出せないので、エラーになります。

問題のソースコード
-
student.introduce # introduceメソッドはクラスメソッドなのでインスタンスstudentからは呼び出せない
introduceメソッドの処理を見ると、インスタンス変数@nameが使われています。@が先頭についた変数はインスタンス変数となり、インスタンスメソッド全てで同じ値が使えるようになります。

今回の問題では以下のインスタンスメソッドset_nameで、インスタンス変数@nameに生徒の名前を代入しています。
※set_nameメソッドはself.がついていないので、インスタンスメソッドです。

```rb:問題のソースコード
def set_name(name)
  @name = name # 引数のnameをインスタンス変数@nameに代入
end
```

問題のソースコード
-
student = Student.new # Studentクラスのインスタンスを作る
student.set_name("山田太郎") # インスタンスメソッドset_nameを呼び出し
set_nameメソッドの@name = nameの箇所では、引数として渡されてきた"山田太郎"という文字列をインスタンス変数@nameに代入しています。
これで、他のインスタンスメソッドの中でも@nameと書くと"山田太郎"という値が使える状態になります。

しかし、クラスメソッドではインスタンス変数は使えません。よってintroduceメソッドの中のputs "私の名前は#{@name}です。"という処理はクラスメソッドの状態では使えないことになります。

問題のソースコード
-
```rb
def self.introduce
  puts "私の名前は#{@name}です。" # @nameはクラスメソッド内では使えない
end
```
そこでintroduceメソッドをクラスメソッドからインスタンスメソッドに変更します。self.を削除するだけです。

```rb
def introduce
  puts "私の名前は#{@name}です。"
end
```
これでintroduceメソッドはインスタンスメソッドになり、puts "私の名前は#{@name}です。"はputs "私の名前は山田太郎です。"という意味になります。

更にintroduceメソッドの呼び出しはインスタンスから行えるようになったので、student.introduceの箇所も動くようになります。

```rb:正しいソースコード
class Student
  def set_name(name)
    @name = name
  end

  def introduce
    puts "私の名前は#{@name}です。"
  end
end

student = Student.new
student.set_name("山田太郎")
student.introduce
```
クラスとインスタンスを使って実装しよう①


クラス名
Human

インスタンスメソッド
メソッド名：hello
メソッドの処理："おはよう"とターミナルに出力する

```rb
class Human
  def hello
    puts "おはよう"
  end
end
```

今回のポイントは以下2つです。
①クラスの定義
②インスタンスメソッドの定義

①クラスの定義
-
まずクラスの定義を行いましょう。クラスの定義はclass クラス名からはじめてendで終わります。

```rb
class クラス名
  # クラスで共通する特徴やメソッドの定義
end
```

今回はクラス名がHumanです。クラス名は先頭の文字を大文字の英語で始めます。2文字目以降は小文字です。
よってクラスの定義は以下になります。

```rb
class Human
  # クラスで共通する特徴やメソッドの定義
end
```
①インスタンスメソッドの定義
-
次にインスタンスメソッドの定義です。インスタンスメソッドは、インスタンスとして作られた個々の値が使えるメソッドです。インスタンスメソッドの定義の方法は一般的なメソッドの定義の方法と同様です。必ずclass Humanとendの間に記載。

```rb
class Human
  def メソッド名
  end
end
```

今回はインスタンスメソッドの名前がhello、メソッドの処理は「おはよう」とターミナルに出力させることです。よって以下のようになります。

```rb
class Human
  def hello
    puts "おはよう"
  end
end
```
引数の基礎


"晴れ" という文字列を引数で渡した時に

明日の天気は晴れです

とターミナルに表示されるようなメソッドを作成。

呼び出し方：get_weather_forecast(“晴れ”)

```rb
def get_weather_forecast(weather)
  puts "明日の天気は#{weather}です"
end

get_weather_forecast("晴れ")
```

「明日の天気は〇〇です」の「〇〇」に任意の文字列（今回は「晴れ」）を表示したいので、引数を使用します。
「〇〇」にはメソッドの呼び出し元の引数に渡した文字列が表示されます。

```
get_weather_forecast("晴れ")
```

そして、文字列を出力するためのget_weather_forecastメソッドを定義します。
引数で渡した文字列を表示させたいので、文字展開を使用しています。

```rb
def get_weather_forecast(weather)
  puts "明日の天気は#{weather}です"
end
```
NVENCを用いた複数並列エンコード【FFMPEG】

# NVENCを用いた複数ストリームエンコード【FFMPEG】

以前の記事で触れたNVENCチップの搭載数と最大セッション数の話
[ffmpeg NVENC についての（個人的な）評価とまとめ](https://qiita.com/Soleiyu/items/712ae291dc732f69afc6)
[Video Encode and Decode GPU Support Matrix](https://developer.nvidia.com/video-encode-decode-gpu-support-matrix)
この意味を最近考えるようになったので検証・まとめを行う
![hoge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/c275af65-ec16-6a77-b74b-26f7bb4c0a2b.png)
このPCに搭載しているGPU (Titan X) は 1GPU, 2NVENC チップを搭載しており、
最大のセッション数は３である

ならば３本まで並列でNVENCを走らせることができる
（確認済み：４本目からエラー）

# 検証環境
## マシン
![hoge2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/8c68524c-3434-5ea7-49e8-af46a45705e8.png)
SSD には PCIe Gen4 接続のものを使用している

## 動画
|No|SIZE| |No|SIZE| |No|SIZE| |No|SIZE|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|01|351MB| |06|320MB| |11|338MB| |16|334MB|
|02|357MB| |07|358MB| |12|338MB| |17|306MB|
|03|329MB| |08|348MB| |13|344MB| |18|329MB|
|04|293MB| |09|363MB| |14|337MB| |19|330MB|
|05|275MB| |10|330MB| |15|340MB|

フルHD, 20Mbps

## ffmpeg コマンド
```
ffmpeg -i 入力動画.mp4 -vf transpose=1 -c:v nvenc -b:v 20M 出力名.mp4
```

90度時計回りに回転させる

# 結果
![hoge3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/a2de841f-4998-d6be-da81-66b5d5368d32.png)
約２倍まで速くなる (x1.85)
３倍にはならなそう

# ソースコード
``` rotate.pl
$inp = $ARGV[0];
$oup = $ARGV[1];

$cmd = "ffmpeg -i ". $inp. " -vf transpose=1 -c:v nvenc -b:v 20M res/".$oup.".mp4";

print $cmd , "\n";
system $cmd;
```
``` main.go
package main

import (
	"fmt"
	"sync"
	"os"
	"os/exec"
)

func main() {
	println(len(os.Args))
	multirote()
}

func multirote() {
	limit := 3
	num := len(os.Args) - 1
	slots := make(chan struct{}, limit)
	var wg sync.WaitGroup
	wg.Add(num)

	for i := 0; i < num; i++ {
		i := i
		slots <- struct{}{}
		go func () {
			fmt.Printf("<%02d/%02d> begin\n", i + 1, num)
			cmd := exec.Command("perl", "rotate.pl", os.Args[i + 1], fmt.Sprintf("%02d", i + 1))
			_, err := cmd.Output()

			if err != nil {
				fmt.Println(err)
			}
			fmt.Printf("<%02d/%02d> done\n", i + 1, num)
			<-slots
			wg.Done()
		}()
	}
	wg.Wait()
}
```

limit の数を変更して、最大並列数を変更する
処理に名前をつけて使おう


以下のプログラムを実行するとエラーが起きます。
①エラーが起きた原因
②正しいソースコード（引数を用いたコードにしましょう）


```rb:実行したプログラム
price = 300

def calculate_price_with_tax
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax
```
解答
①エラーが起きた原因
メソッドの外側で定義した変数は、メソッドの内側では使えない。そのため、1行目のpriceはcalculate_price_with_taxメソッドの中では使えずにエラーが起きてしまった。

②正しいソースコード
-
```rb
price = 300

def calculate_price_with_tax(price)
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax(price)
```


メソッドの中と外は完全に別の世界となっています。そのため、メソッドの中から外にある変数を使ったり、逆にメソッドの外から中にある値を使うことはできません。

唯一、メソッドの中と外を繋ぐ役割が「引数」と「返り値」です。


①エラーが起きた原因
-

解答の通り、エラーが起きた原因は変数priceです。今回の問題文のソースコードには変数priceが2度出てきます。

メソッドの外にある1行目のprice = 300と、メソッドの中にある5行目のprice + price * taxです。

```rb
price = 300

def calculate_price_with_tax
  tax = 0.1
  puts price + price * tax
end
```

メソッドの中では、メソッドの外の変数を使うことができません（変数の使える範囲がスコープ）。

よって今回の問題文のソースコードでは、変数priceの定義はメソッドの外で行なっていたにも関わらず、メソッドの中で変数priceをそのまま使おうとしたことがエラーの原因でした。

②正しいソースコード
```
ではどうすればいいのでしょうか。
スコープの問題を解決するのが、メソッドの中と外を繋ぐ役割を持つ「引数」と「返り値」です。

①メソッドの外から中に値を渡す役割が「引数」
②メソッドの中から外に値を渡す役割が「返り値」

今回は、メソッドの外から中に変数priceを渡すことで問題は解決します。つまり、解決に必要なのは①の「引数」です。

引数の使い方は大きく2ステップです。

メソッドの呼び出しをメソッド名(渡したい値)と書く
メソッドの定義をdef メソッド名(受け取った値を入れる変数名)と書く
では今回の問題に当てはめてみましょう。

1. メソッドの呼び出しをメソッド名(渡したい値)と書く
-
今回、calculate_price_with_taxメソッドに渡したい値は変数priceなので、以下のようにメソッドを呼び出します。

```
calculate_price_with_tax(price)
```

2. メソッドの定義をdef メソッド名(受け取った値を入れる変数名)と書く
2. -
今回は値段の値を受け取りたいので、変数名はpriceにします。今回はメソッドの外の変数名priceと一緒ですが、別の名前にしても大丈夫です。

```
def calculate_price_with_tax(price)
  tax = 0.1
  puts price + price * tax
end
```

よって引数を使って以下のように書き換えれば、問題文のソースコードのエラーは解決します。

```rb
price = 300

def calculate_price_with_tax(price)
  tax = 0.1
  puts price + price * tax
end

calculate_price_with_tax(price)
```
預金システムのアルゴリズム問題

の条件を達成するプログラムを実装。

銀行口座に10万円の預金残高があり、お金を引き出すプログラムを作成します。
・お金を引き出すwithdrawメソッドを作成する
・お金を引き出すと手数料110円かかり、「◯◯円引き落としました。残高は◯◯円です」と表示する（残高は手数料を引いた額を表示します）
・もし預金残高より多く引き落としたら「残高不足です」と表示する

```rb
def withdraw(balance, amount)
  fee = 110　　# 手数料
# 引き落とし額と残高を表示する、もしくは残高より多く引き落としたら残高不足と表示
end

balance = 100000　　# 残高
puts "いくら引き落としますか？（手数料110円かかります）"
money = gets.to_i
withdraw(balance, money)
```

```rb
def withdraw(balance, amount)
  fee = 110
  if balance >= (amount + fee)
    balance -= (amount + fee)
    puts "#{amount}円引き落としました。残高は#{balance}円です"
  else
    puts "残高不足です"
  end
end

balance = 100000
puts "いくら引き落としますか？（手数料110円かかります）"
money = gets.to_i
withdraw(balance, money)
```


13行目で入力した金額（amount）と手数料110（fee）の合計が100000以上か否かを3行目〜8行目で条件づけをしています。100000以上の場合は、balance -= (amount + fee)、つまりbalance = balance - (amount + fee)が処理され、最終的な返り値が出力されます。
任意の文字列を部分的に削除するプログラムの実装


概要
-
対象となる文字列から任意の文字を削除したのち、残った文字列を出力するプログラムを実装。次の要件を満たすmissing_charメソッドを実装。

対象となる文字列からn番目の文字を削除すること
削除された文字以外の文字列を出力すること

雛形
-
```rb
def missing_char(str, n)
  # 処理を記述
end


# 呼び出し例（1つ目の引数には対象となる文字列を、2つ目の引数には対象となる文字列から何番目の文字を削除するのかを指定しましょう）
missing_char('kitten', 1)
```

```rb:出力例：
missing_char('kitten', 1) → 'itten'
missing_char('kitten', 2) → 'ktten'
missing_char('kitten', 4) → 'kiten'
```

 slice!メソッド
-
slice!メソッドは、配列や文字列から指定した要素を削除し、削除した後の要素を返すメソッドです。末尾にエクスクラメーションマーク(!)のつくメソッドを破壊的メソッドといいます。これはもとの配列や文字列を変化させるメソッドです。

```rb
string = "abcdefg"
string.slice!(2)

puts string
#=> "abdefg"
# 2番目の要素のcが取り除かれている
```

```実装コード
def missing_char(str, n)
  str.slice!(n - 1)
  puts str
end

# 呼び出し例
missing_char('kitten', 1)
```


missing_charメソッドの引数strには対象となる文字列、nは何番目の文字を消すのか指示する数字を入れる仕様。

```rb
def missing_char(str, n)
```

例えば、呼び出し元がmissing_char('kitten', 1)であれば、1行目のmissing_charメソッドの仮引数strには'kitten'が入り、nには1が入るということです。

そして、2行目のslice!メソッドの引数には、nから1を引いた数を設定しています。
なぜ1を引くのかというと、文字列の順番を指定する際も、配列と同じように先頭の文字列
は0からカウントされるためです。
よって、下記のように記述することで、nから1を引いた数字に該当する文字列をstrから削除することができます。

```rb
str.slice!(n - 1)
```
【php】処理速度を調査する

```php
<?php
$loop = 100000000;
$sum  = 0;
// 開始時間を取得
$time_start = microtime(true);
 
for ($i = 1; $i <= $loop; $i++) {
   $sum = $sum + $i;
}
print '1から' . $loop . 'まで足した合計値は' . $sum ."\n";
// 終了時間を取得
$time_end = microtime(true);
$time = $time_end - $time_start;
echo '実行に要した時間は' . round($time,3 ). '秒です。';
```


実装結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/af73c745-62f9-e0de-adf0-62eb3af09aa6.png)

```php
<?php

$loop = 150000000;
$sum  = 0;

$start = hrtime(true); // 計測開始時間

// 計測したい処理

for ($i = 1; $i <= $loop; $i++) {
   $sum = $sum + $i;
}


$end = hrtime(true); // 計測終了時間

// 終了時間から開始時間を引くと処理時間になる
echo '処理時間:'.($end - $start).'ナノ秒';

?>
```
2つの文字列の末尾に対して一致・不一致を判断するプログラムの実装


概要
-
2つの文字列の末尾の文字を比較して、一致する場合はTrue、一致しない場合はFalseを出力するプログラムを実装。次の要件を満たすend_otherメソッドを実装。

メソッドの引数に、任意の2つの文字列を指定する。
引数に指定された2つの文字列のうち、どちらかがもう一方の文字列の末尾にある場合は、Trueを出力する
上記を満たせていない場合は、Falseを出力する
入力された文字が大文字でも小文字でも、同一の文字として処理を行う

雛形
-
```rb
def end_other(a, b)
  # 処理を記述
end
```

```rb:呼び出し例
end_other('Hiabc', 'abc') 
```

```rb:出力例
end_other('Hiabc', 'abc') → True
end_other('AbC', 'HiaBc') → True
end_other(‘abc’, ‘HaIoBc’) → False
```


sliceの範囲指定
範囲を指定して要素を切り取る場合は、以下のように記述して使うことができます。


要素を定義
-
```
array = "Hiabc"
```
配列番号（インデックス番号）の-3から-1の範囲の文字列を切り取る

```
array.slice(-3..-1)
#=> abc
downcase
```
downcaseメソッド
-
大文字を小文字に変換するメソッドです。

```rb:ターミナル
# 大文字を含んだ文字列を定義
irb(main):001:0> name = "Hiabc"
=> "Hiabc"

# downcaseメソッドを使用し、小文字に変換
irb(main):002:0> name.downcase
=> “hiabc”
```

```できあがり実装
def end_other(a, b)
  a_down = a.downcase
  b_down = b.downcase
  a_len = a_down.length
  b_len = b_down.length
  if b_down.slice(-(a_len)..- 1) == a_down || a_down.slice(-(b_len)..- 1) == b_down
    puts "True"
  else
    puts "False"
  end
end
```

```rb:呼び出し例
end_other('Hiabc', 'abc') 
```

大文字と小文字を区別しないという条件のため、2〜3行目で任意の2つの文字列を小文字に変換しています。

4〜6行目でどちらかの文字列がもう一方の文字列の最後にある場合を区別するための処理を行っています。
slice(-(a_len)..- 1)としているのは、対象の文字列分を切り取るための記述です。

たとえば、以下のようにend_other('Hiabc', 'abc')でメソッドを呼び出し、実行した場合を考えてみましょう。

```rb
def end_other(a, b)
  a_down = a.downcase
  b_down = b.downcase
  a_len = a_down.length
  b_len = b_down.length
  if b_down.slice(-(a_len)..- 1) == a_down || a_down.slice(-(b_len)..- 1) == b_down
    puts "True"
  else
    puts "False"
  end
end

end_other('Hiabc', 'abc') 
```
すると、2〜5行目で以下のように処理されます。

```rb
a_down = hiabc
b_down = abc
a_len = 5
b_len = 3
```

続いて6行目で、abcの最後にHiabcが含まれているか、Hiabcの最後にabcという文字列が含まれているかを判別しています。

まずは、条件式の左辺を見て見ましょう。
b_down.slice(-(a_len)..- 1)は、b_down.slice(-5..-1)となります。しかし、b_down = abcとなっているので、インデックス番号-5から-1という条件で切り取ることができません。そのため、この部分はnilとなります。結果、nil == a_downは等しくないと評価されるので、falseになります。

続いて、条件式の右辺を見てみましょう。
a_down.slice(-(b_len)..- 1)はと、a_down.slice(-3..-1)となります。ここで、hiabcという文字列の最後にabcが含まれているかを確認したいので、abcという文字列分を左から数えます。すると、hiabcの最後までを範囲指定していることがわかります。そしてa_down = hiabcとなるので、インデックス番号-3から-1という条件で切り取るとabcが残ります。結果、abc == b_downは等しいと評価されるので、trueとなります。
正規表現メモ

# メモ
## 氏名のように全角のみ入力可としたい
文字プロパティを使う。

### Editor等
```test.sh
# 漢字
\p{Han} 
# カタカナ
\p{Katakana}
# ひらがな
\p{Hiragana}
```

### Java
Isを付ければOK。

```test.java
Pattern.compile("\\p{IsHan}");
Pattern.compile("\\p{IsKatakana}");
Pattern.compile("\\p{IsHiragana}");
```

## 半角カナは拒否したい。
Unicodeのレンジチェックを行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/1c4c69ee-ed77-7679-36cc-7857815a5159.png)

### Editor等
```test.sh
([\x{ff66}-\x{ff6f}]|[\x{ff71}-\x{ff9f}])
```

### Java
```test.java
Pattern.compile("([\uFF66-\uFF6F]|[\uFF71}-\uFF9F])");
```

#### \uFF66-\uFF6F
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/79b2086a-40a9-75ef-fec3-1ed1b5dad9c9.png)

#### \uFF71}-\uFF9F
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/3e6090b6-d436-d57b-ae9c-e1bcd7bcb9ee.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/4b5dc92e-8cc0-e929-6bf1-e88dbf828c68.png)

# 参考
[Pattern Javadoc](https://docs.oracle.com/javase/jp/8/docs/api/java/util/regex/Pattern.html)
[[連載:正規表現] Unicode文字プロパティについて (3) 文字プロパティとは](https://techracho.bpsinc.jp/hachi8833/2013_10_15/13889)
[Unicode Scripts-13.0.0.txt](http://www.unicode.org/Public/UNIDATA/Scripts.txt)
[図書館員のコンピュータ基礎講座 Unicode半角](http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/uff00.html)
FizzBuzz問題応用


FizzBuzzという言葉遊びがあります。1から数を数えていく際に、それが3の倍数だったら「Fizz」, 5の倍数だったら「Buzz」と言う、というもの。ただし、15の倍数の時は「FizzBuzz」と言います。

例） 1, 2, Fizz, 4, Buzz, Fizz ,,,,

このFizzBuzzを再現できるメソッドを作成。いくつまでカウントするか、引数で指定できるものとします。

```rb:雛形
def fizzbuzz(max_num)
  if 

  elsif

  elsif

  else

  end
end

puts 'いくつまで数えますか？'
num = gets.to_i
fizzbuzz(num)
```

 範囲を指定して繰り返し
範囲を指定して繰り返しをする場合は、範囲演算子(..)を使用。
以下のように使用します。

1
(開始する値..終了する値）
具体的には以下のように使用できます。

```rb
# 1～6までの範囲を指定して、繰り返し表示
(1..6).each do |num|
  puts num
end
```

```rb
def fizzbuzz(max_num)

  (1..max_num).each do |num|
    if num % 15 == 0
      puts "FizzBuzz"
    elsif num % 5 == 0
      puts "Buzz"
    elsif num % 3 == 0
      puts "Fizz"
    else
      puts num
    end
  end
end

puts 'いくつまで数えますか？'
num = gets.to_i
fizzbuzz(num)
```


3行目で範囲演算子..を使用して、1から入力した値までを繰り返し処理します。

4行目以下で値によって条件分けが行われます。

例えば、入力した値が15だった場合、1~15までの範囲で、条件分岐の処理が繰り返し行われます。
ターミナルの出力は、以下のように結果になります。

```rb
いくつまで数えますか？
15

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
# 15まで繰り返すので、ここで処理が終了します
```
C++ の未定義動作を書く人は、何が起こっても知ーらないっ！

## プロローグ
先日、このような質問を受けました。

> 何故このコードは無限ループするのですか？配列外参照しているのはわかるけど、`i` は確かに増え続けてるし、`while` の条件に引っかからないのはおかしい！

### コード

```C++
#include <iostream>
using namespace std;

int main() {
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  int i = 0;
  while (i <= 10) {
    cout << "i = " << i << " a[i] = " << a[i] << endl;
    i++;
  }
}
```

### 出力
[AtCoder のコードテスト](https://atcoder.jp/contests/arc119/custom_test) で、C++ (GCC 9.2.1) を選択し上記のコードを提出すると、再現するかもしれません（この記事の落ちを先に書きますが、未定義動作なので再現しないかもしれません。）

```
i = 0 a[i] = 1
i = 1 a[i] = 2
i = 2 a[i] = 3
i = 3 a[i] = 4
i = 4 a[i] = 5
i = 5 a[i] = 6
i = 6 a[i] = 7
i = 7 a[i] = 8
i = 8 a[i] = 9
i = 9 a[i] = 10
i = 10 a[i] = -2143330816
i = 11 a[i] = -592414315
i = 12 a[i] = 0
i = 13 a[i] = 0
i = 14 a[i] = -1500878016
...
```
`i = 10` のときに配列外参照が起こっています。
出力を見ると、明らかに `i > 10` なので、`while` を抜けて欲しい気持ちにはなります。ですが、そんな甘い考えは、偉大なコンパイラ様には伝わりません。

## 未定義動作とは
私の尊敬する先輩の記事を読んでください。

https://rsk0315.hatenablog.com/entry/2019/09/10/213859

配列外参照やゼロ除算などは未定義動作ですが、必ずしも実行時エラーになるとは限りません。
未定義動作をプログラマーが書いた場合、**何が起こるかわからない** というのが正しいです。

理由は、コンパイラが以下のような動作をすることが仕様で許されているからです。

- 未定義動作は起こらないと仮定してよい
- 起こらないのだから，無視して最適化してよい

## 今回の例で何が起こってるかの予想
今回の例では、配列外参照をしているので、未定義動作を書いていることになります。その時点で、プログラムが何をしても文句は言えないのです。（仮に、あなたの PC の全データを消去されても、文句は言えません。）

ただ、コンパイラはそこまで意地悪ではないし、むしろ親切です。親切なので、未定義動作なんて存在しないものと仮定し、最適化を試みます。

今回の例で、なぜ無限ループが起こってしまったのかを僕なりに予想して、コンパイラ君の気持ちを代弁してみると、

- コンパイラ君「よし、コンパイルするぞ！」
- コンパイラ君「配列 `a` の長さは `10` だね！」
- コンパイラ君「`while` に初めて入るとき、`i = 0` だから `i <= 10` は `true` だね」
- コンパイラ君「`i` は `a` の添え字になってるね、**配列外参照になることなんてないから**、`cout << a[i]` の時点で `i < 10` が成り立つね」
- コンパイラ君「次の行で、`i++` されても、`i <= 10` が常に成り立つね」 
- コンパイル君「よし、`while (i <= 10)` は常に `true` だから `while (true)` に置き換えよう！こうすることで、毎回条件式を判定するコストが減らせるね！！！さすが僕、最適化のプロ」

と、なっているのだと予想されます。（あくまで予想です。）

### 最適化後のコード（予想）
```C++
#include <iostream>
using namespace std;

int main() {
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  int i = 0;
  while (true) {
    cout << "i = " << i << " a[i] = " << a[i] << endl;
    i++;
  }
}
```

## エピローグ
コンパイラは未定義動作が起こらないと仮定して最適化を行います。
人間がうっかり未定義動作を書いてしまう可能性なんて微塵も考えていないわけですね。


コンパイラ君と少しでも分かり合うためには、普段から未定義動作を書かないように努力する必要がありそうです。



## 追記（5/22 01:56）
未定義動作を踏んではいるが、例えば、

```
i = 0 a[i] = -2143330816
i = 1 a[i] = -592414315
i = 2 a[i] = 0
i = 3 a[i] = 0
i = 4 a[i] = -1500878016
...
```

のような出力にはならないことが保証されているはずです。
C++ コンパイラには **as-if rule**[^asif] というものがあり、**外から見た動作 (observable behavior)**[^ob] については、コードに書かれた通りに実行するように振る舞うことが約束されています。

なので、配列外参照をするまでは、出力についてはまともな挙動をすることが保証されているわけです。


## 追記（5/22 14:23）
どうやら、タイムトラベルも認められるようです。読み物として面白いので、興味がある方は [これ](https://cpplover.blogspot.com/2014/06/old-new-thing.html)[^time] を読んでください。


[^asif]: https://en.cppreference.com/w/cpp/language/as_if
[^ob]: https://qiita.com/akinomyoga/items/592e5a3b8438a0c8556b
[^time]: https://cpplover.blogspot.com/2014/06/old-new-thing.html
特定の数値の個数を算出するプログラムの実装


概要
-
複数の数字が格納されている配列に、「9」が何個含まれているかを出力するプログラムを実装
以下の要件を満たすarray_count9メソッドを実装。

2つの文字列の末尾の文字を比較して

配列の中の数字に対して、9の個数を数える
数えた9の個数を出力する

雛形
-
```rb
def array_count9(nums)
  # 処理を記述
end
```

```rb:呼び出し例
array_count9([1, 2, 9]) 
```
```rb:出力例
array_count9([1, 2, 9]) → 配列の中には9が1個です
array_count9([1, 9, 9]) → 配列の中には9が2個です
array_count9([1, 9, 9, 3, 9]) → 配列の中には9が3個です
```

countメソッド
-
countメソッドは、引数に指定した数字に一致するものの個数を数え、その結果を返すメソッドです。

```rb
ary = [1, 2, 4, 2]

ary.count(2)
 # => 2
```

```rb
def array_count9(nums)
  count = nums.count(9)
  puts ("配列の中には9が#{count}個です")
end
```

```rb:呼び出し例
array_count9([1, 2, 9]) 
```

「ヒント」で紹介したとおり、countメソッドを使用することで指定した数字に一致するものの個数を数えることができます。

上記を踏まえて、array_count9([1, 9, 9])でメソッドを呼び出した場合、
nums.count(9)では、numsの中に9が2個あると処理されます。結果、配列の中には9が2個ですと出力されます。
文字の順番を入れ替えて出力するプログラムの実装

任意の文字列から指定した範囲の文字を最後尾に移動させた状態で、その文字列を出力するプログラムを実装
-

以下の要件を満たすleft2メソッドを実装
-

任意の文字列の最初の2文字を取得する
取得した2文字を最後尾に移動させた状態で、その文字列を出力する

雛形
-
```rb
def left2(str)
  # 処理を記述
end
```

```rb:呼び出し例
left2("Hello") 
```

```rb:出力例
left2("Hello") → lloHe
left2("java") → vaja
left2("Hi") → Hi
```

引数の文字列に対して範囲指定を行い、指定した要素を取得。
文字列に対して配列同様に[]を用いて取得したい文字列のインデックスを指定することで、値を取得できます。

```rb
str = “HELLO”

puts str[1]
# => 1
```
また、2つ以上の文字列を取得したい場合は、取得したい値の範囲を指定することで可能です。

```rb
def left2(str)
  puts str[2..-1] + str[0..1]  
end
```

```rb:呼び出し例
left2("Hello") 
```

①str[2..-1]で3文字目から最後まで、②str[0..1]で最初の2文字を取得しています。
任意の文字列のうち、最初の2文字を最後尾に移動させた状態で出力したいので、①→②の順で出力します。

たとえば、left2("Hello")でメソッドを呼び出した場合は、以下のように処理されます。

```rb
str[2..-1] = llo
str[0..1] = He
```

最終的には、lloHeと出力されます。
末尾の文字列を3回出力するプログラムの実装

概要
-

本ドリルでは、対象の文字列の末尾に位置する文字を取得し、それらを任意の回数繰り返して出力するプログラムを実装します。

以下の要件を満たすextra_endメソッドを実装
-

対象の文字列から末尾にある2文字を取得すること
取得した2文字を3回繰り返して出力すること

雛形
-
```rb
def extra_end(str)
  # 処理を記述
end
```

```rb:呼び出し例
extra_end('Hello') 
```

```rb:出力例：
extra_end('Hello') → 'lololo'
extra_end('ab') → 'ababab'
extra_end('Hi') → 'HiHiHi'
```

 sliceメソッド
-
sliceメソッドとは、配列や文字列から指定した要素を取り出すことができるメソッドです。


配列を作成します
-
array = [0,1,2,3,4,5,6]

配列から引数で指定した要素を取得します
-
```rb
ele1 = array.slice(1)
puts ele1
#=> 1
```

配列番号-4から4つ分の要素をsliceします
-
```rb
ele2 = array.slice(-4,4)
puts ele2
#=> 3, 4, 5, 6
```

配列はもとのままです
-
```rb
puts array 
#=> [0,1,2,3,4,5,6]
```

```rb
def extra_end(str)
  right2 = str.slice(- 2, 2)
  puts right2 * 3
end
```

呼び出し例
-
```rb
extra_end('Hello') 
```


extra_end('Hello')でメソッドを呼び出します。

まず、1行目のextra_endメソッドの仮引数strには対象の文字列’Hello’が格納されます。
そして、2行目ではstrに対してsliceメソッドを使用し、指定した要素を取り出しています。

sliceメソッドの1つ目の引数では、文字列（Hello）の後ろから2番目の要素を基準点としています。
そして、2つ目の引数により、基準点から2つ分の要素を取り出しています。
今回の場合、「H,e,l,l,o」の後ろから2番目の要素は「l」です。そして、基準点「l」から2つ分の要素である「lo」が取り出されるので、end_str = loとなります。

最後に、2 * 3と記述することによって、「lololo」と出力されます。
【React】export defaultとexportの違いと対応するimport をざっくりまとめる

<h2>export default</h2>

export defaultでは中括弧をつけて、componentをimportします。

export defaultでは、ファイル一つに対して一つのみexportできます。

```react:export_default
export default Index {

}
```

```react:export_defaultしたcomponentをimport
#そのままimport
import Index from "./index";

#名前指定する場合
import Hoge from "./index";
```

<h2>export(defaultなし)</h2>

exportで参照できるようにした値は、中括弧をつけることでimportします。

exportでは一つのファイルで複数exportでき、importも複数importできます。

```react:export
export Index {

}
```

```react:exportしたcomponentをimport
#そのままimport
import {Index} from "./Index";

#名前を指定する場合
import {Index as Hoge} from "./index";

#componentから複数の値をimportする
import {Index,IndexHoge} from "./index";
```


<h2>参考</h2>
https://zenn.dev/yumiyoshi/scraps/ba0e53a2cdf40c

https://engineering.linecorp.com/ja/blog/you-dont-need-default-export/
特定の数字を検知する

特定の数字が存在するかどうかを判定するプログラムを実装します。


配列内に1,2,3が全て入っている場合は、「True」と出力すること
配列内に1,2,3の全てが入っていない場合は、「False」と出力すること

雛形
-
```rb
def array123(nums)
  # 処理を記述
end
```

```rb:呼び出し例
array123([1, 1, 2, 3, 1])
出力例
array123([1, 1, 2, 3, 1]) → True
array123([1, 2, 4, ]) → False
array123([1, 1, 2, 1, 4, 3]) → True
```

include?メソッド
```
include?メソッドは指定した値が、配列中に含まれているかを判定するメソッドです。指定した値が含まれている場合はtrueを、含まれていない場合はfalseを返り値として返します。
```

```rb
array = ["foo", "bar"]
puts array.include?("bar")
#=> true
puts array.include?("hoge")
#=> false
```

```rb
def array123(nums)
  if nums.include?(1) && nums.include?(2) && nums.include?(3)
    puts "True"
  else
    puts "False"
  end
end
```

例)array123([1, 1, 2, 3, 1])

まず、1行目のarray123メソッドの仮引数numsには、対象の配列’[1, 1, 2, 3, 1]’が格納されます。

そして、2行目では「配列に123が全て含まれている場合は”True”を出力する」という条件分岐を行うために、if文を使用しています。また、仮引数として受け取った配列numsに1,2,3が全て含まれているかを判断するために、include?メソッドを使用しています。

さらに、&&演算子を複数使用することで、以下のように条件式の条件を複数設定することが可能です。

```rb
  if nums.include?(1) && nums.include?(2) && nums.include?(3)
    puts "True"
  else
    puts "False"
  end
```
偶数値の取得


配列にある値の中から偶数の数をカウントして出力するメソッドを作ります。

```rb:出力例：
count_evens([2, 1, 2, 3, 4]) → 3
count_evens([2, 2, 0]) → 3
count_evens([1, 3, 5]) → 0
```


even?メソッド
-
Rubyが元々用意している、対象の数値が偶数かどうかを判断するメソッドです。
対象の要素の値が偶数であれば真を返し、そうでない場合は偽を返します。

```rb
def count_evens(nums)
  count = 0
  nums.each do |num|
    if num.even?
      count += 1
    end     
  end
  puts count
end
```

配列の中の偶数の数を出力するためにカウントした数を保持するための変数が必要なので、変数countを用意しています。変数countをeach文のループ処理内に記述すると、処理が繰り返されるたびにcount = 0が実行され、countの数値が0に上書きされてしまいます。そのため、countの定義はeach文のループ処理外で行います。

配列に入っている数字をeach文で取り出し、even?メソッドで一つずつ偶数かどうかを確認し、偶数だった場合はcountに1を足していきます。

countに1を追加するための記述はcount = count + 1でも可能ですが、自己代入演算子を使用するとシンプルに記述できるため積極的に使用していきましょう。

each文の処理が終了し、countに代入された最終的な数が偶数の数となります。
スクラムの初心者が読む記事

スクラムではアジャイル開発の内容と重複する箇所が多いため、本記事では重複箇所の記載は極力省略しています。
省略しているアジャイル開発の部分については、過去に投稿した以下の記事をご参照ください。

https://qiita.com/kazuki_kuriyama/items/930a692a4f5fbfb9fd2c

# スクラムとは
アジャイル開発の手法のうちの一つで、不確定な要素の多い開発に適しているフレームワークです。


# スクラムの特徴
* 5つのイベント、３つのロール、３つの作成物がある。

# スクラムの5つの価値基準
スクラムで良い結果を出すには下記の価値基準を取り入れる必要がある。

* 確約<BR>
ゴール達成に全力を尽くす
* 勇気<BR>
困難な問題にも取り組む
* 集中<BR>
作業・ゴールの達成に集中する
* 公開<BR>
仕事や問題を全て共有する
* 尊敬<BR>
互いに尊敬し合う

# スプリントの流れ
以下を１スプリントとして、最大1か月以内の固定された期間のタイムボックスに設定する。
1. スプリントプランニング<BR>
次のスプリント内での作業を決定する。
1. 作業実施<BR>
スプリントバックログから作業を実施し、インクリメントを作成する。
1. スプリントレビュー<BR>
インクリメントのデモとフィードバックを行う
1. スプリントレトロスペクティブ<BR>
改善事項を協議する。

# 注意事項
最低限のルールのみが規定されているため、実運用にはテーラリングが必要。
1,2年毎に改定されているので、最新版を採用したい場合、常にアンテナを張っておく必要がある。


# スクラム開発の用語（暫定版、別途スクラムのページとして後日まとめる予定です。）

## ロール
人の役割

#### プロダクトオーナー
プロダクトの責任者または出資者、利用者、管理職などの利害関係者で最終決定権限を持つが、開発チームに干渉してはいけない。できるのは、あくまで相談のみ。
リリーススケジュールや予算を管理を行う。
プロダクトバックログの管理や項目内容のメンバーへ共有する。

#### 開発チーム
* 効率的に開発を進めるには3人から9人程度のメンバーにする。
* 9人を超える場合、チームを分割する。
* 自己組織化されている（主体的な行動や自走ができる）必要がある。

#### スクラムマスター
* スクラムによるプロジェクトが円滑に回る様に調整する役割で、教育やファシリテータ、コーチ、推進役を担うサーバントリーダー。
* メンバー外の人からの妨害や割り込みからチームが干渉を受けない様に守る。
* マネージャーや管理者ではないので、メンバーへのタスクのアサインや進捗管理は行わない。
* プロダクトオーナーやチームに対してスクラムについて説明し理解を広める。
* 会議では進行役を担う。

#### スクラムチーム
* プロダクトオーナー、開発チーム、スクラムマスターを合わせたチーム


## その他

#### スプリント
* 利用可能な、リリース判断可能なプロダクトを作るための、1 か月以下のタイムボックスのことで、
1～2週間で設定されるのが一般的である。
* 期間の長さを変更してはいけない。開発が遅延している状態でも変更しない。

#### プロダクトバックログ
* 実現したい機能の見える化として一覧表にする。
* 上位の項目は見積もりを行う。
* 記載する情報は常に最新に保つ。
* 実現したい項目の順番で整列する。
* ユーザーストーリーで記述されることが多い
* 管理はプロダクトオーナーが行う
* 実装する機能が価値のある根拠や仮説がないものは記載しない。

#### プロダクトバックログリファイメント（リファイメント）
バックログ内の項目に対して下記のアクションを実施すること
* 具体化
* 疑問点の解決
* 達成基準の明示
* 工数見積もり
* サイズ分割

#### スプリントプランニング(スプリント計画会議)
スプリントゴールの決定
スプリントバックログの選定

#### スプリントバックログ
* スプリント中に実施するタスク一覧
* 各タスクは１日で終わる分量にする。
* 作業者自身がどのタスクを実施するのか選定する。

#### インクリメント　
これまでの全てのスプリントの成果で、動作している状態のもの。

#### 完成の定義
スプリントの実施範囲で、以下の項目等が挙げられる。
* コードレビュー
* ユニットテスト
* 受入テスト
* デプロイ　等


#### イベント
会議等

#### デイリースクラム
≒朝会（ただし朝にしなくてもよい）

* 毎日同じ時間、同じ場所で進捗の確認を15分間行い、延長は禁止とする。
* 確認項目は実施した内容、本日の予定、困っていること等の障害報告の3点。
* 障害については、解決する場はデイリースクラム終了後に別で設定する。


#### スプリントレビュー
* プロダクトオーナーが主催し、スプリントの最後にインクリメント（それまでの成果物）をステークホルダーにデモし、以下の報告・議論を行う。
    * 完成していないプロダクトバックログの項目の報告
    * 現在の問題点の報告
    * プロダクトバックログの追加項目の議論
    * スケジュールの共有

#### スプリントレトロスペクティブ
* スプリント毎のふりかえり
* 改善点の整理やアクションプランを作成する場だが、一度にたくさんの変更を行わないこと。
indexメソッド

 検索
-

任意の文字列に"code"が、左から何文字目に出てくるかを返し、その数を出力するメソッドを作ります。

```rb:出力例：
count_code("codexxcode") → 1
count_code("aaacodebbb") → 4
count_code("cozexxcode") → 7
```

indexメソッドを使用します
-
 index
indexメソッドは、文字列や配列の中に指定した文字列が含まれていた場合、その文字列の開始位置を整数の値で返します。

```
str.index(検索したい文字列, [検索を開始する位置])
```

```
def count_code(str)
  puts str.index("code", 0) + 1
end
```

indexメソッドは文字列の先頭を0から数えた数字を返すため、+1をしています。

また、文字列の先頭から検索を開始する場合、第二引数は省略が可能です。
そのため、下記のようにコードを書き換えることが可能です。

```rb
def count_code(str)
  puts (str.index("code") + 1)
end
```
遅延レスポンスをテストできるAPI２選（意外とない）

遅延レスポンスをテストできる無料のAPIないかなぁと探して見たら、このサイトを見つかりました。
１．

https://httpbin.org/

delay の他に、機能いろいろありますが、詳細はこの記事は詳しく書いてあるので、こちらを参照
https://qiita.com/sameyasu/items/adacceb8a1bee893599b

```shell
# 3秒後結果を帰って来る
curl -X GET "https://httpbin.org/delay/3" -H "accept: application/json"
```

２．

https://deelay.me/

```shell
# 5秒後本当に行きたいサイトに飛ぶ
https://deelay.me/5000/https://picsum.photos/200/300
```

ちょっとテストしたいときは使えるね！
ぶっちゃけ delay ぐらいなら自分で 10 で作れますが、めんくさいので。。。。

３．
ssl の状態をテストできるサイド（これは最高だ！！）

https://badssl.com/

以上
eachの入れ子

 eachの入れ子
-

以下のように、果物の名前と値段が入った配列があります。
この配列を用いて、果物の名前とそれぞれの合計額が出力されるコードを記述します。

```rb
fruits_price = [["apple", [200, 250, 220]], ["orange", [100, 120, 80]], ["melon", [1200, 1500]]]
```

```rb:（出力）
appleの合計金額は670円です
orangeの合計金額は300円です
melonの合計金額は2700円です
```


```rb:コード
fruits_price = [["apple", [200, 250, 220]], ["orange", [100, 120, 80]], ["melon", [1200, 1500]]]

fruits_price.each do |fruit|
  sum = 0
  fruit[1].each do |price|
    sum += price
  end
  puts "#{fruit[0]}の合計金額は#{sum}円です"
end
```


最初に、3行目でfruits_priceから["apple", [200, 250, 220]]という値を取り出し、変数fruitに代入します。その後4行目〜7行目で、fruitの1番目の値[200, 250, 220]から値を1つずつ取り出して、自己代入しながらsumを出力します。丁寧に見ると以下のようになります。

```rb:1回目
sum = 0
#sum += priceはsum = sum + priceと解釈できる
sum = 0 + 200
# 返り値
sum = 200
```
```rb:2回目 
#sumは1回目の200という値が返されます
sum = 200
sum = 200+ 250
sum = 450
```

```rb:3回目 
#sumは2回目の450という値が返されます
sum = 450
sum = 450+ 220
sum = 670
```
この結果、appleの合計金額は670円ですと出力されるようになります。この作業を残り2つorange、melonでも繰り返します。
2重ハッシュ 


配列の内部に、複数のユーザーの情報をハッシュとして持つ変数user_dataがあります。

```rb
user_data = [
 {user: {profile: {name: 'George'}}},
 {user: {profile: {name: 'Alice'}}},
 {user: {profile: {name: 'Taro'}}},
]
```

user_dataを利用して、全てのユーザーの名前だけが出力されるようにRubyでコーディングします。
ただし、出力結果は次のようになるものとします。

```terminal
George
Alice
Taro
```

```rb
user_data.each do |u|
  puts u[:user][:profile][:name]
end
```

あるいは

```rb
user_data.each{ |u| puts u.dig(:user, :profile, :name) }
```

ハッシュから特定の値を取得する場合は、その値に対応するキーを指定します。以下の書き方で取得ができます。

```rb
ハッシュ[取得したい値のキー]
```

また、二重ハッシュから特定の値を取得する場合は、取得したい値のキーまで連続して指定すると取得できます。

```rb
ハッシュ[取得したい値のキー][取得したい値のキー]
```

今回取得したい値は、George, Alice, Taroという値です。
よって、取得したい値に対応するキーはnameというキーだということが分かります。
そのため、nameというキーまで連続して指定すると、George, Alice, Taroという値を取得できます。

```rb
ハッシュ[:user][:profile][:name]
```

また、今回は配列の中にハッシュが格納されています。
そのため、each文でハッシュの1つ1つを取り出した上で、上記の記述を行うことが必要です。


```rb
user_data.each do |u|
  puts u[:user][:profile][:name]
end
```
Git $ git log コマンドで修正した過去コミットで修正したソースの差分を出力する

# 目的

- `$ git log`コマンドを実行した際、過去コミットで修正したソースを出力する方法をメモ的にまとめる

# 方法

- `-p`をつけて`$ git log`コマンドを実行する。

    ```terminal
    $ git log -p
    ```