OmniAICreator/Qiita-1.07M huggingface dataset:
Braveのプロフィールを削除する．

# Braveのプロフィール削除方法
## 環境
- Brave バージョン: 1.5.112 Chromium: 80.0.3987.132（Official Build） (64-bit)

## 方法
Braveでは，プロフィールを2つ以上作成すると右上にプロフィールのアイコンが表示される．
カラフルな背景の上に白線をクロスしたり，縞模様になっていたり，渦巻いている抽象的なアイコンだ．
これをクリックすると「プロフィールを管理」という項目がある．クリックするとポップアップウィンドウが出現し，プロフィール一覧が表示される．

次に，カーソルを削除したいプロフィールのアイコン上にホバーすると，アイコンの右上にハンバーガーメニュー(`⋮`)が表示される．これをクリックすると「プロフィールの削除」という項目があるのでクリックして削除できる．ただしそのプロフィールの

- 閲覧履歴
- パスワード
- ブックマーク
- 自動入力フォームのデータ

は削除されるので注意．

カーソルをホバーしても，アイコンの背景色とハンバーガーメニューの色が両方とも白であるためわかりにくかった．
ボタンを押すと開くナビ、非表示時フォーカスさせない!!


tabキーを連打しても何もフォーカスしない...はてな？
と思っていましたが、absoluteでマイナスをつけまくって端っこにやって見せないようにしていたナビにフォーカスしていました。機械は間違えない。

## 非表示メニューはフォーカスが当たらないようにする。
最初は`display: none;`や`visibility:hidden`などで
フォーカスさせない作戦に出ました。しかし問題が...

```css:
.target {
  display: absolute;
  top: 50%;
  left: -600px;
  transition: .3s;
}
.is-active {
 left: 0;
}
```
`is-active`クラスをつけたり外したりすることでナビを出現するようにしています。
これに`display: none;`や`visibility:hidden`で出し分けしてしまうと、
今まですっと出てきてすっと仕舞われるというアニメーションになっていた表示が　**パっと一瞬で消えたり出てきたりしてしまいます**。当然ですね..

JSでガチャガチャしたりCSSのアニメーションであれこれするのも
コードが増えてなんか嫌...と思っていましたが、もっと簡単な方法がありました。

## tabIndex
`tabIndex="-1"`要素につけるとフォーカスされなくなります。
これを出し分けする方針で行きます。
(ちなみにマイナスの値ならなんでもOKです)

下記はreactでの例です。

```react
<Link
  to="/"
  tabIndex={hamburgerToggle.get('flg') ? 'auto' : '-1'}
>
 HOME
</Link>
```

## スクリーンリーダーも対応させよう
tabIndexでフォーカスを無効にしても、スクリーンリーダで読まれてしまいます。
これを読まれないように調節しましょう。属性に`aria-hidden="true"をつけるとスクリーンリーダに読まれなくなります。

## 非表示にしてもスクリーンリーダー利用者がアクセスしやすいように
非表示ナビへの不要なアクセスを封じ、一件落着！という風ですが、忘れてはいけないことがあると周囲の方に指摘いただきました。ありがたや...
ナビを開閉するボタンがスクリーンリーダーにとってわかりにくいものだったら、アクセスする手段が途絶えてしまいます。
開閉ボタンに`aria-label`属性をつけて**ナビをナビ**します。
こうすることで、`aria-label`に指定したテキストがスクリーンリーダーに読み上げられます。

```html
<button
 type="button"
 onClick={clickhandler}
 aria-label="ナビ開閉ボタン"
>×
</button>
```


もっと良い方法や意見等あればぜひコメントよろしくお願いします!
FirebaseのHostingとFunctionsをローカル環境でテストする 

FirebaseでWebページとcloud functionsをホスティングするまえにエミュレータにてテスト出来ます
コマンドプロンプトで下記実行

```
firebase emulators:start
```

下記参照しました
[ローカルでの関数の実行](https://firebase.google.com/docs/functions/local-emulator?hl=ja)

エミュレータ停止は"Ctrl+C"で行ってください。
下記から情報を得ました
[Firebase CLI について](https://www.ginzaitlab.com/posts/7187082/)
[Python]Classの第一引数はなぜselfなの？

## はじめに
Pythonでクラスを定義する際，第一引数の命名が ```self``` なのはなぜだろうとずっと疑問に思ったので，調べて書き残しときます．

## 第一引数self以外ではダメ？
結論からするとダメです．[PEP8](https://pep8-ja.readthedocs.io/ja/latest/index.html#id36)(1)に ```インスタンスメソッドのはじめの引数の名前は常に self を使ってください。```
と定義されています．ただし，動作上なら ```self``` 以外でもきちんと動きます．例は[ここ](https://www.geeksforgeeks.org/self-in-python-class/)(2)を参考にしてます．

```python
class Hoge():
    def __init__(self_inplace_hoge, string):
        self_inplace_hoge.string = string
        print('self_inplace_hoge: ', self_inplace_hoge.string)

class Fuga(Hoge):
    def __init__(self_inplace_fuga, string):
        self_inplace_fuga.string = string
        print('self_inplace_fuga: ', self_inplace_fuga.string)

hoge = Hoge('aaaa')
fuga = Fuga('bbbb')

print(hoge.string)
print(fuga.string)
```

```bash
self_inplace_hoge:  aaaa
self_inplace_fuga:  bbbb
aaaa
bbbb
```

動きはしますねルール違反なのでやったらだめですけど．

ちなみに ```self``` の役割として見てみるとちゃんと定義したクラスがメモリのどこにあるか返してくれます意外と見てみると楽しい？

```bash
self_inplace_hoge:  <__main__.Hoge object at 0x00000123D17C1CC8>
self_inplace_fuga:  <__main__.Fuga object at 0x00000123D17C12C8>
```

## さいごに
```this``` とか ```self``` って誰でも好きな名前つけたらヤバイってなるからルールができたんだろうな～
ちょっとバズワードみたいですね．

## 参考資料
(1) [pep8-ja](https://pep8-ja.readthedocs.io/ja/latest/index.html#id36)
(2) [self in Python class](https://www.geeksforgeeks.org/self-in-python-class/)
git checkoutコマンドのbオプションとBオプションの違い

# git checkoutコマンド
git checkoutコマンドは皆様何かとお使いかと思います。
自身も新規ブランチのチェックアウト時に、下記のようなコマンドを打つことがあります。
この場合は `-b` オプションです。
(リモートの `feature/hogehoge` ブランチを、ローカルの`feature/hogehoge` としてチェックアウト)

```bash
% git checkout -b feature/hogehoge origin/feature/hogehoge
Branch 'feature/hogehoge' set up to track remote branch 'feature/hogehoge' from 'origin'.
Switched to a new branch 'feature/hogehoge'
```

ただ、既にローカルに `feature/hogehoge` ブランチが存在していた場合、

```bash
% git checkout -b feature/hogehoge origin/feature/hogehoge
fatal: A branch named 'feature/hogehoge' already exists.
```

というエラーが発生します。

これはその名の通り、同名のブランチが既に存在しているため発生するエラーですが、
大文字の `-B` オプションを使用することで、上記エラーが発生することなく、
強制的にブランチのチェックアウトをすることが出来ます。
(強制的にするので使いどころ誤ると大変ですが・・・)
下記のような感じです。

```bash
% git checkout -B feature/hogehoge origin/feature/hogehoge
Branch 'feature/hogehoge' set up to track remote branch 'feature/hogehoge' from 'origin'.
Switched to and reset branch 'feature/hogehoge'
```

シェルスクリプト内で `git checkout` をする必要がある場合等、
強制的にチェックアウトしたい場合は有用かと思います。

短いですが以上です。
どなたかの助けになれば幸いです！
Servicenowの役立つサイト5選

#Servicenowに関する情報
Servicenowについて調べたい時、便利な公式サイトを挙げていきます。

##コミュニティサイト

https://community.servicenow.com/community

Servicenowは、アプリケーション開発プラットフォームの提供をしています。
乗せるアプリケーションは、独自に開発できるようになっています。（製品を契約することもできます）

このコミュニティサイトでは、Servicenowの利用者同士で、情報交換ができます。

##デベロッパーサイト

https://developer.servicenow.com/dev.do#!/

あらゆるドキュメントが確認できます。
開発用インスタンスを無償で利用できます。（インスタンス利用には、アカウント登録が必要です）

##Webセミナー

https://www.servicenow.co.jp/events/on-demand-webinars.html

過去に配信されたWebセミナーを視聴することができます。
日本人が説明してくれているので、わかりやすいです。

##eラーニング

https://nowlearning.service-now.com/lxp#none

英語のコンテンツですが、デモがあるのでわかりやすいです。

##You Tube

https://www.youtube.com/channel/UCJ8To255mAYb2QtWikzt6IQ

You Tubeのチャンネルもあります。
更新頻度は低いです。

#最後に
今現在、日本語のサイトは少ないですね・・・
参考になれば幸いです。
他にも良いサイトや記事があれば教えて下さい。
GA 勉強会 【概要編】


## 目次

* GAとは
* GAを使ってできること！
* まとめ

### ◆ GAとは

* Googleが提供するアクセス解析ツール
=> *サイトのユーザーの行動に関するデータがわかる!*


😁 < けど、それがわかって何が嬉しいんだ？？





---
### ◆ GAを使ってできること！

(・ω・) < `自分のサイトに対するユーザーからの反応やサイトの健康状態を把握できるようになるよ！`

**ざっくり以下三つ！**

1. **【サイトの現状把握】**
2. **【課題点の抽出】**
3. **【改善策の立案】**



---
#### 1.【サイトの現状把握】

* **リアルタイムの利用状況がわかる**
  * 今現在何人が訪れているかわかる
      * 現在`どのページが見られているか`がわかる！
  

* **ユーザーの基本属性がわかる**
  * 日付ごとに`何人が訪れたか`,`どんな人が訪れたか`を知れる
     * 同じ日の`利用回数やデバイスの種類`もわかっちゃう :ghost:


* **ユーザーがどこから来たかがわかる**
  * 流入元ごとに分類され、`どの媒体からのアクセスか`わかる


* **サイト内でのユーザーの動きがわかる**
  * `どのページへ遷移したか、どこで直帰や離脱していったか`がわかる








---
#### 2.【課題点の抽出】

* **なぜ,どこで,直帰離脱してしまうのかわかる**
  * 当てずっぽうに修正することなく`効率的に改善`できる
  
  
* **ページごとの利用率がわかる**
  * `どのサイトコンテンツに注力するべきか`分析できる


* **どの程度目標が達成できているかがわかる**
  * 登録数や 改修後のユーザー反応などの`目標値をヒアリングレスで獲得`、分析できる




---


#### 3.【改善策の立案】

* **利用ユーザーの分析ができる**
  * 1,2 でわかったユーザーの情報や行動特性を利用して`どういったコンテンツがサイトに求められているか等のニーズを得ることができる`


* **マーケティング戦略が建てられる**
  * オンライン広告キャンペーンのデータを収集して分析、`どのページに注力するべきかがわかる`


* **サイトコンテンツの改善につながる**
  * `注力すべきドメインへの効果的な改善`を行える

---

### ◆ まとめ :point_up:


* GA をつかうと
    * **ユーザーのさまざまな情報を得られる!**
      * 僕らの相対している人たちが`どこかの誰かではなく、少し身近な存在`になる :relaxed:
<br>
  * **いま何が求められているかがわかる!**
     * 判断材料が増え、`確度の高い戦略が建てられる` :airplane:
    

  * **データドリブンな判断ができる!**
     * これまで以上に`複雑化する環境に対応できる` :cityscape:

---
#### 次回

  😁< なんか、俺もGA使ってみたくなってきたな！

  (・ω・) < それは GA 勉強会【初級編①】でね！
Atcorder152 A~C問題

Atcorder152
https://atcoder.jp/contests/abc152/tasks


#A問題
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/3b957b66-67fa-6b9e-723a-81a24788393d.png)

```A問題.c++
#include <bits/stdc++.h>
#define rep(i,n) for (int i=0; i<(n); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int main(){
    int N,M; cin >> N >> M;
    if (N==M && N!=0) cout << "Yes" << endl;
    else cout << "No" << endl;
    return 0;
}
```

#B問題
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/ce2a5383-1b00-9247-3e39-b65a7e16347e.png)


```B問題.c++
#include <bits/stdc++.h>
#define rep(i,n) for (int i=0; i<(n); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int main(){
    int a,b; cin >> a >> b;
    int tmp1=max(a,b);
    int tmp2=min(a,b);
    
    for(int i=0; i<tmp1; i++) cout << tmp2;
    return 0;
}
```

```B問題.c++
#include <bits/stdc++.h>
#define rep(i,n) for (int i=0; i<(n); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int main(){
    int a,b; cin >> a >> b;
    int tmp1=min(a,b);
    int tmp2=max(a,b);
    string ans="";
    
    for (int i=0; i<tmp2; i++) ans+=to_string(tmp1);
    cout << ans << endl; 
}
```

#C問題
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/f9ee3a92-8cf5-5ee7-e564-a71ad17827ba.png)

```C問題.c++
#include <bits/stdc++.h>
#define rep(i,n) for (int i=0; i<(n); i++)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int main(){
    int N; cin >> N;
    vector <int> P(N);
    rep(i,N) cin >> P[i];
    
    ll ans=1;
    ll min=P[0];
    rep(i,N-1){
        if (min>=P[i+1]){
            ans++;
            min=P[i+1];
        }
    }
    cout << ans ;
}
```

#まとめ
・B問題 **string ans="";**としてから**for (int i=0; i<tmp2; i++) ans+=to_string(tmp1);** として出力する方法忘れがち。
・C問題 **minを作る**ことをはじめ忘れてた！　注意！
CentOS6から7にアップデートしましたよ

# CentOS6から7にアップデートしました。

コマンドは下の方に全部まとめてます。日本語がガバガバガバナンス（爆笑）なのはご了承いただけますと幸いで候。

CentOS6のサポート期限が迫っているということで、CentOS7にアップデートできるか検証してほしいって言われてしまった。
新しく構築したらいいんじゃないですかって言ったら断られてしまった。
お金がないそうだ。

四の五の言っても仕方ないので手探りでやってみましゅ。

# HELP！ググっても古い情報しかねぇ！！
とりあえずやってみようってことで、ググってはコピペ、ググってはコピペで作業していると秒で詰まった。
どうやらアップデートツールの配布は終了しているようだ。
ツールを配布しているところを探すのに一番手間取った。

# ここから実際のコマンドを羅列します。

環境
～～～centos6.8でLAMP環境を適当に作ったもの～～～

`yum install openscap pcre-devel libxml2-devel libxslt-devel m2crypto python-simplejson mod_wsgi`
`rpm -ihv https://buildlogs.centos.org/centos/6/upg/x86_64/Packages/preupgrade-assistant-1.0.2-36.0.1.el6.centos.x86_64.rpm`
`rpm -ihv https://buildlogs.centos.org/centos/6/upg/x86_64/Packages/preupgrade-assistant-contents-0.5.14-1.el6.centos.noarch.rpm`
`rpm -ihv https://buildlogs.centos.org/centos/6/upg/x86_64/Packages/preupgrade-assistant-ui-1.0.2-36.0.1.el6.centos.x86_64.rpm`
`rpm -ihv https://buildlogs.centos.org/centos/6/upg/x86_64/Packages/redhat-upgrade-tool-0.7.22-3.el6.centos.noarch.rpm`
これでアップデートツールをインストール

`rpm --import https://www.centos.org/keys/RPM-GPG-KEY-CentOS-7`
CentOS7用のGPGキーをインポート

`rpm -Uhv --oldpackage https://buildlogs.centos.org/centos/6/upg/x86_64/Packages/openscap-1.0.8-1.0.1.el6.centos.x86_64.rpm`
アップデートツールopenscapのバージョンダウン
CentOS6.7以上の場合バージョンダウンさせないとうまくいかない。(こういうときってバージョンダウン？ダウングレード？どっちも一緒の意味か・・・)

`preupg -s CentOS6_7`
アップグレードのテスト
バックアップちゃんと取った？ぶっ飛んでも知らんで？？みたいなこと聞かれるので死ぬ覚悟が出来たらyするといいと思います。

`/root/preupgrade/result.html`
これが結果ファイルなのでapacheのドキュメントルートにぶっこんでブラウザで確認。

英語読めないのでGoogleさんに翻訳してもらって確認。
私の環境だと
`semodule -r sandbox`
やれってことくらいしか対処できるものなかったのでとりあえずやってみる。
SELinuxのsandboxってやつを消す？のかな？よくわかってないです。(本番でよくわかんないコマンドは打ってはいけませんよ念のため)

`redhat-upgrade-tool-cli --network 7 --cleanup-post --instrepo=http://vault.centos.org/centos/7.2.1511/os/x86_64/ --addrepo=CentOS7=http://mirror.centos.org/centos/7/os/x86_64/`
いよいよアップデートでございます。勇気をもってyを押そう！

`reboot`
アップデートが完了したら運命の再起動
再起動中にとんでもねぇ量のerror分が吐き出されててゲロ吐きそうになる。でもほとんど同じエラーだった。

再起動後はサービスがいろいろと停止しているので立ち上げたり自動起動の設定したり。
ここでmysqlが立ち上がらないことに気づく。
なんとCentOS7はmysqlじゃなくてmariadbだったのです！！！！ﾅ､ﾅﾝﾀﾞｯﾃｰ

`systemctl start mariadb`
はい、立ち上がりません。再起動中に出てたエラーがここで邪魔をしてきました。

`ln -s /lib64/libpcre.so /lib64/libpcre.so.0`
シンボリックリンクを張ってあげて対応。いけました。

とりあえずここまででLAMPとして問題なく動きました。

# 締めの一言
未経験未知識で始めたインフラのお仕事(会社命令)が早5か月。
一番多く報告した言葉を発表して終わりにしたいと思います。

# なんかよくわかんないけど動きました！！！！！！



参考にさせていただいたもの
[CentOS6からCentOS7へアップグレードする](https://qiita.com/toshiro3/items/0422280e3ea336c8415e)
[CentOS6からCentOS7へアップグレードでdev.centos.orgがリンク切れになっていた](https://qiita.com/kuroki_roku/items/38d5fe0d757349c70cd8)
[CentOS6.9を7.3にアップグレード](https://a-records.info/upgrade-centos69-to-centos-73/)
Ionicの<ion-slides>コンポーネントで手動スワイプを無効にする

#結論
```ｈｔｍｌ:test.page.html
<ion-slides #slides class="swiper-no-swiping">
```
のように、`swiper-no-swiping`クラスを付与してあげるだけで、手動スワイプによる遷移を止めることが出来ます。


#どういうときに使うのか
**あまり使わない方が良いです。**なぜならUIのアニメーションは横移動なのにそれに伴ったアクションで操作ができないから…

例えばIonicのコンポーネントにセグメントというものがあります。セグメントも横移動アニメーションですが、セグメントの動きに合わせて表示をアニメーションで変えたい時、Slidesコンポーネントはとても相性が良いです。但し、その中身で何かしらの横動作が必要な時、Slidesコンポーネントの遷移は発生させたくない（セグメントコンポーネントの操作のみで移動したい）という場合があります。そういうときに使いましょう。

もう一度いうと、**あまり使わない方が良いです。**

#何でこれで出来るのか
IonicのSlidesコンポーネントでは、内部でSwiperJSというライブラリを使用しており、そのAPIとしてこのクラスが用意されているためです。
mac chainercv install failed

#environment
- Macos Catalina 10.15.1
- python 3.6.8
- pip 20.0.2

# installation

~~~linix
$ pip install -U numpy
$ pip install chainercv
~~~

[参考まで](https://chainercv.readthedocs.io/en/stable/install.html)
# error

~~~
Building wheels for collected packages: chainercv
  Running setup.py bdist_wheel for chainercv ... error
.
.
.
error: command 'clang' failed with exit status 1
.
.
.
~~~

#solution

~~~
$ xcode-select --install
~~~
Railsで新規ファイルの作成までの流れ

##【概要】
アプリケーションを作成して、Gitで管理するところまで

##【目標】

- Ruby on Railsのバージョンを変更する
- Gitの管理下に置く

##新規アプリケーションの準備
Railsのバージョンを5.0.7.2にして開発

```:ターミナル
$ cd ~  # ホームディレクトリに移動
$ gem install rails --version="5.0.7.2"
```
gemの変更を反映

```:ターミナル
$ rbenv rehash
```

##アプリケーションを作成しよう
rails newコマンドで新しいアプリケーションを立ち上げ

- バージョン指定をしてrails newをすること
- -d mysqlのオプションをつけること
- DB管理はMySQLで行う

```:ターミナル
$ cd   #ホームディレクトリに移動
$ cd projects  #projectsディレクトリに移動
$ rails _5.0.7.2_ new chat-space -d mysql  #必ず左記の様にバージョン指定を行ってrails newコマンドを実行してください。
$ cd chat-space  #chat-spaceディレクトリに移動
$ rails db:create  # データベースを作成
```
## 不要なファイルを生成しないようにする
'rails g'コマンドでコントローラを作成すると、生成したファイルに対応したスタイルシート・ヘルパー・Javascript・アプリケーションをテストするためのファイルが同時に生成される。今回は不要。

```ruby:config/application.rb
# 省略
module ChatSpace
  class Application < Rails::Application
    config.generators do |g|
      g.stylesheets false
      g.javascripts false
      g.helper false
      g.test_framework false
    end
  end
end
```

## GitHubで管理
###ローカルリポジトリの作成
GItHub Desktopから,該当のアプリのローカルリポジトリを作成
▷左上の「Current Repository」→「Add」→「Add Existing Repository」を選択
▷対象〇〇を選択し「Add Repository」をクリック
▷ローカルリポジトリにある全てのファイルを選択してコミットしましょう。
※その際のコミットメッセージは、最初のコミットなので「Initial commit」としておく。

###リモートリポジトリを作成
コミットしたら、リモートリポジトリに反映させましょう。
GitHub Desktop では、Publish ボタンを押すとリモートリポジトリが作られていない場合にリモートリポジトリも作ってくれます。

以下のようなモーダルが表示され、リモートリポジトリを作成できます。
非公開にする必要がない場合、今回は[Keep this code private]のチェックは外す。

▷[Publish repository]ボタンをクリックすると GitHub のリモートリポジトリが作成できます。
▷GitHub の Your repositories の欄に git-app があれば上手く行っています。
▷適宜、ブランチも作成する


##.gitignoreを編集
.gitignoreは、コミットしたくないファイル・ディレクトリを指定できる設定ファイルです。
画像投稿機能がある場合など、画像データがGitHubにコミットされないようにする。
▶画像が保管されるpublic/uploadsディレクトリを.gitignoreに追加

```ruby:ディレクトリ名/.gitignore
# 末尾に次の記述を追加
public/uploads/*
```

以上です。
GAS DeveloperMetadata【３月２０日修正】

とある理由で、PropertiesやCache以外でデータを保存する方法を検討しました
***MetadataFinderを使わないと見つけられないのでソース修正しました***

#1.PropertiesとCache
どちらも、そのスクリプト内でしか利用できないんですね。
なんでこんな話になったかというと、

***スプシAのスクリプトから、スプシBのスクリプトへデータを渡す***

をやりたかったのですが、Propertiesは

```Javascript
let props = PropertiesService.getScriptProperties();
props.setProperty("key","value");
```

なので、スプシAのスクリプトからプロパティを呼び出すと、当然、スプシAのスクリプトのプロパティとなり、スプシBのスクリプトのプロパティをとることはできません
（設定も同じ）

Cacheも同じ構成をとっているので、こちらも同一スクリプトなり同一ドキュメント内に限定されます。
ユーザープロパティを使えばできるのかもしれませんが、別なユーザーでも動かしたい、と。

#2.DeveloperMetadata
クラスリファレンスをつらつら見ていたら、Metadataというものがあるようで、スプシやレンジ等に設定できる模様。
正しい使い方か微妙でしたが、スプシのMetadataに渡したいデータを埋め込んでみました
埋め込む側

```javascript:b.js
    let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
    let meta = spreadsheet.createDeveloperMetadataFinder().withKey("my_Meta_key").find();    
    let value = meta.find(item => item.getKey() == "my_Meta_key");
    if(value === undefined){
      spreadsheet.addDeveloperMetadata("my_Meta_key","my_Meta_Value");
      return "my_Meta_value";
    }
    return value.getValue();
```

読み込む側

```javascript:a.js
    let spreadsheet = SpreadsheetApp.openById("B_fileId");
    // let meta = spreadsheet.getDeveloperMetadata();
    let meta = spreadsheet.createDeveloperMetadataFinder().withKey("my_Meta_key").find();
    let value = meta.find(item => item.getKey() == "my_Meta_key");
    if(value === undefined){
      return "no meta-data";
    }
    return value.getValue();
```
***3/20追記：MetadataFinderを使わないと見つけられないので修正***

#3.ScriptId

実は、スクリプトのIDを集めるために上記のことをやるハメになったのですが、ScriptIdも

```javascript
let scriptId = ScriptApp.getScriptId();
```

なので、自分のスクリプトIDしかわからないようです。

#4.Metadataのスコープ
スコープ、がただしい表現か微妙ですが、以下の３つにMetadataは設定できるようです
Spreadsheet
Sheet
Range

すべて、
addDeveloperMetadata
で作成できるようになっています。

#5.DeveloperMetadata
私のGoogle力がたりないのか、ほとんど情報みつからなかったんですが、だれも使わないのでしょうか。
普通は、Propertiesで足りるからかもしれません
（スプレットシートのシートに直に書く、という方法もレガシーながらあり）
M5stack uiflow文字背景

#M5stack uiflow文字背景のくせ

こんにちは、お疲れ様です。
**M5stack**を入手して使い勝手を試すため、ちょこちょこ触ってていますが、
その中でつまづいたことを自分なりの対処法をしたのでその備忘録。

そのうちアップデートされてこういう問題も解消されるかもしれませんが、それまで有効なテクニック。

尚、私が試したのは、**uiflow v1.4.5**です。

ちなみに、**micropython**でも**blocky**でも結果は同じなので、今回せっかくなので**blocky**で説明してます。
（そんなに違いはないですが、M5stackらしくということで）

##文字の背景について
さて、**M5stack**のメインLCDに文字を表示させるには以下の方法があると思います。
・**Graphic**　の　**lcd.print**　を使って表示
・UIの　**label**　を使って表示
これが手軽なところでしょうか。

##まずはgraphicで文字を表示
結論はUIの方を使うのですが、筋道立てるために
先に上手くいかない方（いかなかった方）の
まず**Graphic**で文字を表示します。
![blocky001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/03e1b0d5-910d-6d30-8adb-f823496cfa47.png)

![text001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/3130bbd2-62ed-67b8-528e-bdd940d0781c.png)

こうですね。
背景色を黒色にしていると気が付きませんが、背景色を変えると愕然とします。

![blocky002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/0fb5ffab-54e6-9850-43f6-f129a5d1e601.png)

**Graphic**では、文字の背景が”黒”になります。
![text002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/62b6bc4e-99fb-be08-9dca-223d54416fd5.png)


**だ、ダサい・・・**
この**Graphic**の文字背景（黒色）はUIの背景色との因果関係もなく、とにかく黒になるようです。
これ、同じく**Graphic**で塗りなおしたらそもそも表示したい文字も消えちゃうし、その上から文字表示したらまた黒くなる・・・
つまり**print.lcd**の中身の問題なのでそこをいじらないとどうしようもないです。（正直ショボい・・・）

##UIの labelを使用して表示
次に、UIの**label**で文字を表示させると
![blocky003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/ad794444-ffb8-9469-9484-43eac130c523.png)

![blocky004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/e351612b-cba3-aa18-7e74-cb854988bf5f.png)

![text003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/db0ec57e-2996-a247-ca6d-c2a8b2239257.png)

とても簡単ですね。　マウスで配置するだけ。

ところが、下地に別の色を入れてこの文字を変更するとある事に気が付きます。
![blocky008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/adcacbeb-5e4e-1364-09e0-b8642895f9d2.png)
（※rectangle0は変更するlabelに被さる様にしています）
##残像が・・・
![text004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/cfc2fa4d-ddff-decf-3f2e-667d93dd549c.png)

**label**の文字を変更した時点でその変更する前の文字が残像のように残ります。
注目すべきは、この残像が背景色と同じということです。
この現象は、**label**の置かれている場所が、「背景色では無い」時に起こります。
つまり、UIのlabelは以下の手順を踏んでいるということがわかります。

**①　現在の文字を背景色で上書き**
　↓
**②　変更後の文字で描画色で上書き**

この①②の工程が一つで、**label show**の処理だということがわかります。

ちなみに、「本当にそうか？」という検証がてら
・文字変更をする前に一度塗りつぶし
・変更を何回か行う
などやってみましたが結果は同じ。　上記の①②の処理が一つになっている以上、避けられません。

##では、どうやって対処するか
もちろん「pythonなんだしライブラリを修正する」とか、「uiflowを諦める」とか、「blockyなんた糞」なんていうことも有りかもしれませんが、やはりせっかくIOTなM5stackなんだし、blockyでやりたいじゃないですか！！
そこで私が考えた手順がこれです。

**①変更したいlabelを画面外に移動**
　↓
**②元の場所をRectとかで塗りつぶす**
　↓
**③画面の外でlabelを変更する**
　↓
**④変更したlabelを元の場所に戻す**

![blocky006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306697/b0afcda5-681c-caca-deaa-3d9e86a89db5.png)
（※rectangle0は変更するlabelに被さる様にしています）

labelの描画の原理が透過色ではなく、「上書き描画」っていうことを利用したやり方でした。

##まとめ
本音をいうと、透過色が使えればそれでよいのだけど・・・pngとかの活用も広がるので至急対応を望む！！

EOL
umaskコマンドについてまとめてみた

#はじめに
ネット上にはumaskコマンドやマスク値の紹介が色々ありますが、
論理和、論理積、ビットの反転など難しく感じたため記事を投稿します。

#umaskコマンドとは
ファイルやディレクトリを新規作成する際に、
どのようなアクセス権(パーミッション)をマスクするかを決めます。

各**ユーザ**ごとに**マスク**することができます。
ちなみに、umaskはuser maskの略称です。

####マスクとは
そもそも、マスクとは何かというと「覆い隠す」という意味です。
私達が身につけているマスクも口元を「覆い隠して」いますよね。

#umaskとマスク値の仕組み
umaskコマンドとマスク値の関係をみていきます。
元々は、ファイルやディレクトリを新規作成する際は、全権限(777)が付与されます。
そこに、マスク値を引き算することで、実際に付与されるアクセス権が決まります。

. 　777 　←新規ファイルや新規ディレクトリを作成するときのアクセス権
-)　022　 ←umaskコマンド実行結果(マスク値)
ーーーーーーーー
.  　755　 ←umask -Sの実行結果・・・※

**ファイルを作成するときは、※のアクセス権からx権が剥奪されて
644（rw-r--r--）になります。**

##実機操作
![qiita.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440776/fb98f0af-8f7b-4d66-fca8-cdb9258d6316.png)

###参考
umaksコマンドを実行したときに出力される、千の位の「0」は特殊なアクセス権を表します。

- 4：SUID
- 2：SGID
- 1：スティッキービット
- 0：特殊なアクセス権なし

#まとめ
ファイルやディレクトリを新規作成する時のアクセス権を変更したい場合は、umaskコマンドを使いましょう。
ファイル作成時はX権が剥奪されるため、プログラムファイルとして実行したいときは
chmodコマンドでX権を付与しましょう。
~~早くマスクの流通がもとに戻りますように・・・~~
Laravelで簡素なデータ管理とAPIサーバを構築する(1)

# Laravel環境構築

## 目的

社会情勢が不安定で、メインの仕事だけを継続的に続けられるか不透明な状況になってきてます。サービスを短期で提供できる状況を整えるため、別プロダクトで使用されてるlaravelを1から覚えることにしました。ここ数年フロントエンドしかやってなかったので、バックエンドのCRUD＆認証、及びフロントエンドのAPIサーバを作ることを目的にします。

## 環境
macOS 10.15.3

homestead を使用する。

## vagrant インストール
https://www.vagrantup.com/downloads.html

## virtualbox インストール
https://www.virtualbox.org/wiki/Downloads

## Homestead 環境作成

```zsh
$ vagrant box add laravel/homestead
$ git clone https://github.com/laravel/homestead.git ~/Homestead

$ cd ~/Homestead
$ git checkout release
$ bash init.sh
```

## Homestead.yaml を編集

```yaml:~/Homestead/Homestead.yaml
---
ip: "192.168.10.10"
memory: 2048
cpus: 2
provider: virtualbox

authorize: ~/.ssh/id_rsa.pub

keys:
    - ~/.ssh/id_rsa

folders:
    - map: ~/code
      to: /home/vagrant/code

sites:
    - map: homestead.test
      to: /home/vagrant/code/laravel/public

databases:
    - homestead

features:
    - mariadb: false
    - ohmyzsh: false
    - webdriver: false

# ports:
#     - send: 50000
#       to: 5000
#     - send: 7777
#       to: 777
#       protocol: udp
```

## hosts ファイルに追記

```/etc/hosts
192.168.10.10 homestead.test
```

## 起動

```zsh
$ vagrant up
$ vagrant ssh
```

## 動作確認
http://homestead.test

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26601/790138eb-41c7-0f4d-cc41-348e35c55790.png)

### Homestead.yml を編集して反映したいとき
```
$ vim Homestead.yml
（何かしら編集）
$ vagrant reload --provision
```

## Homeページを作成

### ルーティング

```php:routes/web.php
~~
(追加)
Route::get('/home', function() {
    return view('home');
});
```

### View追加

```php:resources/views/home.blade.php
<html>
<body>
Hello World!
</body>
</html>
```



# 参考文献
PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5
https://www.amazon.co.jp/dp/4802611846/
PCにUbuntu18.04をインストールし終えてからのプロキシ・IPアドレス設定のあれやこれ

# はじめに
いつも自分がPCのネットワーク設定をするときにしていることのメモみたいなものです。普段自分がPCを使っている環境下では少し細かな設定も含めて行わなければならないため、少し特殊な環境下で作業をしている人向けの話です。

# インターネットの接続設定
まず、PCのインターネット接続の設定を行っていきます。ここで設定する場所は、ネットワークプロキシ、IPv4、IPv6の箇所です。
## ネットワークプロキシ
まず、デスクトップ画面の右上の逆三角の部分をクリックしてEthernet(hoge)接続...と書かれてる部分を展開すると有線設定という項目があります。これをまずクリックして設定ウィンドウを表示します。
![Screenshot from 2020-03-18 15-54-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323464/43dfa7e2-6d1b-4344-6e45-67d8b9aa7878.png)

そうすると、ネットワークプロキシと書かれた項目がありますので、その文字の横の歯車をクリックします。すると画面が表示され、自動/手動/無効とチェックボタンがありますが、この中の手動を選択してください。
![Screenshot from 2020-03-18 16-16-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323464/eb7aa7ad-613a-63c5-8d8d-3a3820ba316c.png)

そうしたら、HTTPプロキシ(H)、HTTPSプロキシ(T)...とブランクが出てくるので、左側のブランクに設定するプロキシを、右側のブランクに設定するポート番号を入力してください。ブラウザからインターネットを閲覧する時のような普通のプロキシ設定はこれだけです。

## IPv4
(ここの設定は固定IPアドレスを使う人だけ行ってください。)
先ほどの有線設定のウインドウに戻り、次は各LANポート毎の設定を行います。まず、接続済みと書かれているEthernet(hoge)の歯車ボタンをクリックして設定画面を表示させます。次に、「IPv4」と書かれたタブがあるので、そのタブをクリックして画面を切り替えます。すると出てきた画面の上側に「IPv4メソッド」と書かれたチェックリストがあるので、この中の手動を選択します。そして、その下のアドレスに指定されたIPアドレスやネットマスクを設定してください。DNSも指示されていれば、ブランクにコンマ区切りで入力してください。

## IPv6
こちらもIPv4と同じ要領で設定していきますが、IPv4のみの設定にする場合はIPv6メソッドのチェックリストで無効を選択してください。あとは適用を押すだけです。

# apt.confの設定
上の設定が完了していれば最初から入っているFirefoxからYoutubeでも見ることができると思いますが、これだけではまだ不十分だったりします。例えば、```sudo apt update ```をターミナルから打つとエラーで実行できなかったり...。原因としてはaptにプロキシ設定が反映されていないことが挙げられます。ここではaptのプロキシ設定をします。

まず、ターミナルを開いて次のコマンドを打ちます。自分はgeditを使っていますがエディターは自由です。

```
$ sudo gedit /etc/apt/apt.conf
```

すると、ウィンドウズのメモ帳みたいなものが現れるのでそこに

```
Acquire::http::Proxy "your_proxy:your_port";
Acquire::https::Proxy "your_proxy:your_port";
```

を書き込み、保存します。これでaptを使ったコマンドはプロキシが適用されて動くようになります。試しにupdate & upgradeをしてみてください。

```
$ sudo apt update
$ sudo apt upgrade
```
問題なく更新ができたら完了です。

# おわりに
今回はプロキシとIPアドレス設定について書きました。文字ばかりになってしまった部分が多いのでまた書き直していきたいと思います。各コマンド利用時のプロキシ設定に関しては下記のページが役立つと思います。

# 参考ページ
[プロキシ設定まとめ - Qiita](https://qiita.com/Ki4mTaria/items/d10f3d562d02a0a4ded4)
コロナウイルスの拡大を世界地図に色塗りした

# TL;DR
PythonのライブラリであるPlotlyを使って、新型コロナウイルス(COVID-19)の拡大状況を可視化しました。なお時間の殆どはCSVファイルの整形に割かれたため、Pythonのコードをゴリゴリ書くことはありませんでした。
なお、**データは最新のものではありません**のでご注意ください。

![World 0202 fast.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238597/8041b9e4-292f-f4ee-6248-ff3c50bac653.gif)

# 下準備
JHU CSSE(Johns Hopkins University Center for Systems Science and Engineering)がデータを本当にきれいにまとめてくれているので、ダウンロードしてきました。
https://github.com/CSSEGISandData/COVID-19

後に使うPlotlyでは国名(Japanなど)では読み込んでくれないので、3レター(JPNなど)に置き換えないといけません。以下のものをとりあえず拝借してきて、Excelで`=VLOOKUP()`でこのファイルを辞書的に参照して置換しました。
https://www.kaggle.com/nitinsss/military-expenditure-of-countries-19602019

なお、このときGrater china(Hong Kong, Macauなど)やアラブ首長国連邦など、表現の揺れがある国は手動で直す必要がありますのでご注意ください。

手動でnumbersやExcelを使いながらいい感じにデータを整えます。この作業が一番苦痛でした。Pandasとかちゃんと使えたらこんなのも一旦コードを書けば楽になるのに…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238597/fe5f0ba0-d4a8-76d6-92bb-1bee8b5cc1af.png)

# メインとなるコード
Jupyter notebookを普段使っているのですがなんだかうまく行かなかったので、以下実行環境はGoogle colabです。

```python:main.py 
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import plotly
import plotly.express as px
import plotly.graph_objects as go
import os

df_drop = pd.read_csv('PATH')
date_list = (['1/21/2020 10:00 PM',	'1/22/2020 12:00 PM',	'1/23/2020 12:00 PM',	'1/24/2020 12:00 AM',	'1/24/2020 12:00 PM',	'1/25/2020 12:00 AM',	'1/25/2020 12:00 PM',	'1/25/2020 10:00 PM',	'1/26/2020 11:00 AM',	'1/26/2020 11:00 PM',	'1/27/2020 9:00 AM',	'1/27/2020 7:00 PM',	'1/27/2020 8:30 PM',	'1/28/2020 1:00 PM',	'1/28/2020 6:00 PM',	'1/28/2020 11:00 PM',	'1/29/2020 1:30 PM', '1/29/2020 2:30 PM',	'1/29/2020 9:00 PM',	'1/30/2020 11:00 AM',	'1/31/2020 2:00 PM',	'1/31/2020 7:00 PM',	'2/1/2020 10:00 AM',	'2/2/2020 9:00 PM'])


#meltで一意の行列にする
df_reshape = pd.melt(df_drop, id_vars=["Code"])

df_reshape.rename(columns={"variable":"date","value":"confirmed"}, inplace=True)

print(df_reshape)

anime_confirmed = px.choropleth(df_reshape,
                          locations="Code",
                          color='confirmed',
                          hover_name="Code",
                          range_color=[0,10],
                          animation_frame='date',
                          projection="natural earth",
                          color_continuous_scale='emrld')
anime_confirmed.layout.updatemenus[0].buttons[0].args[1]["frame"]["duration"] = 100
anime_confirmed.update_layoayout(title = "nCoV confirmed patients 1/21/2020 -> 2/2/2020")
anime_confirmed.show()
```

# 結論
これでインタラクティブでいけ好かない世界地図をグリグリ動かせます。ハッピー!

# 参考文献
こちらのnoteを大いに参考にさせていただきました。
https://note.com/natto_nebaneba/n/ndf2725aa24ca
Windows HomeでDocker Toolboxを入れてdocker-compose build動かそうと思ったら。。。

Windows HomeでDocker Toolboxを入れてdocker-compose build動かそうと思ったら以下のエラーが発生。

```
$ docker-compose build
nginx uses an image, skipping
db uses an image, skipping
Building php
Traceback (most recent call last):
  File "docker-compose", line 6, in <module>
  File "compose\cli\main.py", line 71, in main
  File "compose\cli\main.py", line 127, in perform_command
  File "compose\cli\main.py", line 287, in build
  File "compose\project.py", line 386, in build
  File "compose\project.py", line 368, in build_service
  File "compose\service.py", line 1084, in build
  File "site-packages\docker\api\build.py", line 260, in build
  File "site-packages\docker\api\build.py", line 307, in _set_auth_headers
  File "site-packages\docker\auth.py", line 301, in get_all_credentials
  File "site-packages\docker\auth.py", line 287, in _get_store_instance
  File "site-packages\dockerpycreds\store.py", line 25, in __init__
dockerpycreds.errors.InitializationError: docker-credential-wincred not installed or not available in PATH
[14212] Failed to execute script docker-compose

```

golangをインストール

docker-credential-helpersを取得

```
go get github.com/docker/docker-credential-helpers
```

以下のように怒られるけど無視

```
can't load package: package github.com/docker/docker-credential-helpers: no Go files in C:\Users\XXXXX\go\src\github.com\docker\docker-credential-helpers
```

make.exeを取ってきて使えるようにして


```
cd C:\Users\XXXXX\go\src\github.com\docker\docker-credential-helpers
make wincred 
```

makeを実行したフォルダのbinフォルダに「docker-credential-wincred.exe」が作成されるので、パスが通っているフォルダに移動する。

※追記
コマンドプロントを管理者権限で開いてリンクを作成した。これはいるのか分からない。。。

```
mklink /D "c:\c" "c:/"
```

以上
Pythonのバージョン管理のためにpipenvとasdf触ってみた

# 概要
TDD本（※）の第２部を写経するにあたって初めてPythonのプロジェクトを作成した際に、先輩から「pipenvやasdfでバージョン管理ができる」と聞いてとりあえず両方触ってみたので、参考にした記事をメモしておきます。
※https://www.amazon.co.jp/dp/B077D2L69C/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

# pipenv でのバージョン管理

[Pipenvを使ったPython開発まとめ]
https://qiita.com/y-tsutsu/items/54c10e0b2c6b565c887a
↑pipenvのインストールや操作について

# asdf でのバージョン管理

[asdfで様々な言語のバージョンを管理する]
https://blog.shimar.me/2018/10/02/asdf.html
↑asdfのインストールや操作について

[各言語環境を Linux (WSL) に asdf で構築]
https://qiita.com/kikuchi_kentaro/items/d951fa7ca7c9c29a77dc
↑asdfソース関連のリンク記載


現状、pipenvを使用したほうで進めていますが、そのうちどちらがいいか検討したいと思います。
diagramsが興味深かったのでflaskでwrapしてみた

# diagramsとは

pythonでアーキテクチャ図が書けてしまうソフトウェアです。

https://diagrams.mingrammer.com

数日前に目について、以下のようなことをやりたいと思ったのが作った動機でした。

```
<img src='http://localhost:8080/?
with Diagram("Grouped Workers", show=False, direction="TB"):
    ELB("lb") >> [EC2("worker1"),
                  EC2("worker2"),
                  EC2("worker3"),
                  EC2("worker4"),
                  EC2("worker5")] >> RDS("events")
```

# とりあえず、えいやっと作ってみる

10時間程度格闘して作成してみました。
ソースコード一式は、以下のリポジトリです。

https://github.com/tamuto/diagrams-server

## Pythonのコードをコンパイルする

まずはなんと言っても問題になるのはURLで渡されてくるPythonのソースコードをどうやってコンパイルするか？です。query_stringから取得するのはよしとしても、整形してからコンパイルしないとダメです。
ライブラリとしてはyapfを利用させていただきました。

## 【課題】そもそもquery_stringには改行コードがない

examplesに掲載されている通りにimport文も含めて、記載してもらう予定でした。
しかし、query_stringには```... import EC2from ...`````のようにくっついており整形しても分離は（当たり前ですが）できませんでした。

## ASTを使って引数を変更する

こちらは、想定通りの動きが実装できました。NodeTransformerを使用し書き換えてコンパイルしてexecで実行です。
途中linenoとかがないとかエラーが出たのですが``` ast.fix_missing_location ```で無事に解決しました。（したと思っている・・・）

## アイコンのリクエストを無理やり・・・

svgで出力するとアイコンのリクエストが別途発生します。
Flaskのrouteで無理やり処理しました。（docker内で実行しているから許されるはず！？）

# その他の課題

頑張って作ってみたものの色々と問題があるなーって思っています。

* 受け取ったPythonのコードをそのまま実行するので、インターネットに公開したらダメです。docker内で実行しているから限定的に大丈夫なのか、どうか判断つきませんでした。（何かしら叩けばセキュリティホールがあるはず）
* 上に書いてあるサンプル以外で試したところ、Syntax Errorになってしまいました。詳細は調べていません。
* URLのところに/pngとか指定すると、そのファイル形式で作成されますが、文字化けしてしまいます・・・。（dockerで実行時。開発時のpython server.pyで実行する分には問題なし）
* 出力された画像ファイルが/workフォルダ内に溜まります。削除は行っていません。

本来であればissueで書くべきですね・・・。

なぜかタイムトライアル的な気分で突っ走ってリリースしてみました。
この後は腰を据えて対応していきたいと思います。
Pythonで毎日AtCoder #9

### はじめに
[前回](https://qiita.com/taxfree_python/items/1f25c79d16e5da5f6c22)
9日目です。今回からBeginnerタグをはずしてPyBegiタグにしました。PyBegiは自分が所属している勉強会です。

### #9
[問題](https://atcoder.jp/contests/abc091/tasks/abc091_b)

**考えたこと**
同じ文字列が複数あるケースがあるので、setに入れて重なりを消してからforで最大値を更新して計算しました。

```python
n = int(input())
s = [input() for _ in range(n)]
m = int(input())
t = [input() for _ in range(m)]

s_set = set(s)
t_set = set(t)
ans = 0
for i in s_set:
    p = s.count(i)
    q = t.count(i)
    ans = max(ans,p-q)
print(ans)
```
[コード](https://atcoder.jp/contests/abc091/submissions/10980788)
### まとめ
今回も解説が短かくなりました。では、また
メモリ

現在勉強している基本情報技術者試験についてまとめたものです。
自分のアウトプット用なので見やすさなどは期待しないでください。

# メモリの分類
**RAM(Random Access Memory)**
読み書きが自由にできるが、電源を切ると中身が消去される（揮発性）。

**DRAM(Dynamic RAM)**
安価で容量が大きく、主記憶装置に用いられる。
読み書きはSRAMに比べ低速で、記憶内容を保つためには定期的に内容を再読み書きするリフレッシュ動作が欠かせない。

**SRAM(Static RAM)**
DRAMに比べ非常に高速だが値段も高いため、小容量のキャッシュメモリとして用いられる。

**ROM(Read Only Memory)**
読み出し専用のため、動作に必要なプログラムやデータはあらかじめ書き込まれた状態で出荷される。
この時書き込まれた内容は、電源の状態に関係なく消えることはない（不揮発性）。

**PROM(Programmable ROM)**
ユーザーが手で書き換えることができるROM。
下記のような種類がある。

- EPROM(Erasable ROM)･･･紫外線でデータを消去して書き換える
- EEPROM(Electrically EPROM)･･･電気的にデータを消去して書き換える
- フラッシュメモリ･･･EEPROMの1種で、ブロック単位でデータを消去して書き換える

**キャッシュ**
記憶装置間の速度ギャップを埋めて、待ち時間のロスを防ぐための手法。

**キャッシュメモリ**
メモリとキャッシュの間に設ける、より高速に読み書きできるメモリ。
キャッシュメモリは重ねて設置することができ、CPUがアクセスする順番に1次、2次…と名前が付けられる。

**ディスクキャッシュ**
主記憶装置と磁気ディスク装置の間に設けるキャッシュ装置。
専用に半導体メモリを搭載したり、主記憶装置の一部を間借りするなどして実装する。

**記憶階層**
下記のような記憶装置の階層構造。

|速度|装置|容量|
|:-:|:-:|:-:|
|高速|レジスタ|小容量|
|↑|キャッシュメモリ|｜|
|｜|主記憶装置|｜|
|｜|ディスクキャッシュ|↓|
|低速|磁気ディスク装置|大容量|

**ライトスルー方式**
キャッシュメモリへの書き込みを行う際に、主記憶装置へも同時に書き込む方式。
高速化は望めないが、常にデータが一致している安心感がある。

**ライトバック方式**
普段はキャッシュメモリにしか書き込みを行わず、キャッシュメモリに入りきらないデータが発生した際に主記憶装置に書き込みを行う方式。
普段の処理は高速化できるが、制御が大変。

**ヒット率**
目的とするデータがキャッシュメモリに入っている確率。
逆に、キャッシュメモリになく主記憶装置に入っている確率を**1-ヒット率**という。

**実行アクセス時間**
キャッシュメモリを利用した平均的なアクセス時間のことで、[キャッシュメモリへのアクセス時間 * ヒット率]と[主記憶装置へのアクセス時間 * 1-ヒット率]を足すことで求めることができる。

**メモリインタリーブ**
主記憶装置の中を複数の区画に分割し、それらに同時にアクセスすることで連続した番地のデータを一気に読み出すことで高速化を図る。
ただし、ランダムアクセスなど連続しないデータの読み出しではあまり効果を発揮しない。
QumicoでReduceMean version 11 is not implemented.が出たときの対応方法

組込向け向けのフレームワークQumicoでONNXを変換しようとしたとき、このようなエラーが出たときの対応方法です。

エラーメッセージ

```python
  File "c:\home\myproj\qumico\qumico\common\exception.py", line 13, in __call__
    raise self._func(self.get_message(*args, **kwargs))
NotImplementedError: ReduceMean version 11 is not implemented.
```

QumicoがサポートしているOPの一覧はこちらにあります。
https://github.com/PasonaTech-Inc/Qumico/tree/master/qumico/handlers/backend

ReduceMean自体は対応しているのでversion 11の方が問題です。現在のQumicoが対応しているONNXはrequirements.txtに記載してあるONNX==1.15.0までです。調べてみると僕の環境はONNX==1.16.0だったので、ONNXのライブラリのバージョンを合わせたらエラーが消えました。

```sh
pip uninstall onnx
pip install onnx==1.5.0
```

QumicoのサンプルにはGoogle Colabファイルもあるので、自分の環境を変更したくない場合はColabベースで使うのも良いと思います。
【Sign in with Apple】「xxxxx@privaterelay.appleid.com」へメールを送った際バウンスする

# はじめに
Sign In with Apple（Appleログインと後述）が2019年に発表され、2020年4月には必須化になるなか導入の際にハマったインフラ系のことについてメモ書きしておきます。
私はiOSエンジニアではないですがPMやっていたときに遭遇しました。
ユーザ登録時にAppleログインで会員登録する際にメールアドレスをサービス提供側に公開するか非公開にするか選択があります。
非公開を選択した場合、サービス側が取得できるメールアドレスは「xxxx@privaterelay.appleid.com」になります。
本家サイトには「xxxx@privaterelay.appleid.com」に返信すれば登録ユーザに届くというようなことを書いているけどもGmailで送信した場合に下記の様にバウンスしてきました。これの解決方法です。

![apple_bounse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397770/7be4cf0d-d06b-67df-59e2-edc3420929f0.png)

# 本記事で力になれないこと
これ以上読んで頂いても目的のものが含まれていない可能性を提示します。

- Gmailから発信されたメールの転送
- Gsuiteからの発信されたメールの転送

本記事はDNS周りの設定がメインとなります。
Gsuiteからの送信についてはもしかしたらやりようがあるかもしれませんが、Apple側の設定ができず。。。Gmailがフリーメールであるため作成可能なため受信は難しいかもしれません。

# 解決策
SPF設定をしましょう（ドン！）

ここに書いてありあました。
https://developer.apple.com/documentation/signinwithapplejs/communicating_using_the_private_email_relay_service

>メールドメインを登録する
プライベートメールアドレスを持つユーザーにメールを送信するには、アウトバウンドメールまたはメールドメインを登録し、Sender Policy Framework（SPF）を使用してアウトバウンドメールを認証する必要があります。これらのメカニズムにより、このチャネルを介してユーザーとのみ通信できるようになり、スパムの通過を防ぎます。

by Google翻訳

ネットワークで、認証系、、、ちょっとだけアレルギーがでました

## SPFとは

細かい説明は下記サイトを見てください。
https://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/spf/


おさえておきたい事柄として、

**受信したメールのドメインが信頼されているサーバから発信されたものなのかを確認する機構です。**

![kamen_warui_businessman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397770/61670a10-31c2-a364-5b6a-46a7de2a18f6.png)

メールの送信者ってプログラムで指定（もとい偽装）できますよね。下のスクショでいう送信元の話です。
SPFはそれがあっても安全さを担保する仕組みと思ってください。
![スクリーンショット 2020-03-18 15.20.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397770/fb3f5319-7bca-eaf6-5ae2-c820aaf5ecc9.png)

## 送信者側設定
DNSの設定になります。
やることは対象ドメインに下記のTXTレコードを追加します。これで終了。
「このドメインはここから送信されたメールに対しては保証します！」って言うことなんですね
※自分自身は設定できません
`"v=spf1 include:[許可するドメイン名] ~all"`

設定の方法にはいろいろあるみたいなので必要に応じてアレンジできますね。
紹介されているのはIPアドレス、ドメイン名、メールサーバ、あわせ技ななどなど。
https://www.naritai.jp/guidance_spf_example.html

チェックツールもいくつかありました。
下記サイトで紹介されているみたいなのでどうしてもうまく行かないときとかは使ってみてもいいかもしれません。
自ドメインの設定が正しいかや、メールの一斉配信ツールなどでメールサーバが外部にあるときとかはspfの設定があるかを確認することもできます。
https://asumeru.net/spf-record-check

余談ではありますが今回nslookupのオプションでDNSのレコードを漁るということを覚えました。
これで、対象のドメインのDNS設定を観ることができます
`nslookup -type=[レコード名] [ドメイン名]`

例えば、
`nslookup -type=mx [ドメイン名]`
で、対象ドメインのメールサーバがわかります。

## Apple Developer側設定
下記の記事を参考にしてみてください。
やることとしては、受信可能にするドメインかメールアドレスを登録することだけです。
**送信元とFromが一緒であればここの設定だけで大丈夫だと思います（多分） **
https://notes.tret.jp/sign-in-with-apple-register/

#終わりに
Appleログインを実装する上では一定数ハマるひとがいなくなればといいなとおもいます。
セキュリティ周りをしっかりするのはいいけどもなかなか初見殺しで面倒に感じました。

あと、黒い画面でネットワークのコマンド打って、ちょっとかっこいいと感じてしまったのは秘密です。
VSCodeでPythonのvenv環境を作ったときハマったところ

ローカル環境でDynamoDb-Lambda用にPythonの仮想環境を構築したときにいつまで経っても
boto3がimportできなかったので、備忘録がてら手順をまとめたいと思います。

##環境の構築
- 仮想環境を作成します

```
$ python3 -m venv 環境の名前
```
- 作成した環境を有効にします

```
$ source 環境の名前/bin/activate
```
- 無事有効化されると以下の様な表示になります

```
(環境の名前) $
```
- 必要なパッケージをインストールします(今回であればboto3)  
  ちなみに私は環境に入らずにそのままインストールしてしまっていたためいつまで経ってもboto3が  
  仮想環境側に入っていませんでした。。。

```
$ pip install boto3
```
- `python -m pip list`コマンドで対象のパッケージがうまく入っているか確認します

```
$ python -m pip list

Package         Version
--------------- -------
boto3           1.12.23
botocore        1.15.23
docutils        0.15.2
jmespath        0.9.5
numpy           1.18.2
pip             19.0.3
python-dateutil 2.8.1
s3transfer      0.3.3
setuptools      40.8.0
six             1.14.0
urllib3         1.25.8
```
今回はうまく入っている様です。

##VSCode側での設定
- 今回作成したフォルダを開く
- setting.jsonを開いて以下を追記する  
  ここの記載を間違えたがばかりに仮想環境側ではない環境にパスがむいてしまいboto3がimportできませんでした...

```
"python.pythonPath": "bin/python3",
```

##参考サイト
- [【Python入門】venvで仮想環境を作る方法をわかりやすく解説](https://www.sejuku.net/blog/68423)
- [VS Codeのsettings.jsonの開き方](https://qiita.com/y-w/items/614843b259c04bb91495)
GitHub ActionsでOpenAPI Generatorを動かす [Docker版]

# TL;DR

API定義ファイルが更新されたらGitHub ActionsでOpenAPI Generatorを動かしてPRを作る

## 用意するもの

1. OpenAPI-Specification v3に準拠したAPI定義ファイル
    - [petstore.yaml](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore.yaml)を拝借
2. API定義ファイルを管理するリポジトリ
    - [**sample-openapi**][sample-openapi]
3. 生成したクライアントを管理するリポジトリ
    - [**client-openapi**][client-openapi]

# GitHub Actionsで動かすOpenAPI Generator

本編です

## 1. sample-openapiの用意

1. GitHub Actionsを作成

```yaml:generate.yaml
# This is a basic workflow to help you get started with Actions

name: generate

# Controls when the action will run. Triggers the workflow on push or pull request 
# events but only for the master branch and petstore.yaml
on:
  push:
    branches: [ master ]
    paths: petstore.yaml

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2

    # clientをcheckout
    - uses: actions/checkout@v2
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        repository: yumemi-nkomiya/github-actions-client-openapi
        path: client

    # openapi generate
    - uses: docker://openapitools/openapi-generator-cli
      with:
        args: generate -i ./petstore.yaml -g swift5 -o ./client/

    # Create pull request
    - uses: peter-evans/create-pull-request@v2
      with:
        token: ${{ secrets.REPO_ACCESS_TOKEN }}
        path: client
        commit-message: update client
        title: update client
        body: update client
        branch: feature/update_client
        branch-suffix: short-commit-hash # 同じプルリクは作らない
```

解説

- trigger

ブランチとファイルを条件指定

- clientをcheckout

**client-openapi**をチェックアウトします。
**client-openapi**がprivateなら`Personal access token`を作って**sample-openapi**のsecretsに登録して使います

- openapi generate

mavenビルドしてとか、jarをリポジトリに入れてとかあったんだけど公式に[Docker](https://hub.docker.com/r/openapitools/openapi-generator-cli/)が提供されているので利用する
パラメータは`args`に指定します

- Create pull request

**client-openapi**の権限がある`Personal access token`が必要

## 2. GitHub Actionsの実行

**sample-openapi**にpetstore.yamlをpush

- GitHub Actionsの実行結果

https://github.com/yumemi-nkomiya/github-actions-sample-openapi/actions/runs/57991712)

- 作成されたPR

https://github.com/yumemi-nkomiya/github-actions-client-openapi/pull/1

---

## おまけ

generatorがpodspecやPackage.swiftを生成してくれるのでCocoaPodsや、tag打つだけでSwiftPMやCarthageも対応できます

---

# 参考記事

- [
GithubActionsでOpenAPIGeneratorの生成機能を自動化する](https://qiita.com/u_nation/items/dcabf7abe84bfa85542b)

[sample-openapi]:https://github.com/yumemi-nkomiya/github-actions-sample-openapi
[client-openapi]:https://github.com/yumemi-nkomiya/github-actions-client-openapi
【AWS Elastic BeansTalk】Python アプリを爆速で展開

#はじめに
[前前回の記事に引き続き](https://qiita.com/JJ33/items/2f821b29cbabcaebd5fa)
AWS の自動化サービスである Elastic BeansTalk を、今度はコンソール画面のみで展開してみました。
びっくりするくらい簡単なのですぐにお試しできます！

![2020-03-06_13h39_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/92cdf1d1-28ea-677a-2e86-0496163b44c7.png)


#1.　プラットフォームを決める
今すぐ始めるをクリック。名前を決めて、基本設定の「プラットフォーム」のプルダウンで「事前設定済み」の「Python」を選択。
「アプリケーションコード」は「サンプルアプリケーション」を選択。
![2020-03-18_13h31_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/eb5167ed-1195-1dce-addd-3edd7da4bc19.png)

#2.　待つ
とくになにもせず数分待ちます。
![2020-03-18_13h32_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/9502bd24-7ad4-c45d-e1b1-079161503c55.png)
中では CloudFormation からスタックベースにアプリケーションのデプロイ環境がつくられており、VPC や EC2 インスタンス（セキュリティグループや Elastic IP）や データベース、S3 バケットがつくられ、後に設定をいじることもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/0986a935-40e8-25ea-79f7-99d6ee53bcac.png)


#3.　Pythonファイルをアップロードする
「最近のイベント」で更新状況が表示されます。モニタリングやアラームの設定を行うこともできます。
![2020-03-18_13h53_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/59002a3e-8918-61ea-68a7-771155b9e579.png)

[開発者ガイドのサンプルアプリ](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/tutorials.html)を使ってアプリケーションをアップロードします。
「実行バージョン」の「アップロードとデプロイ」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/14486485-4420-0d22-2405-0ff86e66ee88.png)
![2020-03-18_17h17_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/e8cf3aca-29a4-f78a-d714-f98f6b8e040e.png)



#4.　確認する
数秒でアップロードされ、ヘルスチェックされて「最近のイベント」が更新されます。
![2020-03-18_14h47_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/68b4df73-7582-f842-f522-2b0263e5688a.png)
URLをクリックして確認するとこんな画面がでてきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543340/f416758f-8de2-9c34-39ae-99d59ad30505.png)


#所感
とっても簡単で、秒でデプロイできました！
これならCLIやコマンドの知識がなくてもすぐにアプリケーションを展開できますし、一つの画面ですべてのリソースをらくらく組み立てられます！
まさに、インフラストラクチャを気にせずにアプリ開発に集中できるとはこのことですね！
#公式サイトリンク
[Elastic BeansTalk](https://aws.amazon.com/jp/elasticbeanstalk/)
[開発者ガイド](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/tutorials.html)
redisの原理

# 事の始まり
以前案件でRedis（ElastiCache）をクラスターモードを有効を用いる時Mgetができない問題に陥った。
その際にそもそもRedisってなんだろ（案件で使う前に考えろって話は置いときましょう。。。）と思い調べることにした。

## ハッシュスロット
redisがなんなのかって話は置いておこう。
キーの値をCRC16のチェックサム(データの信頼性を検査するための算出値)に16834の剰余である。
その値がハッシュスロットに入る。（スロットはノード番号と思ってたら良いかと）

## ノード
ハッシュスロットに入った値がノードの箇所を示しており、そのノード内からキーを検索する。そしてキーに紐づく値を取得するといった流れになっている。

## Mgetできなかった理由
ではなぜMgetできなかったのか。それはこちらのエラーになる。

```
ERR CROSSSLOT Keys in request don't hash to the same slot
```
と出てくる。つまりクラスターモードを有効にした場合、ノード間を渡って値を取得してきているがそれができないとのことらしい。

## ハッシュタグ
ではどう行なったのかというともう片方に寄せてしまおう作戦である。
ハッシュタグ({ } で囲まれた文字列)を利用することで{ } 内の文字列のみがハッシュスロットの計算に使用される。
そのため、setした値はハッシュタグを用いることで特定のノード内に保管されることになる。



[参考](https://www.sraoss.co.jp/tech-blog/redis/redis-cluster/)
Google ColabでYOLOの学習をする上でつまずいたエラー

本記事はGoogle Colab上でYOLOの学習をした際に解決に時間がかかったエラーをまとめたものです。
初歩的なものが多いですが大目に見ていただけると幸いです。
# 改行コード周り
``./src/utils.c:256: error: Assertion `0' failed``
色々原因があるようですが、私の場合.dataファイルの改行コードがCRLFになっていることが原因でした。
テキストエディタ等でLFに変更すれば治りました。
手元のWindows環境で動かす分にはエラーが出なかったので特定に時間がかかりました。

`STB Reason: can't fopen`
`Cannot load image "data/images/xxx.jpg`
原因はtrain.txtやtest.txtの改行コードがCRLFになっていることでした。
私はこちらの[procss.py](https://github.com/wakuphas/wakuphas/blob/master/AI/Scripts/process.py)を用いて学習・テストデータの振り分けをしていたのですが、Windows上で実行した場合勝手にCRLFになってしまうようで、少し改造する必要がありました。
参考にあるように、ファイルを開く際に改行コードをnewlineで指定してやると良いようです。

```py3
file_train = open(path_data + 'train.txt', 'w',newline="\n")
file_test = open(path_data + 'test.txt', 'w',newline="\n")
```

参考:[Windows上で実行したPythonの出力ファイルの改行コードが変わる](https://qiita.com/tatsuya-miyamoto/items/f57408064b803f55cf99)

# メモリ不足によるエラー
`/bin/bash: line 1: 761 Killed`
数字は時によって変わります。解決法からの類推ですが、Out of memoryエラーのことと思われます。
YOLOは.cfgで指定したbatch/subdivisionの枚数を一度に(ここ正確性に欠けます)処理するので、例えば batch 64 subdivision 16の場合は一度に4枚処理します。しかし、GPUの性能等の事情でメモリが足りずエラーが出るので、この場合はsubdivisonの値を順次増やしていけばよいです。
私は最終的にbatch 64 subdivison 64 で動かすとエラーを出さなくなりました。
処理速度とのトレードオフになってくるので、値をどの程度にするかはデータセットによって適宜調整する必要があります。
KubeEdgeとはなにか

# はじめに
仕事の一環でKubeEdgeを試す機会があったので、公式ドキュメントを読み解いてみます。


# KubeEdgeとは
[KubeEdge](https://kubeedge.io/)は[CNCF](https://www.cncf.io/)のサンドボックスプロジェクトとして開発が進められている、コンテナオーケストレーションをエッジに拡張するためのOSSです。
KubeEdgeはK8s上に構築され、エッジにネットワークやアプリケーションのデプロイ、エッジとマスター（公式サイトではクラウドを前提としていました）のメタデータ同期を提供してくれるようです。また、オフラインモードやMQTTを用いたエッジに接続したデバイスとの連携もサポートするようです。
要するにクラウドとエッジでKubernetesクラスターを組んだ際に起きる、NW不安定問題や、外部デバイスとの連携をうまーくラッピングしてくれるのがKubeEdgeと考えていいでしょう。
類似のプロダクトでK3sがありますが、K3sはK8sを最大限軽量化しており、K8sとクラスタを組むことはできませんが、KubeEdgeならK8sとクラスタを組むことができるので、クラウドと同じクラスタにエッジを所属させる、みたいな使い方ができそうですね。
クラウドにコントロールプレーンを持って、エッジのアプリケーションを管理する、みたいなことはKubeEdgeでもK3sでもできるはずです。

# KubeEdgeのコンポーネント
[公式ドキュメント](http://docs.kubeedge.io/en/latest/modules/kubeedge.html)からの転載になりますが、以下のコンポーネント構成となるようです。
気になるところは、Amazon EKSやGoogle GKEなどマネージドのコントロールプレーンが使えるかですね。
ドキュメントの表記だけではいまいちわかりませんでした。。

- Edged: エッジノードのエージェントで、コンテナ化されたアプリケーションを管理する
- EdgeHub: クラウドサービスとインターフェースするためのWebソケットクライアント（EdgeControllerと同義）。クラウド側のリソース更新をエッジに同期したり、エッジホストのステータスをクラウドにレポートしたりする。
- CloudHub: クラウドサイドの変更点をキャッシュしEdgeHubに送信するためのWebソケットサーバ。
- EdgeController: エッジホストとPodメタデータを管理する拡張Kubernetesコントローラ。
- EventBus: MQTTサーバ(mosquitto)とインターフェースするMQTTクライアント。他のコンポーネントにパブリッシュとサブスクライブの機能を提供する。
- DeviceTwin: デバイスのステータスを保存したり、デバイスステータスをクラウドに同期する機能を提供する。また、アプリケーション向けにクエリインターフェースも提供する。
- MetaManager: EdgedとEdgeHubの間のメッセージプロセッサ。軽量DB（SQLite)との間でメタデータの保存・取得する機能も有する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40643/bd12911e-0c29-5072-cbbf-473cd954f96f.png)

# KubeEdgeの動作要件
KubeEdgeのリポジトリをみると、KubeEdgeとK8s、Golangのバージョン要件は以下の通りのようです。
また、[Setup from KubeEdge Installer](http://docs.kubeedge.io/en/latest/setup/kubeedge_install_keadm.html)を確認するとイントールに用いるKubeEdge installerのサポートOSは現状Ubuntuのみのようです。CentOSやRasPiはまだ対応中の模様。

KubeEdge MasterとWorkerのインストール要件は以下。
### Cloud side (KubeEdge Master)
 - golang (If you want to compile KubeEdge)
 - Docker, or other runtime, such as containerd
 - kubeadm/ kubectl
 - Kubernetes cluster with kubeadm

### Edge side (KubeEdge Worker Node)
 - golang (If you want to compile KubeEdge)
 - Docker, or other runtime, such as containerd
 - mosquitto : If you are just trying KubeEdge, this step can be skipped.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40643/c3e8b2f6-8be3-7a4c-fec6-5ff7c1e7e41f.png)
転載元：[Github](https://github.com/kubeedge/kubeedge)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40643/d2b8fb9f-30c2-16bb-e5f5-bf7e1941b6a1.png)
転載元：[Start Developing KubeEdge](https://github.com/kubeedge/kubeedge/blob/master/docs/setup/develop_kubeedge.md)

# まとめ
KubeEdgeの概要、コンポーネント、動作要件を調査しました。
次回は[Amazon EKS上にKubeEdgeが構築できるのか](https://qiita.com/pideoh/items/77f384788b9616c73107)試してみたいと思います。

次回
[EKSでKubeEdgeを構築したら失敗した](https://qiita.com/pideoh/items/77f384788b9616c73107)
[KubeEdgeを構築する(再)](https://qiita.com/pideoh/items/cac19a32fdc723cca68d)を書きました。
IBM Watson Speech to Text API を使ってみた (Python)

## 経緯
PythonからIBMのAI、Watsonに音声データを送信して音声認識( Speech to Text )をしていきます。
API 初心者向けです。

## 環境
Macbook: MacOS Mojave
Python: Python 3.8.0

## 前提
Python インストール済
IBM Cloud アカウントを取得済 (アカウント作成は[こちら](https://www.ibm.com/watson)から。)

## インストール
ターミナル上、または python notebook 上で以下のコマンドを実行。

```
$ pip install "watson-developer-cloud>=1.4.0"
```

## 資格情報の確認
[IBM Cloud のサイト]((https://cloud.ibm.com/login))で Speech To Text を選択すると、マイアカウントから資格情報を確認出来るようになります。
API 鍵と URL をコピーし、以下のコード([こちらのコード](https://qiita.com/white0221/items/4135b48195f55ee5414b)を一部改変)にペースト。


```python
from watson_developer_cloud import SpeechToTextV1
import json

# define
apikey = "[API鍵]"
url = "[URL]"
audio_file = open("voice.wav", "rb")
cont_type = "audio/wav"
lang = "ja-JP_BroadbandModel"

# watson connection
stt = SpeechToTextV1(iam_apikey=apikey,url=url)
result_json = stt.recognize(audio=audio_file, content_type=cont_type, model=lang, timestamps = False)

#print
sttResult = result_json.get_result()
print(sttResult)

# json file save
result = json.dumps(result_json, indent=2)
f = open("result.json", "w")
f.write(result)
f.close()
```
txt ファイルで本文だけ取り出して保存したい時はこちら

```python
# txt file save
with open('result.txt', 'w') as f:
  raw_text=[]
  for i in range(len(sttResult["results"])):
      txt = sttResult["results"][i]["alternatives"][0]["transcript"]
      raw_text.append(txt)
  for i in range(len(raw_text)):
    f.write(raw_text[i])
```
以上！


## まとめ
認識精度は GCP 等の方がいいみたいですが、他サービスと比較して無料枠が大きく色々遊べる Watson もぜひ使ってみてください！

## 参考・引用元
[IBM Cloud 公式](https://cloud.ibm.com/login)
[IBM Cloud API Docs / Speech to Text](https://cloud.ibm.com/apidocs/speech-to-text/speech-to-text?code=python)
[[Python]WatsonのSpeech To Textを使うお話](https://qiita.com/white0221/items/4135b48195f55ee5414b)