OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptのクラスとJSONの相互変換

#SkayWayでデータを送信したい

SkyWay使ってたらStreamと別のデータを送りたいと思い、クラスをJSON,JSONをクラスに変換したくなった
が、調べても出てこなかったのでメモ

[リファレンス](https://webrtc.ecl.ntt.com/android-reference/classio_1_1skyway_1_1_peer_1_1_room.html#adc87abbe83dff60e6fa322064eff7e48)曰く、`String`と`byte[]`で送信できる

なので、`JSONで文字列→送信して→・・・→文字列で受信→クラスに戻す`を目指す

##送信するクラス
データ内容は自作のクラス

```Vec.js
class Vec{
  constructor(x,y){
    this.x = x;
    this.y = y;
  }
}
Vec.prototype.toString = function(){
  return '(' + this.x + ',' + 'this.y' + ')';
}
```

##送信する関数
上記の`Vec`クラスのデータを以下の`Send`関数に投げればいいようにします

```なんかそこらの関数.js
function Send(msg){
  room.send(msg);
}
```

##受信する関数

```受信します.js
function setupRoomEventHandlers(room){
  room.on(`stream`,function(stream){
    接続時の処理;
  });
  //他、peerLeaveとかcloseとかの関数
  //略

  //room.sendで送信したデータは「data」で受信する
  room.on('data',function({data,src}) => {
    //ここに受信時の処理
  });

}
```

#クラスからJSON (class to JSON)
`JSON.stringigy(クラス)`でJSONにできるので
送信したいタイミングでこんな感じにしてマウスの位置送信します

```
Send(JSON.stringigy(new Vec(mouseX,mouseY)));
```

#JSONからクラス（JSON to class）
受信データは`Object`が届くので、
[JSON.parse](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)でJSONにして、[Object.assign(クラス,json)](https://stackoverflow.com/questions/52315147/json-to-javascript-class)でクラスを復元します
なので、

```受信します.js
function setupRoomEventHandlers(room){
  //略

  //room.sendで送信したデータは「data」で受信する
  room.on('data',function({data,src}) => {
    let json = JSON.parse(data);
    console.log(Object.assign(new Vec(),json));
  });

}
```

とすることでこのように↓受信できたので、`JSON to class` & `class to JSON`ができましたとさ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/9ccc6f0b-6af8-3dbe-c7a1-fa353243fe0a.png)
めでたしめでたし
Excelアドイン（VSTO）で非同期処理中にユーザーからのUI変更を受け付けなくする方法

# 開発環境

- Windows 10 Home
- Microsoft Visual Studio Community 2019 Version 16.8.4
- Microsoft .NET Framework Version 4.8.03752

# はじめに
最初に起動するスレッドとは別に、重たい処理を走らせるために非同期でタスクを立ち上げ、そのタスク内からUIを触る（例：editBox.Text = "test"）と、例外エラーで落ちます。

今回は非同期処理中にUIを触れるようにする方法、ではなく
**ユーザがUIに触れなくする方法**について記します。

テキストボックスやボタンは、プロパティのEnabled属性をFalseに変更すればOKです。
ここでは、**シート内のセルへのアクセスを無効化**する方法について説明します。

## 対応前：非同期処理
Threadを使うのは古い方法みたいなので、async/awaitを利用します。

詳しい説明は[コチラ](https://qiita.com/hiki_neet_p/items/d6b3addda6c248e53ef0)

``` C#
private async void func(...)
{
    await System.Threading.Tasks.Task.Run(() =>
    {
        // 重たい処理
        editBox.Text = "test";    //  ※ここでUIを触ると例外エラー！
    });
}
```

## UI部品の無効化
UI変更時の見栄え改善と処理時間短縮のために描画の更新を停止します。

``` C#
Globals.ThisAddIn.Application.ScreenUpdating = false;
```

リボン（Ribbon）内のUIコントロールを全部OFFするには下記のようにしますが、

``` C#
foreach (RibbonGroup group in Globals.Ribbons.Ribbon1.tab_アドイン名.Groups)
{
    foreach (RibbonControl ctrl in group.Items)
    {
        ctrl.Enabled = enable;
    }
}
```

この対応では、シート内のセルにアクセスできてしまい、エラーが発生するので
代わりに、キーボードおよびマウスからの入力を止めます。
※ 確実にエラーハンドリングして、最後はtrueに戻してください。

``` C#
Globals.ThisAddIn.Application.Interactive = false;
```

## 対応後のイメージ

``` C#
private async void func(...)
{
    Globals.ThisAddIn.Application.Interactive = false;
    Globals.ThisAddIn.Application.ScreenUpdating = false;
    await System.Threading.Tasks.Task.Run(() =>
    {
        // 重たい処理 ※ここでUIを触ると例外エラー！
        Globals.ThisAddIn.Application.ScreenUpdating = true;
        Globals.ThisAddIn.Application.Interactive = true;
    });
}

```

---
以上です。
SpringBoot JPAによるPostgresqlの活動統計情報の取得

JPAによるpg_stat_activity統計情報の取得方法です。

```PgStatRepository.java

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

@Repository
public class PgStatRepository {
	
	@PersistenceContext
	EntityManager entityManager;
	
	/**
	 * 接続数の取得
	 * @return 接続数
	 */
	public  int countClient() {
		String query = "SELECT count(application_name) FROM  pg_stat_activity WHERE datname = 'spring-sample';";
		return ((Number)entityManager.createNativeQuery(query).getSingleResult()).intValue();
	}
}
```
Hello Xamarin!

<h1>はじめに</h1>
こんにちは。初めてQiitaを書きます。ドッキドキです。
よろしくお願いします。

2020年に新卒で入社した会社でC#とWPFを使ってぼちぼちやっています。

前々から気になっていたXamarinを使ってみたので自分のアウトプットの場として記事を書こうと思った次第です。

<h1>作ったもの</h1>
今回はお試しということで、簡単な四則演算アプリを作りました。

![スクリーンショット 2021-01-17 19.54.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033036/f8c43a63-9592-5d71-d720-8869aae2ff43.png)

![スクリーンショット 2021-01-17 23.10.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033036/f7e6c0af-923c-8e8e-3c3b-dc7c132ee5ac.png)


数字を入力、演算子を選択して計算ボタンを押すと答えが出力されるだけのものになります。

<h1>コード</h1>
Xaml

```MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="test1.MainPage">

    <StackLayout Orientation="Vertical" Margin="30,50,0,0">
        <StackLayout Orientation="Horizontal">
            <Entry x:Name="left" WidthRequest="100" VerticalOptions="Start"/>
            <Picker x:Name="picker"/>
            <Entry x:Name="right" WidthRequest="100" VerticalOptions="Start" />
            <Label Text="="/>
            <Label x:Name="answer" WidthRequest="100" />
        </StackLayout>
        <Button x:Name="button" Text="計算" Clicked="OnButtonClicked"/>
    </StackLayout> 

</ContentPage>
```

C#

```c#:MainPage.Xaml.cs

using System;
using Xamarin.Forms;

namespace test1
{
    public partial class MainPage : ContentPage
    {
        static string[] operators = new[] { "+", "-", "×", "÷" };

        public MainPage()
        {
            InitializeComponent();
            // pickerに演算子をセット
            picker.ItemsSource = operators;
            // 初期値は"+"
            picker.SelectedIndex = 0;
        }

        void OnButtonClicked(object sender, EventArgs e)
        {
            var leftNumberText = left.Text;
            var rightNumberText = right.Text;
            if (double.TryParse(leftNumberText, out var leftNumber) &&
                double.TryParse(rightNumberText, out var rightNumber)){
                var answer = Calculate(leftNumber, rightNumber, picker.SelectedItem.ToString());
                this.answer.Text = answer.ToString();
            }
        }

        static double Calculate(double leftNumber, double rightNumber, string ope)
        {
            switch (ope)
            {
                case "+":
                    return leftNumber + rightNumber;
                case "-":
                    return leftNumber - rightNumber;
                case "×":
                    return leftNumber * rightNumber;
                case "÷":
                    if (rightNumber == 0) {
                        throw new InvalidOperationException();
                    } else {
                        return leftNumber / rightNumber;
                    }

                default:
                    throw new InvalidOperationException();
            }
        }
    }
}

```

ただボタンのイベントハンドラで計算してるだけですね。
WPFとのコントロールの違いに少し戸惑いました。

お試しなので、コードの内容については(例外処理とか)多めに見てくださいということで。

マシンが非力なせいか、Xamarinだから仕方ないのかエミュレーターの起動が遅くてイライラしますね。

夏のボーナスでたら新しいMac買おうかな。。。

今回はコードビハインドでやりましたが、次はViewModel作ってMVVMで四則演算したいと思います。
【備忘録】Vue：methodsとcomputedの違い

Vueの動作オプションであるmethodsとcomputedの違いに関して

```
new Vue({
  computed: {
      ...
  },
  methods: {
      ...
  }
})
```

## 参考
[これからはじめるVue.js実践入門](https://www.amazon.co.jp/dp/B07WVXRNH3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

## 内容
下記のようなプログラムで違いを説明。
【プログラム内容】
- computedで乱数を表示
- methodsで乱数を表示
- クリックで現在日時を表示

```html:sample.html
 ...
    <body>
        <div id="app">
            <form>
                <input type="button" value="click" v-on:click="onclick" />
            </form>
            <div>computed: {{randomc}}</div>
            <div>methods: {{randomm()}}</div>
            <div>daytime: {{current}}</div>
        </div>
     ...
    </body>
```

```js:sample.s
new Vue({
    el: '#app',
    data: {
        current: new Date().toLocaleString()
    },
    computed: {
        randomc: function() {
            return Math.random();
        }
    },
    methods: {
        onclick: function(){
            this.current = new Date().toLocaleString();
        },
        randomm: function() {
            return Math.random();
        }
    },
});
```

↓ ブラウザで表示した実際の画
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147946/1868f9f5-83ea-e72e-cfb4-8fe366db6e70.png)


## 共通点
ページ遷移した時はcomputedとmethodsのどちらも実行される。

## 異なる点
1)  methodsはhtml上で使うときに引数を持てる。computedは引数を持てない。

```
<div>methods: {{randomm(ここに引数を入れられる)}}</div>
```


2) methodsはページが再描画されるたびに実行される。一方で、computedはページに遷移した初回のみ呼び出したときと、依存したプロパティが更新されたときのみ実行される。
つまり、今回の例だと「クリック」ボタンをクリックしたときに、現在時間が再描画されるので、その際にmethodsの乱数生成は実行されて、computedの乱数生成は実行されない。
ただし、

```
    computed: {
        randomc: function() {
            console.log(this.current);
            return Math.random();
        }
    },
```
のように現在時刻を参照すると、computedも実行される。
9軸センサー使って移動距離を測る

#概要
BMX055という9軸センサーを使って値をとって、加速度から速度を計算して移動距離を取ろうとしてみました。
BMX055から加速度センサーを取得する際に参考にしたサイトこちらです。
[https://labo-kajisaki.blogspot.com/2019/03/2169.html?m=1](https://labo-kajisaki.blogspot.com/2019/03/2169.html?m=1)

#使用ソフト
* uPyCraft

#移動距離計算

```
import urequests
import ujson
from machine import Pin, I2C
from bma2x2 import BMA2X2
from bmg160 import BMG160
from bmm050 import BMM050
import time

i2cBMX055 = I2C(scl=Pin(22), sda=Pin(21))

print('I2C setup')

accl=BMA2X2(i2cBMX055, 0x19)
gyro=BMG160(i2cBMX055, 0x69)
mag=BMM050(i2cBMX055, 0x13)

t = 0.064
count = 1
vx2 = 0
distx = 0
disty = 0
count_result = 0

def vx(ax):
  conv_ax = convx(ax)
  vx = conv_ax*t
  return vx

def convx(ax):
  return ax * 0.00981

def vy(ay):
  conv_ay = convy(ay)
  vy = conv_ay*t
  return vy

def convy(ay):
  return ay * 0.00981


while count <= 300:
  a = BMA2X2.xyz(accl)
  ax = a[0]
  ay = a[1]
  az = a[2]

#X軸方向
  # G　➡　加速度
  conv_ax = convx(ax)
  # 加速度➡速度（一回目のループ）
  if count_result == 0:
    vx2 = conv_ax * t

    #速度➡距離(初速なし)
    dist2x = conv_ax * t ** 2 / 2

  # 加速度➡速度（初速あり（2回目以降））
  if count_result == 1:
    vx2 = vx2 + conv_ax * t

    #速度➡距離（初速あり（2回目以降））
    dist2_1x = vx2 * t
    dist2_2x = conv_ax * t ** 2 / 2
    dist2x = dist2_1x + dist2_2x

#Y軸方向
  # G　➡　加速度
  conv_ay = convy(ay)
  # 加速度➡速度（一回目のループ）
  if count_result == 0:
    vy2 = conv_ay * t

  #速度➡距離(初速なし)
    dist2y = conv_ay * t ** 2 / 2

  # 加速度➡速度（初速あり（2回目以降））
  if count_result == 1:
    vy2 = vy2 + conv_ay * t

    #速度➡距離（初速あり（2回目以降））
    dist2_1y = vy2 * t
    dist2_2y = conv_ay * t ** 2 / 2
    dist2y = dist2_1y + dist2_2y
    
  count_result = 1

  distx += dist2x
  disty += dist2y


  if count % 16 == 0:
    print('x >>> ', distx, '(m)')
    print('y >>> ', disty, '(m)')
    print('----')

  count += 1
  time.sleep(t)
```

データシートを読んだところ加速度は0.064秒ごとに値をとるらしく、それらを物理の式にあてはめて移動距離を測ろうとしています。それをX軸方向・Y軸方向で求め、最初の位置からどのくらい移動したかを計測しています。

#おわりに
結構無理やり物理の式を使っているので、雑な計測結果になってしまいました。
Pythonの再帰関数の変数の取り扱いについてのメモ

# Pythonの再帰関数の値

再帰関数を組んでいる際に、pythonでは関数外の値が関数内でどのように書き換わるのかわからなくなったため検証しました。

##  前提知識

関数内で関数外で定義された変数がどう取り扱われるかを確認します。

```python
a=10
def replace1():
    a=15
replace1()
print(a)

>10
```
この場合、関数内でのみaが変化します。

```python
al=[10]
def replace3():
    al=[15]
replace3()
print(al)

>[10]
```
この場合も、関数内でのみalが変化しています。

```python
al=[10]
def replace2():
    al[0]=15
replace2()
print(al)

>[15]
```
この場合は、関数内で変更された値が関数外でも変化しています。~~これはリストがミュータブルなオブジェクトのためです。~~　　
ローカル変数への代入しているか、グローバル変数を参照しているかの問題でした。

```python
a=10
def replace1():
    global a
    a=15
replace1()
print(a)

>15
```
コメントにてglobal変数の定義を行うと代入可能と指摘いただきました。実際に関数内から関数外の変数に代入できています。クラス変数として定義する方法もあるようです。(コメント参照ください)


## 再帰関数にて変数の取り扱いの検証

ここからは再帰関数にて変数の取り扱いを試していきます。
ここで用いた再帰関数は3-1が0になるまで何回計算できるかカウントするものです。

### ex1
```python
count=0
a=3
def saiki1(a):
    if(a==0): return
    a=a-1
    count += 1
saiki1(a)
print(a, count)

>UnboundLocalError: local variable 'count' referenced before assignment
```
念のためやってみましたが関数内でcountが定義されていないためエラーとなります。
関数内で```global count```と定義するとエラーにはならずcountの正答が得られます


### ex2
```python
count=0
a=3
def saiki2(a):
    count=0
    if(a==0): return
    a=a-1
    count += 1
saiki2(a)
print(a, count)

>2 1
>1 1
>0 1
>3 0
```
この場合、関数内では変化していますが、関数外では最初に定義した値になっています。
なおこの場合は再帰内でcount=0とリセットしているため正しい答えとなっていません。
### ex3
```python
count=0
a=3
def saiki3(a, count):
    if(a==0): return
    a=a-1
    count += 1
    print(a, count)
    saiki3(a,count)
saiki3(a, count)
print(a, count)

>2 1
>1 2
>0 3
>3 0
```
再帰関数の引数にcountを加えた場合、関数内では正しい答えとなっていますが、関数外ではそれを戻り値として受け取っていないため、最初に定義した値となっています。
### ex4
```python
count=0
a=3
def saiki4(a, count):
    if(a==0): return a, count
    a=a-1
    count += 1
    print(a, count)
    saiki4(a, count)
    return a, count
a, count= saiki4(a, count)
print(a, count)

>2 1
>1 2
>0 3
>2 1
```
次にaとcountを戻り値に設定した場合です。この場合は複雑ですが、8行目でsaiki4を実行した時点で戻り値を受け取っていないため、関数内で最初に計算した結果の2 1が出力されています。

### ex5(正当)
```python
count=0
a=3
def saiki5(a, count):
    if(a==0): return a, count
    a=a-1
    count += 1
    print(a, count)
    a,count= saiki5(a, count)
    return a, count
a, count= saiki5(a, count)
print(a, count)

>2 1
>1 2
>0 3
>0 3
```
この場合は関数内でa, countを受け取っているため正当を出力することができています。
なお8,9行目をまとめて ```return saiki5(a, count)```と書いても同じ結果が得られます。
### ex6(正当)
```python
count=[0]
a=3
def saiki6(a, count):
    if(a==0): return a
    a=a-1
    count[0] += 1
    print(a, count)
    a = saiki6(a, count)
    return a
a= saiki6(a, count)
print(a, count)

>2 [1]
>1 [2]
>0 [3]
>3 [3]
```
最後にcountをリストにして、その要素のみを書き換えた場合を確認します。この場合は countを戻り値としていませんが、関数外で定義した値が関数内で書き変わっています。
なお```t= count[0]+1   count=[t]```などとするとリストのオブジェクトが変わってしまうので最後の結果は```3 [0]```が出力されます。

追記
コメントにてグローバル変数で行う方法を教えていただきました。

## 参考
https://excel-ubara.com/python/python016.html
Ruby on rails モデル単体テストでのメールアドレス二重登録テストについて

新規登録時のテストを異常系のテスト実装していた時の疑問です。
単体テスト作成時validateでnicknameの空登録やパスワードの空登録や文字数制限はしましたが、e-mailについて制限した記述をした記憶が全くないのに気づきました。
設定のないもの（ルール？）についてのテストなど意味がないと思い調べました。
けつろん、設定ありました。

解答

```app>models>user.rb
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, `rgb(`:validatable

  has_many :tweets
  has_many :comments
  validates :nickname, presence: true, length: { maximum: 6 }
end
```

installしたdeviseの中のvalidatableというGemモジュールにメール登録２重を禁止が設定してあったようです。

（詳細）//////////////////////////////////////////////////
*deviseの使い方*
devise gemはモジュールの概念に基づいて作成されています。
deviseは大きく10のモジュールから構成されています。

1.Database Authenticatable
2.Registerable
*3.Validatable*
4.Recoverable
5.Rememberable
6.Confirmable
7.Lockable
8.Timeoutable
9.Trackable
10.Omniauthable


*3.Validatable*
ユーザーの電子メールとパスワードに関して必要な全ての検証を作成する。
デフォルトではemailのフォーマットに関するバリデーションと、パスワードの長さに関するバリデーションを設定できる。

デフォルト設定の詳細については以下
email  1. 存在すること  2. 一意であること  3. @を含むこと	
password 1. 存在すること  2. *6文字*以上*128文字*以下であること


e-mailの一意であることが「二重登録禁止」にあたります。
【Android】Android Studioで使えるショートカット(Windows)

#プログラミング勉強日記
2021年1月17日
基本的なショートカットしか使っていなかったけど、使って便利だと思ったショートカットをまとめる。

#個人的に覚えておきたいショートカット


| 説明  | ショートカットキー |
|:--:|:--:|
| クラス、ファイルなどを全体から検索 | shift +shift |
| タブの移動 | Alt + → / Alt + ← |
| 戻る | Ctrl + Alt + ← |
| 進む | Ctrl + Alt + → |
| 1行削除 | Ctrl + Y |
| アプリをビルドして実行 |  shift + F10 |
| 行またはブロックのエラーの修正方法を表示 | Alt + Enter |
| 名前の変更 | shift + F6 |
| プロジェクトのクイック修正 | Alt + Enter |
| 置換 | Ctrl + R |



#参考文献
[キーボード ショートカット](https://developer.android.com/studio/intro/keyboard-shortcuts?hl=ja)
kafka付属のパフォーマンス確認コマンドkafka-consumer-perf-test.shとkafka-producer-perf-test.sh


```sh
bash-4.4# $KAFKA_HOME/bin/kafka-consumer-perf-test.sh --version
2.6.0 (Commit:62abe01bee039651)
```

# kafka-consumer-perf-test.sh
consumerなので後述の```kafka-producer-perf-test.sh```と組み合わせるか他の何かしらの手段でproduceして使う。以下は```--messages=10```なので10個consumeしたら終了する（もしくはタイムアウト）。

```sh
$KAFKA_HOME/bin/kafka-consumer-perf-test.sh  --bootstrap-server localhost:9092 --topic=perftest --messages=10
```

終了するとサマリが表示される。

```sh
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
2021-01-17 13:10:46:392, 2021-01-17 13:10:46:777, 0.0000, 0.0001, 24, 62.3377, 1610889046729, -1610889046344, -0.0000, -0.0000
```

# kafka-producer-perf-test.sh

* ```--num-records 10``` レコード数
* ```--throughput 1 ``` 秒間produce数（たぶん。マニュアル読んでない）。
* ```--record-size 10``` 各レコードのサイズ。10だと```SSXVNJHPDQ```みたいのをproduceする。

```sh
bash-4.4# $KAFKA_HOME/bin/kafka-producer-perf-test.sh  --topic perftest --num-records 10 --throughput 1 --record-size 10 --producer-props bootstrap.servers=localhost:9092
```

終了するとサマリが表示される。

```
7 records sent, 1.3 records/sec (0.00 MB/sec), 54.3 ms avg latency, 295.0 ms max latency.
10 records sent, 1.073192 records/sec (0.00 MB/sec), 41.30 ms avg latency, 295.00 ms max latency, 13 ms 50th, 295 ms 95th, 295 ms 99th, 295 ms 99.9th.
```
[node.js/Express] expressで多言語対応


* 以下のような仕様を想定する。
    * デフォルト
        * PCで設定している言語を使用。
        * [インターネットオプション] → [言語] → [言語の優先順位の設定] → [Windowsの表示言語] で設定。
    * ログイン後
        * ログインユーザに紐づく言語設定に基づき表示言語を制御する。
        * 以下では省略しているが、req.session.locale を変更すると任意のタイミングから言語切替えが出来るイメージ。

---

* i18nをインストールする

```
npm install i18n --save
```

* 全般的な設定

```appSetting.js
var i18n = require('i18n');
...

/**
 * req.session.locale の言語設定で表示言語を切替える
 */
var setI18n = function (req, res, next) {
    if (req.session.locale) {
        i18n.setLocale(req, req.session.locale);
    }
    next();
}
...

// i18n setup.
i18n.configure({
    locales: ['ja', 'en'],
    defaultLocale: 'ja',
    directory: __dirname + '/locales',
    objectNotation: true
});
app.use(i18n.init);
...

```

---

* localesディレクトリを作成して、その下に言語に応じた辞書ファイルを置く。

```locales/ja.json
{
	"common": {
		"title": "XXXXシステム"
	},
}
```
 
```locales/en.json
{
	"common": {
		"title": "XXXX System"
	},
}
```

---

* jade 上の記述
  * 以下のように json の key を設定する。

```xxx.jade
#{__('common.title')}
```
AtCoder 緑が Go で解いてみた

## Go は AtCoder に向いているのか
最近 Go の標準的な package には max 関数がなかったり、型の縛りがかなりキツかったり、色々厳しい面があるという話を聞いたので、Python3 と比較して実際にどれぐらい厳しいのか試してみた。
## ABC188 を解いてみる
### A
https://atcoder.jp/contests/abc188/tasks/abc188_a
バスケでスリーポイントを決めると逆転する展開かどうかを判定するという問題。

入力は宣言した型に対して、`fmt.Scan(&a)` で入れられるらしい。

```a.go
package main

import (
	"fmt"
	"math"
)

func main() {
	var X, Y int
	fmt.Scan(&X, &Y)
	if math.Abs(X-Y) < 3 {
		fmt.Print("Yes")
	} else {
		fmt.Print("No")
	}
}

```

これで問題無いだろうと思ったが、どうやら `math.Abs()` は引数に `float64` しか受け付けていないらしい。よって `var X, Y int` ではなく `var X, Y float64` と宣言すれば動いた。
https://golang.org/pkg/math/
`math` パッケージは基本 `float64` しか受け付けていないらしく `int` を使用する意味はあまりなさそうだ。
これ以降の宣言は全て float64 にしようと決意。
ちなみにこちらを Python3 で記述すると

```a.py
X, Y = map(int, input().split())
if abs(X - Y) < 3:
    print("Yes")
else:
    print("No")
```

当然といえば当然だが Python の `abs()` は int も float もいける。

### B
https://atcoder.jp/contests/abc188/tasks/abc188_b
Vector の内積が0になるかという問題。
配列の入力は先程の `fmt.Scan(&A)` でいけるとすると、

```
var X float64
var A, B []float64
fmt.Scan(&X, &A, &B)
```

みたいな書き方は流石にあるだろうと思ったが、そんなものは存在せず、ググって書いてみた所

```b.go
package main

import "fmt"

func main() {
	var N int
	fmt.Scan(&N)
	A, B := make([]float64, N), make([]float64, N)
	for i := 0; i < N; i++ {
		fmt.Scan(&A[i])
	}
	for i := 0; i < N; i++ {
		fmt.Scan(&B[i])
	}

	total := float64(0)
	for i := 0; i < N; i++ {
		total += A[i] * B[i]
	}
	if total == 0 {
		fmt.Print("Yes")
	} else {
		fmt.Print("No")
	}
}

```

配列の際の標準入力で for文を使用するのは若干きつい。
この辺りはテンプレ作って簡単に入れられるようにしたい。

```b.py
_ = int(input())
X = list(map(int, input().split()))
Y = list(map(int, input().split()))

total = 0
for i in range(len(X)):
    total += X[i] * Y[i]

if total == 0:
    print("Yes")
else :
    print("No")

```

Python であれば `list(map(type, input().split()))` の一行でかけるのでいいですね。

### C
https://atcoder.jp/contests/abc188/tasks/abc188_c

配列を前半と後半に分け、それぞれの最大値と index を保持して最後に比較する感じになりそう。

```c.go
package main

import (
	"fmt"
	"math"
)

func main() {
	var N int
	fmt.Scan(&N)
	sN := int(math.Pow(2, float64(N)))
	A := make([]int64, sN)
	for i := 0; i < sN; i++ {
		fmt.Scan(&A[i])
	}
	fmax, smax := int64(0), int64(0)
	findex, sindex := -1, -1
	for i, rating := range A {
		if i < sN/2 {
			if rating > fmax {
				fmax = rating
				findex = i
			}
		} else {
			if rating > smax {
				smax = rating
				sindex = i
			}
		}
	}
	if fmax < smax {
		fmt.Println(findex + 1)
	} else {
		fmt.Println(sindex + 1)
	}
}
```

`Pow` で `float64` が、for loop の index の `i` で `int` になってしまうなど、場面場面に応じて `int` か `float64` にするのかとか考えないと駄目。脳死の `float64` は通用しませんでした。
slice と自作 `max` 関数を使えばもう少しスマートな書き方にできそう。

```c.py
N = int(input())
sNh = 2 ** (N - 1)
A = list(map(int, input().split()))
fA = A[:sNh]
sA = A[sNh:]
print(A.index(min(max(fA), max(sA))) + 1)
```

Python3 に関しては min, max 関数と Array の index 関数がある為お手軽に実装できた。

## 個人的な感想
まだ3問解いただけだが、

- `int` と `float64` の使い分け
- `max` 関数などのどの言語にもありそうな関数が標準の package には存在しなさそう
- 配列の初期化だるい

上記の3点はテンプレを作ってしまえば解決しそうなレベルなので Go で AtCoder をやっていくのは厳しい、ということはなさそうだが、Go も AtCoder も初心者という方にはあまりおすすめできない。Python の最低限の記法だけ覚えて AtCoder の問題を解くことに専念する方が変な所で躓かず楽しめそう。
忘れやすいあなたにもできるプッシュ型タスク管理【インストール不要】

タスク管理の方法はいろいろありますが、弊社の先輩がクールでナイスな方法を使っていたので一つご紹介します。
自分ログは一定の時間ごとにメモ帳を開きます。
メモ帳とWindowsの「タスクスケジューラ」を使うだけなのでインストールなし、当然無料で作れます！

メリット
>・自動で開いて、メモリを割かずにWindows機能も触って試せる
>・時報代わりにもなる
>・今やっている作業を入力して作業内容を記録する
>・そのタスクがどれくらい時間をかけたかがわかるため、今後のタスクプランを立てやすくなる

#作り方
2つの作業を組み合わせて作ります。
>1.メモ帳を開いたときに自動で日付を入力
>2.タスクスケジューラの設定


#1.メモ帳を開いたときに自動で日付を入力
こちらはとても簡単です。メモ帳から「memo.txt」を作成して開いてください。
#####①メモ帳の一番最初に『.LOG』を入力する

![memo-log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/fbe3850e-13cc-dda5-d202-7a57718e3fc3.png)
はい、おしまいです。

保存して開くと...
![memo-log2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/c1ce98fe-e16c-0095-4a15-d3d797654344.png)

また保存して開くと...
![memo-log3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/24d66459-35cf-8f2f-ad68-074a4fe823dc.png)

このように更新情報が次々に登録されます。


#2.タスクスケジューラの設定
今回は「平日9時から1時間刻みでメモ帳を開く」というタスクを設定します。
#####①タスクスケジューラを開く
![task2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/489c20e9-d7f8-20f8-eefe-bfef56da86ec.png)
デスクトップの検索バーに「task」と入力して、「タスクスケジューラ」を起動します。

#####②タスクの作成
![task3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/d86e3059-a1d2-d444-3480-b13edd213f9d.png)
タスクスケジューラを開いた画面です。
「タスクの作成」でもよいですが今回は難しい設定はあまりないので、「基本タスクの作成」からタスクを作成します。

#####③基本タスクの作成
タスク名と説明を入力します。
![task4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/3b3de56f-2b33-49ea-467d-3c76e7149538.png)
名前は自分がわかりやすいもの、説明は何でもいいと思います。

#####④トリガー
どのくらいの周期でタスクを実行するかを選択します。
![task6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/8e4cddbf-25cd-2757-3f39-83a77daa0c02.png)
今回は「毎週」を選択します。

#####⑤毎週
開始する時間、週間隔、曜日を選択します。
![task7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/e1a9c70a-d160-10b1-d607-3251712f06ae.png)
今回は「平日」の日程を選択します。

#####⑥操作
タスクでどの操作を実行するかを選択します。
![task8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/35c512ea-eb40-7b01-9229-d281f2402f80.png)
今回は「プログラムの開始」を選択します。

#####⑦プログラムの開始
どのプログラムを実行するか、どんな値で実行するかを選択します。
![task9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/93036686-93ce-7eb2-0fcd-64aac885f62b.png)
プログラム/スクリプトには「C:\Windows\System32\notepad.exe」と入力します。
「notepad.exe」というのがメモ帳の正式名称です。
引数という欄には「"C:\Users\{userName}\Desktop\memo.txt"」と入力します。

「{userName}」はWindowsの自分のユーザ名を入れてください。
「memo.txt」はファイルの名前です。

#####⑧要約
これまでの確認情報が見れます。
![task10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/56f72e8c-1d87-d0b2-3c82-59ab5a8fcb57.png)
設定に不備がなければ「完了」を押してタスク作成を終了します。

これでステップは完了です。
作成したタスクは一覧に増えます。
![task11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/37da4484-6412-c4d0-5901-566bde37e558.png)
設定を変更したいときはプロパティをクリックすることで編集画面に遷移します。

#####<完成図>
![task12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741385/0f962913-c13b-3f31-79bb-976fed00e654.png)
こんな感じに毎時表示されていきます。


#####参考
メモ帳での簡単な日付入力法
https://www.atmarkit.co.jp/fwin2k/win2ktips/480notepad/notepad.html
Androidで電話着信のIntentが受け取れなかった顛末

# Androidで電話着信を受けてなんかしたかった
android.intent.action.PHONE_STATE を拾えばいいじゃんと思っていたら、そうは問屋がおろさなかった件。
# 結論
- Androidの設定の中のアプリの設定で電話を有効にする。(https://stackoverflow.com/questions/52369874/broadcast-receiver-for-phone-state-changed-not-working の２つ目の回答)
- 端末の種類によっては動かないぽい（IP電話アプリがデフォルトになっている楽天のとか）

この２つをクリアすれば受け取れるようです。

# ひっかかりポイント
- Virtual deviceでは動作する。
- Build versionは__関係ない__ ぽい。
- Manifestに書いてもだめなIntentも(特にOreo以降）あるが、今回は関係なかった。
- android:priority も関係ないぽい。というか組み込み通話アプリのpriorityが最優先になってるとオーバーライドできないぽい。
- logcatで似たようなIntentに対してpermission なんたらでるけど、そもそも拾えないIntentなので関係ない。
- TelephonyManagerの書き方も関係ない。
Ceph(Octopus)の構築(準備編 ソフトウェア)

##__はじめに__
この記事では、タイトルのとおり現時点(2021.01)で最新である__ceph(octopus)__の構築を目的としています。
また、自分で構築した手順の備忘録を兼ねているので、細かいところで間違いなどあるかもしれません。

基本的には公式のDOCUMENTATIONが必要なことを全て網羅しているので一読しておくことをお勧めします。
Linuxの知識もある程度必要になるので他サイトや書籍などで事前に基本は押さえておくとよいでしょう。

##__関連記事__
[Ceph(Octopus)の構築(準備編 ハードウェア)](https://qiita.com/iriya_v00v/items/651eff2955d5ad7eadf6)
Ceph(Octopus)の構築(準備編 ソフトウェア)　この記事
[Ceph(Octopus)の構築(設定編 共通)](https://qiita.com/iriya_v00v/items/d7d9e439cf4159acae2c)
[Ceph(Octopus)の構築(設定編 ブートストラップ)](https://qiita.com/iriya_v00v/items/d7bcf4dfa6324bacd91a)
[Ceph(Octopus)の構築(設定編 mon/mgr/osd)](https://qiita.com/iriya_v00v/items/75eefdefb7ec61d24812)
[Ceph(Octopus)の構築(設定編 cephFS/mds)](https://qiita.com/iriya_v00v/items/931838d6d56e568bd6d8)
[Ceph(Octopus)の構築(設定編 Crush Map)](https://qiita.com/iriya_v00v/items/2a263a7817434e8b91ed)

##__ソフトウェア(ceph)__
構築するcephのバージョンを確認します。
表題にもあるとおり、今回は__octopus__を使って構築しようと思います。
構築方法が説明されているブログ等はluminousやnautilusに関してのものが多く、octopusについてはあまりありませんでした。

参考までに、現時点(2021.01)での公式サイトの記述は以下のとおりなので、無理にoctopusを使う必要はないのですが、せっかくなので新しいバージョンを試してみることにしました。
![スクリーンショット 2021-01-17 210719.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033108/e4e3cbba-c1fd-28b3-eeb6-86bb9bdada41.png)

##__ソフトウェア(OS)__
業務用途でよく使われているRHELとほぼ同じであるCentOSを採用しました。
当初Releaseバージョンは8を使うつもりでいたのですが、2020.12頃にOS8が廃止されてStreamへ移行するとの発表があり、まさかのOS7よりEnd-of-lifeが早くなってしまうことが判明したため今回は__CentOS7__を使うことにしました。
今後、cephが公式にCentos Streamへの対応を宣言すればそちらへ移行するのもありかもしれません。

##__ソフトウェア(ミドルウェア)__
cephクラスタを稼働させるために必要となるソフトウェアはいくつもあります。残念ながら、OSとcephのパッケージのみで動かすことはできません。
詳しくは構築編に記載するつもりなので、ここでは簡単に紹介だけしておきます。
__・cephadm__
　　octopusではceph-deployは使えません。その代わりにこのコマンドを使います。

__・podmanまたはdocker__　(今回はdockerを利用)
　　octopusから必要になった？
　　cephの役割(機能)は各ノード上でdockerのプロセスとして動きます。

__・NTP__　(今回はchronyを利用)
　　クラスタを維持するために厳密な同期処理が必要なようです。
　　時間がずれていると思わぬエラーとなるようです。

__・samba__
　　構築したcephのファイルシステムを公開するのに使います。
　　ブロック/オブジェクトストレージの場合は不要です。

__・ceph-common__
　　cephファイルシステムをマウントするのに使います。
　　mount -t cephでマウントできるようになります。

__・ssh__
　　クラスタを構成するノードが多くなると必須だと思います。

__・sshpass__
　　シェルスクリプトで作業を自動化する場合は必要です。



##__おわりに__
今回私が利用したソフトウェアについては以上です。
cephadmを使うあたり、あまり情報がなくて試行錯誤が多かったです。
一応公式のドキュメントに色々書いてあるのですが、日本語が欲しいですね。


cephの構築(共通)については[次の記事](https://qiita.com/iriya_v00v/items/d7d9e439cf4159acae2c)に投稿しようと思います。
なぜ「ダビング」はIT用語にならなかったのか

21世紀生まれの新入社員を迎え入れる時代が近づいていますが、20世紀生まれの皆さんはジェネレーションギャップへの備えはできていますでしょうか。

昭和と平成のジェネレーションギャップをネタにするときの定番と言えば「フロッピーディスク」でしたが、世紀をまたいだジェネレーションギャップは何だろうと考えたときに「ダビングって言葉、最近は使わなくなったなぁ」と思いつきました。

VHSビデオやカセットテープが全盛期だった頃は、テレビ番組やラジオ番組のダビング交換などをしている知り合いを見ることも珍しくありませんでしたが、最近は「ダビングさせて」と声をかけている場面も見かけなくなりました。個人的に「ダビング」という言葉を最後に聞いたのは、アナログ放送からデジタル放送に切り替わるときに使われた「ダビング10」（ダビングの上限回数を10回までにする仕組み）という言葉です。

データのコピーを意味する言葉なのに、どうして「ダビング」という言葉がIT業界に残らなかったのか、思いつくままに書いてみますので、読んでいる皆さんの気が向いたら、二の句を繋いでいただければと思います。

#ダビングの語源
英辞郎で[Dubbing](https://eow.alc.co.jp/search?q=dubbing)を調べてみましたが「合成録音、吹き替え、アフレコ」という意味でした。語源としては、Dubが「（国王が剣で人の肩をたたいて爵位を）授ける」という意味で、それが色々と転じて「吹き替え」となったようです。そこから更に転じて「データのコピー」となったようなのですが……。

#和製英語？
ここからは、昭和世代をリアルタイムで過ごした空気感からの推測です。

昭和の時代、音楽業界の技術にダブ（ダビング）というものがありました。原曲を崩したり、効果音を入れたりするもので、今だとリミックスのようなものに近いと思います。

ダビングという作業は、カセットテープやVHSテープに単純にデータをコピーをするものではなかったように記憶しています。それは、ビデオだったらCMをカットしたり、テープだったら気に入った曲だけをテープの時間内に収まるようにセレクトするなど、編集作業が伴うものでした。

そのため、コピー機を使うような単純な作業ではなくて、編集作業を伴うクリエイティブな作業だという意味合いで、メディアのコピー行為を「ダビング」という言葉になったのでは……と考えています。

#IT業界で使われなかった理由
IT業界でダビングという言葉が使われなかった理由については「Copyコマンドがあったから」と書いてしまうと身も蓋もないので、少し話を話を膨らませます。
昭和の時代はプログラマーといえば「人間や社会とコミュニケーションをすることができなくて、コンピュータにしか相手にしてもらえない嫌われもの」という位置づけで、スポーツや音楽をしている人間を「陽」とすれば、コンピュータを理解できる人間は「陰」としており、大きな断絶がありました。そのため、「陽」の人間が使用しているダビングという言葉に侵食されることがなく、デジタル化の時代を迎えることになったのではと推測しています。

#消えていった原因
アナログ時代の終焉と一緒にダビングという言葉は消えたのだと思います。
ダビングはアナログ機器を2台揃えて、1台が再生して、もう1台が記録するというもので、60分間のデータであればダビング完了まで60分の時間がかかりました。しかし、デジタル化の時代となると、データは1台の機器で並列に高速コピーが行えるようになったことで、ダビングは自然に消滅していったのでは……と考えています。

#ダビングという言葉がフックしたら
ここまで色々と書きましたが、個人の偏った視点になっています。ダビングという言葉にフックするものがある人がいらしたら、色々と話を聞かせてください。
日本の高速道路を OSM データから抽出

こんにちは。
日本の高速道路[^1] [^2]を OSM データから抽出しました。[osmium-tool](https://osmcode.org/osmium-tool/manual.html)（の [tags-filter](https://osmcode.org/osmium-tool/manual.html#filtering-by-tags)）を利用し、```w/highway=motorway,motorway_link,service``` の条件を与えて抽出しています[^3]。

```w/highway=service```（敷地内道路）も抽出条件へ加えた理由は、パーキングエリア内道路、高速道路路線バス停用分岐車線も抽出したかったからです（下図）。
* しかし副作用として高速道路とは無関係な敷地内道路も大量に混入します（数十倍以上[^4]）。もしも混入をほぼ排除したい場合には、w/highway=motorway とグラフ的に連結するものに限定する処理が必要です[^5]。

[^1]: 「日本の高速道路」とは、自動車運転教則本の「高速道路」に相当します。自動車専用として指定された道路であり、「高速自動車国道」＋「自動車専用道路」です。「[日本の高速道路](https://ja.wikipedia.org/wiki/日本の高速道路)」 (Wikipedia) より
[^2]: 「[OSM データを NetworkX へ取り込んで最短経路計算（osm.pbf 形式）](https://qiita.com/kkdd/items/a900d2dd60e3215a1138)」では経路探索に利用しています。
[^3]: 参考：「[osmium-tool の tags-filter 処理（シェルスクリプト）](https://qiita.com/kkdd/items/1bc621cffab25737743f)」。
[^4]: GeoJSON データサイズより。
[^5]: 参考：「[道路ネットワークのグラフ生成（OpenStreetMap）](https://qiita.com/kkdd/items/4a27654b9bae04fedf44)」

#### 表示例
日本：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/23755af5-c22d-fd03-0e9b-8d45b3567f9d.jpeg" width=300px>

関東地方：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/861f6e9e-7ee5-c3df-8cad-d48075f71324.jpeg" width=400px>

パーキングエリア内道路、高速道路路線バス停用分岐車線も表示：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/810815d1-586a-326e-ebba-98df5032b308.jpeg" width=400px>

ランプ（motorway_link）も表示：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/3782f6ac-cf1a-50f0-e2db-f7ff51644249.jpeg" width=400px>

海岸線（coast line）も表示[^6]：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54617/e9ac041f-ed60-6032-ff91-bc1b402df4d8.jpeg" width=400px>

[^6]: 参考：「[OpenStreetMap coastline（海岸線）から GeoJSON LineString 生成](https://qiita.com/kkdd/items/4b8b940f7b4e457e6a32)」

#### 実行例

```console
$ wget https://download.geofabrik.de/asia/japan-latest.osm.pbf
$ osmium tags-filter japan-latest.osm.pbf w/highway=motorway,motorway_link,service -o japan-motorway_0.osm.pbf
$ osmium tags-filter japan-motorway_0.osm.pbf -i w/access=no,private,permissive -o japan-motorway_1.osm.pbf
$ osmium tags-filter japan-motorway_0.osm.pbf w/bus=yes -o japan-motorway_2.osm.pbf
$ osmium merge japan-motorway_1.osm.pbf japan-motorway_2.osm.pbf -o japan-motorway.osm.pbf
$ rm japan-motorway_?.osm.pbf
$ ogr2ogr -f "GeoJSON" japan-motorway.json japan-motorway.osm.pbf lines
$ ls -ldh japan-motorway.json
 -rw-r--r--  1 kkdd  staff  435M  9 01 00:00 japan-motorway.json
```
RealtimeDatabase

# 依存関係の宣言

```build.gradle(モジュール)
dependencies{
    implementation 'com.google.firebase:firebase-database-ktx'
}
```

#　準備

```MainActivity.kt
class MainActivity : AppCompatActivity() {
    //追加
    private lateinit var database:DatabaseRefernce

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //追加
        database = Firebase.database.reference
    }
}
```

#書き込み

```
...
database = Firebase.database.reference
database.child("users").child("user01").child("name").setValue("山田太郎")
database.child("users").child("user01").child("email").setValue("yamada@example.com")
```

こうもできる

```
data class User(
    val name:String = "",
    val email:String = ""
)

val user = User("yamadaTarou","yamada@example.com")

database.child("users").child("user01").setValue(user)
```

#読み取り

```
database.child("users").addChildEventListener(object :ChildEventListener{
        override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?){
            //処理
        }
        override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {
            //処理
        }
        override fun onCancelled(error: DatabaseError) {}
        override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {}
        override fun onChildRemoved(snapshot: DataSnapshot) {}
    })
```

これでusers配下に何かしらの変更が行われたときにそれぞれの処理を行います
snapshotには変更が行われた箇所のみが入っています
初回はonChildAddedが自動的に呼び出されます
※listenerをつけた配下に何もない場合は呼び出されない

# Snapshotの仕組み

```
database.addChildListener{}

database.child("name").setValue("yamada tarou")
//snapshot.value = yamada tarou
//snapshot.key = name

database.child("name").setValue("yamada jirou")
/*
{
    name:yamada jirou
}
*/

database.child("users").child("user01").child("name").setValue("yamada jirou")
/*
users:{
    user01:{
        name:yamada jirou
    }
}
*/
ページネーション機能(kaminari)

#はじめに
現在ポートフォリオ制作中の初学者です。
kaminariを導入してページネーション機能を実装したので備忘録です。

#1. gemをインストール

```Gemfile:Gemfile
gem 'kaminari'
```

```:ターミナル
% bundle install
```
#2. コントローラーで定義

```ruby:events_controller.rb
def index
  @events = Event.page(params[:page]).per(10)
end
```
__pageとperいうメソッドがkaminariで定義されたメソッドです。
perメソッドの引数にどれだけのレコードが表示されたらページを増やすかを指定できます。__

#3. ビューファイルを編集

```ruby:events/index.html.erb
<%= paginate @events %>
```
__表示したいビューファイルに記述。__

__以上です！__

#ページネーションの見た目を変える

kaminariで表示させるページネーションはビューの中でcssを当てる事は出来ない。
ので以下方法。

```:ターミナル
% rails g kaminari:views default
```
__app/viewsフォルダにkaminariを追加。__
__フォルダの中にページネーションの部分のhtmlが記述されているので、そこで変更する。__

#cssのフレームワークのデザインを適用させる場合

bootstrapなどのcssのフレームワークを使っている場合、表示やデザインが崩れる場合があるので
defaultの部分をそれぞれのフレームワークの名前に指定する。
bootstrap4を使っている場合は下記のコマンド。

```:ターミナル
% rails g kaminari:views bootstrap4
```
__このコマンドを実行し、ビューファイルを作成すると何も編集しなくてもそれぞれのフレームワークのスタイルに最適化される。__

#kaminariを日本語化する
デフォルトで英語表記になっているため、日本語表記に変更するためには
config/localesフォルダにkaminari_ja.ymlというファイルを作成し、下記のようなコードを書く。

```config/locales/kaminari_ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "..."
```

#参考
https://pikawaka.com/rails/kaminari
SQLの基礎について学ぶ＃０８

　今回はSQL文の内部に別のSELECT文を記述する``副問い合わせ``について説明していきたいと思います！！<b>副問合わせ</b>の機能を用いることで、``１つのSQL文で２つ以上の処理``を行うことができます。
### 過去の関連投稿
「[SQLの基礎について学ぶ＃０１](https://qiita.com/TAISEI-050523/items/31dd74cd386fe4dc46bf "Qiita")」
「[SQLの基礎について学ぶ＃０２](https://qiita.com/TAISEI-050523/items/75265fba015879bd3bf8 "Qiita")」
「[SQLの基礎について学ぶ＃０３](https://qiita.com/TAISEI-050523/items/2d87b30fa3de353af159 "Qiita")」
「[SQLの基礎について学ぶ＃０４](https://qiita.com/TAISEI-050523/items/6c4509276613d5eee488 "Qiita")」
「[SQLの基礎について学ぶ＃０５](https://qiita.com/TAISEI-050523/items/845bbdd046e28b443090 "Qiita")」
「[SQLの基礎について学ぶ＃０６](https://qiita.com/TAISEI-050523/items/bd9effcebe1b0ced652c "Qiita")」
「[SQLの基礎について学ぶ＃０７](https://qiita.com/TAISEI-050523/items/92254021e478309e0d15 "Qiita")」

## 1. 検索結果に対して結果表を操作する
### accountテーブル
|    date（日付）    |    name（項目名）       |    price（金額）     |
|:-----------:|:------------:|:------------:|
| 2020-12-03 |　食費  　 | 800         |
| 2021-01-03 |　交通費 　 | 600         |
| 2021-05-22 |　食費  　 | 1000         |
| 2021-03-14 |　日用品  　 | 1400         |
###① ２つのSELECT文が必要な例
``例：最も大きい金額とその項目名を取得する``

```SQL
SELECT MAX(price) FROM account  /* １行目のSELECT文の結果 => 1400 */
SELECT name, price FROM account
 WHERE price = 1400             /* １行目のSELECT文の結果(1400)を記述 */
```
###結果
| name | price  |
|:----:|:-----:|
|日用品 | 1400  |
▶ １つめのSELECT文で最も大きい金額1400円を取得
▶ ２つめのSELECT文で金額1400円に対応する項目名を取得
###② SELECTのネスト
①では２つのSQL文を用いましたが、``１つのSQL文で①を記述する``ことができます。

```SQL
SELECT name, price FROM account
 WHERE price = ( SELECT MAX(price) FROM account )  /* SELECT文をネスト */
```
###結果
①の結果と同じ

▶ このように、ある構造に対して別の構造が含まれていることを``ネスト構造``や``入れ子構造``と呼びます。
▶ SQL文の一部として含まれているSELECT文のことを``副問合わせ``、``副照会``、``サブスクエリ``と呼びます。
▶ ほかのSQL文の一部として登場する``副問い合わせ``は、``丸括弧（）``で閉じます。

###③ 副問合わせの処理
```SQL
SELECT name, price FROM account
 WHERE price = ( SELECT MAX(price) FROM account )  /* SELECT文をネスト */
```
　副問合せの動作は、``丸括弧（）で囲まれているSELECT文``が先に実行されて結果に化けた後に``外側のSQL文``が実行されます。
##2. 副問い合わせの３パターン
###① 単一の値の代わりとして、服問い合わせの検索結果を用いるパターン

|    price（金額）     |
|:------------:|
| 1000         |
▶ 検索結果が``１行１列の値``となる副問合わせ
▶ ``SELECT文の選択列リスト``や``FROM句``、``UPDATEのSET句``に使用できる。また、１つの値の判定を行う``WHERE句の条件式``としても使用

###② 複数の値の代わりとして、服問い合わせの検索結果を用いるパターン

|    price（金額）     |
|:------------:|
| 800         |
| 600         |
| 1000         |
| 1400         |
▶ 検索結果が``n行１列の値``となる副問合わせ(n>1)
▶ ``SELECT文の選択列リスト``や``FROM句``に使用できる。また、複数の値の判定を行う``WHERE句の条件式``としても使用
###③ 表の値の代わりとして、服問い合わせの検索結果を用いるパターン

|    name（項目名）       |    price（金額）     |
|:------------:|:------------:|
|　食費  　 | 800         |
|　交通費 　 | 600         |
|　食費  　 | 1000         |
|　日用品  　 | 1400         |
▶ 検索結果が``n行m列の値``となる副問合わせ(n>1, m>1)
▶ ``SELECT文``、``FROM句``、``INSERT文``に使用


##3. まとめ
　今回は以上になります。``副問合せの３パターン``については、次回の投稿以降に例文(SQL文)を示して説明していきたいと思います。
　何か間違い等ありましたら、コメントお願いします。引き続きSQLについて学んでいきたいと思います。
mkdocs + material theme で画像を中心寄せ(centerize)にする

https://squidfunk.github.io/mkdocs-material/reference/images/#image-alignment

`attr_list` で left, right はできますが, center はありません.
カスタム css での対応も, material theme だとどうもうまくいかないようです.

inline で HTML タグを書いての対応しましょう!

```
<div align="center">
<img src="img/pic.png" alt="image">
</div>
```
GoogleAppsScriptでのGoogleDrive上のフォルダ/ファイル名検索におけるuft-8-macによるエラーについて

#はじめに
GASを利用したLINE Botの開発中に発生した。
LINE Botでは送信された文字列に一致するフォルダ/ファイルパスを返却する処理を実装。

#開発環境
* MacOS Catalina 10.15.7
* Safari 13.1.3
* Google Chrome 87
* Google Drive 44.0

#エラー内容
LINEよりフォルダ/ファイル名を送信したところ、一部のフォルダ/ファイルにて、
名称が一致するにも関わらず検索に引っかからなかった。
GAS上の文字列一致判定にて不一致と判定されてしまう。

#原因
**MacPC**より**Chrome経由で**フォルダ/ファイルをアップロードした際に、
フォルダ/ファイル名の文字コードが **uft-8-mac**のままアップロードされたことが原因。
MacOSのファイルシステム(HFS+)は**濁点・半濁点を分離して扱う** uft-8-mac (NFDの亜種？)が採用されている。
 uft-8-mac形式で「ダ」や「ぱ」などが入っているフォルダ/ファイル名は、GAS上で文字列比較する際に不一致と判定されてしまう。

#解決策
今回は当該のファイル/フォルダが少なかったため、**Google Drive上で名前変更**することで解消。
ちなみにその名前変更を**Chrome**上で行うとバックスペース１文字ずつ消す際に、濁点・半濁点と本体の文字が別々に消去される様が確認できる。

その他の解決策としては、ファイル/フォルダを**safari経由でアップロード**すると、今回の事象は解消される。(Chrome経由で上げたフォルダはsafari上でバックスペースで１文字ずつ消しても普通に消えてしまうが、エラーは発生する。)

↓バックスペースを１回クリックで「グ」→「ク」に。
![スクリーンショット 2021-01-16 18.54.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948417/33cfbc2f-8afa-d7ca-db07-2990be9502bd.png)
![スクリーンショット 2021-01-16 18.54.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948417/5db80c89-e5cf-7a03-2550-9fca6c38fcba.png)

#まとめ
色々調べる中で、様々な場面でuft-8-macによる障害が出ていることがわかった。
MacOSを絡めた文字列指定の処理を実装する際は注意したい。
また執筆にあたりsafariで事象再現を試みた際に再発せず、Chromeのエンコード機能が無いこと(v55以降にて廃止)、safariがアップロード時やブラウザ表示時にエンコード処理をしてくれていることに気づいた。
開発がクラウドベースに移行するにつれて、開発環境としてのWebブラウザの重要度が高くなっているように感じており、そちらにも注意を払いたい。
Azure Java開発用のサンプルコード集



[Azure-Java-SDK JavaDoc](http://azure.github.io/ref-docs/java/index-all.html)

[Github Azure-Java-SDK](https://github.com/Azure-Samples?q=&type=&language=java)

[MicroSoft公式 : コードサンプル検索サイト](https://docs.microsoft.com/ja-jp/samples/browse/)
【Node.js Sequalize】 Unable to find migration: エラーの解決法

マイグレーションの誤操作により、マイグレートをかけた時に、削除したマイグレーションファイルが引っかかってきて、下記の様なエラーが表示された場合の解決法。

```
ERROR: Unable to find migration: 20210105140820-create-user.js
```

一旦,migrationsディレクトリの中に表示されたファイルを作成する。

```20210105140820-create-user.js

'use strict';

module.exports = {
  up: function (queryInterface, Sequelize) {
    return Promise.resolve()
  },

  down: function (queryInterface) {
    return Promise.resolve()
  }
};
```

全てのマイグレーションをロールバックする。

```
npx sequelize-cli db:migrate:undo:all
```

先ほど作成したファイルを削除する。

マイグレートをかける。

```
npx sequelize-cli db:migrate --env development
```

以上
【AWSデプロイ】S3設定にてExcon::Error::Forbiddenエラーが発生する

# はじめに
Railsでポートフォリオ作成しAWSにてデプロイ後、S3を使って画像をアップロードする設定を行っていましたが、本番環境にてS3にアップロードされない事態が発生。

#環境
・Rails 6.0.0
・Ruby 2.6.5
・Unicorn 5.4.1

# 状況
S3の設定をおこない、ローカル環境で無事にS3にアップロードされたことを確認。
本番環境の環境変数をevnに設定してデプロイをおこなったが
画像投稿を行ってもS3にアップロードされなかった。


# 問題解決のために行ったこと
まずはどのようなエラーが起こっているか確認するため
config/environments/production.rb
を
config.consider_all_requests_local = true
に変更。
これにより、ローカルの時のようにエラー文が画面に表示されるようになります。

するとExcon::Error::Forbiddenというエラーが発生していることが判明。
どうやら環境変数の設定がうまくいっていないよう・・・

sudo vim /etc/environmentにて入力内容を確認

```ruby:ターミナル
AWS_ACCESS_KEY_ID='#####アクセスキー######'
AWS_SECRET_ACCESS_KEY='##########シークレットアクセスキー##########'
```

入力ミスはしていなさそう・・・

env | grep AWSで確認

```ruby:ターミナル
env | grep AWS
AWS_ACCESS_KEY_ID=#####アクセスキー######
AWS_SECRET_ACCESS_KEY=##########シークレットアクセスキー##########'
```

あれ？？
シークレットアクセスキーの最後に’がついている・・？なんで？

もう一度sudo vim /etc/environmentで丁寧に確認してみると・・

```ruby:ターミナル
AWS_ACCESS_KEY_ID='#####アクセスキー######'
AWS_SECRET_ACCESS_KEY='##########シークレットアクセスキー##########'
```
図で表現できませんが、
AWS_SECRET_ACCESS_KEY='##########シークレットアクセスキー##########'の最後に
スペースが一つ入っていました・・・

AWS_SECRET_ACCESS_KEY='##########シークレットアクセスキー##########'　を
AWS_SECRET_ACCESS_KEY='##########シークレットアクセスキー##########'に直す。

変更を反映させるために一度ログアウトし入り直す。

env | grep AWSで確認

```ruby:ターミナル
env | grep AWS
AWS_ACCESS_KEY_ID=#####アクセスキー######
AWS_SECRET_ACCESS_KEY=##########シークレットアクセスキー##########
```

これでもう一度画像投稿を行ったところ、
無事S3にアップロードされました。

# さいごに
スペース一つに数日間悩まされました。
ネットで同じような事例がなく、かなり遠回りをしたので
同じような状況で苦しんでいる人の助けになればと思い投稿しました。
SubtypingとInheritanceを区別する

# はじめに
SubtypingとInheritanceについて説明します。
両者の違いを理解します。[1]を参照します。

# Subtyping (サブタイピング)
>
Subtyping refers to compatibility of interfaces. A type B is a subtype of A if every function that can be invoked on an object of type A can also be invoked on an object of type B.
>

Subtypingは**interfaceの互換性**に着目します。 
AのすべてのfunctionがBにおいても呼び出すことができる場合、BをAのsubtypeといいます。

# Inheritance (継承)
>
Inheritance refers to reuse of implementations. A type B inherits from another type A if some functions for B are written in terms of functions of A.
>

Inheritanceは**実装の再利用**に着目します。
AのfunctionによってBのいくつかのfunctionが実装されている場合、BはAを継承します。

# References
- [1] https://www.cmi.ac.in/~madhavan/courses/pl2009/lecturenotes/lecture-notes/node28.html
AWSのインスタンスタイプ(TとかGとか)の意味まとめ

#### EC2 Instance Types (主要メンバー)

### R 
* RAMのR インメモリキャッシュがたくさん要るアプリケーションならこれ！

### C
* CPUのC 演算処理、DB用でCPUがほしいならこれ！

### M
* mediumのM 中間の性能　通常のappはこれでおけ！

### I
* I/OのI DBの性能がほしいならこれ！

### G
* GPUのG 動画像処理や機械学習するならこれ！

### T2/T3 
* burst可能なインスタンス！　上限あり

### T2/T3 unlimited
* 無限にburst可能！　料金に注意！！

Ultimate AWS Certified Solutions Architect Associate 2021
https://www.udemy.com/course/aws-certified-solutions-architect-associate-saa-c02/
【Unity】カメラの揺らし方

# 方法
揺れるという動きを**「視点が球内部のランダムな点に移動し続けた後、元の視点に戻る」**という風に解釈します。掴みにくい方は以下の動画の立方体を追ってみてください。球内部の点にランダムで移動しているだけですが、立方体に注視することで目が回るような感覚に陥ると思います。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">記事用<br>球内部の点にランダム移動 <a href="https://t.co/TODhvRherq">pic.twitter.com/TODhvRherq</a></p>&mdash; TANUKEINA (@FH1b4mzzirXPoiM) <a href="https://twitter.com/FH1b4mzzirXPoiM/status/1350437645457915906?ref_src=twsrc%5Etfw">January 16, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 実装
実装はシンプルで以下のコードになります。

```cs:CameraShake.cs
using System.Collections;
using UnityEngine;

public class CameraShake : MonoBehaviour
{
    public IEnumerator Shake(float duration, float magnitude)
    {
        Vector3 originalPosition = transform.position;
        float elapsed = 0f;

        while (elapsed < duration)
        {
            transform.position = originalPosition + Random.insideUnitSphere * magnitude;
            elapsed += Time.deltaTime;
            yield return null;
        }
        transform.position = originalPosition;
    }
}
```
球の半径とカメラが揺れる時間を引数に渡して使用します。

```
transform.position = originalPosition + Random.insideUnitSphere * magnitude;
```
`Random.insideUnitSphere`とは半径1の球体の内部の点をランダムに返すメソッドになります。**`半径 = 1 * magnitude`とすることで、揺れの大きさを決定しています。**

```
elapsed += Time.deltaTime;
```
ランダムに位置を変更する毎の時間を`elapsed`に追加しておき、**指定時間を超えるまで処理を続けます。**

# 使用方法
以下のように呼び出して使用します。

```
StartCoroutine(cameraShake.Shake(0.3f, 0.6f));
```
使用用途に合わせて、揺れの大きさや、揺れ時間を変更するとGOOD！

#実装動画
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">記事用<br>カメラを揺らす <a href="https://t.co/skLn7U0KWu">pic.twitter.com/skLn7U0KWu</a></p>&mdash; TANUKEINA (@FH1b4mzzirXPoiM) <a href="https://twitter.com/FH1b4mzzirXPoiM/status/1350770973855780869?ref_src=twsrc%5Etfw">January 17, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#　終わりに

* 注意点として、**`Canvas`内部は揺れません。**UIや背景等も揺らしたい場合は、`Canvas`から外しましょう。
* 一回作成しておくと、使い回しのきく便利なプログラムになると思います。是非参考にしてみてください。
Vue.jsの基本的な使い方　備忘録

#Vue.jsを使うには
HTMLファイルでVue.jsをCDNを用いて直接読み込む場合、ソースコードは上から下に読み込まれて行くのでbodyタグの一番最後の記述する。

```ruby:HTML
<body>
  <div id="app"> ⇦　divタグにid=appと指定することでappの部分は任意の文字でOKです。
　　　<!-- 今回の場合このdivタグ内がVue.jsが影響を及ぼす範囲です。-->
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  <script src="js/main.js"></script>
</body>
```

jsファイルで「 var app = new Vue 」と変数化することでコンソールからアクセスすることができる。

```ruby:js
var app = new Vue({
  el: '#app',
})
```


##v-if
真偽値を用いて要素を表示・非表示の切り替えを行う。要素自体を生成/破棄している

```ruby:HTML
<div id="app">
  <p v-if="toggle"> ⇦　ここでtoggleのfalseをv-ifが受け取り要素を非表示にしています
    Hello
  </p>
</div>
```


```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    toggle: false ⇦　この場合pタグの要素が非表示になる。trueにすると再表示されます。
  }
})
```


##v-show
CSSのdisplayをnoneにすることで表示している要素を消しているためデベロッパーツールで該当の箇所を箇所を確認すると要素は残っている。

```ruby:HTML
<div id="app">
  <p v-show="toggle"> ⇦　ここでtoggleのfalseをv-ifが受け取り要素を非表示にしている。
    Hello
  </p>
</div>
```


```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    toggle: false ⇦　この場合pタグの要素（Hello）が非表示になる。trueにすると再表示されます。
  }
})
```

##v-on
DOM要素にイベントリスナーを登録する

```ruby:HTML
<div id="app">
  <button v-on:click="onClick"> ⇦　ここでv-on:clickにイベントハンドラのメソッド名を入れて呼ぶ
    クリック
  </button>
  <p>
    {{ now }}　⇦　現在日時がnowに代入されて表示される
  </p>
</div>
```

```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    now: ''
  },
  methods: {
    onClick: function() {
      this.now = new Date().toLocaleString(); ⇦　nowに現在時刻を代入するメソッド
    }
  }
})

```

##v-for
"color in colors"とすることで、colorsの配列に入っている値を繰り返し処理でcolorに代入している。その後liタグ内でcolorを呼び出すことで
1. Red
2. Green
3. Blue
と表示される。

```ruby:HTML
<div id="app">
  <ol>
    <li v-for="color in colors">{{ color }}</li>
  </ol>
</div>
```

```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    colors: ['Red', 'Green', 'Blue']
  }
})
```

##v-model
双方向データバインディングが行えるディレクテブ。
入力フォームに値を入れた場合、リアルタイムでプロパティを変更することができる。

```ruby:HTML
<div id="app">
  <p>
    <input type="text" v-model="message"> ⇦　双方向データバインディングがしたいプロパティをv-modelに入れる
  </p>
　<!-- 下記のようにすることでmessageオブジェクトの値が変わって行くことを確認できる -->
  <pre>{{ message }}</pre> ⇦　入力フォームで変更を加えた場合messageの値も同じように変更される
</div>
```

```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
```


##v-bind
属性へのデータバインディングを使用する場合は、マスタッシュ構文ではなくv-bindを使用する。
v-bindを下記のようにインプットタグで使う場合、属性の値にはプロパティ名を使用する。
下記のように記述することで入力欄に「Hello Vue.js」と表示される。

```ruby:HTML
<div id="app">
  <input type="text" v-bind:value="message"/>
</div>
```


```ruby:js
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js'
  }
})　
```
JavaScriptで数値を任意の文字数のゼロ埋め文字列にする

## 結論

数値のゼロ埋め（zfill, ゼロフィル）にはpadStart()を使いましょう。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart

## 本題

「JavaScript zfill」とかで検索しても、``'000' + String(num)``みたいに文字列をくっつけてからslice()するみたいな手法がたくさん引っかかりますが、今のJavaScriptにはpadStart()という便利な関数がありました。

```javascript

const num = 123;
console.log(String(num).padStart(5, '0') // '00123'
```

## 使い方

冒頭のリファレンス読めばわかりますが以下のとおりです

``String.prototype.padStart(<目標の文字数>, <目標への不足分を埋める文字>)``
[React] Reactの学習をします（1-2）コンポーネントの分割

#Reactの学習をします（1-2）

Reactの学習をしてみることにしました。
前回の記事　：　[[React] Reactの学習をします（1-1）](https://qiita.com/IwashiMorino/items/964c0af1df09c83b0872 "[React] Reactの学習をします（1-1）")

##教材

[Reactチュートリアル1：犬画像ギャラリーを作ろう](https://zenn.dev/likr/articles/6be53ca64f29aa035f07#web-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E3%83%9E%E3%83%BC%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B "Reactチュートリアル1：犬画像ギャラリーを作ろう")

likr さんが公開している「Reactチュートリアル1：犬画像ギャラリーを作ろう」という記事を教材に学習させて頂きます。

素晴らしい教材をありがとうございます。

##学習日記

本日は「Web アプリをマークアップする」～「コンポーネントの分割」までやりました！

##Web アプリをマークアップする

※ 教材から箇条書き的に抜粋させて頂きます。

src/App.js

>・React では、JSX という拡張構文で、 JavaScript の中に HTML のマークアップを記述します

>・React では、JSX を返すような関数を特別に コンポーネント と呼びます。

>・コンポーネントは、アプリケーションの状態から JSX 式を組み立てて、その結果を HTML としてレンダリングします。

##CSS フレームワークを使う

※ 教材から箇条書き的に抜粋させて頂きます。

>・本稿では、CSS フレームワークの一種である Bulma を使用します。

Bulma公式ページ　：　[Bulma公式](https://bulma.io/ "Bulma公式")

##コンポーネントの分割

※ 教材から箇条書き的に抜粋させて頂きます。

>・Appコンポーネントの中身が随分長くなってしまいました。こういうときはコンポーネントの分割をしましょう。

>・コンポーネントを使う側のコンポーネントを 親コンポーネント、別のコンポーネントから使われる側のコンポーネントを 子コンポーネント と呼びます。

下図のように表示させることができました！

![023a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/897250/37947c15-a1b1-1bab-4f90-27502f77eedb.png)