OmniAICreator/Qiita-1.07M huggingface dataset:
論文メモ：MultiPoseNet: Fast Multi-Person Pose Estimation using Pose Residual Network

# 論文
**論文名**
*MultiPoseNet: Fast Multi-Person Pose Estimation using Pose Residual Network*

**著者**
*Muhammed Kocabas, Salih Karagoz, and Emre Akbas*

**学会**
*ECCV2018*

https://arxiv.org/abs/1807.04067


# 概要
　人物検出、人物セグメンテーション、姿勢推定をマルチタスクで処理することができる新しいボトムアップ方式手法。正確な姿勢推定のために提案されたPose Residual Network(PRN)が2つの出力（キーポイント・人物検出）を受けてキーポイントを人物インスタンスに割り当てる。精度と速度の両方においてそれまでのボトムアップ手法を上回り、トップダウン手法に匹敵する精度でありながら少なくとも4倍の速度を実現する（23フレーム毎秒）。
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/15460e04-d53b-c7f4-e4bd-6c4d6cab4ccd.png', width=500>
>Muhammed Kocabas, Salih Karagoz, and Emre Akbas. Multiposenet: Fast multi-person pose estimation using pose　residual network. In ECCV.

# 貢献
- キーポイントの割り当てとグルーピングに対して有効に働くPRNの提案
- ボトムアップ手法の精度を凌駕し、トップダウン手法と同等の精度を達成
- 23フレーム/秒のリアルタイム性を実現
- 拡張可能性が高く、同じアーキテクチャを用いてセグメンテーションをなどの他の処理も可能
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/4c5588d6-d198-73bd-d107-a7e8e47593d6.png', width=500>
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/934a8cdb-ff7f-b590-4f30-f58a44c4daab.png', width=500>

>Muhammed Kocabas, Salih Karagoz, and Emre Akbas. Multiposenet: Fast multi-person pose estimation using pose　residual network. In ECCV.

# 評価
- COCO test-devにおいてボトムアップ手法の精度更新、トップダウン手法と同等の精度
- COCOでの人物検出の精度でオリジナル実装の精度を上回る（80クラスのここをperson1クラスに変更しているから当然）
- PASCAL VOC2012においてセマンティックセグメンテーション精度がDeepLabv3と同等（これは苦しくね？？）
- ランタイムが既存手法と比較して速い
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/60dcdc14-c393-e166-ec64-a0494c3d1c77.png', width=500>
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/8a679f99-58d6-2118-3465-3087329a142c.png', width=500>
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246925/241b682b-2391-3c7b-33f2-0f865ca82ca0.png', width=400>

>Muhammed Kocabas, Salih Karagoz, and Emre Akbas. Multiposenet: Fast multi-person pose estimation using pose　residual network. In ECCV.

# 課題
- 人物検出とセマンティックセグメンテーションの精度が課題なのでは（個人的にそう思う）。特に人物検出も最先端の精度でないとキーポイントのローカライズが真に正確になり得ない
Vagrant環境でRailsアプリケーションのDBを削除しようとすると、Errno::ETXTBSY: Text file busy @ apply2filesのエラーが発生した。

表題の通り、Vagrant環境で作成したRailsアプリケーションでデータベースを削除しようとした際にエラーが発生しました。
ググってみると海外の記事だったり、曖昧な表現の記事が多かったため、自分なりに手順をまとめました。

**実行環境**
- Windows10 20H2
- Vagrant 2.2.18
- Ubuntu 20.04.3 LTS


### データベースの削除
以下のコマンドを使うと、データベースを削除することが出来るので実行します。

```
$rails db:drop
```

![rails_drop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/515f155e-9c6c-f46a-e685-3e2f84d7aad3.png)
<font color="Red">Couldn't drop database 'db/development.sqllite3'</font>
**出たわねっ！**
正直何かしら出る気しかしませんでした。エラー読み解いていきます。

<font color="Red">Errno::ETXTBSY: Text file busy @ apply2files - /home/vagrant/workspace/<(アプリ名>/db/development.sqlite3</font>

このエラーは、Vagrantfile内で指定している共有フォルダ内でデータベースファイルを削除しようとしたため発生します。
データベースファイルとは、ここでいうところの "development.sqlite3" です。 

それぞれの環境によって詳細は異なりますが、Vagrantfileには以下のような記載があるかと思います。
![sharefolder.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/be8893da-ca67-2847-9ebf-e7b373c4e3c7.png)
1つ目の” ”がWindowsから見たパス、2つ目の" "が仮想環境(Ubuntu等)から見たパスになります。
つまり、先程のエラーの意味は、私の環境だと<font color="Red">"/home/vagrant/workspace/"</font>より深い階層に <font color="Red">"development.sqlite3" </font>があるとエラーになります。

今回、私は "/home/vagrant" に新規でtempフォルダを作成し、tempフォルダの中へデータベースファイルを移動させました。

**[移動元]** /home/vagrant/workspace/<(アプリ名>/db
![vag-db3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/57a44005-f1d2-c71d-e86a-1ff839a34942.png)

**[移動先]** /home/vagrant/temp
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/c36a67bd-ae8f-0b0d-dead-14c05d3db044.png)

次に、/config/database.yml にデータベースファイルを指定する設定箇所があります。
該当箇所を新しく作ったtempフォルダ内のデータベースファイルを指定します。
![yml.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/05a4bbe2-b811-f8d5-417a-e6d13db043d9.png)

これでデータベースを削除する準備が出来ました。
もう一度、データベースを削除するコマンドを実行します。

```
$rails db:drop
```

![result.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259269/344370f2-8e36-ec36-73ed-d279f2c11350.png)
今度は無事にデータベースが削除されました。
Unity2019でAdmob実装時にクラッシュして表示されないときの対処法

https://kaedeee.com/unity2019-admob/

しばらく更新していませんでした！というのもアプリ作るのにはまってて笑

（アプリのURLはまた後で）

 

ところで今回は、 Unity 2019でAdMobを実装した際にクラッシュしてしまいアプリが表示できなくなってしまう時の対処法です。

 

（やはり Unity 2019は最新版ということで2019に関する記事がなかなかなーい！！笑笑）

というわけで僕のでよければ参考にどうぞ。

結論から言うと以下二つに対応することでうまくいきました！！

(あ、Android アプリ用です。この記事)


#Unityのバージョンを確認する

結論から言うと

 

Unity 2019 1.4f1

　×　

Google mobile ADS Unity plugin 3.16　

が最強！

 

はじめ自分は

Unity のバージョン→ 2019.3.0a3

に

AdMobのバージョン→Google mobile ADS Unity plugin v3.17

を投入！

ですがこの時にx86 not found 的なエラーが起こりました

調べて見るとこんな感じで最新版のUnity にはx86がないみたい。。。

↓Unity のバージョン→ 2019.3.s0a3

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/0a49b321-0ead-accd-7f62-01dab93eb46e.png)

↓Unity 2019 1.4f1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/394cba50-4d98-4a6c-a265-814a1d8b137c.png)

Unity 2019 1.4f1　にはx86のボタンがあるけど

2019.3.0a3にはないですな。

友達がうまくいっているというバージョンでやることにしてみました。

（てかよくみるとβ版じゃん、、、そりゃバグるな）

成功したバージョンはこちら！

Unity 2019 1.4f1　×　Google mobile ADS Unity plugin 3.16

 
#Android manifest を確認する

 

最近の  Unity 用　admob のパッケージは Android manifest に

自分のパッケージ名とアプリ ID を書くことが主流になっていますね。

というわけで実装してみたんですが、、、クラッシュ。表示されない

まじか一週間たちました。

何回もクラッシュしては何回も ReImport all して試行錯誤を繰り返す日々

もう本当に嫌んなっちゃうよ。

 

 

初心に振り返るべきだなと思い公式の Google mobile Ads を確認。

 Android manifest の例外があるじゃありませんか。

 #![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/a34f050f-362d-7223-d25b-14e1098bbc44.png)


というわけで上ではなく、下の方のコードをプラスで追加。

正直あんまりよくわかってないですけど

表示されたやったーこれでまた頑張れますね。

 

追記　表示されたのは勘違いでした！！というわけで追加の解決策を以下に示します。

 

#AdMobやAdseneの規約を確認

 

結論から言うと、僕がAdseceアカウントを二つ取得していたのが原因でした。

サイト用のAdcenseアカウントは以前からあったのですが、最近取得したアプリ用のAdMobアカウントは、

それとは「異なるグーグルアカウントに紐付けていた」んです。

 

前提として

・Adseceアカウントは一人につき一つまで

とGoogleに規定されてます。

ですがなぜか僕の場合、異なる二つのアカウントの申請が通っていました。（普通ならポリシー違反でgmail通告が来るそうです）

通告は来ていないものの、違反と言うことで広告配信がなされなかったようですね。

 

対応策

対応策としてAdMobのアカウントは消去しました（入金はキャンセルされてしまいましたが、Googleさんへの謝罪の気持ち分としてはしょうがないかな。）

 

次は旧Adsenceアカウントの設定です。Adsenceのマイページから、

AdMobやYouTubeパートナープログラム等を追加する設定があるので、

AdMobアカウントを追加。

 

因みに、GoogleAdseceのアカウントには二つ種類が存在し、

・Adseceアカウント

・AdMobアカウントやYouTubeパートナーシップなど、単体としてのAdsence

アカウント

 

それぞれにメリットデメリットがあります。

前者は

・審査が厳しい

・AdMobアカウントやYouTubeパートナーシップの導入や統合が楽

・ポリシー違反をしてしまってもアカウント復活の確率が上がる

 

後者はその逆です。

時間があるなら、AdSenceアカウント取得をした方が良いでしょう

 

あとはもう一度AdMob ID とかを設定して、一日二日ほど放置、、、、

やった！もどった！

 

みなさんもポリシー違反には十分気をつけて下さいね。

（Googleが本気で怒ると同じIPアドレスからAdsenceアカウントは再取得できないらしい、、、神かよ、、、）

 

#まとめ

というわけで今回のまとめはこんな感じ

Unity のバージョンを確認する
アドモブのバージョンを確認する
今のところUnity 2019 1.4f1　×　Google mobile ADS Unity plugin 3.16　がよさげ。

Android Manifest　は、アプリ ID 書く方ではなく、下の方の「アド マネージャーを使用している場合」のコードを書く。
 

おわり。。。

https://kaedeee.com/unity2019-admob/
IOTデバイスを扱うにあたり意外な問題が

簡易的IOTをやってみよう
---
簡易的なIOTをやってみようということで、車に
・Wifiモバイルルーター
・Wifiカメラ（クラウドカメラ）
・ポータブル電源
・モバイルバッテリー
などを積んで外部からカメラの動画を見れる環境を作ってみた。

使用感
-
家庭内のWireless LANを前提に作られているWifiカメラデバイスなのだが、格安SIMでも通常のモード（高速）で使用する分には特にストレスなく使用できることが確認できた。ただし、100KB/s程度の帯域を使用するのでbpsに直すと1Mbpsくらいあればそれなりに使えるという感じであろうか。でもこの状態のカメラ映像をずっと見ているとすぐにGB単位のデータ量になってしまうので、常時監視するような使い方を想定する場合は、定額でかなりのデータ量または無制限に使える契約を使用する必要がある。

Wifiモバイルルーター自体にバッテリーを積んでいるのだが、それにモバイルバッテリーをつないでバッテリーの持ち時間を延長したり、Wifiカメラにポータブル電源を接続して相当な時間使えるようにしてみたり工夫はしてみたが、電力の消費に対して十分にそれを補うだけの走行時間乗ることがないため、主にWifiモバイルルーターのバッテリーがなくなって停止してしまっている。ポータブル電源にすべて接続すると今度はWifiモバイルルーターだけ電池が残り、Wifiカメラがバッテリー切れになってしまうので、ソーラーパネルなどを利用して永続的に使用できる方法を今後検討してみたい。

格安SIMの低速帯域では動作が不完全に
---
300kbpでは帯域が足りずにコマ落ちというレベルではない動画の遅延が発生してしまうため、リアルタイムに監視することはできない。
ただクラウドカメラの機能で動体検知の機能はある程度使えるようで、本体にバッファしている動画をクラウドにゆっくりと送ることはできているようだ。

車の機能に支障が出ることがある・・・
-
最近スマートキーがなかなか反応しないという状況に遭遇した。
どうやらWifiカメラ（中華製）がスマートキーの使用している電波帯域に干渉するようで、キーを相当ドアに近づけないと反応しないという不都合が発生した。トランクがあけられなかったりとスマートキーに関わる機能に不都合が生じたので、Wifiの電波が電波法で規制されている意味を改めて感じた出来事でした。2.4GHz帯のほうで干渉を起こしていると思うので、5GHz帯ならしないかもしれないが、5GHz帯は屋外での使用が電波法で制限されているので使えない。
Unityで事前にロードする方法。ロード後に数秒待つ実装。

https://kaedeee.com/unity-preloading/

Unityで、前シーンにおいて事前にローディングすることで、よりスムーズにシーン遷移ができます。

ユーザー体験はノンストレスである必要があると思い、以下のようなスクリプトを実装しました。

ちなみに、以下では余計なアニメーション部分も実装されているので必要なければ　Update() 中を省略して下さい。




```
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class Loading : MonoBehaviour
{

  
  private AsyncOperation async;
  public Text loadingText;
  public float waitSec = 5.0f;
  public float cycle=0.8f;
  float time=0;
  void Start()
  {
    StartCoroutine("LoadData");
  }

    private void Update()
    {
    time += Time.deltaTime;

        if(time <= (cycle/5f))
      loadingText.text = "Now loading";
    else if (time <= (cycle * 2 / 5f))
      loadingText.text = "Now loading.";
    else if (time <= (cycle * 3 / 5f))
      loadingText.text = "Now loading..";
    else if (time <= (cycle * 4 / 5f))
      loadingText.text = "Now loading...";
    else if (time <= cycle)
        {
      time = 0;
        }
    

  }
    IEnumerator LoadData()
  {
    // シーンの読み込みを開始
    async = SceneManager.LoadSceneAsync("MainScene");
    // ロードが完了していても，シーンのアクティブ化は許可しない
    async.allowSceneActivation = false;
    
    while (async.progress<0.9f)
    {
      yield return null;
    }
    //ロード完了後。任意秒　待ってシーン遷移。
    yield return new WaitForSeconds(waitSec);
    async.allowSceneActivation = true;
  }

}
```

気をつけるべきは、AsyncOperation　の性質で、非同期動作で使用するのですが、

上記スクリプト で while (!asny.isDone) とすると上手くいきませんでした。

async.isDoneは事前に

async.allowSceneActivation = false;

としてしまうと、常にfalseを返すようです。

また、この時

async.progressも最大でも0.9に留まることに注意して下さい。

 

追加情報があればコメントで是非。

https://kaedeee.com/unity-preloading/
XcodeでNo member named ‘drawableafterMinimumDuration’ in ‘UnityDisplaySurfaceMTL’のエラーが出た時の対処法

https://kaedeee.com/xcode-no-member-named-drawableafterminimumduration-in-unitydisplaysurfacemtl/(新しいタブで開く)

UnityからXcodeビルドする際に起きたエラーに対応したので共有します。

#バージョン情報

バージョンは以下。

Unity 2019.3.5f1

Xcode Version 12.0 


原因

XcodeがiOS11に対応したことによるバグかと思います。

Device向けのビルドではエラーは起きませんでしたが、

Simulator向けのビルドで発生しました。

エラー場所はMetalHelper.mm

エラー内容は

XcodeでNo member named ‘drawableafterMinimumDuration’ in ‘UnityDisplaySurfaceMTL’

#![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/af890fa1-22b8-c128-e7b5-b3f23558330a.png)

[UnityCurrentMTLCommandBuffer() presentDrawable: surface->drawableafterMinimumDuration: 1.0 / targetFPS];

の部分を

[UnityCurrentMTLCommandBuffer() presentDrawable: surface->drawable];

 

とすることで修正できました。

お疲れ様です。

https://kaedeee.com/xcode-no-member-named-drawableafterminimumduration-in-unitydisplaysurfacemtl/(新しいタブで開く)
Apex One Trend Micro を　Mac OS Catalina　から削除したい

https://kaedeee.com/apex-one-trend-micro-catalina/

Mac OS Catalina では、Apex One Trend Micro　の削除が困難です。

削除ソフト、tmsminstall.pkg の入手先がなかなか見つからなかったので、以下にリンクを載せておきます。消す際は自己責任でお願いします。


tmsmininstall.pkg

https://ict.kwansei.ac.jp/item/guide/tmsm35_uninstall.zip

詳しいサイト

https://docsplayer.net/178388716-Trend-micro-security-for-mac-持込-pc-用インストールマニュアル-mac-os-用-作成-2018-年-12-月-改訂-2020-年-1-月-情報環境機構.html


docsplayer.net

https://kaedeee.com/apex-one-trend-micro-catalina/
Force Resolve すると resolution failed　になる時の対処法 [AdMobで広告が表示されない]Failed to fetch the following dependencies

Unity のバージョンを上げると、広告が表示されなくなった時の対処法です。

#バージョン

Unity 2019.4.12f

AdMob 5.20

#エラー内容

Force Resolve するとfailed to resolution

エラー内容は

force resolve Failed to fetch the following dependencies: com.google.android.gms:play-services-ads:19.3.0

#対処法

Delete Resolved Libraries の後、

Windowsでは

C:\Users\name\.gradle\wrapper\dists\gradle-5.1.1

Macでは

/Users/name/.gradle/wrapper/dists/gradle-5.1.1-bin

を消去して、もう一度Folce Resolveすることで対応できます。
Unityに画像ファイルをimportした時に、デフォルトでTexture Type を Sprite (2D and UI)　にする。

https://kaedeee.com/unity-import-texture-type

#問題

先日、Unityをアップデートしたためか、png ファイルやjpg ファイルをインポートしても

Texture Type >> Sprite(2D and UI) 　

ではなく、

Texture Type >> Default

のままになってしまいました。

 

この設定のままでは、UI imageに表示されなかったり、Spriteとして Scene view にドラッグアンドドロップできません。

いちいち　Texture Type　を　Default からSprite (2D and UI) に変更するのは手間なので、一括処理ができるように設定を変えてみました。


対処法

対処方法は、

Project Setting >> Editor >> Default Behavior Mode

を

3D –> 2D に変更することです。

#![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/a4958f83-7c4f-a4da-ee4d-6bf981142202.png)

Unityでは、3Dゲーム、2Dゲーム、それぞれで自動的に最適化されているのはありがたいですが

そのどちらの特徴も知っていないと予期しないエラーがおきますね。

https://kaedeee.com/unity-import-texture-type
Initaramfs 不要のカーネルを作る例

# Initaramfs 不要のカーネルを作る例

## 始めに

LFS から Arch にやってきたけど、Arch は initaramfs イメージを使って起動する。LFS で initramfs なしでやってきたノウハウを活かして Arch でも initramfs なしで起動するカーネルを作ってみた

## initramfs なんで必要?

まず Linux のブートの仕組みから。ド素人の理解なので不正確かもしれない。なんとなくそんな感じというように受け止めてほしい。

Grub ブートローダーは、たいていの記憶デバイスを動かせるし、たいていのファイルシステムを扱える。なのでまず、どこかの記憶デバイスのなにかのファイルシステム上に存在するカーネルを起動させることができる。

Grub の役目は終り、カーネルが始動する。この後はカーネル自身がなんとかしなくてはならない。カーネルは /sbin/init を起動しようとする。このとき、自分の例では SATA 接続の SSD に XFS ファイルシステムで /sbin/init がある。Arch のカーネルは XFS はモジュールになっているので、xfs モジュールを読みこみたいが、/lib/modules を読むのに xfs モジュールが必要なので詰む。

なのでカーネル自身に xfs も sata コントローラも両方組み込んでおく必要があるし、逆を言えば、そうすれば initramfs は無くても動く。

## Arch での kernel ビルドの準備

前提としてカーネルのビルドは知ってる、としてます。ビルド方法そのものは説明しません。

まずは Arch の linux パッケージで入ってるのと同じバージョンのカーネルソースを https://www.kernel.org 持ってくる。そうすると Arch の Linux の .config を使って ```make olddefconfig```  でほぼ同じ設定にできるので、そこから開始する。ほぼ同じというのは Archwiki によると多少パッチを独自に当てているから、ということになる。全く同じにしたい人は Arch の物を取ってくれば良いだろう。

ちなみに Arch の .config は ```zcat /proc/config.gz > .config``` で取得できる

## Arch での kernel config 

```make nconfig``` にて

```
File systems --->
   <*> XFS filesystem support  
```

これだけで良い。Arch は記憶デバイス用のドライバーは基本モジュールではなくて組み込みにしてあるみたいだ。自分の例だと以下のおかげで動く。

```
Device Drivers  --->
  <*> Serial ATA and Parallel ATA drivers (libata)  --->
    <*>   AHCI SATA support
```

カーネルパニック起こしながらトライしてみると良いと思う。

## grub.cfg の設定と起動。

カーネル起動コマンドから ```initrd``` の行を削除したら、祈りを捧げよう。

あっと、もうひとつあった。kernel 行の root パーティション指定が UUID になってると思うので、デバイス名直打ちか PARTUUID に変える必要がある。UUID はファイルシステム上の固有 ID であり、カーネルにファイルシステムを組み込んだんだから行ってくれよ、と思うのだけど、この段階では、行ってくれない。自分の場合は ```root=/dev/sda3``` としてる。ノート PC で入れ替えることなどほぼないので。

## 捕捉: CPU マイクロコードは？

initramfs イメージがなくてもマイクロコードは実行中に読みこめる。BLFS の説明が詳しい。

https://www.linuxfromscratch.org/blfs/view/systemd/postlfs/firmware.html

またコンフィグツリーの

```
Device Drivers --->
  Generic Driver Options  --->
    Firmware loader  --->
      ()    Build named firmware blobs into the kernel binary
```

ここにファームウェアをフルパスで指定しておけばカーネルに組込める。

## まとめ
というわけで kernel panic を恐れずにいろいろやってみてください。
Unity でAdmob + FAN のmediation を実装すると gradle failed となって build できない時の対処法。



先日、初めて　Unity に　Admob　を利用した　メディエーションを実装しました。

Admob + Facebook Audience Network でメディエーションを実装することにしましたが、Android に　ビルドする際にgradle failedとなってエラーになるのでその対応方法を示します。

 https://kaedeee.com/admob-fan-mediation/

英語で読める方は以下のリンク先から解決できます。https://answers.unity.com/questions/1784106/applovinmax-inmobi-adapter-failes-the-build-with-g.html

 

実装までに至るファイルのインポートや設定は、Admob公式リファレンスの通りに行えば良いです。

以下では、あくまでビルドエラーの対応に絞って示します。

#バージョン


Unity

　2019.4.19f1
Admob

　GoogleMobileAds-v5.4.0
Fan mediation

　GoogleMobileAdsFacebookMediation-2.11.1

EasyMobilePro

　current 2/16


#対応方法

①　PlayerSetting >minimum API Level -> Android 5.0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/08244a1e-644b-92a9-ee17-5d9df7e705eb.png)


②PlayerSetting > Build > Custom Base Gradle Template -> Check
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/254c524c-daec-53fe-902a-a59b46cdd25e.png)


2021/6/17 Update 
PlayerSetting > Build > Custom Main Gradle Template -> Check
PlayerSetting > Build > Custom Base Gradle Template -> Check
PlayerSetting > Build > Custom Gradle Properties Template -> Check

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/b727ca2b-17cf-b05a-747e-546dec4fe321.png)

③　Open ‘baseProjectTemplate.gradle’

　　convert classpath ‘com.android.tools.build:gradle:3.4.0’

　　to　　　classpath ‘com.android.tools.build:gradle:3.4.3′

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/df17c93a-cb06-e0f3-b709-0ed86b7f59c8.png)


以上です、お疲れ様です。

（多分admob が求めているgradle のバージョンと Unity のそれとがマッチしていないから）

https://kaedeee.com/admob-fan-mediation/
Unity で Resources.load()を使って Texture 2D を呼び出したい。

https://kaedeee.com/unity-で-resources-loadを使って-texture-2d-を呼び出したい%E3%80%82/

Sprite で呼び出す場合と異なり、Texture 2D の設定に細かい修正が必要だったので覚書。

#Importしたpng を inspector view で修正

以下の画像のように修正
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900756/be59f3b7-37e7-afc1-20d1-c5b9bc8842d0.png)


Texture Type : From Sprite to “Default”

Advanced -> Read/Write Enabled “Check”


#Script

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using EasyMobile;
using UnityEngine.UI;

public class ImportT2dManager : MonoBehaviour
{
    Texture2D texture2d; 
	Sprite    sprite;
   
    private void Awake()
    {
        texture2d = ScreenShotManager.screenShotInfo.texture = Resources.Load("Texture2dImage", typeof(Texture2D)) as Texture2D;
        sprite = Resources.Load<Sprite>("SpriteImage");
    }
}
```

https://kaedeee.com/unity-で-resources-loadを使って-texture-2d-を呼び出したい%E3%80%82/
【Rails】html_safeを使用することで発生する脆弱性とその対策

## 結論

- html_safeを使用するのであれば、xss対策としてhメソッドを使用する必要がある。

```ruby
text = "テスト\nテスト"

<%= h(text).gsub(/\n/, "<br>").html_safe %>
```

## 経緯

- devise.ja.ymlで定義した文章を改行するタスクがあり、それを実現するために、以下の実装を行った。
    1. devise.ja.ymlに改行コード(\n)を埋め込む
    2. html_safeを使用して改行を実現

よし。これで改行を表現することができた。よろしくおねがいしまーす。タンッ！

その後、プルリクのコメントに「xss対策をしてください。」の文字。

・・・？

### xss(クロスサイトスクリプティング)

- 脆弱性の一種
- 第三者がWebページにスクリプトを自由に組み込める状態のこと
- スクリプト上で意図していないスクリプトを埋め込まれ、情報を盗み取られる危険性がある

自分が実装した内容だとscriptタグを埋め込まれて情報を盗み取られる危険がある実装をしていたということになります。原因と対策を調べました。

### 原因

html_safeを使用したときに発生する脆弱性を把握していなかったこと

- 今回、改行を表現するためにhtml_safeを使用しました。これで、文字列に改行文字を埋め込むと、改行コードが反映されるようになります。

```ruby

# index.html.erb

text = "テスト<br>テスト"

<% text %>
#=> 
テスト テスト

<% text.html_safe %>
#=> 
テスト
テスト

# 埋め込んだ<br>が適応され、改行されて表示される
```

しかし、このメソッドは、エスケープ処理を行わないようにするメソッドのため、エスケープ処理を自分で実施する必要がありました。それを怠っていたということになります。

今回は、エスケープ処理の動作と対策を確認すべく、scriptタグを文字列に埋め込み、alertが表示されないこと = 対策ができているとして調べました。

## 調査

- 今回の目的は、テキストを改行させることでした。しかし、それを実現するためにhtml_safeを使用すると、脆弱性が発生してしまう。なので、html_safeを使用して改行を実現しつつ、脆弱性対策も実施する方法を探りました。

### hメソッド

- エスケープ処理を実装してくれるメソッドで、特別な意味を持つ記号を、別の文字列に変換してくれます。挙動は以下の通り。

```ruby
> text
=> "テスト\nテスト<script>alert(`test`)</script>"

> h(text)
=> "テスト\nテスト&lt;script&gt;alert(`test`)&lt;/script&gt;"
```

上記のようになります。これにより、文字として扱うことになるのでscriptタグを無効化することができます。

hメソッドを使用して、XSS対策を行った結果が以下の通りになります。

```ruby
> rails c

> text
=> "テスト\nテスト<script>alert(`test`)</script>"

> text.gsub(/\n/, "<br>")
=> "テスト<br>テスト<script>alert(`test`)</script>"

> h(text).gsub(/\n/, "<br>")
=> "テスト<br>テスト&lt;script&gt;alert(`test`)&lt;/script&gt;"

> h(text).gsub(/\n/, "<br>").html_safe
=> "テスト<br>テスト&lt;script&gt;alert(`test`)&lt;/script&gt;"
```

これで、改行を実現しつつxss対策も行うことができました！

```ruby
index.html.erb

<%# pタグに普通に埋め込んだ場合: alertする%>
<% text = "テスト\nテスト<script>alert(`test`)</script>" %>
<br>

<%# そのまま出力 = 改行✗ エスケープ○ %>
<h3>1.text</h3>
<%= text %>

<%# html_safe = 改行✗ エスケープ✗ %>
<h3>2.text + html_safe</h3>
<%= text.html_safe %>

<%# gsub = 改行✗ エスケープ○ %>
<h3>3.text + gsub</h3>
<%= text.gsub(/\n/, "<br>")%>

<%# gsub + html_safe = 改行○ エスケープ✗ %>
<h3>4.text + gsub + html_safe</h3>
<%= text.gsub(/\n/, "<br>").html_safe%>

<%# gsub + html_safe + hメソッド = 改行○ エスケープ○ %>
<h3>5.text + gsub + html_safe + hメソッド</h3>
<%= h(text).gsub(/\n/, "<br>").html_safe %>
```

erbに埋め込んで１つずつ確認すると、alertが表示されるパターン、されないパターンを確認することができました。

### スクリーンショット

動作確認として、以下の２点をチェックしました。

- scriptタグが文字として表示されている = エスケープ処理がされている
- scriptタグが表示されていない = エスケープ処理がされていない

<img width="713" alt="スクリーンショット 2021-11-07 20 29 32" src="https://user-images.githubusercontent.com/64491435/140729389-e936e3f9-b2b6-4e6f-ad5e-7642b47d4378.png">

<img width="713" alt="スクリーンショット 2021-11-07 20 42 39" src="https://user-images.githubusercontent.com/64491435/140729403-820b3d3d-f9a2-40cf-8644-9a30952915e8.png">


エスケープ処理がされていない場合、アラートが表示されてしまいます。
実際に動かしてみることで、エスケープ処理の重要性を確認することができました。

## まとめ

- Railsは自動的にエスケープ処理を実装行ってくれている。
- html_safeを使用することで、エスケープ処理が行われなくなり、脆弱性が発生する
- html_safeを使用した場合は、hメソッドでエスケープ処理を実装することで対策をする必要がある。
[AppStoreアプリリリース]審査に受かるための独自の方法まとめ。

https://kaedeee.com/appstore-release/

# 前書き

Appleの審査結果ほど、自分の1日を左右する出来事はない
東側諸国のベロッパーなら、朝日と共にアプリ承認のメールを確認するのは日課であるが、
結果、非承認であれば、まるで恋人に振られた憂鬱と共に1日を過ごすことになる。
（だがしかし、西側諸国よりはマシだ。なぜなら不眠に悩まされる必要がないのだから）
というわけで今回は、私がAppleの審査に受かるために行っていることを記述していく。

注意：これは自身の経験と、アプリデベロッパー達のサイトをいくつか拝見した上で、独自に考察した根拠のない方法である。自己責任で試していただきたい。

# 審査に関しての豆知識

以下では、審査に関する知見を述べる。

## 回数について
* アプリ審査は、１番最初が一番厳しい。
（アプリの可否判定も含めているため）
* 2回目、3回目は易しい。4回目からはまた難しくなるが、1回目ほどではない。
* ある地域についてLocalize対応を初めてした際は、その地域についての審査が厳しくなる。

# アプリの種類について
* オンラインアプリ（難）＞＞オフラインアプリ（易）
（セキュリティ性のためだろう）
* ブラウザを内包したアプリ（最難）　
（セキュリティ＆それならWebアプリでいいじゃん、と言う正論）
* 英語圏のみにリリース（易）＞＞グローバルリリース（難）
（基本的には審査員はアメリカ人とインド人で、全てを英語に翻訳して審査している、がどうしても不可解な場合はネイティブに審査を頼んでいる、結果、ネイティブはしっかり審査をするので審査が厳しくなる、らしい）
* Game カテゴリ（易）＞＞ Tool App カテゴリ（難）
（クソゲーは需要があるが、クソツールは需要がないらしい）

## シーズンについて
* 月曜日の審査（難）＞＞金曜の審査（易）　
（審査担当者が変わるため張り切る）
* クリスマス＆正月休暇前後（最易）　
（審査提出アプリ数が増えるため一つ一つに割ける時間が減る）


# まとめ


以上を踏まえてのアプリリース方法。

## 1回目のリリース（最も審査が厳しい）

:::note info
アメリカのみ配信　＆　All 英語
ゲームカテゴリ
オフライン
週末もしくは長期休暇前後
:::

## 2回目のリリース　（審査が緩い）

:::note info
グローバル配信　＆　言語のローカライズ
カテゴリを目的のものに変更
オンライン要素導入
曜日は気にしない。
:::


つまり、一回目のアプリは、「良い子ちゃん or 真面目くん」なアプリ。
二回目のバージョンアップで、目的のアプリに「変身」させる感じで。
以上を行うとスムーズに配信に漕ぎ着けるのではないか（適当）

https://kaedeee.com/appstore-release/
Salesforce の Userレコードを Anonymous Apex Code で追加するメモ

- Salesforce の User を `Anonymous Apex Code` で追加するためのミニメモです。
- `Developer Console` (開発者コンソール) の `Debug` | `Open Execute Anonymous Window` から実行可能です。
- 後述の Apex Code を理解できる人、かつ、User オブジェクトの特性を知る人が Apexを実行することを前提とします。

# Profile の Id を取得する

作成したいユーザの Profile の `Id` を取得するために、SOQL をもちいて既存ユーザーを参考として確認します。

- UserName の LIKE検索の値は、参考にしたいユーザをヒットさせるための適当な値に更新して SOQL実行
- SOQL 検索結果の Profile の Id の値をメモ

```sql
SELECT Username, Email, LastName, Alias, CommunityNickname
    , ProfileId, Profile.Name, TimeZoneSidKey, LocaleSidKey
    , EmailEncodingKey, LanguageLocaleKey, LastLoginDate
  FROM User
  WHERE UserName LIKE '%MyName%'
```

# Salesforce の User を Apex で追加する

Anonymous Apex Code 上の文字列値を適切な値で上書きしたうえで実行します。

- 注意: どのような UserName の Userレコードが作成されるのかを Apex を確認して理解して確信を持ってから Apex を実行すること
- この例では User レコードが追加されるのみ
- パスワードリセットは別途実施が必要
- メールアドレスなどを実際に登録したい文字列値で更新する
- profId はその環境における正しい Id 文字列値で更新する

```apex
String sandboxSuffix = '.sand001';
String profId = '00eevvvvvv2vVvVVVU';
String shortName = 'tigap';
String emailAddr = 'tigap@example.org';
String usrName = emailAddr + sandboxSuffix;

System.debug('Add user: begin: ' + usrName);

User newUser = new User(Username = usrName, Email = emailAddr
    , LastName = shortName, Alias = shortName, CommunityNickname = shortName
    , ProfileId = profId
    , TimeZoneSidKey = 'Asia/Tokyo', LanguageLocaleKey = 'ja', LocaleSidKey = 'ja_JP'
    , EmailEncodingKey = 'ISO-2022-JP'
    );
insert newUser;

System.debug('Add user: end.');
```

# Apex 実行後に User を確認する

- User オブジェクトに、指定した内容の User レコードが追加されたことを確認
- パスワードリセットは必要に応じて別途設定画面などから実施

# 補足

- `DataLoader` が利用しづらい場面などで役立つ可能性あり

# 文書情報

初出: 2021-11-08

## 関連情報

* [シンプルな オブジェクトからレコード検索 サンプル (Salesforce CLI で Anonymous Apex Code 版)](https://qiita.com/igapyon/items/a600a1176d18655fcda7)
* [シンプルな オブジェクトへレコード追加 サンプル (Salesforce CLI で Anonymous Apex Code 版)](https://qiita.com/igapyon/items/f5b37ab6554a6aa67d1f)
* [シンプルな オブジェクトのレコード更新 サンプル (Salesforce CLI で Anonymous Apex Code 版)](https://qiita.com/igapyon/items/97bd88aa61b77bf5c834)
* [シンプルな オブジェクトのレコード削除 サンプル (Salesforce CLI で Anonymous Apex Code 版)](https://qiita.com/igapyon/items/baf2f533968176e6e55f)
* [シンプルな オブジェクトの項目一覧取得 サンプル (Salesforce CLI で Anonymous Apex Code 版)](https://qiita.com/igapyon/items/1bedba5dc9d12bdaa34c)
* [Salesforce の Userレコードを Anonymous Apex Code で追加するメモ](https://qiita.com/igapyon/items/3bca5c1a12cfac26d43f)
【Vue.js】イベント修飾子 v-once

#はじめに
こんにちは！
今回は【Vue.js】イベント修飾子 v-onceについてアウトプットしていきます！

#イベント修飾子とは
v-onのために、イベント修飾子を提供している。クリックなどのDOMイベントの振る舞いを変更する修飾子。

v-onceはイベントハンドラを１回だけ実行することができる。

#書き方・解説
現在の時刻を表示するプログラムを例題としていきます。
v-onceを使い、2度目以降はボタンを押してもイベントハンドラが実行されないように書きます。

```HTML:HTML
<div id="app">
  <button v-on:click.once="clickHandler">
                  <!--⏫最初の一回だけ処理を実行する-->
    Now
  </button>
  <p>
    {{ message }}
  </p>
</div>
```
```Vue.js
 var app = new Vue({
   el: "#app",
   data: {
     message: ''
   },
   methods: {
     clickHandler: function() {
       this.message = new Date().toLocaleTimeString()
       　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　//⏫現在時刻の表示
     }
   }
 })
```
`clickHandler`メソッドを用意し、中身に処理を書く。内容は、**現在の時刻を`this.message`に代入する**
とする。すると`data`オプションの`message`に現在の時刻が代入された。

＜テンプレート側＞
ボタンを設置。ボタンの中に**`v-on:click.once="clickHandler"`**と記述。このように`.once`も一緒に記述すると、**ボタンがクリックされた時にclickHandlerの処理を１回だけ実行する**という処理が行われる。
*２回目クリックしても処理は実行されない。
その処理した内容を`{{ message }}`で表示させているというプログラムになる。

![スクリーンショット 2021-10-26 5.52.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/10fd3ef1-432d-6210-c729-369b50992b19.png)



#まとめ
・`v-on:click.once="〇〇"`というふうな形で記述する。`.`を忘れない。
・v-onceは１回だけ処理を実行する。


#最後に
今回はイベント修飾子 v-onceについてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
【AtCoder】JavaでABC226のA,B問題を解く！

ABC226のA,B問題をJavaで解きました。（C問題は難しくて解けませんでした）
備忘録としてまとめておきます。

#A問題『Round decimals』
問題ページ：[A - Round decimals](https://atcoder.jp/contests/abc226/tasks/abc226_a)

X：小数点第三位までの実数
X を小数第一位で四捨五入して得られる整数を出力する

小数点を持つ実数は、「Double型」で宣言します。
宣言（入力値を取得）した変数をroundメソッドを用いて、小数第一位で四捨五入します。

##コード
```java
import java.util.*;
public class Main
 {
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
		
        // 画面入力値を取得する
        double scanD = sc.nextDouble();

        //小数第一位で四捨五入
        System.out.println(Math.round(scanD));
    }
 }        

```

#B問題『Counting Arrays』
問題ページ：[B - Counting Arrays](https://atcoder.jp/contests/abc226/tasks/abc226_b)

入力例より、数列 $a_i,_j$を$N$個取得し、取得した数列のうち重複を除く数を出力します。
​重複を除くリストの取得方法として、HashSetを使用しました。
（[参考サイト](#参考サイト)参照)


##コード
```java
import java.util.*;
public class Main {
	public static void main(String[] args)
     {
        Scanner sc = new Scanner(System.in);
        //数列の数を取得する
		final int N = sc.nextInt();
		int[] L = new int[N];
		//重複を除くリストを宣言する
        Set<List<Integer>> list = new HashSet<>();

		for (int i = 0; i < N; i++) 
        {
            //数列の要素の個数を取得する　（1,2)⇒要素数：２
			L[i] = Integer.parseInt(sc.next());
			//数列を取得する
            List<Integer> k = new ArrayList<>();
			for (int j = 0; j < L[i]; j++) 
            {
                k.add(Integer.parseInt(sc.next()));
            }
            list.add(k);
		}
        //リストの重複を除いた数を出力する
		System.out.println(list.size());
	}
}

```


#参考サイト
A問題：Java 四捨五入するサンプル(round)

https://itsakura.com/java-round#s1

B問題：【Java】HashSetの使い方（順序なしSet）

https://loglog.xyz/programming/usage_hashset
[Mac] VSCodeからGithubにアクセスする

最近VSCodeに乗り換えたのですが、ソース管理ビューにて（前もって`git clone`で取得してた）リポジトリをプル/プッシュしようとするとエラーになりました。

```
...
> git pull --tags origin master
...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

この解決方法をまとめた記事が見当たらなかったので、まとめてみようと思います。


## 環境

* macOS Monterey (バージョン 12.0.1)
  * Sierra / High Sierra / Mojave / Catalina / Big Sur も同様？


## SSH設定

一番参考になったのは、（Windowsですが）こちらのサイトでした。
[VSCodeでGitHub連携のためのSSH設定](https://akihiro-document.azurewebsites.net/post/windows/vscodegithubsetup/)

Git設定〜GitHub設定は今回の事象特有のものではありません。
よって、ここまでは済んでいるものとします。（済んでない方は申し訳ありませんが他をググって進めてください）

本事象の原因は、git configを確認すると見えてきます。

```
% git config --list
credential.helper=osxkeychain
...
```

```
% git config --show-origin --get credential.helper
file:/Library/Developer/CommandLineTools/usr/share/git-core/gitconfig	osxkeychain
```

もしかすると、CommandLineTools を入れなければ発生しない問題なのかもしれません。

いよいよ解決方法です。
まず、`vi ~/.ssh/config`でconfigファイルを作成します。
これに、Macでは以下記述を追加します。

```
Host github github.com
  User git
  HostName github.com
  AddKeysToAgent yes  # 追加
  UseKeychain yes     # 追加
  IdentityFile ~/.ssh/id_rsa
  IdentitiesOnly yes
```

この設定は[Mac OS X以降のssh-agent事情](https://qiita.com/yuki153/items/0ad5cb02faf3ecdcf903)を参考にさせていただきました。
設定の意味等は参照先記事にてご確認ください。

これで準備はできましたが、最初の一回だけは手動で認証する必要があります。
ターミナルから`git pull origin master`を実行し、手動でパスフレーズを入力してください。

以後はVSCode（ソース管理ビュー等）からプルできるようになります。


## ユーザ設定

VSCodeから初回プッシュした時に以下のエラーメッセージが表示されました。

```
fatal: no email was given and auto-detection is disabled
```

VSCodeではgit configを直接設定することはできないんですかね...？
仕方ないので、これもコマンドで設定しました。

```
% git config --global user.email "YOUR_EMAIL"
% git config --global user.name "YOUR_NAME"
```


以上、参考になれば幸いです。
(四角錘)「2019年度 京都大・文系数学問5」をsympyとvbaソルバーとwolframalphaでやってみたい。

オリジナル

球面に内接する四角錘

https://www.densu.jp/kyoto/19kyotolpass.pdf#page=5


# 問題

https://mathexamtest.web.fc2.com/2021/202110541/2021105410100mj.html#top-0107

# SymPy Liveで(微分)
以下のソースコードを貼り付けて、Evaluateです。

https://live.sympy.org/

```python
from sympy import *
var('r h')
f=(sqrt(r**2 - h**2) / sqrt(2) * 2)**2 * (r +h ) / 3
t=solve(diff(f,h), h)
print("#",t[1].subs({r:1}),f.subs({r:1,h:t[1]}))
# 1/3 64/81
```
matplotlibでグラフ作成。勉強中。

# SymPy Liveで(非線形方程式)
勉強中。おすすめ。アドバイス下さい。


# vbaソルバーで

????教えて下さい。
行数を少なくする方法を教えて下さい。
よろしくお願いします。

```vb
Const r = 1
Function myR1C1toA1(i, j)
    myR1C1toA1 = Application.ConvertFormula("R" & i & "C" & j, xlR1C1, xlA1)
End Function
Sub myTaiseki()
    Range(myR1C1toA1(2, 1)).Formula = "= (sqrt( 1^ 2 - " & myR1C1toA1(1, 1) & "^ 2) / sqrt(2) * 2) ^ 2 * (1 +" & myR1C1toA1(1, 1) & ") / 3"
    Dim ws As Worksheet: Set ws = ActiveSheet
    SolverReset
    SolverOk setCell:=ws.Range(myR1C1toA1(2, 1)), _
                      MaxMinVal:=1, _
                      ByChange:=ws.Range(myR1C1toA1(1, 1)), _
                      EngineDesc:="GRG Nonlinear"
    SolverOptions AssumeNonNeg:=True
    SolverSolve UserFinish:=True
End Sub
Sub myFormat()
    Range("A1:B1").Select
    Selection.NumberFormatLocal = "0.000_ "
    Range("B1") = 1 / 3
    Range("B2") = 64 / 81
    Range("A1").Select
End Sub
Sub aaa_Main()
    Dim myTS As Variant
    ActiveSheet.Cells.Clear
    Call myTaiseki
    myFormat
End Sub
' 0.333 	0.333 
' 0.790123457	0.790123457
```
 Dim myTSは、不要です。


# wolframalphaで

https://www.wolframalpha.com/input/?i=%28sqrt%281**2+-+x**2%29+%2F+sqrt%282%29+*+2%29**2+*+%281+%2Bx+%29+%2F+3&lang=ja
【JavaScript】正規表現を用いるときのブラウザによるバリデーションを非表示にしたい

#はじめに
こんにちは。
こちらの記事では、ブラウザのフォームのバリデーションを非表示にする方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

##問題・原因・対処法

###起きていること
正規表現でフォームのバリデーションを行う際、エラーメッセージが重複してしまう。

<img width=“200” src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/2d44b6c0-e6b5-c748-cead-05a14b5053c4.png">

###なぜこの問題が発生したのか
ブラウザに、元々バリデーションの機能が設定されているため。

###解決方法
formタグに`novalidate=`を追記することで、ブラウザのバリデーション機能を無効にできます。

```html:vue.js
<form @submit.prevent novalidate>
```
<img width=“200” src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966101/ec2a7aa0-9c37-a720-f7c7-0a62dc8ecb3d.png">



>参考記事：https://insource-mkd.co.jp/staff-blog/14752.html


<br>


#おわりに
ここまで、ブラウザのフォームのバリデーションを非表示にする方法についてまとめました。
参考記事を見つけるのに少し時間がかかってしまいましたが、辿り着くことができました！この経験から、ネットにある情報をいかに持ってくることができるか、が重要だと改めて感じました。検索力を上達していけるよう、今から回数を重ねていきたいと思います！

以上、最後まで読んでいただきありがとうございました！
よければLGTMを押してくれると嬉しいです！
メモ：Node.js(http)でWebSocketを扱う



基幹系システムではあまり出番がないので触っていなかった双方向通信のWebSocket
[ここ](https://www.sejuku.net/blog/82316)とか
[ここ](https://qiita.com/ij_spitz/items/2c66d501f29bff3830f7)を参考にテスト

WindowsServer2012, Nodejsはv14.16でテスト

# Node.js側

単純にWebSocketを使う場合は
`npm install ws`
でいけるが、Socket.ioを使う場合は
`npm install socket.io`
でインストールする。
今回はsocket.ioを選択

サーバ側ではexpressではなく通常のhttpを利用した。
server.onでclient.htmlを返すように設定


```javascript:server.js
var fs = require('fs');
var http = require('http');
var server = http.createServer();

// HTTPのアクセス
server.on('request', function(req, res) {
  var stream = fs.createReadStream('client.html');
  res.writeHead(200, {'Content-Type': 'text/html'});
  stream.pipe(res);
});

// WebSocketのアクセス
var io = require('socket.io')(server);
io.on('connection', function(socket) {
    socket.on('chat',  function (data) {
      io.emit('chat',data);
      console.log(data);
    });
  });

server.listen(8000);
```

WebSocketではserverを指定してioを取得。
そのioに対してデータが飛んできた時の挙動を指定する。
今回はdataをそのまま返してやると同時にconsole.ogで出力するようにした。
（チャットのようなもの）

# クライアントのスクリプト
実際にはサーバ側に置いているclient.htmlの内容

io.connect()でsocketを取得して、socket.emitでメッセージを送信する。
socket.onで受信を待ち受ける。

```html:client.html
<html>
  <head>
    <title>Socket.IO</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
      $(function() {
        var socket = io.connect();

        $('#send').on('click', function(event){
            var msg =  $('#txtfield').val();
            if(msg != ""){
                socket.emit('chat',msg);
                console.log(msg)
            }
        });

        socket.on('chat', function(data, fn) {
          $('#message').prepend(data + "<br>");
        });
      });
    </script>
  </head>
  <body>
    <h1>Socket.IO</h1>
    <hr>
    <input type="text" name="txtfield" id="txtfield" />
    <input type="button" name="send" value="send" id="send" />
    <hr>
    <div id="message"></div>
  </body> 
</html>
```


AWSのサーバレスでやるとしたらAPIGateway+Lambdaは回数課金だった気がするので向いてなさそう。Fargateでコンテナ利用する形なのかな。
GCPだと[CloudRun](https://www.infoq.com/jp/news/2021/04/google-cloud-run-updates/)がSocketsをサポートしているようだが使った事がない。
VScode + Vim Extention / Normalモードに入ったら日本語入力を解除する

## 問題
VScode+Vim Extentionでコードを書いているとき、デフォルトのままだとInsertモードで日本語を入力したあと、Insertモードに戻るとする。
すると日本語入力が維持されているためカーソル移動すると `っっっっh` みたいに入力されて悲しくなる。
これをなんとかしたい。

## 環境
- macOS Big Sur 11.6
- Visual Studio Code 1.62.0
- Vim Extention v1.21.10

## 解決方法
[公式](https://github.com/VSCodeVim/Vim#input-method)に書いてある解決策を使う。

まず`im-select` をインストールする。

```
curl -Ls https://raw.githubusercontent.com/daipeihust/im-select/master/install_mac.sh | sh
```

その後、VScodeのユーザー設定に以下を追記。

```json
{
  "vim.autoSwitchInputMethod.enable": true,
  "vim.autoSwitchInputMethod.obtainIMCmd": "/usr/local/bin/im-select",
  "vim.autoSwitchInputMethod.switchIMCmd": "/usr/local/bin/im-select {im}",
  "vim.autoSwitchInputMethod.defaultIM": "com.apple.keylayout.ABC",
}
```

これでInsertモードからNormalモードに戻ったとき、日本語入力が解除されるようになる。

## ちなみに
この状態だと再度Insertモードに入ったとき、日本語入力が維持されている状態になる。
これも嫌な場合は以下のようにする。

```json
{
  "vim.autoSwitchInputMethod.enable": true,
  "vim.autoSwitchInputMethod.obtainIMCmd": "/usr/bin/true",
  "vim.autoSwitchInputMethod.switchIMCmd": "/usr/local/bin/im-select {im}",
  "vim.autoSwitchInputMethod.defaultIM": "com.apple.keylayout.ABC",
}
```

コピペしやすいように全文乗せているが、上で書いたものとの違いは `vim.autoSwitchInputMethod.obtainIMCmd` のみ。

## 参考にしたもの
https://qiita.com/altus/items/334aaa27fb2c7b73b837
https://note.com/5mingame2/n/n88d7ceae5a95
【GoogleAnalytics】BigQuery Exportのプロジェクト選択でエラーになる時の対処法

## はじめに
こんにちは。ジールの@________________MFです。
Webログ分析のためGoogleAnalytics(GA)のBigQuery Export機能を利用してBigQuery(BQ)へデータ連携しようとしたところ、GAの設定画面にて連携先のGCPプロジェクトが選択できない謎なエラーが発生しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2166013/1d9c55fe-6013-6721-dd77-e1eec38a7861.png)

※BigQuery Exportを設定する具体的な手順は[公式ドキュメント・ステップ３](https://support.google.com/analytics/answer/3416092?hl=ja&ref_topic=3416089#)をご参考ください。
※BigQuery Exportを設定するユーザーは、GA・GCPともに必要な権限を持っている前提です。



## 結論
GCPのVPCサービスコントロール(VPC-SC)でBQを保護している為、
GAの設定画面からVPC-SCで許可されていないIP・ユーザーでプロジェクトを取得しようとしていることがエラーの原因でした。
BigQuery Exportを設定するユーザーアカウントをVPC-SCのアクセスレベルに追加することで解決できました。


## 利用サービス
- Bigquery
- VPCサービスコントロール + Access Context Manager(アクセスレベルの管理)
- GoogleAnalytics

## アクセスレベルにBigQuery Exportを設定するユーザーを追加
GAのBigQuery Exportを設定するユーザーをアクセスレベルに追加します。
ユーザーの追加はAccess Context Manegerを利用しますが、Webコンソール画面からは実行できない為、gcloudコマンドとユーザーを記載したyamlファイルを利用します。

```
gcloud access-context-manager levels update LEVEL_NAME \
    --basic-level-spec="path/to/CONDITIONS.yaml" \
    --policy=POLICY_NAME
```

yamlファイルにGAの設定画面を操作するユーザーを記載します。
既存で設定されているユーザー・サービスアカウントも併せて記載しないと、
今回追加するユーザーのみのアクセスレベルにアップデートされるので要注意。

```yaml:CONDITIONS.yaml
- members:
  - user:XXXXXXXX@sample.co.jp
  ....
```

コマンドを実行後、Access Context Managerのコンソール画面からアクセスレベルへユーザーが追加されていることを確認します。


## 最後に
上記した方法でユーザーをアクセスレベルに追加後、再度BigQuery Exportを実施したところ、プロジェクト選択画面でのエラーがなくなり無事設定できました。
BigQuery Export設定後は、設定したユーザーをアクセスレベルから外しても連携に影響がない為、不要であればユーザーを外してください。
※yamlファイルから対象ユーザーを消した後、「gcloud access-context-manager levels update」コマンドを上記同様に実行すればOK。

GCPのサービスですとVPC-SCの適用に関してドキュメントに詳しく書かれているのですが、GCP以外の関連サービスでは記載が無いように思えたので今回の記事を書きました。

## 参考リンク
https://support.google.com/analytics/answer/3416092?hl=ja&ref_topic=3416089#

https://cloud.google.com/access-context-manager/docs/manage-access-policy#gcloud_2

https://cloud.google.com/vpc-service-controls/docs/use-access-levels

***
株式会社ジールでは、「ITリテラシーがない」「初期費用がかけられない」「親切・丁寧な支援がほしい」「ノーコード・ローコードがよい」「運用・保守の手間をかけられない」などのお客様の声を受けて、オールインワン型データ活用プラットフォーム「ZEUSCloud」を月額利用料にてご提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
 
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/?utm_source=qiita&utm_medium=referral&utm_campaign=qiita_zeuscloud_content-area
【第三回】YOLOv3を一から実装　～畳み込み層・残差ブロック～

 はじめに
　[前回の記事](https://qiita.com/gotty21/items/7e6bfdc2c221dc3521e9)ではYOLOv3に論文でも使用されたCOCO datasetを使ってdatasetを作成しました。今回からモデル構造の作成に取り掛かります。YOLOv3では画像の特徴を抽出するために複数の畳み込み層と残差ブロックを使用します。本記事では畳み込み層を作成する関数と残差ブロックのclassの作成を解説していきます。


# フォルダ構成
>作業フォルダ
>　┠ COCO (COCO datasetのダウンロードの項で作成します)
>　┠ dataset
>　┠　　┗ cocodataset.py (前回作成)
>　┗ models
>　　　　┗ yolov3.py (今回作成するファイル)

# 使用ライブラリ
　本記事内で使用するライブラリは以下となります。本記事では使用しませんが、動作確認の使用する前回作成したCOCOdatasetもimportしておきます。その際に必要となるモジュール検索パスの追加もここで記述してあります。

```python:cocodataset.py
import os
import sys
from pathlib import Path

import torch.nn as nn

FILE = Path(__file__).resolve()     # fileまでのパス
ROOT = FILE.parents[1]              # 作業ディレクトリまでのパス
if str(ROOT) not in sys.path: sys.path.append(str(ROOT))

from dataset.cocodataset import COCODataset
```

# 畳み込み層
　初めに畳み込み層を作成する関数を実装します。ここで言う畳み込み層は、畳み込みした画像をBatchNormalizeし、活性化関数を通す一連の流れを一括りにして畳み込み層と呼んでいます。この関数はYOLOv3全体のモデルを作成するときやこの後説明する残差ブロックのところで使用します。[入力channel数, 出力channel数, フィルターサイズ, ストライド]の4つを入力とし，出力として畳み込みのモジュール(レイヤー)を返します。

```python:yolov3.py
def add_conv(in_ch, out_ch, ksize, stride):
    layer = nn.Sequential()

    pad = (ksize - 1) // 2
    layer.add_module('conv', nn.Conv2d(in_channels=in_ch, out_channels=out_ch, kernel_size=ksize, stride=stride, padding=pad, bias=False))
    layer.add_module('batch_norm', nn.BatchNorm2d(out_ch))
    layer.add_module('leaky', nn.LeakyReLU(0.1))

    return layer
```

# 残差ブロック
　続いて残差ブロックのclassを作成します。このclassをインスタンス化する際には[入力channel数, nblocks, shortucut]の3つを入力として与えます。図で表すと以下となります。

![img1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2216693/65dc9d15-83c7-ffef-1fca-89d796df6e55.jpeg)

入力が二つの畳み込み層を通ります。出てきた出力hのchannel数は入力と同じになる用設計されています。shortcutがTrueの場合は、畳み込みする前の入力xと出力hを足し合わせたものが出力として得られます。さらに得られた出力を再度入力として層に入力します。これをnblock回繰り返すのがこの残差ブロックとなります。コードは以下となります。

```python:yolov3.py
class resblock(nn.Module):
    def __init__(self, in_ch, nblocks=1, shortcut=True):
        super().__init__()

        self.shortcut = shortcut 
        self.module_list = nn.ModuleList()

        for _ in range(nblocks):
            resblock_one = nn.ModuleList()
            resblock_one.append(add_conv(in_ch,    in_ch//2, 1, 1))
            resblock_one.append(add_conv(in_ch//2, in_ch,    3, 1))

            self.module_list.append(resblock_one)

    def forward(self, x):
        for module in self.module_list:
            h = x

            for res in module:
                h = res(h)

            x = x + h if self.shortcut else h

        return x
```

# まとめ
　ここまで読んでいただきありがとうございます。今回は畳み込み層を作成する関数の定義と残差ブロック層のclassを作成しました。次回はYOLOv3に含まれるlayerの肝となるYOLO Layerの実装を解説したいと思います。
CloudFront単体でレスポンスヘッダを付与できるようになった！！（Lambda@Edgeなしでのレスポンスヘッダ設定）

今までCloudFront＋S3で公開しているシステムはレスポンスヘッダを付与したい場合にLambda@Edge等で設定してやる必要がありました。
しかし、今回のリリースでCloudFrontだけでレスポンスを付与できるようなったらしいので、調べてみました。

https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-cloudfront-supports-cors-security-custom-http-response-headers/


# レスポンスヘッダーポリシーについて

ポリシーメニューから`レスポンスヘッダー`を選択します
デフォルトでいくつか登録されているのが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/7f81bc36-4d90-94b8-4b65-cd8272df8455.png)

### デフォルトで登録されているポリシーを開いてみる

デフォルトで登録されているポリシーを確認してみます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/d7bb7af6-ba13-7da8-25d8-90f1d1999a3c.png)

複数のヘッダが登録されてるのが分かります。

### ポリシーの作成画面

`レスポンスヘッダーポリシーを作成`を押下すると以下のような画面が表示されます。
カスタムヘッダーも定義できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/c0c93b2c-70c3-fe8f-065a-9d94d276dc44.png)


ちなみに、各スイッチをONにすると詳細項目が表示され、必要項目の入力を促されます。
レスポンスヘッダーなんてたまにしか触らなくて毎回調べるのめんどくさかったので、これは助かりますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/060fd0ec-25e6-99f1-16e3-8f28cfa4e34c.png)



# ディストリビューションに紐づけ

ディストリビューションのビヘイビアからレスポンスヘッダーポリシーを選択できるようになっています。
これで、対象のディストリビューションに紐づいたドメインへアクセスした場合に自動でレスポンスヘッダーが付与されるようになるみたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/fedce550-73d2-1f84-9f0e-ce778099b998.png)


### Lambda@Edgeも引き続き使える

既存のLamda@Edgeの設定はビヘイビア編集ページの最下部に以下のように配置されてました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/c31ea630-838e-3264-c2c7-20f26ce3e3ec.png)



# 最後に

CORS関連は最初から定義されているので、必要に応じてカスタムヘッダを追加してあげるだけで良さそうです。
先日Lambda@Edgeでレスポンスヘッダを付与する対応したばっかりだったので、あと数か月早くリリースしてくれれば．．．^^;
Serverless Framework スケジュール実行で Lambda に引数を渡す方法

`serverless.yml` で `input` を定義することで、スケジュール実行に任意の引数を渡すことができます

```yml
# serverless.yml
events:
  - schedule:
      rate: rate(10 minutes)
      enabled: false
      input:
        sampleKey: sampleValue # Lambda に渡したい値
```

JavaScript の場合、handler からは以下のように値を取得することができます

```typescript
// handler.ts
module.exports.hello = async event => {
  const { sampleKey } = event; // serverless.yml に定義した値を取得
};
```

:bulb: `input` 指定の詳細は [Serverless Framework | Schedule](https://www.serverless.com/framework/docs/providers/aws/events/schedule) を参照してください

### :warning: `sls invoke local` では↑で定義した値は渡されない

- `sls invoke local` で実行する場合 `serverless.yml` で定義した `input` は渡されないようです
- 実装をテストしたい場合は下記コマンドを実行すると event に指定の値を渡すことができます

```shell
npx sls invoke local -f functionName --data '{"sampleKey": "sampleValue"}'
```

:bulb: `invoke local` のパラメータ詳細は [Serverless Framework | AWS - Invoke Local](https://www.serverless.com/framework/docs/providers/aws/cli-reference/invoke-local) を参照してください。
chia-blockchain debian package での CLI バイナリのありか(madmax plotter もあるよ)

## 背景

git から clone して chia のビルドめんどい.

Ubuntu を使っているので, debian prebuild があるのでそれいれる.
v1.2.11 以降を想定します.

デフォルト(?)では `chia-blockchain` GUI コマンドしか使えない(`chia` CLI にパスが通っていない)

GUI 動かすほどでもないときは CLI で処理したい(e.g. 複数プロセスで chia plot するときとか, farmer key 確認するときとか)

## ありか

`/lib/chia-blockchain/resources/app.asar.unpacked/daemon` にあります.

## おまけ

v1.2.11 から  Madmax plotter も付きました! :tada:

https://github.com/Chia-Network/chia-blockchain/releases/tag/1.2.11

`/lib/chia-blockchain/resources/app.asar.unpacked/daemon/madmax` に plotter があります!
firebaseAuthを設定するまでの流れ

firebase consoleでAuthenticationを選択する

ログイン方法を設定する
↓
メールアドレスとパスワードを設定した場合
↓
Firebase用の設定ファイルを作成する（歯車のプロジェクトの設定）
↓
構成に書いてあるオブジェクトの値をコピーする
↓
firebaseのディレクトリーを作成する
↓
firebaseのフォルダの中にconfig.tsのファイルを作成
↓
config.tsにexport　const firebaseConfig = {}の形で構成のオブジェクト値を入れる
↓
firebaseのフォルダの中にindex.tsのファイルを作成

index.ts

```
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import 'firebase/storage'
import 'firebase/functions'
import {firebaseConfig} from './config'

firebase.initializeApp(firebaseConfig);
export const auth = firebase.auth();
export const db = fitrbase.firestore();
export const storage = firebase.storage();
export const functions = firebase.functions();
export const FirebaseTimestamp = firebase.firestore.TimeStamp;
```

firestoreへのユーザー登録の追加

signUp.tsx(reduxで書いているのでreactやnextで書く場合は変更する必要があり)

```
export const signUp = (username, email, password, confirmPassword) => {
    return async (dispatch) => {
        // Validations
        if(!isValidRequiredInput(email, password, confirmPassword)) {
            alert('必須項目が未入力です。');
            return false
        }

        if(!isValidEmailFormat(email)) {
            alert('メールアドレスの形式が不正です。もう1度お試しください。')
            return false
        }
        if (password !== confirmPassword) {
            alert('パスワードが一致しません。もう1度お試しください。')
            return false
        }
        if (password.length < 6) {
            alert('パスワードは6文字以上で入力してください。')
            return false
        }

        return auth.createUserWithEmailAndPassword(email, password)
            .then(result => {
                dispatch(showLoadingAction("Sign up..."))
                const user = result.user;
                if (user) {
                    const uid = user.uid;
                    const timestamp = FirebaseTimestamp.now();

                    const userInitialData = {
                        customer_id: "",
                        created_at: timestamp,
                        email: email,
                        role: "customer",
                        payment_method_id: "",
                        uid: uid,
                        updated_at: timestamp,
                        username: username
                    };

                    usersRef.doc(uid).set(userInitialData).then(async () => {
                        // const sendThankYouMail = functions.httpsCallable('sendThankYouMail');
                        // await sendThankYouMail({
                        //     email: email,
                        //     userId: uid,
                        //     username: username,
                        // });
                        dispatch(push('/'))
                        dispatch(hideLoadingAction())
                    })
                }
            }).catch((error) => {
                dispatch(hideLoadingAction())
                alert('アカウント登録に失敗しました。もう1度お試しください。')
                throw new Error(error)
            })
    }
}
```
OCIのオブジェクト・ストレージにAWS S3互換APIでアクセスする

# はじめに
OCIのオブジェクト・ストレージにAWS S3互換APIでアクセスする方法を確認します。

## 参考資料
https://speakerdeck.com/oracle4engineer/ociobuziekutosutorezi-s3hu-huan-apifalseli-yong

# 前提
以下の設定ができていることとします。

- OCIのテナンシー（アカウント）作成
- 利用ユーザの作成
- コンパートメント作成
- AWS CLIのインストール

# 証明書の作成
- 「アイデンティティ」→「ユーザー」→「ユーザーの詳細」に行く。
    - 左の「リソース」メニューの「顧客秘密キー」を選択
        - 「秘密キーの生成」をクリックし、任意の名称を付けて秘密キーを作成する
        -  生成された「秘密キー」と「アクセスキー」をTextファイルなどにメモしておく。
            -  秘密キーはこの時しか表示されないので、メモするのを忘れたら作成し直す。
           
# テナンシー/コンパートメントの確認、設定
- 「管理」→「Tenancy details」に行く。
    - 「テナンシ情報」タブの以下2つの情報を確認する
        - Amazon S3互換APIで指定されたコンパートメント
        - オブジェクト・ストレージ・ネームスペース

## 利用するコンパートメントについて
- AWSにはコンパートメントの概念がないので、使用するコンパートメントはあらかじめ一つにしないといけない。
    - 変更する場合は、「オブジェクト・ストレージ設定の編集」で変更する。

# バケットの作成
- 上記で確認した「Amazon S3互換APIで指定されたコンパートメント」を指定して、バケットを作成する
- テスト用に任意のオブジェクトを作成したバケットにアップロードする

# aws cliの設定

- aws cliをインストールした端末にログインする
    - ここでは、OCIのコンピュートインスタンス（Oracle Linux）を使用

```
$ aws --version
aws-cli/2.3.4 Python/3.8.8 Linux/5.4.17-2102.206.1.el7uek.x86_64 exe/x86_64.oracle.7 prompt/off
```

## 秘密キー、アクセスキーの登録

```
$ aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4f45b # アクセスキーを貼り付け
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8HA= # 秘密キーを貼り付け
Default region name [None]: # 任意（後述）
Default output format [None]: # 設定しない
```

# アクセスの確認

- 書式
    - `$ aws s3 --region <リージョン> --endpoint-url https://<オブジェクトストレージ・ネームスペース>.compat.objectstorage.<リージョン>.oraclecloud.com　ls s3://<バケット名>`

```
$  aws s3 --region us-phoenix-1 --endpoint-url https://mytenancy.compat.objectstorage.us-phoenix-1.oraclecloud.com ls s3://test01/
2021-11-08 07:50:30      23994 oci.jpg
2021-11-08 07:20:31       7466 oralogo.jpg
```

## オブジェクトの移動（標準層からアーカイブストレージ）

```
$ aws s3 --region us-phoenix-1 --endpoint-url https://mytenancy.compat.objectstorage.us-phoenix-1.oraclecloud.com mv s3://standard-bucket-01/oci.jpg s3://archive-bucket-01
move: s3://standard-bucket-01/oci.jpg to s3://archive-bucket-01/oci.jpg
```

# リージョンの指定について
- ホームリージョンのバケットにアクセスする場合、`--region`オプションの指定は不要
- ホームリージョン以外のバケットにアクセスする場合、以下のいずれかで指定する。
    - aws s3 コマンドの`--region`オプションで指定する
    - aws configureコマンドのDefault region nameで指定する