OmniAICreator/Qiita-1.07M huggingface dataset:
C#  WebRequest  WebException: The remote server returned an error: (500) Internal Server Error

# 問題
下記のHttpWebRequestは必要なheaderを設定しましたが、どうしても500エラーを返してきます。
APIのテストは、postmanで試してみました、headerとbodyの設定は問題ないです。
何時間を調査すると、https://www.orcode.com/question/943479_k955ab.htmlで解決方法を見つけました。
# 解決方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/a6b4c033-31f1-cf0d-6341-4622cb11fd17.png)
WebClientは、実際に、user-agentなど選択可能のheaderをデフォルトに設定してくれないです。
APIのリクエストはuser-agentなどのheaderが必要がある場合、設定しないと、サーバーは500エラーが帰ってきます。
今回は、httpRequest.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");を追加することで、問題を解決しました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/f1d66f89-07b0-19f8-432b-3feb151e8a13.png)



# 問題あるソース

               var url = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";

                var httpRequest = (HttpWebRequest)WebRequest.Create(url);
                httpRequest.Method = "POST";

                httpRequest.ContentType = "text/xml; charset=utf-8;";
                httpRequest.Headers["SOAPAction"] = "http://WebXml.com.cn/getWeatherbyCityName";

                var data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><getWeatherbyCityName xmlns=\"http://WebXml.com.cn/\"><theCityName>北京</theCityName></getWeatherbyCityName></soap:Body></soap:Envelope>";

                using (var streamWriter = new StreamWriter(httpRequest.GetRequestStream()))
                {
                    streamWriter.Write(data);
                }

                
                var httpResponse = (HttpWebResponse)httpRequest.GetResponse();

                using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                {
                    var result = streamReader.ReadToEnd();

                    logger.Info(result);
                }

                Console.WriteLine(httpResponse.StatusCode);

# 参考サイト
https://www.orcode.com/question/943479_k955ab.html
https://msdn.microsoft.com/en-us/library/system.net.webclient(v=vs.110).aspx
Catalytic exhaust-gas treatment, ボッシュ自動車handbook 11版(65) p.874

Management for spark-ignition engines, Catalytic exhaust-gas treatment, ボッシュ自動車handbook 11版(65)

人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊
http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0)＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/dfa35aa6f669e5df983e
# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800

# Catalytic exhaust-gas treatment(触媒排ガス処理装置)
p.874
## Catalytic converter
## λ-control
## Particulate filter for gasoline engine

# Reference
参考なし。　

# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221026

### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
Ignition , ボッシュ自動車handbook 11版(64) p.854

Management for spark-ignition engines, Ignition, ボッシュ自動車handbook 11版(61)

人生で影響を受けた本100冊。

https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊

http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0)＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/dfa35aa6f669e5df983e
# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800

# Ignition(点火)
p.854
## Basic principles 
## Moment of ignition 
## Ignition systems 
## Ignition coil
## Spark plug 
# Reference
[1] www.bosch-zuendkerze.de
Bosch Automotive Aftermarket,  What drives you, drives us

このURLは、Fig 4 Designation codeの参照らしい。
サイト内検索しても見つからない。なにしてくれちゃうの。


# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

物理記事　上位100
https://qiita.com/kaizen_nagoya/items/66e90fe31fbe3facc6ff

数学関連記事１００
https://qiita.com/kaizen_nagoya/items/d8dadb49a6397e854c6d

言語・文学記事　１００
https://qiita.com/kaizen_nagoya/items/42d58d5ef7fb53c407d6

医工連携関連記事一覧
https://qiita.com/kaizen_nagoya/items/6ab51c12ba51bc260a82

通信記事１００
https://qiita.com/kaizen_nagoya/items/1d67de5e1cd207b05ef7

自動車　記事　１００
https://qiita.com/kaizen_nagoya/items/f7f0b9ab36569ad409c5

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221026
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
Mixture formation, ボッシュ自動車handbook 11版(63) p.838

Management for spark-ignition engines, Mixture formation, ボッシュ自動車handbook 11版(61)

人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊
http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>
# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022
https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0)＜エンジニア夏休み企画>【読書感想文】
https://qiita.com/kaizen_nagoya/items/dfa35aa6f669e5df983e
# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800

# Mixture formation(混合気形成)
p.838
## Basic principles 654
## Mixture-formation systems
## Intake-manifold injection
## Gasoline direct injection
## Fuel injectors
# Reference
参考なし。　

# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
# 文書履歴(document history)
ver. 0.01 初稿 　20221026
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
【Mac】スリープ解除のスケジュールをコマンドで設定する方法

## 設定方法

`pmset`コマンドを使用してスリープ解除のスケジュールを設定します。  

### 繰り返し

繰り返すスケジュールを設定するには以下のように実行します。

```zsh
sudo pmset repeat 動作 曜日 時間
```

「動作」には以下を設定できます。

* sleep  
  スリープする。
* shutdown  
  シャットダウンする。
* wake  
  スリープを解除する。
* wakeorpoweron  
  スリープ解除または電源を入れる。
* poweron  
  電源を入れる。

「曜日」は以下の中から実行するものを選択します。  
上から月〜日です。

* M
* T
* W
* R
* F
* S
* U

毎日午前3時にスリープを解除するスケジュールを設定するには以下のように実行します。  

```zsh
$ sudo pmset repeat wake MTWRFSU 3:00:00

$ pmset -g sched
Repeating power events:
  wake at 3:00AM every day
```

`pmset -g sched`で現在設定されているスケジュールを確認できます。  

また繰り返しのスケジュールを削除するには以下のように実行します。

```zsh
sudo pmset repeat cancel
```

### 単発

繰り返さない単発のスケジュールを設定するには以下のように実行します。  

```zsh
sudo pmset schedule 動作 "日付 時間"
```

2022年11月1日午前10時にシャットダウンするには以下のように実行します。

```zsh
$ sudo pmset schedule shutdown "01/11/22 10:00:00"

$ pmset -g sched
Repeating power events:
  wake at 3:00AM every day
Scheduled power events:
 [0]  shutdown at 01/11/2022 10:00:00 by 'pmset'
```

また単発のスケジュールを削除するには以下のように実行します。

```zsh
sudo pmset schedule cancel 0
```

上記の`0`の箇所には`pmset -g sched`を実行した際にスケジュールの先頭に表示される番号を記述します。  
## コマンドでスリープする方法

以下のコマンドを実行するとすぐにスリープできます。

* スリープ

```zsh
pmset sleepnow
```

* ディスプレイオフ

```zsh
pmset displaysleepnow
```
ペアプロはよいものですね

### きっかけ
ペアプロはいいぞと聞いていたものの、何となく重い腰をあげられずにいたのですが、ぴゃっとやってみてさくっと記事にでもしたらどうかと声が聞こえたのでやってみました。「今日どっかでペアプロお願いしていいっすか？」とお願いして快諾してくれたバディ役の同僚に感謝です。

### ペアプロの環境
私が働いている会社はフルリモートが基本になっていて、私もペアプロのバディもその日リモートだったので画面共有しながらweb通話で実施しました。また、私はVSCodeでバディはVimなのでLive Shareも使用しませんでした。Live Shareとは、共同編集ができるVSCodeの機能です。これもいつか使ってみたいです。

### どんな感じだったか
まずはテーマというか、どんな機能を実装しようとしているかの軽い認識合わせをします。軽くメモ書きをしてあったので、それを画面共有しつつ口頭で説明します。

ペアプロなるものをまずはやってみようというノリだったので、この辺もゆるい感じで行きました。結論としては、このゆるさのせいでつまづいたりもなかったのでまずはやってみようのノリで正解だったなと感じています。

まずは私の画面を共有して「まずはこの辺りっすかね〜」とか相談しながらコードを書いていきます。こうしようかなと思ってるとか、あれ〜？これどうすりゃいいんだっけとかを呟き、適宜こうじゃね？あぁじゃね？をバディに言ってもらう感じで進みました。実施したのは2時間だったのですが、だいたい半分経過くらいでドライバー(コードを書く人)を交代しました。

考えてることを呟くのは大事ですね。これがないとナビゲーター側が状況を把握できなくなっていくので、こうじゃねあぁじゃね合戦が出来なくなっていきます。

### よかったこと

- 方向性について議論しながらとっかかりの実装までやってしまえるので、後で外してたことが発覚→手戻りが発生しない
- エラー出た時の解決が早い。こうじゃね？の意見が一人の時より多く出る
- 関数などの命名をその場で相談できる
- バディの進め方を見て「あぁその順番でやるんだぁ」などが学びになる
- プルリク等でレビューするときに、読み始めでぱっと頭に入ってきやすい
- あ、ここで悩むのは自分だけじゃないんだと安心できる

こんな感じで、結構いいことあるなという印象です。知恵を出し合ったり知見を共有し合う機会を増やすという観点でも有用で、チーム全体としてのスループットを高めていくことに役立つなと感じました。

今回はあんまり無かったのですが、ショートカットキーとかツールの便利テクニックとか有用なんだけどあんまり伝承するタイミングがなかったりすることも共有できそうです。

### 悪かったこと

- (短期的には)時間がとられる

ただ、「よかったこと」にも書いている通りレビューする時の時間が短縮されたり手戻り発生の頻度が抑えられるので、開発スピードも落ちてないんじゃないかと感じました。1週間くらいのタイムスパンで見るともう回収できるレベルじゃないかと思います。

今回は発生しませんでしたが、気をつけた方がいいかもな〜と思ったこととしては

- ナビゲーター(あぁだこうだ言う人)の指摘の仕方が手厳しいと、ピリピリムードになってつらいかも

っていうのはあるかもなあと思いました。

やってみてペアプロのメリットをかなり感じたので、精神的に障壁となることは減らしていければよいなと思った所存です。
Fuel supply, ボッシュ自動車handbook 11版(62) p.820

Management for spark-ignition engines, Fuel supply, ボッシュ自動車handbook 11版(62)

人生で影響を受けた本100冊。
https://qiita.com/kaizen_nagoya/items/16af53acbb147a94172e

に掲載した本のうち、「新人プログラマ応援」企画で「私の推薦書３３冊」として３３冊紹介した。

新人プログラマ応援　私の推薦書３３冊
http://qiita.com/kaizen_nagoya/items/98c62f051dbdb4f8aca2
残りの６７冊から、順に過去の読書感想を引用し、新たな読書感想文を追記する。

 <この項は書きかけです。順次追記します。>


# ボッシュ自動車ハンドブック version 11, 2022

Automotive Handbook  May 2, 2022

https://www.amazon.co.jp/dp/1119911907/

ボッシュ自動車handbook(英語)11版(0)＜エンジニア夏休み企画>【読書感想文】

https://qiita.com/kaizen_nagoya/items/dfa35aa6f669e5df983e
# Contents
Motor vehicle, 28
Basic principles, 32
Mathematics and methods, 204
Materials, 258
Machine parts, 354
Joining and bonding techniques, 426
Vehicle physics, 462
Operating fluids, 538
Refrigerants for air-conditioning systems, 591
Drivetrain(駆動系), 594
Internal-combustion engines(内燃機関),642
Management for spark-ignition engines,800

# Fuel supply(燃料供給)
p.820
## CFuel supply and delivery with intake-manifold injection 
## Fuel supply and delivery with gasoline direct injection 
## Evaporative-emissions control system 
## Gasoline filter 
## Electric fuel pump 
## High-pressure pumps for gasoline direct injection 
## Fuel rail 
## Fuel-pressure regulator 
## Fuel-pressure attenuator
# Reference
参考なし。　

# 自己参考資料(self reference)

ボッシュ自動車ハンドブック 

https://qiita.com/kaizen_nagoya/items/8e330ce57880f04d71d9
ボッシュ自動車handbook(英語)10版　目次

https://qiita.com/kaizen_nagoya/items/57c799ff544c96efdea9

自動車工学とBosch Vehicle Handbook

https://qiita.com/kaizen_nagoya/items/d13ff6b0e4d7c8907c0d

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221026

### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
CloudBuildとTerraformでProject毎生成するデプロイ試験

# CloudBuildのおさらい

## cloudbuild sampleコマンド
初期に提示された以下のサンプルコマンドをcloudshell経由で行ってエラーなしにデプロイできます。

```
リポジトリGoogleCloudBuild/cloud-console-sample-buildをDLしてディレクトリ内yamlを元にcloudbuildデプロイ
git clone https://github.com/GoogleCloudBuild/cloud-console-sample-build && \
>   cd cloud-console-sample-build && \
>   gcloud builds submit --config cloudbuild.yaml --region=global

```


## cloudbuildリポジトリ中ソースはどうなっている？

Dockerfile

```
FROM alpine
COPY helloworld.sh /
CMD ["/helloworld.sh"]
```

helloworld.sh

```
echo "Hello, world! The time is $(date)."
```

cloudbuild.yaml

```
steps:
- name: 'docker'
  args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/helloworld-image', '.' ]

# Registry.
images:
- 'gcr.io/$PROJECT_ID/helloworld-image'

# You can organize your builds with tags
tags: ['gcp-cloud-build-sample-build']

```


## ビルド履歴

```
# バケット「gs://build0139_cloudbuild」が生成されてるのが解ります。

FETCHSOURCE
Fetching storage object: gs://build0139_cloudbuild/source/1666782905.609219-3c992ed548d041a4a4e75a5bce434391.tgz#1666782907604826
Copying gs://build0139_cloudbuild/source/1666782905.609219-3c992ed548d041a4a4e75a5bce434391.tgz#1666782907604826...
/ [0 files][    0.0 B/  5.4 KiB]                                                
/ [1 files][  5.4 KiB/  5.4 KiB]                                                
Operation completed over 1 objects/5.4 KiB.                                      
BUILD
Pulling image: docker
Using default tag: latest
latest: Pulling from library/docker
213ec9aee27d: Already exists
539e1dfa3993: Pulling fs layer
539e1dfa3993: Waiting539e1dfa3993: Pull complete
Digest: sha256:b44077b08bb253acfe1c7d2a98040147732389ef17a35468ee3df8d55b615bb9
Status: Downloaded newer image for docker:latest
docker.io/library/docker:latest
Sending build context to Docker daemon   21.5kB


# コンテナ内の処理を記述します。

Step 1/3 : FROM alpine
latest: Pulling from library/alpine
Digest: sha256:bc41182d7ef5ffc53a40b044e725193bc10142a1243f395ee852a8d9730fc2ad
Status: Downloaded newer image for alpine:latest
 ---> 9c6f07244728
Step 2/3 : COPY helloworld.sh /
 ---> af43835f87d2
Step 3/3 : CMD ["/helloworld.sh"]
 ---> Running in 46524d4a76f2
Removing intermediate container 46524d4a76f2
 ---> 062f5e7c4bad
Successfully built 062f5e7c4bad
Successfully tagged gcr.io/build0139/helloworld-image:latest
PUSH
Pushing gcr.io/build0139/helloworld-image
The push refers to repository [gcr.io/build0139/helloworld-image]
d0fc15c7a882: Preparing
994393dc58e7: Preparing
994393dc58e7: Layer already exists
d0fc15c7a882: Pushed
latest: digest: sha256:31b08a6f5a8c4ca2ae9e7852442a6f1def5c1f32f97eedf4fa940dfebebbb1a7 size: 735
DONE

```


--------------------------
# CloudBuild

## cloudbuildコマンド
Meta Quest ProでVRモード/複合現実モードを切り替える方法


こんにちは、XRエンジニアのイワケンです。

10月26日ついに[Meta Quest Pro](https://www.meta.com/jp/quest/quest-pro/)が届きました！ 


Meta Quest Proの注目ポイントの1つは、ズバリ「フカラービデオパススルー機能による複合現実(MR)機能」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96970/ecc6c590-659f-b2f6-bf46-fefdb23f3e97.png)

周りの状態が見えている状態で、バーチャルコンテンツを楽しむことができます。

チュートリアルをこなしていくと「複合現実モードにしますか？」と問われるポイントがあり、そこでMR機能を堪能することができます。

しかし、触っていくと

- そこからどうやってVRモードに戻ればいい？
- VRモードと複合現実モードをどう切り替えればいい？

という疑問にぶちあたりました。
この記事ではその解決策を延べます。

# クイック設定->周囲確認ホームで解決

結論

- クイック設定->周囲確認ホームをクリック

で解決します。

その様子を動画にしましたので、確認してください！

<iframe width="560" height="315" src="https://www.youtube.com/embed/jgUe1KBztNA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

クイック設定がわかりにくいのと、周囲確認ホームという名前から連想できるか...というところが最初はわかりにくいかもしれません。

# 終わりに

本記事では、Meta Quest ProのVRモードと複合現実モードの切り替え方について書きました。今後Unityでの開発の知見など記事していきたいと思います。よろしくおねがいします。

# 追記

こちら、Quest2と同じ設定だそうです！

https://twitter.com/wakufactory/status/1585242271477555201?s=20&t=m4G7uCsGz3KzxK9nmYkTBA
セルフホストGitLabインスタンスでWebAuthnの登録に失敗するときの対処法

## 症状
 - yubikeyなどセキュリティキーを設定しようとすると`WebAuthn::OriginVerificationError`になる
 - GitLabはリバースプロキシの後ろにある

## 原因
リバースプロキシ関係の設定が正しくない

## 対処法
`/etc/gitlab/gitlab.rb` の以下の行を以下のように書き換える

```
# example.comはGitLabインスタンスのURLに読み替える。httpではなくhttpsなので注意
external_url 'https://example.com'

nginx['listen_https'] = false
nginx['listen_port'] = 80
```
ニフクラ mobile backendを拡張するNCMBプロキシを開発中です（デモ紹介）

ニフクラ mobile backendでは認証やデータストア（クラウドデータベース）、ファイルストア（ファイルストレージ）、プッシュ通知など様々な機能があります。そして、サーバーレスで拡張できるスクリプト機能もあります。

しかし、実際のアプリ要件は多彩で、場合によっては他にも様々な機能が望まれます。すべての需要を満たすのは困難な場合もあります。そこで、NCMBのフロントとして動作するプロキシソフトウェアを開発中です。

このプロキシを使うことによって、小さなニーズはプロキシ側で実装できるようになります。今回はプロキシを使ったデモアプリを紹介します。

## 追加する機能（予定）

現状は透過的なプロキシ + リアルタイム通知くらいしかありませんが、以下のような機能を実装する予定です。

- 認証をJSON Web Tokenに
- GitHub認証
- ソーシャル認証（標準ではサーバー認証が必要ですが、プロキシだけで認証できるように）
- Webhooks
- 署名なしでデータストア操作
- 全リクエストログ記録

他にもデータストアの集計機能、GraphQL機能なども追加できると便利そうです。なお、Webhooksなどの機能はプロキシ経由でしか実現できませんので注意してください（管理画面で操作しても実行されません）。

## インストール

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)のリポジトリをクローンします。

```
git clone git@github.com:NCMBMania/ncmb-proxy.git
```

ライブラリをインストールします。

```
npm i
```

## 設定の編集

`setting.example.yml` をコピーして `setting.yml` を作成します。そして、ファイル内にあるアプリケーションキー、クライアントキーをそれぞれお持ちのものに書き換えてください。

```yaml
applicationKey: YOUR_APPLICATION_KEY
clientKey: YOUR_CLIENT_KEY
```

## サーバーを起動

サーバーを起動する際には、以下のコマンドを実行します（まだ開発中なので、開発用サーバーが立ち上がります）。

```
npm run dev
```

例えばローカルの場合、 `http://localhost:3000` にてサーバーが立ち上がります。

## デモ

デモサーバーを https://ncmb.moongift.dev で立ち上げてあります。これを実際に使っているデモを[こちらに立ち上げています](https://jsfiddle.net/moongift/dLw5u7em/15/)。

![0314 jsfiddle.net - 1026201726.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/cde9e34f-c217-171c-1483-18d011317394.jpeg)


このデモアプリでは以下のような機能を確認できます。

### ドメインを変更した動作

NCMBの初期化を以下のように変更しています。これで接続先のサーバーを変更できます。また、アプリケーションキーとクライアントキーはサーバー側にありますので、完全に隠蔽できます。

```js
const fqdn = "ncmb.moongift.dev";
const ncmb = new NCMB("dummy", "dummy", {
	fqdn,
	scriptFqdn: fqdn,
});
```

### リアルタイム通知

WebSocketを使った通知も利用できます。URLは同じです。

```js
const socket = new WebSocket(`wss://${fqdn}?classname=Test&action=create`);
socket.addEventListener('open', e => {
	log(`WebSocketに接続しました`);
});
```

パラメータの指定は[ニフクラ mobile backendを拡張するNCMBプロキシを開発中です（リアルタイム通信） - Qiita](https://qiita.com/goofmint/items/ea06f48ef9e05f30a8fa)を参照してください。

今回はアクションをcreateとしていますので、データを作成した際にイベント通知されます。

```js
socket.addEventListener('message', e => {
	log(e.data);
});
```

送られてくるデータは以下のような文字列です。

```json
{
	"action":"create",
	"objectId":"PWLaZ1SfI5KYRBA6",
	"createDate":"2022-10-26T11:23:41.199Z"
}
```

## まとめ

プロキシサーバーを使うことで、キーを隠蔽できたり、リアルタイム通信などの追加機能が利用できます。NCMBをより便利に使いこなすために、ぜひご利用ください。

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)
MMDをwindows11にインストールして動かした

## 環境
Windows11home64bit版

## MMDとは
MikuMikuDance（ミクミクダンス）は、樋口優が制作した、プリセットされたキャラクターの3Dモデルを操作しコンピュータアニメーションを作成する3DCGソフトウェアである。略称はMMD。デフォルトで初音ミクなどVOCALOIDキャラクターの3Dモデルを使用できるほか、オリジナルのキャラクターモデルやアクセサリを組み込んで操作することも可能で、MMD用の3Dモデルも有志によって多数公開されている。
出典:[MikuMikuDance](https://ja.wikipedia.org/wiki/MikuMikuDance)
3Dソフトなのにとても軽いです！低スペPCでも動くのが魅力。
## MMDをインストール
MMD公式サイト(以下リンク)から
[Vocaloid Promotion Video Project](https://sites.google.com/view/vpvp/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/7b1a59d2-d80f-59ff-c17d-c262896c10e7.png)


## MMDをwindows11で作動させようとしたらエラー
調べると「d3dx9_43.dll」がないことが原因らしい。
d3dx9_43.dllはMicrosoftのDirectXに含まれるDirect3Dのバージョン9の拡張ライブラリです。
windows10には標準に入っているのだが、windows11には入っていない。古いゲームなどはd3dx9_43.dllに依存するものも多く困る。



## 解決策
「d3dx9_43.dll」をコピーしてWindows\System32にペースト
参考:[d3dx9_43.dllが見つからないエラーが出る時の対処法 – Windows10](https://itojisan.xyz/trouble/21708/)
1
MMD公式ページから
![スクリーンショット 2022-10-21 18.42.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/e66a84a0-3aaa-2839-d076-52ac90569cb7.png)
2
DirectXユーザーランタイムから
directx_Jun2010_redist.exeをダウンロード
参考:[サポートFAQ（良くある質問） | DirectX エンドユーザーランタイムを手動でインストールする方法](https://faq.tsukumo.co.jp/index.php?solution_id=1321)
3
ダウンロードファイルの中からd3dx9_43.dllを見つけましょう。
d3dx9_43.dllをsystem32フォルダ内にコピペすれば成功です。
しかし、system32はファイルから編集できないようになっているので、コマンドプロントを管理者実行します。
4
コマンドプロントを管理者として実行
```C:\WINDOWS\system32>move d3dx9_43.dll C:\Windows\System32```
5
system32フォルダ内にd3dx9_43.dllが追加されていれば、MMDを起動してください。MMDが起動すれば成功です。
HTMLMediaElementの即時再生可能になるまで待つ時の注意点

# 概要
メディア再生が可能になるまで待って、即時再生をする場合に注意することの備忘録です。

# 注意点
メディア再生が可能になるまで待つ処理を書くときに[HTMLMediaElementの`canplay`イベント](https://developer.mozilla.org/ja/docs/Web/API/HTMLMediaElement/canplay_event)がPromiseの実行より前に発火している場合があるので、[readyState プロパティ](https://developer.mozilla.org/ja/docs/Web/API/HTMLMediaElement/readyState)の状態も見てあげないと実行タイミングによってはresolve() できない。
つまり、サンプルコードのように`readyState`プロパティによる`resolve`をしない場合、
```typescript
if (videoElement.readyState >= 3) resolve()
```
実行タイミングによってはPromiseの値が返却されない可能性があります。

# サンプルコード
```typescript
const onCanPlayVideoPromise = (videoElement: HTMLVideoElement) => {
      return new Promise<void>((resolve) => {
        if (videoElement.readyState >= 3) resolve() // readyStateプロパティが0,1,2の場合は即時再生不可
        else {
          videoElement.oncanplay = () => {
            resolve()
          }
        }
      })
    }
await onCanPlayVideoPromise(this.videoElement)
```
for文if文での条件一致検索からforEach()を経てfind()にたどり着くまで

## この記事の経緯

自分でJavaScriptを書いていて、理解を深める、それをアウトプットして伝えよう！ということで記事にしてみました。
このコードはGASを書いていて使っているコードなので、正確にいうと、JavaScriptではないんですが、大体一緒なんでご勘弁を。
下記で書いている３パターンの記述は全て最終的な戻り値は同じものになっております。
結果は一緒だけども、記述の違いを見比べていただいてJavaScriptの理解を深めていただければと思います。

---
前提：関数の第1引数のpostTextの中に投稿者の情報が含まれています。その投稿者が誰なのかを調べるための関数です。調べるための要素としてgithubアカウントを用いています。そのgithubアカウントが含まれているかどうかで投稿者が誰なのかを調べるための関数となっています。

---
### パターン1: for文とif文の組み合わせ

```javascript: for文とifの組み合わせ
  // postText:string 検索したい文字列が含まれているのかを探す対象
  // membersArr:array 受講生の情報一覧となるオブジェクトが入っている
  // 配列に入っているオブジェクトの情報
  // {
  //   no: int,
  //   username: string,
  //   userid: string,
  //   githubAccount: string
  // }

function searchPostMember(postText, membersArr){

  let returnMemberObj = {};

  for(let i = 0; i < membersArr.length; i++){

    // indexOfを用いて探したいテキストが含まれているのかを判別しています
    if((postText.indexOf(membersArr[i]["githubAccount"]) > -1) &&
       (membersArr[i]["githubAccount"] !== "")){
      returnMemberObj = membersArr[i];
    }

  }

  return returnMemberObj;
}
```

最初はね、for文とif文を組み合わせてやるのがいいと思います。わかりやすいですし。
そこからもう少し踏み込んだ書き方をするとforEachになるのかなと思います。
forEachは配列の際に使用できるメソッドとなっております。
for文は元の要素に関わらず使えるものですが、ここからは各要素に準ずるメソッドになってきます。

---
### パターン２: forEachメソッドとif文

```javascript: forEachメソッド
function searchPostMember(postText, membersArr){

  let returnMemberObj = {};

  membersArr.forEach( member => {
    if((postText.includes(member.githubAccount)) &&
       (member.githubAccount !== "")){

      returnMemberObj = member;
    }
  })

  return returnMemberObj;
}
```

forEachの記述だと、配列内のものを全文回っていった上で、まだif文を使わないといけないのでこれもなんとかしたいですよね。
そこで使うのがfindメソッドとなります。

---
### パターン3: findメソッド

```javascript: findメソッド
function searchPostMember(postText, membersArr){

  return membersArr.find( member =>
    (postText.indexOf(member.githubAccount) > -1)) &&
    (member.githubAccount !== "")
  )

}
```
※ちなみになんですが、findの前はsomeメソッドなんかで出来ないかなーとか思って調べていたんですが、someは戻り値がtrue/falseしかないようなので諦めたというかfindにしました。

---
#### 後書き

findだととてもコンパクトにかけますね。ただ、コンパクトすぎて何やってるのか初見だとわかんないと思います。
これは、「コールバック関数」というものを理解できたときに理解ができると思います。
正直、自分はこんなの何書いてるのか最近までちゃんとわかってませんでした。
最近の皆さんは理解力半端ないのですぐわかるかと思いますが、分かんなくても書き続けているととある瞬間から「そういうことか！！！」と気づくと思います。
とにかく書き続けることです！


 [forEachメソッド参考文献](https://camp.trainocate.co.jp/magazine/javascript-foreach/) 
[findメソッド参考文献](https://tech-lab.sios.jp/archives/27968)
ONLYOFFICE Docs Presentation Editorに新しいテーマを追加する方法

ONLYOFFICE Docs Presentation Editorにテーマを追加して、エディタでの作業を強化したいと思うことがあるかもしれません。それは非常に簡単に行うことができます。

::: note warn
現在、以下のテーマ形式がサポートされています：pptx, potx, pptm, potm
:::

## 基本的な説明

ONLYOFFICE Docsでは、デフォルトでプリインストールされたテーマが使用されます。もし、追加のテーマを使用したい場合は、以下のようにします。

1. テーマを `/var/www/onlyoffice/documentserver/sdkjs/slide/themes/src` にコピーしてインストールします（ONLYOFFICE Docs をインストールしているコンピュータへ）。
2. `usr/bin`フォルダを開きます。
3. `documentserver-generate-allfonts.sh` ファイルを実行します。
4. ブラウザのキャッシュをクリアして、ページを開き直します。

ONLYOFFICE Docsを[今すぐダウンロード](https://www.onlyoffice.com/download-docs.aspx?from=qiita)
まともにプログラミングしたことがないQAエンジニアがjavaで電卓を作ってみた

## 初めに
* プログラミングの経験としては大学で基礎を少し学んだだけであり、社会人になってからは（恐らく）1度も触ったことがありませんでした。ただ、最近javaの勉強をする機会があり、そこで学んだ内容から電卓のようなものを作れ、せっかくなら共有してみればと言われましたのでQiitaの記事を作成しました。

## 実際に作成したコード
```
package projava;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
import java.util.Scanner;

public class test_0902 {
    public static void main(String[] args) throws IOException {

        //数字を入力できるようにする
        Scanner numbers = new Scanner(System.in);
        try {
            //数式を入力できるようにする
            BufferedReader formula = new BufferedReader(new InputStreamReader(System.in));

            //1文字目の入力
            var input1 = numbers.nextInt();
            for (; ; ) {
                //2文字目の入力
                var input2 = formula.readLine();
                //「=」が入力された際は終了する
                if (input2.equals("=")) {
                    System.out.println("計算の答えは%sです。".formatted(input1));
                    break;
                }
                //3文字目の入力
                var input3 = numbers.nextInt();

                //2文字目の式によって分岐
                if (input2.equals("+")) {
                    input1 = input1 + input3;
                    System.out.println(input1);
                    continue;
                } else if (input2.equals("-")) {
                    input1 = input1 - input3;
                    System.out.println(input1);
                    continue;
                } else if (input2.equals("*")) {
                    input1 = input1 * input3;
                    System.out.println(input1);
                    continue;
                } else if (input2.equals("/")) {
                    input1 = input1 / input3;
                    System.out.println(input1);
                    continue;
                } else {
                    System.out.println("2番目の入力は+、-、*、/ の何れかを入力してください。");
                    break;
                }
            }
            
            //1、3文字目に数字が入力されなかった際に出力されるメッセージ
        } catch (InputMismatchException s) {
            System.out.println("数字を入力してください。");
        }
    }
}
```
## 実際の動作
* 正常系
```
5
+
6
11
=
計算の答えは11です。

プロセスは終了コード 0 で終了しました
```
* 異常系1（1文字目に数字ではなく文字を入力）
```
a
数字を入力してください。

プロセスは終了コード 0 で終了しました
```
* 異常系2（2文字目の入力で数式以外を入力）
```
1
a
1
2番目の入力は+、-、*、/ の何れかを入力してください。

プロセスは終了コード 0 で終了しました
```

## 実装してみて
* 一応想定通りに動くものができたので良かったと思います。
* 異常値が入力された際のことも考慮できたので良かったです。
* 2番目に入力した文字が「+」、「-」、「*」、「/」、「=」以外の際にも3文字目の入力が求められてしまうので、改善したかったのですが、改善できませんでした。
* コメントアウトを入れることで逆にコードが見にくくなってしまった気がしましたので、コメントの書き方も工夫できるようにしたいです。


## 最後に
* ここの部分はこうした方がいい等ありましたらぜひ意見をいただきたいです。:bow:
MicroStrategyのスマートメトリック設定

## はじめに
ここではMicroStrategyの「スマートメトリック」という機能についてご紹介します。

MicroStrategy Developerを使用して
「達成率（実績÷目標）」というメトリックを新規作成したところ、
レポート上で「--」となり正しく表示されませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/20593f5b-569e-74db-d231-52573c48af26.png)

また、表示されたと思ったら「合計」の達成率が明らかにおかしくなることもありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/a2fc3db3-5909-6dfa-d388-202a6f361c0d.png)

これを解消するのが「スマートメトリック」になります。
（データは用意したダミーデータを使用しています）

## スマートメトリックとは
複合メトリック（ここでは達成率）の中の個々のメトリック（ここでは実績、目標）の小計を計算するかどうかを指定するものです。

詳しい説明の前に、
実際にスマートメトリックをONにした場合とOFFの場合の達成率を並べたものが以下になります。
（達成率の式自体は同じで、スマートメトリック設定のみを変更しています）
スマートメトリックをONした達成率は値がきちんと表示され、
合計行の達成率が先ほどと変わっていることが分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/20e19525-743c-103e-0591-c9a1887eb692.png)


次に、合計行の数値の差異についてご説明します。
スマートメトリックを設定することで計算の順序が変わります。

__スマートメトリックがOFFの場合__
レポートの各行において達成率（実績÷金額）を計算したうえでそれを合計します。
以下①から③を算出→①～③を合計して④を算出というイメージです。
したがって、この例での2017年4月の達成率は各カテゴリーの達成率を単純に足しあげた値になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/329d12c6-cc0e-7cc7-046e-9dcd7d7d47e2.png)

__スマートメトリックがONの場合__
先に各列の合計を算出したうえで、達成率（実績÷金額）を計算します。
まず①～②を算出→それらを除算という順番になります。
したがって、この例での2017年4月の達成率は2017年4月の実績合計÷2017年4月目標合計の値になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/727733f9-7cfc-5388-8273-7ff6f0d1d2fe.png)


このように計算の仕方が違うため異なる値が表示されます。

## スマートメトリックの設定方法
メトリック編集画面の「小計/集計」タブ左下にある
「スマートメトリックを許可」に「✓」を入れると設定が有効になります。
（✓の右横にある計算式例が前述の計算方法の違いを示しています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737357/52cdb5a9-9ef6-1308-5e2e-5460cf12b6a2.png)

## おわりに
今回はスマートメトリックについてご紹介いたしました。
設定自体は簡単なものですが、
スマートメトリックを設定するかどうかによって
意図と異なる数値が算出されてしまうケースがあるため、
複合メトリック作成の際にはご留意いただければと思います。
やはりStreamlitは素晴らしかった。REACTはもう要らない・・・泣

https://qiita.com/EasyCording/items/3643c482b29c87841207

前から検討を進めてきたテーマであるが、ついに全面的にReactから離脱する瞬間が来たようだ。

## 内容

そもそも、VIS.JSでネットワーク図を書いていて、すこしユーザービリティを追加しようとして、
REACTを覚えかけていた瞬間であるが、ずばりReactを覚える前に、Streamlitで同様の機能が
さらりと実装できてしまった。

## アプリについて

まずは実物を拝んでもらうことに尽きる。

movie https://fb.watch/goNSkif6Wi/

https://chanmoto-streamlit-app-admin-tutt63.streamlitapp.com/

## 追加仕様

今回追加した仕様は、参加者ごとのフィルタ機能である。

仕様の追加は何のことは無い。

・マルチセレクトでdataframeからユニークなラベルリストを抽出
・選択された名前で、dataframeにチョメチョメ処理を追加

たったのこれだけである。

```python.py
    person = st.sidebar.multiselect(
        'Select your favorite parson',
        df['person'].unique().tolist(),df['person'].unique().tolist())

    event = st.sidebar.multiselect(
        'Select your favorite parson',
        df['event'].unique().tolist(),df['event'].unique().tolist())

    nodes,edges = choice_graph(nodes,edges,person,event)
```

# 全体のリスト

agraphというのは、こっちのソースを使った。

https://github.com/ChrisDelClea/streamlit-agraph


```python.py

def choice_graph(nodes,edges,person,event ):

    nodes_choice = []   
    edges_choice = []

    #optionリストの対象人物のNODEとEDGEを抽出して削除する
    for person in person:
        nodes_choice.extend([i for i in nodes if i.id == person])
        edges_choice.extend([i for i in edges if i.source == person])

    nodes_buf = set([])
    for item in edges_choice:
        for i in nodes:
            if( i.id == item.to and i.id in event):
                nodes_buf.add(i)
                
    nodes_choice.extend([x for x in nodes_buf])

    return nodes_choice,edges_choice


data = dataload('data.json')

if st.session_state.login == True:

    reduce_header_height_style = """
        <style>
        div.block-container {padding-top:1rem;}
        </style>
        """
        
    st.markdown(reduce_header_height_style, unsafe_allow_html=True)
    
    nodes, edges=fetchCrossvalidData(data)
    df = pd.DataFrame.from_dict(data)
    st.sidebar.title("連関図")
    person = st.sidebar.multiselect(
        'Select your favorite parson',
        df['person'].unique().tolist(),df['person'].unique().tolist())

    event = st.sidebar.multiselect(
        'Select your favorite parson',
        df['event'].unique().tolist(),df['event'].unique().tolist())

    nodes,edges = choice_graph(nodes,edges,person,event)

    config = Config(
            width=2000,
            height=1000,
            directed=True,
            nodeHighlightBehavior=True,
            highlightColor="#F7A7A6", 
            collapsible=True,
            edges = {
                "smooth": True,
            }
            )

    return_value=agraph(nodes=nodes,
                            edges=edges,                       config=config)
```

# 結論

REACTコンポーネントに触れることなく、機能が実装できた。
ゆえにREACTは不要と判断した。
cert-managerの0系から1系、apiVersionをv1へのアップグレードでエラーになる場合の対処法

# はじめに

Let's EncryptでSSL証明書を更新するためにGKEでcert-managerを動かしています。
今回、apiVersionを`cert-manager.io/v1alpha2`から`cert-manager.io/v1`に変更したさいに、ハマったのでメモ。

# 手順書

公式のドキュメントでいくとこのあたりを見ておく。

https://cert-manager.io/docs/installation/upgrading/upgrading-0.16-1.0/#uninstall-cert-manager

https://cert-manager.io/docs/installation/upgrading/remove-deprecated-apis/

# エラー内容

でも、うまく動かなかった。cert-mangaerのpodででたエラーは下記の通り。

cert-manager

```
k8s.io/client-go@v0.23.4/tools/cache/reflector.go:167: Failed to watch *v1.Certificate: failed to list *v1.Certificate: request to convert CR from an invalid group/version: cert-manager.io/v1alpha2
```

cert-manager-webhook

```
http: TLS handshake error from xxx.xxx.xxx.xxx:xxxxx: EOF
```

# 原因

v1に更新したはずなのに、v1alpha2を見ているようだ。古いCRDが残っているみたいです。
CRDとは、Custom Resource Definitionsというk8sが提供する独自のリソース定義の機能です。
ビルトインのリソースであるPodsやConfigMapと同じものです。

# 解決方法

今回、無停止である必要がなかったので、いったん名前空間ごと削除して作り直しました。

1. 名前空間ごとcert-mangaerを削除
1. 古いCRDを削除
1. 新規でcert-mangaerを作成

## 手順2 「古いCRDを削除」の方法

本来であれば、手順1で`kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/{削除対象のバージョン}/cert-manager.yaml`でCRDも削除される想定でした。
しかし消えなかったので、古いバージョンのCRDを特定する必要があります。（よく分からなかったので、とりあえずcertmanager関連は全部消しました）

```
$ kubectl get crd | grep certmanager
$ kubectl get crd | grep cert-manager
```

表示されたCRDの名前は、`kubectl delete crd {CRDの名前}`でも削除できないため、削除パッチを当てます。
finalizersを空にすることで削除できます。

```
kubectl patch crd/{{CRDの名前}} -p '{"metadata":{"finalizers":[]}}' --type=merge

#（例）
kubectl patch crd/certificaterequests.cert-manager.io -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl patch crd/certificates.cert-manager.io -p '{"metadata":{"finalizers":[]}}' --type=merge
kubectl patch crd/clusterissuers.cert-manager.io -p '{"metadata":{"finalizers":[]}}' --type=merge
```

削除後、新規でcert-mangaerを作成すると、正常にcert-managerが動作します。

# おわりに

下記のissueを見て回ったけど、k8sの理解が浅くて解決方法が分からなかったですが、解決できてよかったです。

https://github.com/cert-manager/cert-manager/issues/4754

https://github.com/cert-manager/cert-manager/issues/4900
やらない理由を書いてやらない  - Good Concepts in Programming -

# 概要
プログラミングの良い概念を理解するとプログラマーレベルが上がると考えています。
良い概念は特定のプログラミング言語に縛られないので、様々なプログラミング言語で役に立ちます。
前回は[OAOO原則](https://qiita.com/masaki_nakada_ari/items/1b4e1ea9a758ef86a498)を紹介しました。
今回紹介する良い概念は「やらない理由を書いてやらない」です。

# プログラミングの3大要素
本編に入る前に、プログラミングの3大要素について復習しましょう。
プログラミングを構成する3つの基本要素は「順次処理」、「分岐処理」、「反復処理」です。
プログラミングの3大要素だけであなたのやりたいことは基本的に実現できます（良いプログラミングであるとは限らない）。

## 1.順次処理
順次処理は記述した順番に従って処理を進めていくことです。

```order.js
// Plan, Do, Check, Actionの順番で処理します
executePlan();
executeDo();
executeCheck();
executeAction();
```

## 2.分岐処理
分岐処理は指定した条件によって処理を枝分かれさせることです。
if文、swtich文がこれに該当します。

```if.js
if (a === b) {
    // 条件に当てはまる場合に実行する処理です
} else {
    // 条件に当てはまらない場合に実行する処理です
}
```

## 3.反復処理
反復処理はある条件を満たすまで（もしくは無限に）処理を繰り返すことです。
for文、while文がこれに該当します。

```loop.js
for (let i = 0; I < 10; i++) {
    // ここに繰り返したい処理を記述します
}

while (condition === true) {
    // 条件がtrueの場合、処理を繰り返します
}
```

# やらない理由を書いてやらないとは
前置きが長くなりましたが、「やらない理由を書いてやらない」を紹介します。
先ほど分岐処理の説明をしましたが、あなたは分岐処理をスマートに使えてますか？
当たり前のように使うのであまり意識して使っていないかもしれません。

## 1.やる理由を書いてやる
まずはよく記述しがちな分岐処理のサンプルコードを見てみましょう。

```do_something.js
function doSomething(a, b, c, d) {
    // やる条件を判定して処理を実行します
    if (a) {
        if (b && c) {
            // この関数内で実行したい処理を記述します
        } else if (b && d) {
            // この関数内で実行したい処理を記述します
        }
    }
}
```
やる条件を判定して処理を実行する、ごく自然なプログラミングです。
特に問題ないように見えますが、以下の問題点があります。
・if文がネストして読みにくい
・やる条件が追加になった場合、修正ミスが起こりがち
・関数内で実行したい処理を複数箇所に記述しなければならない

## 2.やらない理由を書いてやらない
ではどのように記述すれば良いのでしょうか？
ここで「やらない理由を書いてやらない」という概念（考え方）が役に立ちます。
サンプルコードを見てみましょう。

```not_do_something.js
function doSomething(a, b, c, d) {
    // やらない条件を判定して関数を終了します
    if (!a) {
        return;
    }

    if (!(b && c)) {
        return;
    }

    if (!(b && d)) {
        return;
    }

    // やらない条件を追加すれば変更にも柔軟に対応できます
    // この関数内で実行したい処理を記述します
}
```
修正前のコードに比べてif文のネストがなくなり、読みやすくなりました。
また関数内で実行したい処理が1か所だけになりました。
そして実行したい処理の前にやらない条件を追加するだけで変更に対応できます。
条件文を記述して終了（return）するのは少し不自然に感じるかもしれません。
しかしプログラミングが膨大で複雑になるほどこの概念は威力を発揮します。

# まとめ
今回はやらない理由を書いてやらないを紹介しました。
当たり前のように使用している分岐処理ですが、ちょっとした工夫で可読性、保守性が高くなります。
新しい知識や環境がなくてもできるので、ぜひ実践してほしいです。
やらない理由を書いてやらないを理解してプログラマーレベルが上がったと感じていただければ幸いです。

最後まで読んでいただきありがとうございます。
コンパネのPHPiniファイル設定の内容が反映されない？

# 前提

- 言語バージョン設定
  - PHP 7.4.30 (モジュールモード)
- プロジェクトディレクトリ
  - php.cgiでPHP8.*に変更済み

この設定においてタイトルの通り、コンパネのPHPiniファイル設定の内容が反映されない？


# 原因？
コンパネに以下の記載がある。

> PHP8以降のバージョンをご利用いただくことで、規定の設定に加えて記載の設定が反映されます。
> PHP8より前のバージョンをご利用の場合、規定の設定を無視して記載の設定のみ反映されますのでご注意ください。


# 解決策
同PHPiniファイル設定画面に以下の記載がある。

> WEB公開フォルダに php.ini を設置し、個別に php.ini の設定を変更できます。

プロジェクトディレクトリのwebroot直下に直接設置することで解決。

```ini:/{プロジェクトディレクトリ/{webroot}/php.ini
memory_limit = 1024M
post_max_size = 1024M
upload_max_filesize = 1024M
```
ニフクラ mobile backendを拡張するNCMBプロキシを開発中です（リアルタイム通信）

ニフクラ mobile backendでは認証やデータストア（クラウドデータベース）、ファイルストア（ファイルストレージ）、プッシュ通知など様々な機能があります。そして、サーバーレスで拡張できるスクリプト機能もあります。

しかし、実際のアプリ要件は多彩で、場合によっては他にも様々な機能が望まれます。すべての需要を満たすのは困難な場合もあります。そこで、NCMBのフロントとして動作するプロキシソフトウェアを開発中です。

このプロキシを使うことによって、小さなニーズはプロキシ側で実装できるようになります。今回紹介する機能はチャットなどで使えるであろうリアルタイム通信機能です。

## 追加する機能（予定）

現状は透過的なプロキシでしかありませんが、以下のような機能を実装する予定です。

- 認証をJSON Web Tokenに
- GitHub認証
- ソーシャル認証（標準ではサーバー認証が必要ですが、プロキシだけで認証できるように）
- Webhooks
- 署名なしでデータストア操作
- 全リクエストログ記録

他にもデータストアの集計機能、GraphQL機能なども追加できると便利そうです。なお、Webhooksなどの機能はプロキシ経由でしか実現できませんので注意してください（管理画面で操作しても実行されません）。

## インストール

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)のリポジトリをクローンします。

```
git clone git@github.com:NCMBMania/ncmb-proxy.git
```

ライブラリをインストールします。

```
npm i
```

## 設定の編集

`setting.example.yml` をコピーして `setting.yml` を作成します。そして、ファイル内にあるアプリケーションキー、クライアントキーをそれぞれお持ちのものに書き換えてください。

```yaml
applicationKey: YOUR_APPLICATION_KEY
clientKey: YOUR_CLIENT_KEY
```

## サーバーを起動

サーバーを起動する際には、以下のコマンドを実行します（まだ開発中なので、開発用サーバーが立ち上がります）。

```
npm run dev
```

例えばローカルの場合、 `http://localhost:3000` にてサーバーが立ち上がります。

## 使い方

今回はJavaScript SDKでの使い方です。実際に利用するアプリケーション側でJavaScript SDKを初期化する際に、以下のように指定します。以下の例で分かるように、認証やデータストアとスクリプトは同じプロキシサーバーで提供されます。

```js
const ncmb = new NCMB("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY", {
	fqdn: "localhost",
	scriptFqdn: "localhost",
	protocol: "http",
	port: 3000
});
```

この `fqdn` や `protocol` 、 `port` を実際に運用するサーバーのものに書き換えて利用できます。本番運用できるレベルになったら、 `protocol` や `port` は不要でしょう。恐らく以下のようになるはずです。

```js
const ncmb = new NCMB("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY", {
	fqdn: "example.com",
	scriptFqdn: "example.com",
});
```

これでJavaScript SDKは直接ニフクラ mobile backendにはリクエストせず、 `example.com` へリクエストするようになります。

## コードについて

上記以外のコードを編集する必要はありません。これまでのJavaScript SDKを使ったコードがそのまま実行できます。

## リアルタイム通信について

現在はデータストアに対するデータの新規作成、更新、削除に対して通知を受け取れるようになっています。仕様は以下のようになります。

- エンドポイントURL
	- wss://プロキシサーバーのURL/
- クエリーパラメータ
	- classname（必須）：購読するデータストアのクラス名です。
	- action : 購読するデータ操作を指定します。
		- create : データ作成
		- update : データ更新
		- delete : データ削除
	- objectid: 購読するデータのオブジェクトIDを指定します。このデータの更新、削除について通知を受け取れます。

actionかobjectidはどちらか必須です。両方指定した場合にはobjectidが優先されます。

例えば以下のように購読します。

```
wscat -c "ws://localhost:3000/?classname=Test&action=create,update"
```

### 新規作成

新規作成の際には以下のようなデータが送られてきます。

```json
{
	"createDate":"2022-10-25T06:46:26.342Z",
	"objectId":"bIJYu1y1kBrEthK6",
	"action": "create"
}
```

### 更新

更新の際のデータは以下のようになります。

```json
{
	"updateDate":"2022-10-26T08:14:28.580Z",
	"objectId":"bIJYu1y1kBrEthK6",
	"action":"update"
}
```

### 削除

削除の際の通知は以下になります。

```json
{
	"objectId":"bIJYu1y1kBrEthK6",
	"action":"delete"
}
```

## セキュリティ

通知の時点では、通知を受け取ったユーザーがデータの閲覧権限を持っているかを判断できません。そのため、オブジェクトIDだけを通知しています。実際のデータ内容について確認する際には、通知データに含まれるオブジェクトIDを使ってデータ取得を行ってください（権限がない場合にはエラーになりますので注意してください）。

## まとめ

ニフクラ mobile backendは便利なmBaaSですが、機能が足りなくて別サービスと組み合わせて使うこともあるでしょう。そうした場合に2つのサービスをクライアントから呼び出すのではなく、プロキシを使うことで1つのサービスであるかのように利用できます。

開発はまだまだこれからですが、ぜひご期待ください。

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)
「プロを目指す人のためのRuby入門」備忘録

# 概要
プロを目指す人のためのRuby入門を読み、知識を定着させたいと思い、アウトプットさせて頂きます。

## ブロックを使用したメソッドの書き方
記事などを読み、今までは一体何の処理をしているのかわからなかった記述も、この書籍でRubyの深い部分を学ぶことで、理解につながることが多々ありました。

```ruby:ruby
['ruby', 'java', 'python'].map { |s| s.upcase } #=> ["RUBY", "JAVA", "PYTHON"]
# 上記一文の書き換え
['ruby', 'java', 'python'].map(&:upcase)        #=> ["RUBY", "JAVA", "PYTHON"]

[1, 2, 3, 4, 5, 6].select { |n| n.odd? } #=> [1, 3, 5]
# 上記一文の書き換え
[1, 2, 3, 4, 5, 6].select(&:odd?)        #=> [1, 3, 5]
```
こちらでは、mapメソッドやselectメソッドにブロックを渡す代わりに、**&:メソッド名**という引数を渡すことができるということを学びました。
しかし、この書き方を使用するためには条件があり、

①ブロックパラメータが1個だけである。
②ブロックの中で呼び出すメソッドには引数がない
③ブロックの中では、ブロックパラメーターに対してメソッドを1回呼び出す以外の処理がない。

という3つの条件を満たす必要があるということでした。

こちらの書籍では、次のようなコードではこの変換は使用できないと記載されています。

```ruby:ruby
# ブロックの中でメソッドではなく演算子を使っている
[1, 2, 3, 4, 5, 6].select { |n| n % 3 == 0 }

# ブロック内のメソッドで引数を渡している
[9, 10, 11, 12].map { |n| n.to_s(16) }

# ブロックの中で複数の文を実行している
[1, 2, 3, 4].map do |n|
  m = n * 4
  m.to_s
end
```
慣れるまではブロックを使用した書き方を使用していこうと思いますが、今後リファクタリングなどを行う過程で、**&:メソッド名**という記法を使用して記述できるようにしたいと思います。

## timesメソッド
4章では、繰り返し処理も学びました。timesメソッドはpaizaなどの問題を解く上でよく出てきたので、ここでマスターしたいと思います。
```ruby:ruby
sum = 0
# 処理を5回繰り返す。nには0, 1, 2, 3, 4が入る
5.times { |n| sum += n }
sum #=> 10
```
5回処理を繰り返すという記述です。ここで重要だと感じたのは、**nには0〜4**の5つが入るということです。

また、ブロックパラメーターを使用しない書き方もあるようです。
```ruby:ruby
sum = 0
# sumに1を加算する処理を5回繰り返す
5.times { sum += 1 }
sum #=> 5
```
この場合だと、1を単純に5回足すという意味合いになるのですね。

## 繰り返し処理で使うbreakとreturnの違い
ここでは、breakとruturnの違いについて学びました。
breakは、「繰り返し処理からの脱出」、returnは「繰り返し処理のみならずメソッドからの脱出」ということを学びました。
実際に書籍のコードを見てみます。

```ruby:ruby
def calc_with_break
  numbers = [1, 2, 3, 4, 5, 6]
  target = nil
  numbers.shuffle.each do |n|
    target = n
    # breakで脱出する
    break if n.even?
  end
  target * 10
end
calc_with_break #=> 40
```
こちらのコードは、もしnが偶数であれば**繰り返し処理のみ**抜けてメソッド内の`target * 10`を行って返すというメソッドの記述です。
次に、こちらのコードです。
```ruby:ruby
def calc_with_return
  numbers = [1, 2, 3, 4, 5, 6]
  target = nil
  numbers.shuffle.each do |n|
    target = n
    # returnで脱出する？
    return if n.even?
  end
  target * 10
end
calc_with_return #=> nil
```
これは、returnが呼ばれた瞬間にメソッド全体を脱出してしまい、メソッドの戻り値がnilになってしまうということでした。

# まとめ
書籍を読んでいく中で、理解を深められるように今後も定期的にアウトプットをしていきたいと考えています。

# 参考
・伊藤 淳一. プロを目指す人のためのRuby入門[言語使用からデバック技法まで]　株式会社技術評論社
PandasからPolarsに乗り換えるときに対応した変更点

# 初めに

`Polars`というDataFrameライブラリが速くて話題になっているということで、`Pandas`の既存資産への変更点をまとめました。

# 準備
```console
pip install numpy pandas polars
```

```python
import polars as pl
import pandas as pd
import numpy as np
```

## pandas.DataFrame
```python
pddf = pd.DataFrame(
    {
        "a": np.arange(0, 5),
        "b": np.arange(10, 15),
        "c": np.arange(20, 25),
    }
)
```

```console
   a   b   c
0  0  10  20
1  1  11  21
2  2  12  22
3  3  13  23
4  4  14  24
```

## polars.DataFrame
```python
pldf = pl.DataFrame(
    {
        "a": np.arange(0, 5),
        "b": np.arange(10, 15),
        "c": np.arange(20, 25),
    }
)
```

```console
shape: (5, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 0   ┆ 10  ┆ 20  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 1   ┆ 11  ┆ 21  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 12  ┆ 22  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 13  ┆ 23  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 14  ┆ 24  │
└─────┴─────┴─────┘
```

# 動作を比較
## 末尾からn番目の行を抽出

```python
pddf.iloc[-2, :]
```

```console
a     3
b    13
c    23
Name: 3, dtype: int32
```

行を抽出した場合、`pandas.DataFrame` の場合は`pandas.Series`として取得されます。

```python
pldf[-2, :]
```

```console
Traceback (most recent call last):
  File "_test_polars.py", line 34, in <module>
    main()
  File "_test_polars.py", line 30, in main
    print(pldf[-2, :])
  File "C:\Python38\lib\site-packages\polars\internals\dataframe\frame.py", line 1333, in __getitem__
    return df.slice(row_selection, 1)
  File "C:\Python38\lib\site-packages\polars\internals\dataframe\frame.py", line 2827, in slice
    return self._from_pydf(self._df.slice(offset, length))
OverflowError: can't convert negative int to unsigned
```

`polars.DataFrame`の場合はエラーとなってしまいます。

```python
pldf[-2:-1, :]
```

```console
shape: (1, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 3   ┆ 13  ┆ 23  │
└─────┴─────┴─────┘
```

範囲抽出の場合は負の値を指定しても動くので、1行だけ抽出したい場合でも範囲指定する必要があります。
抽出結果は`polars.Series`ではなく`polars.DataFrame`になり、この違いが次項で述べる`numpy.ndarray`の変換に影響してきます。

## 行抽出結果を 'numpy.ndarray' へ変換

```python
pddf.iloc[-2, :].values
```

```console
[ 3 13 23]
```

`pandas.Series`を`numpy.ndarray`へ変換した場合は`shape=(n,)`になります。

```python
pldf[-2:-1, :].to_numpy()
```

```console
[[ 3 13 23]]
```

しかし、`polars.DataFrame`の場合は行の抽出結果も`polars.DataFrame`であるため、`numpy.ndarray`への変換結果は`shape=(1,n)`となります。
ESP32からFlaskサーバにデータを送る方法

## はじめに
ESP32に接続した距離センサからFlaskサーバにその取得データを送れるよう試みました。

## 前提
使用機器
- ESP32
- uPYCraft
- VL53L1X 距離センサ
- WSL Ubuntu(Flaskサーバ)

>upyCraftの導入/初期セットアップはこちらを参考に！
>https://qiita.com/sirius1000/items/0d8aad6abae996051ff6

## 流れ
1. ESP32起動時の初期実行プログラム(boot.py)を記述し, ESP32に格納
1. ESP32をFlaskサーバと同じネットワークセグメント内に接続
1. Flaskサーバにデータを送るプログラム(send.py)をESP32に格納 
1. Flaskサーバ側で受信するプログラムを記述&サーバ起動
1. ESP内のsend.pyを実行し, 受信の可否を確認する

## 実装
####  ①ESP起動時の初期実行プログラム(boot.py)を記述し, ESP32に格納
まず, ESP32起動時に実行されるプログラムboot.pyを作成します。  
今回は, WiFi, WebREPL接続に関するプログラムを記述しています。
プログラムを記述したらuPYCraftを使ってESP32に送信します

::: note info
boot.py起動後は, WebREPLを使ってESP32へのファイル送信/実行が可能。
WebREPLを使う場合, このESP32のIPアドレスとポート番号, それとプログラム内に記述されているパスワード "1234"が必要です。
:::

```boot.py
import time
import utime
import network
import webrepl

#　WIFI設定を記述
SSID_NAME = "YOUR SSID"
SSID_PASS = "YOUR PASSWORD"


def connect_wifi(ssid, passkey, timeout=10):
    wifi= network.WLAN(network.STA_IF)
    if wifi.isconnected():
        print('already Connected. connect skip')
        return wifi
    else :
        wifi.active(True)
        count = 0
        while count < 5:
            try:
                wifi.connect(ssid, passkey)
                break
            except:
                utime.sleep(3)
                count += 1
        while not wifi.isconnected() and timeout > 0:
            print('.')
            utime.sleep(1)
            timeout -= 1
    if wifi.isconnected():
        print('Connected')
        webrepl.start(password='1234')
        return wifi
    else:
        print('Connection failed!')
        return ''


if __name__ == '__main__':
    wifi_dojo = connect_wifi(SSID_NAME, SSID_PASS)
```

#### ②ESP32をFlaskサーバと同じネットワークセグメント内に接続
ESP32とFlaskサーバ(PC)と同じネットワークセグメントに接続するようにしましょう。

#### ③ Flaskサーバにデータを送るプログラム(send.py)をESP32に格納
ESP32からFlaskサーバにデータを送るsend.pyをESP32に格納します
```send.py
import time
import ujson
import urequests

def send():
    url = 'http://FlaskサーバのIPアドレス:ポート番号/get'

    # 送信データ
    sendData = {"message": "HELLO Flask!!"}
    header = {'Content-Type': 'application/json'}

    # postでサーバにJSON形式データを送信し, 送信成功の可否をresに格納
    res = urequests.post(url, data=ujson.dumps(sendData).encode("utf-8"),headers=header)
    print("サーバからのステータスコード：", res.status_code)
    res.close()


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

#### ④Flaskサーバ側で受信するプログラムを記述&サーバ起動
Flaskサーバで受信プログラムserver.pyを記述&サーバを立ち上げる
```server.py
from flask import Flask, request, render_template, jsonify

app = Flask(__name__)

@app.route("/get", methods=["POST"])
def getMessage():
    data = request.get_json(force=True)
    msg = data['message']
  
    print(f'受け取ったメッセージ:{msg}')
```

Flaskサーバを立ち上げる。
```server.py
python3 server.py
```

#### ⑤ESP内のsend.pyを実行し, 受信の可否を確認する
uPYCraftまたはWebREPLでESP32内のsend.pyを実行し, flaskサーバ側のコンソールに,  "受け取ったメッセージ: HELLO Flask!!" がでたら完了!

## 以上, 終わり!
ROSパッケージの作成

# ROSとは
- ロボットを動かすために作られたオープンソースライブラリ
- 処理の単位をNodeといった形で分割し, Nodeの集合によってシステムが構成される
- Node間ではトピックと呼ばれるタグが付けられたメッセージで通信している
- メッセージの出力をPublisher, メッセージの受け取りをSubscriberが行う.
- Nodeの実行はSubscriberでメッセージを受け取ったときに行われる

# 新しいノードの作成方法
catkinコマンドが利用できるディレクトリで以下のコマンドを実行

```cmd
# Set the node name to PKG_NAME
catkin create pkg PKG_NAME
```

```command
-p Nodeを作成するディレクトリを設定
-a 作成者を設定 基本的にメールアドレスを設定
-d パッケージの説明
```

他コマンドは[Create Packages](https://catkin-tools.readthedocs.io/en/latest/verbs/catkin_create.html)を確認してください.

# Debug

## ノードの振る舞いの確認

- ```rosrun rqt_graph rqt_graph```: ノードとトピックの確認
- ```rosnode info hogehoge```: hogehogeノードの送受信状態, Service一覧の確認
- ```roslaunch --nodes hogepackage hoge.launch```: launchファイルの起動するノードの確認

## デバックツール

- GDB
- OProfile
- Valgrind Home

# テスト
Rosノードのテストを行う場合, Python標準のunittestでテストを実装し、rostestラッパーを使用します.
テストの実装が完了したらpackage.xmlファイルに```<build_depend>rostest</build_depend>```を追加します.
```<test_depend>```は利用しないでください.

# README.md
READMEファイルには以下の項目を記載することを推奨します.
1. Title
1. Overview
1. Reference
1. BasicUsage
1. Node
    1. parameter
    1. Subscribed Topics
    1. Published Topics

# フォルダ構成
以下のような構成になると思います
![0_vfNM1mbkhUpvK-nW.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412006/ba6ec938-93c7-ac07-bd67-5af5a33edbad.png)

https://medium.com/swlh/7-simple-steps-to-create-and-build-our-first-ros-package-7e3080d36faa

# 参考
ROS公式

http://wiki.ros.org/ja/ROS/Tutorials/CreatingPackage

http://wiki.ros.org/unittest

ROS開発者マニュアル(日本語訳)

https://myenigma.hatenablog.com/entry/20131221/1387583310

【Python3】unittest使い方まとめ

https://www.mathkuro.com/python/unittest/