OmniAICreator/Qiita-1.07M huggingface dataset:
特定の長さの文字列をクリップボードにコピーする方法

1000字の文字列をクリップボードにコピーしたいとき
PowerShellを起動し、次のコマンドを実行する
環境はWindows10

\[string]::new("w",1000)|Set-Clipboard

貼り付け

```
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
```

---

r1r1r1... という100字の文字列を作る

```posh
(1..50|%{"r1"})-join""|Set-Clipboard
```

貼り付け

```
r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1r1
```
REACT-MAP-GLのexampleを紹介します

##概要
今、マップアプリをReactで作ろうとしています。
Uberが提供しているREACT-MAP-GLというライブラリを使おうと、色々試しています。
REACT-MAP-GLには色々なexampleが入ってますので、少し紹介します。

##表示方法
全てのexapleは以下の手順で使うことができます。

###MapboxからTokenを取得
MapboxのサイトからTokenを取得します。
[Mapbox(リンク)](https://www.mapbox.com/)

###app.jsを編集
exampleフォルダの下に様々なexapleのフォルダがあります。
使いたいexampleフォルダを開きsrc/app.jsを開きます

以下の一文を編集します。

```
const MAPBOX_TOKEN = ''; // Set your mapbox token here
```
この「'　'」にMapboxのTokenを入れます。

```
npm install
```

```
npm run start-local
```
これで表示されます。


##exampleの紹介
###controls
このexampleではポップアップを表示させることができます。
町のポップアップとWikipediaのリンクが確認できるかと思います。

[![Image from Gyazo](https://i.gyazo.com/005c375748b2e6dfda6d0255fd324f8d.png)](https://gyazo.com/005c375748b2e6dfda6d0255fd324f8d)

###geojson-animation 
json情報を元にmap上に描画を行います。
[![Image from Gyazo](https://i.gyazo.com/6a8061b53b2572eb1f210f1541e08b59.gif)](https://gyazo.com/6a8061b53b2572eb1f210f1541e08b59)

###draggable-markers  
こちらはドラックできるマーカーを描画することができます。
[![Image from Gyazo](https://i.gyazo.com/9c62348e6c4cffcd6a3a4e120d80dc04.gif)](https://gyazo.com/9c62348e6c4cffcd6a3a4e120d80dc04)


###heatmap
こちらはヒートマップを描画します。
デフォルトでは地震の回数をもとにヒートマップを描いています。
[![Image from Gyazo](https://i.gyazo.com/72dcbfdd6bce0890b0cf185b092d6329.gif)](https://gyazo.com/72dcbfdd6bce0890b0cf185b092d6329)
ブラウザでローカルの mp4 を再生するプレイヤーを video タグで作る

# やること

ブラウザで、ローカルの mp4 ファイルを選択して、再生、停止、再生速度の変更などができる簡易プレイヤーを作ります。というか、それをベースに何か作りたいと思ったとき用のメモ。

# 参考

- [クライアント側だけでローカルの動画を再生しつつ任意のタイミングでサムネイル画像を生成する](https://qiita.com/geek_duck/items/75823c84645344a1f5f4)

# コード

下記で実際に動いた状態を見られます。
ー https://royalcrab.github.io/mp4_local.html

```index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
    <video id="video" height="480" controls></video><br/>
    royalcrab@超Lチカ団 (2020)<br/>
    <input type="file" id="filename" value="ファイル読み込み"/><br/>
    <input type="button" value="再生" onClick="play()"/>
    <input type="button" value="停止" onClick="pause()"/><br/>
    <input type="button" value="速く" onClick="changeSpeed(0.1)"/>
    <input type="button" value="遅く" onClick="changeSpeed(-0.1)"/><br/>
    再生位置  :<span id="position">-</span><br/>
    再生速度  : <span id="speed">1.0</span><br/>
    ファイル名 :<span id="filename">none</span><br/>

    <script>
    
    function init(){
        var f = document.getElementById("filename");
        f.addEventListener( "change", function (event) {
            var URL = URL || webkitURL;
            var file = event.target.files[0];
            document.querySelector('video').src = URL.createObjectURL(file);
            document.getElementById('filename').innerHTML = document.querySelector('video').src;
        }, false );

        var v = document.getElementById("video");
        v.addEventListener("timeupdate", function(){
            document.getElementById("position").innerHTML = v.currentTime;
            document.getElementById("speed").innerHTML = v.playbackRate.toFixed(1);
        }, false);
    }

    function play() {
        var v = document.getElementById("video");
        if  ( v == null || v.src == null ) return;
        v.play();
    }

    function pause() {
        var v = document.getElementById("video");
        if  ( v == null || v.src == null ) return;
        v.pause();
    }

    function changeSpeed( val ) {
        var v = document.getElementById("video");
        if  ( v == null || v.src == null ) return;
        if ( v.playbackRate + val < 0.1 ) v.playbackRate = 0.1;
        else v.playbackRate += val;
    }

    init();
    </script>
</body>
</html>
```

- input の type を file にして、その input にファイル読み込み function を addListener する。
- Blob URLs は iOS の chrome では動かないかも。他ではだいたい動きそう。
対応状況: https://caniuse.com/#feat=bloburls
MySQLの照合順序について

# はじめに
テーブルを作るときに照合順序の指定を間違えて、期待したことができず混乱したのでメモ。

# 経緯
mysqlテーブルを使って一種のバージョン管理を行うため、比較条件の厳しいutf8_binを使おうとしたら照合順序がテーブルに反映されなかった。


## 期待する結果
テーブルを作成する時、データベースに設定された照合順序に合わせて文字コードなどが指定されること。



# SQL文を色々試してみた。

## 正しいSQL文
文字コードと照合順序を正しく指定したSQL文を処理させてみる。

```sql:正しいSQL文
create `database name`.`table name` (
  column_name data_type ( number )
  column_name data_type ( number )
) character set utf8 collate utf8-bin;
```

結果、文字コードと照合順序を正しく指定しているため、想定通りのテーブルとなる。


## 文字コードだけ指定したSQL文
文字コードは正しく指定するが、照合順序を指定していないSQL文を処理させてみる。

```sql:指定された文字コードをもとにinformation_schema.character_setに対応したis_default=yesの照合順序から取ってくる
create `database name`.`table name` (
  column_name data_type ( number )
  column_name data_type ( number )
) charset set utf8;
```

結果、作成されるテーブルの照合順序は思い通りになるとは限らない。


## 文字コードも照合順序も省いたSQL文
文字コードと照合順序を指定しないSQL文を処理させてみる。

```sql:データベースに設定されている文字コードと照合順序を持ってくる
create `database name`.`table name` (
  column_name data_type ( number )
  column_name data_type ( number )
);
```

# 結論
当たり前のことだけど、SQL文をテキトーに書くと思った挙動にならないので注意が必要。

# 参考
- https://www.dbonline.jp/mysql/table/index1.html
Base64 encode を C# で実装してみる

## Base64 の目的

8bitで表現される任意の値が設定されたバイト列を、安全に通信するためにテキストで表現できる形式に変換すること。

## Base64 encode の変換形式

8bitのバイト列を6bitずつ取り出し、[a-zA-Z0-9+/] に割り当て直す。 

つまり、24 bit = 8 bit * 3 のバイト列は 24 bit = 6 bit * 4 のバイト列に変換される


## 変換の概要

### 8bit の列を 6bit の列に分割する

```
bbbbbbbb bbbbbbbb bbbbbbbb
↓
bbbbbb bbbbbb bbbbbb bbbbbb
```

### 6bit の列を定義した変換表を使って変換する

```
0b000001 = 'A'
0b000010 = 'B'
0b000011 = 'C'
...
0b111111 = '/'
```

3バイトに満たない列には'='を埋める

## Base64 の問題点

割り当て直す [a-zA-Z0-9+/] のうち、[a-zA-Z0-9] はどういう環境でも安全に扱えるが、のこりの [+/] については環境によってはそのまま使えず別途エンコードする必要がある。たとえば '/' はパス区切りには使えず、URL表現だと問題が発生するし、'+' も同様にURL表現で問題が発生する可能性がある。

ゆえに[+/]を別の安全に使えそうな文字に置き換えるとかする必要がある(典型的にはURLEncodeによって数値参照形式にするなど)

## C#による実装

似たロジックはSMF(Standard MiIDI Format)における8bitの列から7bitずつを取り出す方法だが、SMFだとC#のバイト列とはエンディアンが逆なのでそのままは使えない。

参考: https://qiita.com/ringorou/items/5e2384f7cf226d9e648a

### 考え方

変換対象のバイト列の長さは不定だが、8bit から 6bit ずつ取り出せばよいので 24bit のみ考えればよい。

1．第1バイトを2ビット右シフトした値と 0b111111 の積 a を格納
2. 第1バイトを4ビット左シフトした値と 0b111111 の積 b を格納
3. 第2バイトを4ビット右シフトした値とbの和を 0b111111 の積をとった値 c を格納
4. 第2バイトを2ビット左シフトした値と 0b111111 の積を d を格納
5. 第3バイトを6ビット右シフトした値とdの和を 0b111111 の積をとった値 e を格納
6. 第3バイトと 0b111111の積 f を格納
7. 格納した値 a, c, e, f の列を変換表を使って変換する
8. 余った位置には'=' を追加する

### 実装

```csharp
// 変換表
static readonly string map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

public static string Encode(byte[] source)
{
    // エンコード後の長さを計算し、余る長さを求める
    var encodedLength = source.Length * 8 / 6;
    var remain = 0;
    if ((source.Length * 8 % 6) > 0)
    {
        encodedLength++;
        remain = (4 - encodedLength % 4);
        encodedLength += remain;
    }
    var encoded = new char[encodedLength];
    int offset = 0;
    byte next = 0;
    var n = 0;
    var m = 0;
    int i;
    // 変換の本体
    while (n < source.Length)
    {
        next = 0;
        for (i = 0; i < 3 && n < source.Length; ++i, ++n)
        {
            offset = (i + 1) * 2;
            encoded[m++] = map[(next | (source[n] >> offset)) & 0b111111];
            next = (byte)((source[n] << (6 - offset)) & 0b111111);
        }
        encoded[m++] = map[next];
    }
    if (remain > 0)
    {
        for (var p = encodedLength - remain; p < encodedLength; ++p)
        {
            encoded[p] = '=';
        }
    }

    return new string(encoded);

}
```

## その他

* 当然、組み込みの関数を使った方が効率はよい。
* 例えば '+','/' を別の文字に置き換える場合でも組み込み関数の出力を Replace等で置き換えた方が早い。
* 上のロジックでnew string()するのはいかがなもの、と思うがStringBuilderに変換結果を入れても最終的には同じことになるので意味はない
* 他に高速化、効率化するポイントはあると思うけどとりあえずの目的は達成できる

以下はそれぞれ Convert.ToBase64String, それの'+/'をReplaceで変換するもの、この記事のロジックでのベンチマーク結果。

|              Method |     Mean |    Error |   StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------------- |---------:|---------:|---------:|-------:|------:|------:|----------:|
|       ConvertBase64 | 249.4 ns | 560.1 ns | 30.70 ns | 0.0758 |     - |     - |     120 B |
| ConverBase64Replace | 310.4 ns | 404.5 ns | 22.17 ns | 0.1049 |     - |     - |     165 B |
|      OriginalBase64 | 543.8 ns | 982.8 ns | 53.87 ns | 0.1216 |     - |     - |     192 B |
【Unity】ToggleGroup内のToggleを取得するには？

# はじめに
Unityでラジオボタンを作るときに活躍する[ToggleGroup](https://docs.unity3d.com/ja/current/ScriptReference/UI.ToggleGroup.html)。
複数のToggleをグルーピングして、選択Toggleを択一（排他）にする機能を提供してくれます。

ところがこのToggleGroup、少し曲者です。
というのも、管理している**すべてのToggleを知る手段を提供していない**のです。[^1]

[^1]: もちろん選択されているToggleは取得できます（[ActiveToggles](https://docs.unity3d.com/ja/current/ScriptReference/UI.ToggleGroup.ActiveToggles.html)）。でもなんで戻り値が単一じゃなくコレクションなんだろう…？

これは特に問題にならないことも多いですが、例えば、ToggleGroupから選択肢一覧を知りたいときなどに困ります。（結局自分で別管理することになったり…。）
今回はそんなときにどうするのがよいか、考えてみます。

# 案
主に2つの方法が考えられます。

## 1. Toggle側からアプローチする
Toggleは[group](https://docs.unity3d.com/ja/current/ScriptReference/UI.Toggle-group.html)という自身が所属するToggleGroupを表すプロパティをもっています。
それならば、シーンにあるToggleを集めてそのgroupを調べればいい…。例として下記のようなコードで実現できます。

```cs
// using System.Linq;が必要

    /// <summary>
    /// ToggleGroupに所属するToggleを取得
    /// </summary>
    /// <param name="toggleGroup"></param>
    /// <returns></returns>
    private IEnumerable<Toggle> GetTogglesOf(ToggleGroup toggleGroup)
    {
        var toggles = GameObject.FindObjectsOfType<Toggle>();
        return toggles.Where(x => x.group == toggleGroup);
    }
```

この取り方はToggleGroupからのアプローチでない故の分かりにくさが欠点かもしれません。
あとは検索コストがかかるため少し無駄を感じます。

## 2. リフレクションで取り出す
無理やり何とかしたいときの常套、リフレクションです。
実はuGUIのソースコードは[Bitbucketで公開](https://bitbucket.org/Unity-Technologies/ui/src/2019.1/)されているため、内部でどうToggleをもっているかを知ることができます。
[該当のソースコード](https://bitbucket.org/Unity-Technologies/ui/src/2019.1/UnityEngine.UI/UI/Core/ToggleGroup.cs)を見てみると`List<Toggle>`型の**`m_Toggles`**という名前でprivateフィールドでもっていることが分かりました。

フィールド名が分かってしまえば、下記のような拡張メソッドを作ることでいけます。[^2]

[^2]: 本当はToggleGroup.togglesのようにプロパティで書きたいところですが、現時点（C#7.3）には拡張プロパティはないらしいです。


```ToggleGroupExtensions.cs
using System.Collections.Generic;
using System.Reflection;
using UnityEngine.UI;

/// <summary>
/// トグルグループ拡張
/// </summary>
public static class ToggleGroupExtensions
{
    /// <summary>
    /// ToggleGroupがもつToggleのFieldInfo
    /// </summary>
    private static FieldInfo _togglesFieldInfo = null;


    static ToggleGroupExtensions()
    {
        _togglesFieldInfo = typeof(ToggleGroup).GetField("m_Toggles", BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic);

        if (_togglesFieldInfo == null)
        {
            throw new System.Exception("Not compatible with the current version of ToggleGroup.");
        }
    }

    /// <summary>
    /// トグル一覧を取得
    /// </summary>
    /// <param name="self"></param>
    /// <returns></returns>
    public static IEnumerable<Toggle> GetToggles(this ToggleGroup self)
    {
        return (_togglesFieldInfo.GetValue(self) as List<Toggle>);
    }
}
```

使うときはこんな感じになります。

```cs
    foreach (var item in _toggleGroup.GetToggles())
    {
        Debug.Log(item.name);
    }
```

なお、注意点として、リフレクションの性質上ToggleGroupの内部実装が変わると互換性を失う可能性があります。

# おわりに
今回紹介した方法はどちらも素直なやり方という感じはしませんね。
どうせ機能拡張などを見越しているなら、自分でToggleGroupに代わる実装するのがベストなのかもしれません。（中身見れるので参考にもできますしね…。）
PHP基礎構文　ヒアドキュメントとNowdocの構文と違いについて

# TL;DR
- 基礎構文の１つでもある**ヒアドキュメント**と**Nowdoc**の構文に関して
- 基本的に**ヒアドキュメント**で事足りる印象
- **適切さ**でいうと、変数展開を利用しないのであれば、**Nowdoc**を利用すべきなのかもしれない

# ヒアドキュメントとは
文字列を変数に代入、または出力するために利用する機能
機能の特徴柄、主に長い文字列の代入・出力のために利用する事が一般的な利用方法

# ヒアドキュメント構文
```php
$text = 'hello';
echo <<< EOL
input text.
{$text}
EOL;

/*
 * 出力結果
 *
 * input text.
 * hello
 */
```

# Nowdoc構文
```php
$text = 'hello';
echo <<< 'EOL'
input text.
{$text}
EOL;

/*
 * 出力結果
 *
 * input text.
 * {$text}
 */
```

# 構文の違い
## 1. エンドトークンにクォートがついてるかどうか
- ついてるのが、**ヒアドキュメント**
- ついていないのが、**Nowdoc**

### エンドトークンとは
- EOLなどの特定の文字列を指す
- 例文に利用してるEOL以外にも下記ものも利用できる
    - EOD
        - End Of Documentの略
    - EOF
        - End Of Fileの略
    - EOS
        - End Of Sentenceの略
    - EOT
        - End Of Textの略
    - EOL
        - End Of Lineの略

※利用するエンドトークンは同じである必要がある。
例えば、開始のエンドトークンに**EOL**、終わりのエンドトークンに**EOD**、などは利用できない


## 2. 変数展開ができるかどうか
- できるのが、**ヒアドキュメント**
- できないのが、**Nowdoc**
Azure SAS入門



## SAS(Shared Access Signature)とは

- ストレージ操作を認可するための署名済URI
  - 例：参照操作を認可するSASを使えば、当該ストレージを参照できる
  - 署名鍵はSASの種類によって異なる。

## SASの構成
- SASは`https://{ストレージのURI}?{SASトークン}`で表される。
  - SASトークン：クライアントからストレージへのアクセス方法を表すトークン

## SASの種類

|SAS|SASを使用可能なストレージ|署名用キー|補足|
| --- | --- | --- | --- |
|User Delegation SAS|Blob|User Delegation Key|認証機構としてAAD（Azure Active Directory）を用いる。AADは認証方式として最も信頼できる（Microsoft談）ため、Blobへのアクセス時は通常これを使用する。|
|Service SAS|任意のストレージ|Storage Account Key|1つのSASで1種類のストレージのみアクセス可能|
|Account SAS|任意のストレージ|同上|1つのSASで複数の種類のストレージにアクセス可能。また、Service SASに比べて多種類の操作権限を移譲可能|

- BlobにはUser Delegation SASを、他のストレージにはAccount SASを使えば良いと思う。

## SASの2つの形式

### Ad hoc SAS

- SAS URIで下記を指定する
  - SASの生成時刻
  - SASの有効期限
  - 委任する権限
- 全ての種類のSASに使用可能
- 基本はこれを使えば問題ない

### Service SAS with stored access policy

- Service SASに対してのみ使用可能な形式
- 詳細は割愛

## SASを用いたストレージアクセスの流れ
1. クライアントが認可サーバーにSASの発行を要求
    - 発行には認証情報が必要
1. クライアントが、発行されたSASを用いてストレージにアクセス

## 参考

- [公式doc](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview)
Vue AtomicDesignでフォルダ構成する

##AtomicDesign
今回はAtomicDesignの考えのもと、フォルダ構成していきたいと思います。<br>
<b>AtomicDesignとは</b>
一言で言うと5段階に区切って定義するUIデザイン手法。
5段階とは、
`Atoms(原子)`,
`Molecules(分子)`,
`Organisms(有機体)`,
`Templates(テンプレート)`,
`Pages(ページ)`です。<br>
化学用語が分からなくても実は簡単。
##5段階詳しく
`Atoms(原子)` 
ボタンやテキスト入力などの分けられない単位。

`Molecules(分子)` 
ボタンやテキスト入力を組み合わせたフォーム(検索フォーム)。

`Organisms(有機体)` 
フォームだったりボタンなど組み合わせたヘッダー。

`Templates(テンプレート)` 
ヘッダーとかフッターを組み合わせたページの枠組みです。

`Pages(ページ)` 
テンプレートの枠組みに内容を入れた状態がページ。


##VueでAtomicDesign
AtomicDesignの考えをもとにVueでフォルダ構成しました。
それがこちら

```
.
├── node_modeuls/
├── src/
│     ├── assets/
│     ├── components/
│         ├── atoms/
│         │    └──buttons/
│         ├── molecules/
│         └── organisms/
│              └── footer.vue
│ 
├── pages/
├── main.js
├── router/
│   └── index.js
├── store/
└── App.vue

```
AtomicDesignをカスタマイズして構成しました。<br>
カスタマイズ点
<b>1.</b>Templateは必要がないので削除
<b>2.</b>organismsとpagesのみstoreとやりとりするのはOK。
<b>3.</b>pagesはrouterとやりとりするのでcomponents外
<b>4.</b>atomsの中にもボタンや入力欄を分けるためにフォルダを作成<br><br>
人それぞれの好みとプロジェクト規模により異なる点もあるかと思うので参考にしてもらえればと思います。<br><br>以上！

##はてなブログもやってます
はてなブログのVue系⬇︎
https://taitoajiki.hatenablog.com/archive/category/Vue
Node.js module管理の仕組み

Node.jsデザインパターンを読んで勉強中なので
そちらの備忘録として投稿していきます。

まず初めにNode.jsがどうやって異なるバージョンの同一モジュールを管理し、
「依存地獄（dependency hell）」を回避しているかを整理します。

# Node.jsの依存解決アルゴリズム
Node.jsがモジュールを読み込む時に
指定されたモジュール名をもとにモジュールをコアモジュール、もしくはローカルファイル
から探すために使用されるアルゴリズムは
以下の三段階に分かれている。

1. コアモジュール
まずは指定されたモジュール名がNodeのコアモジュールかどうか調べる

2. ファイルモジュール
コアモジュールに見つからなかった場合、ローカルファイルシステムを探す。
モジュール名が「/」で始まる場合は絶対パスとして、「./」、「../」で始まる場合は
requireを呼び出しているファイ ルからの相対パスとして解釈される。

3. パッケージモジュール
モジュール名の開始文字列が「/」、「./」、「../」のいずれでもない場合は、
requireを呼び出しているファイルと同じディレクトリの下にあるnode_modulesディレクトリの中を探す。

それでも見つからない、もしくはnode_modulesディレクトリがなかった場合
さらに親のディレクトリを探しにいき、上へ上へ探索していき
ローカルファイルシステムのルートに到達するまで探す。

## ファイルモジュールとパッケージモジュールのロード時のルール
ファイルモジュールとパッケージモジュールのロード時には
上記のアルゴリズム以外にルールがある。

- 指定されたモジュール名と同じ名前のファイルがあれば
  （なければ拡張子.jsもしくは.jsonを補完して確認）
  そのファイルをロードする。
- 指定されたモジュール名と同じ名前のディレクトリがあれば、その配下にpackage.jsonファイルがないか調べる。
  存在すれば、ファイル中のmainプロパティで指定されたファイルをロードする。
- 指定されたモジュール名ディレクトリ配下にindex.jsというファイルがあればロードする。

## 整理
`myApp/
├── foo.js
└─┬ node_modules
``   ``├── depA
`` ``   |``  `` ``└── index.js
`` ``  ├── depB
`` ``  │``  `` ``├── bar.js
`` ``  │``  `` ``└── node_modules
`` ``  │``  `` `` `` `` `` `` └── depA
`` ``  │``  `` `` `` `` `` `` `` `` `` `` └── index.js
`` ``  └── depC
`` `` ``  `` `` ``├── foobar.js
`` `` ``  `` `` ``└── node_modules
`` `` ``  `` `` `` `` `` `` `` └── depA
`` `` ``  `` `` `` `` `` `` `` `` `` `` `` └── index.js`
上記のようなディレクトリ構成として
各ファイルからモジュールdepAをロードしてみる。

- /myApp/foo.jsからrequire('depA')を呼び出した場合
/myApp/node_modules/depA/index.jsをロードする

- /myApp/node_modules/depB/bar.jsからrequire('depA')を呼び出した場合
/myApp/node_modules/depB/node_modules/depA/index.jsをロードする

- /myApp/node_modules/depC/foobar.jsからrequire('depA')を呼び出した場合
/myApp/node_modules/depC/node_modules/depA/index.jsをロードする

# まとめ
依存解決アルゴリズムにより、Nodeは複雑な依存関係も解決でき、
ひいては大規模なアプリケーションにおいて、
バージョン間の衝突なく何百、何千といった依存パッケージをもつことが可能になる

参考書籍
[Node.jsデザインパターン 第2版](https://www.oreilly.co.jp/books/9784873118734/)
Apacheのインストール：バイナリパッケージとソースファイルのメリット

# Apacheのインストール方法
- 基本unix系です。私は、CentOS or Linuxをいつも利用することが多いです。
- インストール方法は２種類ある。
- Apacheソフトウェア財団が入るしているソースアーカイブをビルドし、インストールする方法
- 各ディストリビューション（LinuxやUbuntuなど）提供しているバイナリパッケージにてインストールする方法。
　＊ざっくり言うと、yum installやapt-get install

# バイナリパッケージのメリット
- バイナリパッケージを利用できるなら、わざわざソースファイルを利用する必要はないと思う。
- 主要なLinuxディストリビューション（Fedora / CentOS / Ubuntu）には、あらかじめバイナリパッケージが用意されている。
- パッケージ管理ユーティリティを利用すると、インストール、削除、アップデート、依存関係の管理も簡単。
- パッケージによっては、プラットフォームのパフォーマンスを最大限引き出せるよう、バイナリレベルで最適化されている場合もある。
- Apacheにおいてはモジュール機構を採用しているので、機能追加のたびに再ビルドする必要はない。
　＊設定ファイルの変更でほとんど対応可能。

# ソースファイルからのインストールが必要なケース
- 使用しているプラットフォームに適合したバイナリパッケージが手に入らない場合
 - 基本的にはあまりないかな。。。
- 安定している旧バージョンをあえてインストールしたい場合。
 - Apache 2.4 /2.2 / 2.0といった複数のバージョンが平行でメンテナスされているので、旧式の安定したバージョンを使いたい場合があるかも!?
- いち早く最新のApacheを使用したい場合
 - 最新版Apacheのリリースはソースファイルが先。
 - 但し、脆弱性が高まる可能性もあるのでリスクは考慮した方がいい。
- インストールパスを変更したい場合
 - ソースファイルからのインストールする理由はこれだけかも。
 - **設定ファイル、ディレクトリ配置などをオプションで指定することが可能。**
- 複数のバージョンを同時にインストールしたい場合
 - インストールパス等を変更し、旧バージョンを残しながら、移行までの間利用することが可能。
- Apacheモジュールを静的に組み込みたい場合
 - **モジュール機能の拡張は「動的」で、サーバの負担となり、起動速度や実行速度が低下する。**
 - **ビルド時のオプションに含むことでApacheのコア機能にモジュールを「静的」に組み込むことが可能。**
- MPMを変更する場合
 - Unix系ではApache2.2まではMPMを切替るためにソースファイルを再ビルドする必要がある。
 - 2.3以降では、動的に切り替えることが可能。

# まとめ：感想
- 最初から利用するモジュールが決まっていれば、MPMに含めて静的モジュールとしてビルド可能なので、ソースインストールがオススメ。
- もしくは、バージョンを統一してどんな時期でも「完全に同じインストール」をする必要がある場合。
 - 小案件のプロジェクトで同じApacheを利用する場合はこっちの方がいいかも。横展開が楽。バージョン差異でのバグや脆弱性対応などがあればしやすい。
- それ以外は、バイナリパッケージがオススメ。
 - 正直ネットの情報もバイナリパッケージのインストールが多い。

# 記事を書いた理由：メモ
- Apache、Nginxなど様々なWebサーバ用OSSがある。
- Apacheをインストールする際に、いつもどっちがいいか迷うので簡潔に記録しておきたかったのが理由です。

# 参考
- 本：サーバ構築の実際が分かる Apache[実践]　運用/管理
Apacheの構造：MPM

# Apacheの構造
- Apacheは高機能と高パフォーマンスを同時に実現するため、モジュール構造を採用している。
 - モジュールとは、ある機能を実現するためのソフトウェア。
 - プログラム本体に組み込んだり、交換したりが可能な小さなプログラムのかたまり。
- ２種類のモジュール（MPMと一般的な機能モジュール）
 - コア機能のモジュール：MPMという
 - 一般的な機能モジュール

![IMG_6287.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484314/637404a1-8ce5-7abd-2423-0b43afd06c92.jpeg)

# MPM：マルチプロセッシングモジュール
- モジュールの機能をサーバの基本機能にまで拡張したのが、マルチプロセッシングモジュール（MPM）
- コア機能（MPM）の役割
 - **ネットワークポートをリスニングし、リクエストを受け付け、受け付けたリクエストを子プロセスやスレッドに割り当てるなどの役割を担う。**
- MPMは上記のコア機能をOSの特性やサーバ環境に合わせて交換可能としている。

# MPMの種類
- worker
 - マルチプロセス、マルチスレッドに対応。
 - 各プロセスに対し決められた数のスレッドを用意する。
 - スレッド動作はリソースあたりの処理能力がプロセス動作よりも高くなり、一般的に性能を向上させる。
- prefork（デフォルト）
 - あらかじめhttpd子プロセスをいくつか生成してクライアントからの要求を処理する。
 - マルチスレッドではなく、マルチプロセスでのみ動作する。
- perchild（Apache 2.2で廃止）
 - マルチプロセス、マルチスレッドに対応。
 - プロセスそれぞれに個別のユーザIDを割り当てることで可溶性を高めることが出来る。
 - 開発途中だったが、Apache 2.2で廃止
- event（Apache 2.2より）
 - スケーラビリティに優れたMPM
 - Worker MPMのようなマルチスレッド処理が可能
 - Keep-Aliveリクエスト処理に、コネクションを処理するスレッドとは別のスレッドを割り当てることが可能。
 - 上記の理由で、大規模な用途にも対応可能。
 - Apache 2.2 までのevent MPMは評価用で安定して利用できなかったが、Apache 2.4で改善されている。

# 記事を書いた理由：メモ
- Apache、Nginxなど様々なWebサーバ用OSSがある。
- Apacheの構造について簡潔に記録しておきたかったのが理由です。

# 参考
- 本：サーバ構築の実際が分かる Apache[実践]　運用/管理
Firestore の Document を定期的にバックアップする

公式ドキュメントが充実しているので、基本的には以下を参考にすれば済みます。

* GCS への定期的なエクスポート: **https://firebase.google.com/docs/firestore/solutions/schedule-export**
* それを BigQuery で色々する: https://cloud.google.com/bigquery/docs/loading-data-cloud-firestore
* gcloud コマンドによる操作: https://firebase.google.com/docs/firestore/manage-data/export-import

昔は GAE のインスタンスを作って cron job を定義して...という作業をしていましたが、今は☝️に書いた感じで済みます。

定期的なエクスポートの部分だけ、TypeScript のサンプルコードを載せます。

```sample.ts
export const exportFirestoreFunc = functions.region('asia-northeast1').pubsub
    .schedule('every day 05:00')
    .timeZone('Asia/Tokyo')
    .onRun(async _ => await exportToStorage())

async function exportToStorage(): Promise<void> {
  const admin = await import('firebase-admin')
  admin.initializeApp()
  const gcpProjectId = admin.instanceId().app.options.projectId
  const bucket = `gs://${gcpProjectId}.appspot.com`
  const client = new admin.firestore.v1.FirestoreAdminClient()
  const databaseName = client.databasePath(gcpProjectId, '(default)')

  try {
    const res : any[] = await client.exportDocuments({
        name: databaseName,
        outputUriPrefix: bucket,
        collectionIds: ['foo', 'bar']
    })
    console.info(`Operation Name: ${res[0]['name']}`)
  } catch (err) {
    console.error(err)
    throw new Error('Export operation failed')
  }
}

```
matplotlibのグラフの箱の大きさを正確に把握したかった

[spa]:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
# matplotlib.pyplot.subplots_adjustの概要
Pythonの描画library [matplotlib.pyplot](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.html#module-matplotlib.pyplot)には余白などを設定する[matplotlib.pyplot.subplots_adjust][spa]があります.

```python:
matplotlib.pyplot.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
```

[公式document][spa]から取ってきたものですが, parameterは以下のように0~1までの実数値を設定します.

```python:
left = 0.125  # the left side of the subplots of the figure
right = 0.9   # the right side of the subplots of the figure
bottom = 0.1  # the bottom of the subplots of the figure
top = 0.9     # the top of the subplots of the figure
wspace = 0.2  # the amount of width reserved for space between subplots,
              # expressed as a fraction of the average axis width
hspace = 0.2  # the amount of height reserved for space between subplots,
              # expressed as a fraction of the average axis height
```

指定する場所を図示すると以下のようになります.
![プレゼンテーション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118901/b5751bb2-c6f8-27ec-11ad-f538892d0664.png)

ちなみにこれらの値は`matplotlib.pyplot.show()`で表示されるGUIから[^2]
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118901/7015db55-c0fc-19e2-9348-25746257ad3d.png)
を押すと以下のようにinteractiveに調節できます.
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118901/110d46bf-b95c-f6db-a006-506d8317f27b.png)

もう1つちなみに`rcParams`の設定を触って変更することも可能です

```python:
matplotlib.pyplot.rcParams["figure.subplot.left"] = 0.125
matplotlib.pyplot.rcParams["figure.subplot.right"] = 0.9
matplotlib.pyplot.rcParams["figure.subplot.bottom"] = 0.1
matplotlib.pyplot.rcParams["figure.subplot.top"] =  0.9
matplotlib.pyplot.rcParams["figure.subplot.wspace"] = 0.2
matplotlib.pyplot.rcParams["figure.subplot.hspace"] = 0.2
```

# ハマったこと
大したことではないのですが, `wspace`と`hspace`の値の意味が他のparameterとは違ったという話です.
`left`, `right`, `bottom`, `top`は左下から測った全体の図の大きさの割合0~1で指定するのですが`wspace`と`hspace`はそうではなかったことでハマりました.

[公式document][spa]をさっさと見ていればよかったのですが

```python:
wspace = 0.2  # the amount of width reserved for space between subplots,
              # expressed as a fraction of the average axis width
hspace = 0.2  # the amount of height reserved for space between subplots,
              # expressed as a fraction of the average axis height
```

の

```python:
# expressed as a fraction of the average axis width
```

の部分です.

つまりgraphの横(縦)幅の平均値(普通は全部同じなので単にgraphの横(縦)幅)の`w(h)space`倍間隔を空けますよという意味になります[^1].
[^1]: ちなみに$n$個の同じ幅のgraphを横に並べた場合の1つのgraphが占める割合$f_w$は, graphの間隔は$n-1$個なので`right`-`left`が$f_w\times n+f_w\times$`wspace`$\times(n-1)$に等しいことより$f_w=($`right`-`left`$)/( n+$`wspace`$\times (n-1))$となります. 縦方向も同様です.
[^2]: これはWindows環境です. Mac環境だとボタンは下側に出るようです.
Apacheの特徴

# Apacheの特徴
- OSS：無償で利用可能
- モジュール機能が方法
 - 必要なモジュールだけを選択し、組み込むことが可能
 - モジュールとは、ある機能を実現するためのソフトウェア。プログラム本体に組み込んだり、交換したりが可能な小さなプログラムのかたまり。
- 多彩なプラットフォームに対応：UNIX系、MAC OS、Windowsで利用可能
- 信頼性が高い
 - ざっくりいうと歴史が古く（1995年初リリース）、OSSなのでバグが常に回収されてきた。

# 記事を書いた理由：メモ
- Apache、Nginxなど様々なWebサーバ用OSSがある。
- Apacheについての特徴を簡潔に記録しておきたかったのが理由です。

# 参考
- 本：サーバ構築の実際が分かる Apache[実践]　運用/管理
Day2 新規登録ページ作成

Day2はUserモデル中心に開発した。
#Userテーブルの身長・体重カラムに適切なデータ型
身長や体重は必ずしも整数ではなく、小数もありうるため適切なデータ型を選ばなければならない。
小数を扱うことができるデータ型はfloatとdecimalであるが、前者は扱うことができる桁数が限られている上、桁数がオーバーすると自動で四捨五入するようになっているため、お金などには向かない。一方、後者は正確な計算ができるがその分処理に時間がかかるといったデメリットがある。
それを考慮すると、制作する健康アプリはBMI等の計算が予想されるがそこまでの正確性は要求されないことからfloat型をチョイスした。
#Rails routesで確認することができるルーティング
<img width="760" alt="スクリーンショット 2020-01-11 20.34.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/3946113a-e284-a49d-158d-3d5c502bac76.png">
ルーティングファイルで、resources :モデルとすることで多くのルーティングとそれに対応するアクションをRailsは用意してくれるが、このコマンドで確認することができる。
#Bootstrapを使ったレスポンシブ化
bootstrapでは、簡単にレスポンシブデザインを整えることができる。
<img width="695" alt="スクリーンショット 2020-01-12 1.27.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/25cd8ce3-faac-8907-891a-48aa4d609d4d.png">
bootstrapは、画面を１２分割するグリッドシステムを基本的な考え方としている。例えば下の画像では、col-sm-4というクラスを設定することによりその要素が、sm（Small ／ 画面幅 小（544px以上 768px未満）のデバイスから表示されていれば１２分割されたうちの４つを使って表示するなどと、クラスを指定するだけでできるようになっている。
<img width="1175" alt="スクリーンショット 2020-01-11 19.36.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/340aebde-c1b8-652d-a70d-28ba956df1c3.png">
#Flash[:success]
RailsTutorialでは、コントローラでこれを書いておけば表示されていたが、railsのバージョンが違うから？、遷移先のビューでも<%=flash[:success]%>と書いておかなければ表示されない。
#Errorメッセージ（モデルが自動生成する方）の日本語化
以下のページを参照。
https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b

#課題
エラーメッセージの工程に入ってから、見た目が崩れたりしているのでそれは早急に直したい。また目先の問題を解決しても俯瞰的に見ないとその解決策が将来別の問題を引き起こしたりしてしまうと感じている。修正を行うときは先のことも考えて行いたい。
またCSSのデザインに時間をかけすぎてしまっているきがする。今はサーバサイドに集中して、すべてできてからCSSを一気に整えた方が全体の整合性も取れそうだし、先のことを考えずに行った修正による問題というのはでにくくなるのではないだろうか。
husky使用時にgit pushするとerror: failed to push some refs to ～

（追記）
下記の問題は[husky v4.0.7](https://github.com/typicode/husky/releases/tag/v4.0.7)で修正された様子。

---

Node.jsで開発中のリポジトリで、気付いたら`git push`ができなくなっていた。

```
$ git push origin master
stdin is not a tty
error: failed to push some refs to 'https://github.com/xxxxx/xxxxx.git'
```

gitのバージョンは以下の通り。

```
$ git --version
git version 2.24.1.windows.2
```

* エラーが起きたrepoで`commit`や`pull`→できる
* エラーが起きたrepoをgithubの新規リモートrepoに`push`→できない
* エラーが起きたrepoをbitbucketの新規リモートrepoに`push`→できない
* 空のrepoを新規作成してgithubの新規リモートrepoに`push`→できる
* 空のrepoを新規作成し、エラーが起きたrepoの`.git`フォルダ以外をすべてコピーして`push`→できる

以上の現象から`.git`フォルダ内の破損かと思ったが、エラーになるのが`push`だけというのが気になる。また、エラーメッセージもなんかスクリプトっぽい。そういえば、プロジェクトに[husky](https://github.com/typicode/husky)を追加していたことを思い出す。

```json:package.json（抜粋）
"husky": "^4.0.6"
```

`.git/hooks`を確認し、**`husky`によって追加された`pre-push`スクリプトを`pre-push.bak`にリネームして無効化**してみると、`push`できるようになった。

[huskyのreleaseページ](https://github.com/typicode/husky/releases)を確認すると、つい最近に破壊的変更を含むメジャーバージョンアップが行われたらしく、そこから毎日のようにバグ修正版がリリースされている（執筆時点）。まだあまり安定していないのかもしれない。

検索したら同じ問題のissueもすでにあったので、そのうち直ると思われる。
[[4.0.0 | Git Bash | Windows 10] stdin is not a tty](https://github.com/typicode/husky/issues/627)

自分は`pre-push`hookを使っていないし、とりあえず今は無効化しておくことにした。
`pre-push`を使いたい場合は`husky`の[バージョンを`3.1.0`系に下げればいいらしい](https://github.com/typicode/husky/issues/627#issuecomment-572435990)。
Pull Request を送る方法（Backlog版）

# はじめに
新しく会社に入社する人に向けた Git および Github の勉強会をすることになったので、重要なポイントを確認するために下記の本を読みました。
その時に話をしたいと思うことをいくつかまとめたいと思い投稿することにしました。

Github については本でもまとめられていたり、他の人がまとめられていたりするので、
"Pull Request の送る方法" の Backlog 版を書きました。参考にしていただけると嬉しいです。

* Github実践入門
    * https://www.amazon.co.jp/GitHub%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-Pull-Request%E3%81%AB%E3%82%88%E3%82%8B%E9%96%8B%E7%99%BA%E3%81%AE%E5%A4%89%E9%9D%A9-PRESS-plus/dp/477416366X

# Pull Request
## 概要
ソフトウェア自体のバグを見つけて修正したコードを管理者に教えてあげること。
Pull Request をソフトウェアの管理者が承認すると、そのソフトウェア自体に修正したコードが反映されます。

この仕組みを用いることでオープンソースとして開発が進められ、IT技術の進歩の早さはこの仕組みがあるからと言われています。

## 全体のフロー
Pull Request を送るまでの全体のフローを下にまとめました。
上から順に作業していくことで、Pull Request を送ることができます。

1. リモートブランチから自分の開発環境へ Clone
2. 自分の開発環境にてトピックブランチの作成 Branch
3. 作成したトピックブランチにてコードの修正
4. 修正した内容を Commit
5. リモートブランチの作成 & Push
6. __Pull Request を送る__


## リモートブランチから自分の開発環境へ Clone
自分のリポジトリのリモートブランチから自分の開発環境へ Clone します。

```
$ git clone ${修正を加えたいコードのリポジトリリンク}
```

## 自分の開発環境にてトピックブランチの作成 Branch
自分の開発環境にてトピックブランチの作成（Branch）します。

* トピックブランチとは
    * 1つのトピック（テーマ・機能）のコーディングをするためのブランチ（複数のテーマについては扱わない）

```
// ブランチを確認（-aオプションをつけることでリモートリポジトリのブランチも確認できる。）
$ git branch -a

// ${作成するブランチ名} を master ブランチを元としてコピーし、${作成するブランチ名}へ作業ブランチを移行する。
// master はローカルリポジトリのブランチ名
$ git checkout -b ${作成するブランチ名} master

// ブランチを確認（-aオプションをつけることでリモートリポジトリのブランチも確認できる。）
$ git branch -a
```

## 作成したトピックブランチにてコードの修正
作成したトピックブランチにてコードの修正します。
ここは修正内容によって異なるかと思うので、各自修正を加えてください。


## 修正した内容を Commit
修正した内容を Commit します。

```
// 変更内容を確認
$ git diff

$ git add .
$ git commit -m "Add Function"
```

## リモートブランチの作成 & Push
リモートブランチを作成し、そのリモートブランチへ Push します。

```
$ git push origin ${作成するリモートブランチ名}
```

## Pull Request を送る（Backlog版）
上記の準備が終わったらようやく Pull Request を送ることができます。
慣れたら大変な作業ではないので、覚えるまでは根気よくやってください。

リモートブランチの作成 & Push の時の ${作成するリモートブランチ名} をここでは __work__ とします。

画像付きで説明します。

Backlog の Git の画面を開いて、ブランチタブを開くと、push したブランチが追加されていることが確認できます。 
次に、表の__work__の行のプルリクエストの追加ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/7536b5b6-b1b8-f311-07ce-e07486aecf01.png)


プルリクエストタブに①のマークがつきますので、プルリクエストラブをクリックします。

すると、先ほど追加した__work__ブランチがプルリクエストとして追加されていることがわかります。
PullRequest を送る方法（Backlog版）としては以上になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308256/757035d1-9b5f-1d53-6224-0ce08f322de1.png)


# まとめ
Backlog 版として記事をまとめましたが、Pull Requestを送る全体的なフローに変わりはありません。
Github と Backlog で UI に差があることから少し操作方法に差があるだけですが、この記事をみて誰かの役に立てば嬉しく思います。

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
RustでWebassemblyのHello World!をやってみた

RustでWebassemblyのHello World!を参考に書いてる通りに実行して言っただけの投稿です。
初心者です。よろしくお願いいたします。 :bow: 

参考
https://rustwasm.github.io/book/game-of-life/hello-world.html

# プロジェクトのテンプレートを作成

```bash
cargo generate --git https://github.com/rustwasm/wasm-pack-template
#※プロジェクト名を聞かれるので `wasm-game-of-life` と設定
cd wasm-game-of-life #プロジェクトのディレクトリに移動
```

# `.wasm` ファイルにコンパイルする

```
wasm-pack build
```

`pkg`フォルダができて、↓の内容となっていました

```console
$ ls ./pkg
README.md                       wasm_game_of_life.d.ts          wasm_game_of_life_bg.d.ts
package.json                    wasm_game_of_life.js            wasm_game_of_life_bg.wasm
```

# wasmを読み込むためにwebページを用意する

```bash
npm init wasm-app www
```

`www`フォルダができるので、そこにある`package.json`に`./pkg`フォルダを含める

```www/package.json
{
  // ...
  "devDependencies": {
    "wasm-game-of-life": "file:../pkg", // 追加
    // ...
  }
}
```

`index.js` での読込先を変更する

```diff:www/index.js
- import * as wasm from "hello-wasm-pack";
+ import * as wasm from "wasm-game-of-life";

  wasm.greet();
```

依存関係をインストールする

```bash
cd www
npm i
```

サーバー起動

```bash
npm start
```

http://localhost:8080/ を開いて、wasmが実行できていることを確認できました

<img width="631" alt="Screen Shot 2020-01-12 at 0.48.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/80cb00a7-1912-562a-0b3d-c9ba0c88a36f.png">

### 引数を渡すようにする

`lib.rs`のgreetに引数を渡すようにする

```rust:src/lib.rs
#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}
```

変更したので、`wasm-game-of-life/` フォルダで再度`wasm-pack build`を実行

greetに引数を渡すように変更し、再度`npm start`ととすると、変更が反映されました

```www/index.js
import * as wasm from "wasm-game-of-life";

wasm.greet("hanako");
```

<img width="631" alt="Screen Shot 2020-01-12 at 1.07.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/416508d9-9013-d346-2eeb-ebcad6854455.png">

引数を渡せるように変更できました。

見ていただいてありがとうございました。m(_ _)m
Javascript Regular Expression Memo

# javascript regular express flag table

| Flag | Description |
|:--|:--|
| g | Global search. |
| i | Case-insensitive search. |
| m | Multi-line search. |
| s | Allows . to match newline characters. (Added in ES2018, not yet supported in Firefox). |
| u | "unicode"; treat a pattern as a sequence of unicode code points. |
| y | Perform a "sticky" search that matches starting at the current position in the target string. |


# Sticky Flag
Bellow is sticky. Regexp holds lastIndex, and when reads strings, `lastIndex` is added. When test failed, `lastIndex` is set to 0.

```javascript
const str1 = 'table football';
const regex1 = new RegExp('foo','y');

regex1.lastIndex = 6;

console.log(regex1.test(str1));
// expected output: true
console.log(regex1.lastIndex);
// expected output: 9
regex1.test("table foofoo");
// expected true;
console.log(regex1.lastIndex)
// expected output: 12
regex1.test("table foofoo");
// expected false;
console.log(regex1.lastIndex)
// expected output: 0
```

# $& means matched string
```javascript
"01234".replace(/[0-9]/g, 'v$&')
// expected output: "v0v1v2v3v4"
```
# Back slash `\` before normal character in string has no meaning
"\a" means "a"
"\t" means "\t"(tab)

# Escaped Regexp Function
```javascript
function escapeRe(value) {
  return new RegExp(value.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'm');
}
```

# Special Characters
## normal context
`-\/^$*+?.()|[]{}`
## In [] context. 
`-\/]`
source code reading of highlight.js

# Check Execution Context.
JavaScript could be run on node._js, browser or WebWorker.
On browser, `typeof window === "object"` equals true.On webworker, `typeof self === "object"` equals true.

```javascript
var globalObject = typeof window === "object" && window || typeof self === "object" && self
```

Bellow line checks is node.js environment
In node.js environment, exports is equals `{}`.  

```
if(typeof exports !== 'undefined' && !exports.nodeType) {
}
```
Below code is setting global object. `factory` is a function to set `hljs` properties. 

```javascript
function(factory) {
 
  // Find the global object for export to both the browser and web workers.
  var globalObject = typeof window === 'object' && window ||
                     typeof self === 'object' && self;

  // Setup highlight.js for different environments. First is Node.js or
  // CommonJS.
  // `nodeType` is checked to ensure that `exports` is not a HTML element.
  if(typeof exports !== 'undefined' && !exports.nodeType) {
    factory(exports);
  } else if(globalObject) {
    // Export hljs globally even when using AMD for cases when this script
    // is loaded with others that may still expect a global hljs.
    globalObject.hljs = factory({});

    // Finally register the global hljs with AMD.
    if(typeof define === 'function' && define.amd) {
      define([], function() {
        return globalObject.hljs;
      });
    }
  }

}
```
summary of above code is following.

```javascript
exports = factory({}) // If Node.js
window.hljs = factory({})  // If browser
self.hljs = factor({})    // If webworker
```

# Create hljs object
VirtualBox上にゲストをOSインストールしようとすると、インストーラーが動かなかったり、kernel panicしたりする。

# 事象
VirtualBox上でCentOS7、をインストールしようとすると、下記の事象が発生し、
インストールができない。

- EFI無効時
kernel panic

- EFI有効時
ISOは読み込めるが、インストーラやRescueを起動しようとすると、
black screen（黒い画面）から進まない。

# 環境
- Windows 10 ホスト
- VirtualBox 6.0.14、6.1.0
- CentOS7

後述の公式フォーラムを見る限り、VirtualBox側が原因の可能性が高く、
VirtualBox 6.0.6 **より後のバージョン**は、同一と思われる事象が発生するようです。
2020年1月11日時点、最新の6.1.0で、今回の事象が発生することを確認しています。

# 回避方法
- VirtualBox 6.0.6を使う。
- CentOS 8を使う。
- 古いkernelを使う？

古いVirtualBoxを使うか、新しいOSを使うかで回避できることを確認しています。
また、私は検証していませんが、kernelのバージョンを下げると回避できるとの記事が
Qiitaにありましたので、下記にリンクさせていただきます。

# 参考
- 公式フォーラム
[kernel panic not syncing fatal exception when trying to start CentOS 7](https://forums.virtualbox.org/viewtopic.php?f=3&t=93990)

- Qiita
[CentOS7の最新版をVirtualBoxにインストールするときにKernel panicを起こしちゃう人が読むページ](https://qiita.com/thisprogrammer/items/fd0844d5d46349d4aa84)

# 2020/02/29 追記
@hrhg 様よりコメントいただきましたが、VirtualBox6.1.2以降でfixされているようです。


- hrhg memo **（2020/02/29追記）**  
[ホストOSのCPU/VirtualBox/CentOS7のKernelの相性について](http://hrhg.hatenablog.com/entry/2020/02/28/053146)
【２】Nuxt.jsのサンプルアプリをPWAとしてFirebaseにホスティングする

## はじめに

PWA（Progressive Web Application）として再デプロイしてみて、実際に自分のスマホにインストールしてみます。

## 手順

### マニフェストファイルの作成

PWAにはmanifest.jsonが必要だが、nuxt.jsでは@nuxtjs/pwaさえ入っていればとてもシンプル。
前記事でやったようにnuxt.config.jsを編集する。

```diff
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/pwa',
    // Doc: https://github.com/nuxt-community/dotenv-module
    '@nuxtjs/dotenv'
  ],
+  pwa: {
+    manifest: {
+      name: 'すずめも', // アプリの名前
+      lang: 'fa'
+    }
+  },
```

もしアイコンを変えたい場合は、 `static/icon.png` を編集すればOK。

その他に必要なことは、下から勉強する必要がありそうです。
https://pwa.nuxtjs.org/modules/meta.html#applestatusbarstyle

これで `npm run deploy` でデプロイしなおすと、

![Screenshot_20200112-004448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144277/7789c6fc-e6f8-0743-7cd2-4becba167827.png)

いい感じ！

## ここまで

https://github.com/koboriakira/sparrow-memo/tree/ver1.2

## 【悩み中】iOS用に調整する

distに出力されたindex.htmlの `head` 属性に下記のjsファイルを入れれば動くと思ったのだけれど、いまは失敗している。

```diff
+ <script async src="https://cdn.jsdelivr.net/npm/pwacompat@2.0.9/pwacompat.min.js"
+          integrity="sha384-VcI6S+HIsE80FVM1jgbd6WDFhzKYA0PecD/LcIyMQpT4fMJdijBh0I7Iblaacawc"
+          crossorigin="anonymous"></script>
</head>
```

あとでこれをやってみる予定。
https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/?hl=ja#ios%E3%81%AEmeta%E3%82%BF%E3%82%B0%E3%81%A8%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0

```
<!-- CODELAB: Add iOS meta tags and icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Weather PWA">
<link rel="apple-touch-icon" href="/images/icons/icon-152x152.png">
```
node 10 -> 12 にバージョンアップしたら、npm installでnode-sass@4.11.0がエラーになる

## Unsupported for `node-sass@4.11.0`

2019年10月に、node v12はついにLTSになりました:clap::clap::clap:

それで、既存のシステムのnodeをバージョンアップしてみたところ、↓のようなエラーになりました！

```sh
    Cannot download "https://github.com/sass/node-sass/releases/download/v4.11.0/linux_musl-x64-72_binding.node":

    HTTP error 404 Not Found

    Hint: If github.com is not accessible in your location
          try setting a proxy via HTTP_PROXY, e.g.

          export HTTP_PROXY=http://example.com:1234

    or configure npm proxy via

          npm config set proxy http://example.com:8080
```

v12はサポートしなくなったらしいので、`node-sass@4.12.0`にアップデートする必要があるようです。

`npm install node-sass@4.12.0`

これでエラーが消えます。

## node v12 はどこが新しくなったのか

* JavaScriptエンジンであるV8はNode.js v10の`v6.8`からv12の`v7.4`にバージョンアップした、そのためパフォーマンスが大きく変わりました
    * Asyncスタックトレース
    * JavaScriptパース高速化
    * Await高速化
    * 引数ミスマッチ高速化
    

* ClassにPrivateFieldsを定義できる
`#`でプライベートフィールドを定義する。（例：`#name`）
この`#name`はClass内にしか使えない。

* HTTP parserはllhttpに変わりました

* [TLS1.3](https://www.ssl.com/blogs/need-know-tls-1-3/)もサポートするようになった
chrome拡張 vimiumをカスタマイズしてみよう

#### vimiumを自己流にアレンジする方法を説明する
### 動機
友人から教えてもらい現在まで俺的chrome拡張ランキング1位に君臨しているため，共有したかった
(**お前のランキング覆すchrome拡張あるぜ!!って人はコメントで是非お教えください**)


## Vimiumとは??
ChromeをVimコマンドで扱えるようにするChrome拡張
![トラックパッド.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/6abc2761-2cf1-a7f4-0b9a-82bd0a31cb95.jpeg)
~~上記のようなトラックパッドを二度と触らなくて良くなる~~
上記のようなトラックパッドをできるだけ触らなくて良くなる
### Vimiumを使うメリット
- web surfingが超高速化する
- vimに慣れていない人はvimに慣れることができる
- vimに慣れている人はchrome上でもvimライクに操作ができる
- ~~女の子にモテる!!~~

### Vimiumのchrome拡張を追加する方法
chromeウェブストアから追加する．(左上の"拡張機能を検索"の部分にvimiumと入力してください)
<img width="1440" alt="スクリーンショット 2020-01-11 19.23.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/6f13bf41-cb4c-7207-b974-37b3cfc1646c.png">

## 本題(Vimiumのコマンドを自分流に変更する方法)
1．chrome右上にあるvimiumアイコンをクリック
<img width="231" alt="スクリーンショット 2020-01-11 19.35.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/bb98a0bc-8898-2305-9524-ba586345d0fb.png">
2．Optionsってとこをクリック
<img width="465" alt="スクリーンショット 2020-01-11 19.37.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/994053ec-bb14-3dda-ba22-b81eb496008f.png">
3．はいここでカスタマイズ設定をします
英語拒絶反応が出るので日本語で説明を付け加えておきましょう．
<img width="1015" alt="スクリーンショット 2020-01-12 00.14.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/2bc6cdb9-db02-b024-57e5-86fa3a3313ee.png">

### map key 機能の機能の部分には<font color="Blue">show available commands</font>をクリックした後にでる以下の画面の()内の英語を打ち込もう!!
<img width="833" alt="スクリーンショット 2020-01-11 20.29.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/2e07d70c-a6c3-1ab9-cc9a-137a10113a1f.png">

## 俺流カスタマイズ
<img width="810" alt="スクリーンショット 2020-01-29 01.15.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/272f0b62-5b2a-e607-40ed-1a1240f7ad10.png">



### Custom key mappingsの設定(以下をコピべすると上記の設定に変更される)

unmap h
unmap H
unmap l
unmap L
unmap gt
unmap gT
unmap F
unmap N
unmap J
unmap K
unmap gf
unmap g0
unmap g$
unmap x
unmap X
unmap n
unmap d
unmap m
map n scrollPageDown
map . performFind
map , performBackwardsFind
map h goBack
map l goForward
map sh previousTab
map sl nextTab
map c LinkHints.activateModeToOpenInNewTab
map gf firstTab
map ge lastTab
map q removeTab
map re restoreTab
### Custom search enginesの設定変更
a: http://www.amazon.co.jp/s/?field-keywords=%s Amazon
g: https://www.google.com/search?q=%s Google
y: https://www.youtube.com/results?search_query=%s Youtube
q: https://qiita.com/search?q=%s Qiita
t: https://twitter.com/search?q=%s Twitter
gm: https://www.google.com/maps?q=%s Google maps
gt: https://translate.google.com/#en/ja/%s Google translate
gp: http://www.google.co.jp/search?hl=ja&source=hp&q=%s&tbm=isch Google image


## 参考文献

[知識0から始めるVim講座](https://qiita.com/JpnLavender/items/fabcc79b4ab0d52e1f6d)
[Chromeをvimライクに使えるようにするvimium](https://qiita.com/satoshi03/items/9fdfcd0e46e095ec68c1)
[custom search enginesについてわからない人はこの記事読むべし](https://qiita.com/evistream/items/70ad2916b01dee33ad52)
libssl.1.0.0.dylibがないことでエラーになった時の対処法 dyld: lazy symbol binding failed: Symbol not found: _SSL_library_init


Railsを久しぶりに起動しようとしたらなんかエラーが起きていた。

```
masashi-no-mbp:MarimoKing pcuser$ rails s
dyld: lazy symbol binding failed: Symbol not found: _SSL_library_init
  Referenced from: /Users/pcuser/.rbenv/versions/2.6.0/lib/ruby/2.6.0/x86_64-darwin18/openssl.bundle
  Expected in: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib
```

結果としては、rbenvで入れていたRubyのリンクの設定が原因でダメだったみたい。

## 対処法

Rubyを入れ直すことで解消した。

`$ rbenv uninstall 2.6.0 && rbenv install 2.6.0`


## 参考リンク

[[MEMO] gem コマンドで Library not loaded: /usr/local/opt/openssl/lib/libssl.1.0.0.dylib が出たときの対処法](https://qiita.com/suzukalight/items/1fd68258c4134ad7fc48)
Unity開発用マシンを調達した話

# はじめに
2019年の暮れ、思い切ってUnity開発用マシンを調達することにした。
これに至るまでに色々と調べたことをナレッジとして残す。

スペック選定がどのくらいの負荷に耐えられるのか算出しづらかったので
今後のために残した感じ。


# 最終的に購入したPC
マウスコンピュータ DAIV 5N(カスタマイズ)

## 金額
約22万円。

## 他に購入候補にしたPC

- Dell ALIANWARE
- MSI
- ASUS


## スペック

||||
|:-:|:-:|:-:|
|端末サイズ|15.6型||
|OS|Windows 10 Pro||
|CPU|Intel Core i7-9750H 2.60GHz||
|RAM|16GB (C4-19200/DDR4-2400)||
|CD/DVD-ROMドライブ|なし||
|カードリーダ|UHS-Ⅱ対応(SD/SDHC/SDXC/MMC)|
|Storage|1TB(NVM Express SSD - M.2.PCI Express)||
|Graphics| NIDIA GeForce RTX2060 (6Gb)||
|スピーカー|カスタマイズ(追加)なし||
|LAN| 1000Base-T||
|無線LAN|wifi6対応||
|画面解像度|フルHD(1920 x 1080)||
|Officeソフトウェア|なし||
|グラフィックボード|NVIDIA Geforce RTX2060||
|HDMIポート|HDMI 2.0||


## ストレージ選定について
CPUの処理能力が向上したからなのか、ソフトウェアRAIDを採用しているPCが多かった。
この辺は好みになるかもしれないが、ディスク制御負荷をCPU負荷に加算したくなかった為、ソフトウェアRAIDタイプのモデルを採用しているメーカーは選定しなかった。また、M2 SSDならアクセス速度もそれなりに早いといううわさがあるのでソフトウェアRADは不要と判断。

### ソフトウェアRAID
RAIDコントローラ(デバイス)を用いず、OSやアプリケーションでRAID制御するものを指す。専用のドライバーを使ってRAID制御しているものはハードウェアRAIDという。一般向けPCにハードウェアRAIDを採用したものは存在しない。


# 選定理由
スペック選定に至った理由をつらつらと書いてみる。

## 画面サイズ選定について
当面は4K描画が必要な開発をするつもりがない為、フルHDタイプを選択。

## 端末サイズ選定について
デモンストレーションマシンとして持ち運びたいため、15.6型を選択。
17型も検討したがデカい/重いを懸念し、お見送り。

## グラフィックボード選定について
下記要件から1070Ti相当のスペックを提供するモデルとしてRTX2060を選定。

- 2Dゲーム描画が快適に行える
- 画面描画はFullHD ~ WQHDに適している

## CPU選定について
1920 x 1080 をイメージしていた為、CPUはそんなに描画負荷のかからないものを選定。

## メモリ選定について
8GBでもよかったんじゃないかなーと思っているが、開発環境として使う為、16GBを選定。

## Officeソフトウェアについて
半分眠っているような状態のライセンスがあるため、今回は購入せず。
Unityでのメモリ管理

# UnityとGC
Tech Academyのメンターさんからメモリ管理を気にして実装できたら中堅という風に言われた(やりたい処理を実装できるのは当たり前で)。
C＃では基本的にガベージコレクション(GC)というやつがいらなくなったメモリをいい感じに解放しているらしい。
しかし、**[Unityでシーン再生中にGCが発生すると数フレーム飛ぶため、アクションゲームではシーン再生中にGCを発生させないようにしないといけない](https://www.slideshare.net/KMC_JP/c-91154309)**らしい。

# GCを発生させる条件とアクションゲームのリアルタイム性を損なわない対策
上のリンク先の記事によると、主なGC発生条件は「メモリが許容されるしきい値を超える場合」であり、これを防げばよいみたい。
で、極論対策としてはそのシーンを開始時にすべてのメモリ領域の確保を終わらせることみたい。
いや、無理じゃね。

実用に耐えうる手段また調べよう・・・


# メモリ利用状況の確認
メンターさんに聞いた話しだととりあえずProfilerというやつでやるらしい。
ただ、具体的にどの部分でめっちゃメモリ食ってるとかはわかんないので、
Profilerで確認しながら実装していかないとまずいらしい。
一通り実装し終わったからさぁメモリの負荷みますか、だと詰むらしい。
メモリの限界値としては、経験上システムメモリの半分くらいに押さえておいた方がよいらしい。iPhoneだと800MBくらいが目安か、というところ。
Microsoft Azure資格 (AZ-301) を取得するまでにやったお勉強のお話

# はじめに
Microsoft Azure の資格の一つである AZ-301 を取得したので、
勉強した内容&所感についてメモします
（試験内容には触れていません)

Microsoft 資格: Azure Solutions Architect Exprt の必須要件の一つとなる資格です

AZ-300についてはこちらの記事を参照いただければと思います
(https://qiita.com/spinrock/items/01f06f7888bcf46e41ef)

# AZ-301について
https://www.microsoft.com/ja-jp/learning/exam-az-301.aspx
こちらを参照のこと

# 筆者の事前知識
普段はオンプレのサーバ~ミドルウェア領域あたりを担当してます
Azure/AWSは個人的にも興味があり、趣味レベルでクラウドサービスを使ってます
- Azure含め、パブリッククラウド上の構築経験はありません
- Azure ポータルは毎度の資格勉強時に触っているレベルです

# やったこと
- Microsoft Learn
普段利用していない部分(私の場合はPaaS周り)をラーニングパス単位でお勉強しました
(非常に膨大な量があるため、全部はやりきることを最初の目標にするのは厳しいと思います)
以降は、問題集を解いた際に理解が不足していると感じた項目を抜粋して確認しました

- Web問題集(Udemy)
私が利用した講座は、「AZ-301 : Microsoft Azure Architect Design : Practice Tests」というものでした
(https://www.udemy.com/course/az-301-microsoft-azure-architect-design-practice-tests-w/)
不明点はMicrosoft ドキュメントを読んだりして解消しました


# 試験が終わった後の個人的な所感
- 私がAZ-300を受験してから試験体系が変わった(?)ようで、時間的には余裕がありました  
(蓋を開けたらかなりギリギリの点数だったので、できれば問題集(上記以外でも)の内容は理解できるようにしておくことをお勧めします)
adbコマンド

Androidアプリを開発するにあたって、
よく使うADBコマンドからたまにしか使わないけど毎回調べてしまうものまとめました。

アプリ（APK）のインストール
-
デバイスに未インストール

```
adb install 
```

インストール済み（上書きインストール）

```
adb install -r 
```

インストール済み（ダウングレード）

```
adb install -d
```

接続済み端末の確認
-
```
adb devices
```

端末指定
-
```
adb -s <device id> * 
```
device idは接続済み端末の確認のコマンドにて取得
*はinstall, uninstallなど指定した端末に対して行いたいコマンド

ファイルの転送
-

```
adb push <転送するファイル名> <転送先のパス>
```

ファイルの取得
-
```
adb pull <取得元のパス>
```


AlarmManagerの設定時刻
-
[【Android】adbを使ってAlarmManagerの実行予定時間を確認する](https://www.takasay.com/entry/2017/06/23/182928)

```
adb shell dumpsys alarm | find "<package name>"
```
ログ取得
-
```
adb logcat 
```

ログクリア
-
```
adb logcat -c
```

ログファイルを取得
-
```
adb logcat > hoge.txt
```

ADBのバージョン
-
```
adb version
```

アプリアンインストール
-
```
adb uninstall
```

文字入力
-

```
adb shell input text <入力したい文字列>
```

インストール済みパッケージリスト
-
[よく使うadbのコマンド](https://qiita.com/t2low/items/cb37cec5f864c4748e14)

```
adb shell pm list packages
```


参考文献
=

[【Android】adbを使ってAlarmManagerの実行予定時間を確認する](https://www.takasay.com/entry/2017/06/23/182928)
[よく使うadbのコマンド](https://qiita.com/t2low/items/cb37cec5f864c4748e14)
Dockerで簡単にRedis試す

##1, フォルダ作成

```
mkdir redis
cd redis
```

##2, docker-compose.ymlファイル作成

```yaml:docker-compose.yml
version: '3'
services:
  redis:
    image: "redis:latest"
    container_name: redis_test #下記のコマンド時に使用するコンテナ名
    ports:
      - "6379:6379" #redisのデフォルトのポートは6379
    volumes:
      - "./data/redis:/data"
```

##3, 上記で作ったymlファイルがある階層で、下記を実行

```terminal
$ docker-compose up -d
Creating network "redis_default" with the default driver
Creating redis_test ... done

$ docker exec -it redis_test /bin/bash

# Redisクライアントの起動
root@9e25d6b48e8c:/data# redis-cli

# 現在のkey全部の確認
127.0.0.1:6379> keys *
(empty list or set)
```

##4, 文字列型の操作
[コマンドリファレンス](http://redis.shibu.jp/commandreference/)が分かりやすいです。

```terminal
# 文字列 valueにkeyをセットする
127.0.0.1:6379> set name hoge
OK

# 指定したkeyに対応するvalueを表示
127.0.0.1:6379> get name
"hoge"
```

```
# keyに有効期限(秒数)を付けることができる(成功時は1, 失敗時は0を返す)
127.0.0.1:6379> expire name 3
(integer) 1

# ３秒後に、nameキーの値がnilになる
127.0.0.1:6379> get name
(nil)
```

```terminal
# valueを１増やしたり、１減らしたりする
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> incr age
(integer) 21
127.0.0.1:6379> decr age
(integer) 20
```

```terminal
# keyの削除
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> keys *
(empty list or set)
```

##参考にさせて頂いた記事
[docker-composeでredis環境をつくる](https://qiita.com/uggds/items/5e4f8fee180d77c06ee1)