OmniAICreator/Qiita-1.07M huggingface dataset:
lockとRlock

```py
import logging
import threading
import time

logging.basicConfig(level=logging.DEBUG, format='%(threadName)s: %(message)s')


def worker1(d, lock):
    logging.debug('start')
    
    #with lockのブロック内の処理が終わるまで他のスレッドは処理されない
    with lock:
        i = d['x']
        time.sleep(5)
        d['x'] = i + 1
        logging.debug(d)
        
        #main関数でlock = threading.Lock()とした場合は処理が進まなくなる
        with lock:
            d['x'] = i + 1
    logging.debug('end')

def worker2(d, lock):
    logging.debug('start')
    
    #lock.acuire()とlock.releaseで囲まれた部分の処理が終わるまで他のスレッドは処理されない
    lock.acquire()
    i = d['x']
    d['x'] = i + 1
    logging.debug(d)
    lock.release()
    logging.debug('end')


if __name__ == '__main__':
    d = {'x': 0}
    lock = threading.RLock()
    t1 = threading.Thread(target=worker1, args=(d, lock))
    t2 = threading.Thread(target=worker2, args=(d, lock))
    t1.start()
    t2.start()
```

```txt:出力
Thread-1: start
Thread-2: start
Thread-1: {'x': 1}
Thread-1: end
Thread-2: {'x': 2}
Thread-2: end
```
swiftのguardとは何か　超個人的メモ

まず、guardの構文について見てみよう

```swift
guard 条件 else {
    statements
}
```
If-elseのように見える。

guard構文は、EARLY EXITのために実装された。

なぜguardを使用するのか

例えば、guardを使用せずに、if-elseを利用すると以下だ。

```swift
if let username = usernameField.text, username != "" {  
    if let email = emailField.text, email != "" {
        if let password = passwordField.text, password != "" {
            // do awesome stuff here
        }
    }
}
// error handling here ...
```

何回もnilチェックを行う必要がある。
Guardを使うと以下のようにスッキリと書ける。

```swift

Guard let username = usernameField.text else {
  throw SignupError.NoUsername
}

Guard let email = emailField.text else {
  throw SignupError.NoEmail
}

Guard let password = passwordField.text else {
  Throw SignupError.NoPassword
}

print(“username: \username, email: \email, password: \password”)
```

読みやすいだろう

guardの目的はearly-exitなので、guardのelse文の中に複雑な処理を書くのはbad practiceです。

```swift
guard let doFoo = doFooProducer.doFoo else {  
  let productId = randomProducer()
  if productId == 3 {
     produceCar()
  } else {
     produceTree()
  }
   return
}
```

参考
https://medium.com/@chris_dus/the-guard-statement-in-swift-fdad41b08798
[SASS / SCSS] scssでメディアクエリを使って要素の大きさを動的に変えた

# やりたいこと
レスポンシブ対応をするにあたって、めっちゃ大量の要素のheightやwidthを「後から」変更しなくてはならなくなった...

```sample.html
<body class="sample">
  <div class="sample__item1">hi1</div>
  <div class="sample__item2">hi2</div>
  <div class="sample__item3">hi3</div>
  <!--
    省略
  --> 
</body>
```

```sample.scss
.sample {
  &__item1 {
    height: 100px;
    width: 200px;
    background-color: skyblue;
  }
  &__item2 {
    height: 50px;
    width: 100px;    
    background-color: green;
  }
  &__item3 {
    height: 80px;
    width: 160px;   
    background-color: #d5d5d5
  }
}
```

# やったこと
元々のスタイルを全てmixinに変更して、倍率を動的に渡すことにした

```sample.scss
@mixin style($multiplier) {
  .sample {
    &__item1 {
      height: 100px * $multiplier;
      width: 200px * $multiplier;
      background-color: skyblue;
    }
    &__item2 {
      height: 50px * $multiplier;
      width: 100px * $multiplier;    
      background-color: green;
    }
    &__item3 {
      height: 80px * $multiplier;
      width: 160px * $multiplier;   
      background-color: #d5d5d5
    }
  }
}

  @media screen and (max-width: 374px) {
    @include style(0.65);
  }

  @media screen and (min-width: 375px) {
    @include style(0.8);
  }

  @media screen and (min-width: 376px) {
    @include style(1);
  }

  @media screen and (min-width: 700px) {
    @include style(1.5);
  }

  @media screen and (min-width: 1024px) {
    @include style(2);
  }
```

# できたもの

- 動画
![media.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317515/5944b283-a04c-27ba-e968-d990af07f53d.gif)

- codepen
https://codepen.io/Wataru-boru/pen/abvNLBB
ncコマンド覚書

ちょいちょい `nc` コマンドを見かけたり、使ったりするがそのたびに、どういう動作するんだっけ、と調べるので、メモしておく。

### 概要
簡易なクライアント、サーバのプロセスを起動するコマンド。

次のように実行して、クライアントとして疎通確認を行う。
`nc 対象ホスト(IPアドレス等) ポート番号`

ヘッダを相手先ポートに送って、処理を実施させることもできる。
`echo -en "GET / HTTP/1.1\n\n" | nc 対象ホスト(IPアドレス等) 80`

### 接続先が生きているかの確認
ncの返り値で接続先が起動しているか確認することができる。
Dockerで接続先コンテナが起動するのを待つときに使いたい。

```bash
wait_for_port() {
  local name="$1" host="$2" port="$3"
  local j=0
  while ! nc -z "$host" "$port" >/dev/null 2>&1 < /dev/null; do
    j=$((j+1))
    if [ $j -ge $TRY_LOOP ]; then
      echo >&2 "$(date) - $host:$port still not reachable, giving up"
      exit 1
    fi
    echo "$(date) - waiting for $name... $j/$TRY_LOOP"
    sleep 5
  done
}
```

### リンク集
- [ncコマンドの使い方](https://qiita.com/hana_shin/items/97e6c03ac5e5ed67ce38)
- [ncコマンドでサービスの接続疎通確認](https://qiita.com/chenglin/items/70f06e146db19de5a659)
- [nc(netcat)コマンドで覚えておきたい使い方8個](https://orebibou.com/2015/11/ncnetcat%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E4%BD%BF%E3%81%84%E6%96%B98%E5%80%8B/)
- [puckel/docker-airflowのentrypoint.sh](https://github.com/puckel/docker-airflow/blob/master/script/entrypoint.sh)

ついでに多段sshする記事も

- [~/.ssh/configでSSHコマンドを快適化](https://odaryo.hatenablog.com/entry/2020/01/23/011253)
- [sshの活用法まとめ](https://qiita.com/ik-fib/items/0af46a19e3083bb0325e)

```
-W host:port
    Requests that standard input and output on the client be forwarded to host
    on port over the secure channel. Implies -N, -T, ExitOnForwardFailure and
    ClearAllForwardings, though these can be overridden in the configuration
    file or using -o command line options. 
```
さくらVPSにDrupal8のディストリビューション Lightning をインストールしたメモ

さくらVPSのLAMPスタートアップスクリプトはうまく動作していないようなので、スクリプト内を参考にしてインストールしたりするも、CentOS7系ではphpが5系になってしまったりで後々苦労するようだ。

結局自分でなんとかするしかない。
スクリプト冒頭で

```
yum -y install expect httpd-devel mod_ssl php php-devel php-pear mysql-server php-mbstring php-xml php-gd php-mysql

```
が実行されているが、php系はいらんので、

```
yum -y install expect httpd-devel mod_ssl

```
でとりあえず。

##PHPのインストール

普通にyumで入れると5系になってしまうのでリポジトリを指定してインストールする。

```
yum -y install --enablerepo=remi,remi-php73 php
```

以後、php73のリポジトリを指定してインストールしていけば、大体うまくいった。

##MySQLのインストール
DrupalのDBはMySQL系であれば問題ないので、MariaDBでもインストール可能。

```
yum install mariadb mariadb-server
```

あとphp-mysqlを入れとく。

```
yum -y install --enablerepo=remi-php73 php-mysql
```

##Composerでエラーを吐きまくる

LightningはComposerによるインストールを強く推奨されている。なのでComposerをインストールして、そこからインストールする。さくらVPSの契約状況によっては、メモリーが足りないだの何だのでエラーが出まくってしまう。

そこで、契約がメモリ4G以上ならphp.iniのmemory_limitを2Gに、メモリ2Gなら-1に一時的に設定してインストールをやり過ごすことにした。インストールが終わったら適当な値へ戻しておくべきだ。今回の環境ではメモリ2Gだったのでインストール中は-1にして、インストール後1Gに設定した。

無事モジュール類のダウンロードや展開が終わったところで今度はライブラリの依存関係でエラーを吐くので、下記ライブラリを突っ込んでおく。


```
yum -y install --enablerepo=remi-php73 php-xml php-gd php-pdo php-mbstring php-opcache
```

opcacheはインストール後にDrupalから「入れといた方がいいよ」って言われるやつだ。

##Drupalはすでにインストールされています

今回はまったのがこの現象。インストール後、どのURLを叩いてもインストール画面へリダイレクトしてしまい、すでにインストールされているというメッセージが出てしまう。

いろいろ原因があるっぽいんだけど、解決としては

```
[mysqld]
max_allowed_packet=16MB
```

する。設定はmy.cnfだ。


これでとりあえずサイトは表示されるようになった。キャッシュのおかげでそれなりにサクッと動いてくれている印象はあるが、Drupalはそれでなくとも割と重い子なので、ヘッドレス化するとかCDNを使って負荷をコントロールするとか、運用にはそれなりのノウハウが必要なようだ。

Lightningの記事が全然ないので、ここにメモしとく。
IEEE829から学ぶテストドキュメント～②テスト設計編～

# 1．概要

前回IEEE829のテストドキュメントを用いて、テスト計画書について説明いたしました。今回はテスト設計書について説明いたします。

ただ、IEEE829のテスト設計書は内容が薄いため、今回私の経験をもとに補足させていただきます。


#2．IEEE829のテスト設計書とは？

テスト計画書と同じくテスト設計書もレベル別のドキュメントがあります。（単体テスト設計書、結合テスト設計書など）。

ただ、レベル別に作ることもありますが、テスト手法ごと（組み合わせテスト、性能テスト、セキュリティテストなど）に作成することもあります。



#3．テスト設計書の考え方

テスト設計書は**テストの最重要ドキュメント**にあたり、**「どのようにして」テストを行うのか**決める工程でもあります。ここの良し悪しがその後にテストに大きく影響を与えるので、テスト担当者の腕の見せ所にもなります。

この工程で抜けや漏れが発生した場合、当然テストの抜け漏れにもつながるので、慎重に作成しなければなりません。

しかしながら、「どのようにして」テストをするかは以下の要因などに大きく左右されるので、フォーマット化が非常に難しいドキュメントでもあります。
**※人によっても「どのようにして」テストするかは、だいぶ変わってきます…**

- テストの実施期間 ⇒期間が短いとできるテスト・できないテストが出てくる
- テスト担当者のスキル　⇒スキルが低いと抜け漏れが発生しやすい
- 仕様などのドキュメントの有無　⇒仕様はコードです！は読み解くにのに時間がかかる

そのため、IEEE829のテスト設計書では、重要であるにも関わらず**記載する項目がテスト計画書と比べても非常に少なくなっています**。以下にIEEE829のテスト設計書の2章部分を記載します。

>2 レベルテスト設計詳細
　　2.1. テスト対象機能
　　2.2. アプローチの具体化　←ここが重要だか「具体化」の一言しかない…
　　2.3. テスト識別子
　　2.4. 合否基準
　　2.5 テスト成果物

そのため、実際の具体化の方法については、私の経験をもとに解説いたします。


#4．テスト設計書の作成方法

実際の現場では「どのようにして」テストを行うか決めているかというと、**何かの参考書を見ながら決めていることが多いです。**

例えば、

- ISO25010の品質特性（機能性、信頼性、使用性…）
- 過去に実施したテストドキュメント
- テスト技法の一覧表（組み合わせテスト、セキュリティテスト、性能テストなど）
- 具体的なテストケース一覧表（入力項目に「ああ」「*!"」「？」と入れる、など）

しかしながら上記は以下のようなメリット・デメリットがあるので、状況に応じて使い分けたり、組わせていることが多いです。

| 参考にする資料       | メリット | デメリット |
|:-----------------:|------------------|------------------|
|ISO25010の品質特性|テスト対象を広く浅くどのようにテストするのか考えることができる|品質特性は抽象的であるため、具体的なテストケースに落とし込むのにかなりの技量がいる|
|過去に実施したテストドキュメント|ものによってはそのまま流用できる |新規開発では役に立たないことが多い|
|テスト技法の一覧表|ISO25010より具体的なので、テストケースを作りやすい|セキュリティテストなどの特殊なテストを具体的にするのに技量がいる|
|具体的なテストケース一覧表|項目が具体化してあるので、テストケースの作成が容易|一覧表が膨大になりやすく、目的のケースを見つけるのに時間がかかる|



#5．まとめ

テスト設計書は**「どのような」テストを実施するのか決めるドキュメントであるため、ここの作成がテスト担当者の腕の見せ所となります。**

ただ、テスト担当者によって「どのように」テストをするのか考え方が違うことが多く、具体的なテスト設計書のフォーマットは作成されないことが多いです。（自由に記載していい「フリーフォーマット」だらけのドキュメントが多い）
Flutterでカウントダウンをなるべくシンプルに実装する

# はじめに
ひょんなことからFlutterでカウントダウンするコードを書くことになったのですが、色々なサンプル実装などを見ていて以下のような引っ掛かりがありました。

- `Timer`自体にはpauseするメソッドはない(カウントダウンのためのものではないため)
- `AnimationBuilder`を使っているためフレームごとでリビルドが起きており、長時間を計測する場合だと動作が重くなる
- `StreamBuilder`やら`bloc`パターンを使って実装しているけど、なんだか複雑に実装しすぎている
- かなり隅のコードなので`Provider`も使うのが億劫

ということで、諸々のパッケージを使わずにカウントダウンをなるべくシンプルに実装しました。

# 実装

留意点としては以下です。

- `Timer`自体には一時停止などの機能はないので、一時停止時には一旦破棄し、再生時に作り直す
- 実際の計算をするのは`currentSeconds`の役割
- `currentSeconds`が更新されない場合はカウントは進まない
- つまり、1秒以内の間隔で再生・停止を連打するとカウントは進まない
- これを進めたい場合は`milliseconds`単位で実装しなおせばよいですが、あまり現実的でないのと余計なリビルドの原因となるためしない方が良いと思います

```count_hoge.dart

class CountHoge extends StatefulWidget {
  CountHoge({Key key}) : super(key: key);

  @override
  _CountHogeState createState() => _CountHogeState();
}

class _CountHogeState extends State<CountHoge> {
  Timer _timer;
  int _currentSeconds;

  @override
  void dispose() {
    super.dispose();
    _timer.cancel();
  }

  @override
  void initState() {
    super.initState();
    final workMinuts = 5;
    _currentSeconds = workMinuts * 60;

    _timer = countTimer();
  }

  Timer countTimer() {
    return Timer.periodic(
      const Duration(seconds: 1),
      (Timer timer) {
        if (_currentSeconds < 1) {
          timer.cancel();
        } else {
          setState(() {
            _currentSeconds = _currentSeconds - 1;
          });
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          const SizedBox(height: 16),
          _timeStr(),
          const SizedBox(height: 16),
          _panel(),
        ],
      ),
    ));
  }

  Widget _timeStr() {
    return Text(
      timerString(_currentSeconds),
      style: TextStyle(fontSize: 32, color: Colors.black),
    );
  }

  String timerString(int leftSeconds) {
    final minutes = (leftSeconds / 60).floor().toString().padLeft(2, '0');
    final seconds = (leftSeconds % 60).floor().toString().padLeft(2, '0');
    return '$minutes:$seconds';
  }

  Widget _panel() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        GestureDetector(
          onTap: () {
            if (_timer.isActive) {
              _timer.cancel();
            }
          },
          child: SizedBox(height: 40, child: Icon(Icons.stop)),
        ),
        GestureDetector(
            onTap: () {
              if (!_timer.isActive) {
                setState(() {
                  _timer = countTimer();
                });
              }
            },
            child: SizedBox(height: 40, child: Icon(Icons.play_arrow))),
      ],
    );
  }
}
```

# 画面

<img width="444" alt="スクリーンショット 2020-04-17 11.15.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190157/70447b32-e541-ca66-5495-8fcd9562bf72.png">
コロナウィルス渦中の転職活動

# 転職活動の背景
一身上の都合により、1年前頃から転職することを決意しており、3月中に前職を退職。会社を辞めたものの、こんなにコロナショックが広まるとは。。。転職活動、大苦戦（汗）

# 経歴
・大学で情報系の学科を専攻
・7年間SIerの企業に勤める

# 利用した転職エージェント
・@Type
　求人数：○　エージェントによるフォロー：◎
・レバテックキャリア
　求人数：△　エージェントによるフォロー：◎
・マイナビエージェント
　求人数：◎　エージェントによるフォロー：×

# 転職活動の戦績
・応募：60社程度　
・書類選考通過：25社　
・WEBテスト落ち：2社
・一次面接落ち：9社
・最終面接落ち：3社
・選考辞退：9社
・内定：2社

# 応募先の職種
・ITコンサルタント
・一次請けSIer
・社内SE
・セールスエンジニア

# コロナショックによる転職活動
### メリット
・ほとんどの企業がWEB面接を導入しており、
　都内に住んでいない遠方の方も比較的面接を受けやすい。
　交通費も浮く。
・経験的に、WEB面接は、対面に比べて、踏み込んだ質問を聴きづらい。
　そのため、対面より、合格率は高くなりやすいと思う。

### デメリット
・採用活動を中止したり、延期したりする企業がある。
　応募していた企業の１～２割位はこのような状況であった。
・会社に訪問する機会が無いため、会社の雰囲気が分かりづらい。
　また、面接官の人柄も分かりづらい。応募企業への愛着心が湧かない。
・WEB面接用のソフトが固まることも少なくないため、
　予想外の心象度の評価ダウンが発生する可能性がある。

# WEB面接で利用したオンラインソフト
・skype
  画質：△　フリーズする割合：○（少ない）　導入する際の難易度：◎（楽勝）
・skype for Business
  画質：○　フリーズする割合：○（少ない）　導入する際の難易度：△（面倒）
・Teams
  画質：◎　フリーズする割合：◎（極めて少ない）　導入する際の難易度：○（簡単）
・zoom
  画質：◎　フリーズする割合：○（少ない）　導入する際の難易度：△（面倒）
・Hangouts Meet
  画質：◎　フリーズする割合：○（少ない）　導入する際の難易度：○（簡単）

※個人的には、トータル的にTeamsが一番使いやすかった。
UNIX時間について調べた【編集中】

【背景】SHOWROOMは日時にUNIX時間を使用している。Javascritpで対応するWebアプリの日時データの型を検討するたみに調査実施
　　　　Webアプリでは日時は。。。

UNIX時間は『「協定世界時の」1970年1月1日0時0分0秒からの累計秒』
[GMT、UTC、UnixTimeって何が違うの？](https://kiridaruma.hateblo.jp/entry/2018/02/10/233957)

JavascritpでUNIX時間に変換すのは下記で

```
Math.floor(Date.now() / 1000);
```
~~// Dateオブジェクトを作成~~
~~var date = new Date() ;~~

~~// UNIXタイムスタンプを取得する (ミリ秒単位)~~
~~var a = date.getTime() ;~~

~~// UNIXタイムスタンプを取得する (秒単位 - PHPのtime()と同じ)~~
~~var b = Math.floor( a / 1000 ) ;~~
※@vf8974さんに教えて頂きました。こちらが断然すっきりします


※下記から引用
[UNIXタイムスタンプを取得する方法](https://lab.syncer.jp/Web/JavaScript/Snippet/2/)
input関数,output関数


#問題
３人分の名前、生年月日のデータが入った構造体を定義し,それをinput関数によって読み込み,output関数によって表示する.
#試行錯誤

関数, ポインタが分かってなかったころの一番最初の回答（ひどい間違い）：

```C
#include<stdio.h>

#define NAME_LEN 20

struct birthday
{
    char name[NAME_LEN];
    int year;
    int month;
    int day;
};

void input(char name, int year, int month, int day)
{
    char birth[4];
    birth = {name, year, month, day};
}

void output(char name2)
{
    printf("%s", name2);
}

int main(void)
{
    struct birthday takao = {Takao, 1998, 7, 5};
    struct birthday kyoko = {Kyoko, 1996, 8, 1};
    struct birthday yuta = {Yuta, 1997, 3, 28};

    puts("【入力】");
    input(takao.name, takao.year, takao.month, takao.day);
    input(kyoko.name, kyoko.year, kyoko.month, kyoko.day);
    input(yuta.name, yuta.year, yuta.month, yuta.day);
    
    puts("【出力】");
    output(input(takao.name, takao.year, takao.month, takao.day));
    output(input(kyoko.name, kyoko.year, kyoko.month, kyoko.day));
    output(input(yuta.name, yuta.year, yuta.month, yuta.day));

    return 0;    
}
```

#正解

```C
#include<stdio.h>

typedef struct birthday
{
    /* data */
    char name[20];
    int year;
    int month;
    int day;
}Birthday;

void input(Birthday *);
void output(Birthday *);

int main(void){

    Birthday p[3];
    input(p);
    output(p);
    return 0;
}

void input(Birthday *man){
    int i;
    for ( i = 0; i < 3; i++)
    {
        /* code */
        scanf("%s\n ", man->name);
        scanf("%d %d %d", &man->year, &man->month, &man->day); 
        man++;
    }
}

void output(Birthday *man){
    int i;
    for ( i = 0; i < 3; i++)
    {
        /* code */
        printf("%-8s ", man->name);
        printf("%5d %2d %2d \n", man->year, man->month, man->day); 
        man++;
    }
}
```
#感想
・もっと言い書き方があるだろうと思う.
・`man++`がC言語っぽい.ポインタについてはまた詳しく学んだとき書き残したい.
・`void input(Birthday *);`
・`void output(Birthday *);`など構造体を宣言してしまえば,関数の引数として`int`など型をまた書かなくても良い.`Birthday *`のみで良いことが分かる.というか`Birthday`のなかに`char name[20]　int year　int month　int day`が入っているというイメージ.
#おまけ
・カルテシアンはデカルトの名前からとられたと知って、なるほど、と思った。
div 枠を付ける、ボックスを並べる、フレックスボックス

#枠を付ける

```

<div style="
text-align: center; /* 文字を中央揃え/* 
padding-top:15px;　/* 上の余白15px/* 
padding-bottom:15px;/* 下の余白15px/* 
background-color:#333333;
color: white;
margin: 0 20px 0 20px;/* 余白　上 下 右 左/* 
">
                メディア掲載実績
            </div>

```

#ボックスを並べる


```

 ul {
                padding: 0;
                justify-content: center;
                background-color: red;
                display: -webkit-flex;
                display: flex;
                list-style: none; /*黒点非表示/*
                flex-wrap: wrap; /端で折り返す/*
            }

 li {
                padding:5px;
                margin: 5px;
                background-color: white;
            }



 <div class="media-jisseki">


                <ul>
                    <li>
                        リスト1
                    </li>
                    <li>
                        リスト2
                    </li>
                    <li>
                        リスト3
                    </li>
                    <li>
                        リスト4
                    </li>
                    <li>
                        リスト5
                    </li>
                </ul>　

                

            </div>

```
#スタイル指定

```
.media-jisseki {

 background-color:#F5F5F5;padding-top:15px;padding-bottom:15px;margin: 0 20px 0 20px;
            }

class="media-jisseki"
で使える。

```

#真ん中に寄せたい

```
text-align: center
text-align: center !important
margin: auto
```
メモ: syncthing

```sh
docker pull linuxserver/syncthing
```

```sh
docker run \
  --name=syncthing \
  -e PUID=1001 \
  -e PGID=1001 \
  -e TZ=Asia/Tokyo \
  -e UMASK_SET=022 \
  -p 8384:8384 \
  -p 22000:22000 \
  -p 21027:21027/udp \
  -v $(pwd)/appdata/config:/config \
  -v $(pwd)/data1:/data1 \
  -v $(pwd)/data2:/data2 \
  --restart unless-stopped \
  linuxserver/syncthing
```

* [Windows Client](https://github.com/canton7/SyncTrayzor/releases)
* port 8384
Docker Engine API について

普通に Docker を使っている分にはあまり気にしなくてもいい領域だが、Docker in Docker などの使い方をすると、ここらへんの知識がないと理解できない。ので、そこらへんをまとめた記事。

> Docker Engine は、主に以下の 3 つのコンポーネントからなるクライアントサーバー型アプリケーションです。  
> 1. サーバー。長時間稼動する種類のプログラムでありデーモンプロセスと呼ばれる（ dockerd コマンド）。
> 2. REST API。プログラムとデーモンとの間での通信方法を定義し、何をなすべきかを指示する。
> 3. コマンドラインインターフェース（command line interface; CLI）クライアント（ docker コマンド）。

<img width="600" alt="server_client.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606419/65d8f3ca-a767-72a6-9c69-1ffcb22b9084.png">

1が右の Docker で、3が左の Docker で、2は真ん中の矢印。

いつも`docker run`とか`docker build`とか色々としているが、あれはただの Docker デーモンプロセスへの命令である。`docker`コマンドが実行された後は、Docker のデーモンプロセスを探しに行くのだが、Docker デーモンプロセスへの橋渡しは REST API によって行われる。REST API なのでエンドポイントがあるわけだが、たいていは`/var/run/docker.sock`にある。クライアントとサーバーが別のホストにいる場合(Docker in Docker など)、`tcp://docker:2376`や`tcp://docker:2375`にエンドポイントがある。

## REST API を curl で叩く

`docker run`は、いうなれば REST API を叩いているだけなので、`curl`でも叩ける。ので、叩いてみる。

REST API のバージョンを確認する。
REST API のバージョンは、DockerデーモンとDockerクライアントのバージョンによって異なる。クライアントとサーバーが同一のホスト内ではないとき、使用しているDocker Engine のバージョンが違う、ということはよくある。

```bash
$ sudo docker version
Client:
 Version:           19.03.6-ce
 API version:       1.40
 Go version:        go1.13.4
 Git commit:        369ce74
 Built:             Fri Mar  6 23:25:53 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.6-ce
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.4
  Git commit:       369ce74
  Built:            Fri Mar  6 23:26:25 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.2
  GitCommit:        ff48f57fc83a8c44cf4ad5d672424a98ba37ded6
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

`docker container ls`の REST API を叩こうと思うが、Docker コンテナが何もないとレスポンスが空になるので、適当に Docker コンテナを作成する。

```bash
sudo docker run -itd --name tmp ubuntu /bin/bash
```

`/var/run/docker.sock`にあるエンドポイントを使っていく。
`container ls`をしたいため、`http:/v1.40/containers/json`を叩く。

```bash
$ sudo curl --unix-socket /var/run/docker.sock http:/v1.40/containers/json
[{"Id":"9e36dbee56dbf11883143529799fa7e978109529e1094984d586828a4df9e8c8","Names":["/tmp"],"Image":"ubuntu","ImageID":"sha256:4e5021d210f65ebe915670c7089120120bc0a303b90208592851708c1b8c04bd","Command":"/bin/bash","Created":1586681448,"Ports":[],"Labels":{},"State":"running","Status":"Up 23 seconds","HostConfig":{"NetworkMode":"default"},"NetworkSettings":{"Networks":{"bridge":{"IPAMConfig":null,"Links":null,"Aliases":null,"NetworkID":"3e33a3326ed11a3ba0c20e1beabc2b968e5d75502c2a5c5f950aba07da1dbe9f","EndpointID":"f3b5ec738d21c9a0f7c52ba970cffd90773e0947a87965dee1b2fef6d2511770","Gateway":"172.17.0.1","IPAddress":"172.17.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:11:00:02","DriverOpts":null}}},"Mounts":[]}]
```

先ほど、作った Docker コンテナがレスポンスとして返ってきたのでOK。

## 参考
https://docs.docker.com/engine/api/
【JavaScript】配列の一部だけを合計して新しい配列を作る

変換前の配列：```array1 = [ 年, 月, 日, 人数1, 人数2, ... , 人数47 ];```
変換後の配列：```array2 = [ 年, 月, 日, 人数1～人数47の合計 ]; ```

つまり、人数を合計したい。

```javascript
let array2 = array1.slice(0, 3).concat(array1.slice(3).reduce((a, x) => { return a + x }));
```
axiosのdeleteでdataが送れない。

axiosのdeleteにpostやputのようにdataを以下のように入れてみる。

```js
const result = await axios.delete(url, data, config)
```

するとconfigのところにエラーが出てきました。

```
Expected 1-2 arguments, but got 3.
```

調べてみると以下のように  
axiosのdeleteにはdataを入れる引数が用意されていないようです。

<img width="853" alt="スクリーンショット 2020-04-17 10.44.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415529/d7d4ec72-fc5a-5e14-79b6-e985b6577990.png">

https://github.com/axios/axios/issues/736

ちゃんとした解決ではないかもですが
configの中にdataのオブジェクトを入れて送信すれば良いそうです。

<img width="881" alt="スクリーンショット 2020-04-17 10.45.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415529/cc6183ea-ee3b-06b2-cbbb-a9677c424333.png">


https://github.com/axios/axios/issues/897

よって以下のようにすればいいのかな。

```js
config.data = {sample: 'data'} // 入れたいデータ
const result = await axios.delete(url, config)
```
python正規表現で文字列が時刻かどうかを判定する

正規表現で0:00から23:59までを時刻として判定したい。
時、分ともに一桁の時と二桁の時に対応したい。

以下だと、29:59も時刻と判定してしまう。

``` python
re.match(r'([0-2]?[0-9]):([0-5]?[0-9])', '29:59')
<re.Match object; span=(0, 5), match='29:59'>
```

以下であれば期待通りの動作だった。

``` python
re.match(r'([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])', '23:59')
<re.Match object; span=(0, 5), match='23:59'>
re.match(r'([0-1]?[0-9]|2[0-3]):([0-5]?[0-9])', '24:00')
```

もし他に良い方法があれば是非コメント下さい!
効率的にDecisionLogを残す

#ステークホルダーとの会話記録を残して欲しい
決定事項（話の経緯）が作業者まで落ちてこない時がある。
「なぜ今この作業をしているのか？」→目的を理解しないまま作ると、ミスの原因になる。

声で話すと記録が残らないので議事録を取ってほしい。議事録役を立てるのが面倒な時は自動入力をしてほしい。

#自動入力のMacを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/5d062a4c-354a-08dd-cb2c-6d8ebc1ddacd.png)
議事録を取る人はスマホでCallingの会話に参加し、
同時にMacも議事録用に参加させてください。

#自動「音声→文字入力」のやり方
SoundFlowerをダウンロードしてインストールします。（Mac）
https://github.com/mattingalls/Soundflower/releases
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/9efd0c4d-c1a2-2c75-c728-4f89fcce6fe6.png)

#環境設定
セキュリティ設定でSoundFlowerを許可したら、
音声（入力・出力）両方を「マイク・スピーカー」ではなく「SoundFlower」にします。

###出力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/6cf76c5a-e3f5-dac5-9467-2bbd24a7e56d.png)

###入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/7680bec5-e75a-7f66-3d1a-f63441cebd5e.png)

#Callingに参加
ZoomでもSkypeでもなんでも良いです。
https://www.calling.fun/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/60960907-fe50-7dc4-c46f-0cc6662b15f6.png)

#Googleドキュメントの「音声入力」を開始
https://docs.google.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/9bcf2b34-9454-3d4d-4f5b-adbab6dd8cfb.png)

マイクのアイコンをクリックすると、Googleドキュメントが自動的に会話内容を文字にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/498efe1c-758a-4ed3-f8d8-9a865b9e8ef8.png)

#自動入力の仕組み
入力の仕組みは、以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/d0444370-3d2f-0eab-3394-4d99506c60e7.png)

#注意
議事録用Macは音がでなくなりますので、会話に参加するために、同時にスマホで参加して下さい。

#参考リンク
https://note.com/yriica/n/n3050888696ab
世にも奇妙で恐ろしいPythonのエラーの話

注）importの仕様には注意しましょうねという話で、初級者向けの内容です。

# Pythonでとある機能のテストをしていた時のこと。

昨日は動いていた次のサンプルコードが突然エラーを出すようになりました。
環境はpyenv+pipenv+python3.7+Google Cloud SDK
(Google Firestoreの書き込みを行うコードです)

```Python:insert.py
from google.cloud import firestore

db = firestore.Client()
db.collection(u'users').document().set({
    u'first': u'oda',
    u'last': u'nobunaga',
    u'born': 1534
})
```

エラーの内容は次のとおり

```shell
>> pipenv run insert
Loading .env environment variables...
Traceback (most recent call last):
  File "insert.py", line 1, in <module>
    from google.cloud import firestore
  File "/mnt/v01/workspace/sandbox-python-firestore/.venv/lib/python3.7/site-packages/google/cloud/firestore.py", line 18, in <module>
    from google.cloud.firestore_v1 import __version__
  File "/mnt/v01/workspace/sandbox-python-firestore/.venv/lib/python3.7/site-packages/google/cloud/firestore_v1/__init__.py", line 17, in <module>
    from pkg_resources import get_distribution
  File "/mnt/v01/workspace/sandbox-python-firestore/.venv/lib/python3.7/site-packages/pkg_resources/__init__.py", line 33, in <module>
    import platform
  File "/home/dev-user/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/platform.py", line 116, in <module>
    import sys, os, re, subprocess
  File "/home/dev-user/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/subprocess.py", line 140, in <module>
    import select
  File "/mnt/v01/workspace/sandbox-python-firestore/select.py", line 3, in <module>
    db = firestore.Client()
AttributeError: module 'google.cloud.firestore' has no attribute 'Client'
```

普段からPythonを愛でておられる方々は薄々感じていると思いますが、pyenvとpipenvを同時に使用している状況でのimport errorなので、嫌な予感がします。

けれど、昨日はちゃんと動いていたのです。gcloud authあたりも心配になってきます。

# ここで、奇妙な事に気づきます。

```shell
  File "/mnt/v01/workspace/sandbox-python-firestore/select.py", line 3, in <module>
    db = firestore.Client()
```

なぜか、

呼んでいないはずの./select.pyが登場しています。確かに、先ほどサンプルコードとして./にselect.pyを作成していました。

この./select.pyを削除するとプログラムは正常に動作するようになりました。

# 結局

処理中に使用されていたsubprocess.pyからカレントディレクトリのselect.pyが呼ばれてしまっていたようです。

今回は一人で作成していたサンプルプログラムだったから良かったのですが、Pythonで特にチーム開発している際はファイル名にも注意が必要なのかと、背筋に冷たいものが走ったエラーでした。
S3とCloudFrontで静的ウェブサイトホスティングをしてみた


コロナの影響で絶賛在宅勤務中のrisakoです:woman_tone1:
ずっと家にいると気持ちが落ち込んだり、運動不足気味になったりしてしまいます...
最近は、朝起きてすぐに犬の散歩に行ったり、部屋の陽のあたる場所で仕事をしてみたり試行錯誤しています笑

今日のテーマは「S3とCloudFrontで静的ウェブサイトホスティングをしてみた」です。
つまづいたところも多々あるので、自分の備忘録としても書いておこうと思います:writing_hand:

#ゴール
**Cloudfront経由でS3に保存した静的ウェブサイトを独自DNSで閲覧する。**

##事前に用意するもの
- 使用したい独自のドメイン名を取得しておく。（今回は仮にhoge.gaとします）
- S3バケットに静的ウェブサイトなど、閲覧したいものを入れておきます。(今回はtest.html閲覧することにします）

#まず初めにS3バケットの設定から
1. 作成したS3バケットのプロパティ→Static website hostingを開く
2. **「このバケットを使用してウェブサイトをホストする」**を選択し、インデックスドキュメント・エラードキュメントを入力する。（今回はindex.htmlとerror.htmlとしておきます。)
![スクリーンショット 2020-04-14 17.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429615/2a13db2e-95a1-46d1-c7e3-c42fffcdc755.png)

＊ブロックパブリックアクセスが全て**オフ**になっていないと設定できないので注意
3. バケットポリシーで、静的ウェブサイトの公開設定をする。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<your-s3-bucket>/test.html/*"
        }
    ]
}
```
一旦S3の設定は終わりです。

#次にCloudFront設定
Cloudfrontを作成する際は、Webを選択して作成する。
最低限、変更しなくてはいけない項目を記載します。

|Settings|Value|
|:------:|:---:|
|Origin Domain Name|作成したS3バケットを選択|
|Viewer Protocol Policy|Redirect HTTP to HTTPS|
|CNAMES|設定したいDNS（test.hoge.ga）|
|SSL Certificate|Custom SSL Certificate（取得したhoge.gaの証明書を選択）|

#Route53
1. 事前に作成しているドメイン（hoge.ga）にサブドメインを追加します。

|Settings|Value|
|:------:|:---:|
|タイプ|CNAME|
|値|作成したcloudfrontのDomain Name|

<img width="410" alt="スクリーンショット 2020-04-15 15.30.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429615/7e8966d8-6ec4-983f-99c4-b89b2115fc9e.png">


#アクセスしてみる
正常に表示されました。

<img width="427" alt="スクリーンショット 2020-04-15 18.38.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429615/b906eaf7-30a9-e310-5128-941a62b2c0b4.png">


#最後に
一見難しそうでしたが、理解すれば「なるほど」となるものでした！
今回でウェブサイトホスティングについてはもちろんのこと、改めてS3やCloudFrontの勉強になりました。
最後までご覧いただきありがとうございました:laughing::sparkles:

#参考

- https://aws.amazon.com/jp/premiumsupport/knowledge-center/s3-website-cloudfront-error-403/
- https://qiita.com/predora005/items/407dfe992e98d0369777
- https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/WebsiteHosting.html
railsのrack-attackで特定のURLにIPアドレス認証をするには

####はじめに
今回はrack-attackというgemを使って特定のURLをにIPアドレス認証をかけます。IPアドレス認証をするだけだったらいろいろな記事がありましたがなぜか特定のURLにだけかけたいという記事があまりなかったので忘れないよう記事にします。

##rack-attackをインストール
```ruby:gemfile
gem 'rack-attack'
```
次にbundleコマンドを実行します。

```ruby:
$ bundle install
もしくは
$ bundle install --path=vendor/bundle
```

###準備
config/application.rbに以下の一文を追加してください。

```ruby:config/application.rb
config.middleware.use Rack::Attack
```

次にconfig/initializersの中にrack_attack.rbという名前でファイルを制作してください。

```ruby:config/initializers/rack_attack.rb
class Rack::Attack
  # your custom configuration...
end
```

###IPアドレス認証
いよいよIPアドレス認証です。

```ruby:config/initializers/rack_attack.rb
class Rack::Attack
    OFFICE_IP_ADDRESS = 'xxx.xxx.xxx.xxx' #IPアドレス

  blocklist('only allow from office') do |req|
    req.path.match(%r{^/admin}) && (OFFICE_IP_ADDRESS != req.ip) #/adminのところは任意のページのURLに変えてください。
  end
end
```

これで特定のページ（例の場合は/admin）IPアドレス認証をかけることができました。

####おまけ Dos攻撃対策・ブラックリスト設定
rack-attackというgemはIPアドレス認証だけでなくDos攻撃やブラックリスト設定までできます。

Dos攻撃対策の場合

```ruby:config/initializers/rack_attack.rb
class Rack::Attack
        # 同一IPアドレスからのリクエストを5回/秒に制限
    Rack::Attack.throttle('req/ip', limit: 5, period: 1.second) do |req|
      req.ip
    end
    
    # 同一IPアドレスからのリクエストを100回/分に制限
    Rack::Attack.throttle('req/ip', :limit => 100, :period => 1.minutes) do |req|
      req.ip
    end
end
```

ブラックリスト設定の場合

```ruby:config/initializers/rack_attack.rb
class Rack::Attack
 　# 1.2.3.4からのアクセスを拒否する
    Rack::Attack.blocklist('block xxx.xxx.xxx.xxx') do |req|
      'xxx.xxx.xxx.xxx' == req.ip
    end
    
    # BadUAが含まれたUserAgentからのログイン画面アクセスを拒否する
    Rack::Attack.blocklist('block bad UA logins') do |req|
      req.path == '/login' && req.post? && req.user_agent == 'BadUA'
    end
end
```

もちろんブラックリスト設定とDos攻撃対策とIPアドレス認証をすべて同時にあることが可能です。

ここまで見てくれてありがとうございました。
参考にしたサイトのURLを貼っておくのでぜひそちらも御覧ください。
[Rails開発でDos攻撃を防ぐためにrack-attackを導入しよう](https://blog.nakamu.life/posts/rails-dos-rack-attack)


あと、ぼくが最近公開したwebアプリ[資格試験の質問サイト QUA](https://blog.nakamu.life/posts/rails-dos-rack-attack)もお願いします。利用者がほぼいません。
XcodeのAutoSigningでProvisioningProfileを手動更新

Xcodeのautosigningは便利なんですけど、デバイスを追加したときにちゃんとProvisioningProfileに反映されてるかわかんないな〜
ということありませんか？わたしはあります。
そういうときは手動で更新してあげることで
「あ！デプロイゲートにアップロードしたらデバイス追加されてねえ！！めんどくせえ！」
という事態を回避できます。

やり方
xcodeでターゲットを選んで「Signing & Capabilities」の「Provisioing Profile」のとこの(i)マークを押す
↓
ファイルのアイコンをデスクトップとか適当なとこにドラッグ&ドロップしてファイル名を確認
<img width="676" alt="xcode.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/95144/aa826197-1b54-ffd0-1f30-4722c3faea00.png">
↓
~/Library/MobileDevice/Provisioning Profiles
に該当ファイルがあるのでそれを削除
↓
xcodeでグルグルしはじめてProvisioning Profileを作成し始めるのでデバイスの更新完了

これでOKです。
とってもかんたん！！
Laravel 419エラー

#前提
Laravel 7

#本題
419エラーがでた時の解消法

例えば下記、Blade テンプレートで、以下のようなお問い合わせフォームを作成した場合。

```from.blade.php
<form action="{{action('ContactController@confirm')}}" method="post">

<input type="text" name="name">

<input type="text" name="email">

<textarea name="message"></textarea>

<input type="submit" value="Confirm">
</form>
```
この場合、下記のように419エラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594409/6db8bc9d-66ab-fd29-b427-52254e2593f7.png)


#解決法
BladeテンプレートにCSRF保護ができていないためエラーが発生します。
具体的には、@csrfを追加します。


```from.blade.php
<form action="{{action('ContactController@confirm')}}" method="post">
@csrf
<input type="text" name="name">

<input type="text" name="email">

<textarea name="message"></textarea>

<input type="submit" value="Confirm">
</form>
```

以上。
Vue.jsの子コンポーネントをリロード・再レンダリングさせる方法

Vue.jsで子コンポーネントを再マウントさせたい、子コンポーネントのステートをリフレシュさせたい。
そんなときの対処法。
まずは以下のような子コンポーネントがあります。

```vuejs:Child.vue
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">increment</button>
  </div>
</template>

<script>
export default {
  setup() {
    const count = ref(0)
    const increment = () => {
      count.value++
    }
    return {
      count,
      increment
    }
  }
}
</script>
```

## v-ifで再マウント

v-ifを使うことによってDOMでレンダリングされなくなり、再度活性化することで再計算されます。
単純にフラグだけを変えると再計算が行われない可能性があるので`nextTick`を利用してDOM更新を待って再計算を実行させます。

```vuejs:Parent.vue
<template>
  <div>
    <child v-if="resetFlag" ref="component" />
    <button @reset="reset">reset</button>
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  setup() {
    const component = ref(null)
    const resetFlag = ref(false)
    const reset = () => {
      resetFlag.value = true
      component.value.$nextTick(() => {
        resetFlag.value = false
      })
    }
    return {
      component,
      resetFlag,
      reset
    }
  }
}
</script>
```

## keyで再マウント
`v-for`でおなじみの`key`ですが、keyが変更される度にコンポーネントを破棄・再マウントという処理を利用することができます。
手軽に再マウントしてくれるのでこの方法が手っ取り早くて良いと思います。


```vuejs:Parent.vue
<template>
  <div>
    <child :key="resetKey" ref="component" />
    <button @reset="reset">reset</button>
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  setup() {
    const resetKey = ref(0)
    const reset = () => {
      resetKey.value++
    }
    return {
      resetKey,
      reset
    }
  }
}
</script>
```

## 最後に
https://jp.vuejs.org/v2/guide/components-edge-cases.html#強制更新
無償版 Microsoft Teams の Web 会議に Teams アカウントを持たないユーザーを招待する方法

企業向け Office 365 に含まれる有償版 Microsoft Teams であれば、予定表の機能で会議予定を登録するときに社外の人のメールアドレスを入れるだけで Teams アカウントを持たないユーザーでも会議に招待できる（会社の設定による）のですが（参考: [Microsoft Teams のアカウントを持たないユーザーを匿名ユーザーとして Web 会議に招待する | idea.toString();](https://idea.tostring.jp/?p=5123)）…、無償版 Microsoft Teams では予定表の機能が利用できません。

しかし！無償版 Microsoft Teams でも、相手がアカウントを持たないユーザーであっても簡単に Web 会議に招待することができます。

#会議をはじめる
まずは会議をはじめましょう。チームのチャネルの中で会議を開始しましょう。

左側のメニューから「チーム」を選択し、チームの一覧からチームを選択して任意のチャネルを選択します。Teams アカウントを持たないメンバーは会議開始後に招待するので、自分ひとりだけが参加しているチームでも大丈夫です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/4b443054-e172-1260-4a2c-26b520b773b6.png)

すると表示される右側の画面の下にあるチャットを開始するところから…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/f669e4c6-ca36-a0e2-7e8e-8514b648ecfe.png)
このカメラみたいなアイコンをクリックすると、次のように会議をはじめるメニューが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/0ed1fdc8-d3a6-1bc0-a035-92fb761b1919.png)
会議名を入れて「今すぐ会議」をクリックしましょう。これで会議をはじめられます。

#参加者を招待する
さて、本題です。

他の参加者を招待するには、会議の参加ユーザーの一覧メニューを表示し、「他のユーザーを招待」の横にあるチェーンみたいなアイコンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/53a3f22c-6ce2-aa6a-adf4-2b6b3ce65017.png)

そうすると、なにかがクリップボードにコピーされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/6534e673-4663-a545-3150-ce2a3ee81684.png)

このまま、新規メール作成の画面を開きます。メーラーはなんでも OK ですが、HTML 形式のメールを作成できるモードにしておきましょう。

メールの本文に Ctrl + V（ペースト）しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/5089eb1d-4bcb-0f83-d997-ce216b0cea9e.png)

これで会議に参加用のリンクを含んだメールを作成できましたので、好きな相手に送ります。相手は Teams のアカウントを持っていなくても大丈夫です。

##URL をテキストで送りたい場合…
どんなリンク先になっているかは「Join Microsoft Teams Meeting」を右クリックしてリンクのアドレスをコピーしておき…、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/b0303990-0534-3af6-7df5-0cdec134af0c.png)

本文にペーストすると確認できます。テキスト形式のメールで送りたいときは、この URL を送りましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/bc4c6f37-d23a-e89b-642f-41b2691f5edd.png)

ちなみに僕は、いつもは Microsoft Teams の会議チャットにペーストしたものを右クリックして URL だけを取得しています。この方法が手っ取り早いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/15407f19-4a21-3abe-16ca-db798401555f.png)

#会議に参加する
URL を受け取った相手が URL にアクセスし、画面の案内に沿って進むと次のような画面が表示されるので、名前を入力して会議に参加しましょう。相手が Teams アカウントを持っていない場合は、ブラウザでアクセスしてもらうことになるんじゃないかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/040a9fe5-06b6-0a85-e944-c15a86feff86.png)

##参加を許可する
Teams アカウントを持たないユーザーが会議に参加する場合は、会議に参加している方の許可が必要です。

会議のコントロールバーに通知が表示されたら、誰かが会議に参加しようとしています。参加させる場合は「参加許可」をクリックしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/35536527-d06e-afb8-ac67-b1db068fdf43.png)

また、複数人が同時に参加しようとしている場合には、一人ずつポチポチするのが手間になることもあります。そんな時は、参加しようとしているユーザーがユーザーの一覧に「ロビーで待機中」として表示されていますので、「すべて参加許可」をクリックすることで一括で許可することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/145c6498-094b-7c4d-d227-544f98193e2b.png)

#さいごに
ちょっとしたテクニックですが、知っておくと無償版 Microsoft Teams の Web 会議の用途が増えると思います。

レッツ！Join Microsoft Teams Meeting！！
Laravel formで送った内容を受け取りたい時に 「419 Page Expired」のエラーが出た話

# 目的

- ビューのbutton要素のクリックをトリガーとしてテーブル内のレコードを削除する処理をコーディングしたが「419 Page Expired」のエラーが発生し解決した話をまとめる

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# エラー内容

- ビューファイルからのボタンクリックがトリガーで指定したレコードを削除する機能を実装した。
- 削除ボタンをクリックしたところ、下記のエラー「419 Page Expired」が発生した。

    <img width="581" alt="スクリーンショット 2020-04-16 15.34.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/64799529-30e4-f1bc-43ca-8c0bb4a84f3e.png">

# 原因

- トリガーとなっているボタンが内包されているform要素内で`@csrf`を記載していなかった。

# 問題のコード

- 削除ボタンを実装しているビューファイルの一部を記載する。

    ```blade.php
    <form action="/delete" method="post">
        <button type="submit" class="btn btn-danger btn-sm">削除</button>
    </form>
    ```
- 下記のように修正することによりエラーは解消されて要素が削除された。

    ```blade.php
    <form action="/delete" method="post">
        @csrf
        <button type="submit" class="btn btn-danger btn-sm">削除</button>
    </form>
    ```
ECRにpushしたコンテナをECSFargateで使うVPCエンドポイントTerraform例


## 必要なエンドポイント
起動タイプに「Fargate」を利用している場合、ECRにあるコンテナを使うためには以下の3つのエンドポイントを作成する必要がある

1. ecr.dkr
dockerコマンドを実行するためのエンドポイント

2. s3
コンテナイメージをpullするためのエンドポイント

3. logs
CloudWatchLogsへログを送信するために必要なエンドポイント
awslogs(CloudwatchLogs)を利用する場合にのみ必要

エンドポイントのタイプが`"Interface"`の場合、エンドポイントのセキュリティーグループを作成し、ECSセキュリティーグループから`443`ポートの通信を許可する必要がある

参考:
[Systems Manager を使用したインターネットアクセスなしでのプライベート EC2 インスタンスの管理](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-systems-manager-vpc-endpoints/)
[エンドポイントを使用してプライベートサブネットでECSを使用する](https://dev.classmethod.jp/articles/privatesubnet_ecs/)

## Terraform例
```tf
/*
  VPC Endpoint for S3

  Endpoint for pulling container image.
 */
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.default.id
  service_name      = data.aws_vpc_endpoint_service.s3.service_name
  vpc_endpoint_type = "Gateway"
}

resource "aws_vpc_endpoint_route_table_association" "private_s3" {
  vpc_endpoint_id = aws_vpc_endpoint.s3.id
  route_table_id  = element(aws_route_table.private.*.id, count.index)
}

data "aws_vpc_endpoint_service" "s3" {
  service = "s3"
}

/*
  VPC Endpoint for ECR DKR

  Endpoint for executing docker command.
 */
resource "aws_vpc_endpoint" "dkr" {
  vpc_id            = aws_vpc.default.id
  service_name      = data.aws_vpc_endpoint_service.dkr.service_name
  vpc_endpoint_type = "Interface"

  security_group_ids  = var.ecr_dkr_endpoint_security_group_ids
  subnet_ids          = aws_subnet.private.*.id
  private_dns_enabled = true

  tags = var.tags
}

data "aws_vpc_endpoint_service" "dkr" {
  service = "ecr.dkr"
}

/*
  VPC Endpoint for logs

  Endpoint for sending logs to CloudWatch Logs
 */
resource "aws_vpc_endpoint" "logs" {
  vpc_id            = aws_vpc.default.id
  service_name      = data.aws_vpc_endpoint_service.logs.service_name
  vpc_endpoint_type = "Interface"

  security_group_ids  = var.logs_endpoint_security_group_ids
  subnet_ids          = aws_subnet.private.*.id
  private_dns_enabled = true

  tags = var.tags
}

data "aws_vpc_endpoint_service" "logs" {
  service = "logs"
}
```
sql-migrate PostgreSQLで環境変数を利用した設定例

## 公式リポジトリ

https://github.com/rubenv/sql-migrate


## 設定例
```yml:dbconfig.yml
development:
  dialect: postgres
  dir: migrations
  table: migration
  datasource: host=${DB_HOST} port=${DB_PORT} dbname=${DB_DATABASE} user=${DB_USERNAME} password=${DB_PASSWORD} sslmode=disable
```

* `dir` マイグレーションファイルを作成するディレクトリ
* `table` マイグレーションテーブルの名前。省略した場合デフォルトの`gorp_migrations`になる
SwiftUIでのViewの扱いについて

#SwiftUIでのViewはどういうポジション？？
##環境
macOS Catalina 10.15.5 Beta(19F53f)
Xcode 11.4.1
##現状
自分は`SwiftUI`が出る前の`Swift4`を以前に学習していました。
それで最近になって再びアプリを作らないといけない状況になり[公式のチュートリアル](https://developer.apple.com/tutorials/swiftui/)を参考にして`SwiftUI`の勉強また、詰め込めこみきれていない`Swift`について勉強しています。

チュートリアルを進め、現在は[Handing User Input](https://developer.apple.com/tutorials/swiftui/handling-user-input)に入りました。

##`@State`? `@EnvironmentObject`?
`@State`とは？ `@EnvironmentObject`とは？ という前に
`Swift`をチュート半端にやっていた自分は`@`の意味がわかりませんでした。
なので調べ「プロパティ同士の関係付のための何か」と、なんとも曖昧な結論になりました。

そして改めて`@State`や`@EnvironmentObject`について調べました。
`@State`は「*UI*の状態をプロパティに紐付けする」
`@EnvironmentObject`は「複数の*View*でインスタンスを共有する」ものなのだと理解しました。

##質問
`@EnvironmentObject`の説明で「複数の`View`で...」という説明がありましたが、
プログラムは*class*単位で作っているものだと思い込んでいた自分からすれば
`@EnvironmentObject`の説明はなんとも引っかかります。

**`swiftUI`においてアプリの構成は*View*というものなのですか？？**
だとしたら確認なのですが
***View*一つと対応しているのは*PreviewProvider*を準拠している*struct*とということでいいのですか？**
そこのところ質問したいです。

あと
`@EnvironmentObject`を追加すると

```
struct LandmarkList_Previews: PreviewProvider {
    static var previews: some View {
        LandmarkList()
            .environmentObject(UserData())
    }
}
```
のように**`.environmentObject()`を追加しているのですがこれは何をやっているんですか？**
あと、あと**`@`の理解について、間違っていますか？**


すいません最後に質問をまとめます。
1. **`swiftUI`においてアプリの構成は*View*というものなのですか？？**
2. ***View*一つと対応しているのは*PreviewProvider*を準拠している*struct*とということでいいのですか？**
3. **`.environmentObject()`を追加しているのですがこれは何をやっているんですか？**
4. **`@`の理解について、間違っていますか？**
どの質問も*yes/no*ではなく解説をしていただきたいです。
あれ･･･実行しているプロセスが表示されない？の理由


# はじめに

ConohaVPSなどで，VPSを借り，自分のPCのVSCodeなどからSSHでアクセスをすることができます．
このとき，VSCodeの端末とシェルが，インターネットを通じてVPSの端末につながることになります．


このとき，例えば

```bash
$ nohup python main.py &
```

のnohupコマンドを用いることで，VPSのバックグラウンドで処理を実行し，かつVSCode側の端末を閉じても処理を継続することができます．

VSCode側を閉じる前は
```bash
$ ps
```

psコマンドで，pythonが実行されていることが確認できます．

# 問題点

VSCode側の端末を閉じた後，再びVPSにつなぎ直すと

```bash
$ ps
  PID TTY          TIME CMD
28883 pts/0    00:00:00 bash
29006 pts/0    00:00:00 ps
```

上記のようにPythonの実行コマンドが消えています･･･
このとき，自分は「端末を閉じてしまったからnohupコマンドでもプロセスが落ちてしまうんだ･･･」と思っていました＞＜

# 原因

VSCode側の端末を新しく開いているため，この新しい端末のシェルから発生したプロセスのみ，ps単体のコマンドでは表示されます．
そのため，閉じてしまった端末でnohup実行していたプロセスは，端末を失った状態で実行されておりpsでは表示されませんでした．


```bash
$ ps aux
```
と打つと，

- a 自分以外のユーザのプロセスも表示
- x　今の端末以外のプロセスも表示
- u ユーザーフォーマットで表示

とより詳細な情報が表示されます．


```bash
$ ps aux | grep python
root       652  0.0  0.0 267080     4 ?        Ssl  Apr16   0:00 /usr/libexec/platform-python -s /usr/sbin/firewalld --nofork --nopid
root       952  0.0  0.0 424304   280 ?        Ssl  Apr16   0:09 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P
root     28572 31.3 32.7 538180 160184 ?       R    07:47  17:45 python make_plot_chart_about_fail.py
root     28989  0.0  0.1  12108   972 pts/0    R+   08:43   0:00 grep --color=auto python
```

上記のように，auxの場合でpythonを実行すると，きちんとpythonコマンドがバックグラウンドで端末を失いながら，頑張っていました＞＜
ありがとう･･･ありがとう･･･（藤岡弘）


# まとめ

- ps auxのほうが情報量が多い（ほかのプロセスや詳細情報を知りたいなど，時と場合ですね）
- Linuxの知識をもっとつけよう･･･！

# 参考文献

- https://eng-entrance.com/linux-process
- https://webkaru.net/linux/ps-command/
- https://qiita.com/toshihirock/items/565fe71d778d3ee36b96
docker-compose で 環境変数で port を切り替える例 ( #docker )

# docker-copose.yml

- 変数を指定する
- docker container の 3000 が expose されている状態
- デフォルトでは 4000番 port を外部に公開する例

```
version: '3.0'

services:
  app:
    ...(色々省略)...
    ports:
      - ${APP_PORT:-4000}:3000
```


# .env 

.env ファイルに以下を設定

APP_PORT=5000

# 実行

```
docker-compose up
```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/3077








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
仮想通貨と仮想通貨トークンの違い

##違いが分かりにくい

自分は過去に、技術者以外の人に「仮想通貨と仮想通貨トークンの違い」を聞かれて、すぐには説明が上手くできなかった事がありました。

なので、仮想通貨と仮想通貨トークンの違いについてこの記事で解説していこうと思います。

まず、仮想通貨トークンについて理解するために、予備知識としてスマートコントラクト通貨についてまず解説していきます。

##スマートコントラクト通貨とは?

スマートコントラクト通貨を理解するために、まず、仮想通貨について再確認します。

仮想通貨は、「ブロックチェーンで作られた通貨」です。

ブロックチェーンは、「通貨」だけではなく、「サーバ」も作る事ができます。

そうした「ブロックチェーンで作られたサーバ」が、スマートコントラクト通貨です。

そして、ブロックチェーンは、「特定の管理者がいない分散型のシステム」を作る技術です。

そのため、スマートコントラクト通貨も、「特定の管理者がいない分散型のサーバ」になっています。

スマートコントラクト通貨は複数あり、その中では「イーサリアム」が最も有名です。

##仮想通貨トークンとは?

前述した「スマートコントラクト通貨」は、「ブロックチェーンで作られたサーバ」であり、様々なプログラムを動かす事ができます。

スマートコントラクトの上では電子マネーのプログラムを動かす事ができ、それらは「仮想通貨トークン」と呼ばれます。

そして、スマートコントラクト通貨は、「特定の管理者がいない分散型のサーバ」でもあります。

そのため、スマートコントラクト通貨の上で動く仮想通貨トークンも「特定の管理者がいない分散型の電子マネー」になっています。

そして、スマートコントラクト通貨の一つである「イーサリアム」の上で動く電子マネーの事を、「ERC20トークン」と呼びます。

ERC20トークンが、現在、最もメジャーな仮想通貨トークンの規格だと思います。

##仮想通貨と仮想通貨トークンの違い

仮想通貨は、「ブロックチェーンで作られた通貨」です。

仮想通貨トークンは、「ブロックチェーンで作られたサーバの上で動く電子マネー」です。

両方共、機能的には大した違いはありません。

にも関わらず、「仮想通貨トークン」が作られた理由は「お手軽」だからです。

仮想通貨トークンは、「ブロックチェーンで作られたサーバ」の上で動くため、自前のブロックチェーンを作らなくて済み、開発の手間が減るのです。

例えるなら、自分で家を建てるより、アパートを借りた方がお手軽、といったイメージに近いです。

##仮想通貨トークンの作り方

仮想通貨トークンのプログラミングを自分で学習して作ろうとすると、高い学習コストがかかります。

そのため、ここでは、プログラミングなしで仮想通貨トークンを作る方法を説明していきます。

＊＊＊以下のサービスは諸事情により、閉鎖しました。

プログラミングなしで仮想通貨トークンを作るには、自分が開発した「[TokenMaker](https://tokenmaker.site/)」というサービスが使えます。

有料サービスで、0.025eth(2020/1/31時点で497円)ほどかかります。

クラウドワークスで人間に外注したら、数千円から数万円は取られると思われるため、お得な値段だと思います。

詳しい使い方は、「[プログラミングなしで仮想通貨トークンを作れるサービスを作ったので解説する](https://qiita.com/SNS_Craftsman/items/10d3cc909ccf6bfb433a)」という別記事にまとめてあります。
QuickSightのデータソース作成(CLI)

## QuickSight セットアップイメージ

![qsflow1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/c9aa550a-2c3b-c3d0-25cd-d5c3c3af23aa.png)


### データソースとは

QuickSightがアクセスする外部データストアの設定です。QuickSightはS3やRedshiftやオンプレミスのRDBなど様々なデータストアに接続し可視化することができます。S3をデータソースにした場合は、マニフェストファイルでデータの場所を指定します。RDBなどのデータベースをデータソースにした場合は、テーブルや認証情報などの接続情報を指定します。また、それぞれのデータソースにアクセス許可の設定も行えます。今回はS3をデータソースにします。

### データソース定義JSON

新しいファイルをターミナルで作成します。Cloud9に以下のコードをコピーし、create-development-data-source.jsonというファイル名で保存します。これはこのあとでるS3マニフェストファイルの指定やアクセス許可を定義しています。
`<your aws account>`、`<your iam user name>`は自身の値に置き換えます。

```json
{
    "AwsAccountId": "<your aws account>",
    "DataSourceId": "Development-Data-Source",
    "Name": "Development Data Source",
    "Type": "S3",
    "DataSourceParameters": {

        "S3Parameters": {
            "ManifestFileLocation": {
                "Bucket": "quicksight-development-lab-<your aws account>",
                "Key": "S3-development-manifest.json"
            }
        }
    },
    "Permissions": [
        {
            "Principal": "arn:aws:quicksight:us-east-1:<your aws account>:user/default/<your iam user name>",
            "Actions": [
                "quicksight:UpdateDataSourcePermissions",
                "quicksight:DescribeDataSource",
                "quicksight:DescribeDataSourcePermissions",
                "quicksight:PassDataSource",
                "quicksight:UpdateDataSource",
                "quicksight:DeleteDataSource"

            ]
        }
    ]
}
```

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

新しいファイルをターミナルで作成します。Cloud9に以下のコードをコピーし、S3-development-manifest.jsonというファイル名で保存します。これはS3マニフェストファイルと呼ばれS3上のファイルの場所を示すものです。
`<your aws account>`は自身の値に置き換えます。

```json
{
    "fileLocations": [
        {
            "URIs": [
                "https://quicksight-development-lab-<your aws account>.s3.amazonaws.com/Patient-Info.csv"
            ]
        }
    ],
    "globalUploadSettings": {
        "textqualifier": "\""
    }
}
```

マニフェストファイルをS3バケットの quicksight-development-lab-`<your aws account>`にアップロードします。

```bash
$ aws s3 cp ./S3-development-manifest.json s3://quicksight-development-lab-<your aws account>
```

## データソース作成

create-development-data-source.jsonを作成したフォルダで次のコマンドを実行し、データソースを作成します。

```bash
$ aws quicksight create-data-source --cli-input-json file://create-development-data-source.json
```

以下のような出力があれば成功です。

```json
{
    "Status": 202,
    "DataSourceId": "Development-Data-Source",
    "RequestId": "35260608-bc7c-479c-8dbf-0eac88b2952f",
    "CreationStatus": "CREATION_IN_PROGRESS",
    "Arn": "arn:aws:quicksight:us-east-1:<your aws account>:datasource/Development-Data-Source"
}
```

画面の最下部に作成したデータソースのDevelopment Data Sourceが表示されます。

![qs-top2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27932/8c3dc320-8bea-4d9e-b9af-268ffcc6b382.png)

コマンドラインでもデータソースの詳細を確認できます。

```bash
$ aws quicksight describe-data-source --aws-account-id <your aws account> --data-source-id 'Development-Data-Source'
```