OmniAICreator/Qiita-1.07M huggingface dataset:
.ignoreって何？

# .ignoreって何？
プロジェクトビルドやプログラム実行時に生成されるファイルってめんどくさいですよね
.ignoreはファイル管理システムにコミットするとき項目から除くときに使われるファイルです。

# やってみよう
自分はバックエンドエンジニアでIntelliJをよく使うので、今回はIntelliJ基準で話していきます。

1．プロジェクト生成後に「ctrl＋shift＋A」を押すと以下のような画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/72a0f713-29d9-ca3e-21a8-ca8d5c918db2.png)

Actionのところに「plugins」と入力してEnterを押しましょう。

2．plugins画面で「.ignore」を検索します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/17b7f8a3-016e-2d72-5cf1-bb02db06520d.png)

そうなると上記の画像が表示しれます。（自分はすでにインストール済みなので「installed」と表示されます。）

3．installします。
重要なのはプラグインをインストールすると、必ずIDEを再起動する必要があります。

4．.ignoreファイルの作成
インストールも終わったし、ファイルを作成しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/63df5e2f-4d1d-5e77-aac0-d9991b921e3f.png)
上記のようにプロジェクトを右クリックして「.ignore」を生成します。

5．ファイル除きましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684074/869e5532-ce50-2ba4-7623-c8d1b850b141.png)
自分のプライベートプロジェクトでは「.gradle」「.idea」が必要ないので（普通これのみです。（実行時に生成されるファイルのため。））書いておきました。

これで今日は.ignoreが何なのか、IntelliJではどうやって使うのかについて調べてみました。

業務ではプロジェクトを生成してルールを決めたり、最初の環境を作成したりことがなかったので、知らなかったのですが、
今回プライベートプロジェクトで身に着けることができてうれしいです。
PythonでABC175 Dを解く

### はじめに
タイトルにPythonとありますが、PyPyを使わないと間に合わないです。
**どうみてもタイトル詐欺です。本当にありがとうございました。**
~~うるせぇ、PyPy使わせろ~~

### [D - Moving Piece](https://atcoder.jp/contests/abc175/tasks/abc175_d)

**考えたこと**
似た問題が最近のABCに出ていました。過去問と今回の問題の大きな違いは、グラフの形が6みたいな形なのか、円なのかです。過去問は6みたいな形だったのでサイクルに入るタイミングも記録する必要がありました。しかし、今回の問題はグラフの形が円になります。

与えられるグラフがサイクル(閉路)を持つ理由:
与えられるグラフがサイクルを持たないとすると、グラフは木になり、子ノードを持たないノード(行き先がないノード)が存在することになる。しかし、条件より$P$は$N$の順列なので、子ノードを持たない($P_i$が空)は存在しない。よって与えられるグラフはサイクルを持つ

与えられるグラフの形が円になる理由：
与えられるグラフの形が円ではないと仮定する。上記より与えられるグラフはサイクルを持つ。円でないサイクルの始点は二つのノードと結ばれている(行き先が一緒⇔$P_i = P_j (i \neq j)$が存在する)。
しかし、条件より$P$の要素は$N$の順列なので、$P$の要素が複合することはない。よって、二つ以上の点と結ばれている点は存在しないので、与えられるグラフは円になる。

サイクルを調べるときは、DFSなどで使うような探索済リストを作って更新していくのが楽だと思います。

あとはスコアの処理をするだけです。
最初は、(周れるだけ周る+余りの回数で最大となるマス動くとき、一周しかしないとき)で更新すれば良いと思っていました。この嘘に気付かずに2時間くらい溶かしました。これだと次のようなテストケースで落ちます。

```
3 6
2 3 1
5 5 -9
```
グラフは、1→2→3→1でループします。最初の考えだと、3→2→1で答えは10になります。これは間違いで、正しい答えは11になります。
このケースの正解は、3→1→2→3→1→2となって11です。
最初の考えだと、2周+1マス or 2マスの二択になります。2周+1マスの場合は7、2マスの場合は上の通り10になります。正解は1周+2マスです。

よって、正しい更新は、(周れるだけ周る+余りの回数で最大となるマス動くとき、一周しかしないとき、**周れるだけ周る-1+余りの回数で最大となるマス動く**とき)になります。
あとは実装するだけです。

ansの初期値が-infなのは、0にすると答えが負になるときに0回移動が答えになるからです。

```python
n, k = map(int,input().split())
p = list(map(int,input().split()))
c = list(map(int,input().split()))

ans = -float('inf')
for i in range(n):
    score = []
    check = [0] * n
    now = i
    cycle = 0
    for _ in range(k):
        go = p[now] - 1
        if check[go] == 1:
            break
        now = go
        if len(score) == 0:
            score.append(c[now])
        else:
            score.append(score[-1] + c[now])
        check[now] = 1
        cycle += 1

    t = k // cycle
    m = k % cycle

    sum_cycle = score[-1]
    if m == 0:
        ans = max(sum_cycle * t, sum_cycle * (t - 1) + max(score), max(score), ans)
    else:
        ans = max(sum_cycle * t + max(score[:m]), sum_cycle * (t - 1) + max(score), max(score), ans)

print(ans)
```

### さいごに
テストケースを教えてくれた、Ryukiさんありがとうございました。
楽しい問題でした。ではまた、おやすみなさい。


<blockquote class="twitter-tweet"><p lang="und" dir="ltr">3 7<br>2 3 1<br>5 5 -9</p>&mdash; Ryuki (@e145755) <a href="https://twitter.com/e145755/status/1295004065663868930?ref_src=twsrc%5Etfw">August 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Flutter備忘録】DataTableを親Widgetに収まるように配置する


# はじめに

`Flutter`を利用したアプリ開発をやっている中で
個人的に詰まった部分を定期的に記事にしていこうと思います。

# DataTableとは
- `Flutter`の`Widget`の一つでデータをいい感じに複数に分割してくれるもの

 ↓こんな感じのやつ
 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360479/50993f01-c69b-fdd1-6152-3661b6ceeb93.png" width=50%>

- [Flutter公式](https://api.flutter.dev/flutter/material/DataTable-class.html)




# どこで詰まったか
公式のものや、記事にあるものをいくつか試したが、
↓のように余白が空いてしまったり、画面に収まらなかったりした。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360479/7201043f-8ab1-0936-08c5-504831927eb2.png" width=50%>

# 試したが意味のなかったもの(自分には使えなかったもの)
- `ConstrainedBox`を使って横幅を固定した→`Datatable`の一つの要素にしか適用されなかった
- `Container`で`DataTable`を囲って`width`を固定→同上 

(他にも色々試したが自分にはよくわからなかった....)



# 解決策
以下のように`SingleChildScrollView`の子要素として`FittedBox`を設定し、
その子要素に`DataTable`を入れることで画面内にデータが均等に収まった。

`FittedBox`とは
>Widgetが親のサイズに収まりきらない時に子Widgetが収まるようにしてくれるもの

`SingleChildScrollView`とは
>Widgetが端末の縦サイズを超えたらスクロールしてくれるもの

```dart:data.dart
 SingleChildScrollView(
   scrollDirection: Axis.vertical,
   child: FittedBox(child: data(documents)));
```

```dart:datatable_widget.dart
 Widget recordData(documents) => DataTable(
          columns: const <DataColumn>[
            DataColumn(
              label: Text(
                "hoge",
                style: TextStyle(fontStyle: FontStyle.italic),
              ),
            ),
         ],
          rows: documents
              .map<DataRow>((document) => DataRow(cells: <DataCell>[
                    DataCell(Text(document["hogeData"]),
                        showEditIcon: false, placeholder: false), 
                  ]))
              .toList());
```

# 最後に
とりあえず親おさまらない時は`FittedBox`を使えばいいことを今回は認識した。
今回が初投稿かつFlutter初学者なので使い方や説明について間違っていたらすみません。
(その時はコメントの程よろしくお願いします)

# 参考文献
(↓とても参考になりました！)
[Flutter DataTable remove extra padding](https://stackoverflow.com/questions/55271153/flutter-datatable-remove-extra-padding)
[SingleChildScrollView](https://www.egao-inc.co.jp/programming/%E3%80%90flutter%E3%80%91%E7%AB%AF%E6%9C%AB%E7%B8%A6%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E8%B6%85%E3%81%88%E3%81%9F%E3%82%89%E8%87%AA%E5%8B%95%E3%81%A7%E3%82%B9%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AB/)
[FittedBoxについて](https://bukiyo-papa.com/fittedbox/)
サーバーのトラブルシューティングについて

サーバーの管理業務の中で最も時間を費やすのが**トラブルシューティング(障害対処)**である。

「障害」と一口にいっても、ソフトが起動しなくなった、サーバーが応答しなくなった、サーバーの部品が故障したなど、トラブルの種類を挙げればキリがない。

ただ、**トラブルに共通するのは「正常に動作しているときに提供されていた機能が使えなくなっている」**ということ。

トラブルシューティングでやるべきことは、この**使えない状態を「正常に動作していた時点の状態に戻す」という作業**になる。


#トラブルシューティングの進め方

基本的なアプローチは以下になる。

**step① 障害箇所を特定する**

**step② 障害要因の「仮説」を立てて、検証する**

**step③ 障害の発生箇所を絞り込み、障害要因を取り除く**

このステップを正しく踏むためには、「トライ＆エラー」を繰り返すしかない。


##step① 障害箇所を特定する

障害が発生したときは、慌てずに問題点を絞り込まなくてはいけない。

- どのような現象が起きているのか 

- いつから起きているのか(いつ気づいたのか)

- 誰が、何(どんな操作)をしたときに起きるのか

- 同じく稼働している他の環境で同じ問題は発生していないか


この作業はビジネスでよく言われる**「5W1H」のアプローチ**に似ている。

######※ 特定の過程の中で、以下の２点の情報を収集しておくことが望ましい。

- エラー発生段階：エラー画面
- 問題の特定段階：実際に使っている環境の動作(画面)


##step② 障害要因の「仮説」を立てて、検証する

発生した問題に対する環境が理解できていれば、「これが要因かもしれない」という「かもしれない(＝可能性)」がいくつか浮上する。

この「かもしれない」がそろったら、これを断定できるよう検証するのが次の段階になる。

※ この確認段階では、問題を解消するためにあれこれと設定を変更することが多いので、「どの箇所をどう変更したか」を正確に記録しておく必要がある。

##step③ 障害要因を取り除く

「障害の要因(かもしれない)」という箇所を洗い出し、１つ１つ検証していけば、最終的に「真の障害要因」に辿り着く。

実際の現場では、障害の解消方法が単一であることは少なく、複数の解消方法が存在することが多い。その場合は「どの解消方法が一番簡単か(＝時間がかからないか)」、「どの解消方法が再発の可能性が一番低いか(＝根本的な解決に繋がるか)」を考慮して、状況によって使い分けていくことになる。
Global Service でのタイムゾーンの設計

# タイムゾーン問題

> 「タイムゾーンはマルチスレッドプログラミングのようにそれ自体が難しさを抱えている」という前提に立つ必要があると私は考えています。
　　-- グローバルサービスでのタイムゾーンとの向き合い方
　　https://quipper.hatenablog.com/entry/2016/12/05/090000


## 前提となる状況
Globalにスケジューリングや実行ログを伴うようなサービスを構築しています。
ユーザーのLocaleと同じくタイムゾーンに応じて時間を表示し、スケジュール実行を予約します。
サーバサイドでは、まとめて処理を行うため、１つのデータベース上に複数のタイムゾーンによって設定・生成された時間が存在します。


## 結論

1. 保存される時間のタイムゾーンを UTC に統一する
2. サーバサイド（Rails）で扱うタイムゾーンをUTCに統一する
3. DBのカラムはDateTime型で保存する
4. フロントエンドとサーバサイド間はUnix Timestampに統一する
5. フロントエンドでは、利用者の設定に応じてタイムゾーンを変換表示する
6. 日時入力は利用者の設定に応じたタイムゾーンで行う

フロントエンドには Rails View と、Vuejs によるSFCがあります。

# どのような問題が生じうるか
複数タイムゾーンを考慮しない場合、次の間で時間がずれる危険性を持ってしまいます。

1. DBとアプリケーション
2. サーバサイドとフロントエンド
3. 運用に伴う、過去の記録時間と今後生じるの時間
4. 利用者によるタイムゾーン変更
5. 外部連携システムの時間

# ずれる原因
現在時間そのものが、２つの要因で変動するためです。
1. 現在という、それ自体が変化する値である
2. 時差という利用者の属性によって変化する値である

# 変化を固定化するには
変化する値は、基準を設けることで起点が定まり計算可能になります。
タイムゾーンは、基準をUTCにしています。
現在時間を止めることはできませんが、Unixタイムスタンプは起点時間を設けています。
そのため、アプリケーションもこうした基準値に寄せることが適切だと判断しました。
ダックタイピング、抽象クラス

#ダックタイピング

```python:qiita.py
class Person(object):
    def __init__(self,age=1):
#デフォルト引数でageを１に設定
        self.age = age

    def drive(self):
        if self.age >= 18:
            print("ok")
#18以上ならOK
        else:raise Exception("No Drive")
#それ以外はNo driveを表示させるエラー

class Baby(Person):
#Personを継承させる
    def __init__(self,age=1):
#デフォルト引数でageを1に設定
        if age < 18:
            super().__init__(age)
        else:raise ValueError

class Adult(Person):
#Personを継承させる
    def __init__(self,age=18):
        if age >= 18:
            super().__init__(age)
        else:raise ValueError

baby = Baby()
adult = Adult()

class Car(object):
    def __init__(self,model=None):
        #ベースクラスは何も設定しない
        self.model = model

    def run(self):
        print("run")
    def ride(self,person):
        person.drive()
#personのdriveメソッドを呼び出す

car = Car()
car.ride(baby)
```

実行結果のエラー内容
No driveと表示されていることがわかる

```
Exception: No Drive
```

このように書き換える事も可能
PersonというクラスではなくBabyにdriveメソッドを入れる
この場合継承するクラスに必ずdriveを定義する必要がある

```python:qiita.py
class Baby(Person):
#Personを継承させる
    def __init__(self,age=1):
        if age < 18:
            super().__init__(age)
        else:raise ValueError

    def drive(self):
        raise Exception("No Drive")
```

#抽象クラス
abcというライブラリを使用する
ここではdriveについて何もしないが、継承するクラスではこのdriveを実装しないとエラーが発生する


```python:qiita.py
import abc

class Person(metaclass=abc.ABCMeta):
    #このクラスが抽象クラスだと明示
    def __init__(self,age=1):
        self.age = age

    @abc.abstractmethod
    def drive(self):
        pass
    #ここでは何もやらない
```

実行結果
adultという継承クラスでdriveメソッドを作らなかった場合

```
TypeError: Can't instantiate abstract class Adult with abstract methods drive
```
競プロ初心者挑戦日記day1【ABC175】

#自己紹介
はじめまして！大学3年のlygumiです。
今回から競プロ始めていきたいと思います。
（この記事作成するのも一苦労……先が思いやられる…）
プログラミングできたらかっこいいな…っていう動機で始めてみました！（PCとかスマホが使えてるこの時代凄くないですか？？中身知りたいって思いますよね！！）
そんなこんなで手探りで始めてみました！
（密かにIT系に就職したいと思ってる）
今日までにやった勉強は

+ [C++入門 AtCoder Programming Guide for beginners (APG4b)](https://atcoder.jp/contests/APG4b)**これでC++の基礎を学習**
+ paizaラーニングのスキルチェック（C問題が解ける程度）
+ 競プロのQiitaの記事を読み漁る（特に[この記事](https://qiita.com/drken/items/fd4e5e3630d0f5859067)は非常に参考になりました）

の主に3つです

#[A問題](https://atcoder.jp/contests/abc175/tasks/abc175_a)
早速問題に移ります

+ 所要時間:10分
+ 一発AC


###解答

```c++:ABC175_A
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)

int main(){
  string s; cin >> s;
  if(s == "RRR") cout << 3 << endl;
  else if(s == "RRS" || s== "SRR") cout << 2 << endl;
  else if(s == "RSR" || s == "SRS" || s == "SSR" || s == "RSS") cout << 1 << endl;
  else if(s == "SSS") cout << 0 << endl;
  return 0;
}  
```

#[B問題](https://atcoder.jp/contests/abc175/tasks/abc175_b)
意外と手間取ってしまいました
原因:問題文の条件の見落とし

+ 所要時間:40分
+ 一発AC

###解答

```c++:ABC175_B
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)

int main(){
  int n, ans = 0; cin >> n;
  vector<int> num(n);
  rep(i, n){
    cin >> num.at(i);
  }  
  for(int i = 0; i < n - 2; i++){
    int a, b, c; 
    for(int j = i + 1; j < n - 1; j++){
      for(int k = j + 1; k < n; k++){
        a = num.at(i); b = num.at(j); c = num.at(k);
        if(a == b || b == c || a  == c) continue;
        if(a < b) swap(a, b);
        if(a < c) swap(a, c);
        if(b < c) swap(b, c);
        if(a + b > c && a - b < c) ans++;
      }
    }
  }  
  cout << ans << endl;
  return 0;
}
```

#[C問題](https://atcoder.jp/contests/abc175/tasks/abc175_c)
これが解けず終わってしまいました
bit全探索でできたと思ったものの

+ AC×13
+ WA×11
+ TLE×7

という結果となり、そもそもbit全探索も不完全な状態であった

+ bit全探索だと思ってしまった…（数が大きすぎることに気づくべし)

##問題文
###解答

```c++:ABC175_C
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (int)(n); i++)

int main(){
  int64_t x, k, d, ans = 10000000000000000; cin >> x >> k >> d;
  int64_t y = x;
  rep(i, 1 << k){
    rep(j, k){
      if((i >> j) & 1) y += d;
      else y -= d;
      //cout << y << endl;
    }
    //cout << y << endl;
    if(y < 0) y = -y;
    if(ans > y) ans = y;
    y = x; 
  }
  cout << ans << endl;
  return 0;
}
```

#反省
###良かった点

+ bit全探索の発想ができた（そもそも違ったけど…）
+ 楽しんでできた

###悪かった点

+ B問題に時間を取られすぎた
+ C問題の制約をよく吟味していなかった

#Rate
0→10になりました！
10回程度コンテストに参加するとrateが本来の値に近づくみたいなので辛抱強くコンテスト参加していきたいと思います！
webpackでSwiperをビルドする際にpolyfillが効かないとき

以下のようにswiperをインポートする場合、
そのままだと、swiperと依存関係にあるモジュールたちがトランスパイルされない。
(swiperのv3.4.2以降)

```app.js
import Swiper from 'swiper
```

## 対処方法
webpack.config.jsのモジュールの除外設定から
dom7とswiperを外すと解消されるかも。

```webpack.config.js
module.exports = {
  // 省略
  module: {
    rules: [{
      test: /\.js$/,
      exclude: [/node_modules\/(?!(dom7|swiper)\/).*/],
      use: [{
        loader: 'babel-loader'
      }]
    }]
  },
  // 省略
};
```
RaspberryPi・シェルスクリプトで複数のDS18B20センサから同時に値を取得する

# 概要

Raspberry Piに接続した、複数の温度センサDS18B20からできるだけ高速に温度値を取得する方法を示します。
DS18B20は、1-Wire接続でRaspberry Piに接続しますが、１個のセンサで値を取得するのに１秒ほどかかります。
１個ずつ値の取得をしていると（逐次実行すると）、n個のセンサでn秒かかってしまいます。
シェルスクリプトを使ってサブプロセスにて値を並列で取得したところ、２個のセンサの値を１秒ほどで取得できました。

# 方法

シェルスクリプトは、コマンドの終わりに`&`をつけると、コマンドの実行が終わる前に次の行の処理を開始することができます。つまり、１個の処理が完了する前に次の処理を開始することができます。

DS18B20の値を並列に取得するシェルスクリプトを以下に示します。

```bash
#!/bin/bash

# 定数設定
dev_path="/sys/bus/w1/devices"

# 温度センサのデバイス名をdev_listに格納
dev_list=($(find ${dev_path} -maxdepth 1 -name "28*" -type l | xargs -I{} basename {}))

# 温度センサの値を一気に取得
result="$(for dev in ${dev_list[@]}
do
echo ${dev}, $(cat ${dev_path}/${dev}/temperature) &
done
wait)"

echo "${result}"
```

配列`dev_list`には`/sys/bus/w1/devices/`にある、`28-`で始まるシンボリックリンクのリンク名が格納されます。これをforで１件ずつ処理します。


ポイントは以下の行です。

```bash
echo ${dev}=$(cat ${dev_path}/${dev}/temperature) &
```

catで`${dev_path}/${dev}/temperature`の値を読み取りますが、echoコマンドの末尾に`&`があるので、読み取りが終わる前にforのループが次に進みます。
よって次のセンサの値の読み取りが開始されます。

温度センサの読み取りが完了すると、各センサごとの結果が`result`に格納されていきます。

```:出力例
28-3c01a816d9f0=28312
```

`wait`コマンドは、実行中のサブプロセスの完了を待つコマンドです。すべての温度センサの読み取りが完了するまでここで待ちます。

# 実行時間比較

順番にセンサの値を読み取る以下のプログラムと、timeコマンドで実行時間を比較してみます。

```bash:previous.sh
#!/bin/bash

dev_path="/sys/bus/w1/devices"

dev_list=($(find ${dev_path} -maxdepth 1 -name "28*" -type l | xargs -I{} basen$

for dev in ${dev_list[@]}
do
echo ${dev}, $(cat ${dev_path}/${dev}/temperature)
done
exit 0
```

```shell:逐次実行結果
$ time bash previous.sh
28-3c01a816d9f0, 28250
28-3c01a8169133, 27937

real    0m1.831s
user    0m0.044s
sys     0m0.099s
```

1.8秒ほどかかりました。

次に並列実行の場合。

```
$ time bash proposed.sh
28-3c01a816d9f0=28250
28-3c01a8169133=27937

real    0m1.075s
user    0m0.084s
sys     0m0.087s
```

1秒とちょっとで取得完了しました。

# まとめ

シェルスクリプトで、温度センサ(DS18B20)から値を並列実行し、高速に温度を取得する方法を示しました。
シェルスクリプトは複数の機能や高度なアプリケーションを記述するのには向いていませんが、シェルスクリプトでは、他の言語と比べ簡単に並列処理を記述することができます。
PHPでSQSのメッセージの取得と削除をする

SQSのメッセージを取得する部分と、メッセージを削除する部分をAWSのSDK経由で行います。

PHPでLaravelを使っている場合、一般的なJobをQueueする処理などは、LaravelのQueueの機能を使えば実装出来ますが、
メールのBounceなど、Laravelの機能とは別のサービス経由で発生したメッセージを処理する場合は、Laravelの機能を使わずにSQSからのメッセージ取得、削除を書くこともあると思います。

以下にSQSからのメッセージ一覧の取得とメッセージの削除を載せます。

```php:SqsClient.php
<?php
declare(strict_types=1);

namespace Infra\ApiClient\Aws\SQS;

use Aws\Credentials\Credentials;
use Aws\Sqs\SqsClient;

class SqsClient {
    private $sqsClient;
    private $apiPath;

    public function __construct()
    {
        $prefix = "";
        $queue = "";
        $this->apiPath = $prefix . '/' . $queue;
        $key = ""; // AWSのプログラマチックユーザーのアクセスキー
        $secret = ""; // AWSのプログラマチックユーザーのシークレット
        $region = "";
        $this->sqsClient = new SqsClient([
            'credentials' => new Credentials($key, $secret),
            'region' => $region,
            'version' => '2012-11-05', // 最新バージョン
        ]);
    }

    public function getList(): array
    {
        $request = [
            'AttributeNames' => ['All'],
            'MessageAttributeNames' => ['All'],
            'MaxNumberOfMessages' => 10, // 一回のリクエストで取得するMessage数、最大10なので最大値
            'QueueUrl' => $this->apiPath,
            'WaitTimeSeconds' => 3, // Messageを取得するまで待つ時間
            'VisibilityTimeout' => 30, // 取得したMessageの可視性タイムアウト
        ];
        
        $response = $this->sqsClient->receiveMessage($request);
        $items = $response->get('Messages');

        return $items;
    }

    public function delete($item) : void
    {
        $this->sqsClient->deleteMessage([
            'QueueUrl' => $this->apiPath,
            'ReceiptHandle' => $item['ReceiptHandle'],
        ]);
    }

```

## 補足

1回の取得で最大10件のメッセージしか取得することが出来ません。大量にメッセージを処理したい場合は並列に実行出来ます。その際に複数のクライアントで実行されてしまうということはありません。SQSには可視性タイムアウトという取得したら一定時間他のクライアントから見えなくなる機能がついているからです。

メッセージの削除には`ReceiptHandle`というメッセージの識別子が必要になります。メッセージを取得したクライアントしかメッセージを削除出来ないようにする配慮ですね。
特異値分解SVDと主成分分析PCA、自己符号化器との関係

E資格取得講座の解説に出てきた特異値分解SVDについてもっと調べてみた。
#特異値分解　SVD
行列$A$ $(A \in \mathbb{R}^{m \times n},rank A = r)$に対して、直交行列$U \in \mathbb{R}^{m \times m},V \in \mathbb{R}^{n \times n}$が存在して
以下のように分解できるというのが特異値分解である。

$A = U\Sigma V^T$
$
\Sigma = \begin{bmatrix}
\Sigma _+ & 0 \\\ 
0 & 0
\end{bmatrix}
$

$\Sigma _+ = diag(\lambda _1,\lambda _2,\cdots,\lambda _r)$

直交行列$U,V$を列ベクトル $u_i,v_i$を用いて
$U = \begin{bmatrix} u_1,v_2,\cdots  ,u_r, \cdots , u_m\end{bmatrix}$
$V = \begin{bmatrix} v_1,v_2,\cdots  ,v_r, \cdots , v_n\end{bmatrix}$
とすると、
$A = \sigma_1 u_1 v_1^T + \sigma_2 u_2 v_2^T + \cdots \sigma_r u_r v_r^T$
と変形できる。
$u_i,v_i$は正規ベクトルなので、$A$への寄与率は$\lambda_i$によってほぼ決まる。
実際に、特異値$\lambda_i$が小さい項を無視した近似行列$A_k$は以下となる。
$A_k = \sigma_1 u_1 v_1^T + \sigma_2 u_2 v_2^T + \cdots \sigma_k u_k v_k^T$  $(k < r)$
この時の打切り誤差は
${\||A - A_k\||}\_F　= \sqrt{{\sigma_{k+1}}^2 + \cdots + {\sigma_r}^2}$
${\|| : \||}\_F$ は行列のフロベニウスノルム



となり、$k$個のベクトル$u _i \in \mathbb{R}^{m \times 1}$と$k$個のベクトル$v _i \in \mathbb{R}^{n \times 1}$と$k$個のスカラ値$\sigma _i$で
$A \in \mathbb{R}^{m \times n}$を近似することができる。
#特異値分解SVDと主成分分析の関係
統計学では次数削減に用いられる手法として主成分分析PCAがあり、その関連性を説明している記事があったので紹介する。
[PCAとSVDの関連について]
(https://qiita.com/horiem/items/71380db4b659fb9307b4)
こちらの記事でどちらも同じ結果となり、共分散行列と特異値にはシンプルな関係が成立している。

#主成分分析削減と自己符号化器
ニューラルネットワークで用いられる自己符号化器と主成分分析との比較については以下記事が分かりやすい。
https://qiita.com/ta-ka/items/44f4288e8723a7bc9a75
自己符号化器の活性化関数を恒等写像$f(a) = a$とした場合に同様の効果が得られるようである。

活性化関数を非線形関数にまで拡張すれば、より複雑な非線形な次数削減が行えるといえ
複雑な予測問題に対してディープニューラルネットワークが良い予測精度を実現できる理由があるのだろう。
VSCodeのTypeScriptのエラーメッセージの言語を変えたい（英語にしたい）

## 問題提起
日本語がエラーでググりにくい。
（日本語で言われても解決策がわからない物も多いのでコピペで検索したい）

![スクリーンショット 2020-08-16 23.22.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206542/1598ac9a-1bf7-78f3-a923-e263201217b3.png)


## VSCodeのTSエラーを英語化

1. VScode>設定 で設定タブを開いて「TypeScript:Locale」で検索
2. TypeScript:Localeを`en`に設定する。

![スクリーンショット 2020-08-16 23.21.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206542/cf5efaec-707a-705b-0a70-8e4499dbfcd8.png)

## 結果
コレでVSCode自体の設定は日本語（Japanese）でも、TypeScriptのエラー文言表示を英語化することに成功しました！

![スクリーンショット 2020-08-16 23.26.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206542/17a18baf-83c8-b02e-7f27-d596c9374245.png)
Azure SDKsのGo Guidelines(現在ドラフト版)を日本語訳

Azure SDKに関するサイトとして「[Azure SDKs](https://azure.github.io/azure-sdk/)」があります。

画面右上の「ハンバーガーメニュー」から「Guidelines」-「Go (Draft)」を選択するとGoのページである「[Go Guidelines](https://azure.github.io/azure-sdk/golang_introduction.html)」にアクセスできます。ちなみに「Go Guidelines」は現在ドラフト版です。

また、本サイトのドキュメントはGitHubに「[Azure/azure-sdk](https://github.com/azure/azure-sdk)」として存在しており「Go Guidelines」のドキュメントである「[Azure/azure-sdk/docs/golang](https://github.com/Azure/azure-sdk/tree/master/docs/golang)」を今回もGoogle翻訳ベースで日本語訳しました。

- [qt-luigi/azure-sdk-docs-golang-jp](https://github.com/qt-luigi/azure-sdk-docs-golang-jp)

主要コンテンツは3つです。

- [Introduction](https://github.com/qt-luigi/azure-sdk-docs-golang-jp/blob/master/introduction.md)
- [Documentation](https://github.com/qt-luigi/azure-sdk-docs-golang-jp/blob/master/documentation.md)
- [API Design](https://github.com/qt-luigi/azure-sdk-docs-golang-jp/blob/master/design.md)

見栄えについては、GitHub形式だと少し見辛いのでAzure SDKs形式に変更しようかとも考えています。表が崩れていたりとかもあるので、ちょいちょい修正して行きます。

日本語訳した理由は、Azure SDKのサイトであり「[Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go)」を見ていくのに読んでおいた方が良いかと思い、同じ読むなら日本語訳しておけば後の人のお役にも立てるかと。Azure SDK for Goの中の人がcommitした形跡もあるので信頼性も大丈夫です。

内容的には、Azure SDK for Goを「提供する側の心得」という感じでした。RESTful API クライアントを作成する方とかにはオススメかと。作り手側の目線を知れたことで、ソースコードを読み進めていく際に着眼点がブレないなど収穫は大きいと思います。
AIP で外部ユーザーとドキュメントを共有する

# この記事は？
Azure Information Protection では、自組織内のユーザー以外に対して、つまり社外のユーザーに対しても権限を付与することが可能です。
ただし、社外のユーザーのアカウント状況によっては制約があるため、少し書き足します。

[https://docs.microsoft.com/ja-jp/azure/information-protection/secure-collaboration-documents](https://docs.microsoft.com/ja-jp/azure/information-protection/secure-collaboration-documents)

## ケース1 Azure ADテナントを保有している場合
* この場合は簡単です。対象の Azure AD アカウント を指定することで、利用可能です。
* この状態で個人用 RMS にサインアップすると、無償のライセンス (Rights Management Adhoc) が発行されます。

## ケース2
### 2-1. 個人用 RMS にサインアップする
* 個人用 RMSの利用には登録が必要です。登録時に Azure AD テナントと保護されたドキュメントを閲覧するための無償のライセンス (Rights Management Adhoc) が発行されます。
* ドメインがフリーメールサービスなどに利用されている場合は、Azure AD テナントが作成できず個人用 RMS の作成に失敗します。
* この Azure AD テナントは、Azure AD のセルフ サインアップ機能を利用した、アンマネージド Azure AD テナントであり、セルフサインアップを行った直後は、テナントの管理権限を持ち合わせておりません。

### 2-2. Microsoft 個人用 アカウントを用いて Office アプリにログオンする
* Microsoft アカウントを利用する場合は Office 365 アプリ (クイック実行、Click to Run) に限られる旨の制限事項があります。MSI で配布される Office と Microsoft アカウントの組み合わせではドキュメントを開封することできません。

### 2-3. メール (OME) での受信
* Exchange Online のメール暗号化ソリューション (転送不可などOffice 365 Message Encryptionを用いた保護) での保護メールを閲覧する場合に、例えば Outlook、mail、Yahooといった各種フリーメールサービスで利用されるアカウントについては、各ソーシャル ID プロバイダ側 でサインインするか、ワンタイムコードを申請頂く方法になります。

# まとめ
||Azure AD ユーザー|Microsoft 個人用アカウント|Office 365 以外のメール ユーザー<br> w/個人用 RMS|Office 365 以外のメール ユーザー without/個人用 RMS|
|:-----------|:-----------|:-----------|:-----------|:-----------|
|Office ファイル (W/E/P/O)|〇|△<br>※Office 365 アプリ (C2R 版) のみ対応<br>|〇|×|
|Office 以外のファイル (PDF/TXT/JPG 等)<br> w/AIP Viewer|〇|〇|〇|×|
|Outlook で保護を設定したメール|〇|〇<br>※ Office 365 アプリ (C2R 版) のみ対応|〇<Br>ワンタイムパスワード、もしくはサービスプロバイダで認証|〇<Br>ワンタイムパスワード、もしくはサービスプロバイダで認証|
Flaskで画像ファイルを保存する方法

##やること
APIで取得したURLから画像ファイルをダウンロードしてFlaskアプリケーションで表示しようと思ったけど、
そういえばやりかた調べてなかったので調べた結果メモ

##概要
・WEBサイト上のファイルを保存するには通常のファイル作成と同様にOpenメソッドを使用する。
・画像データはバイナリ形式であるため、書き込み形式は「wb」を使用する。
・write処理のとき、文字列データの場合は「xxx.text」だが、画像ファイルなどのバイナリ形式の場合は「xxx.content」を使用する。
・Flaskで作成したアプリケーションで使用する画像ファイルは「static」ディレクトリに格納する必要がある。


##Flaskのディレクトリ構造
```bash
├── __pycache__
├── main.py
├── static
│   └── qdevtxu00je.jpg
└── templates
    ├── index.html
    ├── layout.html
    └── list.html
```


##バックエンド
```python
output = 'static/' + save_fname + '.jpg'
with open(output, 'wb') as f:
    f.write(file.content)
```
Swift で CollectionView の最後に謎の余白がつく

Swift で横スクロールの CollectionView の作成している時に最後のアイテム後ろに謎の余白があく現象に悩まされていました。
どうやらこの現象は CollectionView のスタイルが `.horizontal` +  FlowLayout の `minimumLineSpacing` プロパティがデフォルト値(10pt)を下回った時に発生する現象のようです。

https://stackoverflow.com/questions/42980842/minimuminteritemspacing-is-adding-some-strange-content-at-the-end-of-collection


## 解決策

解決策は FlowLayout の `minimumLineSpacing` と `minimumInteritemSpacing` の値を同じにすることで、これで無事余白を省いて表示されることができました。

```swift
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
        flowLayout.scrollDirection = .horizontal
        flowLayout.minimumLineSpacing = 8
        flowLayout.minimumInteritemSpacing = 8
        collectionViewLayout = flowLayout
```
[FTP] vsftpdでRFC959と異なる挙動をした話



## 背景
今はほとんど使われていないとされているFTPですが、
ふとどのようなパケットの送受信が行なわれているのか気になったのがきっかけです。

## 実行環境

* Mac
    * Virtual Box
        * CentOS7
        * vsftpd v.3.0.2

FTPサーバー構築手順等は割愛します。

## 実通信の確認

実際にFTPの通信を見ていきます。
今回はアクティブモードで実行しました。
クライアントとサーバーは次のIPとなっています。

* FTPクライアント(= Mac) : 192.168.1.5 
* FTPサーバー(= vsftpd) : 192.168.1.8

無事パケットキャプチャが取れて一安心、と思いきや…

次のパケットキャプチャはFTPサーバーのデータのダウンロードに用いられる、RETRコマンド実行時のものです。
![vsftpd_retr_active.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526039/0c633274-b9fd-0573-01f0-524a423bb451.png)
あれ、、、

RFC959では以下のようになっています。

```
7.  TYPICAL FTP SCENARIO

   User at host U wanting to transfer files to/from host S:

   In general, the user will communicate to the server via a mediating
   user-FTP process.  The following may be a typical scenario.  The
   user-FTP prompts are shown in parentheses, '---->' represents
   commands from host U to host S, and '<----' represents replies from
   host S to host U.

      LOCAL COMMANDS BY USER              ACTION INVOLVED

      ftp (host) multics<CR>         Connect to host S, port L,
                                     establishing control connections.
                                     <---- 220 Service ready <CRLF>.
      username Doe <CR>              USER Doe<CRLF>---->
                                     <---- 331 User name ok,
                                               need password<CRLF>.
      password mumble <CR>           PASS mumble<CRLF>---->
                                     <---- 230 User logged in<CRLF>.
      retrieve (local type) ASCII<CR>
      (local pathname) test 1 <CR>   User-FTP opens local file in ASCII.
      (for. pathname) test.pl1<CR>   RETR test.pl1<CRLF> ---->
                                     <---- 150 File status okay;
                                           about to open data
                                           connection<CRLF>.
                                     Server makes data connection
                                     to port U.
      
                                     <---- 226 Closing data connection,
                                         file transfer successful<CRLF>.
      type Image<CR>                 TYPE I<CRLF> ---->
                                     <---- 200 Command OK<CRLF>
      store (local type) image<CR>
      (local pathname) file dump<CR> User-FTP opens local file in Image.
      (for.pathname) >udd>cn>fd<CR>  STOR >udd>cn>fd<CRLF> ---->
                                     <---- 550 Access denied<CRLF>
      terminate                      QUIT <CRLF> ---->
                                     Server closes all
                                     connections.
```								

引用元 : [ftp://ftp.rfc-editor.org/in-notes/rfc959.txt](ftp://ftp.rfc-editor.org/in-notes/rfc959.txt)


原因は時間あるときに探ってみたいと思います。
原因わかる方いらっしゃいましたらコメントいただけると嬉しいです。


一先ず新しくVM（Windows 10）を作成＆3cdaemonでRFC通りのフローを確認できたのでここまでとします。<br>（IP等は上記と同一ではありませんのでご了承ください）
![3cdaemon_retr_active.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526039/9a1f9909-9c7f-4609-a49f-c073cad2ebb0.png)
Apache 2.4 リダイレクト設定 チートシート

Apache 2.4のRewriteCond, RewriteRuleのチートシート。
前提条件として、RewriteEngine Onになっていることを確認する。

例えば↓の感じで使える。
この例では、192.168.100のIPレンジ以外のアクセスを全てメンテナンスページへリダイレクトする。

```
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^(192.168.100)$
RewriteRule ^(.*)$ http://example.com/maintenance.html [R=503, L]
```

以下、詳細です。

## RewriteCondの書式

```
RewriteCond %変数名 条件 [フラグ]
```

フラグは次の種類がある。

[OR]
[AND]
[NC] 大文字小文字を区別しない

デフォルトのフラグは[AND]が適用される。
[OR]のほうが[AND]より先に評価される点に注意。

## RewriteRule

RewriteRuleはファーストマッチで評価される。
フラグの細かい話は次の通り。

+ R=301
    + Ridirect 301の略
    + 301の恒久リダイレクトをする
+ L
    + Lastの略
    + マッチしたら以降のルールは無視する 
+ R
    + Redirectの略
    + 302のリダイレクトをする

## HTTPS化したい場合の例

```
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/%{REQUEST_URI} [R=301, L]
```

## URI正規化したい場合の例

```
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301, L]
```
プログラミング学習記録 Day2

#今日の学習時間
２h (トータル3.5h)

#今日の学習内容

##デイトラDAY5 ゼロからサイトを作ってみよう①

**floatの使い方**
float=浮くという意味
浮いてしまうので本来次にくる要素がfloatの下に入ってきてしまう。
これをクリアするためにclearプロパティを使う

floatを設定した要素の親要素のafter擬似要素にclearプロパティを設定する。
※before,after擬似要素に関しては
[CSSの疑似要素とは？beforeとafterの使い方まとめ](https://saruwakakun.com/html-css/basic/before-after)
が分かりやすい！

```CSS:CSS
.clear::after {
  content: ""; /*擬似要素を実体化*/
  clear: both; /*左寄せ、または右寄せされた全ての要素に対する回り込みを解除*/
  display: block;
}
```

**全ての要素にはclass名をつけておいた方がいい**

**要素の高さを揃える**
![スクリーンショット 2020-08-16 14.25.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692520/93990e62-f29e-8afd-2786-baf243a916a8.png)
左のタイトルと右のナビメニューの文字の中央が揃っていない。
これはタイトルの方がフォントサイズが大きいせい。
ナビメニューのaのline-heightを、タイトルの高さである36pxに設定することで解決。

```CSS:CSS
.header-nav-item a {
  line-height: 36px;
}
```

![スクリーンショット 2020-08-16 14.32.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692520/d3a3ee39-ca0e-159a-bc73-a00c3c3551a3.png)

##DAY6 ゼロからサイトを作ってみよう②

**似たような要素は共通クラスを作ってまとめてCSSを当てると良い！**

floatあんまり使ったことないけどやっぱりflexboxの方が便利だなあ。

本日はここまで。いい感じにできてきました！
![screencapture-file-Users-oyamadahayu-Desktop-practice-index-html-2020-08-16-22_45_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692520/6f8383f2-42fe-99ce-8cae-a52c3aac7efb.png)
DynamoDB Local で pythonを使っての登録処理

## 概要

pythonの採番処理を作成するときにDynamoDBを使うときに開発中に実際のDynamoDBを使うのは・・・という場合DynamoDB Local を使っての開発すると思うのでその方法をまとめていきます。
[採番処理で使った内容](https://qiita.com/dmikita/items/c23f10c92f0513b1de7e)を応用してレコードの登録処理の実装をします。

## 事前準備

* pythonのインストール(記事作成時は3.7です)。
    * JupyterNotebookなどでも可能です。
* boto3

## 実装

* ソースは以下のようになります。
    * 各種設定値は環境変数から取得するようにしています。ここにACCESS_KEYなどをべたに書くと大変なことになります。
    * 今回は`signal-datas_1.csv` は固定にしていますが、実際に使うときは引数で受け取るなどしたほうがよいかと。
        * csvはヘッダー付きのデータになります。
    * [過去にlambdaで作った処理](https://qiita.com/dmikita/items/36b27b9760bbac3e73dc)を流用しています。


```python
import os
import boto3

endpoint_url = os.getenv('DYNAMODB_ENDPOINT', 'http://192.168.99.100:8000/')
aws_access_key_id = os.getenv('DYNAMODB_ACCESS_KEY_ID', 'DummyID')
aws_secret_access_key_id = os.getenv('DYNAMODB_SECRET_ACCESS_KEY_ID', 'DummyKey')
aws_region_name = os.getenv('DYNAMODB_REGION', 'ap-northeast-1')

dynamodb = boto3.resource(
    'dynamodb',
    region_name=aws_region_name,
    endpoint_url=endpoint_url
)

tableName='signal-datas'

def write_to_dynamo(rows):
   try:
      table = dynamodb.Table(tableName)
   except:
      print("Error loading DynamoDB table. Check if table was created correctly and environment variable.")
   try:
      with table.batch_writer() as batch:
         for i in range(len(rows)):
            row=rows[i]
            batch.put_item(
               Item=row
            )
   except:
      print(traceback.format_exc())
      print("Error executing batch_writer")

sequences = dynamodb.Table('sequences')

batch_size = 100
batch = []

#DictReader is a generator; not stored in memory
with open('signal-datas_1.csv',encoding='UTF-8') as csvfile:
    for row in csv.DictReader(csvfile):
        if len(batch) >= batch_size:
            write_to_dynamo(batch)
            batch.clear()
        batch.append(row)

if batch:
    write_to_dynamo(batch)

print('完了')

```
* 成功すると最後の 完了が出力されます。

## 登録内容の確認

* DynamoDB JavaScript Shellで確認する場合は以下のように設定を行います。
    * Docker For Desktopの場合は `192.168.99.100` のところは `localhost` になります。
    * AWS ACESS KEY の方は右上の歯車をおして設定してください。
    * scanで全件出力していますが必要に応じてqueryなどを使ってください。
    * regionは登録時の値に合わせてください。

```javascript
AWS.config.update({
  region: "ap-northeast-1",
    endpoint: "http://192.168.99.100:8000"
});

var docClient = new AWS.DynamoDB.DocumentClient();

var params = {
    TableName: 'signal-datas',
}
docClient.scan(params, function(err, data) {
    if (err) ppJson(err); // an error occurred
    else ppJson(data); // successful response
});
```
プロパティーを使った属性の設定

class TeslaCar(Car)のenable_auto_runの属性を後から書き換えることが可能

```python:qiita.py
class Car(object):
    def __init__(self,model=None):
        #ベースクラスは何も設定しない
        self.model = model

    def run(self):
        print("run")

class ToyotaCar(Car):
    def run(self):
        print("toyta_run")

class TeslaCar(Car):
    def __init__(self, model= "ModelS", enable_auto_run=False):
        super().__init__(model)
        self.enable_auto_run=enable_auto_run

    def run(self):
        print("tesla_run")

tesla_car = TeslaCar("modelS")
print(tesla_car.enable_auto_run)
tesla_car.enable_auto_run = True
print(tesla_car.enable_auto_run)
```

##外から書き換えられたくないとき
pythonでは＿は『外から見えないようにする』という意味がある

```python:qiita.py
self._enable_auto_run
```

```python:qiita.py
class TeslaCar(Car):
    def __init__(self, model= "ModelS", enable_auto_run=False):
        super().__init__(model)
        self._enable_auto_run=enable_auto_run

    @property
    def enable_auto_run(self):
        return self._enable_auto_run
```

このように書き換えることで読み込みはできるが書き込みはできなくなる
この状態で書き換えようとすると
![スクリーンショット 2020-08-16 22.25.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527694/35d2170b-4984-1bee-ee57-c8cd4b3c4a1e.png)

再度書き換えを可能にするには次のファンクションを追加する必要がある

```python:qiita.py
    @enable_auto_run.setter
    def enable_auto_run(self, is_enable):
        self._enable_auto_run = is_enable
```
この後、次のように書くと引数にTrueが入る

```python:qiita.py
tesla_car.enable_auto_run = True
```

##使い所
外からの書き換えの制限をかける時など

```python:qiita.py
class TeslaCar(Car):
    def __init__(self, model= "ModelS", enable_auto_run=False,passwd =456):
        super().__init__(model)
        self._enable_auto_run=enable_auto_run
        self.passwd = passwd

    @property
    def enable_auto_run(self):
        return self._enable_auto_run

    @enable_auto_run.setter
    def enable_auto_run(self, is_enable):
        if self.passwd == 456:
            #パスワードが456のときのみ外からの書き換えを可能
            self._enable_auto_run = is_enable
        else:raise ValueError
        #それ以外はエラー
```

さらに進んで
アンダースコアを二つ繋げると、生成後はアクセスできなくなる

```python:qiita.py
self.__enable_auto_run=enable_auto_run
```

###注意点
存在しない属性を付け加えることができる為、付け加える前にクラスの中身を確認する必要がある

```python:qiita.py
class T(object):
    pass
t=T()
#インスタンス化
t.name = "kirin"
t.age = 20
print(t.name,t.age)
#kirin,20
```
Apache 2.4 アクセス制御 チートシート

Apache 2.4はauthz_host_moduleのRequireディレクティブでアクセス制御を実現している。

## RequireAll, RequireAny, RequireNoneについて

+ RequireAll
    + 全ての条件にマッチすればTRUEと評価する (AND条件)

+ RequireAny
    + いずれかの条件にマッチすればTRUEと評価する (OR条件)

+ RequireNone
    + いずれの条件にもマッチしなければTRUEと評価する (NOT条件)

例）

```
<Location /admin>
    <RequireAll>
        <RequireAny>
        Require user admin
        Require ip 192.168.1
        </RequireAny>
        <RequireNone>
        Require group blacklist
        </RequireNone>   
    </RequireAll>
</Location>
```

この場合、adminユーザ あるいは 接続元IPが192.168.1のネットワークである　かつ、
blacklistに記載されていない場合は /adminにアクセスできる。

RequireAll, RequireAny, RequireNone どれも記載がなければ、
デフォルトではRequireAnyが適用される模様。
Requireディレクティブはいろいろと設定値があるようなので、調べたいところ。

## Requireディレクティブについて

+ mod_authz_core
    + Require all granted => 全て許可
    + Require all denied => 全て拒否
    + Require env <環境変数> => 環境変数で制御
    + Require method http => httpメソッドで制御  
    
+ mod_authz_host
    + Require ip \<IPアドレス\> => IPアドレスで制御
    + Require host <ホスト名> => ホスト名で制御

+ mod_authz_user
    + Require user <ユーザ名>
    + Require group <グループ名>
    + Require valid_user => 認証ユーザを許可
Storyboardで定義されたUINavigationControllerをSwiftコードから呼び出す方法


1. New FileからStoryboardを追加（ここでは「Search.storyboard」とする）
2. LibraryからUIViewControllerをstoryboard上にドラッグアンドドロップ
3. 追加されたUIViewControllerを選択し、画面上部のメニューバーより [Editor] > [Embed in] > [Navigation Controller] を選択
4. 追加されたNavigationViewControllerを選択した状態でSotryboard IDを指定（ここでは「SearchNavigationController」とする）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/26f466f1-e7d6-3bd4-fec5-171cf58f367b.png)

5 .Navigationbarのタイトルをつけるため、UIViewControllerの Navigation Item　を選択し、Utilitiesエリアの [Title]　を入力（ここでは「検索」とする）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/4b5e72a4-c71e-363c-776b-ee3a8c152b39.png)


6 .最後に以下のコードでNavigationViewControllerを呼び出す。

```swift:MainViewController.swift
    let storyboard = UIStoryboard(name: "Search", bundle: nil)
    let searchNaviVc = storyboard.instantiateViewController(withIdentifier: "SearchNavigationController") as! UINavigationController
    self.present(searchNaviVc,animated: true, completion: nil)
```

※補足1：任意のViewControllerのコードと紐づけるには、classにViewControllerを指定する（ここではSearchViewControllerとする）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/acb0dc2b-7b7f-128c-2064-445366581be0.png)

これをNavigationViewControllerから呼び出したいときは以下とする。

```swift:MainViewController.swift
    let storyboard = UIStoryboard(name: "Search", bundle: nil)
    let searchNaviVc = storyboard.instantiateViewController(withIdentifier: "SearchNavigationController") as! UINavigationController
    let vc = searchNaviVc.viewControllers[0] as! SearchViewController
    self.present(vc,animated: true, completion: nil)
```

※補足2：UITabBarControllerから使いたいときの例

```swift:MainTabBarViewController.swift
final class MainTabBarViewController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()

        // TODOリストタブ
        let topVc = TopViewController()
        topVc.tabBarItem = UITabBarItem(title: "TODO list", image: UIImage(systemName: "text.badge.checkmark"), tag: 1)
        let topNaviVc = UINavigationController(rootViewController: topVc)
        
        // Searchタブ　⭐️今回追加したstoryboardのコード⭐️
        let storyboard = UIStoryboard(name: "Search", bundle: nil)
        let searchNaviVc = storyboard.instantiateViewController(withIdentifier: "SearchNavigationController") as! UINavigationController
        searchNaviVc.tabBarItem = UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass"), tag: 2)
        
        // カレンダータブ
        let calVc = ColorPickerViewController()
        calVc.tabBarItem = UITabBarItem(title: "Calendar", image: UIImage(systemName: "calendar"), tag: 3)
        let calNaviVc = UINavigationController(rootViewController: calVc)
        setViewControllers([topNaviVc, searchNaviVc, calNaviVc], animated: false)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
```

＜参考にしたサイト＞
https://studio.beatnix.co.jp/develop/swift/storyboard-program/
https://qiita.com/midori004/items/4a67dc70af582aa91eec
https://qiita.com/chubura/items/03a3cddf8fe17361c5b2
なんちゃら Tech (X-Tech)

# FinTech (Financial Technology)
フィンテック。
金融 (Financial) と技術 (Technology) を組み合わせた造語。

# EdTech (Education Technology)
教育テック。
教育 (Education) と技術 (Technology) を組み合わせた造語。

# MediTech (Medical Technology)
医療テック。
医療 (Medical) と技術 (Technology) を組み合わせた造語。

# InsurTech (Insurance Technology)
保険テック。
保険 (Insurance) と技術 (Technology) を組み合わせた造語。

# ConTech (Construction Technology)
建設テック。
建設 (Construction) と技術 (Technology) を組み合わせた造語。

# PropTech (Property Technology)
不動産テック。
不動産 (Property) と技術 (Technology) を組み合わせた造語。
ReTech (Real estate Technology) と同義。

# ReTech (Real estate Technology)
不動産テック。
不動産 (Real estate) と技術 (Technology) を組み合わせた造語。
PropTech (Property Technology) と同義。

# CreTech (Commercial real estate Technology)
企業用不動産テック。
企業用不動産 (Commercial real estate) と技術 (Technology) を組み合わせた造語。
不動産テックとは異なり、対象を企業用不動産に限定している。

# SportsTech (Sports Technology)
スポーツテック。
スポーツ (Sports) と技術 (Technology) を組み合わせた造語。

# AgriTech (Agricultural Technology)
農業テック。
農業 (Agricultural) と技術 (Technology) を組み合わせた造語。

# RetailTech (Retail Technology)
リテールテック。
小売 (Retail) と技術 (Technology) を組み合わせた造語。

# HRTech (Human Resource Technology)
人事 (HR: Human Resource) と技術 (Technology) を組み合わせた造語。

# LabTech (Laboratory Technology)
研究 (Laboratory) と技術 (Technology) を組み合わせた造語。
Slack Appから送るメッセージに日付・時間を入れるときにdateフォーマットを使ってちょっと感動した件

小ネタです。

Slack App(bot)を作るとき、botから送るメッセージに日付や時間の情報を含めたいことが時々あると思います。

例えばこんな感じ。(右下)

![スクリーンショット 2020-08-16 21.45.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20371/417a88e7-6ca1-0699-be9d-761d7c2194e2.png)

「問合せフォームに入力があると、Slackに通知がくる」というものを作っていました。
最初は、このメッセージを送信しているサーバーで日時を表す文字列を組み立てて送信することを考えていたのですが、Slack側で閲覧しているユーザーのタイムゾーンや設定に合わせて日時をフォーマットして表示するという機能があることを知ったので使ってみました。
(長いことSlackのAPIはいろいろと触っていたつもりでしたが、これは知らなかったのでシェア。いつからあったんだろう。)

公式のドキュメントはこちら。
[Formatting text for app surfaces | Slack](https://api.slack.com/reference/surfaces/formatting#date-formatting)

解説記事を書くまでもないくらい簡単に利用することができます。上記スクリーンショットのメッセージはBlock kitという仕組みを使って、以下のようなJSONで表現されています。

```json
{
	"blocks": [
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "<!channel>\n\n:new: 新しい問合せがあります。"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ">hogehoge"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"fields": [
				{
					"type": "mrkdwn",
					"text": "*:name_badge: Name:*\nmogamin3"
				},
				{
					"type": "mrkdwn",
					"text": "*:e-mail: Email Address:*\ntest@example.com"
				},
				{
					"type": "mrkdwn",
					"text": "*:earth_asia: IP Address:*\n192.168.0.1"
				},
				{
					"type": "mrkdwn",
					"text": "*:clock1: Timestamp:*\n<!date^1597582723^{date_num} {time_secs}|1597582723>"
				}
			]
		}
	]
}
```

一番最後のところがtimestampで、以下のフォーマットで日付を書くと、最初のスクリーンショットのように整形して表示してくれます。

`<!date^timestamp^フォーマット^リンク|代替テキスト>`

- timestamp
    - 表示したい時間をUnix timeで。
- フォーマット
    - 日付をどう表示したいかを宣言。使える文字列は予め決まっていて、ドキュメントに書いています。流石に和暦とかはないですがまあ困ることはないでしょう…笑
- リンク
    - この日付文字列をリンクにしたいときはURL等を渡すと書いてあります。今この記事を書くにあたってドキュメントを確認していて気づいたので試してないですが…。オプショナルなので渡さなかったら上記のように文字列として出力されます。
- 代替テキスト
    - この日付のフォーマットが使えないクライアントからみたときに表示されるテキスト。タイムゾーンとか関係なくこの文字列が出るので、どのタイムゾーンの話なのかを書いておくと良いでしょう、といったことがドキュメントに書いてました。
    - 上記の例では面倒だったのでそのままtimestampを吐くようにしてみています。

---

ユーザーが日本にしかいないことが明らかなときはサーバーサイドで文字列作ってやってもまあいいといえばいいんですが、24h表記・12h表記の切替などもユーザーの設定に応じてやってくれるそうなので、少しでもユーザービリティあげたいとかあればやってみてはいかがでしょうか？（あと地味に日付のフォーマットとかライブラリに頼ったり、自力でゴリゴリやったりする部分でもあると思うので単純に楽ですよ:grimacing:)
TkinterとOpenCVを使用したWebカメラ画像表示プログラムの作成

###最初に
自分用メモ
TkinterとOpenCVを使用してWEBカメラから取得した画像をGUI表示するプログラムの作成

###環境
windows10
python 3.8.2
opencv-python 4.2.0.34
numpy 1.19.0
Pillow 7.2.0

###プログラム本体

```python:app.py
import cv2
import tkinter as tk
from PIL import Image, ImageTk
import tkinter.ttk as ttk

# define valiable
width = 640
height = 480

class SsFrame(ttk.LabelFrame):
    def __init__(self, master=None, text=None):
        super(SsFrame, self).__init__(master, text=text)
        self.start_b = ttk.Button(self, text="start", command=master.start_cap)
        self.stop_b = ttk.Button(self, text="stop", command=master.stop_cap)

        self.start_b.grid(row=0, column=0)
        self.stop_b.grid(row=0, column=1)

class App(tk.Tk):
    def __init__(self):
        super(App, self).__init__()
        # root configuration
        self.title("VideoCapture")
        self.resizable(width=False, height=False)

        # valiables configuration
        self.capture_flag = False

        # canvas configuration
        self.canvas = tk.Canvas(self, width=width, height=height)
        self.canvas.create_rectangle(0, 0, 640, 480, fill="black")
        self.canvas.pack()

        # ss_frame configuration
        self.ss_frame = SsFrame(self, text="start_stop_buttons")
        self.ss_frame.pack()

    def start_cap(self):
        if not self.capture_flag:
            self.capture_flag = True
            self.capture = cv2.VideoCapture(0)
            self.after_id = self.after(10, self.update_cap)

    def update_cap(self):
        ret, frame = self.capture.read()
        if ret:
            frame = cv2.resize(frame, (width, height))
            self.tk_frame = ImageTk.PhotoImage(
                Image.fromarray(
                    cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                )
            )
            self.canvas.create_image(0, 0, image=self.tk_frame, anchor='nw')
        else:
            self.canvas.create_text(width/2, height/2, text="None")

        self.after_id = self.after(10, self.update_cap)

    def stop_cap(self):
        self.after_cancel(self.after_id)
        self.capture.release()
        cv2.destroyAllWindows()
        self.capture_flag = False

    def start(self):
        self.mainloop()


if __name__ == "__main__":

    app = App()
    app.start()
```

###備考
後で追記予定
Service Workerのキャッシュ管理

<h1>導入</h1>
Service Workerとは、ページ上のスクリプトと並行して読み込まれ、ウェブページのコンテキスト外で実行されるスクリプトのことです。Service Worker は DOM やユーザー インタラクションにはアクセスできませんが、<a href="https://developer.mozilla.org/ja/docs/Web/API/Client/postMessage">postMessage API</a> を介してスクリプトと通信することができます。これは Web アプリのプロキシとして動作し、すべてのサーバのリクエストを傍受し、例えばキャッシュを使って応答したり、<a href="https://developer.mozilla.org/ja/docs/Web/API/Window/localStorage">LocalStorage</a> や <a href="https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API">IndexedDB</a> からデータを取得したりすることを提案します。そのため、アプリケーションをオフラインで利用できるようになります。


<h1>Service Workerのライフサイクル</h1>
Service workerを有効に活用するためには、サービスライフサイクルの理解が不可欠です。
![Qiita](https://image.slidesharecdn.com/serviceworkermobileweb1-150225013305-conversion-gate01/95/service-worker-mobile-web-27-638.jpg?cb=1424888272)
Service Workerのライフサイクルは、主に3つのフェーズで構成されています。
<ul>
<li>__登録__(_Registration_)</li>
<li>__インストール__(_Installation_)</li>
<li>__アクティベーション__(_Activation_)</li>
</ul>
それぞれを見ていきましょう。
<h1>登録</h1>
最初のブロックは、以下のコードでサービスワーカーを登録します。

```js
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker/sw.js', { scope: '/sw-test/' }).then(function(reg) {
    // 登録がうまくいった
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // 登録に失敗しました
    console.log('Registration failed with ' + error);
  });
};
```
Service Worker スクリプトは /service-worker/sw.js にあります。
次の段落で詳しく見ていきましょう。
<h1>インストール </h1>
Servie workerが呼ばれて初めてブラウザにインストールされます。

```js
this.addEventListener('install', function(event) {
 event.waitUntil(
  // キャッシュにファイルを追加する
    caches.open(expectedCacheNames).then(cache => cache.addAll([
        'index.html',
        'style.css',
        'app.js',
        'cat.png',
]))
  );
});
```
event.waitUntil は、パラメータで渡されたPromiseの解決(または拒否)まで他のイベントをブロックすることができます。Service Workerは、キャッシュされる Request/Response オブジェクトのペアを表現するための<a href="https://developer.mozilla.org/ja/docs/Web/API/Cache">キャッシュインターフェイス</a>を提供します。

<h1>アクティベーション</h1>
activate イベントはService WorkerがRequestの処理を担当する直前に発行されるので、不要なキャッシュを削除するに良いタイミングです。

```js
this.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(cacheNames.map(function(cacheName) {
        if (expectedCacheNames.indexOf(cacheName) === -1) {
          //期限切れのキャッシュの削除
          return caches.delete(keyList[i]);
        }
      }));
    })
  );
});
```
<h1>Fetch イベント　</h1>
Requestを傍受するために、Fetchイベントに動作を追加します。

```js
this.addEventListener('fetch', function(event) {
  // ここでマジックが起こります!
});
```
event.respondWith は、カスタムレスポンスを記録したり、ネットワークエラーを処理したりすることができます。そして、キャッシュが利用可能であれば、リクエストに対応するリソースを返すだけです。

```js
let response;
event.respondWith(caches.match(event.request).catch(function() {
  return fetch(event.request);
}).then(function(r) {
  response = r;
  caches.open(expectedCacheNames).then(function(cache) {
    cache.put(event.request, response);
  });
  return response.clone();
}));
```
リクエストオブジェクトとレスポンスオブジェクトは一度しか消費できないストリームなので、レスポンスのコピーを返します。
最後に、後者のケースでは、リクエストがキャッシュにマッチせずネットワークが利用できない場合、デフォルトのリソースを返します。

```js
catch(function() {
  return caches.match('404.jpg');
})
```
以上
Apache 2.4 SNI (ServerName Identification)について

結論、SNIを利用すれば1台のサーバで異なるドメインの証明書を使い分けることができる。

## SNI (ServerName Identification)とは?

ApacheにはVirtualHostといって、1台のwwwサーバで複数ドメイントを運用できる仕組みがある。
元来、１つのグローバルIPではSSL証明書は1つのドメインしか運用できなかった。
その問題を解決するのが**SNI**。
SSLハンドシェイク時にクライアントがアクセスしたいホスト名を通知することで、サーバ側がグローバルIPではなく、
ホスト名によってSSL証明書を使い分けることができる。
実現のためにはサーバとブラウザ双方でSNIに対応する必要があるのだけど、今時SNIに対応していないブラウザなんてあるのだろうか?

詳細はGMOグローバルサインさんの↓の記事をみてちょ。

注目の集まるSNI（Server Name Indication）導入の必要性とは | グローバルサインブログ
https://jp.globalsign.com/blog/articles/server_name_indication.html