OmniAICreator/Qiita-1.07M huggingface dataset:
macOS CatalinaでChromeからオレオレ証明書のHTTPSサイトにアクセスできない場合の対処法

macOS CatalinaのChromeで、オレオレ証明書を利用しているHTTPSの社内サイト等にアクセスすると、以下のように証明書エラーで閲覧できない（閲覧続行のボタンも表示されない）問題があるため、その対処法をメモしておく
<img width="1129" alt="00_Chromeで閲覧_設定変更前.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/3050ab4b-3e33-5724-c905-b290375e31db.png">

# 環境
- macOS Catalina 10.15.2
- Chrome 79.0.3945.88

# 手順
まず、**Safari**で該当サイトにアクセスし、警告画面で閲覧を続行する
![01_Safariで閲覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/3a455455-47ce-8580-509c-3841f5775fdb.png)

![02_Safariで閲覧続行.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/60d3eef5-6ca8-f46d-e894-178eee432461.png)

すると、「キーチェーン」アプリで該当サイトの証明書が追加されているはずなので、それをダブルクリック
![03_キーチェーン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/9016a5a4-9b5a-a27d-6f0c-8449647429bf.png)

「信頼」情報を展開する
![04_キーチェーン証明書詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/9f32f3e5-54ec-6bea-9d28-11556cf49925.png)

「この証明書を使用するとき」を「常に信頼」に変更する
![05_キーチェーン証明書詳細_信頼情報変更前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/96414ff6-b881-bbea-93f5-c448899a146e.png)

画面を閉じる際にログインユーザで認証することで、変更が確定する
![06_キーチェーン証明書詳細_信頼情報変更後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/ac6f7e24-ffd1-79f0-e03f-ff544d33ac13.png)

Chromeでアクセスできることを確認する

# 参考
- https://qiita.com/takky/items/2dbc431b278329465093
- https://qiita.com/suin/items/be87a7a581f30b38c5f7
マンガでわかる Visitor

![79EE08DE-CF05-4CCF-BC83-9EBA53327402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/57a7aa00-237a-59e4-e7bd-0f91feaece2d.png)

いつもお世話になってる上司さんに、めもりーちゃんサンタからクリスマス前倒しでこっそり街コンの案内をプレゼント。と思ったら、イケボCDなんて異なるソリューションもやってきました。さて、こみっとさんはどんなクリスマスを過ごすのかな。
(翌日「私...こんないじられキャラだっけ?」)

操作対象が操作の詳細を決められないとき、Visitor を受け入れられるようにだけしておけば、操作の詳細を除いて先に安定させてしまえる、というのがこのパターンです。やりたいことの詳細は後から別のパッケージで作ってもらうのです。やっぱりここでも DIP です。

こみっとさんはガードが固すぎて安定しちゃってるけど、夢見る乙女の心(枕元に靴下)を implements しているので、自分で自分を変えなきゃとがんばらなくても、Visitor がいれば寝ている間にうまういことやってもらえるわけです。

寝ている間にプレゼントをくれるサンタクロースはまさに Visitor パターンの典型例ですね。

サンタクロースのインスタンスは、クリスマスイブの夜に世界中の良い子のもとに訪れて、靴下にそっとプレゼントをインジェクションしては、誰にも知られず去っていきます。家に入って来たからといって、その行動に介入しないのがお約束です。夜中まで起きていて、サンタに向かって `getToys()` などと言ってはダメですよ。

煙突が Visitor を受け入れる `accept(Visitor v)` メソッドになります。その引数として侵入したサンタクロースが公開しているメソッドは `visit(Target t)` のみ。その中で何が行われるかはサンタクロースインスタンスにおまかせです。こみっとさんが本当に望んだプレゼントを入れてもらえたのかは、...まあサンタによりますが。

こみっとさんは寝ているので、Visitor は保持されません。適用される対象から見れば、Visitor がどこに住んでいるのかは知らないけれど、どこからともなくメソッドの引数としてやってきてうまくやってくれ、return 後は靴下にプレゼントが入っているだけ。

他の振る舞いに関するパターンと違う特徴がここです。もし Visitor が関数で、対象が集合だった場合、その集合の Iterator は acccept した visitor の visit に各要素を渡します。

`[1, 2, 3].map(function(n){ return n + 1; })`

なんだか馴染みある形になりました。クラスとインターフェースで考えると少し依存がややこしいのですが、いろいろ端折ってすごく大雑把にいうと、まあこんな感じです。安定しているオブジェクトに、後からやりたいことをスッと与えるわけです。

ただ、サンタに何でもして欲しいからといって、オープンすぎると泥棒にやられるかもしれません。

通常の外部からのアクセスに対しては、メソッドの少ない抽象型で公開しておき、 サンタだけが通れる `accept()` を通ればそこで初めて、`visit()` により公開情報の多い具象型(自分とサンタしか知らない)が明かされるといったような工夫ができます。

いよいよ明日はクリスマス・イブですね。Visitor に visit してもらえるように、良い子 (優秀なプログラマー) のみんなは accept を実装して (いちいち対象を変更しなくても、操作を後で決定できる設計をして) 待っててね。
rails indexってなんだ

## indexってなんだ

検索速度をあげるモノ

## なんで上がるのか

検索して行く時通常は、上から検索されていく。

しかし、indexをはると、userテーブルの場合、アルファベット順に並び替えてくれるらしい。


## こうゆうことか?

青山で検索する

```
#index貼らない

神田
青木
田中
青山

## データが煩雑なので、上から検索するしかない


# index貼る

青木
青山
神田
田中

## アルファベット順だからあ行の中で検索がかけられるのかな？
```

## メリット・デメリット

- デメリットは書き込み速度が遅くなるらしい。




## 参考記事

https://qiita.com/seiya1121/items/fb074d727c6f40a55f22

負荷対策
https://qiita.com/N-qiita/items/4c9b3efdaefb32181fc9
ショートカットキー

自分のメモ帳なので、都度更新しています。

##ショートカットキー


###Atom
| やりたいこと              |       コマンド（win)      |    メモ            |
|:-------------------------|-------------------------:|:------------------:|
| tree view の表示/非表示   |            ctrl + \      |              |
| 画面の分割                |  ctrl + k 一旦放して矢印（➡） |            |
| 画面を閉じる              | ctrl + w                 |            |
| 同じ単語を選択していく     | ctrl + D                 |  ctrl + U で解除   |
| ◎行目の〇文字に移動       | ctrl + G の後　◎:〇　    |  移動したい先の行と文字を入力する          |
| タグ内を全選択            | ctrl　+  Alt + ,         |           |
|  検索窓（プロジェクト内）  |  shift + ctrl + F               |           |
|  検索窓（ファイル内）     |  ctrl + F               |           |
|  検索窓（次の単語）        |  F3                     |             |
|  検索窓（前の単語）        |  shift + F3             |           |
|  コメントアウト     | ctrl + /    | 行にカーソルがあればOK          |
|  行の追加     |  ctrl + Enter   |  行中にカーソルがあってもOK         |
|  行の複製     | shift + ctrl + D    |           |
|  行の削除     |   shift + ctrl + K   |           |
|  コマンドパレット | shift + ctrl + P    |           |
|       |     |           |
|       |     |           |
|       |     |           |
- 自分でショートカットキーを設定したいとき
https://dotinstall.com/lessons/basic_atom_v2/38814


###Visual Studio Code
| やりたいこと              |       コマンド（win)      |    メモ            |
|:-------------------------|-------------------------:|:------------------:|
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |
|    |               |              |



###エディタの設定でまずやること

- Auto Save
- Tab Size
- Font Family
- Render Whitespace
- Word Wrap
- カラーテーマの変更
- ミニマップのOFF  

###ウィンドウ操作のショートカットキー

| やりたいこと              |       コマンド（win)      |    メモ            |
|:-------------------------|-------------------------:|:------------------:|
| デスクトップの表示   | win + D              |              |
|  アクティブウィンドウの最小最大 | win + ↑　or 　↓ |              |
| デュアルディスプレイ間移動  | win + shift + → |              |
|    |               |              |
元事務職がモデル駆動型アプリを使ってタスク管理を作ってみたの巻～その2～ 

#あらすじの巻

その1ではpowerAppsの画面はかんせーい！
したのURLみてねー

https://qiita.com/sayaka121413/items/84320244e41cd6515509

#作の巻

1,Powerautomateを開いて自動化されたフロー>commonDataserviceの[**レコードが作成されたとき**]>作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404009/47176413-dc1e-235e-b6e7-76352383977d.png)

2,環境/エンティティー名/スコープを入れる
・ 環境→**PowerApps画面を作成した環境**
・ エンティティー名→**タスク**
・ スコープ→**user**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404009/2cb89317-6818-5eea-8952-9d878c0dc71f.png)

3,新しいステップ>[**レコードの取得**]>環境/エンティティー名/項目識別子を入れる
・ 環境→**PowerApps画面を作成した環境**
・ エンティティー名→**タスク**
・ 項目識別子→動的なコンテンツの追加から**タスク**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404009/9f81c848-a8a7-b317-9b74-2fb98d5e2b5a.png)

4,新しいステップ>[**レコードの取得**]>環境/エンティティー名/項目識別子を入れる
・ 環境→**PowerApps画面を作成した環境**
・ エンティティー名→**ユーザー**
・ 項目識別子→動的なコンテンツの追加から**作成者**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404009/e707c7a7-b9a6-e5a7-c19a-b0a7d2f4a346.png)

5,新しいステップ>[**タスクを作成する**]>グループID/プランID/タイトル/パケットID/開始日時/期間日時/割り当てられたユーザーIDを入れる
・ グループID→**PowerApps画面を作成した環境**
・ プランID→**ユーザー**
・ タイトル→動的なコンテンツの追加から**件名**
・ パケットID→**To Do**
・ 開始日時→動的なコンテンツの追加から**開始日**
・ 期間日時→動的なコンテンツの追加から**期日**
・ 割り当てられたユーザーID→動的なコンテンツの追加から**既定電子メール**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404009/0ca3543e-ad9a-6b27-4923-5696f53a2584.png)

6,保存

#その3の巻
teamsのチャネルに送信してお知らせするのまきー
#Rails - In controller Block double request / duplicated proceeding with DB lock Transaction and respond ok or ng

```rb
class SomeController
  def create
    ProceedingHistory.transaction do
      begin
        ProceedingHistory.create(proceeding_id: proceeding_id)
      rescue ActiveRecord::RecordNotUnique
        head :bad_request
        return
      end

      do_something
    end

    head :ok
  end
end

```

```rb
# == Schema Information
#
# Table name: proceeding_histories
#
#  id              :bigint           not null, primary key
#  created_at      :datetime
#  proceeding_history_id :string(255)
#
# Indexes
#
#  index_proceeding_histories_on_proceeding_history_id  (proceeding_history_id) UNIQUE
#

class ProceedingHistory < ApplicationRecord
end

```

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
#Rails の controller で処理の多重送信を防ぐために、model に 処理のid単位の履歴テーブルを作成して、transaction lock と rollback を利用する例

処理一個はユニークな proceeding_id を持つものとする
重複処理が起こった場合はレコードがINSERTできずにbad request を返す
処理本体が失敗した場合はrollbackされて再度処理可能状態となる

```rb
class SomeController
  def create
    ProceedingHistory.transaction do
      begin
        ProceedingHistory.create(proceeding_id: proceeding_id)
      rescue ActiveRecord::RecordNotUnique
        head :bad_request
        return
      end

      do_something
    end

    head :ok
  end
end

```

```rb
# == Schema Information
#
# Table name: proceeding_histories
#
#  id              :bigint           not null, primary key
#  created_at      :datetime
#  proceeding_history_id :string(255)
#
# Indexes
#
#  index_proceeding_histories_on_proceeding_history_id  (proceeding_history_id) UNIQUE
#

class ProceedingHistory < ApplicationRecord
end

```

# Original by Github issue

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








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【Rails】Action Cable まとめ

TODO: 続き書く
# 1.はじめに
###Action Cable(以下AC)とは
WebSocket(以下WS)とRailsのその他の部分をシームレスに(継ぎ目のないように)統合するためのもの

ACが導入されたことで
リアルタイム機能をRubyでコーディングすることができる。

クライアント側のJavascriptフレームワークとサーバー側のRubyフレームワークを同時に提供する。フルスタックのフレームワークである。

# 2. 用語について
1個のACサーバーは、コネクションインスタンスを複数扱う事ができる。WSのコネクションごとに1つのコネクションインスタンスを持つ。

1人のユーザーは、ブラウザタブを複数開いたり複数のデバイスを用いている場合、アプリケーションに対して複数のWSコネクションをオープンする。WSコネクションのクライアントはコンシューマーと呼ばれる。

各コンシューマーは、複数のケーブルチャンネルに登録することができる。各CHには機能の論理的な単位がカプセル化され、そこで行われることがコントローラが通常のMVPセットアップで行うことと似てる。
trim()について

なぜtrimで全角スペースを削れると思ったのか:thinking:

```php
$str = "　sample　";
trim($str); // 「　sample　」 のまま
```

全角スペースを削るには色々手段がありますが、preg_replaceを使いたいと思います。

```php
function trim_space($str){
    return preg_replace('/^[ 　]*/u', '', preg_replace('/[ 　]*$/u', '', $str));
}

$str = "　sample　";
trim_space($str); // "sample"
```
「/(正規表現)/<font color="Red">u</font>」でUTF-8を明示的に指定するとなお安全。

※12/27 - trimと挙動が違っていたので修正しました
Railsでfullcalendarを使ってみる(Ajax通信でイベント登録)

# 概要
gemのfullcalndarを使ってイベントの登録をAjax通信でできるようにする。

- カレンダーの日付をクリックするとイベント登録用のモーダルが表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476948/0ff7636b-ca90-300c-4630-ed0bad1a2438.png)

- 登録ボタンを押すと、イベントが登録される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476948/580b162b-07a9-0eec-4ddb-c5fd2a952e45.png)

# コード
- jsファイル  
`dayClick`でカレンダーの日付をクリックした時のアクションを記述する。クリックした日付情報を取得し、イベント登録用のモーダルに自動入力させる。

```javascript:calendar.js

$('#calendar').fullCalendar({
    events: '/shops/events.json',
    timeFormat: 'H:mm',
    eventColor: '#63ceef',
    lang: 'ja',
    dayClick: function (start, end, jsEvent, view) {
      //クリックした日付情報を取得
      const year = moment(start).year();
      const month = moment(start).month()+1; //1月が0のため+1する
      const day = moment(start).date();
      //イベント登録のためnewアクションを発火
      $.ajax({
        type: 'GET',
        url: '/shops/events/new',
      }).done(function (res) {
        //イベント登録用のhtmlを作成
        $('.modal-body').html(res);
        //イベント登録フォームの日付をクリックした日付とする
        $('#event_start_time_1i').val(year);
        $('#event_start_time_2i').val(month);
        $('#event_start_time_3i').val(day);
        //イベント登録フォームのモーダル表示
        $('#modal').modal();
        // 成功処理
      }).fail(function (result) {
        // 失敗処理
        alert('エラーが発生しました。運営に問い合わせてください。')
      });
    },

  });
```

- イベントコントローラー  
`render_to_string`を使って、イベント登録フォームのviewを文字列として取得し、モーダル上に表示する。

```ruby:events_controller.rb
  def new
    @event = Event.new
    render plain: render_to_string(partial: 'form_new', layout: false, locals: { event: @event })
  end
```

- イベント登録フォーム  

```ruby:_form_new.html.slim
h1 新規イベント追加
= form_with model: event, url: shops_events_path do |f|
  = render "devise/shared/error_messages", resource: f.object
  .form-group
    = f.label :title
    = f.text_field :title, class:'form-control mb-3', required: true
  .form-group
      = f.label :start_time
      br
      = f.datetime_select :start_time, {default: Date.today + 19.hours + 00.minutes, minute_step: 10}, class:'form-control bootstrap-date mb-3'
  .form-group
    = f.label :description
    = f.text_area :description, class:'form-control mb-3'
  .actions
    = f.submit class: "btn btn-primary mb-3 js-event-create-btn"
```

- createアクション時の処理  
`removeEvents`の後、`refetchEvents`するとカレンダー上のイベントが再描画される。

```ruby:create.js.slim
| $('#modal').modal('toggle');
| $("#calendar").fullCalendar('removeEvents');
| $("#calendar").fullCalendar('refetchEvents');

```

# 結論
fullcalendarを使ってAjax通信でイベント登録することができた。
pythonで正弦波の音をステレオのwavで出力する

# はじめに
~~M-1が面白すぎて投稿が遅れてしまった。~~
　この記事は [Pythonその３ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/python3) の23日目の記事です。この記事ではnumpyなどで生成した正弦波をステレオのwav形式で出力する方法について記述します。

# 概要
今回はLchに880Hzの正弦波Rchに440Hzの正弦波を出力する5秒間のwavファイルを出力しようと思います。

## コード
```python

import numpy as np
import wave  # wave
import struct  # structpack

def createWavFile():
    Fs = 44.1*1000  # 44.1 kHz
    Lch = 880  # Hz
    Rch = 440  # Hz
    scale = 10**(-3/10)  # -6dBで生成
    t = 5  # 5秒
    N = Fs*t  # サンプル数
    filename = "L440R880.wav"

    # 正弦波の配列を生成
    sinwaveL = scale * np.array([np.sin(2*np.pi*Lch*n/Fs)
                                 for n in np.arange(N)])
    sinwaveR = scale * np.array([np.sin(2*np.pi*Rch*n/Fs)
                                 for n in np.arange(N)])

    # 16ビットに変換
    waveL = np.array([int(x * 32767.0) for x in sinwaveL])
    waveR = np.array([int(x * 32767.0) for x in sinwaveR])

    # ステレオ形式のwavのデータ構造に合わせ込む
    quantizeWave = np.array([[waveL[i], waveR[i]]
                             for i in range(int(N))]).flatten()

    # バイナリ化
    binwave = struct.pack("h" * len(waveL)*2, *quantizeWave)
    w = wave.Wave_write(filename)
    # (チャンネル数(1:モノラル,2:ステレオ)、サンプルサイズ(バイト)、サンプリング周波数、フレーム数、圧縮形式(今のところNONEのみ)、圧縮形式を人に判読可能な形にしたもの？通常、 'NONE' に対して 'not compressed' が返されます。)
  # 参考：https://docs.python.org/ja/3/library/wave.html
    p = (2, 2, Fs, len(binwave), 'NONE', 'not compressed')

    w.setparams(p)
    w.writeframes(binwave)
    w.close()

if __name__ == '__main__':
    createWavFile()
```

## 感想とか
Webで調べてもステレオでWAVファイルを生成する方法は見つからず途方にくれていましたが形になって良かったです

# 参考文献
[[python]　sin波の音をWAV形式で出力する](https://qiita.com/kinaonao/items/c3f2ef224878fbd232f5)
私のテキストエディタ使用遍歴

この記事は <a href="https://qiita.com/advent-calendar/2019/webcrew">ウェブクルー Advent Calendar 2019</a> 24日目の記事です。
昨日は@kouaresさんの[Kustomizeを運用に組み込んでみた](https://qiita.com/kouares/items/ea671b256ec589af7e14)でした。

#はじめに
メリー・クリスマス・イヴ:snowman2:
今年もいよいよ残すところ1週間ですね！

2010年代ももうすぐ終わり。最近はこの10年間を振り返っているのですが、
その中でもテキストエディタは10年間で様々なものが開発され、
目まぐるしい進化を遂げてきたコンテンツではないでしょうか。
私がフロントエンドエンジニアとして働き始めたのが2013年。現在に至るまで、
職場やトレンドの変化と共にあらゆるエディタを使用してきました。

今回は、私が今まで使用してきたテキストエディタを振り返って、
その中で最も使いやすいものを発表したいと思います。
各エディタを使用した際のレビューを記しておりますので、
パーソナルな内容にはなりますが、これからエディタを使っていく方、
今使っているエディタから別のものに変えたい方などの参考になれば幸いです。

#私のテキストエディタ使用遍歴

###[Coda（2013-2014）](https://panic.com/jp/coda/)
※( )は私が使用した年です。

Panic社が2007年に開発したmacOS用のテキストエディタ(有料)。
####使ってみて良かったこと
- 画面のデザインが綺麗で見やすい
- プレビュー画面が充実してる（PHPやJavaScript、jQueryの動作確認ができる）
- ブラウザチェックがスムーズにできる
- FTPクライアント機能が搭載されているため、データのアップロードが楽

####レビュー
当時私が入社した会社のPCがMacで、かつCodaを推奨していたため使用。

コーディングも初心者だったため、どういった面で使いやすい・使いづらいのかの
判断もできず「こんなもんなのかな」ととりあえず使用しておりました。
今になってみると、テキストの整形がワンタッチでできなかったり（プラグインを追加しないとできない）、
動作が重かったりなど、そのあたりが改善されていたらもっと使いやすかったなと思います。
有料のアプリなので、それだけの価値を見出せるかの覚悟も必要ですね。
デザインは綺麗で見やすかったですし、FTPが搭載されているのは便利でした！
初めて使ったテキストエディタということで、以降の指標にもなりましたし、個人的に思い出が多いです。

###[Adobe Dreamweaver CS5～CC（2014-2015）](https://www.adobe.com/jp/products/dreamweaver.html)
もはや説明不要。アドビ社による、テキストエディタというよりはWebオーサリングツール。

####使ってみて良かったこと
- クリッカブルマップで大活躍
- 検索・置換が見やすい（未だにそのためだけに使いますｗ）

####レビュー
2014年に転職をして、その職場のOSがwindowsだったのでcodaは使えず。
代わりにDreaweaverを使い始めました。

当時はクリッカブルマップを使う機会が多かったため、その点ではかなり活用させていただきました。
検索・置換も使いやすい、見やすいのも魅力です。
また、現在のCCは動作も軽くなり、かなり使いやすくなった印象です。
デザインもシンプルになったので、CCはオススメです。

###[NetBeans（2015-2018）](https://ja.netbeans.org/)
オラクルを中心としたコミュニティにより開発されたオープンソースの統合開発環境。

####使ってみて良かったこと
- とにかく軽い。作業がスムーズに進む
- コードの整形がワンタッチでできるので楽
- 日本語版のソフトが用意されているので安心

####レビュー
当時の職場にいた、とても優秀なエンジニアの方が勧めてくれたのをきっかけに使用。
以降、転職するまではずっと使用しておりました。
とにかく軽いので動作がスムーズですし、無料で使えるし、
コード補完機能もあるし、日本語にも対応してるし。使いやすかったですね。
余談ですが、NetBeans IDE 日本語コミュニティの公式マスコットの
「ねこび〜ん」がとってもカワイイです。

###[SublimeText（2018-2019）](https://www.sublimetext.com/)</a>
Jon Skinner氏によって2008年に開発されたテキストエディタ。

####使ってみて良かったこと
- 動作が軽い
- プライグインが豊富

####レビュー
転職して、約1年ほど使用しておりました。
世界的に人気なテキストエディタで、確かに使いやすかったけど…
「自分好みに使いやすくする」までが大変でした。
まず、デフォルトだと日本語に対応していないので設定が必要なのですが、
その設定が個人的には手間だなと…（[このサイトで詳しく紹介されております](https://proengineer.internous.co.jp/content/columnfeature/7341)）
日本語の文字検索もプラグインを入れないとできなかったり…。
設定が終わればとても使いやすいのですが、
別のPCでSublimeTextを使う場合は設定データをインポートしないといけないので、
手軽に、長く使うという点では私には向かなかったなぁと思います。

###[Visual Studio Code（2019-）](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)
マイクロソフト社によって2015年に開発されたテキストエディタ。

####使ってみて良かったこと
- 軽快な動作
- プラグインを入れなくともデフォルトの状態で使いやすい
- シンプルなで見やすい画面

####レビュー
webcrewに入社してから使い始めました。
社内のフロントエンドエンジニアの皆さんが使っているとのことで、それも納得。
とにかく使いやすいです。面倒な初期設定もありませんし、
プラグインがとても充実しているけど、デフォルトでも十分使いやすいので
インストールして日本語設定(これも簡単)すれば即、仕事に取り掛かれます。
実際、私は何のプラグインも入れてません笑 それでも何の問題もありません。
手軽にすぐ使えるのが素晴らしいと思います。

#一番使いやすいのは？
他にもAtomだったりVimだったり、メジャーなエディタはありますが
使ったことが無いため、完全に独断と偏見ではありますが…

###<b>Visual Studio Codeがダントツで使いやすいと思います。</b>
今一番オススメしたいテキストエディタですね。
シンプルで使いやすい。これ以上に何を求めましょうか。
2010年代のテキストエディタの代名詞だと思います。

2020年はどんなエディタが開発されるのか非常に楽しみですね。

明日の記事は@kamenbudoukaiさんです。
よろしくお願いします。
備忘録　さくらのVPSにAWXセットアップ

さくらのVPS
標準OS：CentOS7 x86_64
を新規追加した状態からのAWXセットアップ作業

```shell
cat /etc/redhat-release
# CentOS Linux release 7.7.1908 (Core)
```

```shell
yum update

yum install https://centos7.iuscommunity.org/ius-release.rpm

yum install python36 python36-pip python36-devel

pip3 install --upgrade pip

reboot
```

```shell
pip3 install ansible
```

```shell
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io
systemctl enable docker
systemctl start docker
pip install docker
```

```shell
yum -y install perl-TermReadKey perl-Error libsecret
yum --disablerepo=* --enablerepo=ius -y install git2u
👆ここでエラー
```

```shell
yum remove git
```

```shell
yum --disablerepo=* --enablerepo=ius -y install git2u
```

```shell
curl -sL https://rpm.nodesource.com/setup_10.x | bash -
yum install -y nodejs
```

```shell
pip install docker-compose
```

```shell
git clone https://github.com/ansible/awx
cd awx/installer/
ansible-playbook -i inventory install.yml
👆ここでエラー
```

```php
ailed to import the required Python library (Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.6)) on ik1-414-39139.vs.sakura.ne.jp's Python /usr/bin/python. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` or `pip install docker-py` (Python 2.6). The error was: No module named requests.exceptions"
```

./installer/inventory書き換え

```vimscript:/awx/installer/inventory
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/python3"
```

```shell
ansible-playbook -i inventory install.yml
```

##起動
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331573/2f284ec2-0b37-4498-9a93-6f9915614090.png)
基本情報10週目(12/23週)

# 目標と結果
### 目標
- 参考書をみる。
- 基礎理論とアルゴリズムの勉強を続ける。
    - 時間管理、工数管理も忘れずに。
- [基本情報技術者試験ドットコム](https://www.fe-siken.com/)を使う。
    - (午後問題もカバーされてる)
- 独習ゼミの解説動画を観てみる。
- 午後で通用する様に内容を理解する。
- 午後問題で重視する分野を見つける。

### 結果
- 卒業論文の作業に集中したので、午後問題にはまだ本格的に手をつけられなかった。
    - 1月の中頃までは大学が結構忙しいです……
- 忘れないように道場は継続しています。

# 振り返り
### Keep
- 道場は継続する

### Problem
- 大学が忙しいです……
    - 1月は卒業優先で頑張ります！
- 基礎的なこと(午前問題のような)を忘れないようにする。

### Try
- 1月の予定を立てる。
- 記事ステータスを「公開」にする。
BigQueryでURLをデコードする方法

関数で定義すればOK

```sql
CREATE TEMPORARY FUNCTION urlDecode(s STRING)
RETURNS STRING
LANGUAGE js AS "return decodeURI(s);";

-- with句でdbの代わりをしているだけです
-- アクセスログなどに代替してください
with db as (
    select '%e3%83%86%e3%82%b9%e3%83%88' as url
)

select
    urlDecode(db.url) AS decoded
from
    db
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105093/24fc5066-6ae9-d2b5-bf3a-b77f299b7355.png)
StartTag: invalid element name

# 背景
チーム開発において、developブランチからプルしてきた際に、xibファイルの変更による「問題の状況」のエラーをみたことがあると思います。検索してすぐに出てこなかったので、一応、記事にしておきます。

# 問題の状況
<img width="430" alt="gGgRq.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233118/ebeacb6d-2917-0a12-4c3e-dfeab118acd3.png">

# 解決方法：規定のxibファイルのコンフリクトを解消すればいい
この状態の問題は、xibファイル内に変更が加えられたために生じます。  
僕の知識の問題ですが、普通にはこのconflictを解消するためにファイルを開くことがXCodeの初期設定ではできません。  
きっと開く方法があると思うのですが、特に解決方法にこだわりがなければ、別のエディタで開くとファイルの中身が見れるので、すぐに修復可能です。大抵の場合は、HEADを残して変更をコミットすることになりそうです。

# まとめ
以下に参考記事を貼ります。  

参考： https://stackoverflow.com/questions/21818821/couldnt-open-xib-file-after-git-pull-invalid-element-name
備忘録　Node.jsでexportsを使ったモジュール化の作り方

Node.jsには、モジュール化といってさまざまな機能を持ったプログラムを個別のファイルに分割することができる。

効率よくコードを管理できるだけでなく、さまざまなユーザーが作成したプログラムを再利用しやすくできる。

Node.jsにはこのようなモジュールを管理できるツール「npm」や「yarn」等がある。

#「exports」
基本的なモジュール化の方法として「exports」がある。

exportsを使うと、指定した値を外部のNode.jsファイルから読み込んで再利用することができるようになる。

>**exports.プロパティ名 = 値**

この値は文字列・数値・配列・オブジェクト・関数など、さまざまなものを設定できる。

>**exports.str = 'こんにちは';**

>**exports.obj = {
  name: 'メロン',
  price: 500,
  store: '東京店舗'
};**

>**exports.func = function() {
  console.log('exportsの関数');
};**

#「module.exports」
module.exportsを利用するのが一般的。
両者の大きな違いは、プロパティ名付与せずに値を直接格納できるか。
module.exportsの場合、下記の様にプロパティ名をつけずに値を設定できる。

>**module.exports = {
  name: 'メロン',
  price: 500,
  store: '東京店舗'
};**

「module.exports」の場合はmoduleオブジェクトの中にあるexportsプロパティを参照している。

exportsも同じようにデフォルト状態ではmoduleオブジェクトの中にあるexportsプロパティを参照しているが、値を直接格納してしまうとそれはただの新しいオブジェクトに変わってしまうからモジュール化にはならない。

#まとめ
###・exportsは任意のプロパティ名を付与することでさまざまな値をモジュール化できる
###・module.exportsも同じことが実現できてプロパティ名無しでもモジュール化できる
###・exportsは必ずプロパティ名を付与しないと正しく機能しない
[OpenSiv3D] ローグライクサンプル (不思議であるダンジョン)

# 不思議であるダンジョンをつくった

OpenSiv3D v0.4.2で動作確認したローグライクサンプルを創りました。

# [ソースコード](https://github.com/Kasugaccho/Roguelike_Siv3D_Sample)

ソースコードは[**"こちら"**](https://github.com/Kasugaccho/Roguelike_Siv3D_Sample)。

(役立ったら、GitHubリポジトリにスターを押して頂けると励みになります)

[![Window.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213065/4e1e5c79-a31c-cc90-db10-e2fe9000839d.png)](https://github.com/Kasugaccho/Roguelike_Siv3D_Sample)

# 操作方法

|入力|説明|
|:---|:---|
|上矢印キー|画面の上へ進む。|
|下矢印キー|画面の下へ進む。|
|左矢印キー|画面の左へ進む。|
|右矢印キー|画面の右へ進む。|
|Wキー|画面の上へ進む。|
|Sキー|画面の下へ進む。|
|Aキー|画面の左へ進む。|
|Dキー|画面の右へ進む。|
|Nキー|サブマップの表示/非表示。|
|Mキー|マップの表示/非表示。|
|Lキー|補助タイルの表示/非表示。|
|Hキー|HPバーの表示/非表示。|
|1キー|カメラを遠ざける。|
|2キー|カメラを近づける。|
|3キー|全体のサブマップを表示する。|

[![GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213065/6170fca8-ba07-71a5-ec45-f8b328322a72.gif)](https://github.com/Kasugaccho/Roguelike_Siv3D_Sample)

このように動きます。


# 仕様

矢印キーまたはWASDキーを操作して上下左右に移動する。
その他のキーはサンプル用のお試し機能。
緑アイテム1を食べるとHPゲージ、緑アイテム2を食べるとHungerゲージが上昇する。
3ターンごとにHungerゲージが1減る。
Hungerゲージが0になると1ターンごとにHPが1減る。
HPゲージが0になるとゲームオーバー。
階段マスに(他のキーを押さずに)ぴったり止まると次の階へ移動できる。

# さいごに

OpenSiv3Dを使用してローグライクを作成することが出来ました。
何か参考になれば幸いです。
（ヘンテコなソースコードがあったら気軽にプルリクを飛ばして頂けると幸いです）
[Powershell] Azure Load Balancer のバックエンド プールに VM を追加/切り離す

本稿では、Azure ロードバランサー (Load Balancer) のバックエンド プールに仮想マシン (VM) を追加したり、バックエンド プールから切り離す Powershell コマンドを紹介します[^doc]。

[^doc]: ほぼ同じ内容が公式ドキュメントにかかれてますが、それを見やすくまとめました。 [PowerShell を使用して Azure の内部ロード バランサーを作成する - Azure Load Balancer | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-get-started-ilb-arm-ps#add-the-network-interface)

# 事前知識

- Azure Load Balancer のバックエンド プールで管理している実体は、VM ではなく NIC の IP 構成 (ipconfig)
- 取り外しの際は気にしなくてもいいけど、どのような VM (ipconfig) が追加出来るかは Azure Load Balancer に依存してるので注意
    - Basic SKU は同じ可用性セットじゃないと駄目
    - Standard SKU は複数可用性セット🆗
    - 参考:
        - 
[Azure Load Balancer の概要 - Azure Load Balancer | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-overview#skus)
        - [サポート エンジニアが Azure Networking をじっくりたっぷり語りつくす会](https://www.slideshare.net/ShuheiUda/azure-networking-165852712)
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127839/ba9f6bdb-211c-3943-dadb-bc558da547e3.png)
- 可用性セットについては次のような文献が大変参考になります
    - [Azure 可用性セットとリソースグループ、ロードバランサとオートスケーリングの関係性について - Qiita](https://qiita.com/U11/items/8fb3a8a29bc5fb00ebfe) 
    - [Azure 仮想マシンにおける可用性の考え方 – ainaba's blog](https://blogs.msdn.microsoft.com/ainaba-csa/2017/05/31/availability-of-azure-virtual-machines/)

# VM (ipconfig) の追加

```powershell
# LB を取得
$lb = Get-AzLoadBalancer –Name "<LB 名>" -ResourceGroupName "<LB のリソース グループ名>"

# バックエンド プールを取得
$backend = Get-AzLoadBalancerBackendAddressPoolConfig -Name "<バックエンド プール名>" -LoadBalancer $lb

# 関連付ける VM の NIC を取得
$nic = Get-AzNetworkInterface -Name "<NIC 名>" -ResourceGroupName "<NIC のリソース グループ名>"

# 指定の IP 構成をバックエンド プールに配置する
($nic.IpConfigurations | where Name -eq "<IP 構成名>").LoadBalancerBackendAddressPools = $backend

# NIC を更新
Set-AzNetworkInterface -NetworkInterface $nic
```

# VM (ipconfig) の切り離し

[Azure ロードバランサーのオフライン機能について - Qiita](https://qiita.com/Aida1971/items/b9f6720ac4da688ecb61#2-%E3%83%90%E3%83%83%E3%82%AF%E3%82%A8%E3%83%B3%E3%83%89%E3%83%97%E3%83%BC%E3%83%AB%E3%81%8B%E3%82%89%E5%A4%96%E3%81%99) の「2. バックエンドプールから外す」を、Powershell でやる場合の方法です。。

```powershell
# NIC を取得
$nic = Get-AzNetworkInterface –Name "<NIC 名>" -ResourceGroupname "<NIC のリソースグループ名>"

# 特定の IP 構成をバックエンド プールから切り離す
($nic.IpConfigurations | where Name -eq "<IP 構成名>").LoadBalancerBackendAddressPools = $Null

# NIC を更新
Set-AzNetworkInterface -NetworkInterface $nic
```


# 参考文献

- [Load Balancer | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/load-balancer/)
- [Azure ロードバランサーのオフライン機能について - Qiita](https://qiita.com/Aida1971/items/b9f6720ac4da688ecb61)
- [Azureのロードバランサ事情 - ロードバランサの中ってどうなっているの？ - - Qiita](https://qiita.com/yuhattor/items/60e4547019473761be3f)
- [Ananta: Azure を支えるステートフル L4 ロードバランサー - Qiita](https://qiita.com/OpenJNY/items/6c5e6614868c732dff3b)
強化学習41　ロボットの強化学習への第1歩　Colaboratory+Pybullet

　中学生から大学生のAI初学者を対象にしています。
本シリーズもここからは、対象が初学者なのかとの疑問もありますが、強化学習40までをやっていれば、中級くらいの内容かもしれません。
　ロボットの強化学習に突入です。
　この強化学習シリーズは、ここからロボットの機械学習と40までの内容をtensorflowで行うものを混ぜ込んでいきます。理由は、ロボット学習は機械学習の時間が数日かかるものもあるので、バックグランドで行いながら、数時間で終了するtensorflowも入れていくからです。
　
　さて、ロボットの機械学習ですが、chainerrlにあるroboschoolなるものをやろうと調べてみました。そうしたら、このプロジェクトは現在、deplecatedです。日本語に治すと非推奨？。これ以上やるなになっています。代わりに、pybulletに統合したので、そちらをやるように推奨されました。
　そこで、pybulletを調べましたが、OpenAIのgymに対応していることが分かりました。
　乱暴にローカルPCにpipをしたら、はじかれました。
sudoでやると通ります。

```bash
sudo pip install pybullet
```

Colaboratoryには、

```
!pip install pybullet
```
で数分間かけてインストールされました。途中でコンパイルしているみたいで、一度インストールすると、ランタイムを再起動しても残るみたいです。
なので、接続するたびに行えば済みます。
以下のようなcolaboratory　notebookで動画を見ることができます。
しかし、パラメータを変更して、再度見ようとするとうまくいきません。ランタイムを再起動する必要があります。


#画面のチェック
　最初に画面チェックするためのノートブックです。

　手順に沿ってやってみましょう。

　最終更新日　2019年12月23日

##program install
必要なプログラムをインストールします。数分で終了します。
pybullet　がかなりかかります。

```
!apt-get install -y xvfb python-opengl ffmpeg > /dev/null 2>&1
!pip install pyvirtualdisplay
!pip install pybullet
```
##パラメータの作成


```python

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--env', type=str, default='HumanoidBulletEnv-v0')
parser.add_argument('--outdir', type=str, default='result')
parser.add_argument('--save_mp4', type=str, default='test.mp4')
parser.add_argument('--mode',type=str,default='human')
args = parser.parse_args([])
```
##パラメータ設定
パラメータを設定します。

```python

#@title Configuration
args.outdir="result" #@param{type:"string"}
args.env = "HumanoidBulletEnv-v0" #@param ["HumanoidBulletEnv-v0","Acrobot-v1","Pendulum-v0","CartPole-v0","MountainCar-v0"]{allow-input: true}
args.save_mp4=args.outdir+'/pretrain.mp4'#@param{type:"string"}
args.mode='rgb_array'#@param{type:"string"}
import os
if not os.path.exists(args.outdir):
    os.makedirs(args.outdir)
```
##Evaluation
1回試行した結果が表示されます。動画は、outdir+'/pretrain.mp4'に出力されます。

```python

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1024, 768))
display.start()
%matplotlib inline
from IPython.display import HTML
from matplotlib import animation
import matplotlib.pyplot as plt
import gym
import pybullet_envs

env = gym.make(args.env)

frames = []
obs = env.reset()
done = False
R = 0
t = 0
while not done and t < 200:
  frames.append(env.render(mode = args.mode))
  action = env.action_space.sample()
  obs, r, done, _ = env.step(action)
  R += r
  t += 1
print('test episode:1',  'R:', R)
env.close()

plt.figure(figsize=(frames[0].shape[1]/72.0, frames[0].shape[0]/72.0),dpi=72)
patch = plt.imshow(frames[0])
plt.axis('off') 
def animate(i):
  patch.set_data(frames[i])
anim = animation.FuncAnimation(plt.gcf(), animate, frames=len(frames),interval=50)
#anim.save(save_mp4)
HTML(anim.to_jshtml())
```
Epoxyのスクロールがかくつくので調べたらリサイクルされていなかった


この記事はand factory Advent Calendar 2019の24日目の記事です

# きっかけ

とあるページの初回表示を高速化するためにをEpoxyのRecyclerView（以下、Epoxyと書きます）を使うようリファクタしました。

対象となるページの構成はこちらです。rootがLinearlayoutでその下にいくつかのViewをぶら下がっています。

```
LinearLayout // rootのViewGroup
  ∟ RecyclerView
  ∟ RelativeLayout
  ∟ RecyclerView
  ∟ RecyclerView
  ∟ LinearLayout
  ∟ ...
```

- 要素毎にaddViewしています。ただ、要素数がそれなりに多く、ページ初回表示するときに画面外の要素の処理も動いていました。

- Epoxyでは画面外要素の処理はページ表示した時に動かないので、ページ表示の高速化が期待できそうです :relaxed:


## LinearLayoutをEpoxyに切り替える

- 先ほどのrootに配置していたLinearLayoutをEpoxyに切り替えて、子ビューのコードを`EpoxyModelWithHolder`を拡張したクラスに移動しました

## 動作テスト

- 起動時のページ表示が早くなった（体感）気がします。少なくとも画面外の要素の処理は走っていないです。

- 古い端末だとスクロールでちょいちょいかくつきが気になります。

- 上下のスクロールを何度繰り返してもカクツクので、キャッシュが効いていなさそうです。EpoxyのViewPool周りの実装をみていきました。


## EppxyがViewPoolを管理している箇所

```kotlin:ActivityRecyclerPool.kt
internal class PoolReference(
    context: Context,
    val viewPool: RecyclerView.RecycledViewPool,
    private val parent: ActivityRecyclerPool
) : LifecycleObserver {
    private val contextReference: WeakReference<Context> = WeakReference(context)

    val context: Context? get() = contextReference.get()
```

- Epoxyは独自でViewPoolを管理しているようです。RecyclerViewでは１つのActivityで保持するインスタンスがViewTypeごとに５つまでと制限されていますが、Epoxyはこの制限が外されています。この辺りの仕様からもEpoxyとRecyclerViewが別々の実装を持っていることがなんとなくわかります。

- [ActivityRecyclerPool.kt](https://github.com/airbnb/epoxy/blob/ccc38fda40/epoxy-adapter/src/main/java/com/airbnb/epoxy/ActivityRecyclerPool.kt#L68)

## RecyclerView内でViewPoolからキャッシュを取得するコード

```java:RecyclerView.java
// この辺りでキャッシュを探しているようです（おそらく）

ViewHolder getScrapOrHiddenOrCachedHolderForPosition(int position, boolean dryRun) {
            final int scrapCount = mAttachedScrap.size();
// 省略..

            final int cacheSize = mCachedViews.size();
            for (int i = 0; i < cacheSize; i++) {
                final ViewHolder holder = mCachedViews.get(i);


```
- RecyclerViewでも保持しているViewPoolからキャッシュを探しているようです
- メソッド名からにじみ出ていますが、ViewPool以外でもキャッシュを保持しているクラスがいるようですね。adapterとかmChildHelperとか、どんな役割なのか気になります。
- [RecyclerView.java](https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java)

## 原因

- 今回のリファクタでrootのLinearLayoutをEpoxyに変更しましたが。子ビューで使っていたRecyclerViewはそのままだったのが原因でした。

- Epoxyは１つのActivity内のEpoxy同士で描画したViewをViewPoolにキャッシュして次回からリサイクルできますが、RecyclerviewのViewPoolはEpoxyのものとは別管理のため毎回inflateが発生していたため、古い端末でかくつきが起こっていました。:zap:


## 対応

- EpoxyとRecyclerViewの混在するとViewPoolの共有が上手くいかないことがわかったので、RecyclerViewをEpoxyに変更して古い端末でもカクツキが軽減されたことを確認しました。


## まとめ
- EpoxyはネストされたEpoxyでもViewPoolをデフォルトで共有してくれるので便利です。
- Epoxy使っているのにカクツクことがある場合は、子ビューにRecyclerViewが紛れていないか確認すると良いかもしれません。
- 公式でViePoolのことがちゃんと書いてあるので、しっかり読むの大事だなと思いました

## 参考
- https://github.com/airbnb/epoxy/wiki/EpoxyRecyclerView#shared-view-pool
DWHとは

DWHは、**Data WareHouse**の略。直訳で「データの倉庫」ですね。
雑に言えば、「データを貯めておくところ」でしょうか。

> データウェアハウス（DWH）とは、基幹系などの複数システムから、必要なデータを収集し、目的別に再構成した統合データベースです。
データ分析や意思決定に役立てる目的で編成され作られるため、BI（ビジネスインテリジェンス）に位置づけられます。
http://www.advanlink.co.jp/crmconsultation/crm_dwh.html

アクセスログとか購入ログとかを統合して、活用できるよう再構成するのもDWHの役目のようですね。
becaualizedse it was seri with a newer version of Unity. (Has a higher SerializedFile version)

2019.3から1に変えようとしたら発生

結論
新しいものから古いのにマテリアルとかコンバート不能
古いのから作ってアップコンバートしたほうがよろし

規格ちゃうねんな
PHPStanで素のPHPをテンプレートとして使うとき、htmlspecialcharsをチェックする

前に[テンプレートエンジンでも型チェックしたい](https://qiita.com/nishimura/items/bfabfb137abe42e62c39)ということを書いたが、まだ一点不満があった。

そもそもテンプレートエンジンを使う唯一にして最大のメリットは、`htmlspecialchars`を漏れなく実行することにある。
PHP自体がテンプレートエンジンと言われていても、別途テンプレートエンジンのライブラリを使うのは

```php
<?= $message ?>
```

というような出力を書いてしまってXSSが発生するということを防ぐのが目的である。
他の機能は、例えばBladeなら

```php
@if ($flg)
  <span>OK</span>
@endif

@foreach ($data as $key => $row)
  <div>{{ $row->id }}: {{ $row->name }}</div>
@endforeach

<?php if ($flg): ?>
  <span>OK</span>
<?php endif; ?>

<?php foreach ($data as $key => $row): ?>
  <div><?= $row->id ?>: <?= $row->name ?></div>
<?php ehdforeach; ?>
```

素のPHPを使ってもあまり変わらない。
違いは、`<?= $row->name ?>` の箇所が少々危険である、ということぐらいだ。
おそらく`<?= htmlspecialchars($row->name) ?>`と書きたかったはずだ。


つまり、素のPHPをテンプレートエンジンとして使ってPHPStanで型チェックをするためには、あと一手`htmlspecialchars`をチェックする機能も必要になってくる。


幸いPHPStanは拡張機能というプラグイン的な仕組みがあるので、ちょっとしたエラーチェックのルールを独自に追加できる。

なので作った。
https://github.com/nishimura/phpstan-echo-html-rule

```php:src/ProductDto.php
<?php

namespace App;

class ProductDto
{
    /** @var int */
    public $product_id;
    /** @var string */
    public $name;
    /** @var ?string */
    public $description;
}
```

このようなデータがあるとき、表示用のHTMLを含むPHPテンプレートクラスは

```php:src/ProductHtml.php
<?php
namespace App;
class ProductHtml {
    public function view(ProductDto $product): void {
?>

<div>
  <div>
    <?= $product->product_id ?>
  </div>
  <div>
    <?= $product->name ?>
  </div>
  <div>
    <?= $product->description ?>
  </div>
</div>

<?php
    }
}
```

こんな感じになるだろう。
`phpstan-echo-html-rule`を使えば

```
 3/3 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ---------------------------------------------------- 
  Line   ProductHtml.php                                     
 ------ ---------------------------------------------------- 
  16     Parameter #1 (string) is not safehtml-string.       
  19     Parameter #1 (string|null) is not safehtml-string.  
 ------ ---------------------------------------------------- 

                                                                                
 [ERROR] Found 2 errors
```

`htmlspecialchars`を使わずに出力している箇所のエラーを報告してくれるようにした。
独自の仮想的な型`safehtml-string`を導入したので、`htmlspecialchars`は`safehtml-string`を返す必要がある。

```php:functions.php
<?php

/**
 * @param int|string|null $input
 * @return safehtml-string
 */
function h($input)
{
    return htmlspecialchars((string)$input);
}

/**
 * @param int|string|null $input
 * @return safehtml-string
 */
function raw($input)
{
    return (string)$input;
}
```

このようなユーティリティ関数を用意する。

そしてエラーを修正する。

```php:src/ProductHtml.php
<?php
namespace App;
class ProductHtml {
    public function view(ProductDto $product): void {
?>

<div>
  <div>
    <?= $product->product_id ?>
  </div>
  <div>
    <?= h($product->name) ?>
  </div>
  <div>
    <?= h($product->description) ?>
  </div>
</div>

<?php
    }
}
```

これでテンプレートエンジンを使わなくても`htmlspecialchars`なしの出力を網羅的にチェックできるようになった。
外部サーバのファイルをzipファイルにまとめてローカルにダウンロードする方法

## 外部サーバ接続
sshで外部サーバに接続します。
(root のパスワードを聞かれる)

```
自分のパソコン$ ssh root@xxx.xxx.xxx.xxx
```

## 外部サーバで zip ファイル作成

目的のディレクトリ target に移動します。
(target ディレクトリの中身を全て zip ファイルとしてダウンロードする場合)

```
外部サーバ$ cd target
```

目的のディレクトリでzip作成します。
source.zip という名前で target ディレクトリ配下のファイルが全て zip ファイルにまとめます。

```
外部サーバ$ zip -r source *
```

zip コマンドが使えない場合は zip をインストールします。

```
外部サーバ$ yum install zip
```

sshを切断します。

```
外部サーバ$ exit
```

## zip ファイルをローカルにダウンロード

自分のパソコンに先ほど作った外部サーバの zip ファイルをダウンロードします。
下の例だと /home ディレクトリにダウンロードされます。
(root のパスワードを聞かれる)

```
自分のパソコン$scp root@xxx.xxx.xxx.xxx:target/source.zip /home
```
WrikeとAppsScriptでバーンダウンチャート作成

#はじめに
初めまして、サムザップの白濱です
本記事は、[サムザップ Advent Calendar 2019 #2]
(https://qiita.com/advent-calendar/2019/sumzap2) の12/25の記事です。

今回は、WrikeとAppsScriptを使用してバーンダウンチャートを作成して
運用しましたので、そちらの話をしたいと思います

#作成のきっかけ
タスク消化の管理にWrikeを使用していますが、
プロジェクトの開発が終盤になってくるとタスクの消化の推移を管理する必要がでてきました。
そのため、バーンダウンチャートを作成しようとしましたが、Wrikeにいいチャートがなかったので
自作することにしました

#構成
以下の流れで、バーンダウンチャートを作成しました

1. GoogleAppsScriptを毎日実施
2. GoogleAppsScriptでWrikeAPIを実施して、タスク情報を取得する
3. タスク情報から総タスク数と終了したタスクから、GoogleSpreadシートに日々グラフを作成

#Wrikeから情報を取得する
まず、Wrikeから情報を取得する部分を解説します

1. WrikeのAPIアプリを作成
　まず、Wrikeのタスク情報を外部から取得するために、
  Wrikeでアプリを作成して、WrikeのTokenを取得しておきます
　![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/1b0463cc-fe34-ecee-80b4-74b30ca66b32.png)

2. AppsScriptからWrikeのAPIを実施して、タスク情報を取得
　WrikeのTokenを使用して、Google AppsScriptからAPIを実施して、情報を取得します

　WrikeからいろいろなAPIが提供されています。
　こちらを使用して、バーンダウンチャートに必要な様々な情報を取得します

　WrikeAPI仕様（v4）
　https://developers.wrike.com/documentation/api/overview

　・チームメンバーの情報を取得（contacts）
  　　バーンダウン対象のチームメンバーの情報は、**ttps://www.wrike.com/api/v4/contacts** で取得できます

　・タスクのステータスの情報を取得（workflows）
　　タスクのステータス情報は**ttps://www.wrike.com/api/v4/workflows** で取得できます

　・タスク情報を取得（tasks）
　　タスクの情報は、**ttps://www.wrike.com/api/v4/tasks** で取得できます
  
AppsScriptからのAPI実施例
```
param = workflows
  var url = "https://www.wrike.com/api/v4/" + param;
  var response = UrlFetchApp.fetch(url,options);
  var projects = JSON.parse(response.getContentText());
```

APIからは以下のようなJSONが返ってきます
```
{
   "kind": "workflows",
   "data":
   [
       {
           "id": "IEAAAAJ6K77777WC",
           "name": "Default Workflow",
           "standard": true,
           "hidden": false,
           "customStatuses":
           [
               {
                   "id": "IEAAAAJ6JMAAAAAA",
                   "name": "New",
                   "standardName": true,
                   "color": "Blue",
                   "standard": true,
                   "group": "Active",
                   "hidden": false
               },
```

#バーンダウン完成イメージ
集計を日々とると、以下のようなバーンダウンが完成しました

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/ed3f5294-7438-af91-183d-9e63ced67894.png)


#Slack投稿
集計したタイミングで、slackにも日々投稿するようにして、メンバー内で「消化してる感」を共有しました
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265768/28f91497-a71b-ceb5-3e1d-834ce95ca3f5.png)


#作成にあたって注意した点

・taskes APIの取得制限
　taskesでは、Wrikeのフォルダ配下のタスクが全て取得できますが、タスク数が大量にある場合は
　取得数制限に引っかかってしまいます（MAX 1000件）
　プロジェクトが大きくなると、総件数1000件を超えるケースも出てくると思います。

　それを回避するため、子フォルダや孫フォルダ単位に小分けにしてAPI取得しました
　フォルダ構成は、、**ttps://www.wrike.com/api/v4/folders** で取得できます

・タスクに複数アサインしている人のカウント
　１つのタスクに複数の人がアサインされているケースは多々あります。
　複数アサインされているケースを考慮してカウント処理を考慮しないと、タスク数の分析数値が正確にでません
　複数アサイン状況の取得は
　**ttps://www.wrike.com/api/v4/tasks** の中のresponsibleIdsで取得します
　カウント処理でダブりでカウントしないように気を使いました
宮本さんjest導入 ~Typescript導入~

# Typescript導入
前回の記事 [宮本さん ~jest導入~](https://qiita.com/taichi0514/items/e3037bc21631d4a92008)
今回はテストをTS化するのでGAS依存のTS化の話はしないです。
ていうか対応してない。

## 環境構築

特にしていないです。
とういのもローカルで使用しない + GASではpushした時点でTSをコンパイルしてくれるから
VScode入れたらTSが同時にインストールされるのでダイジョブ
TSのバージョン固定しないと行けない場合はnpmでバージョンしてからインスコ
`tsc --init` すればtsconfigを生成してくれのですが特に指定したいルールがなければ
tsconfigは必要ないです。tsconfigがなくともデフォルトのルールが有るようなので

## 下調べ

TS書くとなっても全然わかってないのでとりあえず型定義の仕方からググりました。

### Type Annotation


```sample.ts
const x: number = 1;
```

```解説.ts
const 変数名:型 = 値
```
値に初期値が存在する場合は型推論が働き、
上記のような宣言でもxの型がnumber型であることをコンパイラが推定してくれます。

### interface

```ts:interface
interface MyInterface{
    name:string
}

class MyClass implements MyInterface{
    name:string;
}
```
変数の値を指定せずにメンバーや型の定義だけ持つ。

最初に調べたのはこの２つぐらいです。

## npmをTS化
ここからは勢いで書きました。

```date_utils_test.ts
import { contains, isNaN } from "underscore";
```

`import { contains, isNaN } from "underscore";`
まずモジュールをtsしようと思い`@types/underscore`をインストールしたのですが、
TS化ならずググったところ
`underscore`、`@types/underscore`２つとも必要だった。

`npm i  underscore @types/underscore`
↑で解決読み込むのは元のモジュールの方
`import { contains, isNaN } from "underscore";`

## classをTS化(簡単に説明)


```date_utils_test.ts
import { contains, isNaN } from "underscore";
export class DateUtils {
  now: Number;
  setTime(now: any) {
    return (this.now = now);
  }
  dateUtilsNow(datetime: Date) {
    let _now = new Date();
    if (typeof datetime !== "undefined") {
      _now = datetime;
    }
    return this.setTime(_now);
  }

```

1. まずType Annotationで`now: Number;`型指定
2. 関数の引数を型指定  functionでもType Annotationのように引数に型を指定できます。

```ts
dateUtilsNow(datetime: Date) {
    let _now = new Date();
    if (typeof datetime !== "undefined") {
      _now = datetime;
    }
    return this.setTime(_now);
  }
 ```

## 快適さ
既存ソースをコピペしてもある程度型定義してくれるので楽
他のプロジェクトをでも使ってみたがTSでエラー吐いてコンパイルしてくれないのが
最初は辛いがなれるとエラー文とバグが紐づくイメージになってきてありがたみを感じはじめる。


## 辛さ

宮本さんは文字列と時間がデフォルトで混ざっているので型定義が辛い。
この辺は書き直し等で改善はできそう
ただ、宮本さんに限らず既存コードをTS化するのは辛いという印象を持った。
cron.logの容量が肥大化しないように、定期的にクリアさせる

# はじめに
**cron**で実行したコマンド（つまり、**crontab -e**で設定したコマンド）を、**rsyslog**サービスを使って、**/var/log/cron.log**に定期的に書き込む設定をした後、このログファイルは永遠に書き込まれて行き、容量が肥大化しないだろうかと思い、定期的に、**/var/log/cron.log**のファイルをクリアする処理も、**cron**で設定する事にした。

# 環境
Ubuntu 16.04.5 LTS

# 試した事１
単純に、ログファイルを削除しようと思い、cronに下記のコマンドをスケジュールさせる。確かに、ログファイルは削除してくれたが、rsyslogサービスを再起動しないと、ログファイルは二度と作成されない事が判明する。しかも、root権限がないと削除できない。よって、この方法は没となる。

```cmd
rm /var/log/cron.log
```

# 試した事２
**/var/log/cron.log**ファイルを残したままで、中身をクリアして、0KBの空ファイルにするも、やはり、root権限がないと書込みができない事が判明。

```cmd
cp /dev/null /var/log/cron.log
```

# cronでsudoを指定したコマンドを実行するには（vimで躓く編）

**visudo**を編集する事で、cronでsudoを指定したコマンドが実行できるようになる事が判明したため、やってみる。

```
sudo visudo
```

Ubuntuでは、visudoを表示すると、デフォルトで、**nano**が起動するようになっているため、**vim**に変更します。

```
sudo update-alternatives --config editor
```

>
参考記事
https://qiita.com/koara-local/items/35b999631b6ab41fdc9f

自分の環境では、**vim.nox**と、**vim.tiny**の２つのvimが入っているが、下記コマンドで、vim.noxが表示されたため、vim.noxの方を選ぶ事にする。（画面では3を選択）

```
ls -l /etc/alternatives/vi
/etc/alternatives/vi -> /usr/bin/vim.nox
```

vim.noxに変更した後、再度、確かに変更された事を確認する。

```
sudo update-alternatives --config editor
```

nanoではなく、vimで表示されるようになりました。

```
sudo visudo
```

# cronでsudoを指定したコマンドを実行するには（やり方を考察編）

visudoを編集するには、visudoを直接編集する方法と、visudoは触らずに、**ドロップイン**を作成する方法と２つの方法がある。下記のコマンドで、１つのファイルと、１つのディレクトリが検索されます。visudoを編集すると、**/etc/sudoers**ファイルが編集されるが、**/etc/sudoers.d**というディレクトリの配下に、編集したい行だけ追加したファイルをセットすると、sudoersファイルを触る事なく、カスタマイズが行えるというのがドロップインの仕組みらしい。ドロップインを推奨する人もいるようだが、自分は、visudoを直接編集する事にした。

```
ls /etc | grep sudo
```

>
参考記事
https://www.teradas.net/archives/13222/

# cronでsudoを指定したコマンドを実行するには（visudoを編集する編）

>
参考記事
https://www.bloguchi.info/1846
https://www.crossl.net/blog/crontab/

ググると、デフォルトで、**Defaults:user requiretty**が記載されているので、**Defaults:user !requiretty**を記述して、**Defaults:user requiretty**を無効にして下さいとあるが、RedHat系のディストリビューションでは、**Defaults:user requiretty**がデフォルトで記述されているのだが、Debian系のディストリビューションでは、デフォルトで、この記載はないとある。確かに、自分の環境にはなかった。

```
sudo visudo
```

なので、この１行のみ追加する。**cp**コマンドのパスは、**which cp**で探します。

```
user ALL=(root)   NOPASSWD: /bin/cp
```

>
参考記事
https://orebibou.com/2017/06/sudo%E3%81%A7%E8%A6%9A%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%A8%E4%BE%BF%E5%88%A9%E3%81%AA%E8%A8%AD%E5%AE%9A%E3%83%BB%E4%BD%BF%E3%81%84%E6%96%B9/#Defaults

**crontab -e**で、テスト的に、sudo 付きのこの１行を追加する。

```
*/1 * * * * sudo cp /dev/null /var/log/cron.log
```

確かに、ファイル容量が小さくなっている事が確認できました。（sudo付のコマンドが実行された事が確認できた）

```
ls -l /var/log/cron.log
```

C'est fini :sweat_smile:
新卒エンジニアの成長tips（6個）

新卒エンジニアとして入社して8~9ヶ月経過して、`ruby`なら少しは慣れたような気がしたので、今の気持ち(ポエム)を書こうかなと思い立ちました😳

以下のような新卒エンジニア向けの記事です!
・本格的な中〜大規模の`rails`は初めてで
・エンジニアインターンでGitの使い方を知っていて
・railsを少し触った事があって
・国籍がコロンビアである🇨🇴

以下に限ったことではないのですが、僕の中で実践して良かったなと思った事だけなので🚷

これは`ruby`に関するtipsがメインです

# メソッド名をググらない
method名すぐ忘れますよね
`methods.grep()`を使うと良いと思いました！

```rb
> Date.today.methods.grep /begin.*day/
=> [:beginning_of_day, :at_beginning_of_day] 
```

# rspecを書く
特に大事なのはrspecを一番書ける人と仲良くなって、rspecの書き方を教えてもらった事です！
初めてのrpsecは書き方のイメージがつかないので、とりあえず書いてレビューしてもらおう😈
結果的に仕様を再確認したり、自分のコードのバグを見つけられます！

[Better Specs](http://www.betterspecs.org/) は初めて読むと何とも思わないけど、色々と自分で書いたら、意味がわかったし、学びもあった！

次のステップとして、`rspecのレビューをする`があると思います。
スラスラ書けても、スラスラレビューできないのがrspecなんだなと思いました!
（書き方が色々あったり、裏技があったり、ややこしいんですよね😒）

# 同じ実装を個人開発でも作ってみる
会社の技術をコピペしろということではなく、同じ機能を自分で実装するのです。
結果と手順は知っているので、調べながら、どうしてもわからない場合は出勤した時にコードを少し読んで、どんなライブラリを使っているのか確認しましょう😎
僕はこれで`rescue`の仕組みや、`DeviseTokenAuth`の仕組みを勉強しました！

`0→1`にフェーズでしか実装しない（その後、改修されない）仕組みは自分から学ぼうとしないと、わからないので、大事だと思いました！

# gemのソースコードを読む
rubyのgemは素晴らしいです。
とにかく読みやすい！！👀
また、普段何気なく使っているが意図がわからなかった`do~endブロック`の挙動とかもわかります！
PR → [【ruby】簡単ッ! do~endブロックって？](https://qiita.com/yujiG/items/c69c7dd552a727d2ac01)
何より、機能を見に行けばqiitaには書かれていないmethodを見つけることもできます。

とにかく`source_location`を使おう！

```rb
> User.method(:take).source_location
 => ["/Users/****/Desktop/****/vendor/bundle/ruby/2.5.0/gems/activerecord-5.1.6.1/lib/active_record/querying.rb", 3]
```

端から読むのでなく、興味のある所だけ摘むだけでokだと思います。
将来的には全部知りたいですね。

# Object(オブジェクト)を意識する
`hoge.class`でクラス名を知るだけで検索効率が全然違います。
何より、わからなければソースコードを読めば良いのです👾

```rb
> Array.new.each.class
=> Enumerator 
```

# とにかくレビューする
これは`ruby`に関わらないことなんですが、、
やっぱり身近にいる優秀なエンジニアのコードを読むのが一番良いです☺️
もちろん自分で書いてレビューしてもらうのも大事ですが、レビューしないと視野が広がらないと思いました。
とにかく、レビューして自分では思いつかない箇所をその都度勉強すべし！

# 所感
レビューの話と似たようなことなのですが、とにかく優秀な先輩の仕事は全てストーキングしてます🕵️‍♀️
先輩のslackは全てスレッドフォローして普段からも疑問は質問して、勝手に学ぶのが一番近道だなと思います。

以上です！
来年は、もっと成長してたら良いな〜🚀
Power Apps キャンバスアプリのフォームコントロールをレイアウトするテクニック

#列のスナップ
Power Apps のキャンバスアプリで業務アプリを作成しようとした場合、フォームコントロールを利用して入力（または表示）フォームを画面に追加することが多いと思います。

このフォームコントロールの各入力コントロールを簡単にレイアウトするための機能として「列へのスナップ」というモードがあり、指定して列数に応じて自動的に項目をレイアウトしてくれます。

初期値は 3 列のレイアウト。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/a0e62cd2-8feb-dc7b-59a8-bcc16f37c113.png)

3 列なのでこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/d3acbcb4-225d-5ab0-4d55-72984bb15a9f.png)

2 列に切り替えるとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/dc4095b7-4200-3211-1cde-514400a6c107.png)

#項目の幅を広げる
幅を広げたい項目（カード）を選択して横にグイッと広げると、テーブルの隣のセルと結合されたようにレイアウトが変わります。このとき、以降の項目は自動で並び替わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/d6ff3a3e-e4a7-b1f9-ec86-1473763b1f47.png)

#3 列を保ったまま行によって項目数を変える
3 列の幅を保ったまま、1 行目の項目は 2 つ、2 行目は 3 つ、のようにレイアウトするにはカスタム カードという機能を使うと良いようです。

フォームコントロールのフィールドの編集メニューから「…」を選択して「カスタム カードの追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/8369f9fd-4e55-89db-51c0-3a9c4bab1cc3.png)

追加されたカスタム カードを任意のところにグイッと並び替えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/528c3f07-7a58-9c86-fb96-ffb663cacf71.png)

こんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/a1fdd0b4-a172-9a92-4680-1eed98e4cff1.png)

高さが揃っていないので気持ち悪いですね。他の行に合わせて各カードの高さを変更しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/8a1447f9-f369-885e-571a-9859c75e078a.png)

これはダメですね。カードの高さは変わったのに、下の行が上に移動してきません。というわけで、この状態でフォームコントロールの「列へのスナップ」をオフ・オンします。

オフにして、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/0fb16b0a-19ec-f03e-bbcf-84c46a702b47.png)

もう一度オンに切り替えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/8beeed08-f351-fd3d-af1e-8ad7dde41304.png)

確認のダイアログが出ますが、そのまま「列のスナップを有効にしてください」をクリックしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/4bb8c358-ef74-d91b-c0d2-34476a03fd30.png)

BOOOOOOOOOOOOM!!! キレイに並びました！！

#まとめ
Power Apps のキャンバスアプリで業務アプリを作成するときに良く利用するフォームコントロールですが、こうしたレイアウト手法を知っておくと更にアプリの作成効率が高くなりそうです。

カスタムカードの使い方は @h-nagao さんに教えてもらいました！Thanks!!