OmniAICreator/Qiita-1.07M huggingface dataset:
Helmでループ処理を書く




```values.yaml
batch:
  names:
   - Batch1
   - Batch2
   - Batch3
```


## サンプル
- rangeのループ内で他のValuesを参照する場合、`{{ $.Values.batch.image }}`のように$をつける

```yaml
{{- range $i, $batchname := .Values.batch.names -}}
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: {{ lower $batchname }}
  namespace: {{ $.Values.global.namespace }}
spec:
  schedule: "* * 31 2 *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: batch
            image: {{ $.Values.batch.image }}
            command:
            - batch
            - {{ $batchname }}
          restartPolicy: OnFailure
{{- end }}
```
p5.js で createGraphics() と SVGフィルターを組み合わせて使う（CanvasRenderingContext2D.filter で適用）

この記事は、前に以下の記事で書いていた「SVGフィルター」に関するものです。

●p5.js で SVGフィルターを使う（p5.js Web Editor上の HTML・JavaScript に手を加えて利用） - Qiita
　https://qiita.com/youtoy/items/217bfe7e940f2a7e2626

もう少し補足すると、上記の記事では `createCanvas()` で作成したキャンバスに、 `style("filter", 'url()')` という形の [style()](https://p5js.org/reference/#/p5.Element/style) を使ったやり方を用いましたが、今回の内容はそれとは少しだけ違う方法で SVGフィルターを適用する話です。

## CanvasRenderingContext2D.filter を使う
「少しだけ違うやり方」と書いた部分の具体的な内容は、タイトルにも記載している「[CanvasRenderingContext2D.filter](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter)」を使う方法になります。

### なぜ CanvasRenderingContext2D.filter を使おうとしたか
今回の内容について、「冒頭の記事でも SVGフィルターをキャンバスに適用できているのに、なぜ別の方法を使うのだろう？」と思われた方がいらっしゃるかもしれません。
`CanvasRenderingContext2D.filter` を使おうとした理由は、タイトルにも出てきている「 `createGraphics()` と組み合わせる」というところが関係してきます。

#### createGraphics() と style()　を用いた SVGフィルター適用を試す
本題である「 `CanvasRenderingContext2D.filter` と `createGraphics()` を組み合わせる話」に入る前に、これが必要になった理由を具体例を用いて示そうと思います。
そのために、「 `createGraphics()` と組み合わせる」という話について、冒頭の記事で使った p5.js の [style()](https://p5js.org/reference/#/p5.Element/style)　を用いた方法だとどうなるかをここに示してみます。

p5.js Web Editor の index.html と sketch.js の内容と、それを実行した結果を以下に順番に掲載します。

```javascript:sketch.js
let pg;

function setup() {
  createCanvas(400, 400);

  pg = createGraphics(width, height);
  pg.style("filter", "url(#feGaussianBlur)");
  pg.fill(100, 100, 150);
}

function draw() {
  pg.background(220);
  pg.circle((frameCount * 5) % width, frameCount % height, 50);
  image(pg, 0, 0);
}
```

```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
    <meta charset="utf-8" />
  </head>
  <body>
    <main></main>
    <script src="sketch.js"></script>
    <svg>
      <filter id="feGaussianBlur">
        <feGaussianBlur stdDeviation="10 3" />
      </filter>
    </svg>
  </body>
</html>
```

![style() を用いた場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/07347c3a-c586-d870-efe5-0e8d86384a6f.png)

この画像のとおり、SVGフィルターが適用されていない状態になります。

#### createGraphics() と CanvasRenderingContext2D.filter を用いた SVGフィルター適用を試す
それでは、 `CanvasRenderingContext2D.filter` を利用した場合の内容を示します。
上記の style() を使った場合との違いは、 sketch.js のほうのみになるので、index.html の内容は省略して掲載します。

```javascript:sketch.js
let pg;

function setup() {
  createCanvas(400, 400);

  pg = createGraphics(width, height);
  pg.drawingContext.filter = "url(#feGaussianBlur)";
  
  pg.fill(100, 100, 150);
}

function draw() {
  pg.background(220);

  pg.circle((frameCount * 5) % width, frameCount % height, 50);

  image(pg, 0, 0);
}
```

![CanvasRenderingContext2D.filter を使った場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0c23b442-533c-a7b4-5301-4d849d14b788.png)

今度は、描画した円にブラーフィルターがかかっているのが分かります。

## 今回の差が生じた理由
最後に上で試した　2つの内容の違いについて触れて終わろうと思います。
今回の、SVGフィルターを適用する 2つのやり方について上記の違いが生じた理由は以下だと思われます。

- style() を使った方法
   - ブラウザでのレンダリング時にフィルターを適用（元の描画内容の画素には手が加えられていない）
- CanvasRenderingContext2D.filter を使った方法
   - 描画されている画素の値自体を変化させている
bashスクリプト内でCSVのヘッダー行を飛ばす処理

# CSVのヘッダー行を飛ばしたい…

ひよっこエンジニアの個人的な覚書です。
CSVからデータを読み込んで処理するスクリプトを作成したかったのですが、
bash(というかスクリプト)初心者は、一行目のヘッダの部分を飛ばすにはどうしたらいいのかとてもとても悩みました。
あんまりお手本の記事が見つからなかったんですよね。~~きっと探し方が悪かっただけ。~~

## 手順
`ReadCount=1`を変数指定
if文を使用し、ReadCountが1以外の場合のみ処理するように記述
let ReadCount＋＋で変数ReadCountをインクリメント（1増やす)
CSVのデータの行数分これの繰り返し(while文)

## 具体例

#### 読み込むCSVの内容(test.csv)
```
タイムスタンプ,名前,メールアドレス
2022/07/20 11:15:31,Tom Brown,test1@test.com
2022/08/01 09:00:01,Kate Spade,test2@test.com
```
#### SAMPLE CODE(csv_test.sh)
```shell
#!/bin/bash
ReadCount=1
while read row || [ -n "${row}" ];do
    if [ $ReadCount != 1 ];then
        TIMESTAMP=$(echo $row | cut -d "," -f 1) #CSVの1列目から日付データ取得
        echo $TIMESTAMP
        NAME=$(echo $row | cut -d "," -f 2)      #CSVの2列目から名前データ取得
        echo $NAME
        MAIL=$(echo $row | cut -d "," -f 3)      #CSVの3列目からメールアドレスデータ取得
        echo $MAIL
    else
        echo "ヘッダー行なので処理しません"
    fi
    let ReadCount++
done < test.csv
```
#### 実行結果
このサンプルコードの実行結果は以下のようになります。
```
$ bash csv_test.sh
ヘッダーなので処理しません
2022/07/20 11:15:31
Tom Brown
test1@test.com
2022/08/01 9:00:01
Kate Spade
test2@test.com
$
```
参考までに、デバッグ結果も載せておきます。
```
$ bash -x csv_test.sh
+ReadCount=1
+read row
+'['1'!='1']'
+echo $'\203\203.......202\223'
ヘッダーなので処理しません
+let ReadCount++
+ReadCount=1
+read row
+'[' -n '2022/07/20 11:15:31,Tom Brown,test1@test.com' ']'
+'['2'!='1']'
++echo 2022/07/20 $'11:15:31,Tom Brown,test1@test.com\r'
++cut -d , -f 1
+TIMESTAMP='2022/07/20 11:15:31'
+echo 2022/07/20 11:15:31
2022/07/20 11:15:31
++echo 2022/07/20 $'11:15:31,Tom Brown,test1@test.com\r'
++cut -d , -f 2
+NAME=Tom Brown
echo Tom Brown
Tom Brown
++echo 2022/07/20 $'11:15:31,Tom Brown,test1@test.com\r'
++cut -d , -f 3
+MAIL=test1@test.com
+echo test1@test.com
test1@test.com
+let ReadCount++
+read row
+'[' -n '2022/08/01 9:00:01,Kate Spade,test2@test.com' ']'
+'['2'!='1']'
++echo 2022/08/01 $'9:00:01,Kate Spade,test2@test.com\r'
++cut -d , -f 1
+TIMESTAMP='2022/08/01 9:00:01'
+echo 2022/08/01 9:00:01
2022/08/01 9:00:01
++echo 2022/08/01 $'9:00:01,Kate Spade,test2@test.com\r'
++cut -d , -f 2
+NAME=Kate Spade
echo Kate Spade
Kate Spade
++echo2022/08/01 $'9:00:01,Kate Spade,test2@test.com\r'
++cut -d , -f 3
+MAIL=test2@test.com
+echo test2@test.com
test2@test.com
+let ReadCount++
+read row
+'[' -n '' ']'
$
```

## 終わりに
今回は分かりやすく「ヘッダーなので処理しません」と表示していますが、当然これはなくても構いません。
変数名は何でもいいです。わかりやすい名前を付けてあげてください。
Unity 2021.3.xでのAndroidビルド時のGradle エラーについて

自分が止まっちゃったので忘備録として。また、調べても出てこなかったので一応。
Unity 2021.3.x系統のバージョン(3.6f1と3.8f1で確認済み、2021.3.xならどれでも起きる可能性大)で、Androidビルドをしようとすると2つエラーが出て、失敗してしまう件についてです。External ToolsのGradleでは"You are missing the recommended Gradle. Install the recommended version using Unity Hub."と表示されている。指示通り再インストールしたりするが、何度やっても同じものが出ず試行錯誤...最終的に、バージョンを変えることで解決しました。
![Screenshot_2022-08-11-00-04-12-08_40deb401b9ffe8e1df2f1cc5ba480b12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781491/5e3d17d2-575f-98f5-70d2-8c237d12a174.jpeg)
https://docs.unity3d.com/ja/2021.3/Manual/android-gradle-overview.html
公式サイトのGradleの項目を見るとわかるんですが、どうやら2021.3.xのバージョンにGradleが対応していないようなのです。
筆者は気づいた時｢じゃあAndroidビルドサポートをモジュール欄に置くな！！！！！｣と叫びました。
というわけで、別バージョンで読み込むと上手くいくようなので、2022.1.xや2021.2.xを使ってみるといいです。
Cloudant SDKの置き換え

# あらまし

1年半ほど前にリリースしたアプリにて、[@cloudant/cloudant](https://www.npmjs.com/package/@cloudant/cloudant) というパッケージを使用していたのですが、いつの間にかdeprecatedになってしまっていたので、後継の[@ibm-cloudant/cloudant](https://www.npmjs.com/package/@ibm-cloud/cloudant)へ移行したほうが良いかなと思われ、折を見て移行を実施しました。
その際のログを備忘のため残しておきます。


# 導入

@ibm-cloudant/cloudantのインストール
```
npm install @ibm-cloudant/cloudant --save
```

@cloudant/cloudantのアンインストール
```
npm uninstall @cloudant/cloudant --save
```

# node.jsアプリからDBへの接続

接続情報の記載方法が、以前と微妙に変わっているように思いました。
環境変数に格納する、というやり方になるようですが、当初いまいち良く分からず、[こちら](http://dotnsf.blog.jp/archives/1079476281.html)の記事を参考にさせていただきました。
シンプルにIAMでの接続を選択し、以下のような形で接続できました。
```javascript:app.js
const { CloudantV1 } = require( '@ibm-cloud/cloudant' );
const cloudantConfig = require('../../config.cloudant.js');

//settings
const db_service_name = 'CLOUDANT';

//. env values
process.env[db_service_name + '_AUTH_TYPE'] = cloudantConfig.db_auth_type;
process.env[db_service_name + '_URL'] = cloudantConfig.cloudant_url;
process.env[db_service_name + '_APIKEY'] = cloudantConfig.cloudant_iam_apikey;

const cloudant = CloudantV1.newInstance( { serviceName: db_service_name});
```


# DBアクセスの構文

アプリからDBに対しては、insertとfindの2種類のアクションを実行していました。
@cloudant/cloudant から @ibm-cloudant/cloudantに移行するにあたり、構文が変わっており、少し手こずりました。
[API Reference](https://cloud.ibm.com/apidocs/cloudant?code=node) を参考にしつつも、どちらのメソッドに置き換えればよいのか迷ったのと、サンプルコードがいまいち良く分からず・・・一旦以下のような感じで書き換えできました。

@cloudant/cloudantの例
```javascript
// insert
cloudant.use(feedback_db_name).insert(log_data);

// find
const query = {
     "selector": {
        "_id": {"$gt": "0"}
     },
     "limit":2000,
     "sort": [{"feedback_date": "desc"}]
};
cloudant.use(feedback_db_name).find(query,function(err, result){});
```

@ibm-cloudant/cloudantの例

```javascript
// insert
cloudant.postDocument({
   db: feedback_db_name,
   document: log_data
})

// find
cloudant.postFind({
   db:feedback_db_name,
   selector: CloudantV1.selector = {
     "_id": {
       "$gt": "0"
     }
   },
   sort:CloudantV1.JsonObject =[{'feedback_date': 'desc'}],
   limit: 2000
}).then(response => {});
```

# おわりに
作ってから1年以上放置していたら、以前何やっていたんだっけ・・・というのを思い出すところから苦労しました。
また1年後くらいの自分に向けて、やったことの備忘録はちゃんと残していこう、いくべきだ、と心を新たにいたしました。
Javaの学習 ~データ型~

Javaのデータ型には、プリミティブ型と参照型の２つがあります。
データ型・・・データの種類を表すもの。コンピュータにデータの扱い方を指定するために記述する。

### プリミティブ型
数値、真偽値、文字を扱うデータ型です。基本型とも呼ばれます。
|  整数型  |    |
| ---- | ---- |
|  byte  |  8ビット整数（-128~127）  |
|  short  |  16ビット整数(-32768~32767)  |
|  int  |  32ビット整数(-2147483648~2147483647)  |
|  long  |  64ビット整数(-9223372036854775808~9223372036854775807)

|  論理型  |    |
| ---- | ---- |
|  boolean  |  真偽値(true/false)  |

↑※C言語と違い、「bool」ではなく「boolean」であることに注意！

|  浮動小数点数型  |    |
| ---- | ---- |
|  float  |  32ビット単精度浮動小数点数  |
|  double  |  64ビット単精度浮動小数点数  |

|  文字型  |    |
| ---- | ---- |
|  char  |  16ビットUnicode文字(u0000～uffff)  |

### 参照型
参照型には、オブジェクト型・列挙型・配列型があります。具体的には、new演算子を用いてオブジェクトを生成してから使用するデータ型のことです。

### プリミティブ型と参照型の違いは？
プリミティブ型がメモリ上の値そのものを扱っているのに対し、参照型はその値を格納しているアドレスを参照しています。

##### プリミティブ型の例
```java
int x = 0;
int y = x;  //xのメモリ上の値を代入している。
y = 1;  //yのメモリ上の値が書き換えられる。
System.out.println(x);
System.out.println(y);
```
実行結果
```
0　　  //xは元のメモリ上の値のまま
1   //yは新しくメモリ上の値を更新されたため、1となっている
```

##### 参照型の例
```java
int[] x = new int[1];
x[0] = 0;  //配列xの[0]に0（値そのもの）を代入
int[] y = x;
//↑参照型のオブジェクトを他の参照型に代入している場合、メモリ上のアドレスをコピーする
y[0] = 1;  //配列yの[0]に１（値そのもの）を代入
System.out.println(x[0]);
System.out.println(y[0]);
```
実行結果
```
1    //int[] yはint[] xのアドレスをコピーした為、同じ値を参照することになる。（どちらか一方の値を変更すると、もう片方も変更される）
1
```

値を参照しているか、アドレスを参照しているかの違いによって上記の例のような結果になります。

### まとめ
最後まで閲覧いただき有難うございます！何か間違いやお気づきの点がございましたらコメントお願いいたします！！
found page without a React Component as default export in がでたときの解決方法


ググってると、
export default しろ。ってでてくるんですけど、いやしてるんですけど・・・って感じで結構ハマりました。

結論としては、 **pages配下に、themeファイルをおいてしまっていた** からでした。

nextjsの特性上、pages配下はいわゆるページになるわけで、それらはreact componentでなければならないようです。

僕は何がreact componentで、何がreact componentじゃないのかとかはよくわからないんですけども。
少なくともthemeファイルは違うようです。

というわけで、pages配下にあったthemeを、別の場所に移動させることで解決しました。


エラーメッセージをよく見ると、

```
See https://nextjs.org/docs/messages/page-without-valid-component for more info.
```

https://nextjs.org/docs/messages/page-without-valid-component

とでています。

そこをよく見ると、

>If the file is not meant to be a page, and instead, is a shared component or file, move the file to a different folder like components or lib.

がっつりかかれてました。
めでたしめでたし。。。
Visual Studio CodeでRemote SSHからVMに接続した時に、prettierが効かないときの対処法

## はじめに
Visual Studio CodeでRemote SSHからVMに接続した時に
prettierなどの拡張機能が効かないときの対処法です。

拡張機能はすでにインストール済みの想定です。

## 手順

### 1.settings.jsonに以下を追加

被っているところは削除してください。

```:settings.json
  "[typescriptreact]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "eslint.probe": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue"
  ],
```

### 2.VSCode再起動

### 3.VSCodeで自動整形を実行

| Windows | Mac |
|:-----------:|:------------:|
| Shift + Alt + F | Option + F |


ログを見て、以下で怒られる場合は4を試してみること。

```
["ERROR" - 12:31:09 AM] Cannot find module 'prettier' from '/home/hoge/XXX'
Error: Cannot find module 'prettier' from '/home/hoge/XXX'
```

![0ed5d29d80b2499b09a24a642b6cfd65.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/f6cedf6f-2e2f-690d-793e-81ed3845b1cf.png)

### 4.VMにsshしてプロジェクトのディレクトリで以下のコマンドを実行
もしくはVSCodeのターミナルからでも良いです。

```
$ cd ~/home/hoge/XXX
$ yarn
```

今回はyarnで試したのですが、npmなら以下でも可。
```
npm install -D --save-exact prettier
```


その後、VSCodeで自動整形を実行。

## 結論
当然のことなのですが、
VMでも必要なパッケージを入れてあげないといけないということですね。
AWS cloud9でRubyのバージョンのアップデートをする

## Cloud9のRubyのバージョンを変更したい！！
自作アプリを作成していて、デプロイ時にRubyのバージョンが古いままだったので、本番環境のみでRubyのバージョンの変更をおこなっていましたが、開発環境でもバージョンを揃えたいなと思って色々苦戦したので忘備録として記事にしました。

## Cloud9のデフォルト
私がCloud９を使い始めてからのデフォルトのRubyバージョンは2.6.3でした。
これを、最新の安定バージョン3.1.2（2022/8/10現在）にしたい！！
ちなみに、最新の安定バージョンは以下で確認できます。
https://www.ruby-lang.org/ja/downloads/
![スクリーンショット 2022-08-10 22.27.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/89e3537d-c31c-787c-2ac6-227c3be70652.png)

## それでは、やっていこう！！
#### rvmの最新の安定バージョンをインストールする
```ruby
ec2-user:~/environment $ rvm get stable
```
以下の公式ドキュメントに従い、↑のコマンドを実行します。

https://rvm.io/rvm/upgrading#top

![スクリーンショット 2022-08-10 22.34.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759696/0bc824ee-920f-aa88-05ed-bd59c9c61ab4.png)

#### rubyの最新の安定バージョンをインストールする
ここで、引っ掛かっていました！！
なぜなら、他の記事や公式ドキュメントにも、以下のコマンドでインストールできるrubyのバージョンを見ることができると書かれていたからです。
```ruby
ec2-user:~/environment $ rvm list known
```
試しに実行してみると、、、
```ruby
#〜割愛〜
[ruby-]2.4[.10]
[ruby-]2.5[.8]
[ruby-]2.6[.6]
[ruby-]2.7[.2]
[ruby-]3[.0.0]
#〜割愛〜
```
あれ！？ruby3.1.2がない！！
諦めて開発環境で作業しよう…とcdコマンドでアプリのルートに移動しようとしたその時、
```
Required ruby-3.1.2 is not installed.
To install do: 'rvm install "ruby-3.1.2"'
```
このようなすごく親切なエラーを吐き出してくれました✨
エラーの内容通りに
```
ec2-user:~/environment $　rvm install "ruby-3.1.2"
```
このコマンドを実行すると、しばらくしてから、
```
Install of ruby-3.1.2 - #complete
```
こちらがターミナル上で表示されました！！
#### rubyバージョンを確認する
rubyのバージョンの確認は以下のコマンドで確認できます。
```
ec2-user:~/environment $ ruby -v
```
実行すると、、、
```
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
```
rubyのバージョンが3.1.2にすることに成功しました🎉✨

## まとめ
これで開発環境と本番環境のrubyのバージョンを揃えることができました！！
そもそも、超基本的なことなのに、デプロイする時になって気づいた部分だったので大いに反省しております。
もし、同様なことで困っている方がいたら、ぜひ参考にしてほしいなと思いました！！
Pythonで写真にファイル名を記載するコード

印刷する際に写真とID(=ファイル名)の紐付けができるように、写真内にファイル名を記載したい。
Adhocにinteractive shellで実行する想定


font_pathはPCによって異なるので各自で確認のこと。

```python
import glob
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

files = glob.glob("./*")

def add_text_to_image(img, text, font_size, font_color):
  position = (50, 50)
  fontpath = "/System/Library/Fonts/Helvetica.ttc"
  font = ImageFont.truetype(fontpath, font_size)
  draw = ImageDraw.Draw(img)
  draw.rectangle((20, 20, 700, 100), fill=(255, 255, 255), outline=(0, 0, 0))
  draw.text(position, text, font_color, font=font)
  return img

quality=90 #deafulat: 75, max: 95
for file in files:
  print(file)
  target = Image.open(file).copy()
  file_name = file.replace('./', '')
  font_size = 30
  font_color = (0, 0, 0)
  img = add_text_to_image(target, file_name, font_size, font_color)
  img.save(file, quality=quality)
```
adMobの審査が通らない

# 初めに
今回、Flutterでアプリを制作し、アプリの下部にGoogle adMobで広告配信することにした。
通常、adMobの審査は24~48時間とドキュメントに書かれているが、今回、自分のアプリでは約8日間時間を要した。時間がかかった原因について記録を残しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663093/dfc92bef-0366-d63c-2d3d-2f98c41dceb6.png)
# 結論
結論としては下記の画面のお支払いの設定が必要だった可能性があると考えている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663093/03cd9441-ca30-c9ed-c725-3917a8247fcb.png)
この支払の設定を行うと約12時間後に審査が通り、広告が配信されるようになった。
キュメント上に記述はなく、完全な因果関係はわからないが、これが審査が遅くなった原因だったと考えている。もし、他の方で審査が遅く、支払い情報を登録していない方がいたら試していただけると嬉しいです。(結果も報告してくれると助かります笑)

# 参考URL
https://support.google.com/admob/answer/10417515?hl=ja
【PHP】PHPUnitの環境構築（インストール→オートロードの設定→テスト実行まで）

最近仕事にゆとりができたので、TDD（テスト駆動開発）の勉強として、PHPUnitを使って試そうとしたところ、見事にハマったので備忘録として記載する。

# 0.環境
MacOS 11.5.2(Big Sur)
php 8.1.2
XAMPP
Composer 2.3.7
※ComposerとはPHPのパッケージ管理システムである。
参考：[composerとは](https://qiita.com/atwata/items/d6f1cf95ce96ebe58010)

# 1.ComposerでPHPUnitをインストール
まず、/Applications/XAMPP/xamppfiles/htdocs直下に、TDD用の"phpunit"ディレクトリを作成。
phpunitディレクトリ直下にcomposer.json作成。下記のプログラムを記述し、ターミナルで```composer update```を実行。インストール後、```composer.lock```と```vendor```フォルダが追加されている。
```json:composer.json
{
    "require-dev": {
        "phpunit/phpunit": "*"
    }
}
```
# 2.オートロードの設定。
今回のテストで使用するサンプルプログラム```Sample.php```と```SampleTest.php```を加えたディレクトリ構成は下記のようになる。

phpunit
├ composer.lock
├ composer.json
├ src
　　├ Sample.php
├ test
　　├ SampleTest.php
└ vendor
　　├ autoload.php
　　└ composer...etc

        

```php:Sample.php
<?php
namespace app;

class Sample
{
	public function hello()
	{
		return "Hello";
	}
}
```

```php:SampleTest.php
<?php
use PHPUnit\Framework\TestCase;
use app\Sample;

class SampleTest extends TestCase
{
    public function test_Hello()
    {
        $sample = new Sample();
        $result = $sample->hello();
        $this->assertEquals("Hello",$result);
    }
}
```
```Sample.php```には'Hello'と表示させる簡易なメソッドを用意する。
```SampleTest.php```で、hello()メソッドから表示されたものが、 'Hello 'かをチェックする。
この時、```Sample.php``で定義するSampleクラスを```SampleTest.php```で使えるようにするために、```composer.json```に下記のコードを追加する。
```json:composer.json
{
    "require-dev": {
        "phpunit/phpunit": "^9.5" //インストール後にバージョンの数字が変化
    },

    "autoload": {
        "psr-4": {
            "app\\": "src/"
        }
    }
}
```
コードを追加したらターミナルで、```composer dump-autoload```コマンドを実行する。
これにより、srcディレイクトリ配下を「app」という名前空間にしていし、使用することができる。
参考：[composer.jsonのautoloadの書き方参考ページ](https://pointsandlines.jp/server-side/php/autoload-composer)
# 3.テスト実行
ターミナルでphpunitディレクトリまで移動し、```vendor/bin/phpunit test/```を実行。
下記のような結果となり無事成功！

```
PHPUnit 9.5.21 #StandWithUkraine

.                                                                   1 / 1 (100%)

Time: 00:00.004, Memory: 4.00 MB

OK (1 test, 1 assertion)

```
【初心者向け】Linuxの種類と基本操作をざっくりまとめていくお

# Linuxとは　
```
■ オープンソース（無料で使用できプログラムの改変が可能）なOSである
---→ ここ20年程度で天才プログラマーたちが改良に改良を重ねてすんばらしいOSになった！

■ オープンソースゆえにサーバーとしてよく用いられる
---→ Windowsだと何万円もかかってしまう

■ MacOSやAndroidみたいな新しいOSを作ることもできる
---→ かの有名なOSも基はLinux

■ UIはCUIだけのものもあればGUIでの操作ができるものもある
---→ CUIとは、あの真っ暗な画面でコマンドが打てるあれ

■ 大きく分けてDebian系とRedHat系に分かれる
---→ それ以外にもあるが、とりあえずこれだけ覚えておけば何とかなる
     目的によって適切なものを選べばよい
```
Debian系とRedHat系それぞれの一部種類と詳細を以下で紹介
※なおカーネルやらディストリビューションやら話をすると長いので割愛、、、

# Linuxの種類

### Debian系
**■Debian**
主にCUIでコマンド入力し操作するLinux
初学者には少しお堅く元祖Linuxというイメージ

##### **普通のパソコンとしてDebian系を使いたい場合は下記がおすすめ**
**■Ubuntu**
Windowsに近いGUIでとても使いやすい
筆者が最初に触ったLinuxはこれ
あまりWindosとデザインや操作感が変わらないのでLinux初学者におすすめ

**■Linux Mint**
Microsoft Officeに似たソフトが使えることで有名
GUIもUbuntuのように使いやすくシンプル

**■elementary OS**
Windowsはあまり使わないという人におすすめ
デザインや操作感はMacのような感じ

### Red Hat系
Red Hat系は商業的側面の強く、安定性があり、有償ライセンスでのサポートもあるためサーバーとして用いられることが多い

**■Red Hat Enterprise Linux(RHEL)**
Red Hat社が開発した有償のLinuxである
個人というよりは企業が使用しているイメージ

**■Cent OS**
RHELとの互換性が高く人気のある無償のLinux
個人でRed Hat系を使うならこれ
ただし、2021年にサポートは終了したため、企業では採用しずらいが
個人で楽しむ分には問題ないかと

**■Raspbian**
軽量なPCを作成するのに向いているLinux
人気なものにRaspberry Piがある
本体価格は安くスターターキットが1万円くらいで購入できる
### Debian系とRed Hat系のコマンドの違い
Debian系とRed Hat系はパッケージと呼ばれる拡張機能（nanoやSambaやNTP等）をインストールする際に、コマンドの入力が必要だが下記のようにそれぞれで異なる

**■パッケージのインストール**
```
・Debian系
apt-get install <パッケージ名>
・Red Hat系
yum install <パッケージ名>
```
**■パッケージの削除**

```
・Debian系
apt-get remove <パッケージ名>
・Red Hat系
yum erase / remove <パッケージ名>
```
サーチリスト とは

## 勉強前イメージ

DNS系のなんかのリスト？

## 調査

## サーチリスト とは

ユーザがドメイン名を入力する手間を減らせるようにするためのリストです。
DNS検索サフィックス や DNS suffix search list など呼ばれています。
多くのOSなどはサーチリストの機能を持っています。
基本的には大まかに標準化されていますが厳密な規定はないので、OSやブラウザによって動作が異なります。

どういうものかというと、名前解決のときにユーザがドメイン名を最後まで入力しなくても
サーバやクライアントで保管ができるように、候補となる文字列を順番に並べたものです。
例えば www.example.com があるとして、リストに example.com を設定しておけば
www と打てば www.example.com に保管してくれるようなものです。
優先度をつけて複数指定することもできます。

CentOSでの設定方法は以下です。

```
vi /etc/resolv.conf
==========
search         example.com example.net example.org
==========
```

これを設定することで、 www に名前解決させる際に以下の順番で名前解決を試していきます。

1. www.example.com
2. www.example.net
3. www.example.org

## 勉強後イメージ

そんな機能があるって知らなかった・・・
けど、resolv.confでの設定方法みたら
確かにsearchは見たことあったわ。。。。

## 参考

- [「/etc/resolv.conf」ファイル](https://linuc.org/study/knowledge/507/)
- [DNSサフィックス 【DNS suffix】 ドメインサフィックス / domain suffix](https://e-words.jp/w/DNS%E3%82%B5%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9.html)
- [サーチリストとは](https://www.nic.ad.jp/ja/basics/terms/search-list.html)
Haskell でモンテカルロ法を試してみた

## 概要
腕試しにHaskellでモンテカルロ法を試してみた。

## コード

処理の流れ。簡単ですね。
第一象限の全体は (x,y) = (0..1, 0..1)で全体では1の面積となる。
一般に第一象限の円の面積は $\dfrac{\pi r^{2}}{4}$ ですが、今回は $r=1$ なので円の面積は $\dfrac{\pi}{4}$ になります。
円内に入る確率が $\dfrac{\pi}{4}$ に近づくことを確認できます。確率密度関数がどうこう…といった話です。

1. 第1象限内で (x, y) で (0..1, 0..1) の範囲をランダムな座標を生成する
1. 円内部に点があれば True、そうでなければ False を返却する
1. (Trueの個数) / (試行回数) = (円内に入る確率)

**Haskell特有の注意点**

* x, y で別々に mkStdGen seed / newStdGen で乱数を生成し、座標を作ると乱数の品質が悪くなる
  * 1つの系列から 2つの乱数を取り出して(x, y)のペアを作り x^2 + y^2 の計算をしている

```haskell
module Main where
import System.Random
import System.Environment (getArgs)
import Text.Printf

computeNorms :: [Double] -> [Double]
computeNorms []  = []
computeNorms [x] = []
computeNorms (x:y:xs2) = (x*x + y*y) : (computeNorms xs2)

calcPi :: Int -> [Double] -> Double
calcPi n xs =
  (\x -> ((4 :: Double) * (fromIntegral x))/(fromIntegral n))
  $ length $ filter (== True) $ take n
  $ map (\x -> x < 1) xs

runMonteCarloNoSeed :: Int -> IO ()
runMonteCarloNoSeed num_trials = do
  gen <- newStdGen
  let monte_carlo_pi = calcPi num_trials (computeNorms (randomRs (0, 1) (gen) :: [Double]))
  printf "trial=%10d, result=%.10f, error=%.10f\n" (num_trials) (monte_carlo_pi) (abs (monte_carlo_pi - pi))

runMonteCarloWithSeed :: Int -> Int -> IO ()
runMonteCarloWithSeed num_trials seed = do
  let monte_carlo_pi = calcPi num_trials (computeNorms (randomRs (0, 1) (mkStdGen seed) :: [Double]))
  printf "trial=%10d, result=%.10f, error=%.10f\n" (num_trials) (monte_carlo_pi) (abs (monte_carlo_pi - pi))

main :: IO ()
main = do
  let trialList = [1, 10, 10^2, 10^3, 10^4, 10^5, 10^6, 10^7]
  putStrLn "-- runMonteCarloNoSeed"
  mapM_ (\n -> runMonteCarloNoSeed n) trialList

  let seed = 1
  putStrLn $ "\n-- runMonteCarloWithSeed: seed=" ++ (show seed)
  mapM_ (\n -> runMonteCarloWithSeed n seed) trialList
```

## 実行結果

試行回数が増えるに従って誤差が減っていることが分かる。ただし、収束はとても遅い。

* runMonteCarloNoSeed
  シードの指定なし。自動的にシードを生成するので、呼び出すごとに結果が異なる
* runMonteCarloWithSeed
  乱数のシードあり。結果は毎度同じ。

```console
$ cabal v2-run
Up to date
-- runMonteCarloNoSeed
trial=         1, result=0.0000000000, error=3.1415926536
trial=        10, result=2.8000000000, error=0.3415926536
trial=       100, result=3.3200000000, error=0.1784073464
trial=      1000, result=3.1960000000, error=0.0544073464
trial=     10000, result=3.1360000000, error=0.0055926536
trial=    100000, result=3.1355600000, error=0.0060326536
trial=   1000000, result=3.1412320000, error=0.0003606536
trial=  10000000, result=3.1416380000, error=0.0000453464

-- runMonteCarloWithSeed: seed=1
trial=         1, result=4.0000000000, error=0.8584073464
trial=        10, result=3.2000000000, error=0.0584073464
trial=       100, result=3.0800000000, error=0.0615926536
trial=      1000, result=3.1160000000, error=0.0255926536
trial=     10000, result=3.1268000000, error=0.0147926536
trial=    100000, result=3.1389600000, error=0.0026326536
trial=   1000000, result=3.1408120000, error=0.0007806536
trial=  10000000, result=3.1413364000, error=0.0002562536
```
Retty サマーインターン2022参加記

# 概要
この記事は、Rettyサマーインターン2022の参加記です。バックエンドでの参加でした。

# インターン概要
- 3週間
- 基本オンライン・出社も許可を取れば出来る
- GoとgRPCでマイクロサービスを開発
- 新しいマイクロサービスを設計から
- チーム開発・モブプロ
# 学んだこと
学びしかなかったです。というか、知っている技術領域や設計・開発思想等が一つもなかったので、当たり前なんですが。よく採用してくれたな...
## TDD
今まで開発でテストを書くことがほぼなかったですが、初めて書きました。その勢いで（？メンターさんの宗派もあり？）後半のほうはTDDで開発を行いました。私的な観点ですが、TDDのメリットとして
- 振る舞いを定義してから実装に移れる
    - 途中で、「こういう時は異常系？」「あれ、この場合って何が返ってくるんだ？」が起こりづらい
- 見通しを立ててから実装できる
のような点があると思います。一方、見通しを立てないと実装に移れない。というデメリットもあると思っていますが。
テストを書くメリットもかなり学ぶことが出来、大満足でした。テストは絶対書いたほうがいい気がします。思ったより時間はかからないですし、列挙するパターンが多すぎるときはそもそも関数の切り分けが上手くいっていないみたいなお話もメンターさんからいただきました。
## Go
Goは初めてでしたが、Go結構好きになりました。書きやすいし、Pythonみたく変にグローバルになったりしないし、ポインタの概念等も上手く組み込まれてるし、パッケージ等の管理も結構簡単。個人的に、変数名をCapitalizeするとpublic関数になる規則に関してだけ好きじゃないかなあといった感じです（三週間しか触っていない感想ですが。）
## クリーンアーキテクチャ
参加前は名前を知っているぐらいで、思想をインターン前に少し学んでから参加しました。手を動かしてみないと理解できない概念だと感じていて、インターンを通して60%ぐらいは理解できました。クリーンアーキテクチャについて書くと各方面からマサカリが飛んできそうなので、書籍を読んでから言及しようと思います。
## モブプロ
モブプロを初めて行いました。正直、開発効率はかなり落ちると考えています。（人数にもよりますが）一方、理解度をそろえるという点では、かなり有用な手段だと考えていて、メンターさんからの受け売りですが、「ある領域の属人化を解消する目的」というのはしっくりきました。また、一番クリティカルに良いと思った点は、使ってる拡張機能であったり、VSCode内の検索の仕方であったり、ターミナルの使い方等、全員の「これを使うとちょっと便利になる」を見れるところだと思いました。自転車や、電車を知らない人が、徒歩圏内で生活出来るから、徒歩を不便と感じない。ように、「便利なもの」ってそれ自体を知る機会がないと使わないんですよね。（それが無いと強烈に不便であるものは別ですが。）
## その他
- SQLとかしっかり書いたのは初めてでした。大した量は書いてないですが
- gRPCもはじめて、結構いい感じでした。
- git-hooksの導入もしました。あれいい。
# Rettyインターンの良かった点
- 裁量がかなり委ねられていました。自主性を重んじるといったら安っぽく聞こえますが、デリゲーションポーカーというものを使用し、メンターさんにどの程度頼るか？みたいなものを自分たちで決めたり、出社のタイミングもチームで合わせていこうか～みたいに話して許可を出してもらったり、休憩のタイミングや、昼休憩、一日のスケジュール等をほぼ自分たちで話し合って決めていました。
- 出社したタイミングである程度のエンジニアさんと話しましたが、みんないい人でした。
- 人事の方との1on1が週一であり、フォローアップも充実していました。
# まとめ
- しらない技術領域のインターン、めちゃくちゃよかったです。
- 非の打ち所がなかったインターンでした。テスト期間と被ってるのはしんどかったです。
WordPressで突然記事が公開できなくなった

突然記事が公開できなくなった。

公開ボタンを押した時、
何を書いても記事が削除されて「自動下書き」という内容に書き換えられる。


原因は大量にあるらしいが、今回の場合はwordpressを設置しているサーバに.htaccessを配置したことが原因だった。
.htaccessの内容を全部消したら治りました。
[NodeCG] イチから(簡単な)バンドルを作ってみた(その3)

# 前回のおさらい

https://qiita.com/na2na/items/bae92a203ec25b0c8e3a

- graphicsとdashboardについて、React製な画面を出せるようにした
- ちょっと便利になるpackage.jsonのscripts整備した

# 今回の目標

- extensionについて、TypeScriptでいい感じにしていきたい。

# 今回の登場人物
- TypeScript

# 作業

コマンドラインでのカレントディレクトリが、自作バンドルの直下にいる想定で進めます。
余談かも)nodecg本体がESM対応してないように見えた(package.jsonのtype="module"とかそういう表記が無い)ので、PureESMで作るのは無理そう（出典無し

## tsconfigを作る
### 流れ
1. extensionへ移動する
1. yarn initする。
1. yarn add -D typescriptする
1. yarn tsc --initする
1. .gitignore作る
1. tsc-alias導入する
1. (お好みで)ついでにこのタイミングでeslint入れる(前回記事を参考にするか、他の記事見てもらえるといいのかも)

### 作業
```shell
cd extension
yarn init # ここは基本Enterだけでいいです。なんなら-yオプション付けてもよかったかも
yarn add -D typescript
yarn tsc --init
touch .gitignore && echo dist > .gitignore
yarn add -D tsc-alias
```
ここまで来たらVSCodeを開いて、tscinfig.jsonを確認します。気になる箇所があれば好きにカスタマイズしてください。

## ディレクトリ構成をいい感じにする
想像していたものの1000倍難しかったので説明が難しいです。とりあえず、[これ](https://github.com/na2na-p/my-usual-layout/tree/471f29715ff44ab95a0230c7aaa779cde971fbb0)のextensionディレクトリ以下を見てもらえると助かります。。。少なくとも執筆時点での私には、extensionのindex.jsファイルの位置の指定の変更がわからなくてどうしようもないです。とりあえず動くように作ります。。。該当コミット段階ですでに下の型定義追加までやっています。ちなみにextension直下にいるindex.jsはこれをコンパイルした物です
```ts:index.ts
import main from './dist/main';
export default main;
```

## NodeCGの型定義を追加する
[ここ(リンク)](https://www.nodecg.dev/docs/frameworks/typescript)を参考に、index.tsをいじります。
ついでに微修正します。

## 一度使ってみる
### 流れ
1. extension内のpackage.jsonのscripts追加
1. バンドル直下のpackage.json修正
1. NodeCG起動

### 作業
extension内のpackage.jsonにビルド用スクリプトを追加します。
```json:extension/package.json
	"scripts": {
		"build": "yarn tsc -p tsconfig.json && yarn tsc-alias -p tsconfig.json"
	}
```
バンドル直下のpackage.json修正します(extensionだけ書き方違うのアレなので後で直しておきます。。。)
```json:package.json
scripts: {
		"build": "yarn build:extension && cd dashboard && yarn build && cd ../graphics && yarn build",
		"build:extension": "cd extension && yarn build",
}
```
ここまで来たら起動してみます。
バンドル直下のpackage.jsonのscriptsに`nodecg:start`の定義をしてあるなら同階層で`yarn nodecg:start`してあげれば起動します。
```
info: [my-usual-layout] Hello, from your bundle's extension!
info: [my-usual-layout] I'm where you put all your server-side code.
info: [my-usual-layout] To edit me, open "/home/na2na/develop/nodecg/bundles/my-usual-layout/extension/dist/main.js" in your favorite text editor or IDE.
info: [my-usual-layout] You can use any libraries, frameworks, and tools you want. There are no limits.
info: [my-usual-layout] Visit https://nodecg.com for full documentation.
info: [my-usual-layout] Good luck!
```
と表示が出ていれば問題ありません。お疲れさまでした。

# まとめ
- extensionに使うエントリポイントとしてのindex.jsの場所変える方法が欲しい

とりあえず、Yoでできたテンプレートがすべて出るような状態になったのでこのシリーズの目標は達成です。
もしかしたらその4書くかも...?
イントラネット とは

## 勉強前イメージ

聞いたことはあるなぁ・・・

## 調査

### イントラネット とは

イントラネットとは Intranet と書き、内部のネットワークを意味する言葉になります。
意味はそのままで内部ネットワークになり、企業などの内部のネットワークを指します。
イントラネットの対義語はインターネットになります。

基本的にはインターネットで標準的に使用されているTCP/IPを利用したネットワークがベースで
webシステムやメールのシステムが構築されます。
普段利用しているブラウザやメールなどは同じように使えます。

### イントラネットとLANの違い

どちらも小規模ネットワークであることは共通しています。
例えば、東京・大阪・名古屋に拠点がある会社の場合
東京・大阪・名古屋の事業所はそれぞれLANのネットワークが使われていますが
会社全体をつなぐのはイントラネットになります。
会社に閉じたネットワークになります。

## 勉強後イメージ

## 参考

- [【ネットワーク基礎】LANとWANの違いについて解説する！](https://gyroibaraki.com/network-lan-wan/)
- [イントラネット 【intranet】](https://e-words.jp/w/%E3%82%A4%E3%83%B3%E3%83%88%E3%83%A9%E3%83%8D%E3%83%83%E3%83%88.html)
PIL.Image.Imageをdiscord.Fileに変換したい

こんにちはbeatbox4108です。
今回は少しPythonを書いていて躓いた点を覚書程度にまとめましたので見てみてください

# TL;DR

:::note
`io.BytesIO`を使おう。
:::
:::note warn
`seek(0)`するのを忘れずにしよう。
:::
# 本文
Pythonで、Discordのスラッシュコマンドに反応して画像を送るbotを作っていた時のこと...

**あれ?ファイルに出力しないと送信できなくね?**

この時の環境、クラウド上で容量が結構少なかったのでどうしてもファイルに出力するのは避けたかったんです。
でも**ファイルオブジェクト**かパスじゃないと送信できないし...

と、気づいたんです。そうか`BytesIO`介せばいいのか！
ということで書いたこちらのコード、ダメな点が一つありました。
```python3
# im は PIL.Image.Image
fileio=BytesIO()
image.save(fileio,format="png")
await interaction.followup.send(file=discord.File(fileio,"file.png"))
```
**あれ？**
Discord側ではちゃんとファイルは送信されたものの、肝心の中身がありませんでした。
* * *
原因は簡単。ある1行が抜けていました。
```diff_python3
  fileio=BytesIO()
  image.save(fileio,format="png")
+ fileio.seek(0)
  await interaction.followup.send(file=discord.File(fileio,"file.png"))
```
これはIOの最初に戻るコマンド。
さっきのままだとどれだけ読み込んでもファイルの末端なので0バイトが出力されるだけでした。

:::note info
筆者はこれに半日費やしました...
:::
* * *
ってことでみんなは気を付けてくださいね...
minecraft統合版のサーバーをdockerで構築

docker-ceとdocker-compose-pluginをインストール
（ほかの記事に任せます）

一般ユーザでdockerを実行できるようにする

    $ sudo usermod -G docker hoge
    $ sudo cat /etc/group | grep docker
    docker:x:993:hoge

上記設定反映のために一度切断

    $ exit


再接続し、loki-driverをインストール

    $ docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions
    latest: Pulling from grafana/loki-docker-driver

/opt配下に統合版用のcompose置き場を作成

    $ sudo mkdir /opt/docker
    $ sudo chown hoge:hoge /opt/docker
 

compose作成

    $ cd /opt/docker
    $ vi compose.yml
    ----------ここから----------
    services:
      minecraft:
        image: itzg/minecraft-bedrock-server
        container_name: minecraft
        environment:
          EULA: TRUE
          SERVER_NAME: 任意(hogeサーバ等)
          LEVEL_NAME: 任意(yyyy-mm-dd等)
          GAMEMODE: survival
          FORCE_GAMEMODE: true
          DIFFICULTY: normal
          ALLOW_CHEATS: true
          ALLOW_LIST: false 
          ONLINE_MODE: true
          TZ: Asia/Tokyo
        ports:
          - 19132:19132/udp
        volumes:
          - /minecraft:/data
        stdin_open: true
        tty: true
        logging:
          driver:loki
          options:
            loki-url:http://192.168.1.x:3100/loki/api/v1/push

      loki:
        image: grafana/loki:latest
        container_name: loki
        ports:
          - 3100:3100

      grafana:
        image: grafana/grafana:latest
        container_name: grafana
        ports:
          - 3000:3000
        volumes:
          - grafana:/var/lib/grafana

    volumes:
      minecraft:
      grafana:
    #volumeの場所
    #/var/lib/docker/volumes/
    ----------ここまで----------
   
docker を起動

    $ docker compose up -d

動作を確認

    $ docker compose ps
    CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS                    PORTS                      NAMES
    73c49f8ce89d   itzg/minecraft-bedrock-server   "/usr/local/bin/entr…"   22 seconds ago   Up 22 seconds (healthy)   0.0.0.0:19132->19132/udp   minecraft
    0e8493f158e6   grafana/grafana:latest          "/run.sh"                22 seconds ago   Up 22 seconds             0.0.0.0:3000->3000/tcp     grafana
    f785179953c3   grafana/loki:latest             "/usr/bin/loki -conf…"   22 seconds ago   Up 22 seconds             0.0.0.0:3100->3100/tcp     loki
 
子供向けのサーバチューニング（お好みで）
    
    $ docker attach bedrock_server #アタッチコマンド
    gamerule showCoordinates true　#座標を表示
    gamerule pvp false　#味方へのダメージ無効
    gamerule keepInventory true　#死亡時にアイテムを落とさない
    Ctrl+P　→　Ctrl+Q #タッチコマンド

サーバのバージョンアップ

    $ docker compose down
    $ docker compose up -d
NCMBのFlutter SDKがスクリプト実行に対応しました

FlutterはDartで書かれたフレームワークになります。元々iOSやAndroidといったスマートフォン向けでしたが、今ではWebやWindows、macOSといったマルチプラットフォームで動作します。Flutter/Dartを覚えることで、多くの環境に対してアプリケーション開発が可能になります。

NCMBでは公式SDKを提供していませんが、非公式に開発を進めているFlutter SDKがあります。だいたいの機能は実装してきましたが、今回スクリプトの実行にも対応したので使い方を解説します。

[ncmb | Dart Package](https://pub.dev/packages/ncmb)

## インストール

`flutter pub get ncmb` でインストールできます。

## 使い方

任意のファイル上でライブラリを読み込みます。

```dart
import 'package:ncmb/ncmb.dart';
```

そしてNCMBオブジェクトを初期化します。

```dart
NCMB('APPLICATION_KEY', 'CLIENT_KEY');
```

## スクリプトオブジェクトの作成

まずスクリプトオブジェクトを作成します。引数はアップロードしたスクリプトのファイル名です。

```dart
var script = NCMBScript('script_test_get.js'); // Script name
```

## ヘッダー、ボディ、クエリーの指定

スクリプトはヘッダー、ボディ、クエリーを指定できます。

### ヘッダーの指定

```dart
script.header('foo1', 'bar1');
script.header('foo2', 'bar2');
```

### クエリーの指定

```dart
script.query('hoge1', 'fuga1');
script.query('hoge2', 'fuga2');
```

### ボディの指定

ボディはPOST/PUTメソッドの時しか使えません。

```dart
// Only POST or PUT method
script.body('hoge2', 'fuga2');
script.body('hoge3', 'fuga3');
```

## 実行

実行は各HTTPメソッドごとにメソッドを用意しています。

### GET

```dart
var result = await script.get();
```

### POST

```dart
var result = await script.post();
```

### PUT

```dart
var result = await script.put();
```

### DELETE

```dart
var result = await script.delete();
```

## レスポンス

レスポンスは何が返ってくるか分からない（Object）なので、スクリプトの実装に合わせてキャストしてください。

## まとめ

Flutter SDKはiOSやAndroidはもちろん、Linux/macOS/Windows/Webでも利用できます。ぜひ皆さんのアプリ、Webアプリ開発に利用してください。

[ncmb | Dart Package](https://pub.dev/packages/ncmb)
テスト75

```vb
Public Sub PW付PDF分割()
'-----------------------
'参照設定：Acrobat(Adobe Acrobat 10.0 Type Library)
'有料のAcrobat Proを使えるようにしておく必要がある
'-----------------------
'主な参考サイト様
'初心者備忘録beginner's memo
'https://www.ka-net.org/blog/?p=7293

'VBA(Excel)からAcrobat経由でPDFをプログラミング操作(OLE:IAC)する
'http://pdf-file.nnn2.com/?p=93
'-----------------------
'メモ
'テスト74の応用
'パスワード付PDFを開いて、それを1ページずつ
'パスワード無しPDFとして分割して出力する。...〆(･ω･´)ﾒﾓﾒﾓ
'-----------------------

Dim jso As Variant
Dim i As Long
Dim fp As String
Dim fn As String
Dim FSO As Variant
Dim objWSH As Object
Dim Limit As Date
Dim hwnd As Long
Dim edt_hwnd As Long
Dim btn_hwnd As Long
Dim strPassword As String
Dim strFileName As String

'--------------------------------------
'初期設定
'PDFファイルのパスワード
strPassword = "111111"

Const PdfFilePath = "C:\Users\User\Desktop\VBA練習\PDF\分割\PW付test.pdf"

Set objWSH = CreateObject("Wscript.Shell")
'PDFファイルオープン
objWSH.Run """" & PdfFilePath & """", 1

'--------------------------------------
'パスワードダイアログのハンドル取得
Do Until hwnd <> 0

    hwnd = FindWindow("#32770", "パスワード")
    '処理待ち
    Sleep (50)
    
    DoEvents
    
Loop

hwnd = FindWindowEx(hwnd, 0&, "GroupBox", vbNullString)


'パスワード入力欄のハンドル取得
edt_hwnd = FindWindowEx(hwnd, 0&, "RICHEDIT50W", vbNullString)
'OKボタンのハンドル取得
btn_hwnd = FindWindowEx(hwnd, 0&, "Button", "OK")

If (edt_hwnd <> 0) And (btn_hwnd <> 0) Then

    'パスワード送信
    Call SendMessage(edt_hwnd, WM_SETTEXT, 0&, strPassword)
    
    'OKボタンをクリック処理
    Call SendMessage(btn_hwnd, WM_ACTIVATE, 1, 0&)
    Call SendMessage(btn_hwnd, BM_CLICK, 0, 0&)

End If

'--------------------------------------
'PDFの処理
Dim objAcroApp As New Acrobat.AcroApp
Dim objAcroAVDoc As New Acrobat.AcroAVDoc
Dim objAcroPDDoc As Acrobat.AcroPDDoc
Dim PageCount As Long
Dim Ret  As Long

Set FSO = CreateObject("Scripting.FileSystemObject")

'フォルダパスとファイル名取得
With FSO

    fp = Getfolpath(.GetParentFolderName(PdfFilePath))
    fn = .GetBaseName(PdfFilePath)
  
End With

'Acrobatを起動
Ret = objAcroApp.Show

Ret = objAcroAVDoc.Open(PdfFilePath, "")

'PDDocを取得
Set objAcroPDDoc = objAcroAVDoc.GetPDDoc

'ページ数を取得
PageCount = objAcroPDDoc.GetNumPages()


With CreateObject("AcroExch.PDDoc")

    If .Open(PdfFilePath) = True Then
    
        Set jso = .GetJSObject
        
        For i = 0 To PageCount - 1

            CallByName jso, "extractPages", VbMethod, _
                        i, i, fp & fn & "(" & i + 1 & ").pdf"
        Next
        
        .Close
    
    End If
  
End With

'--------------------------------------

Set objWSH = Nothing
Set FSO = Nothing
Set objAcroApp = Nothing
Set objAcroAVDoc = Nothing
Set objAcroPDDoc = Nothing
Set jso = Nothing

MsgBox "処理が終了しました。", vbInformation

End Sub
 
Private Function Getfolpath(ByVal str As String)
  If Right(str, 1) <> ChrW(92) Then str = str & ChrW(92)
  Getfolpath = str
End Function
Unreal Engine 5 ハンズオン(環境構築編)

## 概要
Unreal Engine 5 ハンズオンの環境構築をやってみましょう！
## 所要時間
2時間~10時間(通信環境による)
## 内容

### EpicGames Launcherのインストールまで
Unreal Engine 5は、他のゲームと同様に、EpicGames Launcher と呼ばれるゲームランチャーを介して起動します。

1. [https://www.unrealengine.com/en-US/unreal-engine-5](https://www.unrealengine.com/en-US/unreal-engine-5) にアクセス
2. EpicGamesアカウントを持っていなければアカウント登録/すでに持っていればログイン
3. DOWNLOADをクリック
![%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2022-08-10_20.18.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/dc0d0b1a-2f20-af10-b8ee-97243c9a3368.png)


1. EpicGamesLauncherをダウンロード(58MB)
![%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2022-08-10_20.22.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/eceda725-6016-a27c-6b46-c848b2f7079c.png)

4.インストール

### Unreal Engine 5のインストールまで

1. 起動
1. しばらく待機するとこの表示が出てくるので　ダウンロードが終わるまで待つ(269MB)

![%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2022-08-10_20.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/555c6a1c-b767-fff2-f556-557c6b1b019d.png)


6.アプリケーション内でログイン後、次のようにクリックしてUnreal Engine 5をダウンロード(27.5GB)1時間位かかる
![%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2022-08-10_20.41.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/5401a260-4e3d-63ae-279e-ae7cf92dcf2a.png)



1. 起動(直ちに反応がなくても2回以上クリックしない)。初回起動は ~~ちょっと~~  めっちゃ時間がかかる。

「シェーダをコンパイル」がめっちゃ長い。(20分)括弧の中の数字が減っていくのを眺めよう。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/2afb0c0a-baca-c2b5-50dd-272352de61f6.png)



![スクリーンショット 2022-08-10 22.20.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/e2b4bac2-75c7-a126-8414-40d96903ec6f.png)

## プロジェクト作成

品質プリセットを"Scalable"にする。

![スクリーンショット 2022-08-27 17.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/6f87c84d-2615-b19a-6607-32d496237d2b.png)


## UnrealEngine5の設定



### 軽くしたい

ノートパソコンの場合は初期設定だと重いです。(MacBook Pro 14" (M1 Pro))

![スクリーンショット 2022-08-10 22.52.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/135f503d-925c-3baa-5c7d-aed23d0b606b.png)

動作が重くなってしまうのは、プレビュー画面の解像度が高すぎること一番の原因です。デフォルトのレイアウトだとプレビュー画面が大きいことがわかります。このまま使うと、特にmacのRetinaディスプレイなどの高解像度ディスプレイではパフォーマンスに大きく影響します。それではプレビュー画面を小さくしましょう。

"ウィンドウ">"レイアウトをロード">"デフォルトのエディタレイアウト"をクリックすることで、いつでもレイアウトをデフォルトの状態に戻せます。

![スクリーンショット 2022-08-27 16.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/c9fad067-c602-4570-d31d-937b456129e8.png)

画面左下のコンテンツドロワーをクリックします。


![スクリーンショット 2022-08-27 16.55.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/788f4f59-25c7-ef47-ea15-79a7ca13d24a.png)


レイアウトにドッキングを押します。

![スクリーンショット 2022-08-27 16.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/aab7fef6-de04-3acf-ef01-77990b405c4b.png)

レイアウトの境界をドラッグすることでプレビュー画面を小さくします。

![スクリーンショット 2022-08-27 16.58.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326888/5f593f0f-f59e-d544-03e1-8b3fd1fbc8fa.png)

こうしておくだけで作業中も結構軽くなります。
MySQL8.0のDBとユーザー管理をしやすくするTips

# はじめに
ほぼ初記事で拙いところがあると思いますが、ご容赦ください。
[完成品](https://docs.google.com/spreadsheets/d/1e14_jKtZbhKc2ns0QWeau4800nrou-n_ubg0D2dKiPs/edit?usp=sharing)はこちらです。使用する際はコピーして使用してください。
また、本記事のシートはMySQL8.0のみに対応しています。ご注意ください。
# 自宅のMySQLサーバーのDB管理
私の自宅にはMySQL8.0のサーバーが設置されている。
開発しているプロジェクトごとにDBを用意して開発をしているのでプロジェクトごとに
対応するDBとそのDBを持ったアカウントを作成する必要がある。
下記が今まで使用していた管理を行っていたスプレッドシート。
![sql.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664165/152d0fd7-8057-87de-4ce8-fdda88a7edbe.jpeg)
# スプレッドシートに入力した情報からコマンドを自動作成する
今までは上記の画像のように作成したDBとユーザーの管理用として使っていましたが、
逆にスプレッドシートに入力したDBの名前とユーザー名からそれらを作成できるコマンドを自動生成してみる。
それぞれの役割のコマンドは以下の通り。
```sql:set.sql
create database Test;
--Testという名前のDBを作成
CREATE USER 'Test-1'@'%' IDENTIFIED BY '1test#$2pass';
--Test-1というユーザーを作成。
--1test#$2passはパスワード。
GRANT ALL ON Test.* TO 'Test-1'@'%';
--Test-1というユーザーにTestというDBの全権限を割り当て。
FLUSH PRIVILEGES;
--設定を反映。
```
これらのコマンドをスプレッドシートに入力した情報から自動生成する。
[完成品](https://docs.google.com/spreadsheets/d/1e14_jKtZbhKc2ns0QWeau4800nrou-n_ubg0D2dKiPs/edit?usp=sharing)で行っている関数処理は単純な文字結合なのでスプレッドシート上の関数処理については省略。
K列にコマンドが生成されるのでMySQL8.0のコンソールにコピペして実行する。
# 今後の展望(?)
個人的に使うために思いつきで作ったものなのであまり完成度は高くありませんが、自分が使っているところではかなり重宝している。
今後需要があれば複数ユーザーへの対応やアクセス制限や権限の詳細設定などのコマンド生成に対応したバージョンのものを作ろうと思う。
Golangでログイン機能を実装する。(Step1:APIで値を返却する)

### はじめに
[前回の記事](https://qiita.com/kouji0705/items/cda9038c6d6e2d3c4efe)に付随する記事となります。
前回の記事まででは、UIコンポーネントを利用してログイン機能のデザインのみを作成しました。API疎通するためのバックエンドのシステムを作成します。本記事ではGolangでAPIを作成します。

### 環境情報
```
PC:M2 Mac Book Air
Golang:go version go1.19 darwin/arm64
```

### HelloWorld出力
本記事では、go fiberを利用してAPIを作成します。fiberを利用しHelloWorldを出力します。

```shell:ディレクトリ構成
~/go/src/fiber_login$ tree
.
├── go.mod
├── go.sum
└── main.go

0 directories, 3 files
```

```go:go.mod
module fiber_login

go 1.19

require github.com/gofiber/fiber/v2 v2.36.0

require (
	github.com/andybalholm/brotli v1.0.4 // indirect
	github.com/klauspost/compress v1.15.0 // indirect
	github.com/valyala/bytebufferpool v1.0.0 // indirect
	github.com/valyala/fasthttp v1.38.0 // indirect
	github.com/valyala/tcplisten v1.0.0 // indirect
	golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
)

```

```main.go
package main

import (
	"fmt"
	"log"

	"github.com/gofiber/fiber/v2"
)

func main() {
    app := fiber.New()
    app.Get("/", func(c *fiber.Ctx) error {
        fmt.Println("🥉 Last handler")
        return c.SendString("Hello, go fiber 👋!")
    })
    
    log.Fatal(app.Listen(":1323"))
}
```

```go:main.go実行
~/go/src/fiber_login$ go run main.go 

 ┌───────────────────────────────────────────────────┐ 
 │                   Fiber v2.36.0                   │ 
 │               http://127.0.0.1:1323               │ 
 │       (bound on host 0.0.0.0 and port 1323)       │ 
 │                                                   │ 
 │ Handlers ............. 2  Processes ........... 1 │ 
 │ Prefork ....... Disabled  PID ............. 64530 │ 
 └───────────────────────────────────────────────────┘ 
```
→localhost:1323でListen状態を確認します。

![スクリーンショット 2022-08-10 19.48.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/bb6391ba-9ba4-2d2b-a13f-3ea469453e6d.png)
→ここまでできれば、肩慣らし完了です。

### ログイン機能の前提
本記事では、機能の実装内容を絞りプログラミングしていきます。
下記内容は今後の記事でアップデートしていきます。

```go:実装しない内容
・Validationチェックなし
・エラーハンドリングなし
・DB疎通なし
・JWTの生成なし
```

```:APIの仕様
エンドポイント：/api/login
メソッド：POST通信
リクエストBody：
{
   user_id:"",
   password:""
}

レスポンス：ステータスコード：200
{
}
```
→リクエストBodyの値は受け取りますが、リクエストをそのままオウム返しします。

### コードの実装

```shell:ディレクトリ構成
~/go/src/fiber_login$ tree -I tmp 
.
├── go.mod
├── go.sum
├── main.go
└── model
    └── user.go

1 directory, 4 files
```

```go:main.go
package main

import (
	"fiber_login/model"
	"fmt"
	"log"

	"github.com/gofiber/fiber/v2"
)

func main() {
	app := fiber.New()
	app.Use(cors.New())
	app.Post("/api/login", func(c *fiber.Ctx) error {

		var body model.User
		c.BodyParser(&body)

		// Userの中身を確認
		fmt.Println(body)

		// json
		return c.Status(fiber.StatusOK).JSON(body)
	})

	log.Fatal(app.Listen(":1323"))
}
```

```go:model/user.go
package model

type User struct {
	UserID   string `json:"user_id"`
	Password string `json:"password"`
}
```

■実行結果
![スクリーンショット 2022-08-11 13.26.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/308bbbde-8422-a215-35d0-d42a1753dd17.png)
はい、これで完成。次回はフロントの実装に写って行きます！！！
【JavaScript】コメント

# 概要
JavaScriptを学習、理解を深めるため「[JavaScript Primer 迷わないための入門書](https://jsprimer.net/)」を読み、
理解した内容等を記載していく。

「[【JavaScript】JavaScript入門一覧](https://qiita.com/andota05/items/22fae452225b785fd405)」に他の記事をまとめています。

# この記事で理解できること
* JavaScriptにおけるコメントの種類
* JavaScriptにおけるコメントの書き方

# コメントとは
* プログラムの`補足・説明`を行うもの。
* (動作確認や諸事情により)一時的にプログラムを無効化するためにコメント化(`コメントアウト`)することもある。
* JavaScriptでは「`一行コメント`」「`複数行コメント`」の方法がある。<br>※他、HTML-likeコメントという方法も存在するが割愛

## 一行コメント
* 一行ずつコメントを書く方法。
* 「`/`(バックスラッシュ)」を2つ続けて記載した後にコメントの内容を記載する。
* `コードエディタ`(VSCodeなど)では、`ショートカット`が用意されていることが多い。<br>※VSCode(Mac)だと`command + /`

```js
// console.log('こちらは出力されない');
console.log('こちらは開発者コンソールに出力される');
```

## 複数行コメント
* 長い説明など複数行コメントを書く方法。
* 「`/*`」と「`*/`」内の記載がコメント対象。
* 複数行コメントの中に複数行コメントは書けない。
* こちらもコードエディタにショートカットが用意されていることが多い。<br>※VSCode(Mac)だと複数行選択した状態で`Shift + Option + A`

```js
// これが一行コメント

/* 複数行コメントここから
ここも複数行コメント
ここも複数行コメント
複数行コメントここまで */

console.log('こちらは開発者コンソールに出力される');
```
```
/*
/* 複数行コメントの中に、複数行コメントを書くと(ネストすると) */
*/ => 構文エラーになる
```
【JavaScript】ラッパーオブジェクト

# 概要
JavaScriptを学習、理解を深めるため「[JavaScript Primer 迷わないための入門書](https://jsprimer.net/)」を読み、
理解した内容等を記載していく。

「[【JavaScript】JavaScript入門一覧](https://qiita.com/andota05/items/22fae452225b785fd405)」に他の記事をまとめています。

# この記事で理解できること
* ラッパーオブジェクトとは
* ラッパーオブジェクトの挙動

# ラッパーオブジェクト
* `null`、`undefined`を除くプリミティブ型のデータには、対となる`ラッパーオブジェクト`が存在する。
* JavaScriptでは、プリミティブ型の値の`プロパティへアクセス`する際、自動で対となる`ラッパーオブジェクトに変換されている。`
* 結果的に、プリミティブ型のデータでも、各Objectが持つプロパティにアクセスができる。

|ラッパーオブジェクト|プリミティブ型|例|
|------|------|------|
|Boolean|真偽値|true、false|
|Number|数値|1、3.14|
|String|文字列|"Hello"|
|Symbol|シンボル|Symbol("シンボル")|

```js
// プリミティブ型のデータ(文字列)を宣言
const str = "string";

// あれ？ただの文字列なのにtoUpperCaseメソッドが使用できる。なぜ？
// => 対象のメソッドを持つStringラッパーオブジェクトに変換されているから
console.log(str.toUpperCase()); // => STRING
```
```js
// 以下と同じこと
const str = new String("string");
console.log(str.toUpperCase()); // => STRING
```

# プリミティブ型のデータはリテラルの使用が推奨される理由
主な理由として、以下が挙げられる。
* プリミティブ型のデータは、自動的に対となる`ラッパーオブジェクト`に変換されるため。
* `new ラッパーオブジェクト(データ)`のようにラッパーオブジェクトのインスタンスを扱う利点がないため。
* ラッパーオブジェクトを`typeof演算子`で評価した結果が、プリミティブ型ではなく`"object"`となり混乱を生むため。

```js
const str = "文字列";
console.log(typeof str); // => string
```
```js
const str = new String("文字列");
console.log(typeof str); // => object
```