OmniAICreator/Qiita-1.07M huggingface dataset:
特定のwindowサイズ変更時にJavaScriptでcssのクラス名を切り替える方法

こんにちは、Shota(@Mii4a_2501)です！
BootstrapやMaterialize等のフレームワークを用いてフロントエンドの記述をしていく際、
**col-s-4(Bootstrap)**あるいは**col s9(Materialize)**などといったグリッドシステムを活用することがあると思います。

自分は現在Materializeを用いてアプリ作成をしており、windowサイズのwidthが小さくなった際、サイドバー(class="s3")を表示しないようにしているのですが.....

追記 jQueryのコードを改善しました。

<h2>問題点</h2>

![コメント 2020-03-13 142204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440707/2b4d5f06-686b-7379-6d71-ada1ec1d50f7.png)


↑（画面幅全体です。）

この写真のように、サイドバー(class="s3")が表示されなくなったことで残りのグリッドシステム適用内の要素(class="s9")が左側に詰められてしまいました。これは見た目上あまり気持ちが良いとは言えませんね....。（そもそも設計の問題かもしれませんが....）

また、HTML内で記述したclass名に紐づけられたプロパティを読み込んでいるため、cssで変更を試みようにも改善は厳しそうです。そこで、JavaScriptあるいはjQueryを用いてclass名を切り替えることでこの問題に対応しようと思います。

<h2>改善方法</h2>

```javascript:Javascript
window.addEventListener('resize', function(){
    const smWindowSize = 600; //cssを切り替えるときの画面幅
    const target = document.getElementById('hoge'); //変更する対象 
    if (window.innerWidth >= smWindowSize){ //画面幅が600px以下の場合
      target[1].className = "s12" //クラス名変更 "col s9" => "col s12"
    } else {
      //window幅が600pxよりも大きい時
      target[1].className = "s9"
})
```
このようにwindowに対してaddEventListenerメソッドを用い、**resize**イベントで画面幅の変更を監視しています。
なぜelse文でwindow幅が600pxよりも上の場合を記述しているのかというと、幅600px以下から600pxよりも大きい画面幅に戻した際、class名がs12のままになってしまうからです。


jQueryでは次のように書けそうです。
こちらの方が変更の際の把握はしやすいかも？

```javascript:jQuery
   $(window).on("resize", function(){
     const smWindowSize = 600;
     if (window.innerWidth <=  smWindowSize){
       $("#hoge").removeClass("s9").addClass("s12");
     }　else {
      $("#hoge").removeClass("s12").addClass("s9");
    }
   });
```

こうすると....?

<h2></h2>

![コメント 2020-03-13 150350.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440707/65f599b9-b5f3-f8ad-db36-c2c94d5fe9bc.png)

はい！クラス名を切り替えたことで見た目も思い通りになりましたね！
(開発途中なので編集と削除の部分はお許しを.....）

正直なところ、もっといい手があるのではないかなと感じているのですが
誰かの助けになったら幸いです！ご覧いただきありがとうございました！
仮想マシンの複製

【仮想マシンの複製】
個々の仮想マシンの環境設定やハードディスクはファイルとして保存されます。それらのファイルをコピーすることで任意の仮想マシンをクローンとして複製できるため、テンプレートとして使用したり、同様の仕様のシステム展開が容易にできるようになります。ただし、同一の仮想化ソフトウェア上で複製した仮想マシンのUUID（Universally Unique Identifier: 汎用一意識別子、全世界で重複が起きないように生成される一意な値）が重複していると正常に動作しませんので、注意が必要です。
また、ホスト名やIPアドレス、SSH接続時に使用するSSHホスト鍵（公開鍵、秘密鍵）などサーバごとに一意でなければならないものも変更しなければなりません。

上記に加えて、systemdのマシンはホストを識別するための32bitのマシンIDを持っています。インストール時に、ランダムに生成されるUUIDがマシンIDとして設定されます。仮想マシンを複製するとマシンIDもコピーされるので、ネットワーク内で重複しないようにクローンのマシンIDを初期化する必要があります。

マシンIDは「/etc/machine-id」ファイルに格納されています。

# cat /etc/machine-id
d602b9b22ae94e7d871f403f2ab5eb46

なお、クラウド上のインスタンスはテンプレートから展開されるため、テンプレートから複製された環境を重複しないようにインスタンスごとに変更する必要があります。この作業をまとめて行う「cloud-init」というパッケージが用意されています。
cloud-initパッケージはクラウド上でなくても、インストールして使うことができます。

例：CentOSの場合
# yum install cloud-init
【Rails】pluralize

#pluralizeヘルパー
英語専用のテキストヘルパー。
最初の引数に整数があると、それに基づいて２番目の引数である英単語が複数形に変化したものが渡される。

##サンプルコード

```
>> pluralize(2, "woman")
=> "2 women"
>> pluralize(3, "erratum")
=> "3 errata"
```

##実施例

```rb
<%= pluralize(@user.errors.count, "error") %>
```
このコードだと"0 errors"、"1 error"、"2 errors"などのように、エラーの数によって活用される単語が変わってきます。"1 errors" のような英語の文法に合わない文字列を避けることができます
転職日記１２日

こんにちは、

今日はLeetCodeにてRubyの問題を解いていました。

アルゴリズム系の問題は個人的に大学でJavaをやっていたときに

嫌になって完全に逃げ出してしまった愚かな民なのですが、

この歳になっていざやってみると面白いものですね。

本当に、この時、この歳になってみて面白いと思うことが多くあります。

お金は日に日に減っていくのですが、お金に関する知識も多少ついたし、

そんなの当たり前だろと思うことも多いと思うのですが、まだまだ自分伸び代あるなと思うこともあります。

内定は１つもらっているのですが、そちらは辞退して、自分の考えている会社に全力でアタックしていきたいと思います。
シェルスクリプトを使ったサーバ資材のバックアップ(ファイルの世代管理付き)

# 概要

* サーバの特定の資材を毎日ローカルバックアップ(世代管理)をしていたので、そのシェルスクリプトを備忘録としてまとめます。
  * かなり今更感のある技術ですが、温故知新ということで

# 結論

* 作成したシェルスクリプトは以下になります。
  * ディレクトリなどは適宜環境に合わせて修正してください

```backup.sh
#!/bin/sh -u

# スクリプトの位置にカレントディレクトリを設定
cd `dirname $0`

# 処理開始時刻を取得
todaydatetime="date '+%Y-%m-%d %H:%M:%S'"
echo "バックアップファイル処理を実行します"
eval $todaydatetime

# 処理時間の計測開始
SECONDS=0

# バックアップ対象
TARGET_DIR='/home/origin'

# バックアップファイルを格納するディレクトリ
backupdirpath="/home/backup"

## ディレクトリの存在チェック
if [ -d ${backupdirpath} ]; then
    # バックアップディレクトリが存在している場合、
    # 格納されているファイル一覧を表示
    ls -lrth ${backupdirpath}
else
    echo "バックアップディレクトリがありません。処理を終了します。"
    eval $todaydatetime
    exit 1
fi

# バックアップファイル名を定義(※ファイル名で日付がわかるようにしておきます)
BACKUP_FILE_NAME=`date +%y%m%d`

# バックアップファイルの作成処理
tar czfp $BACKUP_FILE_NAME.tar.gz $TARGET_DIR
mv $BACKUP_FILE_NAME.tar.gz $BACKUP_DIR

# バックアップファイルをローカルのバックアップフォルダで世代管理
tgtfile="${backupdirpath}/backup_????-??-??.tar.gz"
chkage=$(ls -1 ${tgtfile}|wc -l)

# 保管世代数を設定
age="5"
## tailコマンドで6つ目以降を取り出して削除する処理のため、
## 変数に設定する値は、「保管世代数+1」で指定する
tailage="+6"

# 削除対象ファイルリスト
delfilelist=$(ls -1 -t ${tgtfile}|tail -n ${tailage})

## ファイル削除要否判定
if [[ ${chkage} -gt $age ]]; then
    # バックアップファイル数が保管世代数より多い場合、
    # 逆順ソートして、最新5世代を残して削除
    echo "フォルダに保管されている世代数：${chkage}"
    echo "保管世代数${age}を上回っているため、古いファイルを削除します"
    echo "削除対象ファイル：${delfilelist}"
    echo "古いバックアップを削除します"
    rm -f ${delfilelist}
else
    echo "不要なバックアップファイルはありません。処理を終了します。"
    eval $todaydatetime
    exit 1
fi

# 処理終了時刻を取得
echo "バックアップファイル処理を終了します"
eval $todaydatetime

# 処理時間の計測終了
echo "処理実行時間：${SECONDS}秒"

```

# おまけ(日々のバックアップログを作成するシェルスクリプト)
* こうした日々のバックアップログが欲しいと言われたときのメモ
  * 楽に見るならJenkinsとかジョブツールを構築するのがいいですが、そこまでのコストかけるほどでもない場合に
  * 上記で書いたバックアップシェルを呼び出す親シェルを作成します。  
(cronなどで仕込む場合はこちらを呼び出すようにしてください)

```top_backup.sh
#!/bin/sh -u

cd `dirname $0`

# バックアップスクリプトを制御する親スクリプト
sh ./backup.sh > logfile_`date "+%Y-%m-%d"`.log 2>&1

# 古いログファイルを削除
tgtfile="./logfile_????-??-??.log"
chkage=$(ls -1 ${tgtfile}|wc -l)
# 保管世代数を設定
age="5"
## tailコマンドで6つ目以降を取り出して削除する処理のため、
## 変数に設定する値は、「保管世代数+1」で指定する
tailage="+6"
# 削除対象ファイルリスト
delfilelist=$(ls -1 -t ${tgtfile}|tail -n ${tailage})

if [[ ${chkage} -gt $age ]]; then
    # バックアップファイル数が保管世代数より多い場合、
    # 逆順ソートして、最新5世代を残して削除
    echo "削除対象ファイル：${delfilelist}"
    echo "古いログファイルを削除"
    rm -f ${delfilelist}
else
    exit 1
fi

```
論点を一つずつ分解すると訳が分からなくなる「はず」。


# 電子機器

電子機器を分解された方がおみえになった。

![87654159_2670919649696732_4004093762614591488_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/44383cd6-c453-9cef-a20f-e5049130012f.jpeg)

この写真は寺久保敏さんのfacebookへの投稿を引用させていただいています。

電子機器で、分解はできても組み立てられない場合の記録。

組み立てられない要素を考える。

## 機構の構成図がない

一つはずすごとに、写真をとれば、機構の構成図、組み立て図、分解図は作成できるかもしれない。
写真を撮った順番は、最近の携帯電話、デジカメの機能で日時がわかる。

## 機構が破壊的にしか分解できない

ねじや、接着剤などの、再度構成可能な方法ではなく、
嵌め込み式で外すには破壊するしかない場合がある。

再組み立てのためには、交換部品が要るかもしれない。

配線などで、切るかはんだを剥がせば取れる。細かくて半田付けに技術が必要な場合がある。
外す作業ができる技術はあっても、短絡がないように半田付けする技術はない場合もある。

ねじのような、再利用可能な部品だけで構成されている場合も、１０個以上のねじどめにつき、１個余ることがある。
元に戻せていない。

摩擦を利用した可動部や、圧着により接点になっているような場合は機能しないことがある。

## 組み立てに道具が要る

特定の形状、特定の力を入れることができる道具がないと組み立てることができない場合がある。

複雑な形状の複数の部品を組み合わせるための道具を用いることがある。

Macintoshで、星形の螺子回しがいることがあった。買った。

## 組たてに特定の接合材料が要る。

接着剤などによっては、絶縁、通電の目的が違う可能性がある。

# Preparing for the HAZOP studies

http://ise.me.tut.ac.jp/lectures/safety/lectures/safety-week-3.pdf

p.8
>対象となる人工物を分割する

分解しても機能するような構造になっていることが前提。

化学プラントの場合に、個々の要素が独立して試験できるようになっている場合がある。

製鉄所のプラントでの高炉のような制御系では無理かも。

# 制御系

連立微分方程式による現代制御理論に基づく自動制御系では、部品ごとに分解できず、入力と出力を計算している途中経過が、物理的に何を表しているかがわからない。

そのため、式の一部を分解しても、その入出力の意味が不明で、全体でしか意味をなさない。

一見不可能なように見える模型でも、最初の入力と最後の出力は物理量である。

それらの物理量を、機械学習させ、入力の組みの変化が、出力の組みの変化に、よりよい状態を見つけ出すことができるかもしれない。

それぞれの学習過程での計算量は、物理的な意味を探し出すことができるかもしれないし、物理的な意味を探し出すことができないかもしれない。

論点を分解してもいいのは、線形性が成り立つこと、扱うのが物理的な意味がわかっているものであることが推測できる。

高炉ではなく、圧延工程は、次元数が少ないため、必ずしも現代制御理論を使う必要がないかもしれず、
機械学習で今よりよいパラメータを発見できたという報告を聞いたことがある。

これも、論点をひとつずつ、分解するのではなく、一気に全部計算して出した力技。
ただ、解が出たあとでは、関連する物理量に着目し、論点を分解できる可能性はある。
発見的な解が見つかったあとで、解をみつけるための方法ではないかも。

# 社会系

社会系は、生産量と価格のように、１年に限定したり、地域を限定すると、線形に遷移する場合がある。

あるいは、１００年間の合計したりすれば、１０００年間の推移は線形かもしれない。

社会に関する制約条件は、測定できるとは限らず、線形な関係は発見的にしかわからない場合がある。

論点を分解したら、大きな影響が消えてしまい、関係性が破壊されるかもしれない。

論点を分解しても線形性が保てるのは、特定の組織の１０年くらい変わらない制約条件を前提にしたりしているだけかもしれない。

#論点を一つずつ分解する

どういう制約条件の場合に線形になるかを確認していること。

論点を分解した影響を測定していること。

全体の構造を理解していること。

賢い人にしかできない作業であることを確認。

#文書履歴(document history)
ver. 0.01 初稿 20200313
ver. 0.02 補足 20200317
ver. 0.03 URL追記　20230307

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
C# WebBrowserを利用して、jsが実行された後の通知を受け取る方法について

現在WebBrowserを用いたツールを作成中の者です。

WebBrowserを用いてWeb画面を読み込んで処理を実施しているのですが、表題の通りwebbrowser1.ReadyStateが完了になったタイミングはサイトのjsの処理が完了しておらず、一部の処理を実行することができません。
(webbrowser1.Document.GetElementById("hoge").All.Countの値が0になったりなど)

たどり着いた先が「非同期処理にてWebBrowserの処理を続行させ、画面の更新があったタイミングで処理を実施する」です。

しかし、非同期処理中にキャストの例外が発生し、実現することができていません。

以下にソースコードを示しますので、どなたかこの問題の解決方法をご教授いただければ幸いです。
※目的はjsとページが全て読み込まれて処理をすることなので、以下のソースコードを改善する他の手段でも構いません。

お手数ですがよろしくお願い致します。

            await Task.Run(() =>
            {
                int iSleepTime = 200;

                while (webbrowser1.Document.GetElementById("hoge").All.Count==0)
                {
                    Thread.Sleep(iSleepTime );
                    System.Windows.Forms.Application.DoEvents();
                }     
            });

＞while (webbrowser1.Document.GetElementById("hoge").All.Count==0)
でキャストの例外が発生します。
＞int iCount= webbrowser1.Document.GetElementById("hoge").All.Count;
として同様に処理を確認しましたがやはり「webbrowser1.Document.GetElementById("hoge").All.Count」この箇所でキャストエラーが発生します。
ちなみに、この例だと場合によっては無限ループする可能性もありますが、できる限り処理を簡潔に書きたかったので諸々の処理は割愛しております。


【やってみたこと】
非同期処理ではなくwebbrowser1.ReadyStateの読み込みが完了した後に、

                while (webbrowser1.Document.GetElementById("hoge").All.Count==0)
                {
                    Thread.Sleep(iSleepTime);
                    System.Windows.Forms.Application.DoEvents();
                }
とやってみましたが、画面に表示されているWebBrowserコントロール上、ソース上で該当する箇所は空欄(js読み込みが完了してない)のままでした。

デバッガ上で、returnをかまして一度スレッドを手放すと、すぐに画面上には該当する箇所には値が設定されていました。

補足：
webbrowser1.Document.bodyの変化をキーに非同期で確認するやり方も試しましたが、同じでした、、、
その場合は
＞string strBeforeHtml=webbrowser1.Document.Body.OuterHtml;
ここでキャストのエラーが発生しました。
PyTorchのDataLoaderが遅い


PyTorchでは、データセットからミニバッチを取り出すのにDataLoader(`torch.utils.data.DataLoader`)がよく用いられるが、大きなサイズのデータを用いて実験しているときに、PyTorchのDataLoaderを用いると、とても時間がかかることがわかった。比較のためにデータセットからミニバッチを取り出すイタレータを自作し試してみたが、それと比べてもPytorchのDataLoaderはかなり遅いことがわかった。特にこれは、大きなサイズのデータを用いている時にはボトルネックになりうると思われる。

[追記：2020/03/23] 遅い原因はDataLoaderにデフォルトで使われているBatchSamplerであるというコメントをいただきました。詳しくはコメントをご覧ください。

# 設定

以下では、データ数が100万の`label`と`target`からバッチサイズ1万のミニバッチを繰り返し取り出すことを想定する。計算環境はGoogle Colaboratoryを使用した。

~~~python
import torch

label  = torch.randn(1000000,10)
target = torch.randn(1000000,10)
batch_size = 10000
~~~

ミニバッチを取り出すための`loader`を作成し、単にミニバッチを取り出すことを繰り返す以下の関数を用いて実行時間の計測を行う。

~~~python
def run_loader(loader):
    for label,target in loader:
        pass
~~~

# PytorchのDataLoader

`torch.utils.data.DataLoader`を用いてloaderを作成し(shuffleしない場合)、実行時間を計測すると、6.8秒であった。単にデータを取り出しているだけにしては時間がかかっている感じがする。

~~~python
dataset = torch.utils.data.TensorDataset(label,target)
loader1 = torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=False)

%timeit -n1 -r1 run_loader(loader1)

# 1 loop, best of 1: 6.83 s per loop
~~~

shuffleを行う場合は、7.0秒であった。

~~~python
dataset = torch.utils.data.TensorDataset(label,target)
loader2 = torch.utils.data.DataLoader(dataset,batch_size=batch_size,shuffle=True)

%timeit -n1 -r1 run_loader(loader2)

# 1 loop, best of 1: 6.97 s per loop
~~~

# 自作のDataLoader

比較のために、データセットからミニバッチを取り出すイタレータを作成し同様に実験を行なってみた。

~~~python
class DataLoader:

    def __init__(self,dataset,batch_size=1,shuffle=False):
        self.dataset = dataset 
        self.batch_size = batch_size
        self.shuffle = shuffle
        assert all([ dataset[i].size(0) == dataset[0].size(0) for i in range(len(dataset)) ]), 'all the elemtnes must have the same length'
        self.data_size = dataset[0].size(0)

    def __iter__(self):
        self._i = 0
        
        if self.shuffle:
            index_shuffle = torch.randperm(self.data_size)
            self.dataset = [ v[index_shuffle] for v in self.dataset ]

        return self

    def __next__(self):

        i1 = self.batch_size * self._i
        i2 = min( self.batch_size * ( self._i + 1 ), self.data_size )
        
        if i1 >= self.data_size:
            raise StopIteration()

        value = [ v[i1:i2] for v in self.dataset ]

        self._i += 1

        return value
~~~

自作のDataLoaderを用いた場合には(shuffleはしない)、実行時間が500マイクロ秒とほとんど取り出しには時間がかからないことがわかる。

~~~python
loader3 = DataLoader([label,target],batch_size=batch_size,shuffle=False)

%timeit -n1 -r1 run_loader(loader3)

# 1 loop, best of 1: 468 µs per loop
~~~

shuffleする場合には実行時間は300ミリ秒であり、しない場合と比べると時間はかかるが、それでもPytorchのDataLoaderを用いた場合に比べると、無視できるほどの時間である。

~~~python
loader4 = DataLoader([label,target],batch_size=batch_size,shuffle=True)

%timeit -n1 -r1 run_loader(loader4)

# 1 loop, best of 1: 296 ms per loop
~~~

# まとめ

PyTorchのDataLoaderを用いてミニバッチを取り出す時にとても時間がかかることがわかった。特に大きなサイズのデータを扱う時にはこの影響はとても大きい。
フローチャート作成ツール


自分のための全体を把握や、ドキュメント作りに必要なフローチャートを何で作っていますか？
私はパワポやExcelでメンドイながらも、仕事だから作っていました。

あまりにも手間なため、便利ツールを探しました。（今日は資料作りの日と決めたので）

そしたら無料でブラウザから使えるツールを発見。
しかもマルチデバイス対応かな？
GitHubからインストーラもDLできるし。

[おすすめツール](https://www.draw.io/)

### Excelやパワポでメンドウな点
- 挿入ー＞図形と階層が深い
- パワポはスライドなので、フローチャートだと数ページにわたり、把握しづらい
- Excelは。。。なんかイヤだ パワポと操作感が同じ


---
- 新規作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/8ccf7e64-c915-79c5-976a-9b49ffc77475.png)
- 好きなテンプレートを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/6437e93a-0c7b-9516-b832-7a313f383f41.png)
- 左のペインからドラッグして作成していく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/eebc232b-8645-1f92-dc81-219b5a20a534.png)
- ドラッグした図をポイントすると、矢印が表示される（四方に矢印をカンタンにひける）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/b3959c98-4548-9145-018c-72e0c7841de0.png)
- 好きな形式でエクスポートもできる PDFやJPEGなど
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208182/b27a2ced-03ee-410e-31ce-a12db5edcd80.png)
レンダリングとは何か

## はじめに
去年までAndroidアプリ開発をしていましたが、今年からWebの開発に参加し始めました。
Androidアプリを開発している時は気にしていなかった、サーバーレンダリングやクライアントサイドレンダリングについて、意識して開発する必要が出てきたのでレンダリングについて改めて調べてみました。
途中で詳しく書かれている記事を見つかったため、この記事は調べたことのメモとして残しています。
サーバーレンダリングやクライアントサイドレンダリングについては、改めて調べてみたいと思います。

## レンダリングとは
改めてレンダリングとは何かについて、ググって調べてみました。

> `レンダリングとは、何らかの抽象的なデータ集合を元に、一定の処理や演算を行って画像や映像、音声などを生成すること。`
例えば、一つのWebページに含まれる、HTMLやCSSなどによる描画内容の記述、スクリプトによる動作の記述、画像ファイルやフォントファイルなど外部のデータなどを組み合わせ、Webブラウザのウィンドウ内にページ内容の描画を行うことを指す。  
[* IT用語辞典 e-Words 「レンダリング  【 rendering 】  レンダ / render」 より抜粋](http://e-words.jp/w/%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0.html)

何をレンダリングするのかにも寄ると思いますが、webページのレンダリングとして考えるなら、HTMLやjavascriptなどのコードとしての情報・データと通信を行って取得したデータなんかを組み合わせてページとして描画するということなのでしょう。

ここまで調べていたら、ちょうど詳しく説明してくださっている[記事](https://qiita.com/goemp/items/91dcc8b50d7a61ce98bc)があったので、
調査はここで終わりました。


## おわりに
次はデータを元に描画することがレンダリングだとすると、サーバーでレンダリングした場合とクライアントサイドでレンダリングした場合での違いはどこにあるのかを詳しく調べてみたいと思います。
vue.jsでリンク先の拡張子でFont Awesome Iconが変わるあいつをつくってみた


##具体的にどんなの？
`a[href$=".pdf"]`のようなCSSの疑似要素を利用してアイコンを表示していた下記のようなやつを
[vue-fontawesome](https://github.com/FortAwesome/vue-fontawesome)を利用して作ってみよう、というお話です。
![アートボード 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181107/664da3ac-41ce-60ed-b336-2c91d70efb80.png)
###Q:今まで通りCSSの疑似要素で実装すればいいじゃん
A:~~それじゃこの記事の意味ないでしょ~~:upside_down:
[疑似要素はエラー発生しやすいからお勧めしない（意訳）](https://fontawesome.com/how-to-use/on-the-web/advanced/css-pseudo-elements)書いてあるからね。~~つべこべ言わずに~~勉強のつもりで考えてみよう。
##実際に作ってみた
拡張子のパターン振り分けどうしよう、いくつまで対応したらいいんだろうと考えてたら、[font-awesome-filetypes](https://github.com/spatie/font-awesome-filetypes)という素敵なものを発見したので利用したところあっという間でできてしまった。

```vue:linkFileIcon.vue
<template>
  <a :href="href">
    <font-awesome-icon
      :icon="faIcon(href)"
      :class="`text-` + faIconColor()"
      fixed-width
    /><slot v-slot="text">{{ text.label }}</slot>
  </a>
</template>
<script>
import geticonForExtension from "font-awesome-filetypes";
export default {
  name: "href",
  props: {
    label: {
      type: String,
      default: "リンク"
    },
    href: String
  },
  methods: {
    isExternalLink(path) {
      //外部リンクかどうか
      return /^https?:\/\//.test(path);
    },
    faIcon(path) {
      if (path) {
        //外部リンクの場合は"external-link-alt"
        if (this.isExternalLink(path)) {
          return "external-link-alt";
        } //それ以外は拡張子によってアイコンを変更
        return geticonForExtension(path.split(".").pop()).slice(3);
      }//拡張子が判別できない場合は"file"
      return "file";
    },
    faIconColor() {
      //アイコンごとに色を変更、BootstrapVueを使用しています
      const faIcon = this.faIcon(this.href);
      if (faIcon === `external-link-alt` || faIcon === `file-word`) {
        return `info`;
      } else if (faIcon === `file-powerpoint`) {
        return `warning`;
      } else if (faIcon === `file-excel`) {
        return `success`;
      } else if (faIcon === `file-video` || faIcon === `file-pdf`) {
        return `danger`;
      } else if (!this.href) {
        return `muted`;
      } else return `primary`;
    }
  }
};
</script>

```
### ポストカードウェア
[font-awesome-filetypes](https://github.com/spatie/font-awesome-filetypes)は、自由に使っていいけど、役に立ったら使ったパッケージ書いた手紙送ってね（意訳）と書いてあるので、もし利用したら送ってあげてね。私もそうするつもり。
[いっぱいあって楽しいね](https://spatie.be/open-source/postcards)
macOS版のGravio Studioでアクション変数を表示するには

macOS版のGravio Studioは、普段使っているWindows版とはちょっとUIが異なるので戸惑うことがある。
アクション変数はデバイスからのトリガーを受けてなにかしようと思ったときにデータなどが受け渡されるので結構大切なんですが、どこで表示されるのかよく忘れてしまうのでメモ。

このアクション名のところをクリックすると、
![スクリーンショット 2020-03-13 14.19.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/736cfa42-e3b6-9308-e507-067b189c8a1b.png)

ここに一覧が表示されます。＼(^o^)／
![スクリーンショット 2020-03-13 14.19.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41603/899054ec-2e8c-5322-2d22-f4ab1470958e.png)

ちなみに、Slackに送信したりするときにコンポーネントプロパティで参照するには、`av.Data` のように `av.` (Action Variableの略)とプレフィックスをつけます。
Laravelインストール時に困ったこと

プログラム初心者です。
Mac OS Catalina(10.15.3)を使用してます。
本物の初心者なので、間違っている事を書いているかもしれません。
もしありましたらご指摘いただけたらと思います。

とにかく動かすために環境構築しないと、ってことで勉強中のPHPとLaravelのインストールを行うとした矢先、早速エラーが。

```
$ composer global require laravel/installer
```
これをやったら、

```
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - laravel/installer v3.0.1 requires ext-zip * -> the requested PHP extension zip is missing from your system.
    - laravel/installer v3.0.0 requires ext-zip * -> the requested PHP extension zip is missing from your system.
    - Installation request for laravel/installer ^3.0 -> satisfiable by laravel/installer[v3.0.0, v3.0.1].

Installation failed, deleting ./composer.json.
```

なんかよく分からないが、必要なものが足りていないっぽい。
再度PHPバージョンを確認。

```
$ php -v
```
```
$ brew search php
```
表示されるPHPのバージョンを確認した後に、再度インストール。
（私がしたときは7.3でした）

```
$ brew install php@7.3
```
終了するとこんな表示が出てくるので、言われた通りにパスを通す。

```
If you need to have php@7.3 first in your PATH run:
  echo 'export PATH="/usr/local/opt/php@7.3/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/php@7.3/sbin:$PATH"' >> ~/.bash_profile
```

その後、もう一度Laravelインストールできるか試す。

```
$ composer global require Laravel/installer
```
そうしたらなんとか完了しました。
ただ下の方に気になる文章が出てきたので、メモ代わりに残しておきます。

```
symfony/service-contracts suggests installing symfony/service-implementation
symfony/console suggests installing symfony/event-dispatcher
symfony/console suggests installing symfony/lock
symfony/console suggests installing psr/log (For using the console logger)
guzzlehttp/psr7 suggests installing zendframework/zend-httphandlerrunner (Emit PSR-7 responses)
guzzlehttp/guzzle suggests installing psr/log (Required for using the Log middleware)
Writing lock file
Generating autoload files
1 package you are using is looking for funding.
Use the composer fund command to find out more!
```
Laravelのコマンドが認識されることを確認。
試しにデスクトップに新規でプロジェクト作成。

```
$ cd desktop
```
```

$ Laravel new laravelプロジェクト名
```
```
ce laravelプロジェクト名
```
```
php artisan serve
```
この後ブラウザで
```http://localhost:8000/```
にアクセスして、Laravelトップページが表示されました。

やっと終了。
ありがとうございました。
Bash で dotnev ファイルを読み込んで複雑な環境変数を sed でパースする

あるプロジェクトで、環境変数が`.env`ファイルに格納されており、その中の一つの環境変数が、独特のフォーマットで記述されており、それをパースする必要があった。
そのメモとしてブログを残しておく。

# 問題

`.env` ファイルに格納された文字列がある。

```
FOO=BAR
SOME='{ aks_node_vm_size="Standard_L8s_v2", dns_prefix="staging-e", agent_count_min=1,agent_count_max=10, agent_count_enable_autoscale=true, kubernetes_version="1.14.7", cluster_name="some-aks", vnet_subnet_name="some-aks-subnet", gateway_name="some-gateway" }'
```

この状況で、`cluster_name` の値だけを取得したい。


# dotnenv ファイルを読み込んで環境変数にする

これは意外とややこしい。当初は`grep`を使ってやろうとしていたが、上記のような複雑な変数は上手く読めなかったりした。しかし簡単な方法があった。

```bash
set -o allexport; 
source $TEST_ENV_FILE_PATH
set +o allexport; 
```

ちなみに`-o allexport` は全ての変数をexportする指定で、`-a` でもよいようです。

* [4.3.1 The Set Builtin](https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html)

ちなみに `+o` の指定はオプションの無効化になります。つまり、AllExportを指定した状態でEnvファイルを読み込めばまずは、環境変数までもってこれます。


# 複雑な環境変数をパースする。


```bash
SOME='{ aks_node_vm_size="Standard_L8s_v2", dns_prefix="staging-engine", agent_count_min=1,agent_count_max=10, agent_count_enable_autoscale=true, kubernetes_version="1.14.7", cluster_name="some-aks", vnet_subnet_name="some-aks-subnet", gateway_name="some-gateway" }'
```

これのパースだが、最初はこんなコードを書いていた。できるねんけど、ダサさが漂っている。基本的にやってることは、IFSを変えて`,`で分割して、
余計なダブルクオートや、変数名をカットという感じ。

```bash
#!/bin/bash

OLDIFS=$IFS
IFS=","
pattern="^cluster_name="
CLUSTER_NAME=""
for kv in $SOME
KEY_VALUE=$(echo $kv | xargs)
if [[ $KEY_VALUE =~ $pattern ]]; then
   CLUSTER_NAME=$(echo $KEY_VALUE | sed 's/cluster_name=//')
fi
done

echo $CLUSTER_NAME
```

これを何とかワンライナーで出来ないかと思い、Sedを調査した。Sedの置換のコマンドを使っている。
cluster_name=の直後で、空白、もしくは`,`ではない文字列をヒットさせる。` \( \)` は、ここで
ヒットした内容を後で参照できる。つまり、空白や`,`が先ほどの文字列の区切りにでてくるので、次にそれがヒットするまでは
`( )`の中の内容になる。`.*`は任意の文字列にヒットする。この内容（つまり、cluster_name=以降の文字列）を、`\1` つまり、
`( )` の中でヒットした内容を置換する。つまりそれは、"some-aks" になるので、それのダブルクオートをxargsでとって終わり。

```bash
CLUSTER_NAME=$(echo $SOME | sed 's/.*cluster_name=\([^ ,]*\).*/\1/' | xargs)
echo $CLUSTER_NAME
```

xargs で、"" が取り除かれるのは、元々 xargsはデリミタで分割した文字を返すもの

> xargsは、改行等で区切られた標準入力を読み込み、空白で区切られた１行の文字列へ加工し、それを引数として指定したコマンドへ渡して実行させる。

https://ja.wikipedia.org/wiki/Xargs

なので、デリミタが無い場合は、単純に、１行の文字列に加工するけど、""をストリップするのだろう。

部分抽出に関しては下記のブログを参考にしました。

* [[Linux][sed] 文字列から部分抽出する/置換後に特定文字列を使いまわす方法](https://qiita.com/koara-local/items/2911bd81df2420a420ad)
iTerm2の便利機能ベスト３

# iTerm2の便利機能ベスト３をお送りします
`iTeam`っていうふうに打ち間違えちゃいますよね

それはそうと先日、`FLU 運命の36時間`という映画を観てしまい
パンデミック怖いと思ってしまった次第です

今は2020年3月…、数年後にこの記事を読んだ、あなた
どうですか？ いまはどうなってますか？ パンデミックは落ち着いていますよね？

100日後に死ぬワニはどうなりましたか！？
気になって昼と夜しか眠れません！

### それでは第３位！
### `option を押しながらマウスをクリックする`

これなんですけど、vimで編集してるときだけ機能するんですよね
vimの機能かもしれません
でもoption押して機能する感じはiTermっぽいのでここで

vimの編集画面に文字がズラーッと並んでいる場合
特定の箇所にマウスカーソルを持っていきoptionを押します
すると画面内の編集用カーソルもそこに移動します

　　![002.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/7e304cbf-d8b4-533b-6e5e-94bab4f6f82e.gif)

## 続いて第２位！！
### `command + Shift + I タブやペインを同時に動かす`


```bash
ペイン ［1］ 【pane】
〔窓枠・窓ガラスなどの意〕
コンピューターの GUI において、ウインドー内部を機能別に区画した領域。 → ウインドー ・ GUI （ ABC 略語）
```

まず、`command + d で左右にペイン分割`できます
（`control + d でサーバからログアウトできて最終的に画面を閉じる`ことができます）

私はさらに左右のペインに対し
`command + shift + d で上下に分割`し、４画面にしています

そこにさらに`command + t でタブを追加します`
場合によってはその新規タブ画面を左右に分割しペインを作ります

そんな状態でsshコマンドで同じサーバに入りたいとき
全部のペインに同じコマンドを打たなければなりません
*上記の場合だと計６回…*
いままではコピペでしてましたがこれがあれば一発ですよね

なんかこんなマークが画面右上にでます
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/5c22b0ca-3d59-d322-a78e-2621bc8ac053.png)

　　![スクリーンショット 2020-03-13 12.23.21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/cbd868fb-d88b-650a-87fd-1f7552249617.jpeg)

```bash:ところで、ですけど
最初の頃、bash（バッシュ）って聞いて
「え？ 靴？」って思いませんでした？
```

ただし、
全部が同じ挙動になるのでこっちの画面だけ固定したい
ということができないんですよね、設定であるのかな？
*知ってる方は教えて下さい*

**追記**

- `command + Shift + I`がすべてのタブもペインも一緒に動かしますよ
- `command + Option + i`で今見えてるタブとすべてのペインを一緒に動かしますよ
- `command + Shift + OPtion + Cntrol + I`で指定したペイン
（今使用しているペインで上記のキーを打つ、またペインを移動して上記のキーを打つ…）
だけ動かしますよ


# 最後はこれ！ 第１位!!
### `cmmand + option 同時押しで、短形選択`
これです
`cmmand + option`を押すとカーソルが十字になります
vimで開いた大量のデータテキストをコピーするときに重宝しています
`ctrl + v`とかでもいいだろうと、お思いでしょうが
やっぱり特定のエリアをマウスでグイーっと囲めるのはありがたいし
気持ちいいです

![001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/a56b646c-b270-0852-e07b-0f3df5e67b04.gif)

**追記**
こんなものも見つけました！
`commandを押しながら`好きな箇所をいくつも選択できます
選択したものは順番に一つのクリップボードに入れられます

![001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/dc3bf30a-9217-3abb-92cf-80ca44c7a4a7.gif)


### これらのおかげで作業効率が数秒上がりました

---

### あ、あとiTerm2とは、全然関係ないんですけど
[Notion](https://www.notion.so/)っていう、
すごく使いやすいメモツールを使ってるんですけど
あれで`->`って打ってみてください`→`っていう普通の矢印が出てきます
もちろん`<-`で`←`になりますが、
`-`って打ったあと、カーソルを左に動かして`<`って打って`<-`を作っても
`←`にはなりませんのであしからず
CakePHP3にて全テーブルの内容をCSVファイルに出力する方法

# はじめに
CakePHP3で全テーブルの内容をCSV出力したので、まとめました

# 環境
PHP 7.2.28-3
CakePHP 3.6.14

# コード

```Hoge.php
<?php
namespace App\Hoge;

use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;

public function outputCsv()
{
    // CSVの出力先（tmp/csv）を作成する
    $base_dir = TMP . 'csv' . DS;
    if (!file_exists($base_dir)) {
        mkdir($base_dir, 0777, true);
    }

    // CSV出力をするテーブルのリストを取得する
    $tables = ConnectionManager::get('default')->getSchemaCollection()
        ->listTables();
    while (($index = array_search("phinxlog", $tables, true)) !== false) {
        // phinxlogはCSVに出力しない
        unset($tables[$index]);
    }

    // テーブルのリスト分データを取得し、CSVファイルに出力する
    foreach ($tables as $table) {
        $data = TableRegistry::get($table)->find()
            ->toArray();
        $fp = fopen("{$base_dir}{$table}.csv", 'w');
        foreach ($data as $key => $row) {
            $output_data = $row->toArray();
            if ($key === 0) {
                // 取得したデータのキーからヘッダーを作成する
                fputcsv($fp, array_keys($output_data));
            }
            fputcsv($fp, $output_data, ",", '"');
        }
        fclose($fp);
    }
}
```

# 参考
- [スキーマコレクション](https://book.cakephp.org/3/ja/orm/schema-system.html#id6)
- [fopen](https://www.php.net/manual/ja/function.fopen.php)
- [fputcsv](https://www.php.net/manual/ja/function.fputcsv.php)
- [配列から指定した値を削除する方法](https://lab.syncer.jp/Web/PHP/Snippet/12/)
Google Drive APIの小ネタ集

# はじめに

こちらの記事は、

- PHP
- [Google Drive API](https://developers.google.com/drive/api/v3/reference?hl=ja)

を使ってできることの小ネタ集です。

サービスアカウントの取得などが必要なのですが、だいたい[こちらの記事](https://qiita.com/niiyz/items/30fab61adc4fcf87b98a)に書いてあることと同じです。

ただ、有効にするのは、`Google Sheet API`ではなく、`Google Drive API`になりますので、ご注意ください。

※あと、自分の書いたコードをQiita用に書き換えていますので、動作確認はしていません。
エラーになったらごめんなさい。

# 共通で使うコード

```php
require_once __DIR__.'/vendor/autoload.php';

class GoogleDriveClass {
    protected $client;
    protected $service;

    protected $serviceKeyJson = 'サービスアカウントキーが書いてあるファイル.json';

    function __construct() {
        putenv('GOOGLE_APPLICATION_CREDENTIALS=' . dirname(__FILE__) . '/' . $this->serviceKeyJson);

        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope(Google_Service_Sheets::DRIVE);
        $client->setApplicationName('test');
        $this->client = $client;
        $this->service = new Google_Service_Sheets($client);
    }
}

```

# Googleドライブ上のファイルをコピーする

コードを動かす前に、サービスアカウントへの共有設定が必要となります。
サービスアカウントというのは、`aaaaaaa@aaaa.iam.gserviceaccount.com`みたいなやつのことです。

- コピーするテンプレートファイル
- コピー先のフォルダ

上記２点を共有しておいてください。


```php

$drive = new Google_Service_Drive($this->client);

//コピー先のフォルダID
$makeFileData['parents'] = [$parentFolderId];

$makeFileData['name'] = 'コピーしてできるファイルのお名前';

$makeFileMetadata = new Google_Service_Drive_DriveFile($makeFileData);

//第一引数はコピーしたいファイルIDを設定してください
$file = $drive->files->copy($templateSpreadsheetId, $makeFileMetadata);

```

[公式ドキュメント](https://developers.google.com/drive/api/v3/reference/files/copy?hl=ja)

サービスアカウントに共有設定かけるのを忘れていて、はまりました。

ちなみに、コピーしたファイルはサービスアカウントのものになって、私は共有してもらっている人みたいな扱いになるっぽいです。
ですので、Google Driveの画面上から消しても、実はサービスアカウントのフォルダにはあったりして。
消すときは、画面から消せないので、APIでファイルIDを指定して消すしかなさそうです。たぶん。


# Googleドライブ上のファイル一覧を取得する

```php

$drive = new Google_Service_Drive($this->client);
$fileList = $drive->files->listFiles();

```

サービスアカウントのファイルが全部取得できます。
パラメーターで絞り込みできるみたいですが、書き方が分からなかった...

[公式ドキュメント](https://developers.google.com/drive/api/v3/reference/files/list?hl=ja)

メソッド名`list`だと思ってエラー出てはまった。`listFiles`でした。


# Googleドライブ上のファイルを削除する

```php

$drive = new Google_Service_Drive($this->client);
$drive->files->delete($fileId);

```

[公式ドキュメント](https://developers.google.com/drive/api/v3/reference/files/delete?hl=ja)

ファイルIDを指定するだけです。


# Googleドライブ上にあるファイルをファイル名を指定して削除する

ファイル一覧取って、ループして、ファイル名一緒だったら削除するという力技に出ました。
本当はファイルを取得する時点で、絞り込みが必要だと思います。


# まとめ
[公式ドキュメント](https://developers.google.com/drive/api/v3/reference?hl=ja)は、あんまり初心者に優しくない...
pagePhiling.jsを実装してページ毎にスクロールさせてみる！

#WEBサイトで1ページ毎にスクロールさせたい！
そんなことが、pagePhiling.jsを実装すれば可能になります。
[pagePhiling.js](https://alvarotrigo.com/pagePiling/)←公式HPからプラグインをダウンロード！
[デモ](https://t.co/ai4ZQosnTS?amp=1)←私のポートフォリオですが、pagePhilingを実装しております。ご覧ください！

##準備するもの
- html,cssファイル
- javascript基礎知識
- やる気スイッチ
- pagePhiling.jsをダウンロード

##実装する

###HTML
```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
   <title></title>
  </head>
<!-- stylesheet -->
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="pagePiling.js-master/jquery.pagepiling.css">
<body>

<!-- nav要素  -->
<ul id="nav">
    <li data-menuanchor="Page1" class="active"><a href="#Page1">First section</a></li>
    <li data-menuanchor="Page2"><a href="#Page2">Second section</a></li>
    <li data-menuanchor="Page3"><a href="#Page3">Third section</a></li>
    <li data-menuanchor="Page4"><a href="#Page4">Fourth section</a></li>
</ul>



<!-- section毎に内容を記述する　-->
<div id="pagepiling">
	<div class="section"　id="section1"> section 1</div>
	<div class="section　pp-scrollable" id="section2"> section 2</div>
	<div class="section" id="section3"> section 3</div>
	<div class="section" id="section4"> section 4</div>
</div>
      <!-- javascript -->
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="pagePiling.js-master/jquery.pagepiling.min.js"></script>

</body>

</html>

```
htmlファイル内に、cssファイルである**jquery.pagepiling.css**とjsファイルである**jquery.pagepiling.min.js**を記述しておく。**ajax**のsrcもお忘れなく！
親divのpagePhiling内の各section内に内容を記述する。記述が長い場合は、classで**pp-scrollable**と記述すればOK!

###js
```html
<script>
      $(function() {
  $('#pagepiling').pagepiling({
      menu: '#nav',
      sectionSelector: '.section',
      sectionsColor: ['#fff', '#eee', '#ddd', '#ccc'],
      anchors: ['page1', 'page2', 'page3', 'page4'],
      navigation: {
          'textColor': '#000',
          'bulletsColor': '#000',
          'position': 'right',
          'tooltips': ['page1', 'page2', 'page3', 'page4']
      },
  });
});
      </script>

```
jsは上記の記述で機能します。ちなみに、navigationは、ページの右側にスクロールした際の案内が表示されます。

###css
問題はスタイルです。nav要素のスタイルや各sectionのz-indexなどをお好みのスタイルに調整すればいい感じになるはずです。
###追記
スクロールするページを増やしたい時は、htmlファイル上でdivのsection要素と、jsの**anchors**と**tooltips**のpageを追加する。
##後記
いかがでしたでしょうか？工夫次第でおしゃれでいい感じのウェブページが作れるはずです♪ぜひ、実装してみてください！
Daily&Weekly Backup via systemd

### Overview

マシンを変えたのでcronで行っていたdaily/weeklyのbackupをsystemdで行うようにしたのでメモのため記事にしておこうと考えた。

### Environment

- Ubuntu18.04 (というかsysmtedであれば動くはず)

### Procedure

##### Dump Scriptの準備

/usr/local/binに以下を配置。(systemd serviceファイルにコマンド直書きでもいいが、あとでやりたいことが増えた場合にscriptのほうが良さそうなので、backendはscriptにしておく)

/usr/local/bin/backup-daily.sh

```
#!/bin/bash

echo "Dumping backup in daily, /dev/nvme0n1p2 will be in /mnt/data1/dump-nvme0n1p2.daily"

dump -0uf /mnt/data1/dump-nvme0n1p2.daily /dev/nvme0n1p2

```

/usr/local/bin/backup-weekly.sh

```
#!/bin/bash

echo "Dumping backup in weekly, /dev/nvme0n1p2 will be in /mnt/data1/dump-nvme0n1p2.weekly"

dump -0uf /mnt/data1/dump-nvme0n1p2.weekly /dev/nvme0n1p2
```

※(もちろんだが、)dumpの保存先のマウントポイントは必要に応じて準備しておくこと。

##### systemd serviceとtimer

serviceとtimerファイルを以下のように準備

```
>ls -lt  /etc/systemd/system/backup-*
-rw-r--r-- 1 root root 133 Mar 13 12:20 /etc/systemd/system/backup-weekly.service
-rw-r--r-- 1 root root 122 Mar 13 12:20 /etc/systemd/system/backup-weekly.timer
-rw-r--r-- 1 root root 148 Mar 13 12:20 /etc/systemd/system/backup-daily.timer
-rw-r--r-- 1 root root 131 Mar 13 11:51 /etc/systemd/system/backup-daily.service
```

それぞれの中身は以下。

/etc/systemd/system/backup-weekly.service

```
[Unit]
Description=Weekly backup activities
ConditionACPower=true

[Service]
ExecStart=/usr/local/bin/backup-weekly.sh
Type=oneshot
```

/etc/systemd/system/backup-weekly.timer

```
[Unit]
Description=Weekly backup activities

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target
```

※weekly=Mon --* 00:00:00

/etc/systemd/system/backup-daily.service

```
[Unit]
Description=Daily backup activities
ConditionACPower=true

[Service]
ExecStart=/usr/local/bin/backup-daily.sh
Type=oneshot
```

/etc/systemd/system/backup-daily.timer

```
[Unit]
Description=Daily backup activities

[Timer]
OnCalendar=*-*-* 02:00
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target
```

##### systemd-timerをenable

```
sudo systemctl enable backup-daily.timer
sudo systemctl enable backup-weekly.timer
```

##### 補足

ログを見たいときは、

```
systemctl status backup-daily.timer
systemctl status backup-daily.service

systemctl status backup-weekly.timer
systemctl status backup-weekly.service
```
文字列からASCIIコードの制御文字を削除する

<h1>LT;DR</h1>
Hexをbyte配列に変換して`new String(byte[])`したら0x00とか0x01とか入ってきてムキーってなったので調べた。

<h1>ASCII制御文字を文字列から除去する。</h1>
```java:replaseAsciiCC.java
// hexからbyteに変換するのに必要。
import javax.xml.bind.DatatypeConverter;

// class定義とかmethod定義とか略

String hex = "0100313233343536373839302D5E5C";  // 先頭4byteが制御文字

byte[] hexFromByte = DatatypeConverter.parseHexBinary(hex);
String strFromByte = new String(hexFromByte);

String resultStr strFromByte.replaceAll("\\p{C}", ""));

// 制御文字が消えて"1234567890-^\"って出力されるはず。
System.out.println(resultStr);
```
なぜ"\\p{C}"でいいのかはこの辺。
https://regular-expressions.mobi/unicode.html?wlr=1

改行コードも除去されるので注意。
Java以外の言語で使えるかは解らぬ。
Python でつくるオセロゲーム開発

#はじめに
Pythonを用いてオセロゲームを開発しました. 
誰でも簡単に遊べます

github ページ 
https://github.com/chihina/othello-game-python

![top_resized.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/9c1762e8-e461-9f22-c3e5-0bb5d31ab043.png)

## 開発環境
python3.7.1 
その他は以下のgithubページのrequirement.txt確認してください.
https://github.com/chihina/othello-game-python

## ゲーム開始まで
まず, 以下のコマンドでgit clone をします. 

```
git clone https://github.com/chihina/othello-game-python.git
```

次に, 以下のコマンドでライブラリを一括インストールします.

```
pip -r install requirement.txt
```

これで環境構築は終わりです. 簡単ですね.
以下のコマンドでゲームが始まります. ぜひ遊んでみてください!!

```
python game.py
```
# ゲーム解説

## 対戦モード
対戦モードとしては以下の3つを実装しました. 
- Human vs Human (人対人)
- Human vs CPU (人対コンピュータ)
- CPU vs CPU (コンピュータ対コンピュータ)

上2つのモードでは先攻・後攻を選択できます. 

## CPU種類
コンピュータは３つの強さを実装しました.
- Weak (弱い)
- Little strong (少し強い)
- Strong (強い)

以下にコンピュータの実装方法についてを述べます.
### Weak (弱い)
着手可能な手の中から乱数を用いてランダムに打つ手を決定します.
要するにテキトーに手を選んでいます.

### Little strong (少し強い)
オセロでは4隅を取ると強い(あくまで一般的に)と言われます. 
つまり, 以下の画像の赤枠に自身のコマを打たなければ, 4隅を相手にとられることはありません. 
よって, 以下の画像の赤枠に自身のコマを打たないように実装しました. 
<img width="240" alt="top_resized - コピー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/3eb67e19-f61d-1b8d-e216-bad3b538ad10.png">

### Strong (強い)
以下のwebサイトより入手したオセロの静的評価値を用います.
https://uguisu.skr.jp/othello/5-1.html

この静的評価値を利用して手を決定します. 
![value.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/e6bba1d9-20b0-0b61-a504-8ee43a9dfc0f.png)

## 対戦シミュレーション結果
3つのCPUのシミュレーション結果を以下に示します. 
<img width="288" alt="result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482108/86eaab8c-c445-70c6-2314-f0c28a2fd565.png">

強さの順に勝率が出ていることがわかります.
如何にオセロにおいて隅が重要かがよくわかります. 

# あとがき
ここでは単純なCPUの実装にとどまりました.
今後の可能性としては, 数手先を読んだ手の決定, 機械学習を用いた手の決定が考えられます. 
アドバイス等々ありましたらコメントいただけるとありがたいです!!

github ページ
https://github.com/chihina/othello-game-python

参考文献
オセロ（リバーシ）の作り方（アルゴリズム） ～石の位置による評価～ (2020/3/13 アクセス)
https://uguisu.skr.jp/othello/5-1.html
効率的なWeb会議の仕方（案）

ここでは、Zoom, WebEX, Teams, Skype, Hangoutはじめ、各種テレビ会議システムを利用してきて、
うまくいったこと、うまくいかなかったことを記録します。


#うまく行ったこと

##1 複数拠点間

複数拠点間の会議で、うまく行った時は、こちらと向こうの会議の調整する方が、
会議の内容と大事な点を把握されていて、必要な助言や行動を、個別にされていた時です。

その際に、大事だと思ったことを整理してみます。

### 1.1 連絡経路は複数用意

テレビ会議システムがうまくつながらなくても、携帯電話、Lineなどの３つ以上の連絡手段があって、
必要に応じて、音声、写真などで相互の状況を相手に伝える。

### 1.2 最低限文字情報のやりとりは頻繁に

会議の題材にもよりますが、最低限、文字情報のやりとりで解決することが何かを判断できること。



#必要技術・技能・素養

ここに書く、すべての技術・技能・素養が必要なわけではない。

拠点または主催者の何人かで、技術・技能・素養を分担してもよい。

## 通信

### 導通確認(ping, ブラウザ等）
ネットワークがつながっているかどうかの確認方法がわかるとよい。
pingコマンドはICMPを利用しており、ICMPを通さない設定、応答しない設定だと確認できない。


### 記録(Wireshark)
Ethernet, Wi-Fi, Internet Protocolを利用した通信で会議を行う場合には、
何があっても測定ができるとよい。

その時に解決しなくても、記録してあとから解読することができるかもしれない。


### 画像
カメラなどを接続し、表示するにあたって、内臓機器または外付け機器の操作ができるとよい。

OS、アプリ、ブラウザの種類、版などで、うまく画像取得、送信できないことがあるかもしれない。

動画の利用の場合には、ライブラリに特定のcodecが入っていないとインストールする必要がある場合もある。

### 音声
画面がうまく表示できなくても、マイクとスピーカを接続して設定できれば、
多人数電話として利用できるかもしれない。


# 文書履歴(document history)
ver. 0.01 初稿 20200313
ver. 0.04 URL追記　20230305

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
【Laravel】ドット区切りの文字列から一部を取得する

`example.co.jp` という文字列から `example` を取り出したいとき

```php
$url = 'example.co.jp';

// 最初のドットの位置
$pos = strpos($url, '.');

// 先頭からドットまでの文字列を取得
$name = substr($url, 0, $pos);

var_dump($name); // 'example'


// 1行で書く場合
var_dump(substr($url, 0, strpos($url, '.'))); // 'example'
```

とかしなくても↓でいける

```php
$url = 'example.co.jp';

var_dump(Str::before($url, '.')) // 'example'
```

```php
$url = 'example.co.jp';

var_dump(Str::after($url, '.')) // 'co.jp'
```

### [2020/05/10 追記]
`afterLast` でTLDを取得できる

```php
$url = 'example.co.jp';

var_dump(Str::afterLast($url, '.')) // 'jp'
```

https://readouble.com/laravel/6.x/ja/helpers.html#method-str-after-last
自動テストツールKatalon Studioでテスト自動化 vol.03

 自動テストツールKatalon Studioでテスト自動化 vol.02 の続きです。

> ここではKatalon Studio Verion 7.1.1を使ってる前提で話しを進めます。

<h2> Data Files の続き・・・</h2>


> [自動テストツールKatalon Studioでテスト自動化 vol.02](https://qiita.com/McLaren/items/1148452f629a179386c8)

上記の続き、具体的にどんな手順でTest Dataを使っていくか、、、

1. Test Dataを使用したいTest Suiteを選択し、Show data bindingをクリック
![スクリーンショット 2020-03-13 10.53.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/85be41b7-a801-99e0-8244-cba2da4ef21e.png)


1. Test Dataフィールドの、+Add をクリック
![スクリーンショット 2020-03-13 11.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/b60f37f9-f84b-e4a1-27fa-9263c1798f97.png)

1. 選択したテストケースに存在するすべての変数を表示しているVariable Bindingの表(選択したテストケースに変数が存在しない場合は何も表示しません) で、テストデータのデータを使いたい行を選択し、Typeを選択、Data Columに設定する。
![スクリーンショット 2020-03-13 11.07.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/ad2f303a-281f-aa8b-936c-f9160780c60c.png)

1. Variable Binding表のTest Dataの各セルをクリックし、リストから実行に使用したいテストデータを決定する
![スクリーンショット 2020-03-13 11.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/f3e15edc-0e61-9f32-0412-9c0e8a5cbb5f.png)

1. Variable Binding表のValueの各セルをクリックし、選択したデータファイルの中の使いたいデータフィールドを指定します
![スクリーンショット 2020-03-13 11.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/cb697054-c6bc-5932-8ba3-b1da6a735ba0.png)

1. 上記の全ての手順を完了させると、Test Suiteを保存したらTest Suiteでテストデータを使う準備が完了です。


<h2>Tips</h2>
![スクリーンショット 2020-03-13 11.23.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148127/5af0cf86-3c53-6899-4b4d-903c72ee353d.png)

テストデータを選択後、[Map All]ボタンを使用すると、選択したTest caseのパブリック変数をテストデータの各列にすばやくマッピングできます。
ただし、変数をデータに自動的に結びつけるには、変数とテストデータの各列が同じ名前を使っている必要があります。

例えば、選択したテストケースの「Username」「Password」変数は、「Map All」をクリックすると、テストデータの「Username」「Password」列を自動的にマッピングできます。

<h2>参照サイト</h2>
* [Katalon Docs](https://docs.katalon.com/katalon-studio/docs/run-test-case-external-data.html#create-a-new-test-suite-with-test-case-variables)
* [Katalon Studio | How To Get Data From Excel](https://youtu.be/tu5Zc89w6oQ)

* 関連資料
[Test-Hack | 3分で理解するIT/テスト技術/ テスト自動化](https://test-hack.com/category/test-automation/)
【Laravel】Model::where()->get() で返ってくるオブジェクトの空判定

###使い時
有効なユーザーがいたら何らかの処理をしたいなぁ〜とか思ったとき


###失敗

```php
$users = DB::table('users')->where('active', true)->get();

// 全部trueになる😭
if (! empty($users)) { ... }
```

###成功(?)

```php
$users = DB::table('users')->where('active', true)->get();

// toArray()で配列にしてしまえば解決🤣(ﾖｼｯ!!
if (! empty($users-toArray())) { ... }
```


->get() で返ってくるオブジェクトは`Illuminate\Database\Eloquent\Collection`です。
便利なので配列に変換せずそのまま使いましょう！👍

```php
$users = DB::table('users')->where('active', true)->get();

// パターン①
if ($users->isNotEmpty()) { ... }

// パターン②
if ($users->count() > 0) { ... }
```

ドキュメント
https://laravel.com/docs/7.x/collections#method-isnotempty
【R・Mecab】自分と河野太郎さんのツイートをword_cloudしてみた

（備忘用なので、時間あるときに分かりやすい記事にします。）

下記リンクを参照して、word_cloudしてみました。
https://qiita.com/Sota_N/items/dfd435c4ebee29e100f7


まず自分のツイートの結果
![wordcloud_hikaru.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589618/c8341cd5-d0b2-56b3-ecc0-ab2a724c8baa.png)

反省点は
・取得するツイート数を500に設定し、リツイートを除外したのでサンプルが少ない。
・する、てるなどを除外するべき。
・そもそも私のツイートは具体的な名詞が少ないので、分析しがいがない

反省を生かし、防衛大臣の河野太郎さんのツイートを分析したのが下記。
![taro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589618/a6b925e1-9a11-d74f-322a-e59a7c7d6596.png)

最近コロナウイルスの感染者等をツイートされているので、名が上位であることは納得。
河野さんくらい上位にヒットするワードが多いと傾向がつかめ、分析のしがいがあるといえる。


ちなみに私、河野さんの分析双方ともword_cloudするときに下記でfilterをかけている。

```R
frq_Zimin_exp_taro <- frq_Zimin_taro %>%
  filter(Info1 %in% c("名詞","形容詞","動詞")) %>% 
  filter(Freq > 10) %>% 
  filter(!(Info2 %in% c("数", "サ変接続", "一般"))) %>% 
  filter(!(Term %in% c("する", "いる", "ある")))
```

最終的には
"#(ハッシュタグ)"や、特定の言葉を含むツイートを取得したいからまだ道のりはながい・・・


今日はここまで！
MakerDAOの400万ドルGoxについて

MakerDAOが運営しているステーブルコイン発行のDeFiであるDaiについて、400万ドル余りの損失がネットワーク全体で発生したとの情報がありました。
今回はとりあえずそれについてまとめてみます。
参照: https://forum.makerdao.com/t/black-thursday-response-thread/1433
# 概要
　まず、昨日、Ethereumの価格が暴落しました。すると、送金が活発になったり、DeFiの担保が清算される前に取り除きたいとの思惑からネットワークが混雑します。普段は10Gwei程度がせいぜいのGas代も100Gweiを余裕で超えるまでネットワークが混雑します。
　ネットワークが混雑すると何が問題かというと、自分のトランザクションが取り込まれるのがいつになるのかわからなくなります。
　一方、MakerDAOでは価格が下落するとCDPと呼ばれる担保が清算されます。MakerDAOでは清算されるとETHが没収され、そのETHがDaiとの取引でオークションにかけられます。その上でETHをオークションで売ってDaiをもらい、そのDaiをBurnすることで、ETHの担保とDaiの発行量のバランスを保っています。つまり、ネットワーク全体で清算されたDai（Burnで消滅）とETH（売ることで消滅）がほぼ同量消え去ることでETHの担保を確保しています。
ここで昨日のような下落があると大量に清算され、オークションに大量のETHが流れます。
　さて、ここからが本番なのですが、この状況でオークションに参加したい人はどれくらいいるでしょうか？
 ネットワークが混雑しています。なのでいつ自分のBidのトランザクションが取り込まれるかわかりません。取り込まれた時果たしてETHはいくらになっているでしょうか？ 昨日の感じだと、ETHをゲットした時点でETHは多分相当値下がりしているはずだし、みんなそう予想します。さらにはGasが超高騰しているので迂闊にトランザクション投げるのもはばかられます。そうなった結果、オークションの参加者は一人だけになりました。
　その人は0Dai、つまり無料でETHを競り落とすことができます。そうしてこの人は400万ドルあまりのETHを引き出しました。おそらくGasをかなり高めに設定して意地でもトランザクションがすぐ通るように設定したのでしょう。（そうすると単純にGas代、例えば0.1ETHガスに設定して1ETH競り落とすと、ただただ0.1ETHと1ETHを交換したことになる）
　そうなるとどんな問題が生じるでしょうか？ Daiの価値は担保のETHとDaiの発行額のバランスに依存します。なので単純にDaiのネットワーク全体に悪影響が生じます。


# そもそもDaiとはなんなのか
そもそもDaiとはなんなのでしょう。Daiには二つの役割があります。

- 清算されたETHへのオークション参加券
- CDPを維持、解約するための料金

つまり、Daiの価値にはこの二つの役割が反映されることになります。
逆にいうとDaiにはそれ以上の価値はありません。
前者はざっくり言えばDai発行量とETH担保量の比率で価値が定まります。（つまりオークションへの参加券の枚数と商品の数の比率）
後者はCDPをどう動かしたいかに依存します。つまり解約したい人が多ければ多いほど、価格が上がります。

ここで重要なのは**Daiには価格がドルに近傍するメカニズムは理論的に存在しない**ということです。
Daiの価格は理論的には上記二つの要素が絡み合って決まります。
現に今、Daiの価格は上がっています。みんな清算される前にCDPを解約したいからです。

こいつが一ドル付近にいるのはマーケットがそう信じ込んでいるから、もしくは **偶然の産物** にすぎません。
MakerDAOにはStability Feeという税金のようなものがあり、それを上下させることで一応供給の長期的な操作は可能なのですが（税金が高ければ供給が下がる）、Auction参加券としての価値が変わるわけではないので、あまり意味がある施策とは思えません。(供給が減るとCDP解約などのための買い圧力は高まりますが、それよりもDai全体に被る負の外部生の方が大きいでしょう）


# なぜそんなことになったか
### オークションに最低入札価格がない
最低入札価格がなかったことで0 Daiでの入札を許してしまいました。
### オークションに参加しづらい
Daiは一般ユーザーからすればただのETHオークション参加券にも関わらず、ユーザーにとって参加障壁が高いため十分な参加者が集まりにくいことが考えられます。
### (少し本筋から離れますが）Daiの価格が遊離しやすい
本件とは関係ないのですが、これは重大な問題です。
Daiの重要なファクターとしてETH担保とDai発行量の比率の問題があります。ETHの比率が高いほどDaiのオークション参加券としての価値は上昇します。
しかし一方でETHオークションが多く開催される価格急下落局面（昨日今日とか）は、CDPの清算を防ぐためみんなDaiを買い集めます。するとDaiの価格が上がります。するとどうでしょう。
オークションでETH：Daiの比率を維持するのに十分なDaiがETHを売っただけでは集まらなくなります。また、自分のBidがチェーンに取り込まれるタイミングは少し先なのでそれを見越してETHの価格は過小評価される傾向にあります。
そうなるとどんどんETH：Daiの比率は下がっていきます。これを担保するための仕組みとしてLiquidity Feeという仕組みが備わっているのですが、Daiの価格が1.28ドル(3/13 13:30現在）まで行ってしまうとどこまで機能するかはわかりません。
また、そのニーズが終わった段階でETH:Daiの比率はどうなっているでしょうか。ETHの量が非常に低くなっていた場合、価格下落は避けられません。


# これからどうする可能性があるか
### Makerトークンを新しく発行してDaiで買ってもらいそのDaiをBurnすることでDai：ETH比率を元に戻す
Makerトークンを希釈し、その利益でDaiを買い戻すという戦略です。これは実行にうつされそうです。Makerトークンホルダーは損失を被りそうですが、そもそもCDPホルダー（債務者）からStability Feeという運営費を巻き上げているでMakerDAOがやらかした時は彼らがケツを拭くのが当然の流れでしょう。

### いったんクローズする
いったんDaiのコントラクト自体を止めて、清算するというやり方です。一応コントラクトには緊急停止機能がついていますが、そうするとDaiの時価総額はほぼ0になりますし、コミュニティ的にもダメージが大きいので最終手段でしょう。現状では否定しています

### オークションを使いやすくする
オークションに参加者がいないのが問題なのであれば使いやすくするという選択肢があります。

### 最低入札価格をつける
入札価格の最低値がないのが問題なので最低入札価格をつけるという選択肢があります。
組み込みのデータ型を勉強する(1)   リスト型

#本記事について
組み込みのデータ型のうちリスト型についてまとめる

・Python3を想定
・コードに対して説明が少なめ

#リストの基本情報
**定義**
・Pythonでリストを定義するには, [ ]を用いる. 
・[ ]の中に要素を並べ, それらを",(カンマ)"で区切る.

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey']
```

**要素の取り出し**

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey']
>>> animal[0]
'cow'
>>> animal[-1]
'fox'
>>> animal[1:3]
['horse', 'fox']
```
***要素入れ替え***

```python
>>> animal[0] = 'dog'
['dog', 'horse', 'fox', 'rabbit', 'monkey']
```
***要素の追加・削除***

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey']
>>> animal + ['dog', 'cat'] #要素の追加
['cow', 'horse', 'fox', 'rabbit', 'monkey', 'dog', 'cat']
>>> del animal[5] #要素の削除
>>> animal
['cow', 'horse', 'fox', 'rabbit', 'monkey', 'cat']
```

***リストの長さ***

```python
>>> len(animal)
5
```

#リストで使えるメソッド一覧
1) list.append(x)

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey']
>>> animal.append('dog')
['cow', 'horse', 'fox', 'rabbit', 'monkey', 'dog']
```

2)  list.count(x)

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey', 'cow']
>>> animal.count('cow')
2
```

3) list.reverse()

```python
>>> animal = ['cow', 'horse', 'fox', 'rabbit', 'monkey']
>>> animal.reverse()
['monkey', 'rabbit', 'fox', 'horse', 'cow']
```
知識ゼロから始めるTypeScript 〜関数編〜

## はじめに

[基本編](https://qiita.com/yukiji/items/52ea9106e254c1a12dea)の続きです。

TypeScriptシリーズ全4回連載中です:writing_hand:
[知識ゼロから始めるTypeScript 〜基本編〜](https://qiita.com/yukiji/items/52ea9106e254c1a12dea)
[知識ゼロから始めるTypeScript 〜関数編〜](https://qiita.com/yukiji/items/614ff63ade4072731750) :point_left:今ココ
[知識ゼロから始めるTypeScript 〜クラス編〜]
(https://qiita.com/yukiji/items/3db06601ece7f080b0d0)
[知識ゼロから始めるTypeScript 〜応用編〜]
(https://qiita.com/yukiji/items/e890053e62d2f7edc7c7)

関数の世界でTypeScriptがどう関わっていくのか。
そんな疑問を解決したい。

基本的には`引数`と`戻り値`この2点に型定義をしていく。

## functionキーワードの関数定義

- `引数`と`return`で返される値に型定義する

```js
function bmi(height: number, weight: number): number {
  // function 関数名(引数名: 引数の型定義): returnで返される型定義
  return weight / (height * height)
}
```

## 無名関数の関数定義

- 関数が格納された変数自体にも型定義する(なんかややこしい)

```js
let bmi: (height: number, weight: number) => number = function(
  height: number,
  weight: number
): number {
  return weight / (height * height)
}
```

## アロー関数による関数定義

- 少しスッキリ

```js
let bmi: (height: number, weight: number) => number = (
  height: number,
  weight: number
): number => weight / (height * height)
// アロー関数省略記法
```

## オプショナルなパラメータの定義

- 変数名の末に?を付与する事でオプショナルなパラメータの型定義ができる
- 下のコードの場合、第三引数に設定されたパラメーターはあってもなくてもエラーにはならない

```js
let bmi: (height: number, weight: number, printable?: boolean) => number = (
  height: number,
  weight: number,
  printable?: boolean
): number => {
  const bmi: number = weight / (height * height)
  if (printable) {
    console.log(bmi)
  }
  return bmi
}

bmi(1.75, 70)

// bmi(身長, 体重, console.logで出力するかどうか？)
// bmi(1.75, 70, true) 出力する
// bmi(1.75, 70, false) 出力しない
// bmi(1.75, 70) 出力しない
```

## デフォルトパラメータの設定

- 引数の値が未入力の場合のデフォルト値を設定できる。

```js
const nextYearSalary = (currentSalary: number, rate: number = 1.1) => {
  return currentSalary * rate
}

console.log(nextYearSalary(1000))
```

## RESTパラメータの設定

```js
const reducer = (accumulator: number, currentValue: number) => {
  console.log({ accumulator, currentValue })
  return accumulator + currentValue
}

const sum: (...values: number[]) => number = (...values: number[]): number => {
  return values.reduce(reducer)
}

console.log(sum(1, 2, 3, 4, 5))
```

## オーバーロード

- オーバーロードは関数の実体では型制約を行わない
- 下記の例では`number型`か`string型`のみ受け取れる

```js
//関数の前に書く
function double(value: number): number
function double(value: string): string

// 全ての型を受け取れるようにany型で定義
function double(value: any): any {
  if (typeof value === 'number') {
    return value * 2
  } else {
    return value + value
  }
}

console.log(double(100))
console.log(double('GO '))
console.log(double(true)) // コンパイルエラーになる
```

## まとめ

型の基本を抑えていればそこまで難しくなさそう:metal:
appsync aurora １つのリクエストマッピングテンプレートにかけるクエリは２つまで

appsync でデータソースにAuroraを指定してmutationを実行したら下記のエラーが出ました。

```
Only up to 2 queries are allowed in a template
```

リゾルバーのリクエストマッピングでSQLクエリを3つ書いていたので出たようです。。

3つ以上実行するときは、mutationを分けるかパイプラインリゾルバーかLambdaにすればよいのかと思います。

### 追記

ちなみにトランザクションは効かないみたいです。