OmniAICreator/Qiita-1.07M huggingface dataset:
Tk.textでログ表示させるときのハマりポイント

#初めに
職場でメモリリーク問題でトラブった調査してたら予想外の罠が見つかったので投稿します。
ちょっと乱文になると思うのですがご容赦ください。

#環境
OS:Windows10

```powershell:Anaconda&#x20;PowerShell&#x20;Prompt
(base) PS C:\Users\95315> python -V
Python 3.6.10 :: Anaconda, Inc.
(base) PS C:\Users\95315> conda -V
conda 4.9.2
(base) PS C:\Users\95315>conda list
…
tk                        8.6.8                hfa6e2cd_0
…
```

#何がしたかったのか

https://tkdocs.com/tutorial/text.html
上記ページのExample: Logging Windowの節を参考して欲しいのですがロガーの内容を引っ張ってTk.textで表示するプログラムを作ってました。
要は下のコードです。

```Python:
from tkinter import *
from tkinter import ttk

root = Tk()
log = Text(root, state='disabled', width=80, height=24, wrap='none')
log.grid()

def writeToLog(msg):
    numlines = int(log.index('end - 1 line').split('.')[0])
    log['state'] = 'normal'
    if numlines==24:
        log.delete(1.0, 2.0)
    if log.index('end-1c')!='1.0':
        log.insert('end', '\n')
    log.insert('end', msg)
    log['state'] = 'disabled'
```

#何が起きたのか
ロガーの表示内容がある行数を超えると頭から削除してたんですが、それでもメモリ消費量がモリモリ増えて最終的にPC毎メモリ不足で落ちるというヤバげな挙動を示しており頭が痛い不具合が出ておりました…。

#何がマズかったのか
色々探してたら以下のリファレンスがちょっと古いものの原因を記してました。
https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/text-undo-stack.html
>The Text widget has a built-in mechanism that allows you to implement undo and redo operations that can cancel or >reinstate changes to the text within the widget. 

要はTk.textはオプションでundo/redoスタックを持つよ。便利だね。
そうだね。勝手にONにしてスタック数無制限っぽい挙動をしなければ良かったね。

#んでどう直したか
要はスタックを無効にするだけです。ぶっちゃけさっきのコードで言えばこう直します。

```Python:
from tkinter import *
from tkinter import ttk

root = Tk()
log = Text(root, state='disabled', width=80, height=24, wrap='none',undo=False)
log.grid()

def writeToLog(msg):
    numlines = int(log.index('end - 1 line').split('.')[0])
    log['state'] = 'normal'
    if numlines==24:
        log.delete(1.0, 2.0)
    if log.index('end-1c')!='1.0':
        log.insert('end', '\n')
    log.insert('end', msg)
    log['state'] = 'disabled'
```

undo=Falseを追加するだけっすね。
~~俺はこの一行のためになんて時間を…~~
とまぁ割とえげつない話だったので記事にでもしとこう。~~そうでないと溜飲が下がらん。~~
というわけで記事にした次第です。

#終わりに
公式からリンク張ってあるようなTKDocsでもこういうことがあるので、もはや何を信用してよいやら…
とりあえず一つのソースだけじゃなくて多角的に色々探るってのは大事だと思った次第です。
だからTkinterはクソとかそういうつもりはないです。というかPythonでGUIはどれも色々あるし標準で用意されてるTkinter使ってもいいんじゃないっすかね。
こういうトラブルがいくつか埋まってるのが気になるなら良さげなライブラリ使うのも一考ですが。
後はまぁ集合知でこういうトラブルあったよということはQiitaの記事にジャンジャン書いていいんじゃないでしょうか。
辛いトラブル引いたときはまぁQiitaに書くネタが出来たとでも思えば多少は気が晴れます。
~~んでここからが怖い話なんですが、メモリリーク要因はまだもう一件残っててそっちも探して潰さないといけないんですよ…フフフ~~
とまぁあまり引っかかる人はいないと思うので読み物としてそういうことあるんだと思っていただければ幸いです。
ここまで読んでくださりありがとうございました。
【Go】go-oidcを使ってOpen ID Connectを利用する

## Open ID Connect
- outh2の進化版でトークン発行の処理がある
- アプリケーション自体にユーザーパスワードなどの認証情報を持たせずに、別のプロバイダー（ここではGoogle）に委任する
- プロバイダーはいろいろある
    - Google
    - AzureAD
    - AWS Cognito
    - outh0
- `state`という概念があり、クロスサイトスクリプティングなどのなりすましを防止

## 公式パッケージ
https://github.com/coreos/go-oidc

## インストール

```bash
git cloen https://github.com/coreos/go-oidc
```


## exampleのREADMEの通りにセットアップする

```
cd go-oidc/example
```

```
yuta:~/go-oidc/example (v3=) $ cat README.md
# Examples

These are example uses of the oidc package. Each requires a Google account and the client ID and secret of a registered OAuth2 application. To create one:

1. Visit your [Google Developer Console][google-developer-console].
2. Click "Credentials" on the left column.
3. Click the "Create credentials" button followed by "OAuth client ID".
4. Select "Web application" and add "http://127.0.0.1:5556/auth/google/callback" as an authorized redirect URI.
5. Click create and add the printed client ID and secret to your environment using the following variables:
```

### Google Developer Consoleへアクセス
https://console.developers.google.com/

### 認証情報（アプリケーション）を作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/ce317d16-08f4-d87b-341a-fd147a2fc32b.png)

### 設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/2de3b58d-19b8-b54e-3473-61bcf94675a0.png)

### 環境変数の設定
- `作成`すると、クライアントIDとクライアントシークレットが作られる

```
export GOOGLE_OAUTH2_CLIENT_ID=739786550065-g36863uform2efr5nrvvmjpj30pu9nuf.apps.googleusercontent.com
export GOOGLE_OAUTH2_CLIENT_SECRET=4sLRLGBdYu_un8C58c8Yg2yr
```

osパッケージで実行サーバのOS環境変数が読み込まれる

```golang
var (
  clientID     = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
  clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
)
```

## 動作確認

### 起動
```
yuta:~/go-oidc/example (v3=) $ go run idtoken/app.go
2021/01/17 16:13:04 listening on http://127.0.0.1:5556/
```

### `http://127.0.0.1:5556/`へアクセス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/2cecdb6c-17f6-ae50-a7f6-eff74f44d021.png)

### 認証成功時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/e1bb6266-1ef2-fb5b-e9df-42418bef1e47.png)
InfiniteScrollとkaminariで無限スクロールを作る

## 完成系
![2021-01-17 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169545/800ff264-5333-dcc6-8446-736baaf7a88f.png)


## 開発環境

```
rails 6.0.2
ubuntu(wsl)
InfiniteScroll 4.0.1
```

## 事前準備
- 投稿一覧
- 投稿一覧のデモデータ
- kaminariの導入

## 手順

### infinite-scrollの導入

[ここから](https://github.com/metafizzy/infinite-scroll)ダウンロードしてください。
CDNを使ってもokです。
自分は`vendor/assets/javascripts/`に置きました。（場所はどこでも良いです。）
ここの読み込む場所が違うとエラーになりました。
`//= require_tree .`の真下に置くと良いと思います。

```application.js
//= require infinite-scroll.pkgd.min
```

### 無限スクロールを実装

```talk.js
$(document).on('turbolinks:load', function () {
  if ($("nav ul.pagination a[rel=next]").length) {
    $('.talk-cards').infiniteScroll({
      path: "nav ul.pagination a[rel=next]",
      append: ".talk-cards .card-index",
      hideNav: "nav ul.pagination",
      history: false,
      scrollThreshold: false,
      button: ".loadmore-btn",
      status: ".page-load-status",
    });
  };
});
```
[公式サイト](https://infinite-scroll.com/)を見るのが一番良いと思いますが、オプションの説明しておきます。
`path`：次に読み込むページのURLの指定（必須）
`append`：読み込んだ次ページの内容のうち、追加する要素の指定。ここを間違るとレイアウト崩れたりする。
`history`：urlを変更し、履歴を残すか。 `false`なら固定のurlになる。
`hideNav`：非表示にするnavigationを指定する。
`scrollThreshold`：スクロールで自動で読み込むか。 `false`なら読み込まない。
`button`：ページをロードするためのボタン要素の指定。
`status`：読み込み中や全部読み込んだ後に表示するもの指定。

### 部分テンプレートと投稿一覧のビュー
cssは[こちら](https://codepen.io/desandro/pen/owWLYz)を参考にしてください。

```talks/_infinitescroll.html.slim
.loadmore-btn-wrapper.p-0.d-flex
  button.loadmore-btn.btn.active.mx-auto さらに表示
.page-load-status style="display: none"
  .infinite-scroll-request
    .loader-ellips
      span.loader-ellips__dot
      span.loader-ellips__dot
      span.loader-ellips__dot
      span.loader-ellips__dot
```
```talks/index.html.slim
.talk-cards
  - @talks.each do |talk|
    .card.mx-auto.card-index
      .card-body
        .card-title.text-muted.user-info
        #省略
          = link_to simple_format(h(talk.content), {}, sanitize: false, wrapper_tag: "div"), talk
  = paginate @talks
  = render "infinitescroll"
```
### 終わりに
もし間違がありましたら、編集リクエスト又はコメントお願いします。
上手く行かない場合は、developer toolsを使って頑張ってください。

### 参考文献
- [loader-ellips](https://codepen.io/desandro/pen/owWLYz)
【PHP】Ajax




```blade.php
<!-- ajax -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $('#answer-btn').on('click', function () {
      $question_id = {{ $question->id }};
      $answer_choice = {{ $question->answer_choice }};
      $answered_choice = Number($('input[name="answer"]:checked').val());
      console.log($answered_choice);
      console.log($answer_choice);
      console.log($question_id);
       $.ajax({
        type: "POST",
        url: "/question/choice",
        headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
        data: { 'answered_choice': $answered_choice, 'question_id': $question_id },
      });
    })
</script>
<!-- ajax -->
```

```QuestionController.php
  /**
   * Remove the specified resource from storage.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function choice(Request $request)
  {
      $answered_choice = $request->answered_choice;
      $question_id = $request->question_id;
      $question = Question::find($question_id);
      if($answered_choice == $question->answer_choice){
        $question->update(["status_num" => 2]);
      } else {
        $question->update(["status_num" => 3]);
      }
  }
```

```web.php
use App\Http\Controllers\QuestionController;
Route::resource('/question',  QuestionController::class)->middleware('auth');
Route::post('/question/choice',  [QuestionController::class, 'choice'])->middleware('auth');
```
Dagger Hiltで @Singleton を使うときの @InstallIn は SingletonComponent 



### 一行で言うと
`@Singleton` は `@InstallIn` が `SingletonComponent` じゃないと使えません。 [^1]




### 事象
`@InstallIn` が `ActivityComponent` の Module で `@Singleton` すると、以下のビルドエラーとなる。
```
error: [Dagger/IncompatiblyScopedBindings] com.example.XXXApplication_HiltComponents.ActivityC scoped with @dagger.hilt.android.scopes.ActivityScoped may not reference bindings with different scopes:  public abstract static class SingletonC implements XXXApplication_GeneratedInjector
```

[Hilt を使用した依存関係の注入  \|  Android デベロッパー  \|  Android Developers](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja) の例だと `@InstallIn` が ActivityComponent になっているので、注意しましょう。

### その他
Dagger Hiltは2021年3月時点で、2.33-betaです。

[^1]: Dagger 2.31以前は `ApplicationComponent` でしたが、 2.32から `SingletonComponent` に変わりました。2.32以上にあげると `error: cannot find symbol @dagger.hilt.InstallIn(value = {ApplicationComponent.class})` というエラーになります。
zabbixをdockercomposeで起動し動作確認する方法

#dockerのインストール
```
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum-config-manager --enable docker-ce-edge
$ sudo yum makecache fast
$ sudo yum install -y docker-ce
$ sudo systemctl start docker
$ sudo systemctl enable docker
$ sudo docker run hello-world
```

#dockercomposeのインストール
```
$ sudo -i
# curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# exit
$ docker-compose --version
```

#zabbixの入手
```
https://github.com/zabbix/zabbix-docker
cd zabbix-docker
```

#起動
docker-compose.yamlファイルの存在するディレクトリに移動

```
docker-compose up -d
```

#管理画面にアクセス
http://localhostでアクセス
![スクリーンショット 2021-01-17 16.02.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/cc101449-c6c8-6273-8780-a2e3d63b0bc7.png)

username,Passwordはyamlファイルで設定した値
デフォルトでは, usename:Admin Password:zabbix

ユーザ設定から言語、パスワードの変更が可能

![スクリーンショット 2021-01-17 16.11.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/5dbe4ced-f3fd-d3f3-9277-39f9764e5ddd.png)

![スクリーンショット 2021-01-17 16.12.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/a37f0a14-5636-f2ce-bbe9-68146db8b4ba.png)

#利用不可の解消
起動したばかりは、利用不可となって監視ができない状態となっている
設定項目のホストからZabbix serverを選択し、インターフェースのDNS名をzabbix-agentに変更し接続方法をDNSに設定.ポートを10050に変更すると負荷の状態を監視できる状態になる.
![スクリーンショット 2021-01-17 16.13.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/5d4c8cca-f3b3-b133-deff-893a162f0c31.png)

#動作確認
```
$ sudo docker run -d --rm -it --cpus=0.5 alpine dd if=/dev/zero of=/dev/null
```
このコマンドを打つことでCPUに50%の負荷をかけることが可能.
また、0.5の値を変えることで負荷の割合をかえることができる.
以下のコマンドでコンテナの負荷を確認.

```
docker stats
```

![スクリーンショット 2021-01-17 16.20.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/f792b47c-b6e8-9bc4-a8db-125fc54e559f.png)

このように、CPU使用率が50%となっている.

zabbixの方で確認してみるとコマンドを実行してから負荷が上がっていることがわかる.
![スクリーンショット 2021-01-17 16.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690609/d64b3187-e8bd-ef98-175b-f34fb32962e7.png)

#参考にした記事
https://qiita.com/zembutsu/items/d98099bf68399c56c236
https://qiita.com/dbgso/items/eb35a8ee9e1a5d4410c1
PowerAutomateで受付番号を作りたい

PowerApps で入力した内容で、SharePointOnline のリストに登録されたアイテムに対して、
”受付番号” 的なやつを追加してみたい! と思って試した結果を記録します。

受付番号はユニークな値であればよいので、リストにアイテムが登録されると自動的にふられる ”ID” の値をそのまま使うでもよいのですが。。。
それだけだと味気ないので、「日付 (年月日) + ID 」の組み合わせでそれっぽくしたいと思いました。

私自身まだまだ詳しくなく、色々と試行錯誤した結果なので、もしかしたら適切な方法ではないかもしれません。
もっといい方法がありましたら、ご教示いただけますと幸いです。

#1. SharePointOnline リストの設定
SharePointOnline リスト ”受付番号” の種類は、「 1 行テキスト」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996237/646f5f16-4df8-af88-d7d4-0fd1ab120604.png)

#2. PowerAutomate アクションの設定
"項目の更新" アクションの "受付番号" 項目へ以下関数を組み込みます。

string(concat(convertFromUtc(utcNow(),'Tokyo Standard Time','yyyyMMdd'),outputs('項目の取得')?['body/ID']))
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996237/0c9259ce-9d00-7282-bef5-87c8ad8a3046.png)

① : 以降の値を文字列化
② : 文字列の結合 (③ と ④ を結合)
③ : UTC時間を yyyymmdd の形式で日本時間へ変換
④ : 前段の "項目の取得" アクションの出力結果から、body に含まれる ID の値を動的に取得 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996237/40d69735-00d5-01ea-7596-316245d0f840.png)

#3. 実行結果
以下のように、 年月日 ＋ ID の値 "153" で、イメージ通りの受付番号ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996237/b9000412-c53e-7c6a-de31-e4a54c6f5867.png)

めでたしめでたし。
[Rails] deviseを利用したユーザー管理機能を実装する時、バリデーションで気をつけること


# 書くこと
Ruby on Railsでユーザー管理機能を実装する際に利用することができるgem、**devise**を導入して実装する際に、気を付けたいバリデーションのこと

# 環境
- Rails 6.0.3.4
- ruby 2.6.5

#概要
deviseという便利なgemがある。
ユーザー管理機能（ログイン・ログアウト・新規ユーザー登録など）実装を簡単に行うことができる。正し、バリデーションについては注意が必要である。
具体的には、デフォルトで付与されているバリデーションが存在することである。そのカラムは以下の二つ

1. email
2. password

である。

# 書こうと思った理由
筆者は、  　**「で、結局デフォのバリデーションってなんだっけ...」**となってしまうことが多々あるので、自分の備忘録として記録しようと思い書くことにした。（Qiitaに初投稿。）

# 結論

#### emailカラムには
- 一意性がある（被っちゃダメ）
- 存在が必須である
- @が必須である

#### passwordカラムには
- 存在が必須である
- 6文字以上であること
- パスワードと確認用パスワードが一致している

というバリデーションがかかっている。
じゃあ、どこでバリデーションの記述が？と思った方は

```user.rb
devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
```

この記述の中で、**validatable**によって、バリデーションが発動していることになる、と考えるといいと思う。

ちなみに、少し本題からは外れるが、devise以下の記述はそれぞれを**モジュール**と呼び、変更可能である。それぞれの機能を外したり、または追加したい場合は削除したり付け足したりすると、そのモジュールが呼び出され、使用可能になる。

間違い等あれば、是非ご指摘いただければと思います。


###参考文献
- pikawaka 【Rails】deviseの使い方をマスターしてログイン認証機能を実装しよう！
https://pikawaka.com/rails/devise#devise%E3%81%AE%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E4%BD%BF%E3%81%84%E6%96%B9
【Golang】サポートする GOOS と GOARCH を一覧で確認するコマンド（ビルドの対応プラットフォーム確認）

> `go build` する際に指定可能な `$GOOS` と `$GOARCH` の一覧を**コマンドで確認**したい。

なんか、Go 言語のバージョンだけでなく環境によってもビルドできる（サポートされた）OS やアーキテクチャが異なるようだったので、シェル・スクリプトで事前にチェックしたいのです。

[「golang GOOS 一覧 確認 コマンド」でググって](https://www.google.com/search?q=golang+GOOS+%E4%B8%80%E8%A6%A7+%E7%A2%BA%E8%AA%8D+%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)もピンポイントな記事が出てこなかったので、自分のググラビリティとして。

## TL; DR

> `go tool dist list`

## TS; DR

```shell-session
$ go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
...（以下省略）

$ go version
go version go1.15.6 linux/amd64
```

- とりま、どんなものがあるか知りたい人
  - [Go言語のクロスコンパイル設定値 $GOOS, $GOARCH 一覧リスト](https://qiita.com/suin/items/7ddfcbc708c8863ea76a) @ Qiita
  - [Environment](https://golang.org/doc/install/source#environment) | Install | Doc @ Golang.org （本家、英語）
- `$GOARM`（Arm 系 CPU の一覧）
  - https://github.com/golang/go/wiki/GoArm | wiki @ GitHub

## 参考文献

- [Gist コメント](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63#gistcomment-3129408) | Go (Golang) GOOS and GOARCH @ Gist by asukakenji
- [Go言語のクロスコンパイル設定値 $GOOS, $GOARCH 一覧リスト](https://qiita.com/suin/items/7ddfcbc708c8863ea76a) @ Qiita
- [Environment](https://golang.org/doc/install/source#environment) | Install | Doc @ Golang.org （本家、英語）
JavaEEとJakartaEE、どう違うの？

　よく考えてみると、わかりやすい説明がほとんどないことに気づきました。戸惑っている人も多いのではないかと思ったので、あえて、誤解をおそれず、本当のところ（と思うこと）をやさしく書いてみました。（もしも勘違いや間違いなどがあれば、お知らせください。）
#Java EEのままではいけなかったの？
　2017年に、Java EEがOaracle社からEclipse財団に移譲されるという記事を見て、最初に思ったことでした。今は、大分時間が経ったので、少しわかるような気がします。背景として、クラウドネイティブという大きな潮流があったことがあげられます。

　docker（2013年）やKubernetes（2015年）のようなシステムの登場が大きな契機でした。エンタープライズシステム開発の将来を予見するような、エポックメイキングなプロダクトです。ただ、Oracle社の動きは鈍く、意欲も見えなかったので、これに対して、コミュニティでは、 Java EE Guardiansを結成（2016年）し、Orcle社へ働きかけました。そして、Microprofile（2016年）が登場する一方、ようやく、Java EE8も公開されることになりました。

　Java界のエッジの部分で大きなパラダイムシフトが起きそうなのに、Oracle社はなかなか動かない、そういうジレンマがコミュニティの活動を巻き起こし、Jakarta EEの誕生へと向かっていくことになった大きな原因だったのでしょう。

 

#Java EE 8、そしてJakarta EE 8
　Java EE は、バージョン5（2006年）、6（2009年）、7（2013年）とバージョンを重ね、最後がJava EE 8（2017年）でした。開発の容易さを標榜して大きな成果をあげていたJavaEEですが、EE 8は、それまでのバージョンに加えて、JSFやCDIの改良、JPAのjava8対応、HTTP2への対応、そしてセキュリティAPIの追加など小さい変更に終わりました。MVCの追加も見送りになりましたが、Eclipse財団への移譲を控えて、あえて、大きな変更を避けたということだったのでしょう。
　
　Eclipse財団に移譲されたあと、移行作業が膨大なあまり、なかなか次のバージョンが出ませんでしたが、2019年にようやくJakarta EE 8が公開されました。しかし、何か新機能が追加されたわけではなく、Java EE 8のJakartaバージョンという位置づけです。
　機能を追加するには、Oracle社との権利関係にカタを付ける必要があったので、次のEE 9は、昨年12月でした。この辺りは、コロナ禍のせいばかりではなく、Oracle社が権利に固執しすぎたように思います。ただ、なんといっても営利企業ですから、仕方のないことだったのかもしれません。

# Jakarta EE 9の位置づけは？
　機能的には、Jakarta EE8と変わりません。つまり、2017年のJava EE8から3年、ほぼ何も変わっていません。本当に？
　いえいえ、Javax.から始まるライブラリ（Java EEのすべてのライブラリ）がなくなり、Jakarta.から始まるライブラリに置き換わっています。これが大きな変更です。jakarta EE 9はこのために作られたバージョンです。

　Oracle社が、javaxライブラリの改訂を認めなかったので、新機能を追加するには、最低限、名前を変える必要があったのです。ただ、すぐに理解できるように、ライブラリの名称を変更すると、過去のプロダクトとの互換性が失われます。Jakarta EE9 の依存関係の元では、Java EEはもとより、Jakarta EE8のプロダクトもコンパイルできません。
　影響は、PrimeFacesやOmniFacesなど、サードパーティのミドルウェア製品にもおよび、Jakarta EE9に対応しないと、使えないことになります（2021年1月現在、PrimeFacesは未対応のまま）。サードパーティ製品を使っているプロダクトは、その方面にも目配りが必要です。

　このように、影響が大きく広範囲に及ぶので、新生Jakart EEの出発点として開発されたバージョンが、Jakarta EE 9であると言えるでしょう。ですから、失われた数年間を取り戻すJakarta EEの巻き返しは、これから始まるところです。実際、コミュニティの熱気は相当なもので、来年にもリリースされるJakarta EE 10から、怒涛の快進撃（？）が始まるのではないかと期待しています。

#これからどこへ向かうのか？
　そうれは、もう、マイクロサービス化へ向かうというのが、常識的な見方です。ただ、現在、Java界に氾濫している様々な専門用語を見聞きして、驚いたりする必要はありません。まだ発展途上のジャングル状態ですが、いずれ、すっきりした体系にコモディティ化するはずです。そうでなければ、広範な活用は見込めないからです。

　基本的な考え方はシンプルです。システムを小さなサービスに分けて作り、それらをまとめ上げて、大きなサービスにするということです。ですから、Jakarta REST（RESTful ウェブサービス）が開発の基本単位になるでしょう。
　Jakarta RESTは、ユーザーインタフェースを持たないので、JSFアプリケーションのようなものは作れないのかというと、そうではありません。ユーザーインタフェースは、何で作ってもいいのです。もちろん、クライアントAPIというのがあるので、Javaでも作れます。JSFでも作れますし、時期バージョンでMVCシステムが入ってくると、それも大きな選択肢のひとつになるでしょう。

　これまでとの大きな違いは、メンテナンスの容易さです。ひとつのサービスの守備範囲は小さく、明快に役割分担を行います。ですから、改訂しようとすると、どこをどうすべきか、コードの迷路に迷い込むことはありません。また、使い勝手はUIにかかる部分ですが、これは、それぞれ独立しているので、どうにでも作り変えられます。別な言語で書き直すことすら可能です。

　いいことだらけなのですが、唯一難しいのは、サービス同士の連携で、マイクロプロファイルに含まれる部分です。この部分が、現在進行形でどんどん発展しているところです。また、最近、Jakarta EEへの統合を議論するコミュニティグループが立ち上がりました。その成果が公開される頃、次のフェーズが始まるのではないかと思います。
Azure IoT Hub に Node.js で publish

Ubuntu 20.10 で確認しました。
      
ライブラリーのインストール

```bash
sudo npm install -g azure-iot-device-mqtt
sudo npm install -g azure-iot-device
```

```js:azure_publish.js
#! /usr/bin/node
// ---------------------------------------------------------------
//	azure_publish.js
//
//					Jan/20/2021
//
// ---------------------------------------------------------------
'use strict'
var devicemqtt = require('azure-iot-device-mqtt')
var device = require('azure-iot-device')
const dotenv = require('dotenv')
//
// ---------------------------------------------------------------
function printResultFor(op) {
	return function printResult(err, res) {
	if (err) console.log(op + ' error: ' + err.toString())
	if (res) console.log(op + ' status: ' + res.constructor.name)
	}
}
// ---------------------------------------------------------------
function define_data_proc ()
{
	const device_id = "atami"
	const jikan= new Date()
	const hour = jikan.getHours()
	const minute = jikan.getMinutes()
	const second = jikan.getSeconds()
	const current_time = "" + hour + ":" + minute + ":" + second
        const tt = (20 + (Math.random() * 15)) * 10
        const temperature = Math.round (tt) / 10
        const hh = (60 + (Math.random() * 20)) * 10
        const humidity = Math.round (hh) / 10
        const ddx = { device_id: device_id, time: current_time, temperature: temperature, humidity: humidity }
        const data = JSON.stringify(ddx)

	return data
}

// ---------------------------------------------------------------
console.error ("*** 開始 ***")
dotenv.config()
const connectionString = `${process.env.CONNECTSTRING}`
console.log(connectionString)

var Message = device.Message

var client = devicemqtt.clientFromConnectionString(connectionString)

var connectCallback = function (err) {
if (err)
	{
	console.error('Could not connect: ' + err);
	}
else
	{
	console.log('Client connected')

	const data =  define_data_proc ()
	var message = new Message(data)
	console.log("Sending message: " + message.getData())
	client.sendEvent(message, printResultFor('send'))
console.error ("*** ppp ***")
	}
console.error ("*** qqq ***")
}

client.open(connectCallback)
console.error ("*** rrr ***")

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

```text:.env
CONNECTSTRING="HostName=iot-aa.azure-devices.net;DeviceId=pansy;SharedAccessKey=SvsFWVsCy2bJkH0QuPJeIabcdefgh8mo6S6vNCjom92="
```

プライマリ接続文字列 をポータルで調べる必要があります。
![primary_jan17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f6721fb9-1f3e-3d32-4779-75fcbc05428f.png)

次のコマンドでも調べることが出来ます。

```bash
az iot hub device-identity connection-string show --hub-name iot-aa \
	--device-id pansy --output table
```

実行コマンド

```bash
export NODE_PATH=/usr/lib/node_modules
./azure_publish.js
```

関連情報
[Azure IoT Hub に Node.js で subscribe](https://qiita.com/ekzemplaro/items/9933236f6c2ab3dee121)
【Promiseは規格？みたいなもの】

### 【Promiseとは】

Promiseはrejectedかfulfilledという結果が帰ってくることを約束してくれる。

そのため、それらに対するハンドリングがしやすいといったメリットがあると勉強していて感じた。実際、Node.jsの各メソッドをPromiseインスタンスに変換できるようなものが導入されたりとそのうちPromiseの規格に統一されるかもしれない。

### 【Promiseの挙動】

Promiseは、Promiseインスタンスを返す。

その時、Promiseインスタンスは最終的に、rejectedかfulfilledを返すが、それは以下のようにpendingな状態をreject()かresolve()で解決しないといけない。

```markdown
         pending
　　　　　　　↓
　　　　　　／ ＼
    reject()   resolve()
       ↓         ↓
　 rejected     fulfilled    <=  これらの状態をsettledという
```

### 【Promiseインスタンスをsettled状態にしてみる】

まずPromiseは`new Promise()` のようにして一度pendingな状態にする方法と、

pending状態を経ずに直接fulfilled、rejected状態にする2パターンある。

```js
// 一度pendingにする
// settledにするには一度変数に入れて、setTimeoutで3000経過させるなどしないといけない
function asyncFunc(){
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			try{ 
				resolve('成功')
			}catch(err){
				reject(err)
		}},3000)
	})
}
console.log(asyncFunc()) => Promise { <pending> }

// 直接resolve、rejected
Promise.resolve('成功') => Promise { '成功' }
Promise.reject(new Error('エラー')) => Promise { <rejected> Error: エラー ~~(省略)
```

### 【settled状態を利用して次の処理をおこなう】

.then()、.catch()、を使えば、Promiseインスタンスがsettledになったら、実行するコールバック処理を設置できる。

以下の処理は、Promiseが1でfulfilled状態になり、その結果を.then()のnumで受け取っている。

Promiseでコールバックヘルが解決できるのはこういったことができるからだ。

```js

Promise.resolve(1)
			 .then(num => console.log('resolve', num))
```

上記の.then()は省略されており、第二引数には.then()で起きたエラーの処理を受け取れるようになっている。しかし、これは.then()が多くなると長くなる。

.catch()を最後につけることで.then()で起きたエラーを全て一箇所で受け取れる。

```js

// 同じことをしている
Promise.resolve(1)
			 .then(
					num => console.log('resolve', num),
					err => new Error('エラー')
			 )

Promise.resolve(1)
			 .then(num => console.log('resolve', num))
			 .catch(err => new Error('エラー'))
```

### 【複数のPromiseを並行に処理してみる】

####・ Promise.all　

中のPromiseインスタンスが全部fulfilledになったら、その値でfulfilledを返す。

これだと各処理が平行に実行されるので効率がいい。

```js

const all = Promise.all(
	[1,Promise.resolve('成功'), Promise.resolve('fulfilled')]
)
all => Promise { [ 1, '成功', 'fulfilled' ] }
```

####・Promise.allSettled

中のPromiseインスタンスがfulfilledかrejectedかに関わらずそれぞれの結果を返す。

とりあえず結果をきにせず平行に処理したい時に便利かも。

```js

const allSettled = Promise.allSettled([
	Promise.resolve('成功'), Promise.reject(new Error('エラー'))
])
allSettled => Promise {[
	{ status: 'fulfilled', value: '成功' },
	{ status: 'rejected',
	  reason: Error: エラー ~ (省略)
```

Node.jsでよく使うasync awaitもPromiseインスタンスをawaitの直前に置くことで実装できるように設計されているためPromiseの理解が重要。
Unity Bloomがうまくいかない

Unityで物体を発光させるためにBloomというものを使えば簡単にできるという
記事をみたのでやってみたのですが、なぜかうまくいかない
テストで下記画像のようにできた！！
と思っていたのですが、、![2021-01-17 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560721/827b0cbf-4976-ab5e-e9fa-1b1ff7e792fb.png)

プラットフォームをIosにしたら効果が反映されませんでした。
おそらく対応されてないのでしょう。
プラットフォームを変更したら下記のようになってしまいます
![2021-01-17 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560721/2f476a97-2f27-1816-344a-63ab977068e1.png)
JavaでRSA公開鍵による暗号化と復号化の方法

RSAを使った暗号化と復号化のやり方を今日も忘れたので備忘録として残しておく。

マイクロサービスアーキテクチャにおいて、ユーザーの認証情報を引き渡していくための方法として、いろいろなやり方があるが、オーバーヘッドが小さく確実にサービス側、呼び出し元の相互に認証と認可が可能なので公開鍵を使った認証済みのユーザー情報の暗号化がいいと思う。

なお、RSAの場合、鍵長に1024ビットを指定すると128バイトとなり、パディングが11バイトなので暗号化可能な文字列の長さは117バイトまでとなる。

認証済みのユーザーのIDなどを送信するには十分であるが、このあたりは注意が必要だ。

## RSA鍵ペアの作成

```java
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024); // RSA鍵の長さを指定する
KeyPair keyPair = keyGen.generateKeyPair();
```

`KeyPair` には、秘密鍵と公開鍵の両方が含まれている。

## 秘密鍵のPEM形式での書き出し

```java
"-----BEGIN RSA PRIVATE KEY-----\r\n" + 
encodeBase64(keyPair.getPrivate().getEncoded()) + "\r\n" +
"-----END RSA PRIVATE KEY-----\r\n";
```

`encodeBase64(byte[])` は64文字ずつ改行を入れたBase64エンコードを行う関数。

## 公開鍵のPEM形式での書き出し

```java
"-----BEGIN PUBLIC KEY-----\r\n" +
encodeBase64(keyPair.getPublic().getEncoded()) + "\r\n" +
"-----END PUBLIC KEY-----\r\n";
```

## 公開鍵での暗号化

```java
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);

String encrypted = Base64.getEncoder()
    .encodeToString(cipher.doFinal(plainText.getBytes("ISO-8859-1")));
```

暗号化モードとして `ECB` を利用しているので、平文が同じ場合は常に同じ暗号文になる。これが許容できない場合はデータの頭にでも乱数でIVの代わりとなるダミーデータを入れておくとよいだろう。

## 秘密鍵での複合化

```java
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());

String plainText = new String(
    cipher.doFinal(Base64.getDecoder().decode(encrypted)), "ISO-8859-1");
```

## まとめ

JWTほど面倒ではなく、あらゆる言語環境で共通して利用可能なRSAによる暗号化はマイクロサービス間の認証と認可の現実解だ。
AWS Lambda Layersでsam buildを行うとファイルの階層が変わりimportエラーになる問題

## 概要

sam deploy刷る前にsam buildをするだけでLambda Functionからimportできなくなってしまったので原因を調べました。

## 対象コード

**Lambda Layer Template**

```yaml
Resources:
  SystemSharedLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      ContentUri: src/layers/system_shared
      CompatibleRuntimes:
        - python3.8
    Metadata:
      BuildMethod: python3.8
```

**Lambda Layer Src構造**

```
src
└── layers
    └── system_shared
        ├── python
        │   └── hogehoge.py
        └── requirements.txt
```

**呼び出し側**

```python
import hogehoge.py
```

## Lamnda Function側での展開パス

**sam buildしなかった場合**

```
/opt
└── python/
    └── hogehoge.py
```

**sam buildした場合**

```
/opt
└── python/
    └── python/    ←　余計なパスが付与される
        └── hogehoge.py
```

## 解決策

仕様が一貫していないので諦めてtemplate側の階層指定を切り替える

```yaml
Resources:
  SystemSharedLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      ContentUri: src/layers/system_shared/python
      CompatibleRuntimes:
        - python3.8
    Metadata:
      BuildMethod: python3.8
```
【emacs】company-ironyを導入してC言語補完環境を構築

ironyサーバーのビルドに失敗したので、その備忘録。

## 環境
macOS Mojava 10.14.6
GNU Emacs 26.3

## company-irony導入までの手順

ここは今回の主題ではないので、簡潔に（間違った箇所があるかも）。

まず必要なパッケージは以下で全部なはず。
company, irony, company-irony

例えば設定としては（.emacsなどに記述）

```emacs-lisp

;; companyとcompany-ironyを連携させる
(with-eval-after-load 'company
  (add-to-list 'company-backends 'company-irony))
;; Cファイルを開いたときにcompany, ironyモードが起動するようにする
(add-hook 'c-mode-hook lambda()(
    ('company-mode)
    ('irony-mode)
))
```

設定は以上だが、初回に

```emacs-lisp

M-x irony-install-server
```

を実行する必要がある。
returnを押すと以下が実行されることを確認してきて、再びreturnで実行される。

```emacs-lisp
cmake -DCMAKE_INSTALL_PREFIX\=/Users/myname/.emacs.d/irony/  /Users/myname/.emacs.d/elpa/irony-1.4.0/server && cmake --build . --use-stderr --config Release --target install
```

ここでエラーが出た。

## cmakeでエラー

エラーは以下のような内容。

Could NOT find LibClang (missing: LIBCLANG_LIBRARY LIBCLANG_INCLUDE_DIR)

## 解決策

まず`brew install llvm`でllvmをインストール。
ただしmacだと自動でこのllvmを見に行ってくれないらしい。

インストールされた場所を確認すると`/usr/local/opt/llvm`をリンクすればいいらしい。

```shell

$ brew info llvm
llvm: stable 11.0.0 (bottled), HEAD [keg-only]
Next-gen compiler infrastructure
https://llvm.org/
/usr/local/Cellar/llvm/11.0.0 (8,922 files, 1.3GB)
  Poured from bottle on 2021-01-16 at 18:53:48
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/llvm.rb
License: Apache-2.0
==> Dependencies
Build: cmake ✘, python@3.9 ✘
Required: libffi ✔
==> Options
--HEAD
	Install HEAD version
==> Caveats
To use the bundled libc++ please add the following LDFLAGS:
  LDFLAGS="-L/usr/local/opt/llvm/lib -Wl,-rpath,/usr/local/opt/llvm/lib"
<以下略>
```

ということで、cmakeする際に`-DCMAKE_PREFIX_PATH=/usr/local/opt/llvm`というフラグを追加するとうまくいった。

チャンチャン。
MYSQLコマンド

ポスグレとごっちゃになってしまっているので、まとめてみました。

####テーブル作成
```
mysql> CREATE DATABASE `testtable`;
```

####テーブル確認
```
show databases();
```
結果

```
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql_test         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)
```
このような表記が出る。

####現在接続しているDBの確認

```
mysql> SELECT database();
```

#### DB接続

```
mysql> use mysql_test;
Database changed
```

#### テーブル作成

```
mysql >  CREATE TABLE テーブル名(カラム名 データ型, カラム名 データ型)
```

#### テーブルの確認

```
mysql > show tables;
```

####  テーブルにデータをロードする

```
INSERT INTO テーブル名 VALUES (カラム１, カラム２, カラム３)
```

複数入れる場合

```
mysql > INSERT INTO pokemon VALUES
    (1, 'Andy', 35 , America, 'Ramen')
 ,(2, 'Betty', 26, Canada, 'Sushi')
 ,(3, 'Carol', 21, America, 'Sushi')
```

#### データを削除

```
DELETE FROM テーブル名
```

#### テーブルを削除

```
mysql > DROP FROM テーブル名;
```

#### DBを消す

```
mysql > DROP DATABASE データベース名;
```

### テーブルのデータ検索

```
SELECT * FROM テーブル名; 
```

必要なカラムの値を検索

```
SELECT カラム名1, カラム名2 FROM テーブル名; 
```

条件を指定してデータを検索

```
SELECT * FROM テーブル名 WHERE 条件文;
```
例

```
mysql> SELECT * FROM user WHERE food = 'Sushi';
+------+---------------+---------------------------+------------------------+
| id   | name          | country|       Food                                |                  
+------+---------------+---------------------------+------------------------+
|    1 | Betty         | America| Sushi                                     |                
|    7 | Yusuke        | Japan  | Sushi                                     |                 
|   21 | Zack          | India  | Sushi                                     |            
+------+---------------+---------------------------+------------------------+
3 rows in set (0.16 sec)
```
Unityでカメラの方向が変になる問題の解消

## 問題
Blenderで作ったモデルをUnityでインポートして使っていたが、ゲームを実行すると、本来のカメラとは別の視点から表示されてしまう問題が発生した。

## 解消法

この原因は、Blenderで作ったモデルに含まれているカメラからの視点になってしまっていたため。
モデル内のカメラを無効化したら解消した。

UnityとBlenderを使っていて初めて経験した現象なので、必ず起こるというわけではなさそう。

## 確認環境
MacBook Pro (16-inch 2019)
macOS Catalina 10.15.7
React Bootstrapのカレンダーを使う

## 概要
Reactのカレンダー用ライブラリといえば、[react-calendar](https://github.com/wojtekmaj/react-calendar)や[react-datepicker](https://github.com/Hacker0x01/react-datepicker)といったものが挙げられます。
これらのライブラリは機能も多いし便利なのですが、React Bootstrapを使っている場合は他のフォーム項目と同様の実装にしたいという思いがあって、React BootstrapでBootstrapのカレンダー用コンポーネントを使えないのかと考え少し調べてみました。

## 対応
[React Bootstrap Datepicker Example](https://www.nicesnippets.com/blog/react-bootstrap-datepicker-example)の記事にある通り、react-bootstrapのFormコンポーネントを使って`type="date"`と設定するだけです。react-calendarのように細かい制御まではできないと思いますが、Bootstrapを使っていてとりあえずカレンダーを表示させるだけで十分であれば、非常に簡単な実装で済ませられます。

## 表示イメージ
下記の通りテキストボックスとカレンダーボタンが表示されて、カレンダーボタンを押すとカレンダーが表示されます。
<img width="200" height="100" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/6a782386-1688-12c0-86d4-888fc4b82688.png">
テキストボックスでも日付は入力できるのですが、中途半端な入力でsubmitをすると自動でチェックをかけてくれます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32098/f2c0ab12-272d-50f8-920e-30a1d828e158.png">
新人教育マニュアル

##初心者が初心者を教えるという実情がある
初心者が初心者を教えているという環境は、
今やどの現場でもあるのではないでしょうか。  
私が未経験の新人さんと1年仕事して学んだ、
ちょっとしたコツをここにまとめようと思います。  
また、歴年の経験者の方は初心者が初心者を教えるときの
実情が分かるような記事にしたいと思っています。

そして私が初心者のときに考えていたことを
忘れないようにするためにここに残します。

##スペック
私　　　　→2年目
新人さん　→1年目

##教えていて思うことベスト3
1.前も言ったんだけどな〜
2.時間かかりすぎなんだけど何でかな〜
3.もっと早く報告してほしいな〜

これらは**教える側の指示指導が悪い**と思うべきです。
適切なプロセスを踏ませて、お互いハッピーに仕事しましょう。

>1.前も言ったんだけどな〜

**→心穏やかに、何度でも教えましょう**
根本から理解していないから、同じことをもう1度聞いてくるのです。
根本から理解できるように言い方を工夫する、図を描いて説明する、チャットにURLを貼ってあげるなど、自分で答えを出せるようにいろいろ工夫してあげましょう。
「前も言ったよ、研修でやったよ」というのは「お前は無能だな」と言っているに等しいです、次回から質問しにくいです。

>2.時間かかりすぎなんだけど何でかな〜

**→タスクの細分化してあげましょう**
やることを言われても、その手順がそもそも分からずに1歩も動けない状態に陥りがちです。
タスクを細分化して、「いつまでに、ここまでおいで」してあげることが大事です。新人が質問しやすくなります。今自分が何をしているか、分かりやすくなります。

>3.もっと早く報告してほしいな〜

**→あなたから声をかけましょう**
いつでも質問していいよーと言い続けるのは大事ですが、正直どんな先輩でも質問しにくいです、申し訳なく思います。なるべく上の立場の人間から声をかけてあげましょう。
30分調べてわからなかったら聞いてね、など具体的な数字を提示してあげると分かりやすいです。


##その他、教える側が意識すること
**・心理的安全性の確保**

>**心理的安全性とは?**
→発言しても否定されない、罰せられないこと。
→**心理的安全性がチームの構築に最も大事ですよ**とGoogleが発表したことで話題となりました。

あなたのチームでは、心理的安全性の確保は出来ていますか？

新人さんは「忙しいかな、こんなこと質問していいのかな、もう少し自分で何とか出来ないかな」と思いがちです。

自分で考えさせることはほどほどにして、こちらから手順解答を示すのが大事だと思います。
質問してくるということは、大体かなり考えてます、でも検索する方法が分からない、そもそも概念を把握していないので、適切な手段が踏めないのです。
こちらが思う制限時間を超えたらこちらから声をかけて手順や答えを教えましょう。

**・文字に残す**
一方的にベラベラ話して教えるのではなく、チャットに要点をまとめることを意識します。新人の理解度が増して、もう一度質問してくる回数が減るはずです。

**・分からないことは分からないという**
私にも分からないことだらけで正直新人を教えられるレベルに到達しているとは思えません。分からないことは分からないと伝えて、先輩に聞きます。



##新人の発言の読み解き

>新人さん「研修でやりました(｡･ω･)ﾉ！」  

**→研修で学んだ知識と、現場で通用する知識には雲泥の差がある**
**→研修でやりましたと言われても、おさらいも兼ねて基礎から説明する**

「研修でやりました！」と言われて、
「あーじゃあ基礎的な知識はあるし、やったことあるなら大丈夫だね。」と思っていました。**違います。**
「研修でやりました。」と言われても、基礎的な質問にも答えられないことが多いです。
この知識の差があることを把握していなかったので、会話が食い違ったり、余計な手戻りが発生します。
おさらいも兼ねて1から教えるor新人さんに説明してもらうのが良いです。
(実際は忙しいので、新人さんに説明してもらうのはちょっとキツイです)

>なんかエラーが出てます

→エラーの解決方法が分からない場合、エラーの調べ方から分かっていない場合が多いです。

・エラーの画面をスクショさせる
・エラーは調べたのか聞く
・ネットにはどういう解決法が載っていたのか聞く
・エラーの検索の仕方を教える
・画面共有で見てあげる

##終わりに
新人教育は現場に任せきりなのが現状なのではないでしょうか。

・心穏やかに
・心理学的手法に頼る
・新人教育から自分も学ぶ

この3点を意識すれば、自分も新人さんもハッピーに仕事出来るのかな？と思います。

##余談
>心理的手法に頼る

**・ピグマリオン効果**
期待をかけると成果が上がるという効果です。
(信憑性についてはわりと批判の多い効果です。)

期待をかけすぎるのも負担になるので良くないですが、
「私が1年目の時より出来てるから大丈夫だよ〜」というと誰も傷付かず、
安心する平和的手法だと思ってます。

(逆に期待しないことで成果が下がるゴーレム効果というのもあります。)

**・自己開示**
自分から自分のことを話すと、話しやすい人だと思ってくれます。
こんな映画観たよー、これ買いたいなーとか。
過去の栄光、仕事の愚痴、恋愛に関しては話さないほうが無難です。

**・好意の返報性**
何かしてもらったら、何かしてあげたいと思う原理の応用版。
新人さんのことを大切に扱いましょう。そして、新人さんもこちらのことを大切な人だと思ってくれることを願いましょう。
mac python 環境構築時のエラー

macにpython環境を構築する際に発生したエラーの対処方法が調べても出てきにくかったのでまとめました．

pythonのインストール時に以下のコマンドをターミナルに入力しました．

```
$ pyenv install 3.9.1
```

すると，以下のようなエラーが出てきました．

```
Last 10 log lines:
checking for python3.9... python3.9
checking for --enable-universalsdk... no
checking for --with-universal-archs... no
checking MACHDEP... "darwin"
checking for gcc... clang
checking whether the C compiler works... no
configure: error: in `/var/folders/9y/b18s20496nz6mc47pmf2czdm0000gn/T/python-build.20210117143950.2739/Python-3.9.1':
configure: error: C compiler cannot create executables
See `config.log' for more details
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

gcc(XcodeのCommand Line Tools)をインストールすると解決しました．


1.Xcodeを開き，左上(りんごマーク横)の
  Xcodeタブ>Open Developer Tool>More Developer Tools...

2.Xcodeのapple IDでログイン

3.Command Line Tools for Xcode 12.0.dmg(任意のバージョン)をダウンロード

4.インストール

5.インストールの確認

```
gcc -dumpversion   
12.0.0
```

以上の操作をしたところ，エラーがなくなりpythonをインストールできました．

```
pyenv install 3.9.1
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.1.tar.xz...
-> https://www.python.org/ftp/python/3.9.1/Python-3.9.1.tar.xz
Installing Python-3.9.1...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.9.1 to /Users/shogo/.pyenv/versions/3.9.1
【自己学習】スクラムについて学んだこと

![スクリーンショット 2021-01-17 13.11.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594740/e9e5aca4-4287-d159-1295-469666ec75aa.png)

上記を読み、学んだことをまとめた。

# スクラム開発とは
スプリントと呼ばれる短い期間（最長1か月）を何度も繰り返し、
その中で計画・設計・開発・テストなどを実施し、プロダクトバックログ項目（機能や要求、要望）を完成させるのに必要な作業を行うフレームワークのこと。

# スクラムについて最低限のルール（ルールを基に繰り返す）
 1. 5つのイベント  
   - スプリント
   - スプリント プランニング
   - デイリー スクラム
   - スプリント レビュー
   - スプリント レトロスペクティブ
   
 2. 3つのロール
   - プロダクトオーナー
   - 開発チーム
   - スクラムマスター
   
 3. 3つの作成物
   - プロダクトバックログ
   - スプリントバックログ
   - インクリメント

# 5つのイベントについて
### スプリント
スクラムでは固定の期間に区切って繰り返し開発を行う。
そのために期間は一定にして定める必要がある。

- 最長 1か月までの固定の期間に区切って繰り返し開発を行う。
- 最長 4週間として定める。
- 期間の長さが変わってはいけない。

### スプリント プランニング
スプリントで何を作るのか、どのように作るのかを計画したもの。

- スプリント計画会議とも呼ぶ
- スプリントで何を達成するかを決めて計画する。
- プロダクトバックログを基にして、プロダクトオーナーは何が欲しいか
- 開発チームはどれくらいでできそうか
- 開発チームはどうやって実現するか
- スプリントの目標をまとめたものをスプリントゴールと呼ぶ

### デイリースクラム
毎日行う朝会のようなもののこと。（実際に朝である必要はない）
ゴール達成に向けて進んでいるかを毎日検査する。
最低3つの定型の質問で答える形で進めていくことが多い。

- スプリントゴール達成のために、昨日やったことは何か？
- スプリントゴール達成のために、今日やることは何か？
- スプリントゴール達成するうえで、障害となるものはあるか？

### スプリント レビュー
スプリントの最後に、プロダクトオーナー主催でスプリントの成果をレビューするイベント。
プロダクトオーナーはスプリントレビューに必要な利害関係者（ステークホルダーと呼ぶ）
を招待して開催する。

- 開発チームのスプリント成果物を関係者にデモする
- フィードバックを得て、プロダクトバックログを見直す
- 全体の残作業や進捗をトラッキングする
- プロダクトオーナーが主催
- ステークホルダーに参加してもらう

### スプリント レトロスペクティブ
もっとうまく仕事が進められるようにカイゼンするための振り返り会
KPTや色々な振り返り方法がある

- もっとうまく仕事が進むようカイゼンを繰り返す
- バグを直すのではなく、バグが生まれるプロセスを直す
- うまくいったこと、今後の改善点を整理する
- 今後のアクションプランを作る
- 人、関係、プロセス、ツールなどの観点で今回のスプリントを検査する
- 一度にたくさんのことを変更しようとしない

# 3つのロールについて
### プロダクトオーナー
プロダクトバックログの管理責任者

- プロダクトのWhatを担当
- プロダクトの価値を最大化する
- プロダクトの責任者

### 開発チーム
モノを作る担当。実際に開発を行うメンバーのこと。

- プロダクトのHowを担当
- 3~9人が適切な規模
- 肩書きやサブチームはなし、平等な立場

### スクラムマスター
プロダクトをうまく作れるようにプロダクトオーナーや開発チームを支えるのがスクラムマスター。

- このフレームワーク・仕組みがまわるようにする
- 妨害の排除
- 支援と奉仕（サーバントリーダーシップ）
- マネージャーや管理者ではない
  - タスクのアサインも進捗管理もしない

# 3つの作成物について
### プロダクトバックログ
機能や要求、要望などプロダクトに必要なものを抽出し順番に並び変えたリスト。
順番が上位のものから開発を行う。
  
- 実現したいことをリストにして並び替える（優先度ではない）
- 常にメンテナンスして最新に保つ

### スプリントバックログ
具体的な作業を洗い出した作業計画

- 選択したプロダクトバックログ項目と実行計画
- プロダクトバックログを具体的な作業に分割する
- 1タスクは1日以内で終わるサイズ

### インクリメント
インクリメントとは。過去に作ったものと今回のスプリントで完成したプロダクトバックログ項目を合わせたもの。

- 開発チームは完成したインクリメントを作成する。
- インクリメントとはこれまでのスプリントでの成果と今スプリントで完成したプロダクトバックログ項目を合わせたもの
- リリースするかどうかに関係なく動作して検査可能でなければならない
- プロダクトオーナーと開発チームが「完成」について共通基準を持つ必要がある。これを「完成の定義」という。

# 書籍情報
SCRUM BOOT CAMP THE BOOK【増補改訂版】 スクラムチームではじめるアジャイル
https://www.amazon.co.jp/SCRUM-BOOT-CAMP-BOOK-E3-80-90-E5-A2-97-E8-A3-9C-E6-94-B9-E8-A8-82-E7-89-88-E3-80-91-E3-82-B9-E3-82/dp/4798163686/ref=dp_ob_image_bk

# 感想
正直なことを言えば「ことば」がカタカナばかりで覚えずらかった。
しかし、初めてでもわかりやすく書かれており、
実際の現場例を基に書かれていたのでイメージがしやすかった。
【Shopify】LiquidのMath filterを全てまとめてみた話

#はじめに
今回の記事では、ShopifyのMath filterを全てまとめてみました。

[こちら](https://shopify-dev.shopifycloud.com/docs/themes/liquid/reference/filters/math-filters)を参考にしました。

#Math filter
Mathフィルタを使うことで、**四則演算や四捨五入等の数学的処理**を行うことができます。

Mathフィルタも他のフィルタと同様に左から順に処理をし、複数の処理をつなげて書くことができます。

下の例では、`minus`の引き算、`times`の掛け算、`divided_by`の割り算の順で、処理されます。

```.liquid
You save {{ product.compare_at_price | minus: product.price | times: 100.0 | divided_by: product.compare_at_price }}%
```

それでは、Math filtersを見てみましょう。

##abs
``数値の絶対値を返します。``

```.liquid
{{ -17 | abs }}
```
>17

`abs`フィルタは、**数字のみの文字列でも処理ができます。**

```.liquid
{{ "-19.86" | abs }}
```
>19.86

##at_most
`数値を最大値に制限します。`

**`at_most`で指定した値よりも、入力値が大きいときに`at_most`で指定した数字を返し、指定した値以下のときは入力値をそのまま返します。**

例を見てみましょう。

入力値`4`に対して、`at_most`フィルタで最大値を`5`、`3`を設定しています。

最大値を`5`に設定したとき、入力値`4`よりも大きいため、そのまま`4`が返されます。

最大値を`3`に設定したとき、入力値`4`よりも小さいため、`at_most`で設定した`3`が返されます。

```.liquid
{{ 4 | at_most: 5 }}
{{ 4 | at_most: 3 }}
```
>4
3

**つまり、最大値を設定して、入力値が最大値を超えていたら、最大値を返すフィルタです。**

##at_least
`数値を最小値に制限します。`

`at_least`で指定した値よりも、入力値が小さいときに`at_least`で指定した値を返し、指定した値以上のときは入力値をそのまま返します。



```.liquid
{{ 4 | at_least: 5 }}
{{ 4 | at_least: 3 }}
```
>5
4

`at_most`と似たような処理の仕方をしていることがわかりますね。

`at_least`フィルタと、先程の`at_most`フィルタを用いることで、値の最小値や最大値を設定して返すことができます。

##ceil
`入力値を繰り上げて、整数を返します。`

```.liquid
{{ 4.6 | ceil }}
{{ 4.3 | ceil }}
```
>5
5

##divided_by

`divided_byで設定した値（下記例だと10）で入力値を除算した値を返します。`

```.liquid
<!-- product.price = 200 -->
{{ product.price | divided_by: 10 }}
```
>20

入力値か、divided_byで指定した値のどちらかに小数があれば、少数点以下を表示できます。

```.liquid
{{ 50 | divided_by: 10 }}
{{ 50 | divided_by: 10.0 }}
{{ 50.0 | divided_by: 10 }}
{{ 50.0 | divided_by: 10.0 }}
```
>5
5.0
5.0
5.0

##floor

`入力値の少数を切り捨て、整数を返します。`

```.liquid
{{ 4.6 | floor }}
{{ 4.3 | floor }}
```
>4
4

##minus

`入力値からminusで設定した値を引き算します。`

```.liquid
<!-- product.price = 200 -->
{{ product.price | minus: 15 }}
```
>185

##plus

`入力値からplusで設定した値を足し算します。`

```.liquid
<!-- product.price = 200 -->
{{ product.price | plus: 15 }}
```
>215

##round

`入力値を整数または任意の小数部の桁数にします。`

`round`に値を設定しない時は、四捨五入した**整数**を返します。

`round: 2`のように値を設定すると、**小数部の桁数を少数第二位までに四捨五入した値**を返します。

```.liquid
{{ 4.6 | round }}
{{ 4.3 | round }}
{{ 4.5612 | round: 2 }}
```
>5
4
4.56

##times

`入力値をtimesで設定した値で乗算します。`

```.liquid
<!-- product.price = 200 -->
{{ product.price | times: 1.15 }}
```
>230

##moudulo

`入力値を、moduloで設定した値で割り、その余りを返します。`

下記の例では、`12`を`5`で割ると`2`が余るので、`2`が出力されます。

```.liquid
{{ 12 | modulo:5 }}
```
>2

#終わりに
今回の記事はここまでになります。

お疲れさまでした。


# Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://coming-soon.reterior.jp/

https://apps.shopify.com/shopify-application-314?locale=ja&surface_detail=%E3%83%AA%E3%83%86%E3%83%AA%E3%82%A2&surface_inter_position=1&surface_intra_position=1&surface_type=search
【Tips】UITableView.tableHeaderViewのoffset

TIPSなのでサクッと終わります。

poしてみると分かりますが、`UITableView`の`tableHeaderView`を割り当てているとき、`tableView`の`contentOffset.y`はデフォルトでマイナスを示します。

`tableView`が`contentOffset.y==0`を示すのは、`tableHeaderView`分をピッタリスクロールした箇所です。

# 注意点
この挙動が気になるケースとして遭遇したのは以下です。

「`UINavigationBar`のタイトルをスクロール状態に応じて隠したり表示したりする場合に「なんかズレがあるなぁ」と思ったとき、実は上記の`tableHeaderView`分の高さだった」なんてことがありました。

もしサンプルであげたような問題に遭遇したら疑ってみましょう。
JavaScriptを学びたい初学者の【CODEPREP】メモ

#前提
・個人忘備録です
・JavaScript初心者
・CODEPREPで完結できず調べた内容をまとめた

#学習内容
JavaScript入門 基本操作編を終了しました
https://codeprep.jp/books/3

![スクリーンショット 2021-01-17 14.49.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298793/09356e31-2769-355e-3277-3eb5855e6e42.png)

#わからなかったところ

##Strictモードって何？
単元の最初の方、Strictモードで実行させましょう、というのがあります。（↓画像みたいな）
なんぞ？と思ったのでググってみました。
![スクリーンショット 2021-01-17 14.51.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298793/d68780ce-0830-5fc2-6bab-a89e08031de5.png)

ざっくり、**あなたの書いたJavaScriptを厳しめにチェックするよ**ってことだと思われる。
>strictモードでは、より的確なエラーチェックが行われるため、これまでエラーにならなかったような曖昧な実装がエラー扱いになります。このことにより、コード内に存在する潜在的な問題を早期に発見しやすくなります。また、JavaScriptエンジンによる最適化処理を困難にする誤りを修正するため、strictモードのコードは非strictモードの同一コードよりも高速に実行することができる場合があるなどのメリットがあります。

参照：https://analogic.jp/use-strict/

さらに、**具体的にはどんなことをチェックしてくれるか？**はこちら
参照：https://www.javadrive.jp/javascript/ini/index8.html

##厳密等価演算子って何？
こんな（===）やつ。左辺と右辺の値が同じかな？って比較している。
じゃあ等価演算子（==）と何が違うの？

```
 //厳密等価演算子
console.log(10 === 10);

 //等価演算子
console.log(10 == 10);
```
厳密等価演算子は**型を見る**。
等価演算子は**型を見ない**。

詳しくはこちら
https://qiita.com/SE-studying-now/items/438cbf32a1b31b2a714b


以上。
何かご指摘ありましたら、優しめな文章でコメントください笑
laravel 背景画像を固定化させる方法


#はじめに
1. 今回、久々にHTML CSSを編集して画像を背景にしたいと思い備忘録で投稿させて頂きます。
1. 画面をスクロールしても背景は固定化されている。
2. 背景の大きさは画面一杯に設定します。
3. Asset関数を使用してフォルダを参照します。
3. 写真素材はこちらでDLしました。[写真AC](https://www.photo-ac.com/)

#HTMLの編集
HTMLとCSSを結びつけるasset関数を記述して下さい。
` <link rel="stylesheet" href="{{ asset('css/sample.css') }}">`
これをhead内に記述して下さい。

```sample.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Sample Title</title>
    <link rel="stylesheet" href="{{ asset('css/sample.css') }}">//これを記述して下さい
</head>
<body>
</body>
```

#Asset関数とは
laravel独自のヘルパ関数の一つです。
画像やCSS、JavaScriptといったリソースデータの読み込みをする際に使います。
極論に言うと、publicフォルダの中を確実に参照させるために使います。
因みに`{{}}` の意味は、xssの対策です。


#CSSの編集
```sample.css
body {
  width: 100%;
  height:100vh;
  background-image: url(../images/4317917_m.jpg);  
  background-position: center center; 
  background-repeat: no-repeat;  
  background-attachment: fixed; 
  background-size: cover;
 }
```

###background-imageを使って画像を呼び出し
  background-image: url(../images/4317917_m.jpg); 
`..`は一つ上の階層フォルダを参照しているという意味になります。 
`/images` imagesというフォルダ(ＣＳＳと同じ位置に作ったフォルダ)を参照する。
最後に画像の名前をコピペ+`拡張子`も必ず記述。

###background-position: center center
画像を常に上下左右の中央に配置させる。

###background-repeat: no-repeat;  
画像を繰り返し表示しないようにする。

###background-attachment: fixed; 
ページなどのコンテンツの高さが画像より大きい場合は自動で調整してくれる。
  
###background-size: cover;
画面、ブラウザのサイズに基づいて、背景画像を調整。
このように画像いっぱいに画面を調整してくれます。以上です。
![“スクリーンショット” 2021-01-16 19.34.37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/a8098881-8d09-bebd-1fbb-a8c37ac47d9a.jpeg)


#参考にしたURL
[テックアカデミー] (https://techacademy.jp/magazine/8610)
[背景画像をブラウザいっぱいに表示しているCSS記述方法] (https://w.atwiki.jp/nicepaper/pages/50.html)
gitで差分を1行単位でcommitする方法

こんにちは、フロントエンドエンジニアの[てりー](https://twitter.com/teriteri_code)です。
僕の詳しいプロフィールは[こちら](https://terrblog.com/about/)

# はじめに
　チーム開発では、実際に本番環境に反映させたいコードのみを反映させることが重要になります。
 
commitメッセージに反する変更を加えずに開発を進めていく必要があります。
 
　これができないとコードレビューの際に、「これ消しておいて！！」の様なあまり生産的じゃない私的に時間を使ってしまいます。（僕はよくこれで怒られました！笑）
 
　この記事では自分が意図していない変更を含まない為に、commitを行単位で行う方法を普段自分が使っている手法を中心にまとめました。
 
　参考になれば幸いです。(作業環境はvscodeを想定しています)
 
# 1行単位でのcommitがなぜ必要なのか？
commitは作業ログではなく、実現した事ベースで行う事が望ましいと考えています。

参考[コミットは作業ログではない！](https://qiita.com/suzuki-hoge/items/cc91877ce69527ced692)

その理由について簡単にまとめると。

 ## バグを生む可能性があるから
機能を作る際に、それ以外の部分に影響を及ぼすコードは含まない事が望ましいです。
  
lintの設定、フォーマッターによる既存部分の不要なフォーマッティング、他の部分でちょっとした動作確認をした際に書いたコードetc..。
 　これらを本番環境に反映させると意図していない挙動になる場合があります。

 ## レビュアーがレビューしやすいから
 　例えばAの機能を作る際にB、Cの機能のコードが入っていると、レビュアーの可読性が下がってしまいます。
  

# 1行単位でcommitする方法

# git add -p
``git add -p``を使うと全ての差分をステージングするかどうかの取捨選択ができます。
例えばこのような変更があったとします。
[![Image from Gyazo](https://i.gyazo.com/953c3218f38e268f77c27e642f6fcddb.png)](https://gyazo.com/953c3218f38e268f77c27e642f6fcddb)

これに``git add -p``を行うと

```zsh

diff --git a/src/compornents/Banner.scss b/src/compornents/Banner.scss
index 1d275cb..cd7b375 100644
--- a/src/compornents/Banner.scss
+++ b/src/compornents/Banner.scss
@@ -11,7 +11,7 @@
 
   &-title {
     font-size: 3rem;
-    font-weight: 800;
+    font-weight: 900;
     padding-bottom: 0.3rem;
   }
 
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? 

```

と変更差分ごとにY/Nでステージングするかどうかを選択できます。
多くの差分がある際に有効です。

# vscodeから行う
vscode上で差分をステージングすることも可能です。
[![Image from Gyazo](https://i.gyazo.com/d463a07d7d7019e375b927171ff35912.gif)](https://gyazo.com/d463a07d7d7019e375b927171ff35912)
目視で意図した通りに1行単位でステージングできます。



# まとめ
commitやPRの粒度はプロジェクトのお作法によって食うrと思いますが、不要な変更を含めずにcommitできる様になるとチーム開発での不安は減ってくるかと思います。


#### もし現状の仕事に不満があるなら

転職ドラフトに登録して見てはいかがでしょうか？

実際に企業からのオファーを受ける事で、企業から見た自分の強みや市場価値などポジティブな発見がたくさんあります！！

https://terrblog.com/job-draft-merit/
初心者が1時間おきにiTunes ストアのトップソングの RSS 保存するbot作成

<h1>初めに</h1>

シェルスクリプトのファイルを touch コマンドで作成して、 chmod コマンドで実行権限をつける。


```touch itunes-topsong.sh
chmod a+x itunes-topsong.sh```

作成したファイル  `itunes-topsong.sh` を VS Code で開いて、シバンを入力する。

`#!/bin/bash`
ここまでは、シェルスクリプトを書く際のお決まりの手順。

<h1>要件定義</h1>
データの保存先となるディレクトリを作る
現在の時刻から、データを保存するファイル名を決める
そのファイルに、itunes topsongの毎時ランキングのデータを保存する

<h1>データの保存先となるディレクトリを作る</h1>


```itunes-topsong.sh
#!/bin/bash
dirname="/home/vagrant/workspace/itunes-topsong-rss"
mkdir -p $dirname
```

保存先ディレクトリを示す変数として dirname を使っています。
さらに mkdir コマンドに -p オプションを与えることで、すでにディレクトリが存在した時にも、問題なく動作する.


<h1>現在の時刻から、データを保存するファイル名を決める</h1>

```itunes-topsong.sh
filename="${dirname}/hourly-ranking-`date +'%Y%m%d%H%M'`.xml"
echo "Save to $filename"
```


変数 dirname が ${dirname} のような書き方になっています。変数の値を使うとき、区切りがスペースなどではない時は、今回の例のように変数名を { } で囲むことによって正しく呼び出すことができる。

またバッククォーテーション ` で囲んだ部分は、コマンドを実行した標準出力を文字列として取得して使う、という構文。

`date +'%Y%m%d%H%M'`

このコマンドを実行すると、202007101334 のような文字列が標準出力に出力されます。 バッククォーテーションによって、この実行結果が文字列として取り込まれることになりますので、結果として hourly-ranking-202007101334.xml のようなファイル名ができあがる。

#そのファイルに、itunes topsongの毎時ランキングのデータを保存する

```itunes-topsomg.sh
curl -s -H "User-Agent: CrawlBot; your@mail" -o $filename https://itunes.apple.com/jp/rss/topsongs/limit=10/xml
```

これまでも使用した curl コマンドに、何も表示せずに実行するための -s オプションと、結果を指定したファイルへ保存する -o オプションを指定しています。
さらに -H オプションに続けて、

"User-Agent: CrawlBot; your@mail"
と書くことで、HTTP のリクエストに、User-Agent というヘッダを追加。
your@mail の部分は、メールアドレス。

このように他のサイトにアクセスするボットを作る場合、設定ミスやバグなどによって意図せずサーバーに対して大きな負荷をかけてしまう可能性があります。 そのような場合に、サーバーの管理者がこのボットからのアクセスを遮断しやすくするために User-Agent を設定しています。また、万が一の場合に連絡を取りやすくするためにメールアドレスも追加しています。

実際に動かすとvs.codeで xml ファイルでランキング取得を確認できる。

#自動化
<strong>cron</strong>

`crontab -e`
2を選択し、vimエディタにする。

`Number  * * * * /home/vagrant/workspace/bot/niconico-ranking.sh`


Number に好きな数字を入力し、好きな時刻にランキングの取得。
Macでgqlgenのserver.goを起動するとファイアウォール警告が出る

GoのGraphQLサーバライブラリであるgqlgenの開発サーバ（GraphQL Playground）をMac上で起動すると、ファイアウォールの警告が出てしまってめんどくさい。
![20210108160313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9148/5e192904-6f03-13d6-85c8-5c0daf851b80.png)

通常はMacの環境設定のセキュリティとプライバシーのファイアウォール設定で例外を設定するのですが、うまくいかなかったので別の方法で解決します。

server.goの最後で次のようになっています。

```go
log.Fatal(http.ListenAndServe(":"+port, nil))
```

これだと「0.0.0.0」でlistenするようです。0.0.0.0はすべてのネットワークインタフェースを指し、過剰です。

以下のように「localhost」まはは「127.0.0.1」を明示するように変更します。

```go
log.Fatal(http.ListenAndServe("localhost:"+port, nil))
```

これで警告は出なくなりました。