OmniAICreator/Qiita-1.07M huggingface dataset:
VBA 重複リストをユニークリストに変換

## 配列(重複リスト)→配列(ユニークリスト)
### 例(A,A,A,B,B,C)の配列のから(A,B,C)の配列を返す
```vb
Sub SAMPLE_rUniqueArr()
'rUniqueArrの呼び出しサンプル
  Dim arrList, uniqueArr, keyName
  arrList = Array("a", "a", "a", "b", "b", "c")
  uniqueArr = rUniqueArr(arrList)
  Dim arr
  For Each arr In uniqueArr
    Debug.Print arr
  Next
End Sub

Function rUniqueArr(arrList As Variant) As Variant
'配列(重複リスト)を渡して配列(ユニークリスト)を返す
'例(A,A,A,B,B,C)の配列の場合(A,B,C)を返す

  'Dictionaryオブジェクトの宣言
  Dim myDic As Object
  Set myDic = CreateObject("Scripting.Dictionary")
  Dim arrTmp, keyName

  'ユニークリストを作成し、itemに各keyの数量を持たせる
  For Each arrTmp In arrList
    keyName = arrTmp
    If Not myDic.Exists(keyName) Then
      myDic.Add keyName, 1
    Else
      myDic.item(keyName) = CInt(myDic(keyName)) + 1
    End If
  Next

  '辞書型.Keys:Keyを配列に格納
  rUniqueArr = myDic.Keys

End Function
```

## 配列(重複リスト)→辞書(key：数量)
### 例(A,A,A,B,B,C)の配列から、{"A":3,"B":2,"C":1}の辞書型を返す

```vb
Option Explicit

Sub SAMPLE_rUniqueDic()
'rUniqueDicの呼び出しサンプル
  
  'Dictionaryオブジェクトの宣言
  Dim myDic As Object
  Set myDic = CreateObject("Scripting.Dictionary")

  'rUniqueDicに渡す配列を定義
  Dim arrList, dicList As Object, keyName
  arrList = Array("a", "a", "a", "b", "b", "c")
  Set dicList = rUniqueDic(arrList)
  
  'Keysプロパティで辞書型のkeyを配列に格納する
  'dicList(辞書型)をKeyで周回する
  For Each keyName In dicList.Keys
    Debug.Print keyName & ":" & dicList(keyName)
  Next

End Sub

Function rUniqueDic(arrList As Variant) As Object
'配列を渡してkey(配列のユニークリスト):item(keyの数量)の辞書型で戻す
'例(A,A,A,B,B,C)の配列の場合、{"A":3,"B":2,"C":1}を返す
  'Dictionaryオブジェクトの宣言
  Dim myDic As Object
  Set myDic = CreateObject("Scripting.Dictionary")
  
  Dim arrTmp, keyName
  'ユニークリストを作成し、itemに各keyの数量を持たせる
  For Each arrTmp In arrList
    keyName = arrTmp
    If Not myDic.Exists(keyName) Then
      myDic.Add keyName, 1
    Else
      myDic.item(keyName) = CInt(myDic(keyName)) + 1
    End If
  Next
  
  Set rUniqueDic = myDic

End Function
```

https://www.sejuku.net/blog/29736
XGBoostはpickleでなくJSONで保存せよ 備忘録

# 概要
GPU付きPCでモデルのTrainingを行いpredictはGPUなし(つまりCPUのみ)のPCで行う運用を想定する。
そのときのXGBoostモデルの保存方法について備忘録を残す。

- 実施時期: 2022年9月
- Python: conda 3.8.13
- XGBoost: py-xgboost, py-xgboost-gpu 1.6.1

## 問題
XGBoostはLightGBMに比べTrainingが遅いことは有名だ。GPUを使えばCPUよりも体感で4~5倍高速になり十分な速さだが、どのPCにもGPUが乗っているわけではない。
しかしCPUであってもPredictはLightGBMより速いのでdeployを考えるとどうしてもXGBoostを使いたくなる。老舗なため情報が豊富なこともありがたい。
ただモデル保存時、いつもの便利なpickleで保存してしまうと運用時に困ったことになってしまうので対策を残す。

## Training at PC with GPU
XGBoostをGPUでTrainingするときは下記のようなコードとなる。
ここのポイントはモデルを**JSONで保存する**点であり、**pickleで保存しない**こと。

```python
    param_wk['tree_method'] = 'gpu_hist'
    param_wk['predictor'] = 'cpu_predictor'    # ⇐　deploy先のPCにGPUがない運用
    reg = xgb.XGBRegressor(**param_wk)
    reg.fit(X_train, y_train, eval_set = [(X_train, y_train), (X_val, y_val)], hogehoge....)
    reg.save_model('reg_model.json')
```

## Predict at PC without GPU
GPUありPCで保存したJSONファイルをGPUがないPCで読込んでpredictさせるときは下記となる。

```python
    reg = xgb.XGBRegressor()
    reg.load_model('reg_model.json')
    reg.get_booster().set_param({'tree_method': 'hist'})    # ⇐　jsonファイルをエディタで編集してもOK
    y_pred = reg.predict(X_test)
```
JSONで保存したときは、それを読込んだあとでset_param関数で‘tree_method’をCPUを示す'hist'に変更することができる。変更しなければモデルはGPUを期待したままなので後述のwarningが発生する。
pickleで読み込んだときはset_param関数が使えないので詰む。
JSONファイルなのでエディタで開いてファイル冒頭に書かれている‘tree_method’: ‘gpu_hist’　を　‘tree_method’: ‘hist’　に書き換えてもよい。pickleはバイナリなのでそんなことはもちろんできない。
ちなみにpickleで保存してしまい、それを読み込むと下記のようなwarningが発生しモデルをロードすることができない。

```terminal
WARNING: D:\bld\xgboost-split_1660208973102\work\src\gbm\gbtree.cc:390: Loading from a raw memory buffer on CPU only machine.  Changing tree_method to hist.
```

"**Unknown tree updater grow_gpu_hist**"と出るときもあるが、同様にロードはできない。


## まとめ
Trainingもpredictも同じPCならもちろんpickleでもOKだが、JSONにするとモデルのハイパラやパラメータをエディタで確認できるので、基本的にはJSONで保存すべきだろうと、思った。
またpickleではXGBoostのバージョン互換性がなくなることも考えられ、やはりJSONの一択と思われる。

https://github.com/dmlc/xgboost/blob/master/doc/tutorials/saving_model.rst

以上
正三角形(equilateral triangle)「2022年 早稲田本庄高等学院 数学[1]問3」をwolframalphaとsympyでやってみたい。 

A(0,4),B(2,0),C(a,b)...

オリジナル:ますいしい様

https://ameblo.jp/mathisii/entry-12734081753.html

# WolframAlphaで(2円の交点計算で)

https://www.wolframalpha.com/input?i=%280%2C4%29%2C%282%2C0%29&lang=ja

距離 2sqrt(5)

(勉強中)

# sympyで(ますいしい様の手順で)
勉強中:補助点Hを計算する。


# sympyで(2円の交点計算で)
if文について、かっこ悪くてすみません。
```python
from sympy import *
A=Point(0,4)
B=Point(2,0)
AB=A.distance(B)
ans=Circle(A,AB).intersection(Circle(B,AB))
if ans[0].x > 0 and ans[0].y > 0:
   print("#", ans[0])
if ans[1].x > 0 and ans[1].y > 0:
   print("#", ans[1])
# Point2D(1 + 2*sqrt(3), sqrt(3) + 2)
```

# sympyで(座標変換Matrixで)
最後に値を入力しています。
Matrixだと、小数点が表示されます。
```python
from sympy import *
var('x1 y1 x2 y2 tx ty si co sx1 sy1 sx2 sy2 sx sy')
sx1=0.0
sy1=0.0
sx2=sqrt((x1-x2)**2+(y1-y2)**2)
sy2=0.0
d=sx2
v=solve([
         co*sx1-si*sy1+tx-x1,
         si*sx1+co*sy1+ty-y1,
         co*sx2-si*sy2+tx-x2,
         si*sx2+co*sy2+ty-y2
        ],
        [co,si,tx,ty])
A=Matrix([
          [v[co],-v[si],v[tx]],
          [v[si], v[co],v[ty]],
          [    0,     0,    1]
])
B=Matrix([[sx],[sy],[1]])
print("# A*B",A*B)
myMatL=(A*B).subs({x1:0.0,y1:4.0,x2:2.0,y2:0.0,
                   sx:Rational(1,2)*d,sy: Rational(1,2)*d*sqrt(3)})
myMatR=(A*B).subs({x1:0.0,y1:4.0,x2:2.0,y2:0.0,
                   sx:Rational(1,2)*d,sy:-Rational(1,2)*d*sqrt(3)})
if myMatL[0] > 0 and myMatL[1] > 0:
   print("#", myMatL[0],myMatL[1])
if myMatR[0] > 0 and myMatR[1] > 0:
   print("#", myMatR[0],myMatR[1])
# A*B Matrix([[sx*(-x1/sqrt(x1**2 - 2........(以下省略)
# 1.0 + 2.0*sqrt(3) 1.0*sqrt(3) + 2.0
```



# 参考

(DeeｐL翻訳)第1象限:1st Quadrant,First Quadrant,Quadrant 1

https://qiita.com/mrrclb48z/items/fca16b65c9186954fedc

https://www.wolframalpha.com/input?i=intersection+of+two+circles&assumption=%7B%22DPClash%22%2C+%22LaminaE%22%2C+%22intersection+of+two+circles%22%7D+-%3E+%7B%22LensAsymmetric%22%7D&lang=ja

https://ja.wikipedia.org/wiki/%E6%AD%A3%E4%B8%89%E8%A7%92%E5%BD%A2

https://en.wikipedia.org/wiki/Equilateral_triangle
CrystalをWindowsで試してみる

これまで、WindowsでCrystalを動かすにはWSL環境に落とし込んだり仮想マシンを立ち上げる必要がありましたが、ついにWindowsのPreview版が出ました。

https://crystal-lang.org/

## installation
CrystalのインストールにはScoopeが必要なので、先に準備を行います。
公式のインストールガイドに従い、インストールをします。
```powershell
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex
```
https://scoop.sh/

次にCrystalのインストールを公式のインストールガイドに従い行います。
```powershell
scoop bucket add crystal-preview https://github.com/neatorobito/scoop-crystal
scoop install crystal
```
https://crystal-lang.org/install/on_windows/

## Hello Crystal!
プロジェクトを作成してみます。
```powershell
PS F:\dev> crystal init app hello-cr
    create  F:\dev\hello-cr\.gitignore
    create  F:\dev\hello-cr\.editorconfig
    create  F:\dev\hello-cr\LICENSE
    create  F:\dev\hello-cr\README.md
    create  F:\dev\hello-cr\shard.yml
    create  F:\dev\hello-cr\src/hello-cr.cr
    create  F:\dev\hello-cr\spec/spec_helper.cr
    create  F:\dev\hello-cr\spec/hello-cr_spec.cr
Initialized empty Git repository in F:/dev/hello-cr/.git/
PS F:\dev>
```

`\src\hello-cr.cr` が作成されるので、中身を少しだけ触ります。
```crystal:hello-cr.cr
# TODO: Write documentation for `Hello::Cr`
module Hello::Cr
  VERSION = "0.1.0"

  # TODO: Put your code here
  puts "Hello Crystal!"
end
```

`hello-cr.cr`の階層まで移動し実行してみます。
```
PS F:\dev> cd .\hello-cr\src\
PS F:\dev\hello-cr\src> crystal run .\hello-cr.cr
Error executing process: 
(中略…)
 /ENTRY:wmainCRTStartup iconv.lib advapi32.lib Kernel32.lib shell32.lib ole32.lib WS2_32.lib legacy_stdio_definitions.lib DbgHelp.lib libcmt.lib': 指定されたファイルが見つかりません。 (File::NotFoundError)
(中略…)
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues
PS F:\dev\hello-cr\src>
```

なんだと

## Visual Studio Build Toolsのインストール
改めてCrystal for Windows Previewの必要システム要件を見直してみると、VisualStudioもしくはVisual Studio Build Toolsが必要なようです。

https://github.com/neatorobito/scoop-crystal#requirements

VisualStudio Installerをダウンロードし、以下のコンポーネントをインストールします。
完了したら一度再起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131298/d9caf3c3-afd1-5b4c-1da5-9bffa0649af4.png)

https://visualstudio.microsoft.com/ja/downloads/

## Hello Crystal!（再）
```powershell
PS F:\dev\hello-cr\src> crystal run .\hello-cr.cr
Hello Crystal!
PS F:\dev\hello-cr\src>
```

🎉
Golangにおけるポインタの必要性を理解したのでその解説

今までRoRやPHPなどの動的型付言語をメインでやってきたんですが、今回行っているインターン先で、`Go`を使うことになったので、勉強しています。

そのなかで、初めて知った概念であるポインタについて今回は解説していこうと思います。

今回の記事を読んでわかることは以下の3つです。
* ポインタとはなんなのか
* ポインタの書き方
* ポインタってなぜ必要なのか

この2つがわかるようになると思いますので、最後までお付き合いお願いいたします。

なお、この記事では公式のPlayGroundからハンズオンでコピペではなく、手を動かしてみるのをお勧めします

https://go-tour-jp.appspot.com/welcome/4

## ポインタとは何なのか？
簡潔に言えば、ポインタとは**アドレス情報であるメモリにアクセスするためのもの**です。
メモリとは一時的にデータが保存されている場所でその中に変数が保存されています。

メモリについては[こちらの記事](https://qiita.com/Sekky0905/items/447efa04a95e3fec217f#%E5%A4%89%E6%95%B0%E3%81%A8%E3%83%A1%E3%83%A2%E3%83%AA%E3%81%A8%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9)が参考になるのでぜひ。

例として以下のコードを見てください
```main.go
package main

import "fmt"

type Fruit struct {
    Id   int
    Name string
}

func main() {
    var f *Fruit

    f = &Fruit{
        Id: 1,
        Name: "ばなな",
    }
    fmt.Printf("変数fに格納されているアドレスは%p", f)
}

//変数fに格納されているアドレスは0xc000094018
```
最終行に書いてあるような16進数で表現されるのがアドレスで、ポインタを使用することでメモリに自由自在にアクセスすることができるようになります。

次に`golang`におけるポインタの書き方を解説していきます

## ポインタの書き方
結論から言うと、`&`を使用することでポインタを使用することができます。
先程のコードよりもう少し簡単なコードを記述してみましょう
```main.go
package main

import "fmt"

func main() {
    var a string = "こんにちは！"
    var b = &a

    fmt.Println(a)
    //　こんにちは！
    fmt.Println(&a)
    // 0xc00009e210 値は人によって違います
}
```
最後のあたりで`&`が使われています。この記号を使用することで、ポインタを使用することができます。
加えて以下のコードを見てください
```main.go
package main

import "fmt"

func main() {
    var a string = "こんにちは！"
    var b = &a

    fmt.Println(a)
    //　こんにちは！
    fmt.Println(&a)
    // 0xc00009e210 値は人によって違います
    fmt.Println(*b)
    //　こんにちは！
}
```
最後の`fmt.Println(*b)`で変数`a`のアドレスの値を取得しています。
アドレスの値を取得するときは、`*`を使います。

ここまで読んできた方でメモリに自在にアクセスできるポインタの何が嬉しいの？って思いますよね。
次のセクションでそれを解説してきます

## ポインタはなぜ必要なのか
普通に考えたら、「メモリに保持されているアドレスではなく、基本的な値を操作したい」と思いますよね。
ではどうしてポインタが必要なのでしょうか。
以下のコードを見ながら考えていきましょう

```main.go
package main

import "fmt"

type User struct {
    Name string
    Post []string
}

func (u User) newPost(){
    u.Post = append(u.Post, "こんばんは！今日もいい天気ですね！")
    fmt.Println(u)
    // {Anna [明日もいい天気です！ こんばんは！今日もいい天気ですね！]}
}

func main() {
    u := User{Name: "Anna", Post: []string{"明日もいい天気です！"}}
    u.newPost()
    fmt.Println(u)
    // {Anna [明日もいい天気です！]}
}
```
ここで「あれ？」と思いませんか？
`main`関数で変数`u`を出力したとき、なんで`{Anna [明日もいい天気です！]}`しか取得できたないんだろうと思いませんか？
ここにはポインタが関与してるんです。
ポインタとは、アドレス情報であるメモリにアクセスするためのもの、と1つ前の章で言いました。

ポインタを使うことでデータの値を参照することができます。
しかしながら、中身のデータを変えることはできないんです。

つまり、ポインタのメリットは、**予期していない値によって参照するデータが変更されてしまわないようにしながら、データを参照するため**に使われているんです。

「ポインタはなぜ必要なのか」という問いに答えるとするならば、「データを参照する際に、データが保持されているアドレスを渡して、意図せずにデータが変更されるのを防ぐため」と言うのが答えになります。

以上です。
何か間違いなどありましたら、コメントで教えていただけると幸いです。


【参考文献】

https://medium.com/@annapeterson89/whats-the-point-of-golang-pointers-everything-you-need-to-know-ac5e40581d4d

https://qiita.com/Sekky0905/items/447efa04a95e3fec217f#%E5%A4%89%E6%95%B0%E3%81%A8%E3%83%A1%E3%83%A2%E3%83%AA%E3%81%A8%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9

https://www.sparknotes.com/cs/pointers/whatarepointers/section1/#:~:text=Stated%20simply%2C%20a%20pointer%20is,a%20specific%20location%20in%20memory

https://go.dev/ref/spec#Address_operators
Ruby での デバッグ方法

# 目的
- ruby における デバッグ方法 を 理解する。

# ポイント
- デバッグ とは プログラムの手直し のこと。
- 問題点の確認 に用いる。
- ファイル の先頭に require "pry"
- binding.pry は pry の 拡張ツール


# 書き方の例
```ruby
require "pry"

def double(i:)
  i*2
end

binding.pry

result = double(i:3)
puts result

```
~実際の表示~
 4:   i*2
     5: end
     6: 
     7: binding.pry
     8: 
 =>  9: result = double(i:3)
    10: puts result



# 注意するポイント
- biding.pryの後にコードがないと、動作が終了しない。

# 具体的な例
```ruby
require "pry"

japanese_score = 30
english_score = 20

binding.pry
total = japanese_score + english_score
p total

```
~実際の表示~

    2: 
    3: japanese_score = 30
    4: english_score = 20
    5: 
    6: binding.pry
 => 7: total = japanese_score + english_score
    8: p total
paizaラーニング レベルアップ問題集 Aランクレベルアップメニュー JavaScript リバーシの操作（縦横）

リバーシの操作（縦横）

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_pincerattack_step2


を解いてみました。

```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//出力する盤面の行数 H , 列数 W と石を置くマスの y , x 座標である Y , X
const [H, W, Y, X] = lines[0].split(" ").map(Number);
//盤面を作る
let board = lines.slice(1,H + 1).map(line => line.split(""));
//盤面の ( Y , X ) に石を置き
board[Y][X] = '*';

//石を置いたY行目について、Y固定
//石を置いた左側、盤面の中を調べる
for (let i = X - 2; i >= 0; i--) {
    //調べる場所が、かつ自分の石があるかつ１つ右に何もない
    if (board[Y][i] === '*' && board[Y][i + 1] === '.') {
        //中に石を置く。１つ右から石を置いた手前まで
        for (let j = i + 1; j < X; j++) {
            board[Y][j] = '*';
        }
        // 新たに置いた石によってさらに石が置けるようになった場合でも
        // その時点で操作を終える。
        break;
    }
}

//同様に石を置いた右側を調べる
for (let i = X + 2; i < W; i++) {
    //調べる場所が、盤面の中かつ自分の石があるかつ１つ左に何もない
    if (board[Y][i] === '*' && board[Y][i - 1] === '.') {
        //中に石を置く
        for (let j = i - 1; j > X; j--) {
            board[Y][j] = '*';
        }
        // 新たに置いた石によってさらに石が置けるようになった場合でも
        // その時点で操作を終える。
        break;
    }
}

//石を置いたX列目について
//同様に石を置いた上側へ
for (let i = Y - 2; i >= 0; i--) {
    //盤面の中かつ自分の石があるかつ間に何もない
    if (board[i][X] === '*' && board[i + 1][X] === '.') {
        //中に石を置く
        for (let j = i + 1; j < Y; j++) {
            board[j][X] = '*';
        }
        // 新たに置いた石によってさらに石が置けるようになった場合でも
        // その時点で操作を終える。
        break;
    }
}

//同様に石を置いた下側へ
for (let i = Y + 2; i < H; i++) {
    //盤面の中かつ自分の石があるかつ間に何もない
    if (board[i][X] === '*' && board[i - 1][X] === '.') {
        //中に石を置く
        for (let j = i - 1; j > Y; j--) {
            board[j][X] = '*';
        }
        // 新たに置いた石によってさらに石が置けるようになった場合でも
        // その時点で操作を終える。
        break;
    }
}

//操作を終えた後の盤面を出力
console.log(board.map(row => row.join("")).join("\n"));
```
PowerAutomateで受信したOutlookメールをTeamsに投稿する方法

<h1>はじめに </h1>
Outlookに受信したメールをTeamsのチャットに投稿する方法について、連携は簡単にできますが、改行に少し手こずったので記載いたします。
<br>・準備作業
<br>1.受信トレイで新規フォルダを作成する
<br>2.Teams投稿したいメールを仕分けルール（件名や送信者など）で1.で作成したフォルダに振り分けするように設定する
<br>3.PowerAutomateを起動し、OutlookとTeamsのサインインを行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/2e5beacb-4f9e-1e20-b522-b7b840888690.png)
<h2>自動化フロー</h2>
1.作成するから自動化したクラウドフローをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/c9345bf3-32e3-c5a7-bec3-154084b6fb44.png)
2.新しいメールが届いたとき（V3）を選択し、作成するをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/2100abd7-7750-892d-7202-af9a8cb554ea.png)
3.フォルダに作成した受信トレイ内のフォルダを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/6bcdc80b-bf60-b2bb-4542-145666ec3643.png)
4.変数を初期化するを選択し、<br>名前:本文<br>種類:文字列<br>値:本文<br>を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/3b9d28ac-3f87-9170-c973-dfa18b68c904.png)
5.変数を初期化するを選択し、<br>名前:改行<br>種類:文字列<br>値:動的なコンテンツの追加をクリックし、式に以下コードを記入する。
```
uriComponentToString(replace(uriComponent(triggerBody()?['Body']),'%0D%0A','<br>'))
```
6.文字列変数に追加を選択し、<br>名前:本文<br>値:改行<br>を記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/6e51e19e-5c41-93aa-9555-f45bd38a7c32.png)
7.チャットまたはチャネルでメッセージを投稿するを選択し、<br>投稿者:フローボット<br>投稿先:Channel<br>チーム:投稿したいチームを選択<br>チャネル:投稿したいチャネルを選択<br>メッセージ:改行がメールの本文になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462058/484944d3-198b-8d8f-e4f0-422f6b111577.png)
以上です。
docker-compose upでWordPressを動かす(もちろんHTTPS)

# はじめに

ふとおもいつきでWordPressのサイトを立ち上げました。
`docker-compose.yml`を書いておきます。

# docker-compose.yml

```yml:docker-compose.yml
services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy
    container_name: nginx-proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - certs:/etc/nginx/certs
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nginx-proxy-acme:
    image: nginxproxy/acme-companion
    container_name: nginx-proxy-acme
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - acme:/etc/acme.sh
      - certs:/etc/nginx/certs
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
    environment:
      - DEFAULT_EMAIL=example@example.com
      - NGINX_PROXY_CONTAINER=nginx-proxy
    depends_on:
      - nginx-proxy

  wordpress:
    image: wordpress
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
      VIRTUAL_HOST: wordpress.autoracex.dev
      VIRTUAL_PORT: 80
      LETSENCRYPT_HOST: wordpress.autoracex.dev
      LETSENCRYPT_EMAIL: example@example.com
    volumes:
      - wordpress:/var/www/html
    depends_on:
      - nginx-proxy-acme

  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql
    depends_on:
      - nginx-proxy-acme

volumes:
  certs:
  vhost:
  html:
  acme:
  wordpress:
  db:
```

## 環境変数

以下の環境変数の値は適宜書き換えてください。

- DEFAULT_EMAIL
- VIRTUAL_HOST
- LETSENCRYPT_HOST
- LETSENCRYPT_EMAIL

以下の環境変数にはそれぞれ同じ値を設定してください。

- WORDPRESS_DB_NAMEとMYSQL_DATABASE
- WORDPRESS_DB_USERとMYSQL_USER
- WORDPRESS_DB_PASSWORDとMYSQL_PASSWORD

## [Let's Encrypt](https://letsencrypt.org/ja/)

[Let's Encrypt](https://letsencrypt.org/ja/)でSSL証明書を取得しています。
[nginxproxy/acme-companion](https://hub.docker.com/r/nginxproxy/acme-companion)が取得してくれます。
また有効期限が近くなったら自動的に更新してくれます。

前提として、VIRTUAL_HOSTとLETSENCRYPT_HOSTに設定したドメインのAレコードには、動作させているサーバのIPアドレスが設定されているものとします。


# 動かし方

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


# 参考記事

[Dockerを使ってLivebookとGrafanaをサーバ上でイゴかす(もちろんHTTPS)](https://qiita.com/torifukukaiou/items/6f6e9297e5275b951094)

自分で書いた記事です。

# おわりに

ふとおもいつきでWordPressのサイトを立ち上げて、ふとおもいつきでそのままQiitaにdocker-compose.ymlファイルを書いておきました。
【Xcode】正規表現を使用して一括置換

# はじめに
Xcodeの検索機能や置換機能はよく使うと思います。
置換を正規表現使ってやりたいと思ったときにやり方に迷ったので記録しておきます。

# やり方
① `⌘ + F`で検索欄を表示させます
![スクリーンショット 2022-09-09 1.07.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/de242ca9-1280-1fd6-4067-223aeeac9d70.png)

② Findの右にある矢印を押します
![スクリーンショット 2022-09-09 1.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4a830658-a1fb-02c9-6c71-830392ca856c.png)

③ 「Replace」を選択します
![スクリーンショット 2022-09-09 1.10.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/87b333ac-d29c-d823-ba71-d0c883cf4791.png)

④ 「Contains」の右にある矢印を押します
![スクリーンショット 2022-09-09 1.11.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a4256caf-598c-3d86-414b-ed35eaefafc7.png)

⑤ 「Regular Expression」を選択します
![スクリーンショット 2022-09-09 1.13.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ac844bff-6c69-346e-697a-61aa82e40697.png)

おわり！！
これでReplaceがWithに変わります！！
![スクリーンショット 2022-09-09 1.18.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/443c1cf4-7a15-ef4b-4280-db7f9b7cb6db.png)
paizaラーニング レベルアップ問題集 Aランクレベルアップメニュー JavaScript編 裏返せる可能性（縦横）

裏返せる可能性（縦横） (paizaランク C 相当)

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_pincerattack_step1

を解いてみました。

解答例1
盤面を作りながら`!`,`*`,`.`を置いていく。
```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//出力する盤面の行数 H , 列数 W と石を置くマスの y , x 座標である Y , X
const [H, W, Y, X] = lines[0].split(" ").map(Number);
//盤面を作る
let board = [];
//行について
for (let i = 0; i < H; i++) {
    //列について
    let board_j = [];
    for (let j = 0; j < W; j++) {
        //石を置いたマス
        if (i === Y && j === X) {
            board_j.push('!');
        //石を置いたマスと行または列が同じマスを '*'    
        } else if (i === Y || j === X) {
            board_j.push('*');
        //それ以外のマスを '.'     
        } else {
            board_j.push('.');
        }   
    }
    //完成した列を行列二次元配列へ
    board.push(board_j);
}
//盤面を出力
console.log(board.map(row=> row.join("")).join("\n"));
```
***
解答例2
盤面を作ってから、そこに`*`や`!`を置いていく。
```javascript:javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");
//出力する盤面の行数 H , 列数 W と石を置くマスの y , x 座標である Y , X 
const [H, W, Y, X] = lines[0].split(" ").map(Number);
//盤面
//それ以外のマスを '.' にする
const board = Array(H).fill(0).map(row => row = Array(W).fill("."));

//石を置いたマスと行または列が同じマスを '*' に
//Xを固定して、行iについて
for (let i = 0; i < H; i++) {
    board[i][X] = "*";
}
//Yを固定して,列jについて
for (let j = 0; j < W; j++) {
    board[Y][j] = "*";
}
//石を置いたマスを '!' に
board[Y][X] = "!";

//盤面を出力
console.log(board.map(row => row.join("")).join("\n"));
```
Basic認証の導入（健忘録）

## RailsのAppにBasic認証を導入する

全てのコントローラーで行いたいため`application_controller.rb`に記述する

```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth


  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"] # 環境変数で呼び出す
    end
  end
end
```

## （補足）　環境変数の設定
vimコマンドで設定ファイルの`.zshrc`に記述する

```:ターミナル
% vim ~/.zshrc
```

通常モードのコマンド
| コマンド | 説明                             |
| ----- | -------------------------------- |
| :w    | 作成・編集したファイルを保存            |
| :q    | vimを終了                         |
| :q!   | 編集した内容を保存しないでvimを強制終了 |
| :wq   | 編集した内容を保存してvimを強制終了    |

[i]キーで「insertモード」　ファイルに編集を加えることができる
[Esc]キーで通常モードに戻る

```:ターミナル
% source ~/.zshrc　　
   # sourceコマンドで設定を実行
```

## Heroku上で環境変数を設定
```:ターミナル
% heroku config:set BASIC_AUTH_USER="「ユーザー名」"
% heroku config:set BASIC_AUTH_PASSWORD="「パスワード」"
```
配置するAPの個数と周波数の干渉について

APを配置する方法は二つあります。

# Coverage design

これは少ないAPで大きいエリアでの通信を実現する方法です。それぞれのAPが100%の力で電波を飛ばします。接続できる人数が少ないかつ低い周波数帯域(伝達すべき情報量が少ない)のデバイスを扱うのに適しています。人があまりいない広いエリア向き。

# Capacity design

これは少ない電力で多くのAPを配置する方法です。多くの人が接続できて、高い周波数帯域のデバイスを扱うのに適しています。オフィス向き。

# 無線周波数の干渉問題

電子レンジやBluetooth信号は2.4GHzなので、干渉は主に2.4GHzで起きます。2.4GHzの信号の電波が強い時には、通信速度が遅くなります。これは私たちの日常会話でも起きることなのですが、例えば、友達といくら近くで話していたとしても隣を通ったトラックの音の方が大きければ、声が聞こえなくて同じことを聞き返しますよね？それと同じです。

しかし、Bluetoothはあまり影響がありません。それは、干渉する時間が短いからです。例えば、長い間トラックの音が会話を遮るのと短い間トラックの音が遮るのとでは、影響が違います。

## 解決方法

WLANコントローラを使って自動でAPチャネルの管理をすることが効果的です。

以上です。
お疲れ様でした。
Express パスワードをハッシュ化

題名通りサクッと解説する
`async`関数の中で使うことを想定しています。
実装方法の選択肢が3~4通りほど用意されていた。一番シンプルな内容を抜粋
公式が読みやすいので一読して欲しい

## bcrypt

*ソルト* → 平文に追加するランダムな文字列 (セキュリティ向上のため)
*hash* → 平文とソルトを組み合わせたものをハッシュ化したもの (複合化できない(元に戻せないってこと))

*`hash化`*
```js
const bcrypt = require('bcrypt');
// soltの長さ
const saltRounds = 10;
const password = 'Password123';

// 第1:平文, 第2:soltの長さ
const hash = await bcrypt.hash(password, saltRounds)
```

*ハッシュを用いてパスワードを検証*
```js
const bcrypt = require('bcrypt');
const hash = '$2b$10$CW9OqVEHzLLd/RNKJ02zBu9fMytwQGNLjNWa90WuJHL0kOhIwBfDm';
const password = 'Password123';

// 第1:平文,  第2:DBに保存したhash値
// 返り値はboolean (trueかfalse)
const flag = await bcrypt.compare(password, hash)
```

終わり!! 短い!!

## 注意点
`bcrypt`はnodeの安定板のみサポートしているらしい。 つまり`node`の偶数番号
`node`は `v17`等の奇数番号はチャレンジングな機能を入れていてサポートも短い。 偶数番号は安定板

公式に環境によってはエラーが出ると書いてあった。ため一読して欲しい。

## expressで使うなら？
`api`
こんな感じになりますね `ORMはsequelize`です
```js
// 新規ユーザーを登録
router.post("/", async (req, res) => {
  try {
  // 入力されたpasswordをhash化する
    const hash = await bcrypt.hash(req.body.password, 10);

// DBにはhashを登録する
    const user = await User.create({
      name: req.body.name,
      email: req.body.email,
      password: hash,
    });
    return res.status(200).json(user);
  } catch (err) {
    return res.status(500).json(err);
  }
});
```


## 参考

https://www.npmjs.com/package/bcrypt


https://nodejs.keicode.com/nodejs/bcrypt-async.php

https://medium-company.com/bcrypt/#:~:text=%E3%82%BD%E3%83%AB%E3%83%88%E3%81%A8%E3%81%AF%E3%80%81%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92,%E3%81%AF%E3%82%BD%E3%83%AB%E3%83%88%E3%81%AE%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E5%9B%B3%E3%81%A7%E3%81%99%E3%80%82
【Git】認証情報を保存する方法

## 認証情報を保存する方法
### 一定時間メモリーに記憶する
一定時間メモリーに記憶させるためには以下のコマンドを実行します。

```zsh:ターミナル
git config --global credential.helper cache --timeout 任意の秒数

```

デフォルトでは15分間記憶されます。

### テキストファイルとして保存する
テキストファイルとして保存するには以下のコマンドを実行します。

```zsh:ターミナル
git config --global credential.helper store --file 任意のファイルパス
```

デフォルトでは`~/.git-credentials`に保存されます。

### OSのキーチェーンに保存する
OSのキーチェーンに保存するには以下のコマンドを実行します。

- Macの場合
```zsh:ターミナル
git config --global credential.helper osxkeychain
```

- Windowsの場合
```zsh:ターミナル
git config --global credential.helper wincred
```
オブジェクトの取り出し方、forループ文の「i」の意味と取り出し方法




### arrayに何個オブジェクトが存在するのか

```javascript
const array1 = [
 "AAAAAAA",
 "BBBBBBB",
 "CCCCCCC",
 "DDDDDDD",
 "EEEEEEE",
 "FFFFFFF",
 "GGGGGGG",
];

//取り出し方
console.log(array1.length);  // 7
```

### array1の１番を選択する。　方法
```js
for (let i = 0; i < array1.length; i++) {
 console.log(array1[i]);　
 //array１の０〜６を選択する。
 //AAAAAAA 
 //BBBBBBB
 //CCCCCCC
 //DDDDDDD
 //EEEEEEE
 //FFFFFFF
 //GGGGGGG
 }
// A：
console.log(array1[1]); //[1]で指定している。  //BBBBBBB
```

### for文の使い方

```js
const array1 = [
 "AAAAAAA",
 "BBBBBBB",
 "CCCCCCC",
 "DDDDDDD",
 "EEEEEEE",
 "FFFFFFF",
 "GGGGGGG",
];

for (let i = 0; i < array1.length; i++) {
 console.log(array1[i]);　
```

arrray1の中にAAAAAAAからGGGGGGGまで７個の配列がある。それをfor文で回すと....for文の中身内容の意味は、
- 左から、iが「０」だと定義します。
- 条件はarrray1の中に入っている配列回数分ループします。
- iを１づつ＋していきます。



### 「i++」「++i」の違い

- 「i++」後で１を足す（代入後に加算する）

```js
let i = 1;
let y = i++;
console.log(i);  // 2
console.log(y);  // 1
```

- 「++i」先に１を足すと言う意味(代入する前に加算する)
語呂：ぷらぷら前代入か〜さん（代入する前に加算する）

```js
var i = 1;
var y = ++i;
console.log(i);  // 2
console.log(y);  // 2
```
Viteで本番と開発環境で変数を変えたい


## 本番と開発環境で叩くAPIのURIを変えたいなぁ
そういうときってあるよね。.envでなんとかするんだったけど、どうするんだっけな〜と毎回ググることになるのでここにメモ。

## 手順
1. .env.devと.env.productionファイルを用意する
2. 変数を```VITE_API_URL=https://*****/**/api```とする
3. 使いたいところで```export const API_URL = import.meta.env.VITE_API_URL;```とする
4. devとbuildのときに変数を渡す


.env.devと.env.productionファイルを用意する
変数を定義する

```text:.env.dev
VITE_API_URL=https://dev-server***.jp/api
```

```text:.env.production
VITE_API_URL=https://prod-server***.jp/api
```

注)VITE_という名前をつけておかないとvite側で.envの変数を認識してくれないようです。
参考：https://ja.vitejs.dev/guide/env-and-mode.html#env-files
→よく読んだら違った

> 環境変数が誤ってクライアントに漏れてしまうことを防ぐために、VITE_ から始まる変数のみが Vite で処理されたコードに公開されます。例えば、以下のファイルで:

```text
VITE_SOME_KEY=123
DB_PASSWORD=foobar
```

> VITE_SOME_KEY だけが import.meta.env.VITE_SOME_KEY としてクライアントソースコードに公開され、DB_PASSWORD は公開されません。


```ts:apiConfig.ts
export const API_URL = import.meta.env.VITE_API_URL;
```

そしてdevとbuildのところで環境変数を与えてあげましょ

```json:package.json
    "dev": "vite --host --mode dev",
    "build": "tsc && vite build --mode production"
```

## 補足：productionのときだけ通りたいif文とか

```TypeScript:if.ts
if (import.meta.env.PROD) {
  console.log('Production!');
  return;
};
```

※ちなみにdevのときは```import.meta.env.DEV```

当たり前といえば当たり前の環境変数。ちょっと面倒くさいけど、最初にこれをやっておくと効率変わると思いますよ。うん。
Blue Prismの差分比較機能、履歴差分だけじゃなく、違うプロセスやリリースファイルとでもできるって、知らなかった #blueprism

# 比較機能って？
いわゆるdiffです。
不具合対応のときなどに、変更履歴の新しいのと古いのを差分比較して、「この改修のときはどこを変更したのか」と見るのは保守時の定番作業で、私もよく使います。
![比較1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/8d582ce7-fb14-28cb-2061-627b2ceb671a.png)
比較したいどうしを並べて見比べられて、差のある箇所は色塗りで表示してくれるのがすごく便利。
![比較5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/187f3bd6-1fe1-1866-bef1-e33bb3e77c9a.png)
どういう機能かとか、やりかたとかは下の記事を参照。
[Blue Prismはどこまで変更箇所をトレースできるのか](https://ciprogram.jp/rpa/blueprism_diff_maji_easy/)
[この記事の「バージョン管理ができる」の項](https://qiita.com/irohamaru/items/374bca9d46211f16a4f1)

Blue Prism社の公式ガイドのページはここ→ [比較フォームを使用する](https://bpdocs.blueprism.com/bp-6-10/ja-jp/frmProcessComparison.htm)

履歴とその比較についての記載はこうです。
> プロセス履歴機能により、Blue Prism管理者（または外部監査人）は、すべての保存でプロセスに加えられた変更を検査できます。
プロセスのコピーは保存のたびに作成され、そのバージョンのプロセスは無期限に保存されます。
プロセス比較フォームを使用すると、並べて比較したり、プロセス内の変更されたステージをハイライトしたりすることで、2つのプロセスをすぐに比較できます。


# 比較できる対象が同一プロセスの履歴どうしだけじゃないって知ってました？
私は今日知りました！（情弱）
違うプロセスもしくはオブジェクトどうしでも比較できるんですって！

たとえば、既にリリースして本稼働しているロボを、コピーして改造して他所へ横展開して、…… っていうことをしたロボに対して
これって何をどう改造してこっちに持って来たんだっけ？と確認したいときに、この機能を知っているとちょっと便利です。

# 異なるプロセスどうしを比較する
比較したい片方のプロセスもしくはオブジェクトを1個選び、右クリックして「次と比較…」をクリック。
![比較2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/b5f93527-18f1-b29d-cfb5-9e151bd1e2c4.png)
「データベースのプロセスまたはビジネスオブジェクトと比較」を選択して「次へ」
![比較3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/6deed1b7-31e0-531e-f108-31b26f02bd70.png)
最初に選択したのがプロセスならプロセス、オブジェクトならオブジェクトの一覧が出るので比較対象を選択して「次へ」
![比較4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/3bad4f84-658f-dc40-dccb-97c43d728a30.png)
あとはご存じの「履歴どうしの比較」と同じです。

# 比較対象がエクスポートされたやつでもOK！
エクスポートして.bpreleaseファイルを作成してしまってからでも、それと比較することができます。

比較したい片方のプロセスもしくはオブジェクトを1個選び、右クリックして「次と比較…」をクリックするところまではさきほどと同じ。
「ファイル内のプロセスまたはビジネスオブジェクト比較」を選択して「次へ」
![比較6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/d7fa3db5-89f8-fc8d-a3ba-a382b9eda561.png)
「参照」ボタンを押下すると、ファイルエクスプローラが出てきてファイルを選択できます。
![比較7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/161ee9f3-02cf-893a-755f-c835dc9f1f6f.png)
比較画面が出てくるので、あとは同じです。
このエクスポートしたやつっていつのバージョンのだっけ？というときに確認できてちょっと便利です。

# 終わりです
Blue Prism社の公式ガイドにも、さらっと載っていました。
[プロセス比較ウィザード](https://bpdocs.blueprism.com/bp-6-10/ja-jp/frmProcessCompare.htm)
> 同じプロセスの2つのバージョンを比較できます（編集の前後など）。
あるいは、任意の2つのプロセスを比較することもできます。

ええ…… そんな便利機能まえからあったっけ……？勉強します……
viteでbuild時にconsole.logを削除する

## build時に自動的にconsole.logを削除してほしい

そもそもeslintでconsole.logはwarnにしているわけですが、手っ取り早くlogを取りたいときもあってたまにconsole.logを使ってしまいます。

そんなときはこれ！

## vite-plugin-remove-console

```sh
npm install vite-plugin-remove-console -D
```

## configはこうだ

```TypeScript:vite.config.ts
import { defineConfig } from 'vite';
import removeConsole from 'vite-plugin-remove-console';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    removeConsole()
  ]
});
```

これでデバッグ用のconsole.logを削除できます。まあdebugとか使ったほうが良いよなぁ、と思いつつもついついconsole.logを使ってしまう。やめたほうが良いな。やめよう。
サーバー送信イベント

# 概要
サーバーからクライアントにpush送信するイベント。

本来のクライアントがリクエストしてレスポンスを貰うという、
クライアントで発火したイベントタイミングでの通信とは違い、
サーバー側のタイミングで通信を行う（イメージ）。

# 流れ
1. クライアントがリクエストURLを渡して`EventSource`オブジェクトを生成する
2. サーバー側は上記リクエストを検知しpush配信を開始する
3. クライアントはpush配信を監視し、サーバーからのメッセージを待ち受ける

# 実装
## サーバー側
 MIME タイプ `text/event-stream` で応答するように実装する。
（この記事では詳しくは説明しない）

## クライアント側
### EventSourceオブジェクト生成
これによりサーバーにpush配信を開始させるリクエストを送る。

```typescript
const evtSource = new EventSource(requestUrl);
```

### サーバーからのメッセージ受け取り
push配信を受け取ったタイミングで`onmessage`に代入した関数が発火する。
クライアント側は受け取ったメッセージを利用して処理を行うことができる。

```typescript
evtSource.onmessage = function(event: MessageEvent<string>) {
  const message: string = event.message
  // 受信したメッセージを用いてクライアント側を更新
}
```

# 参考
https://developer.mozilla.org/ja/docs/Web/API/Server-sent_events
https://developer.mozilla.org/ja/docs/Web/API/Server-sent_events/Using_server-sent_events
gensimのトピックモデルのget_document_topicsで再現性のある結果を得る

## 環境
- Python 3.7.13
- gensim 3.6.0
- Google Colaboratoryにて実行

## 事象

[gensimのトピックモデルのサンプルコード](https://radimrehurek.com/gensim/models/ldamodel.html)を参考に、適当なモデルを作ってみます。

```python
from gensim.corpora.dictionary import Dictionary
from gensim.models import LdaModel

texts = [
    ['computer', 'time', 'graph'],
    ['survey', 'response', 'eps'],
    ['human', 'system', 'computer']
]

dictionary = Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
model = LdaModel(corpus, num_topics=2, random_state=0, id2word=dictionary)
```

適当な入力をすると、トピックに割り当てられる確率が出力されます。

```python
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
```

```:出力
[(0, 0.67178893), (1, 0.32821107)]
```

この確率は`random_state=0`にしていても実行する度に結果が微妙に変化してしまいます。

```python
model = LdaModel(corpus, num_topics=2, random_state=0, id2word=dictionary)
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
```

```:出力
[(0, 0.67178893), (1, 0.32821107)]
[(0, 0.6716176), (1, 0.32838237)]
[(0, 0.6716369), (1, 0.32836312)]
```


これは、`get_document_topics()`の内部で呼び出している`inference()`メソッドで乱数が進んでいるのが原因のようです。

参考: https://github.com/RaRe-Technologies/gensim/blob/62669aef21ae8047c3105d89f0032df81e73b4fa/gensim/models/ldamodel.py#L677

再現性のある結果を得るには、以下のように実行前に毎回`model.random_state`を指定すると再現性が取れるようになります。

```python
from gensim.utils import get_random_state

model = LdaModel(corpus, num_topics=2, random_state=0, id2word=dictionary)
model.random_state = get_random_state(0)
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
model.random_state = get_random_state(0)
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
model.random_state = get_random_state(0)
print(model.get_document_topics(dictionary.doc2bow(["computer"])))
```

```:出力
[(0, 0.67151856), (1, 0.32848147)]
[(0, 0.67151856), (1, 0.32848147)]
[(0, 0.67151856), (1, 0.32848147)]
```

### 注意点
[gensimのFAQ](https://github.com/RaRe-Technologies/gensim/wiki/Recipes-&-FAQ#q11-ive-trained-my-word2vec--doc2vec--etc-model-repeatedly-using-the-exact-same-text-corpus-but-the-vectors-are-different-each-time-is-there-a-bug-or-have-i-made-a-mistake-2vec-training-non-determinism)には、word2vecやdoc2vecにおいて、結果が微妙に異なり再現性が取れない場合について述べられています。
そこでは、乱数による結果の微妙なズレには寛容であるべき、といったことが述べられています。（evaluation processes should be tolerant of any shifts in vector positions, and of small "jitter" in the overall utility of models, that arises from the inherent algorithm randomness.）
乱数を固定する方法は存在しますが、推奨はされないようです。

トピックモデルにおいては述べられていませんが、同様の事が言えるのではないかと思います。乱数を固定して用いるのはあくまで問題の切り分けなどで使う際に留めるべきなのだと思います。
【Flutter】iOSエミュレーターで実行できなくなった

# 実行できるようになります。
## 出たエラー
```
Launching lib/main.dart on iPhone 13 Pro Max in debug mode...
Running pod install...
Running Xcode build...
Xcode build done.                                            8.2s
Failed to build iOS app
Error output from Xcode build:
↳
    2022-09-09 18:26:27.927 xcodebuild[69619:651609] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionSentinelHostApplications for extension Xcode.DebuggerFoundation.AppExtensionHosts.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
    2022-09-09 18:26:27.927 xcodebuild[69619:651609] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionPointIdentifierToBundleIdentifier for extension Xcode.DebuggerFoundation.AppExtensionToBundleIdentifierMap.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
    ** BUILD FAILED **

~~~~~~~

Error (Xcode): In /Users/ワイのいろんな階層, building for iOS Simulator, but linking in object file built for iOS, file '/Users/ワイのいろんな階層' for architecture arm64

Could not build the application for the simulator.
Error launching application on iPhone 13 Pro Max.
```

## 解決手順
### Podfire内の変更
・バージョンを指定する(１行目とかでよし。)
``` :Podfire
platform :ios, '14.0'
```

・post_install内を書き換える
-> 設定でarm64以外を指示する。
``` :Podfire
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
      end
  end
end
```

### 一回実行。(まだ治らない)

・Xcodeを開く(エラーが出てることを確認)
![スクリーンショット 2022-09-09 18.35.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633771/da56fa47-90c5-74aa-e2eb-283867b5b6e8.png)

・Updata to recommendedを押下
![スクリーンショット 2022-09-09 18.36.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633771/b9f825f2-35fc-5bc2-7207-d0c98ae9dd73.png)

・バージョンを合わせるかの確認ダイアログが出るのでPerform Changesを押下
![スクリーンショット 2022-09-09 18.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633771/d918819a-7636-8085-aa34-3699eb132d37.png)

・プロジェクト内のexcluded architecturesを修正
![スクリーンショット 2022-09-09 18.47.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633771/e7291401-2f1a-5410-b02b-9e1afaa7aa67.png)

## 最後にもう一回実行

```
Launching lib/main.dart on iPhone 13 Pro Max in debug mode...
Updating project for Xcode compatibility.
Upgrading Runner.xcscheme
Running Xcode build...
Xcode build done.                                            9.4s
Debug service listening on ws://999.0.0.1:57349/sVgHDUaUAXA=/ws
Syncing files to device iPhone 13 Pro Max...
```

無事、ビルドが通りました

## それでもビルドが通らない場合

Xcode、simulatorをロゼッタ経由で。。
シミュレーターって読むんだって。シュミレーターで変換しようとしてた。
プログラミングをチュートリアル通りに進めるのがすごく苦手だ

- プログラミングをチュートリアル通りに進めるのがすごく苦手だ。なんというか堪え性がないのかもしれない。チュートリアルが死ぬほど面倒なのは誰でもそうなのだろうか。質問サイトのQuoraで聞いてみたところ同意見の人が多かった。
- 品質の高いコードを書こうという情熱を持っているか？
- 仕事が失敗しても死ぬことはない。だが僕らの本能は命の危機を感じる。
- 「アーキテクトって何？」と聞かれても答えられる自信がない。
- 人生の虚しさを忘れるためにプログラミングをし仕事をする。
- Qiitaで組織論について記事を書いても大丈夫だろうか。大丈夫だろう。なぜならプログラマは組織に属しているからだ。
- たとえ機能の本質に関係のない些細なバグでも、ユーザーには低品質の証のように考えるんじゃないだろうか。
- 妙なコードを見つけた時、それが熟練エンジニアの書いたものであることが分かると、コードへの評価を変えてしまう。認知バイアスの悪しき修正。プログラミングのハロー効果。
- プログラミングの設計を極めるために建築業界の専門書を読んでいるプログラマはいるだろうか
- 仕事をしていると自動的にSNSに参加してるみたいなものだ。
- やりがいのある仕事の蜜は甘すぎて中毒になる。
- 誰もがPCを覗き込みながら聞くプレゼンテーションに何の意味があるんだろうか。誰も特に反応を示さないと思ったらSlackでは会話が交わされている。人の話を聞く時は顔を上げなさい。
- ピカソは子供のように絵を描けるようになるまで相当長年かかったらしい。僕は初心者のように座禅が出来るように試みる。
- 体が健康でなければ座禅なんて物の役にも立たない。儚いものだ。
- スターバックスに来たら、前にも見かけた「英単語を音読で練習する青年」がいた。その向こうを見ると3年前にも来ていた常連の別の青年。かと思えば久しぶりに見る店員さんがバーカウンターで話しかけてくれて談笑した。
- 市役所の人がアイドルかぐらいに可愛かった。アイドルをやったら良いのに。
- 心理的安全性がないとロケットも落ちる。
- まだ出版されていない本は読むことが出来ない。
- 本を読んで賢くなるというのは思い込みだ。賢くなるのは仕事、実践、自問のおかげ。

# チャットメンバー募集


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

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


# Twitter

https://twitter.com/YumaInaura
編集ページをモーダルで表示したのでメモ

### Bootstrapでモーダルを使用した投稿機能を実装したので編集もモーダルで編集したかったので実装してみた


Bootstrap5とJQueryはCDNで読み込んでいる。
コントローラーは通常通り記述
```:recioes_controller.rb
 def index
    @recipes = Recipe.all
    @recipe = Recipe.new
  end

  def create
    Recipe.create(recipe_params)
    @recipes = Recipe.all
  end

  def edit
    @recipe = Recipe.find(params[:id])
  end
 
  def update
    @recipe = Recipe.find(params[:id])
    @recipe.update(recipe_params)
    redirect_to root_path
  end
 

  def destroy
    recipe = Recipe.find(params[:id])
    recipe.destroy
    redirect_to root_path
  end

  private
  def recipe_params
    params.require(:recipe).permit(:dish_name, :cook_method)
  end
```

編集モーダルを表示したいページに以下を記述
```
<div id="product-modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true"></div>
```
編集モーダルへのlink_toにはremote: trueを追加する
```
<div class="offset-1 pb-2">
    <%= link_to '編集', edit_recipe_path(recipe.id), method: :get, class: "btn btn-secondary btn-sm", remote: true %>
    <%= link_to '削除', recipe_path(recipe.id), method: :delete, class: "btn btn-secondary btn-sm",  data:{confirm: 'Are you sure?'} %>
    </div>
```


モーダルの作成
editアクションが呼び出された際にモーダルを出したいので部分テンプレートとして作成
非同期にしたいのでform_withのlocalオプションはfalseに変更

```:_modal.html.erb
<div class="modal-dialog">
  <div class="modal-content">
    <%= form_with model: @recipe, local: false do |f| %>
    <div class="modal-body">
      <div class="form-group">
        <%= f.label :dish_name, "レシピ" %>
        <%= f.text_field :dish_name, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :cook_method, "作り方" %>
        <%= f.text_area :cook_method, class: "form-control" %>
      </div>
    </div>
    <div class="modal-footer">
      <%= f.submit "編集する", class: "btn btn-primary" %>
      <% end %>
    </div>
  </div>
</div>
```



editアクションと連動するためにeditページを二つ作成
編集ページを非同期でモーダル表示したいのでeditページの拡張子はjs.erbにする
formのlink_toでremoteをつけることでedit.js.erbが読み込まれモーダルウインドウを表示させる
product-modalのidを取得し、escape_javascriptで下記の_edit.html.erbにエスケープ処理
showメソッドでモーダルの表示

```:edit.js.erb
$("#product-modal").html("<%= escape_javascript(render 'edit') %>")
$("#product-modal").modal("show")
```


モーダルフォームにレンダリング
```:_edit.html.erb
<%= render partial: 'modal' %>
```

updateアクションと連動するためのファイル作成
下記の_save.js.erbへのレンダリング
```:update.js.erb
<%= render 'save' %>
```


escape_javascriptでindex.html.erbにエスケープ処理
hideメソッドでモーダルを非表示にする
```_save.js.erb
$().html("<%= escape_javascript(render 'index') %>")
$("#product-modal").modal("hide")
```

以上が実装した手順

Bootstrap5自体にJQueryが不要なので他の方法がありそう
$().html("<%= escape_javascript(render 'index') %>")にクラスを指定しなくても動いたり投稿用のモーダルに若干の不具合が発生したりしたので修正の必要があるので解決次第、記事を更新する
プロキシサーバーの仕組みとは？メリットや注意点も解説

プロキシサーバーとは、インターネット上に潜むあらゆる脅威から守る重要な役割を持ちます。セキュリティ面の安全を担保するためにもプロキシサーバーの利用は欠かせません。

しかし、プロキシサーバーを上手に活用するためには、どういった仕組みなのか、そもそもどういったメリットがあるのか理解しておくことが重要です。そこで本記事ではプロキシサーバーの仕組みから、活用するメリットや注意点について解説しますので、ぜひ参考にしてください。

<h1>プロキシサーバーとは？</h1>

プロキシ（Proxy）とは日本語で「代理」と訳されます。つまりプロキシサーバーとは、インターネットに接続できないコンピューターの代わりにアクセスするサーバーを指します。続いてプロキシサーバーの仕組みや特徴をさらに詳しく見ていきましょう。

<h3>プロキシサーバーの概要</h3>
プロキシサーバーは、利用者（クライアント）とWebサーバーの間に設置することで、両者の通信アクセスの橋渡しを行います。セキュリティ対策でファイアウォールが設置されている場合、ネットワーク保護のためインターネット接続ができません。

そこで、クライアント端末とインターネットの間にプロキシを設置することで、インターネット接続が可能になります。また、別のネットワーク同士の通信を中継する際にも利用できます。

<h3>プロキシサーバーの仕組み</h3>
プロキシサーバーの仕組みについて例を用いて解説します。利用者があるサイトを閲覧する場合、以下のようなデータのやり取りが発生します。

外部のWebサーバーからリプライが届く
プロキシサーバーを経由して、クライアントマシンへリクエストを送る
プロキシサーバーがクライアントに返事を出す
サイトが閲覧できる
クライアントマシン目線から見れば、プロキシサーバーは外部Webサーバーのように映り、一方で外部Webサーバーの視点ではクライアントマシンのように見える仕組みとなっています。

<h1>プロキシサーバーの種類</h1>

プロキシサーバーと一言でいっても4つの種類に分けられます。以下の表では、それぞれの種類について特徴をまとめています。
![screenshot-20220909-173117.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/8a7b0eb8-6365-5dd1-1071-2411fe24e049.png)

<h1>プロキシサーバーを活用するメリット</h1>

プロキシサーバーを導入することはインターネット上の脅威から守ることができますが、その他にも数多くのメリットがあります。以下では具体的なメリットについて解説します。

<h3>アクセスログを確認できる</h3>
プロキシサーバーを利用することで、いつ・誰が・どのサイトにアクセスしたか「アクセスログ」を記録出来るようになります。業務に不要なWebサイトや、危険なサイトの閲覧を防ぐことができます。万が一不正なアクセスが行われた場合でも、ログ解析によって適切な対処が可能になるでしょう。

<h3>匿名性の確保が可能</h3>
プロキシサーバーでは、個人のIPアドレスではなくプロキシサーバーのIPアドレスだけが送信されます。そのため、アクセスした端末を隠すことで、サイバー攻撃の対象となることや、悪用されるリスクを防ぐことが可能です。

<h3>サイト表示速度の高速化が可能</h3>
プロキシサーバーのキャッシュ機能は、ユーザーがアクセスしたWebサイトの情報を一時的に保存します。2回目以降のアクセス時は、Webサーバーにリクエスト送信する必要がなくなるため、Webサイトの表示速度が早くなります。

通常のキャッシュ機能はデバイスに保存されますが、プロキシの場合はサーバーに保存されるため、すべての端末で表示速度が高速化します。 

<h1>プロキシサーバーのデメリット</h1>

プロキシサーバーには、キャッシュデータやアクセスログなど様々なデータが残るため、個人情報ややり取りしている情報を見られてしまう可能性があります。また、悪意のあるプロキシサーバーが設置されている場合は、アクセスの際に送受信した情報を抜き取られるリスクもあるので注意しましょう。

<h1>プロキシサーバーを利用する際の注意点</h1>

プロキシサーバーには数多くのメリットがありますが、一方で利用する際には注意点があることもあらかじめ理解しておきましょう。ここではプロキシサーバーを利用する際の注意点を3つ解説します。

<h3>必要なときだけ利用する</h3>
プロキシサーバーは、高度なセキュリティを必要とする場合にのみ利用しましょう。表示速度の高速化のためにプロキシサーバーを利用したとしても、かえって表示速度が低下してしまう場合があります。

<h3>非公開プロキシを利用する</h3>
誰でも利用できる「公開プロキシ」は、個人情報を抜き取るための悪意のあるプロキシが設置されている可能性があります。プロキシサーバーを利用する際は、提供元が信頼できる非公開プロキシを利用しましょう。

<h3>プロキシは正しく設定する</h3>
プロキシの設定を誤ってしまうと、別のプロキシを経由してしまい、個人情報の情報漏えいにつながるリスクもあります。また、ID／パスワード認証を有効化しないと公開プロキシになり、不特定多数の人に利用されてしまう可能性があるので注意しましょう。 

<h1>Octoparseのプロキシサーバー機能の紹介</h1>

WebスクレイピングツールのOctoparseでは、高度なIPプロキシ機能を備えています。Webスクレイピングは、スクレイピング先のサーバーに大きな負荷が掛かります。そのため、相手サーバーはサーバーダウンなどの事態を防ぐため、「IPブロック」のようなスクレイピング防止対策を取るケースがあります。

そのような場合において、複数のIPを使用することは非常に有効な手段です。Octoparseのクラウドサービスは、唯一のIPアドレスを持つ何千ものクラウドサーバーによってサポートされています。

対象のWebサイトで追跡およびブロックされる可能性を最小限に抑えながら、さまざまなIPを自動的に変換することでWebスクレイピングを実行できます。また、Octoparseのプロキシサーバー機能は約3ドル/GBで利用でき、世界62の地域をカバーしています。

<h1>まとめ</h1>

本記事ではプロキシサーバーの基本やメリット、活用時の注意点まで解説しました。プロキシを活用することで、インターネット上に潜むあらゆる脅威から守ることができます。また、スクレイピングにおいてもプロキシサーバーを使えば、個人を特定されずにアクセスすることができます。

ただし、スクレイピング禁止と書かれているWebサイトではプロキシサーバーであっても利用は控えるように注意してください。
ClusterでMP4を会場スクリーンに出力すると上下が見切れるのを何とかする

# ClusterでMP4を会場スクリーンに出力すると上下数ピクセルが見切れてしまう

1920x1080のMP4動画を会場のスクリーンに出力したところ、上下が見切れる現象に遭遇しました。

![a](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c46c4fec-55d5-8a2a-c0c8-664afa8b6d31.jpeg)

↑が元動画で、↓がClusterのスクリーンに表示したものです。

![b](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9e6b49dd-f771-dcee-c14a-a92010abee56.png)

動画の上下が見切れています。

たとえば、右上の `Thumbnail` という文字や、右下の `PUBLISH` ボタンは、スクリーンからはみ出しています。

計測したところ、上36px、下36px分だけ、見切れることがわかりました。

実際に表示されているのは `1920x1008` の部分ということになります。

何個か、プレゼンワールドを移動して試してみましたが、どこでも同じ現象が発生しました。

おそらく、私の用意したMP4ファイルに問題があるのだと思うのですが、登壇前日で調べる時間がありません！

# 上下に黒帯をいれてみる

そこで、1920x1008にリサイズしてから、上下に36pxずつ黒帯を挿入してみることにしました！
実際に使ったFFmpegのコマンドを載せておきます。

```
ffmpeg -i input.mp4 ^
    -filter_complex "scale=w=1920:h=1008:force_original_aspect_ratio=disable,setsar=1,pad=w=iw:h=ih+72:x=0:y=36:color=black" ^
    -vcodec libx264 -qscale 0 -pix_fmt yuv420p ^
    -acodec copy ^
    -y cluster.mp4
```

完成した動画はこちらです。黒帯が上下に入っています。

![c](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/c34ba59d-798d-4423-634f-ec98f8f66f13.jpeg)

これをClusterのスクリーンに出力してみたところ、無事に画面に収まりました！

![d](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/cd2efe23-e461-1b04-0175-a14eea3a9c9d.png)

# さいごに

本記事作成にあたり、以下の記事を参考にさせていただきました。ありがとうございました。

- [映像に余白を追加する PAD](https://nico-lab.net/pad_with_ffmpeg/)
Android  ViewModelとDataBindingを使ってみた

# はじめに
学習記録
開発業務でも使用しているViewModelとDataBindingを触ってみる

# 導入
・ViewModelを使用するため、以下設定
```java:build.gradle
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
```
・DataBindingを使用するため、以下設定
```java:build.gradle
// android{・・・}内
    buildFeatures {
        dataBinding = true
    }
```
続いて、各ファイルの編集・作成
・ViewModel
```java:MainViewModel.kt
package com.example.sampleapp

import androidx.lifecycle.ViewModel

class MainViewModel : ViewModel() {
// 画面に表示するデータ
    var text = "This is Sample Message"
}
```
・レイアウト
```java:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
// MainViewModelクラスを変数viewModelとして定義
        <variable
            name="viewModel"
            type="com.example.sampleapp.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/message"
// MainViewModelの変数textの値を設定
            android:text="@{viewModel.text}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/main_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button"
            app:layout_constraintTop_toBottomOf="@+id/message"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
```
・Activity
```java:MainActivity.kt
package com.example.sampleapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.example.sampleapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ViewModel, DataBindingの設定
        val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        val viewModel: MainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)

        binding.viewModel = viewModel
        binding.message.text = viewModel.text

        binding.mainButton.setOnClickListener {
            viewModel.text = "Button clicked"
            binding.message.text = viewModel.text
        }


    }
}
```

動作確認
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1231945/f9dd4348-fda4-4130-9d35-469a62ec6dd8.png">
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1231945/bdcbfa6e-1f69-6e8d-e5c8-cac2e0a82818.png">

# おわりに
これまで関わったMVVMアーキテクチャを使用しているプロジェクトではこのViewModelかなり使ってます。
データ管理、役割の分担、Activityの肥大化を防ぐ等、目的やメリット・デメリットをもっと深く理解して開発できるようになりたいです。