OmniAICreator/Qiita-1.07M huggingface dataset:
Bevyが落ちる時の解決法

前々から**Bevyが途中で落ちる**問題がありまして、それを何とかできないかと思い調べてみました。
元記事は[Github](https://github.com/bevyengine/bevy/issues/3645)です。


**使用環境**
OS: Windows11 Home
CPU: AMD Ryzen 7 5800H
GPU: NVIDIA GeForce RTX3060 Laptop GPU

発生したエラーメッセージ

```
ERROR present_frames: wgpu_hal::dx12::instance: ID3D12CommandQueue::Present: Resource state 
(0x800: D3D12_RESOURCE_STATE_COPY_SOURCE) (promoted from COMMON state) of resource 
(0x000002580E633720:'Unnamed ID3D12Resource Object') (subresource: 0) 
must be in COMMON state when transitioning to use in a different Command List type, 
because resource state on previous Command List type : D3D12_COMMAND_LIST_TYPE_COPY, 
is actually incompatible and different from that on the next Command List type : 
D3D12_COMMAND_LIST_TYPE_DIRECT. [ RESOURCE_MANIPULATION ERROR #990: RESOURCE_BARRIER_MISMATCHING_COMMAND_LIST_TYPE]
```

どうやら２つのGPU（CPU内蔵GPUと外部GPU）が**競合**していることが原因っぽいです。
私の場合、この問題は以下のコードを追加することで解決しました。



```rs
use bevy::prelude::*;
use bevy::render::options::{Backends, WgpuOptions}; // <- Bevy 0.6
use bevy::render::settings::{Backends, WgpuSettings}; // <- Bevy 0.7

fn main() {
    App::new()
        // バックエンドをVULKANに指定（どれが最適なのかは環境によって異なる）
        .insert_resource(WgpuOptions {
            backends: Some(Backends::VULKAN),
            ..Default::default()
        })
        .add_plugins(DefaultPlugins)
        .run();
}
```

ですが、この方法では**外部GPUが使われず内臓GPUが使用**されました。
もし、**外部GPUで実行したい**と考えているのならば代わりに**片方のGPUを無効にする**方法を提案します。
その場合、バックエンドの設定は削除してください。

デバイスマネージャーから無効にする方法もありますが、以下の方法を推奨します。

`NVIDIA 設定 > ディスプレイモードを管理する > NVIDIA GPU のみ`を選択

これらの方法で落ちることはなくなりましたが、**外部GPUの時のフレームレートが100FPS前後**なのはおかしい。
どなたか原因がわかりましたら教えてください。

あと、**WSL2**でのBevyの起動ができない原因がわかる方がいましたらお願いします。
【パブリッシャー】レポートを複製してみる

ここでは、[Sharperlight](https://sharperlight.jp/)パブリッシャーで作成した公開クエリ(WEBレポート)の複製ができるという事を紹介します。
時に、既存の公開クエリに少し変更を加えて、新しい公開クエリを作成したい場合が多々発生します。最初からクエリ等を作り直すのは面倒であり時間の浪費ですよね。そういった場合、この機能が使用できます。
[Sharperlight](https://sharperlight.jp/)アプリケーションメニューから**パブリッシャー**を起動します。
公開クエリ一覧が表示されたら、複製の基にしたい公開クエリを選択し、右クリックメニューを開きます。
**複製**を選択します。
![2022-04-11 Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/7207727a-1ade-baf9-385c-3db95945f314.png)
すぐに作成完了のメッセージが表示されます。
![2022-04-11 Figure 02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/84ae1a26-86c0-aad1-e3a9-fa775ae58b67.png)
複製された公開クエリのコードは、基にした公開クエリのコードに**２**を付与し生成されます。
このコードは一時的に生成されたものなので、自由に変更可能です。もちろんそのまま使用してもOKです。
![2022-04-11 Figure 03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/e9e2dce2-8214-c118-f1dd-9803e39f7634.png)
:postbox:[Sharperlight](https://sharperlight.jp/)
京大生が0から作る競馬予測

`京大生が0から作る競馬予測`
ここでは京都大学に通う学生二人がPythonを用いて競馬の予想AIを作ろうというものです。筆者はPython経験歴半年の未熟者です。ギャンブル狂で数学がとても得意な京大理学部の友達にPythonを教えながらAIを作っていくという連載にしようと思っています。友人は全くプログラミングの知識がないので最初はかなり初歩的なことから始めようと思っています。ここでは新しくプログラミングを始める人たちの道標になればいいなと思い記録に残そうと思っています。
Cloud WorkflowsからCloudRunを認証付きでリクエストする


# 背景
Cloud WorkflowsからCloudRunを認証付きでリクエストしたい場合です。Cloud Workflowsの起動Service AccountにCloudRunを呼び出すための十分な権限が紐づけられている必要があります。



# 実装

非常にシンプルでOIDCの設定を行えば認証が通ります


```yaml
main:
    steps:
    - call_cloud_run:
        call: http.get
        args:
            url: https://cloud-run-host.a.run.app
            auth:
              type: OIDC
        result: output
    - returnOutput:
            return: ${output}
```

OIDCでログインが認証通っちゃいます。

# 参照

https://cloud.google.com/workflows/docs/calling-run-functions?hl=ja#add_auth_info
M1 Mac Homebrew環境のcabocha gemで `ld: library not found for -lcrfpp` が発生する

# 概要

cabochaをhomebrewでインストールしたらcabocha gemのインストールに失敗する。

# 対応
以下でインストールできた。

```
brew install cabocha
bundle config --global build.cabocha --with-opt-dir="$(brew --prefix)"
bundle
```

もしくは以下。

```
brew install cabocha
gem install cabocha -- --with-opt-dir="$(brew --prefix)"
```

# NOTE
- 僕の環境は `$ echo $(brew --prefix)` => `/opt/homebrew`
- Homebrewでインストールしたライブラリのパスを共通で通す設定がどこかにあるのかもしれないが見つけられなかった。
[自分用メモ] select2のoptions（選択肢）にclassとhtmlを引き継ぐ

select2の選択肢表示に元のoptionタグのcalssとinnerHTMLを引き継ぎたい話
忘れてまた探し回りそうなので自分用コピペメモ

### 注意点
この方法だと、ただの`<option>`でも中にタグがないと
`$(data.element.innerHTML)`のところでjQueryが停止するので、`<span>`要素で囲む
jsを工夫すればいいのでしょうけど、見づらくなりそうなので一旦これでＯＫとする
### コード
```select.html
<select id="select">
  <option><span>ただの選択肢</span></option>
  <option class="bg-warning"><i class="fa-solid fa-user-injured"></i><span> 怪我</span></option>
</select>
```
```select2_init.js
$selectEl = $('#select').select2({
  templateResult: (data, container) => { // 一覧に適用する内容
    if (data.element !== void 0) $(container).addClass($(data.element).attr("class"));
    return data.element !== void 0 ? $(data.element.innerHTML) : data.text;
  },
  templateSelection: (data) => {return data.element !== void 0 ? $(data.element.innerHTML) : data.text}, //選択結果表示に適用する内容
});
```
## 動作確認環境
* Google Chrome 100.0.4896.60 (64bit)
* jQuery 3.6.0
* select2 4.0.13
* select2-bootstrap4-theme 1.5.2
* bootstrap 4.6.0 (今回は関係ないけど一応)
## いつ使う？
select2の項目にfontawsomeのアイコンと、背景色を指定したかった

## 参考文献
* classコピーの話

https://stackoverflow.com/questions/33926375/how-to-pass-option-attributes-to-select2

* HTML渡しの話

https://codepen.io/svutl3cpy7/pen/OEPNPX
jqueryを使用したシンプルな「もっと見る」ボタンの実装

# 実装したもの
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="mdpBXgL" data-user="yoshi090" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yoshi090/pen/mdpBXgL">
  Untitled</a> by yoshida (<a href="https://codepen.io/yoshi090">@yoshi090</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# シンプルな箇所
・「.c5-banner__content」のdivを加えるだけでコンテンツを追加できる。わざわざ「もっと見る」部分のコンテナを作成する必要がない。
```index.html
<div class="c5-banner__content">
  <p>Content 1</p>
</div>
```

・「もっと見る」部分のコンテナの数が設定した数より少なければ「もっと見る」ボタンが非表示になる。下はコンテナの数が4つ以上なら「もっと見る」ボタンを表示する。
```page.js
morenum1 = 3;
if(contentNum1 > morenum1){
 //４つ目以降のコンテンツを隠す
 $('.js-banner1 .c5-banner__content:nth-child(n+' + (morenum1 + 1) + ')').addClass('js-more1').hide();
  moreContents(btn1,content1);
}else{
   //コンテンツが３つ以下ならボタンを隠す
   $(btn1).hide();
}
```

# 参考
https://web.runland.co.jp/blog_cate2/post-4137
Cloud Pak for Data as a Service（CP4DaaS） 利用 の Hints & Tips

Cloud Pak for Data as a Service の利用に関するQiita記事のまとめページです。


### Cloud Pak for Data as a Service について

Cloud Pak for Data as a Service(以降、CP4DaaSと表記)は、IBM Cloud上で提供されるマネージドな データ活用のプラットフォームです。
IBM Cloud上の複数のサービスを組み合わせることで構成されています。
このうち Watson Studio および Watson Machine learning は、Cp4DaaSのコア・サービス*に位置付けられています。
Watson Studioはチームで協業して分析を行うための統合分析環境であり、Watson Machine learningはAIモデルの学習・実行環境です。
*Watson Studio単独でもご利用いただけます。

Cloud Pak for Data as a Service の詳細や環境のセットアップ方法につきましては、@Asuka_Saitoさんの下記記事をご参照ください。

### リンク集

カテゴリごとにQiita記事へのリンクと概要を記載しています。
今後も拡充予定です。

#### 全般
|カテゴリ | 概要 | 記事 |
|-|-|-|
|セットアップ|@Asuka_Saitoさんのシリーズ。セットアップから、各機能の利用方法まで網羅的に紹介|[IBM Cloud Pak for Data as a Serviceを始めてみる(1.プロビジョニング編)](https://qiita.com/Asuka_Saito/items/df3467dc4c9919772c63)|

#### セキュリティ
|カテゴリ | 概要 | 記事 |
|-|-|-|
|ストレージ|Watson Studio プロジェクトのストレージとして使用する IBM Cloud Object Storage の バケット作成先を日本国内に設定する方法|[IBM Cloud の Watson Studio プロジェクトで使用するデータの保存先を日本国内に限定する](https://qiita.com/1000aki/items/1d0776b0a0efebfed82e)|
|ネットワーク|CP4DaaSへログインを許可するIPアドレスを制限する方法|[Cloud Pak for Data as a Service へログイン可能なIPアドレスを制御する](https://qiita.com/1000aki/items/96cc3e3e51a0abce2f16)|
|ネットワーク|IBM CloudのCSE対応サービスへの接続にプライベート・エンドポイントを使用する方法|[Cloud Pak for Data as a Service から IBM Cloud のデータベース・サービスへの接続時、Private Endpointを使用する](https://qiita.com/1000aki/items/fbb512ecc5245ca80815)|
|権限管理|IBM Cloud IAMによるCP4DaaSのアクセス権限 設定例|[IBM Cloudのリソース・グループとアクセス・グループを利用してCloud Pak for Data as a Service へのアクセス制御を行う](https://qiita.com/1000aki/items/c060681cdb5c4b6042af)|

#### Federated Learning
|カテゴリ | 概要 | 記事 |
|-|-|-|
|Federated Learning UI|Watson Studio の UIを使用してFederated Learningを実行|[IBM Cloud の Watson Studio と Watson Machine learningサービスで、Federated Learningを動かす（UI編）](https://qiita.com/1000aki/items/5e5290a7665d63e96727)|
|Federated Learning API|APIを使用してFederated Learningを実行|[IBM Cloud の Watson Studio と Watson Machine learningサービスで、Federated Learningを動かす（API編）](https://qiita.com/1000aki/items/f6200c75e2d710fa2718)|
|Federated Learning UI/API|Federated Learningのトレーニング参加者へ特定の許可IPアドレスを構成|[Cloud Pak for Data as a Service の Federated Learning: Remote Training System へトレーニング参加者の許可IPアドレスを構成する](https://qiita.com/1000aki/items/0ab8df44af672a8a3fc0)|
|Federated Learning API|フレームワークや手法別のPythonサンプルコード|作成中：Cloud Pak for Data as a Service の Federated Learning: フレームワーク別のPythonサンプルコード|

#### MLOps
|カテゴリ | 概要 | 記事 |
|-|-|-|
|Model Inventory|モデルのトラッキングおよびメタデータ管理|[Cloud Pak for Data as a Service でモデルのトラッキングやメタデータ管理にModel Inventoryを使う](https://qiita.com/1000aki/items/0e9704143f62603ea0ac)| 

### 関連資料

Cloud Pak for Data as a Service製品資料
https://dataplatform.cloud.ibm.com/docs/content/wsj/getting-started/welcome-main.html?audience=wdp&locale=en
Azure Pipelineで同じ組織の別リポジトリがcheckoutできない（Git fetch failed with exit code 128）

### またもやドキュメントで躓く…
こういうのはどこに意見送ったら良いんだろうか。ほんとに公式ドキュメントがわかりにくい…
書いてはいるんだけどね…

## やろうとしていたこと
メインプロジェクト（ASPなど）とライブラリ系を分けて別リポジトリで管理、ビルド時に引っ張ってきてもらう。
まぁよくあるような構成

## よくあるやり方
https://docs.microsoft.com/ja-jp/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops
こういう感じですね。
けどうまくいきませんでした。
何度やっても別リポジトリのCheckoutが失敗する…

``` 
remote: TF401019: The Git repository with name or identifier samplelib does not exist or you do not have permissions for the operation you are attempting.
fatal: repository 'https://dev.azure.com/hogeorg/samplelib/_git/samplelib/' not found
##[warning]Git fetch failed with exit code 128, back off 6.747 seconds before retry.
```

リポジトリはもちろんある、URLも間違ってない。あとは権限まわり？けどどこで設定するんだろうか…
ビルドエージェント的なユーザーにリポジトリのread許可を与えても変わらない…
仕方ないといえど、こういう権限まわりってどんどん複雑になっていく印象。まぁゆるければそれに乗じて悪いことするやつがいるからなんだが。

## いきついたところ
https://mikerodionov.com/azure-devops-pipeline-unable-to-checkout-external-repo-remote-tf401019-the-git-repository-with-name-or-identifier-does-not-exist/
なんとか検索しまくってこちらの記事に行き着いた。

どうやらここの設定が、公式で言う

:::note warn
Azure Pipelines Git リポジトリのジョブ スコープ設定を制限Azure Repos提供します。 別のプロジェクトでホストAzure Repos Git リポジトリをチェックアウトするには、アクセスを許可するようにジョブ スコープを制限するを構成する必要があります。 詳細については、「ジョブ承認スコープ の制限」を参照してください。
:::

ことらしい。機械翻訳わけわかめ。英語で読んだほうが早い。
https://docs.microsoft.com/ja-jp/azure/devops/pipelines/repos/azure-repos-git?view=azure-devops&tabs=yaml#limit-job-authorization-scope
なお、公式だとこちら。AzureDevOpsの画面は英語なので日本語で読むべきでなかった…
- ジョブ承認スコープを現在のプロジェクトに制限する
- ジョブ承認スコープを参照先リポジトリAzure DevOps制限する
この２つの設定が、
![スクリーンショット 2022-04-11 10.21.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120789/13748d8f-a689-b993-c2a4-75f3942a9c37.png)
このへんに当たる。
特に
- Limit job authorization scope to current project for non-release pipelines
- Protect access to repositories in YAML pipelines
の２つ

### 先に Organization Settingsを変更する
個別Projectの設定を変えようとしてもデフォルトだとグレーアウトしていて変更できない。
まずはOrgの方を変えないといけないみたい。（こういうのも書いといてほしいな…）

行き着くには
Organization Settings > Pipelines > Settings のGeneralにある。

### 次にProjectの方を変更
**メインプロジェクトの方を変更する**（ライブラリ側は変更しなくても良い）
Project Settings > Pipelines > Settings
にあります。今度はグレーアウトしてないはず。

## やっとビルドできた
同じエラーに遭遇している方のお役に立てれば幸いです。（ほんと時間かかった…）
CakePHP4 containで二つ先のテーブルが取得できない

## 環境

PHP 8.1.4RC1
CakePHP 4.3.6

## 想定

CakePHPではアソシエーションを用いることで以下のようなSQLに対して、次のようなオブジェクトでデータを扱える。

```sql:SQL
SELECT * FROM A JOIN B ON B.id = A.id JOIN C ON C.id = B.id
```

```php:CakePHP
$a->belongsTo('b', ['className'=>'B', 'bindingKey'=>['id'], 'foreignKey'=>['id']]);
$a->b->belongsTo('c', ['className'=>'C', 'bindingKey'=>['id'], 'foreignKey'=>['id']]);
$data = $a->find()->contain(['b', 'b.c'])>all();
```

```php:var_export
object(App\Model\Entity\A) id:0 {
    'id' => 1,
    'name' => 'Aのカラム',
    ...
    'b' => object(App\Model\Entity\B) id:1 {
        'id' => 1,
        'name' => 'Bのカラム',
        ...
        'c' => object(App\Model\Entity\C) id:1 {
            'id' => 1,
            'name' => 'Cのカラム',
            ...
        }
    }
}
```

## 現象

しかし、間で結合しているBはカラムを取得せずに、Cを取得しようとすると、エンティティBが取得できなかった。

```sql:SQL
SELECT a.id, c.id FROM A JOIN B ON B.id = A.id JOIN C ON C.id = B.id
```

```php:CakePHP
$a->belongsTo('b', ['className'=>'B', 'bindingKey'=>['id'], 'foreignKey'=>['id']]);
$a->b->belongsTo('c', ['className'=>'C', 'bindingKey'=>['id'], 'foreignKey'=>['id']]);
$data = $a->find()->contain(['b', 'b.c'])->select(['a.id', 'c.id'])->all();
```

この場合、以下のように取得できるはずが、```$a->b```が存在しない模様。

```php:PHP
$a_id = $a->id;
$c_id = $a->b->c->id; // Attempt to read property "id" on null

var_export($a->b); //=> NULL
```

どういう文言で調べればいいかわからなかったので、```select```にbの適当なカラムを設定することに。
【OSS-DB Silver】Ping-tにはには出てくるけれど教科書(緑本)&問題集(黒本)には出てこない事項

OSS-DB Silver 取得に向けて勉強中です。

Ping-tの最強問題集に取り組んでいます。

前もって学習した
『OSS教科書 OSS-DB Silver ver.2.0対応(翔泳社)』（緑本）と
『徹底攻略OSS-DB Silver 問題集 ver2.0対応(インプレス)』（黒本）
には出てこない事項が、チラホラPing-tの問題に取り上げられているので

Ping-tにはには出てくるけれど教科書(緑本)&問題集(黒本)には出てこない事項
をここにメモしておきます。忘備録。

# スーパーユーザ権限なしでロールを作成

「test」ロールをスーパーユーザ権限なしで作成するSQL。

`CREATE ROLE test NOSUPERUSER;`
`CREATE ROLE test;`

緑本p77(4章標準ツール-4 createuser）にコマンドは紹介されていたが、
SQLは紹介されていなかった。

因みにコマンドだと
`createuser [接続オプション][オプション][ユーザ名]`
で、オプションで下記のように指定する。
`-s、--superuser`　：スーパーユーザ権限を設定する
`-S、--no-superuser`　：スーパーユーザ権限を設定しない（デフォルト）

# リリースノート

問題に「PostgreSQLのリリースノートについて正しいものはどれか。」と取り上げられていた。
（Ping-t 最強WEB問題集OSS-DB Silver(Ver2.0) 問題ID : 12322）

緑本と黒本の「バージョン」の項を確認したが、掲載されていなかった。

リリースノートって何？
↓
・バージョンアップがリリースされるたびに公開されるドキュメント
・バージョンアップに伴う変更点が記載されている

ドキュメントの記載内容は以下。

>このリリースノートには、PostgreSQLの各リリースでなされた重要な変更点が記載されています。 また、主要機能や移行に関する問題点も最初に記載されています。 リリースノートにはごく一部のユーザにしか影響しない変更点や内部的なものであるためユーザには隠れている変更点は記載されていません。 例えば、オプティマイザはほぼすべてのリリースで改良されていますが、この改良はユーザにとっては通常、ただ問い合わせが高速になったと感じるものです。
（引用元：[PostgreSQL 11.5文書](https://www.postgresql.jp/document/11/html/release.html)）

Ping-tの解説は以下。
>PostgreSQLのリリースノートは、メジャーバージョンとマイナーバージョンの各々がバージョンアップし、リリースされるたびに公開されます。マイナーバージョンアップは、バグ修正やセキュリティ修正が主となります。
（引用元：Ping-t 最強WEB問題集OSS-DB Silver(Ver2.0) 問題ID : 12322解説）

# ALTER SYSTEM

問題に「サーバのパラメータ値を変更するALTER SYSTEMコマンドについて正しいものはどれか。」と取り上げられていた。
（Ping-t 最強WEB問題集OSS-DB Silver(Ver2.0) 問題ID : 12224 設定ファイル）

ALTER SYSTEMは、バージョン9.4において新機能として追加された、サーバのパラメータ値を変更するSQLコマンド。

//書式//
ALTER SYSTEM SET パラメータ名 TO {設定値 | DEFAULT};
ALTER SYSTEM SET パラメータ名 = {設定値 | DEFAULT};

Ping-tの解説は以下。
>ALTER SYSTEMコマンドで設定したパラメータは「postgresql.auto.conf」ファイルに書き込まれ、「postgresql.conf」ファイルが読み込まれる際に設定を上書きします。
（引用元：Ping-t 最強WEB問題集OSS-DB Silver(Ver2.0) 問題ID : 12224解説）

# プリペアド文

「PREPARE」コマンドが入っているSQL文で取得できるデータ件数を問う問題が取り上げられていた。

PREPAREはプリペアド文を作成するコマンド。

//書式//
PREPARE プリペアド文の名称 [(引数のデータ型[, 引数のデータ型...])] AS 問い合わせ;

「$n」には引数の値が入る。

プリペアド文を使用すると指定した問い合わせの書き換え・構文の解析・実行計画の作成が一度実行するだけで済むため、性能の向上が図れる。

（メモ：詳細はOneNoteへ）
工場勤務だった私がAndroidエンジニアになるために参考にした教材

# 初めに
今回は工場勤務だった私が、半年の勉強期間でAndroidエンジニア目指した際に、使った本を記事にします
今、Androidエンジニアを目指していたり、これからの選択肢にAndroidエンジニアという道がある人の参考になれば幸いです。

# 勉強の際に使った教材
まずは、Androidプログラミングの基礎を学ぶためにこの本を選びました。
（Androidエンジニアの先輩にオススメして頂きました）
初心者からAndroidプログラミングを学ぶ上でまず必要だったものが、
**言語を覚えること** です。
Androidアプリ制作に必要なソフトである　Android StudioをPCに入れ
「いざ！アプリ作ってやるぞー！」と立ち上げてみても何がなんだかさっぱりわかりません。
また、言語を覚えてもコードの書き方がわからない　なんてこともありました。

ですので、以下のふたつの本を主な資料として勉強しました



https://www.amazon.co.jp/%E4%BD%9C%E3%82%8C%E3%81%B0%E3%82%8F%E3%81%8B%E3%82%8B-Android%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Kotlin%E5%AF%BE%E5%BF%9C-10%E3%81%AE%E5%AE%9F%E8%B7%B5%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%81%A7%E5%AD%A6%E3%81%B6Android%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80-%E9%87%91%E5%AE%8F/dp/4798160148/ref=pd_vtp_sccl_4/356-4762342-0400411?pd_rd_w=lBGdS&pf_rd_p=949e26f5-c2ef-4c96-bfde-49d7614d0317&pf_rd_r=D3J2929N32G5K0B4Z1Z6&pd_rd_r=ee53c72a-846f-453a-9553-3b82b055a59e&pd_rd_wg=q3cm0&pd_rd_i=4798160148&psc=1

こちらは　Android　Studio内でのコードの書き方やコードの使い方を主に勉強ができます。
Androidプログラミング言語の中で　kotlinという新しめな言語に対応したものを選びました。
***


https://www.amazon.co.jp/%E3%82%84%E3%81%95%E3%81%97%E3%81%84Kotlin%E5%85%A5%E9%96%80-%E9%87%8E%E5%B4%8E-%E8%8B%B1%E4%B8%80/dp/4877834273/ref=pd_vtp_sccl_2/356-4762342-0400411?pd_rd_w=k3Zxj&pf_rd_p=949e26f5-c2ef-4c96-bfde-49d7614d0317&pf_rd_r=ET0BJN2BANMBB53FACHM&pd_rd_r=d486b873-a0f5-4a17-9f1e-07c14643d273&pd_rd_wg=vQXFd&pd_rd_i=4877834273&psc=1

こちらはkotlinについての言語の勉強用に選びました
Android Studio内で使用される言語ですのでAndroidプログラミングの基礎になります。


# 終わりに
今回紹介した教材以外にも、たくさんの本や資料があります
私のように有識者におすすめしてもらうもよし
本屋や通販サイトなどで自分に合ったものを探してみるのもよし
本以外にも
　[Android デベロッパーの基礎の Codelab](https://developer.android.com/courses/fundamentals-training/overview-v2)
というAndroidプログラミング勉強用のGoogleが用意したサイトなどを使用して勉強を進めるのもいいかもしれませんね
【メモ】VScode ショートカットキー (mac) 


shift + opt + F　　　 改行（自動調整）
⌘ + opt + ↑↓ 　　　複数行を同時に編集
⌘ + shift + L　　　　　　⌘ + d　　　  同単語を編集
Option + 矢印キー	選択行の移動

Cmd + O　　ファイルを開く
Cmd + N　　新しいファイルを開く
Shift + Cmd + E　エクスプローラーを開く
Shift + Cmd + S　名前を付けてファイルを保存
【メモ】Git関連まとめ


# Gitの基本操作
1.Gitの初期設定
2.ローカルリポジトリを作成
3.ローカルリポジトリへコミット
4.リモートリポジトリにプッシュする（反映させる）


## 1.Gitの初期設定
```
$ git config --global user.name "ユーザー名"
$ git config --global user.email "メールアドレス@xxx.com"
```

## 2.ローカルリポジトリを作成
前提)GitHubでリモートリポジトリを作成
    任意のディレクトリを作成
上記ディレクトリをリポジトリとして初期化する
```
$ git init　
```

## 3.ローカルリポジトリへコミット
```
git add .  //インデックスへファイルを追加
git commit -m "コミットメッセージ"
```

## 4.リモートリポジトリにプッシュする（反映させる）
前提）ローカルリポジトリとリモートリポジトリを紐づけする（ローカルリポジトリ配下）
```
git remote add origin https://github.com/ユーザ/xxx.git
```
リモートリポジトリへプッシュ
```
git push origin master
```














# チーム開発の操作
1.リポジトリをクローンする
2.ブランチを作成
3.ブランチコミット
4.リモートリポジトリにプッシュ
5.コードレビュー・マージ
6.リモートリポジトリからプルする




## 1.リポジトリをクローンする
新たに開発現場に参加することになった場合に
すでに存在するリモートリポジトリからソースコードを取得する必要がある。
リモートリポジトリからファイルデータを取得する作業をクローンと呼ぶ。
```
git clone https://github.com/ユーザ名/xxx.git
```


## 2.ブランチ作成
```
//ブランチを作成
git branch ブランチ名　 
//ブランチを切り替える
git checkout ブランチ名　
//作業中のブランチを表示
git branch 

```
## 3.ブランチへコミット
作業中のブランチにコミットする。
```
git add .
git commit -m "コミットメッセージ"
```

## 4.リモートリポジトリにプッシュ
リモートリポジトリにも作業中のブランチへプッシュする
```
git push origin ブランチ名
```


## 5.コードレビュー・マージ
ブランチでの開発作業が完了→メインとなるブランチに変更内容を取り込み、開発内容を統合する。
特定のブランチの変更内容を別のブランチに取り込むことをマージと呼ぶ。

マージを行うに、GitHub上でプルリクエストと呼ばれる機能を使い、コードレビューを行うことができる。指摘がある場合にはコメントを追加し、作業者に修正をしてもらう。

・レビューの依頼
まずはGithub上で作業したブランチを開き、「New Pull Request」をクリックします。
次にプルリクエストを作成します。
以下の点を確認・入力の上、「Create pull request」ボタンをクリックしてください。
① マージ元・先のブランチ
② レビュアー（レビューを行う人）
③ レビュー内容
④ レビュー・マージ対象のソースコード
・レビューの実施
問題がなければ「Conversation」の「Merge pull request」をクリックしてレビューを完了。
このタイミングでブランチのマージも実施され、作業したブランチの内容がメインブランチに反映される。


## 6.リモートリポジトリからプルする
ブランチをマスターに切り替え、リモートリポジトリのメインブランチからローカルリポジトリに最新の変更内容を取得する。
```
git pull
```


## コマンドまとめ

**ローカル基本操作（記録）**
git add .      ファイルを指定。 「.」は全変更ファイル。
git commit -m  "コミットメッセージ"コミットする


**ローカル基本操作（状況確認）**
git diff リポジトリとワークツリーの差分をチェック
git diff --staged リポジトリとステージの差分をチェック
git status 変更ファイルを確認


**ローカル基本操作(変更履歴)**
git log 変更内容を確認

**ローカル基本操作（元に戻す）**
git restore {ファイル名}　ワークツリーの変更を取り消し
git --staged restore {ファイル名}ステージにあげた変更をワークツリーに戻す


**ブランチ　（分岐して開発）**
git branch ブランチ名　　ブランチ作成
git branch -a githubも含めたブランチ一覧表示
git checkout ブランチ名　　ブランチを変える
git switch ブランチ名　ブランチを切り替える
git switch - ブランチ名　新規のブランチを作成しそのブランチに切り替える
git merge　リモート名/合体したいブランチ名　ブランチをマージ（合体）する
git branch -d　ブランチ名　ブランチを削除する


## その他メモ

* Gitのバージョン情報を表示
```
$ git --version
git version 2.26.2.windows.1
```

* Pull(プル)
　※fetchと　mergeを同時に行うため　、コンフリクト起きる可能性もある（mainブランチいる時など）
git fetch リモート名　リモートリポジトリから情報を取得する（subブランチにいる時など）





参考
https://tech-blog.rakus.co.jp/entry/20200529/git
Streamlitを使ってスマホから開発環境を作る(2022.4.11)

# <h1>背景</h1>
前回まででDjangoやFlaskで簡単なアプリをデプロイしました。「いよいよAIアプリを！」とイキってデプロイしようとしたら、「メモリが足りません」＝＞「バージョンが違います」＝＞「コードが違います」と当たり前のエラーを吐かれて、違う方法を探すのも100n回目でトラウマになりそうです。と思ったらstreamlitなるものがあったのを思い出しました。とりあえず、streamlitを使えばcolab上で開発できそうな噂を聞いたので、どのように出来るか検討したいと思います。<br>

<b>前回までの記事</b>

1. [Flaskメモアプリをデプロイする(2022.4.9)](https://qiita.com/tan0ry0shiny/items/bce772a73ed0a89d9f1d)
1. [HerokuにGitHub経由でDjangoアプリをデプロイする。DBにはPostgreを使う。（2022.3.26）](https://qiita.com/tan0ry0shiny/items/28024ee6f01d24d61e40)

# 目的：スマホでwebアプリの開発環境を作りたい。

## 目標：ネットからアクセスできるurlを発行したい
colabからデプロイする事を目標にします。ここでは、colabに繋がっている間、urlが発行されてそこにアクセス出来れば良いものとします。

# 資料

今回は、SAI-Lab株式会社の代表取締の我妻さんのYouTubeを参考に、そのまま使わせてもらっています。我妻さんはUdemyにも多くの講座を持ってらっしゃいます。大変、分かり易いと思いますので、気になったら覗いてみるのも良いかもしれません。
[【Section1: Streamlitの概要】【Streamlit+Colab】人工知能Webアプリを手軽に公開しよう！ -Udemyコースを一部無料公開](https://youtu.be/QGZ-qqHtnQ4)

# 結果：発行したurlでスマホからアクセスできました

上のYouTubeの通りにすると、下の図の様になります。同じURLをスマホから見ても同じように表示されます。ここだと「http://4ff6-34-86-225-50.ngrok.io 」です。colabのセッションが切れると接続しない様です。これは一時的に発行される物として考えた方が良さそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/3c3267e5-af99-91fb-d5a7-2b8a8b29e105.png)

# <h1>方法</h1>
ここでは、先ほどのYouTubeの大まかな説明をさせて頂きます。詳細は我妻先生がYouTubeで分かり易く説明されています。

ざっくりとした項目は以下になります。
1. streamlitのインストール
1. ngrokの登録とToken発行
1. 実行ファイルの作成
1. アプリの起動とURLの発行

ローカルサーバーを外部公開するため[ngrok](https://ngrok.com/)を使います。私はgoogleアカウントを使って登録しました。登録するとAuthtokenも自動で発行されているみたいで、下図の様に確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/8d9978d0-fb10-a343-364f-faf2bd27b6d7.png)

# <h1>注意点</h1>

1. streamlitをインストールしたらcolabを再起動する。
これに関しては```!pip install stremalit```をした後にcolabのランタイムを再起動して下さい。
1. 発行したURLに接続しようとすると危険だと言われる。
chromeで接続しようとすると、下図の様に注意されます。ここは落ち着いて青丸の「詳細」とクリックします。すると、次の図の様に情報が開かれますので、更に青丸部の「安全でないこのサイトにアクセス」をクリックして下さい。すると、<b>結果</b>にあった図が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/0f3eb97e-1969-2342-522b-a5e1741ab5b0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2496939/ba88cfcb-3c7e-2581-f573-c8c5422d095e.png)

# <h1>感想</h1>
今回はStreamlitを使ってデプロイしてみました。これがデプロイというのかは微妙な所ですが、colabのプログラムをwebブラウザで可視化したり、UIで操作出来るのは嬉しい気がします。探すと、GANを実装してwebブラウザで画像を生成する物もあるようでした。今後、そのような複雑なディレクト構造も挑戦しながら、アプリ開発も出来るようにしたいと考えています。

# <h1>参考</h1>

1. [streamlit](https://streamlit.io/)
1. [ngrok](https://ngrok.com/)
1. [【Section1: Streamlitの概要】【Streamlit+Colab】人工知能Webアプリを手軽に公開しよう！ -Udemyコースを一部無料公開](https://youtu.be/QGZ-qqHtnQ4)

# 次の記事
[Streamlit Cloudで画像認識AIアプリをデプロイする(2020.4.12)](https://qiita.com/tan0ry0shiny/items/c14f02fb1a3d00734348)
Power Automateのコネクタ"Encodian"を使って、PDFから画像を抜き取る

<h2>"Encodian"とは何か？</h2>
拡張されたドキュメント形式の変換、OCR、透かし、データ抽出、校正機能などが出来るアプリケーション。
Power AutomateとPower Appsに対応しています。

https://docs.microsoft.com/ja-jp/connectors/encodiandocumentmanager/#extract-images-from-pdf

PAの編集画面で見てもアクションの種類は30個くらいはありそうです。Encodian側は今後もっと増やすと発表しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624137/81e4f046-519e-43c5-2c6e-86a6a9941514.png)


<h2>画像の切り取り方法</h2>
"PDFから画像を抽出する”というアクションがあるのでそれを選択します。
抽出するページ・切り取り座標を入力する箇所があります。座標は左下がスタートになるので、いい感じに抽出できる数字を入力します。


![mceclip2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624137/e71797be-7ecb-e889-d672-4d9489e1fb86.png)

https://support.encodian.com/hc/en-gb/articles/360006998058-Extract-Images-from-PDF

<h2>切り取った画像を保存する</h2>
Encodianの作業だけだとファイルは保存されないので、OneDrive等のファイルの作成を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624137/1b1339c6-b6c2-becc-ac85-b90c3555cb4f.png)

シンプルなフローだと大体1分以内には完了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624137/f2589de3-ba58-2fb0-9889-1337c51dde84.png)

<h2>ビジネスにおける活用例</h2>
私の場合ですが、エクセルのレポートを自動配信する際にメール本文にトップの画像を貼り付けることで
重要な箇所はメールを開かなくても確認できる、といった運用をしています。<br>
ほかにもＱＲコードやバーコードの生成もできるようです。

<h2>まとめ</h2>
日本では話題にしている人がほとんどいないEncodianですが、今後もさまざまな機能が追加されそうです。
Power Automate Userは要チェックかも。<br>
フリートライアルもあり、一か月で500アクションが試せます。無料プランでも50回までなら実行できるので、ちょこっと使うだけでも役立つかも。
【Crystal】インタープリターを有効にしたCrystalをhomebrewでインストールする

## はじめに

Crystal言語で公式にインタープリターが導入されたが、Crystal 1.4.0 ではまだ標準搭載されておらず、オプションを指定してソースコードからコンパイルする必要があるために試していない人は多いと思う。

## brew edit

しかし、brew edit を利用すればhomebrewのコンパイルオプションを変更することができる。

```
brew edit crystal
```

（ちなみに上記はcrystalというディレクトリが存在するディレクトリで実行すると期待したように動かないので、気をつけてください。）

`interpreter=true` を追加する。下はCrystal 1.4.0の場合

```diff
@@ -82,6 +82,7 @@ class Crystal < Formula
     # Build crystal
     crystal_build_opts = []
     crystal_build_opts << "release=true"
+    crystal_build_opts << "interpreter=true"
     crystal_build_opts << "FLAGS=--no-debug"
     crystal_build_opts << "CRYSTAL_CONFIG_LIBRARY_PATH="
     crystal_build_opts << "CRYSTAL_CONFIG_BUILD_COMMIT=#{Utils.git_short_head}" if build.head?
```

これで

```sh
brew reinstall crystal
# brew reinstall crystal --build-from-source
```

すればよい。

## Formula を編集しても大丈夫？　次回 brew update するときにトラブルにならないか？

https://docs.brew.sh/FAQ#can-i-edit-formulae-myself

> As a bonus, brew update will merge your changes with upstream so you can still keep the formula up-to-date with your personal modifications!

> おまけに、brew updateがあなたの変更をupstreamにマージしてくれるので、あなたの個人的な修正でformulaを最新に保つことができます!

なので、公式では変更しても brew update は問題なく動く風の記載はある。macOSユーザーではないので詳しく調査していない。自動でrebaseしてくれるのかしらん。どうなんだろう。

## それでも壊れたら

homebrewのレシピはgitで管理されているので、

```
brew --prefix
cd $(brew --prefix)
find . -name crystal.rb
```

とかして、homebrew-core のディレクトリに移動し、homebrew-core をgitでゴニョゴニョすれば直ると思う。

この記事は以上です。
heroku Mixed Content: The page at 'https://appname.herokuapp.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://appname.herokuapp.com/api/photos?page=1'. This request has been blocked

### herokuにdeployしてアプリを開いてみるとconsoleにて以下のエラーが発生し、画面が正しく表示されない

```
Mixed Content: The page at 'https://appname.herokuapp.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://appname.herokuapp.com/api/photos/?page=1'. This request has been blocked
```


### 以下のURLがおかしいみたい

```
http://appname.herokuapp.com/api/photos/?page=1
```

### クエリ前の「/」を省く

```
http://appname.herokuapp.com/api/photos?page=1
```

### herokuに再度deployしてみるとエラー解消!!!
Jetson Nanoへのtorchaudioインストール

## summary
[ここ](https://drive.google.com/drive/folders/1RbrIAIm5qjH3hPPYxSwH9SYAvK7h93Bq?usp=sharing)でtorch1.10, torchaudio0.10, torchvision0.11のwheelを公開しています。torch, torchvisionのwheelは[ここ](https://qengineering.eu/install-pytorch-on-jetson-nano.html)から拝借しました。

テスト環境は次の通りです。
- Jetson Nano 2GB / 4GB
- Jetpack 4.6.0 (Python 3.6)
## 背景
Jetson Nanoでtorchaudioを使いたかったのですが、公式にはdockerを使う方法しか乗っていません。wheelがどこかに転がっていないか結構探したけど見つかりませんでした。
おとなしくdockerを使え、という話でもありますが、自分でビルドしてみました。ちなみに、CUDAを使わない場合は[ここ](https://github.com/KumaTea/pytorch-aarch64)のwheelを使えます。
## ビルド手順

[Jetson用PytorchのDockerfile](https://github.com/dusty-nv/jetson-containers/blob/e6047853df66260bf567e820c24747bcdceebb4a/Dockerfile.pytorch#L90)や、[JetsonNano用のtorch/torchvisionwheelを公開しているサイト](https://qengineering.eu/install-pytorch-on-jetson-nano.html)の手順を参考にしました。
aptで入れたcmakeを使おうとするとバージョンが古すぎる、と怒られるので、まずcmakeを新しくします。2022/4/7現在、最新版の[3.23.0にするとtorchaudioがmakeできない](https://github.com/pytorch/pytorch/issues/74985)ので、少し前のやつ(3.22.2等)を使います。
```
wget https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2.tar.gz
tar zxvf cmake-3.22.2.tar.gz
cd cmake-3.22.2
./bootstrap
make
sudo make install
```
最後に、torchaudioをクローンしてビルドします。
```
git clone -b release/0.10 https://github.com/pytorch/audio.git torchaudio
cd torchaudio
sudo apt-get install clang
sudo su
export USE_FBGEMM=OFF
export BUILD_CAFFE2_OPS=OFF
export USE_FAKELOWP=OFF
export BUILD_TEST=OFF
export USE_MKLDNN=OFF
export USE_NNPACK=OFF
export USE_XNNPACK=OFF
export USE_QNNPACK=OFF
export USE_PYTORCH_QNNPACK=OFF
export USE_CUDA=ON
export USE_CUDNN=ON
export TORCH_CUDA_ARCH_LIST="5.3;6.2;7.2"
export USE_NCCL=OFF
export USE_SYSTEM_NCCL=OFF
export USE_OPENCV=OFF
export MAX_JOBS=4
export PATH=/usr/lib/ccache:$PATH
# set clang compiler
export CC=clang
export CXX=clang++
sudo ln -s /usr/lib/aarch64-linux-gnu/libcublas.so /usr/local/cuda/lib64/libcublas.so
export CUDACXX=/usr/local/cuda-10.2/bin/nvcc
python3 setup.py clean
python3 setup.py bdist_wheel
```
`dist/`以下にwheelができているはずです！
ちなみに、私ははじめ手元にあったJetsonNano2GBでビルドを試みたのですが、RAMをすぐさま使い切った後フリーズしてしまったので4GBに変えて作業しました。
【データ抽出/SQL】商品ごとに商品毎の平均単価より高い商品を抽出する

# 相関サブクエリとは
WHERE句に外部クエリからの値を使用するサブクエリ。
外部クエリによって処理される各行を一行ずつ取り出して、
相関サブクエリ内の指定した位置に一行ずつ代入される。



# 相関サブクエリの実際の動き
相関サブクエリは、小分けしたグループ内での比較をする時などに便利。

具体例として、以下のテーブルを使用して、
**各`shouhin_bunrui`毎の平均単価よりも、`hanbai_tanka`が高い商品のデータを抽出**してみる。
![9fa808574b05b0ebdd9febaa20460f54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/f21c875b-8973-d184-8cea-1cf3cc8ce1f3.png)
## 使用クエリ
```SQL
select
    shohin_mei
    , shohin_bunrui
    , hanbai_tanka
from
    shohin s1
where
    hanbai_tanka > (
                     select
                         avg(hanbai_tanka) 
                     from
                         shohin s2 
                     where 
                         s1.shohin_bunrui = s2.shohin_bunrui
                     group by
                         shohin_bunrui
                   );
```
## 抽出結果
![4f7bb227eb6bcc65f86fd448d98ebed8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/883573/6efede15-9ae0-97ac-d973-29551fd70dfa.png)
## 処理の流れ
1. サブクエリの中で`shohin_bunrui`毎に平均`hanbai_tanka`を算出
2. 外部クエリで取得したデータ（=商品毎の`hanbai_tanka`）一つ一つを、
サブクエリ内の`shohin_bunrui`毎の平均`hanbai_tanka`と比較していく。
（同じ`shohin_bunrui`のデータ同士を比較する。）
3. `shohin_bunrui`毎の平均値よりも、`hanbai_tanka`の高い商品が抽出される。

### 抽出結果の具体例

shohin_idが1のTシャツについて見てみる。
1. `shohin_id`が１のTシャツは`shohin_bunrui`が衣服で、`hanbai_tanka`が1000。
2. 相関サブクエリの中では、衣服の`avg(hanbai_tanka)`は2500と算出されている。
3. 相関サブクエリ内で、`shohin_bunrui`毎に1.の数値と2.の数値を比較している。
4. Tシャツの`hanbai_tanka`は、衣服の平均`hanbai_tanka`よりも小さいため、データが抽出されなかった。
Laravel初心者わい「このベストプラクティス集ええやん」

## はじめに
こんにちは。WEBエンジニアのmasakichiです。

Laravelって自由度が高く拡張しやすい反面、「コードの書き方が煩雑化しやすい」と感じたことはありませんか？

そんな方に向けたおすすめのGitHubリポジトリ[laravel-best-practices](https://github.com/alexeymezenin/laravel-best-practices)を共有したく記事にしました。

## 記事の対象者
- これからLaravelを勉強したいと思っている人
- Laravelの経験はあるけど、より良質なコードを書きたいと思っている人
など

## この記事を書いた経緯
ネット上にはさまざまなLaravelのベストプラクティスがありますが、個人的にいちばんシンプルですっきりとまとまっているのが今回紹介するものです。
同ベストプラクティスをすでに共有しているQiita記事や他のネット記事もたくさんあると思いますが、改めていまLaravelを学んでいる同士にこのベストプラクティスの存在を知って欲しいなと思い執筆しました。

## laravel-best-practicesとは？
- [RealWorld](https://github.com/gothinkster/realworld/)のプロジェクトとして実装された[laravel-realworld-example-app](https://github.com/alexeymezenin/laravel-realworld-example-app)に利用されているベストプラクティス集
- 日本語にも翻訳されており、多言語対応している

**日本語訳のリンク先**
[https://github.com/alexeymezenin/laravel-best-practices/blob/master/japanese.md](https://github.com/alexeymezenin/laravel-best-practices/blob/master/japanese.md)

## ベストプラクティスを読んだ所感
ベストプラクティス集はさまざまな形式で共有がされていますが、個人的には今回紹介したものが簡潔でわかりやすくおすすめだな感じました。
特に、ベストプラクティスが1ページにまとまっているのが好印象です。複数ページかに分かれていると追うのが大変なので。

いまLaravelの学習を進めている同士は是非いちど目を通して見てください。
また、できることなら過去に作ったプロジェクトをベストプラクティスを参考にリファクタリングなどすると尚更勉強になると思います。
【jQuery】submit()を使ったのにフォームのPOSTが出来ない

## まえがき
フォームで送信用のボタンのクリックイベントを用いた際に発火は確認できているのに送信が出来ず詰まっていた。


## コード(送信できないパターン)
＊送信ボタン
```
<input id="submit" type="submit" value="確認画面へ">
```

＊送信処理
```
     var clickCount = 0;
        $('#submitForm').click(function() {
            clickCount++;
            if (clickCount === 1) {
                $(this).closest('form').submit();
                return false;
            } else {
                setTimeout(function() {
                    clickCount = 0;
                }, 2000);
            }
        });
```
## 原因
POST送信のボタンに使用したid名がsubmitだったため。


## まとめ
送信用の要素のidやnameにはsubmitを使用しない。
今回はsubmitFormという名前にして回避した。(プロジェクト内で他のフォームに同様のものがあったため)


## 参考
jQueryで$(form).submit()でフォームが送信されない場合の対処法
https://yuzurus.hatenablog.jp/entry/jquery-disable-submit
2022/4/10 atcoder メモ

# D - Cylinder
- ランレングス符号化　：　データの圧縮アルゴリズムで、要素×長さで表す
- pythonのcollectionの一種であるdequeを使用
    - 要素の追加・取り出し（削除）・アクセス（取得）が両端のみ → deque
    - 両端以外の要素に頻繁にアクセス → リスト

> Pythonの標準ライブラリcollectionsモジュールのdeque型を使うと、データをキューやスタック、デック（両端キュー）として効率的に扱うことができる。
>collections.deque --- コンテナデータ型 — Python 3.7.3 ドキュメント
>組み込みのリストlistをキューやスタック、デック（両端キュー）として使うことも可能だが、リストでは先頭の要素に対する削除や追加（挿入）は処理速度が遅いためdequeのほうが効率的。なお、dequeには、両端以外の要素へのアクセスが遅いというデメリットもあるので注意。
iOS用の画像分類モデルをTuriCreateで作る

# iOS用の高品質画像分類モデルを作ります

# CreateMLだけではない

Appleの機械学習モデルを作るフレームワークといえば、CreateMLがあります。
GUIで簡単にモバイル用モデルを作成できます。が、大量のデータセットでCreateMLの画像分類学習を回そうとすると、なぜか１０iterで止まるという現象がありました。
こんなCreateMLでうまくいかない時に使えるのが、turicreateです。
TuriCreateも、Appleがリリースしている機械学習フレームワーク。
Pythonで画像分類などのモデルが作れ、iOS用のモデルとして保存できます。

# 方法

必要なものをインストール

```shell
pip install turicreate==6.4.1
# The wrong version of mxnet will be installed
pip uninstall -y mxnet
# Install CUDA10-compatible version of mxnet
pip install mxnet-cu100
# install Skafos python sdk
pip install skafos
pip intall coremltools
```

インポートとGPUの設定

```python
import urllib
import tarfile

import coremltools
import turicreate as tc
tc.config.set_num_gpus(-1)
```

データセットはCreateMLやImageNetの画像分類の形式と同じで、
クラスごとにディレクトリを作ってそこに画像を入れておきます。

```

|
|__chocolate
|    |__image1_0.jpg
|    |__image1_1.jpg  
|
|__cookie
|    |__image2_0.jpg
|    |__image2_1.jpg
|
|__lolipop
|    |__...
...
```

上記のデータセットディレクトリから、sframeというturicreate用のデータ形式を作ります。

```python
data = tc.image_analysis.load_images('./dataset', with_path=True, ignore_failure=True)
```

sframeにラベルの列を与えます。
ラムダ式でif文を繰り返して、画像ファイルのパスのディレクトリ名からラベルをつけています。
クラスラベルが多い時は、if文のネストを深くします。

```python
data['label'] = data['path'].apply(lambda path: 'chocolate' if '/chocolate/' in path else ('cookie' if '/cookie/' in path else 'lolipop'))
```

データセットを学習用と検証用に分割します。

```python
train_data, test_data = data.random_split(0.8)
```

学習します。事前トレーニングされたモデルのファインチューンが行われます。３０iterだと数分です。

```python
model = tc.image_classifier.create(
    dataset=train_data,
    target='label',
    model='resnet-50',
    batch_size=32,
    max_iterations=30
)
```

CoreMLModelとしてエクスポートします。

```python
res = model.export_coreml("candies.mlmodel") 
```

より詳細なドキュメント。

https://apple.github.io/turicreate/docs/userguide/image_classifier/

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
JetsonNanoが起動しなくなったのでリカバリーモード＋SDK Manager on Dockerで復帰

SDカード抜き差ししてたり、初期化を繰り返していたらJetson Nanoが急に起動しなくなりました。具体的には電源を入れてもNVIDIAのロゴすら画面に表示され無い状況となってしまいました。

ネットで調べると該当しそうな記事が。ありがとうございます。

https://ebi-works.com/jetson-recovery/

この記事の通り進めればきっと上手くいくはずです。ただ、一部条件が違ったためDockerを使ってCLIから処理を進める方法としたのでこちらの記事を書いておきます。

私も基本は上記の記事の通り進めました。

- Linuxの物理マシンを準備
- 「FC REC」と「GND」をリカバリーモードに設定しLinuxに接続
- `lsusb` コマンドで接続認識を確認
- NVIDIAアカウントへの登録
- sdkmanagerをaptでインストール


と、途中までは順調だったのですが、

# `Target Operating System` という項目が出てこない事象

ウィザードの以下の部分が選択できない事象に当たりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/548a9437-bfba-0bb9-2a7b-485625f536b9.png)


以下に書かれている通り色々な条件で出ないようです。
Linuxのバージョンだとすると今使っているマシンを入れ直すのは厳しい。

https://forums.developer.nvidia.com/t/sdk-manager-does-not-let-me-select-target-operating-system/82609/6



# Dockerで実行
ということでDockerで実行することにしました。

[こちらのページ](https://developer.nvidia.com/nvidia-sdk-manager)に書かれている方法で、Dockerからsdkmanagerが利用できます。この場合はLinuxのバージョンの問題はクリアできます。


イメージをダウンロードして `docker load` で取り込む形になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/b80ea598-b6d2-63aa-743a-b8aba4681411.png)


Dockerのsdkmanagerが使えるようになったら、以下のコマンドを実行します。


```sh
docker run -it --privileged -v /dev/bus/usb:/dev/bus/usb/ \
  --name JetPack_NX_Devkit \
  sdkmanager --cli install \
  --logintype devzone \
  --product Jetson \
  --version 4.6.1 \
  --targetos Linux \
  --target JETSON_NANO_TARGETS \
  --flash all \
  --license accept \
  --staylogin true \
  --datacollection enable \
  --exitonfinish
```

NVIDIAアカウントへのサインイン等、ウィザード通りに進めると以下のような画面となり、Jetson NanoにOSがインストールできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/80499280-2af3-1862-b197-1a52ada4bce4.png)

なお、 `Flash Jetson OS` でエラーが出たのですが、その場合は以下にあるようにホストのLinux側に `qemu-user-static` をインスト－ルすることで解決しました。

https://forums.developer.nvidia.com/t/failed-to-flash-with-sdk-manager-docker-version/170549

これで正常終了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/db89a625-f47c-30c0-ebe2-66b71e0ab32b.png)



# 起動してみると
NVIDIAのロゴが出るようになりました。が、起動しない。
MicroSDにJetsonのOSを書き直して起動してみると上手く起動しました。ちょっとこの辺りは原因追えてないのですが、事象として書いておきます。
SSH接続（ターミナル）

### SSH接続
```
ssh -i <秘密鍵のパス> ユーザー@アドレス

例）
ssh -i /Users/hoge/〇〇.pem user@localhost
```

### pemファイルの権限
pemファイルの閲覧権限を変更していないとセキュリティが低いと、SSH接続をした際にエラーが出る

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/hoge/〇〇.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/hoge/〇〇.pem": bad permissions
bitnami@52.199.244.147: Permission denied (publickey).
```

これが出たらこの記事が参考になった。
[ファイルのパーミッション設定](http://www3.u-toyama.ac.jp/furuta/unix-permit.html)

対象のファイル（今回はpemファイル）の権限をターミナルで変更する。

```
chmod 600 Users/hoge/〇〇.pem
```

これで再度SSH接続すると接続できた。
メンテナンスウィンドウを確保したバッチ処理計画

ウェブサービスであっても、ウェブアプリだけで全ての処理を完結できません。大抵、バックでいくつかのバッチ処理が必要になってきます。スモールスタートだと1台だけのサーバでウェブサービスが実行されていて、そこに crontab でバッチ処理を起動したりするわけですね。だんだんサービスが成長してくるとウェブサービス側も複数台構成になるし、バッチ処理は専用のサーバに分けたりします。更に成長してくるとcrontabでは機能不足となってジョブ管理システムを導入したりもします。システムの正常な成長なのでいいのですが、意外と見落とされがちなのがメンテナンスウィンドウの確保ではないかと思います。

バッチ処理を実行するタイミングを決定するとき、大体次のようなことを考えます。

* アクセスが少なくてユーザ影響が少ない時間帯
* 他の処理があまり動いてなくて DB 負荷の軽い時間帯
* 前提処理があって、その処理が確実に完了する時間
* 他のシステムとの連携があって、連携タイミングまでに完了する時間

ここに「メンテナンスウィンドウを確保する」を付け加えようという話です。

メンテナンスウィンドウが確保されていないとどうなるかというと、24時間365日つねになんらかのバッチ処理が実行されている状態に陥る可能性があります。最初の内は時間に隙間が空いていたとしても、サービスの成長に伴ってデータが増えるとバッチ処理時間も長くなっていきますからね。

24時間365日バッチ処理が実行されていると、システム全体のメンテナンスが行えなくなります。ウェブアプリのサーバは複数台構成になってるでしょうからメンテナンスも容易ですが、DB サーバやジョブ管理サーバ自身はどうにもなりません。

メンテナンスによるサービスダウンと言っても、実際に必要なのは数秒程度の時間だったりもします。前後の作業はもちろんありますが、その間はサービスは止めなくてもよかったりしますよね。そしてウェブサービスの場合、最悪数秒程度なら落としてもなんとかなったりもします。そのサービスの重要度によりますが。でもバッチ処理が24時間動きっぱなしだと、その数秒程度のメンテナンス時間すら確保できなくなってしまう。

例えば「日次バッチは0時から6時の間に開始して長くても数時間で完了するように。週次バッチは月曜から土曜に実施し、日曜には行わない」というルールを設けておくと、日曜の午後はメンテナンス作業に当てられるわけですね。これではインフラ担当者が必ず日曜出勤になってしまうわけですが、そこはまあシステムと労務管理で相談してもらうとして。

こうして書き出してみるとメンテナンスウィンドウの確保なんて当たり前のことのようですが、日々の業務に追われながらシステムがだんだん成長していっていると、意外と見落とされてしまうことかなと思います。というか、実際に前職でこの罠に陥ってしまってにっちもさっちもいかなくなってしまった経験から書いてみた次第です。
AtCoder Beginner Contest 247　A~D　4完記事

アルゴリズムの学習改善のための自身の備忘録及び学習の一環として記事を書くことにしました.
読んでくれた方で何かありましたら気兼ねなくコメントしてください.お待ちしております.

# [A - Move Right](https://atcoder.jp/contests/abc247/tasks/abc247_a)

## 問題文　概要
$4$桁の$0,1$からなる文字列を右に移動し,先頭に$0$を挿入.上$4$桁を出力する

## 制約と入力
制約
>$S$は$0,1$からなる長さ$4$の文字列

入力
>入力は以下の形式で標準入力から与えられる。
>$S$

## 考察
問題より,先頭の$0$は固定である.
与えられた文字列の末尾を除く$3$文字をそのままの順序で出力する.


## サンプルコード
```python:a.py
s=input()
print('0'+s[0]+s[1]+s[2])
```

# [B - Unique Nicknames](https://atcoder.jp/contests/abc247/tasks/abc247_b)

## 問題文　概要
あだ名は苗字または名前と等しいものを定義する.
あだ名が一意か判定する.

## 制約と入力
制約
>$2\leq N \leq 100$
>$N$は整数である。
>$s_i,t_i$は英小文字からなる$1$文字以上$10$文字以下の文字列である。

入力
>入力は以下の形式で標準入力から与えられる。
>$N$
>$s_1 \ \ t_1$
>$s_2 \ \ t_1$
>$ \vdots $
>$s_N \ \ t_N$

## 考察
全体の出現回数が$1$回であればあだ名として成立する.
苗字と名前が同じである場合,全体での出現回数が$2$回であればよいことに注意したい.


## サンプルコード
```python:b.py
n=int(input())
ST=[]
for i in range(n):
    s,t=map(str,input().split())
    ST.append(s)
    ST.append(t)
for i in range(n):
    if (ST.count(ST[2*i])!=1 and ST.count(ST[2*i+1])!=1) or ():
        if ST[2*i]==ST[2*i+1] and ST.count(ST[2*i]):
            continue
        print("No")
        exit()
print("Yes")
```

# [C - 1 2 1 3 1 2 1](https://atcoder.jp/contests/abc247/tasks/abc247_c)
## 問題文　概要
* $S_1=1$
* $S_n=S_{n-1},n,S_{n-1}$

を定義する.
$S_N$を求める.


## 制約と入力
制約
>$N$は整数
>$1 \leq N \leq 16$

入力
>入力は以下の形式で標準入力から与えられる。
>$N$

## 考察
$S_0$を空とする.
以降$S_n=S_{n-1},n,S_{n-1}$として順に定義し$S_n$を求める.
これは,$S_1=1$になるため問題に反しない.

## サンプルコード
```python:c.py
n=int(input())
s=[]
for i in range(1,n+1):
    s=s+[i]+s
print(*s)
```


# [D - Cylinder](https://atcoder.jp/contests/abc247/tasks/abc247_d)
## 問題文　概要
* $1$:数$x$を右から$c$回挿入する.
* $2$:左から$c$回取り出し,取り出した合計の数値を出力.

この操作を全てのクエリを実行する.


## 制約と入力
制約
>$1 \leq Q \leq 2 \times 10^5$
>$0 \leq x \leq 10^9$
>$1 \leq c \leq 10^9$
>$2 \ c$のクエリが与えられるとき、筒の中には$c$個以上のボールがある
>入力に含まれる値は全て整数である

入力
>入力は以下の形式で標準入力から与えられる。
>$Q$
>$query_1$
>$\vdots$
>$query_Q$

$i$番目のクエリを表す$query_i$は以下の$2$種類のいずれか
>$1 \ \ x \ \ c$

>$2 \ \ c$

## 考察
挿入と出力を愚直に行うと計算回数は$10^5 \times 10^9 = 10^{14}$となるので,実行時間が間に合わない.
$x,c$を$1$つのまとまりとして扱う.
出力の際,充足するまで取り出し続ける.超過分は左から挿入する.

## サンプルコード
```python:d.py
from collections import deque
q=int(input())
Deque=deque()
for i in range(q):
    query=list(map(int,input().split()))
    if query[0]==1:
        Deque.append([query[1],query[2]])
    else:
        cnt=0
        j=query[1]
        while j:
            POP=Deque.popleft()
            if POP[1]<=j:
                cnt+=(POP[0]*POP[1])
                j-=POP[1]
            else:
                cnt+=(POP[0]*j)
                POP[1]-=j
                j=0
                Deque.appendleft(POP)
        print(cnt)
```
LaravelのAPIのエラーレスポンスをカスタマイズ

# はじめに
Laravelのエラーレスポンスについて書いている記事はいくつか見かけましたが、どれも自分には合わないと感じて自分なりに色々と試してみました。
ソースコードを追ってみて個人的なベストプラクティスを見つけたので共有します。 


# APIで起きたエラーをJsonで返す
```php:app/Exceptions/Handler.php
protected function prepareResponse($request, Throwable $e)
{
     // /apiから始まるエンドポイントはjsonでエラーを返す
    if ($request->is('api/*')) {
        return parent::prepareJsonResponse($request, $e);
    }
    return parent::prepareResponse($request, $e);
}
```
ここで一度APIにリクエストを送り、エラー発生させてみてください([`abort()`](https://www.larajapan.com/2020/07/25/abort%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88/)が便利)。
下記のようなエラーが返ってくるかと思います。
```json:エラーレスポンス
{
    "message": "エラーのテストです",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",
    "file": "/Applications/MAMP/htdocs/project/vendor/laravel/framework/src/Illuminate/Foundation/Application.php",
    "line": 1122,
    "trace": [
        {
            "file": "/Applications/MAMP/htdocs/project/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php",
            "line": 44,
            "function": "abort",
            "class": "Illuminate\\Foundation\\Application",
            "type": "->"
        }
     ]
}
```

# APIのエラーメッセージをカスタマイズ
Jsonで返ってきたレスポンスをカスタマイズします。`convertExceptionToArray()`という関数をオーバーライドします。
自分は下記のようにカスタマイズしました。
```php:app/Exceptions/Handler.php
protected function convertExceptionToArray(Throwable $e)
{
    return [
        'message' => $e->getMessage(),
        'exception' => get_class($e),
        'status_code' => $this->isHttpException($e) ? $e->getStatusCode() : 500,
    ];
}
```
レスポンスを見てみると、このように上手くカスタマイズできました。
```json:エラーレスポンス
{
    "message": "エラーのテストです",
    "exception": "Symfony\\Component\\HttpKernel\\Exception\\HttpException",
    "status_code": 500
}
```

# 参考
https://github.com/laravel/framework/blob/8.x/src/Illuminate/Foundation/Exceptions/Handler.php
Apple Low Latency HLS のオリジンサーバを自作して試した話

## 初めに

WWDC 2020 で Apple Low Latency HLS が GA してから、はや 2 年。
あまりサポートしているという情報をきかず、Appleのツールでしか確認できてませんでした。
LDASH (CMAF-ULL) はよく聞きますが、LL-HLS の話は全然されてません。

実際にどのようにプレイリストを作るのか分かれば、自分で使えるかも?
というわけで、週末の時間を使って作ってみました。

## 前提

### LHLS とは?

コミュニティベースで生まれた規格で、CMAF-ULL との互換のある規格です。

https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md

EXT-X-PREFETCH タグによる、プリロード対象を Chunked transfer で読むという方法で
低遅延を実現しており、Appleを対象としてない、独自の低遅延HLSはコレです。

### Apple Low Latency HLS とは?

Apple が提唱している 低遅延HLS の規格となります。
2020 年に beta が取れて、Apple 製のプレイヤーでは受けられるようになっています。

https://developer.apple.com/documentation/http_live_streaming/enabling_low-latency_http_live_streaming_hls

特徴は以下の通りです。

* partial segments: 1セグメントを複数の部分セグメントに分けられます
* Playlist delta updates: 部分セグメント単位でのプレイリスト更新が可能
* Blocking of playlist reload: 当該セグメントが更新されるまで、リクエストをブロック
* Using preload hints: 先読みをサポート
* Rendition reports: マスタープレイリストを参照せず他プレイリストの切り替え

要するに、今までの 1 セグメントを分割可能になり、分割した単位で更新が可能で
プレイリストがアップデートされるまで、リクエストをロングポーリング可能になった
というものになります。

これらをオリジンが実装する必要があり、上記の LHLS のような単純なものではないのが欠点です。

## 実装

ここでは、ライブ再生に必要な以下の 3 つをサポートしてみます。

* partial segments
* Playlist delta updates
* Blocking of playlist reload
* preload hints
(preload hints は実際に使ってるクライアントを見たことないので、出すだけ出します)

実際に作ってみたのが、以下のリポリトジになります

https://github.com/monyone/biim

python 製のツールで、標準入力で受け取ると、HTTPサーバになり
オンメモリで /playlist.m3u8 にプレイリストを出力します。

一応、以前に [node.js 製で作ったもの](https://github.com/monyone/node-ts-fragmenter) を移植した形です。
node.js でも、Python でもやっていることは同じですので、好きな方をみてください

やっていることは超単純で、TS をデマックスして、キーフレームでセグメント分割します。

## 評価

実際に LAN 内で通信したところ、delta update と bloking request により
従来の TARGETDURATION より高い頻度で更新が出来ている事が確認できました。

遅延も 1 秒までは Apple のプレイヤーでは抑える事が出来そうです。
1 秒はプレイヤーが強制的にバッファするためになります。

## 余談

なかなかルールが分からず、mediastreamvalidator のお世話になりました。
Safari でエラー表示してくれればよいのですが...

## あとがき

LHLS の方が、オリジン, ストレージ, CDN が chunked-transfer をサポートすれば
楽にスケールするため、あまり乗り気ではないというのが、現状なのかなと思いました。

CMAF-ULL を考えると Apple を無視して LHLS にするのが得策なのかもしれないですね。
Capistrano で長時間バッチがこける話

## Capistrano によるデプロイ

Capistrano でデプロイすると、こんな感じのディレクトリ構成になります。

```
.
├── current -> releases/20220405000000/
├── releases
│   ├── 20220401000000
│   ├── 20220402000000
│   ├── 20220403000000
│   ├── 20220404000000
│   └── 20220405000000
└── shared
```

デプロイされると releases/ に現在の日時でディレクトリが作られ、current は最新 releases へのシンボリックリンクになり、アプリケーションは current で実行されます。

アプリケーションにはウェブアプリだけではなくバッチ処理も含まれます。バッチ処理を実行する際も current ディレクトリで行うわけですね。ここまでは問題ありません。

## 問題点

問題はバッチ処理が長時間にわたる場合です。1日1回デプロイをしていたとして、5日後(デフォルトの keep_releases)にはかつて current であった releases 下のディレクトリは消えてなくなります。バッチ処理が5日以上かかる場合、実行時のディレクトリが消えてしまうわけですね。1日に複数回デプロイされる場合にはもっと早く実行時ディレクトリが消えてしまいます。

バッチ実行時のディレクトリが無くなっても、バッチ処理自体には即座には影響はありません。必要なソースコードはメモリ上に読み込まれていますから。ただ、想定外の事態であることは確かなので、いろいろ問題が起こったりします。経験上、以下のようなことが起こります。

* 遅延読み込みしてるソースコードが読めなくなる。
* shared/ からのファイル読み込みに失敗する。
* shared/ にファイル出力しようとして失敗する。もしくは消えた releases ディレクトリが復活する(mkdir -p付きで出力される場合)

## 対処法

* バッチ処理を分割実行出来るようにして、そもそも長時間実行しないようにする。最も理想的な対応策でしょう。
* 長時間バッチ専用の環境を用意する。バッチ処理起動時にインスタンスを起動して最新ソースコードをデプロイし、随時デプロイは行わず、バッチ処理終了時にインスタンス削除します。どうしてもバッチ処理が分割できない場合には有効だと思われます。
* keep_releases を増やして、バッチ処理が終わるまでは releases ディレクトリが消えないようにする。今すぐできる対処法としてはありですが、いずれ抜本的な対応を行うべきでしょう。
* 複数のデプロイをとりまとめてデプロイ回数を減らす。これまたアドホックな対応です。デプロイしまくって rollback が出来なくなってしまっては Capistrano を使ってる意味が無いのでデプロイルールの見直しはあってもいいですが、長時間バッチ対策として行うのは意味が違いますね。
Blender 4.2で花火を打ち上げるアドオン

Blenderで、花火を打ち上げるアドオンをPythonで作成したので紹介します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13955/a5d919a0-ae1e-e31f-af96-580e25f88813.gif" width="300">

## やり方

### アドオンのインストール

- [Blender Add-on: Fireworks](https://github.com/SaitoTsutomu/Fireworks)の画面にしたがってインストールしてください

### Tomlファイルの作成

花火の設定は、Tomlファイルで行います。アドオンには、下記のサンプルTomlファイルが含まれています。

* [サンプルTomlファイル](https://github.com/SaitoTsutomu/Fireworks/blob/master/fireworks.toml)

**サンプルの説明**

`shot1`は、作成する花火のオブジェクトの名前です。任意の名前が使えます。花火はいくつでも作成できます。
`launch`は打ち上げ時のフレーム（アニメーションの時刻のようなもの）です。`explode`は爆発時のフレームです。

花火はパーティクルで実現しています。
上記では、下記の３つのパーティクルシステムを設定しています。いくつでも設定できます。パーティクルシステムの名前も任意です。

- `up`：爆発までの火花
- `ex1`：内側の爆発
- `ex2`：外側の爆発

### 作成

- サイドバーの編集タブの「Fireworks」を開いてください
- `file`に作成したファイルを指定します
  - デフォルトの `./fireworks.toml` はサンプルの指定です
- `Make（作成）`ボタンを押します

## 補足

花火の色はカラーランプで、時間により色が変わるようにしています。Cyclesではパーティクル情報ノードが使えたようなのですが、Eeveeだとパーティクルの情報が取得できなかったので、ドライバーで設定しています。爆発時にカラーランプの係数が0で、爆発終了＋寿命で係数が1になります。

### Pythonのコード

https://github.com/SaitoTsutomu/Fireworks/blob/main/__init__.py

以上
OpenSSL : 複合化時に bad magic number ／複合化したファイルが文字化けする

OpenSSL を使用して暗号化したファイルを、 Ubuntu 20.04 で複合化しようとすると、`bad magic number` のエラーが発生して複合化できませんでした。
暗号化を実行した環境は不明です。

また、Ubuntu 20.04 で暗号化したファイルを、Windows 10 で複合化すると、複合化したファイルの1行目が文字化けしていました。

暗号化のコマンドは以下のとおりです。

```
SALT=0000000000000000
IN=test.txt
OUT=test.enc
openssl aes-256-cbc -e -base64 -pbkdf2 -S $(SALT) -in $(IN) -out $(OUT)
```

## やりたいこと

この問題が発生したプロジェクトでは、メンバーが各自の好きな環境を利用して開発していました。
そのため、OS やライブラリーのバージョンに依存しない暗号化／複合化の手段を提供する必要がありました。

## 考えられる原因

Web検索で、考えられる原因が２つ出てきました。

1. ダイジェストアルゴリズムが異なる。

   OpenSSL は 1.1.0 を境にダイジェストアルゴリズムのデフォルト値が md5 から sha256 に変更されています。
   OpenSSL のバージョンに依存させないためには、 `-md` オプションでダイジェストアルゴリズムを明示してあげる必要がありそうです。

1. Windows 10 の base64 時の改行コード変換が悪さしている。

   `-base64` または `-a` を指定しないでファイルを暗号化すると、暗号化されたファイルはバイナリー形式になります。 暗号化／複合化時にBase64エンコード／デコードする際に echo が利用されるらしいのですが、Windows の改行コードは CRLF のため、改行コードの差異が悪さをしているかもしれません。  
   
   また、SALT利用時は暗号化ファイルの先頭に `Salted__` が付与されるのですが、改行コードの違いにより `Salted_` の付与がうまくいっていないかもしれません。  
   
   そのため、SALTを利用しない方法で上手くいくか検討してみる価値はあるかなと考えました。

## 解決方法

最終的に、暗号化のコマンドは以下になりました。

```
IV=00000000000000000000000000000000
IN=test.txt
OUT=test.enc
openssl aes-256-cbc -e -base64 -pbkdf2 -md sha256 -nosalt -iv $(IV) -in $(IN) -out $(OUT)
```

このコマンドによるファイルの暗号化 → 複合化は、以下の環境で成功することを確認しています。
- Mac 12.3 (OpenSSL 3.0.2)
  → Ubuntu 20.04 (OpenSSL1.1.1f / ホストOSが Mac のDocker）
- Windows 10 (OpenSSL 3.0.1)
  → Ubuntu 20.04 (OpenSSL 1.1.1f / ホストOSが Windows 10 の Docker)
- Windows 10 (OpenSSL 3.0.1)
  → Ubuntu 20.04 (OpenSSL 1.1.1f / Azure VM)
- Ubuntu 20.04 (OpenSSL 1.1.1f / Azure VM)
  → Windows 10 (OpenSSL 3.0.1)
- Ubuntu 20.04 (OpenSSL 1.1.1f / Azure VM)
  → MacBookPro17 (OpenSSL 3.0.2)

### 注意 : Mac の場合

Mac に標準でインストールされている LibreSSL はオプションが異なるため、解決方法に提示したコマンドはそのまま利用できません。

```
% openssl version
LibreSSL 2.8.3
```

そのため、OpenSSL を別途インストールする必要があります。