OmniAICreator/Qiita-1.07M huggingface dataset:
Rust で書いたプログラムがなんか遅い

# 要約

C++ だと 11.44 秒かかるものが Rust だと 18.36 秒もかかって遅い。なぜだ？

## 議論する内容

Leibniz 級数というものを使って円周率を計算するプログラムを Rust と C++ で実装して速度を比較する。実行時に級数の項の数を引数として渡して計算させる。うまくプログラムが書けていれば、Rust と C++/Clang ではほとんど性能が変わらないはずだが…

## Rust でのコード・コンパイル・実行

```rust:leibniz.rs
use std::env;

fn powersign(n: i64) -> i64 {
    if n % 2 == 0 {
        1
    } else {
        -1
    }
}

fn leibniz(n: i64) -> f64 {
    let mut s: f64 = 0.0;
    for k in 0..=n {
        s += powersign(k) as f64/ (2 * k + 1) as f64;
    }
    4.0 * s
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let n = &args[1].parse::<i64>().unwrap();
    println!("{}", leibniz(*n));
}
```

コンパイル：

```shell-session
$ rustc -C opt-level=3 -o leibniz-rust leibniz.rs
```

実行：

```shell-session
$ time ./leibniz-rust 10000000000
3.141592653688346

________________________________________________________
Executed in   19.24 secs    fish           external
   usr time   18.36 secs    0.16 millis   18.36 secs
   sys time    0.04 secs    1.74 millis    0.04 secs
```

## C++ での実装・コンパイル・実行

```c++:leibniz.cpp
#include <cstdint>
#include <sstream>
#include <iostream>
#include <limits>

template <typename T>
auto is_even(T n) {
    return n % T{2} == T{0};
}

template <typename T>
auto powersign(T n) {
    return is_even(n) ? T{1} : T{-1};
}

template <typename T>
auto leibniz(T n) {
	using F = double;
    auto s = F{0};
    for (auto k = T{0}; k <= n; k++) {
        s += static_cast<F>(powersign(k)) / static_cast<F>(T{2} * k + T{1});
    }
    return F{4} * s;
}

int main(int, char * argv[]) {
    std::stringstream stream;
    stream << argv[1];
    int64_t n;
    stream >> n;

    typedef std::numeric_limits<double> lim;
    std::cout.precision(lim::max_digits10);
    std::cout << leibniz(n) << std::endl;
}
```

コンパイル：

```shell-session
$ clang++ -O3 -o leibniz-c++ leibniz.cpp
```

実行：

```shell-session
$ time ./leibniz-c++ 10000000000
3.1415926536883458

________________________________________________________
Executed in   11.50 secs    fish           external
   usr time   11.44 secs    0.11 millis   11.44 secs
   sys time    0.03 secs    1.02 millis    0.03 secs
````

## 考察

C++ で実装し Clang-15.0.7 でコンパイルしたものだと 11.44 秒かかるものが Rust/rustc-1.67.1 だと 18.36 秒もかかる。遅すぎる。

昔（数年前）、同様のコードで速度差をテストしたときは、差異はほとんどなかったはずなのに、なぜなのだろうか。コンパイラが悪くなってしまったのだろうか。なぜ Rust のコードが遅いのかわかる方がいらっしゃったら教えて下さい。
【Django】formsファイルで動的なフォームを作成（__init__関数の使い方）

# ポイント
formsファイルで動的なフォームを定義するときは__init__関数を使いなさいよという話。
formsファイルは基本的にシステムを起動した最初の一度だけしか実行されないが、__init__だけは毎度実行されるため、動的な処理はこの中に書かないといけない。

# 例１：動的な選択肢を持つChoiceField

~~~python:forms.py
class SelectForm(Form):
    select_sample = ChoiceField(
        widget=Select()
    )

    def __init__(self, *args, **kwargs):    
        super().__init__(*args, **kwargs)

        # ここで選択肢となるsample_choicesを作成...

        self.fields['select_sample'].choices = sample_choices
~~~

# 例２：viewsからの値取得
もし任意の値をviewsからformsに渡したいときはkwargsを使う
~~~python:views.py
# フォームを定義する時に値を渡す
form = SelectForm(sample_text=sample_text)
~~~
~~~python:forms.py
class SelectForm(Form):
    select_sample = ChoiceField(
        widget=Select()
    )

    def __init__(self, *args, **kwargs):
        self.sample_text = kwargs.pop('sample_text') # この行を追加
        super().__init__(*args, **kwargs)

        # ここで選択肢となるsample_choicesを作成...

        self.fields['select_sample'].choices = sample_choices
~~~
Vue.jsの学習を始めました①

まずVue.jsはjavascriptのフレームワークである。ではVue.jsの何がすごいか個人的に気になった点を抜粋。

# データバインディングで開発負担が軽減できる
生のjavascriptであればhtmlに変更を加える際に、
①定数や変数で要素を取得
②変更する内容を定義
③変更した内容をHTMLに反映する
以上の3ステップが必要。
しかし、Vue.jsではVue.jsで記述したデータとHTML側にあるデータ反映対象に対して、片方が変更されたらそれをもう片方に反映する仕組みを持っている。これにより記述を減らすことができる。

# SPA開発ができる
仮想DOMを使用することで、SPA（シングル・ページ・アプリケーション）開発が可能になる。
SPAとは同じURLのままで他のページに遷移したような画面表示を提供する技術です。

# 実際にVue.jsで動かしてみる
https://zenn.dev/sdkfz181tiger/books/363d20b1e591fc/viewer/0beb4c
上記サイトを参考に勉強させてもらっています。

Vue.jsはjQueryと同じくCDNで使用することができる。
htmlに以下を記述

```index.html
<script src="https://unpkg.com/vue@next" defer></script>
```

全体のhtmlは以下
```index.html
<html>
<head>
	<meta charset="UTF-8"/>
</head>
<body>
	<div id="app">
		<h1>{{ appName }}</h1>
	</div>
	<!-- JavaScript -->
	<script src="https://unpkg.com/vue@next" defer></script>
	<script src="script/script.js" defer></script>
</body>
</html>
```

ここで二重括弧の{{appName}}はMustache構文と呼ばれVue.jsのデータをHTMLテンプレートに埋め込むためのものらしい
```index.html
{{ appName }}
```
なのでappNameという単語だけではなく、{{ name }}や{{ age }}といった任意の単語も入る
javascriptの${name}みたいな感じか

## 1.Vue.jsで扱うデータを用意する
まずはVue.jsで扱うデータを用意する
記述はJSON方式

```script.js
const myData = {
  appName: "Hello Vue.js!!"
}
```

## 2.Vue.jsの準備をする
先ほどのデータをVue.jsに設定する。
"Vue.createApp();"を実行する事で、"Vue"オブジェクトが作られる。
引数にはVue.jsに対する様々な設定を記述する。

```script.js
const app = Vue.createApp({
  data(){
    return myData;// Vue.jsで扱うデータを指定する
  },
  created(){
    console.log("created!!");// Vue.jsが起動した時に実行
  }
});
```

## 3.Vue.jsを起動する
最後は、Vue.jsオブジェクトを起動する。
引数には、タグに指定してあるID名"app"を指定する。

```script.js
app.mount("#app");// 3. Vue.jsを起動する
```

これでブラウザにはHello Vue.js!!と表示される。
```script.js
const myData = {
  appName: "Hello Vue.js!!"//この文字列を変更するとブラウザに表示される文字列も変更される
}
```

Vue.jsの初歩の初歩を勉強することができました。
Vue.jsを勉強する際にjavascriptも同時並行で学習できていい感じかもです。
次回はVue.jsで簡単なアプリケーションを作りたいと思います。
自作ポン出しWebアプリを5分で作る


# 自作効果音アプリ作ってみた

先日配信をすることになっていろいろ音をいじることになってWebアプリ作って配信しました。
音源Aを流しながら、音源Bのポン出ししたり（このときAは再生したまま）などの要件があったので自分で作った次第です。

## 流れ

* html書く
* netlifyにフォルダごとデプロイ

Netlifyじゃなくてもいいので「html ホスティング 無料」とかでぐぐるとよいと思います。

## html部分

フォルダ構成

```bash
yk@yk music % tree
.
├── assets
│   └── 和太鼓でドン.mp3
├── index.html
```

html部分


```html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ポン出しアプリ</title>
</head>

<body>
    <div id="app">
        <p>
            和太鼓でドン
        </p>
        <audio src="./assets/和太鼓でドン.mp3" controls></audio>
    </div>
</body>

</html>
```

以上で完成。

今回例で[効果音ラボさん](https://soundeffect-lab.info/)の和太鼓でどんを使おうとしたのですが、再配布禁止だったので誰でもアクセスできる状態のWebアプリでの作成だと使えないみたいでした。

> 利用規約
> 再配布に該当するケース
> 例1）効果音を自由に鳴らせるアプリを作る（効果音集的なもの）

というかそもそも編集自由なポン出しアプリを作られていることに気づきました。
https://soundeffect-lab.info/pon/app.html

Netlifyのproプラン以上だとベーシック認証付けられるので、ID・PASS認証により自分しか絶対にアクセスできない私的利用状態でのWebアプリだと問題ないかもしれませんが、そもそも再配布可能な音源使いましょう。


![スクリーンショット 2023-02-24 12.50.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/2cdeb145-d6a9-00db-2eba-0e2ebb183ed6.png)

![スクリーンショット 2023-02-24 12.50.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/112929/851af3c0-7247-4bbb-a977-3cfeecb3c509.png)
[Tips] Power Automate から Teams に投稿するメッセージに画像を埋め込む

Teamsに画像を埋め込んだメッセージを投稿する方法です。
このような感じで画像を埋め込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3659e805-ed15-e120-289b-f394e2f2584c.png)

方法はいたって簡単。Power Automateの"チャットまたはチャネルでメッセージを投稿する"アクションの `Hosted Contents`という詳細オプションを指定するだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/32e8545c-211b-c31e-7526-b6909341a534.png)

ここに指定するのは特定の形式のJSON配列です。

```json
[
    {
        "@microsoft.graph.temporaryId": "1",
        "contentBytes": "/9j/4SXpRXhpZgAASUkqAAgAAAAOAAABAwABAA....<base64 image>",
        "contentType": "image/jpg"
    },
    {
        "@microsoft.graph.temporaryId": "2",
        "contentBytes": "iVBORw0KGgoAAAAN....",
        "contentType": "image/png"
    }

]
```

`contentBytes`部分にはBase64化した画像ファイルを指定します。

メッセージ部分ですが、普通のHTMLで画像を表示するときのように`img`タグを使います。その際、src属性は以下のように指定します。

```html
<img src="../hostedContents/[temporaryId]/$value">
```

`[temporaryId]`部分にはHosted Contentsで指定したtemporaryIdを入力します。

たったこれだけで、最大4MBまでの画像ファイルをメッセージに埋め込むことができます。もし画像の幅や高さを指定するのであれば、通常どおり`height="xxx"` や `width="xxx"` で指定してください。

# References

https://mofumofupower.hatenablog.com/entry/AC_Image_2023

https://learn.microsoft.com/en-us/graph/api/chatmessage-post
[iOS] 写真のExifデータを編集して、フォトライブラリーに保存する方法

# これは

画像のExifデータ(metadata)を編集して、
それを保ったままフォトライブラリーに保存したいな〜と思っていましたが、案外情報がなかったのでまとめてみました。
(現在Deprecatedになっている情報が多かった)

# 実装

## Exifの読み込み

```swift
// URLからCGImageSourceを作成 URLはPHPickerViewControllerから取得を想定
let cgImageSource = CGImageSourceCreateWithURL(url as CFURL, nil)
// Exif
let metadata = CGImageSourceCopyPropertiesAtIndex(cgImageSource, 0, nil) as? [String: Any]
```

- 位置情報の場合

```swift
var locationDictionary = metadata[kCGImagePropertyGPSDictionary as String] as? [String: Any]

// Latitude & Longitude
locationDictionary[kCGImagePropertyGPSLatitude as String]
locationDictionary[kCGImagePropertyGPSLongitude as String]
```

このほかのそれぞれのキー値は[こちら](https://developer.apple.com/documentation/imageio/image_properties)を参照


## Exifへの書き込み

これは先ほど取得した値を使っていきます。

```swift
// Latitude & Longitude
locationDictionary[kCGImagePropertyGPSLatitude as String] = "0.000"
locationDictionary[kCGImagePropertyGPSLongitude as String] = "0.000"

// 上書き
metadata[kCGImagePropertyGPSDictionary as String] = locationDictionary
```

## フォトライブラリーに保存

```swift
 // 書き込み用のCGImageを作成
guard let cgImage = CGImageSourceCreateImageAtIndex(cgImageSource, 0, nil) else { return }

// 任意の名前をセット
let tmpName = UUID().uuidString
// URLを作成
let tmpUrl = NSURL.fileURL(withPath: NSTemporaryDirectory() + tmpName + ".jpeg")

if let _ = CGImageDestinationCreateWithURL(tmpUrl as CFURL, UTType.jpeg.identifier as CFString, 1, nil) {
   // 先ほどのmetadaをCGImageに反映する
   CGImageDestinationAddImage(destination, cgImage, metadata as CFDictionary)
   // 指定したURLに書き込み
   CGImageDestinationFinalize(destination)

   PHPhotoLibrary.shared().performChanges({
      // フォトライブラリーに書き込み
      PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: tmpUrl)
   }, completionHandler: { success, error in
      print("performChanges success: \(success), error: \(error?.localizedDescription)")
      // tmpFile削除する
   })
}
```

ポイントは`CGImageDestinationFinalize`を使って適当な場所に保存してしまうこと
そこから`PhotoKit`の`PHPhotoLibrary`を使って、フォトライブラリーに保存してあげてください

終わり


### その他

フォトライブラリーに保存する際に`UIImage`に変更してしまうと、Exifが欠損してしまうので注意


### 参考

ドキュメント: https://developer.apple.com/documentation/imageio
stackoverflow: https://stackoverflow.com/questions/51987255/save-images-to-photos-gallery-in-ios-with-exif-data-using-swift
サンプルプロジェクト: https://github.com/Take111/PhotoPickerSample
docker-composeでdjango+mariadb環境を構築した際の備忘録

# やりたかったこと
docker-composeでdjangoコンテナとmariadbコンテナを構築し、djangoコンテナからmariadbコンテナのDBにアクセスできるような環境を作成したかったのですが、少し手間取ったので手順を備忘録としてまとめておきます。

# 環境
Raspberry Pi OS (32bit)で試しています。
```bash
pi@master:~ $ uname -a
Linux master 5.10.103-v7l+ #1529 SMP Tue Mar 8 12:24:00 GMT 2022 armv7l GNU/Linux

pi@master:~ $ docker --version
Docker version 20.10.17, build 100c701

pi@master:~ $ docker-compose --version
docker-compose version 1.21.0, build unknown
```

各コンテナのIPアドレスとポートフォワードの設定は以下のようになっています。それ以外のdocker-composeの設定詳細については割愛します。
* djangoコンテナ
    * IP : 172.100.0.2 (172.100.0.0/24)
    * ポート : 8888:8888
* mariadbコンテナ
    * IP : 172.100.0.4 (172.100.0.0/24)
    * ポート : 3306:3306

# mariadb設定内容
mariadbコンテナで実施する設定内容です。

## mariadbを外部から接続できるようにする
```/etc/mysql/mariadb.conf.d/50-server.cnf```を編集し、bind-addressの設定をコメントアウトする。

```conf
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address		= 127.0.0.1  # ← この行をコメントアウトする
```

サービスをリスタートする。
```bash
service mysql restart
```

```netstat -atn```を実行して、tcp6のローカルアドレスが:::3306となっていればOK。

## 外部接続用ユーザの作成と権限設定
mariadbにログインして以下のSQLを実行する。
```sql
/* DB作成 */
create database django;

/* ユーザ作成と権限設定 */
create user 'django'@'172.100.0.%' identified by 'password';
grant all on django.* to 'django'@'172.100.0.%';

/* ユーザのパスワード設定 */
set password for 'django'@'172.100.0.%' = password('password');   -- 例：パスワードを"password"に設定

/* 確認 */
select user, host from mysql.user; -- django | 172.100.0.% が出ればOK
```

# django設定内容
djangoコンテナで実施する設定内容です。

## settings.pyの修正
DATABASESの設定をmysql用に変更する。
docker-composeでhostnameをmariadbに設定しているため、HOSTはホスト名のmariadbで設定している。
```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'django',
        'PASSWORD': 'password',
        'HOST': 'mariadb',
        'PORT': '3306',
        'OPTIONS': {
                'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
                },
    }
}
```

ここまでの設定でdjangoコンテナとmariadbコンテナ間の通信が可能になっているはずです。
djangoコンテナ内で```python manage.py dbshell```を実行してmariadbコンテナのDBに接続できれば成功です。

# ホストからdjangoコンテナで起動したアプリケーションにアクセスする
Windowsのブラウザ → コンテナが起動しているRaspberry Pi → djangoコンテナ
という関係性になっている場合の話になります。

* Windowsのブラウザ → コンテナが起動しているRaspberry Pi
docker-composeで8888ポートをフォワーディングすることで接続できます。

* コンテナが起動しているRaspberry Pi → djangoコンテナ
Raspberry Piのホストからdjangoコンテナへのアクセスを許可するよう設定が必要です。
djangoのsettings.pyのALLOWED_HOSTSの項目を修正します。今回は全許可で設定しています。
```
ALLOWED_HOSTS = ['*']
```

後はアプリケーション起動時に```python manage.py runserver 0.0.0.0:8888```とすることで、8888をlocalhostではなく全ホスト向けで立ち上げることができます。
これで、WindowsからRaspberry Pi上で起動しているコンテナにアクセスできます。
バッチファイルで引数（ファイル）を利用する

バッチファイルの引数（ファイル）のパスを取得したり、処理をしたりする方法。毎回忘れてしまうので具体例でまとめ。

## ファイル(%1)のパスを展開する

```dos:コマンドの例
C:\work>a.bat sample.txt
```

|修飾子|展開結果||
|:---|:---|:---|
|%~f1|C:\work\sample.txt|フルパス|
|%~dp1|C:\work\\ |フォルダパス|
|%~nx1|sample.txt|ファイル名(拡張子あり)|
|%~n1|sample|ファイル名(拡張子なし)|
|%~x1|.txt|拡張子|
|%~1|sample.txt||
|%~d1|C:||
|%~p1|\work\\ ||

## バッチファイル(%0)のあるフォルダを作業フォルダにする

```bat:a.bat
REM エコーをOFFにする場合は @echo off
cd /d %~dp0
```

## すべての引数(%*)に対して処理をする

すべての引数に対して個別に処理をする方法

```bat:a.bat
for %%f in (%*) do (
  REM 処理内容
)
```

先にファイルの存在確認をしてから処理をする方法

```bat:a.bat
REM ファイルの存在確認
for %%f in (%*) do (
  if not exist %%~ff goto error
)

REM すべてのファイルに対して処理
for %%f in (%*) do (
  REM 処理内容
)
goto end

REM ファイルが1つでも存在しない場合はエラーを出して終了
:error
echo ファイルが存在しません。
goto end

:end
```

## バッチファイルの処理を一時停止する

バッチファイルはたまにしか作成しないので、うまく動作しないことが多い。最後にpauseを書いて状況確認をする。

```bat:a.bat
REM 処理内容をここに記載
pause
```
アクティビティモニターの立ち上げ方はどうしますか？Macの場合


はじめに

> あれ、パソコンめっちゃ重いな、、、どこで何が動いてるんだろう立ち上げすぎかな？そういえば、何だっけどこからみたらいいんだ！！！

 って思った昼下がりのこと、立ち上がっている「アプリケーションがわかる方法を教えて！！」欲しいと思ってたどり着いたのがこちらです

# アクティビティモニター

## Macの場合
# アクティビティモニターの立ち上げ方はどうしますか？

Macでアクティビティモニターを開く方法はいくつかありますが、以下の手順を参考にしてください。

## Finderから選択

1. Finderを開きます。
2. メニューバーの「移動」をクリックし、「ユーティリティ」を選択します。
3. 「ユーティリティ」フォルダが開きますので、そこから「アクティビティモニター」を選択します。
4. 「アクティビティモニター」が起動します。

また、別の方法としては、スポットライト検索を使ってアクティビティモニターを開くこともできます。以下の手順を参考にしてください。

## スポットライト検索

1. Command + Spaceを押してスポットライト検索を開きます。
2. 「アクティビティモニター」と入力します。
3. 検索結果から「アクティビティモニター」を選択します。
4. アクティビティモニターが起動します。

## Launchpadから探す

1. 「Launchpad」のアイコンをDockからクリックして、「Launchpad」を開きます。
2. 「Launchpad」ウィンドウにある「その他」フォルダをクリックします。
3. 「アクティビティモニター」アイコンをクリックします。
4. アクティビティモニターが開かれます。

これらの方法で、Macで「アクティビティモニター」を開くことができます。

## アクティビティモニター」について

　Macに標準で搭載されているユーティリティアプリの1つで、Mac上で実行されているプロセスやアプリケーション、CPU使用率、メモリ使用量、ネットワーク接続、ディスクアクティビティ、エネルギー使用状況など、システムのさまざまな活動をモニタリングするために使用されます。アプリケーションを強制終了することができる機能や、CPUの使用状況によってパフォーマンスを向上させることができるようになっています。

　アクティビティモニターを使用すると、システムがどのように動作しているかを詳しく確認することができます。たとえば、重いアプリケーションがCPUを多く消費していることが分かれば、他のプロセスを停止することでパフォーマンスを改善することができます。また、アプリケーションがクラッシュした場合に、原因を特定するためにも使用することができます。

　一般的に、アクティビティモニターはMacのトラブルシューティングに欠かせないツールの1つとして知られています。

たまにわからなくなるので皆さんにシェアのつもりで書きました。

---

## 関連記事
[サンストライプについて](http://qiita.com/sunstripe)　- About

---

### 制作チーム：サンストライプ
[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/
[サンストライプについて](http://sunstripe.main.jp/)
制作チームのサンストライプのコンテンツについては以下の通り

月3回のコンテンツをリリースしています。
参加者は、プログラマーやデザイナー、イラストレーター、声優やVTuberなどが募集中です。

#### 関連プロジェクト・支援団体

- [地域情報 THEメディア](https://the.themedia.jp/)
地域活性化をテーマに様々な情報を発信しています。

- [ワークショップ情報 THEワークショップ](https://workshop.themedia.jp/)
多様化の時代に向けて他者理解を鍛えることを目的としています。

- [青空プログラミング](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8)　　- 月１だけのプログラミング学習塾
プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに取り組むことができます。


- [プログラミングラボ](https://twitter.com/PLab2020) - オンラインプログラミング研究チーム
３ヶ月にコンテンツを作成するAIを活用した実践形式の開発

- [Vの輪 バーチャル促進イベント企画・開発](https://twitter.com/VTuberLinks) - メタバースサークル
メタバースに向けた企画やイベントの実施およびメタバースとリアルの融合を目指してます。

- [スクランブルスクール バーチャル学校](https://twitter.com/scramblevschool) - バーチャル学校
VTuberに向けた情報発信とバーチャルイベントの企画と実施およびバーチャル番組制作

#### その他協力応援 / 支援者の集い
- [トラストヒューマン](http://trusthuman.co.jp/) - 私たちは何よりも信頼､人と考えてます｡
人材戦略パートナーとして、コンサルティングやクリエイティブの両角度からサポートをしています。
- キャリア教育事業 - [広域学習支援プラットフォーム『のびのび日和』](https://slc-lab.amebaownd.com/)
【2023】JavaScriptでクリップボードのコピーをする方法

こんにちは！普段は<a href="https://tantakatan-game.com/">TK:Re GAMES</a>というゲームブログを書いているTKです！
現在WordPressの自作テーマを作っており、その過程で調べたことを記事にしていこうかと思いますのでよろしくおねがいします！

# 非推奨の書き方

さて、今回はJavaScriptでクリップボードのコピーをする方法についてです。
クリップボードのコピーといえばこちらの方法を思い浮かべる方が多いのではないでしょうか？

```
const text = document.getElementsByTagName("textarea")[0];
// 文字をすべて選択
text.select();
// クリップボードにコピー
document.execCommand("copy");
```
ネットで調べると上記の方法が多く出てくるのですが、実は2023年現在非推奨になっており今後削除される可能性があるとのことでした。
https://developer.mozilla.org/ja/docs/Web/API/Document/execCommand

なので可能であれば以下の方法に切り替えましょう。

# 今後はnavigator.clipboardを使った書き方へ
今後クリップボード周りに関してはexecCommandのに代わりnavigator.clipboardが使われるようになります。
具体的な使用例は以下になります。

```
const text = document.getElementsByTagName("textarea")[0];
// クリップボードにコピー
navigator.clipboard.writeText(text);
```


## 注意点
navigator.clipboardの使用に関してですが、2点注意点があります。
1.https環境のみ使用可能
2.文字列ではなくDOMに使用
任意のタイミングでThree.jsのカメラの真正面にオブジェクトを配置する方法

# 概要
Three.jsで[OrbitControls](https://threejs.org/docs/#examples/en/controls/OrbitControls)のようなカメラの移動や回転を加味してクリックイベントなどの任意のタイミングで画面の真正面にオブジェクトを配置するのに楽だった方法を備忘録として記します。(three.js r149)

# 方法
1. カメラを中心とした透明の球を定義する
2. 任意のタイミングでレイキャスター([Raycaster](https://threejs.org/docs/#api/en/core/Raycaster))と球体の交点座標を取得する
3. 取得した交点座標にオブジェクトを移動する

# サンプル
```typescript
// シーン
const scene = new THREE.Scene()
// カメラ
const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
scene.add(camera)
// 仮の任意のオブジェクト
const object = new THREE.Object3D() 
scene.add(object)

// 1. カメラを中心とした透明の球を定義する
const radius = 100 // 結果的にカメラとオブジェクトの距離になる
const panoramaGeometry = new THREE.SphereGeometry(radius, 32, 32)
// Raycasterが反応するように急の反転を表裏を反転する(THREE.DoubileSideでも良い)
panoramaGeometry.scale(-1, 1, 1) 
this.customWorld = new THREE.Mesh(
    panoramaGeometry,
    new THREE.MeshLambertMaterial({
        transparent: true,　// 透過する
        opacity: 0.0,
      })
    )
this.customWorld.userData = { type: 'customWorld' }

...

// 2. 任意のタイミング(クリックイベントとか)でレイキャスターと交点の球体の交点座標を取得する
const raycaster = new THREE.Raycaster()
raycaster.setFromCamera({ x: 0, y: 0 }, camera)
const intersects = raycaster.intersectObject(scene)
// 事前に定義している球とカメラの視線の交点座標(THREE.Vector3)を取得する
const intersectsCustomWorldPosition = intersects.find(
    (obj) => obj.object.userData.type === 'customWorld')?.point
if (!intersectsCustomWorldPosition) throw new Error()
// 3. 取得した交点座標にオブジェクトを移動する
object.position.copy(intersectsCustomWorldPosition)
```

# レイキャスターで交点を取得するのに気にするとよかったこと
[Raycaster](https://threejs.org/docs/#api/en/core/Raycaster)はMeshに対してはデフォルトでは表側の面しか検出できないことに注意してください。今回の場合は、以下のようにジオメトリの裏表を反転させることで事足りますが、一般的にはマテリアルに対して`THREE.DoubleSide`を適用してください。
```javascript
panoramaGeometry.scale(-1, 1, 1) 
```
また、[Raycaster\#intersectObject](https://threejs.org/docs/#api/en/core/Raycaster.intersectObject)でレイキャスターと交差するオブジェクト全てが取得できるのですが、`intersectObject`の返り値のオブジェクトが複数あり対象を見つけるのが難しいことがあるかと思います。今回の場合は、透過している球にあたるものですね。そういう場合は思い切ってメッシュに対して(userData)[https://threejs.org/docs/#api/en/core/Object3D.userData]などに自前の設定してしまうと以下のように取得が楽になりました。(もっと良い方法があるかもしれない)
```javascript
this.customWorld.userData = { type: 'customWorld' }
// 事前に定義している球とカメラの視線の交点座標(THREE.Vector3)を取得する
const intersectsCustomWorldPosition = intersects.find(
    (obj) => obj.object.userData.type === 'customWorld')?.point
```
チーム開発における心得

この記事はチーム開発において私個人的の心得を記録したものとなります。
作業の流れとしては作業始める前に変数名、ファイル名などのを決める命名規則。開始予定日、開始日、終了日を記録する作業予定、日々作業内容と担当を記録する工程表などを作成して、皆がルールに従って作業を行い日々これらを中心に報連相を行う。


## 1.git
基本的にVSCodeなどのエディタでgitをマウス操作できるけどよく使うコマンド命令が二つあります。

```
//githubと一致
git pull

//githubと強制一致
git reset --hard
```

## 2.excel
表決算を効率的に使うには計算式を活用する必要があります。
例
=COUNTIF(F10:F47,F4)
=IF(I14="","資産漏れ","調査対象")
MacOSにおけるPATH管理(個人的備忘録)

# そもそもPATHとは
PATHは「実行ファイルの場所」を指定することでプログラムを動かすことのできる機能。
PATHには道といった意味がある通りプログラムの大元である実行ファイルの場所(道)を表す。
例えば、MacOsの場合 **usr/local/bin** といった形でスラッシュ区切りで表す。

# 記事を書いた経緯
PATHの管理をbash_profile内で行っていたところ **zsh: command not found** と表示があり、bashは対応していないの？と疑問に思い色々と調べました。すると2年程前のmacOS Catalina以降はデフォルトのshellが**bashからzsh**に変わったのことで急遽、頭の整理も兼ねて記事を書くことにしました。

# PATHの復習
よく使うコマンドを載せておきます。

```:PATHの参照
> echo $PATH
```
改行なしでPATHを表示するので見やすくするにはこのコマンド
```:PATHの参照
> echo $PATH | sed -e 's/:/\n/g'
```
PATHの追加は2種類コマンドがあります。

```:PATHの追加
> export PATH="通したいパス:$PATH"
```
個人的にはこっちの方が好き。
```:PATHの追加
> export PATH=$PATH:通したいパス
```
**＊永続PATHには通していないのでこの時点で、ターミナルを閉じるとPATHが消える**

/usr/libをPATHに追加した結果
![Screen Shot 2023-02-24 at 13.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153036/997a753e-da36-477f-b767-fd80384153b3.png)
ターミナルを閉じると
![Screen Shot 2023-02-24 at 13.56.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153036/9524b643-e92b-6a2d-4b6c-c2e233a816e5.png)
本命の/usr/libが消えてる！

>私が初心者の頃はいちいちPATHの追加を繰り返し行なっていました。また、たくさんPATHを追加するとどれがどれだかわからなくなるので必要最低限の量で収めるのがいいですね！
>

# 永続PATHの追加
ようやく冒頭で話したbashがどうこうという話に戻ります。
今までの永続PATHの管理はbash_profileで行なっていましたが、macOS Catalina以降(2020年4月？〜）zshrcファイルで行います。

```:zshrcファイルを開く
> open ~/.zshrc
```
ここの部分にexport PATH="通したいパス:$PATH"を追記すればOKです！
![Screen Shot 2023-02-24 at 14.07.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2153036/0c4805b0-34ba-307f-ac00-82748d8fcd6b.png)
>Vimでの操作が苦手な方もやりやすいのでは？
>
**ここで満足して終わる人が多いので注意**
最後に環境変数を反映させるコマンドを実行します。
```:環境変数を反映
> source ~/.zshrc
```
ファイルの追記やらをすっ飛ばしていっきに終わらせたい方はこのコマンド！
```:永続PATHの追加
> echo "export PATH=$PATH:通したいパス" >> ~/.zshrc ; source ~/.zshrc
```
【Docker-compose】MysqlDumpファイルを一括で流し込む


初のQiita記事です。どうぞお手柔らかに

前置き長いので目的
docker-composeで個別のDumpファイル（ってかSQL）を、初期化時にまとめてbashでレストアしたい！

以上記事終了。

というわけにもいかず、まぁdocker-composeでMySQL環境構築はみなさん当たり前にやってるかと思います。
まぁなんで、何番煎じの記事なんじゃという話ではあるんですが。

Amazon Aurora MySQLを使っているのですが、なんらかの理由で全データをローカルで見たいとなるんです。`--all-databases`でdumpを取得してレストアしてみたものの、権限周りもセットでバックアップされる関係もあってレストア直後は接続できますが、コンテナを一度落とすと接続できなくなるという残念な結果になります。
（ローカルでやるとMySQLぶっ壊れるので、必ずdocker使いましょう。私は壊しました。）

よってDBごとに個別でdumpを取得して、個別にレストアする必要があります。

で、この個別のDumpファイル（ってかSQLなんですけど）を、初期化時にまとめてレストアしたいんじゃ！ってのが今回の目的です。
まぁ細かいことは他の記事に移譲します。私もそこを参考にしました。
先駆者はとても偉大ですね。本当に尊敬します。ありがとうございます。

まぁdumpに付けられた名前をそのままDBの名前として使いたいが本当の目的。
結局なにかって、初期化時に走るbashスクリプトを書いただけです。

あとは参考文献をもとに構成されてます。
sqlディレクトリにDB単位のdumpファイルつっこんで、`docker-compose up -d --build`するだけです。

本当はSQLのIF分とか使えやとかヒアドキュメントでかけやとか言われてしまいそうだしconfにパスワード書けとか言われそうだけどヘーキヘーキ（あかん）
その辺うまく書き換えてください。

[docker-compose でMySQL環境簡単構築](https://qiita.com/A-Kira/items/f401aea261693c395966)を参考にしているのですが、以下のコードは記事で言えばinit-database.shファイルの中身です。
ファイルの階層とかも気にしてください。

とりあえず誰かの役に立てれば幸いです。

```
#!/bin/bash

#MySQL
DB_HOST=localhost 
DB_USER="任意のユーザー"
DB_PASS="任意のパスワード"
DB_PORT="任意のポート"

CURRENT=$(cd $(dirname $0);pwd)

files="${CURRENT}/sql/*"

#配列作成
array=()
for filepath in $files; do
  echo $filepath
  #変数$filepathの中身を配列に追加
  array+=("$filepath")
done

# Dump Databases
for e in ${array[@]}; do
  name=`basename $e .sql`
  echo $name
  dbname=\``echo ${name}`\`
  echo $dbname
  mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS  -e "CREATE DATABASE $dbname;"
  mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" ${name} < ${e}

done

```

【参考文献】
[Aurora MySQLでリストア権限のあるDBを個別にダンプするスクリプト](https://blog.denet.co.jp/rds-for-mysqldump/)
[docker-compose でMySQL環境簡単構築](https://qiita.com/A-Kira/items/f401aea261693c395966)
タスク管理アプリ 開発録

# 本記事作成の背景
IT系の職についたものの、言語で開発することがなく、フレームワークに触れつつ苦手なC++を学習していこうかと考えてます!
そのうえで誰もが使うであろうものを作成するとなったとき、タスク管理アプリがいいのかなと思いまして開発に至りました。
本記事では基本設計、詳細設計と困った際の試行錯誤を記載していきます。
# 開発背景
タスク管理アプリは世の中にあふれてはいるが、タスク管理のみとなっており、プロジェクトとは無関係の振り返りがおろそかになってしまう
クライアントに説明するときは不要でも今後の作業の効率化のために振り返りは必要
振り返りを別ファイルで保存すると、どのタスクに紐づいたものでどういうときの教訓だったかというのが把握しずらくなる
そのため、タスク管理票内で、振り返りも紐づけておくことで、再度見たときに思い出し、効率化につながる
# 概要
個人またはプロジェクト内で使用するタスク管理アプリ。
個人の進捗、プロジェクトの進捗をチームリーダーがひと目で把握できるようにすることができ、
タスクの振り返り欄を設けて新人の振り返りにもなるようにしておくことが目的
# システム構成
![システムアーキテクチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1223452/f33d4d0b-422e-0c4f-cbfb-9e3665ba5ec4.png)

# 規模
- 開発規模：1.5人月
- 開発人数：1人
# 機能要件
#### 機能一覧
- プロジェクトの登録
　プロジェクト名称、チームメンバーをチームリーダーが登録
　内容はのちに編集できるようにすること
- 親タスクの登録
　クライアントの名称、タスクの名称、背景、目的、完了の定義、チームメンバー、をチームリーダーが登録
　内容はのちに編集できるようにすること
- 子タスクの登録
　各タスクに対して、調査、実装、レビューなどやることの一覧とその目的をチームリーダーまたはチームメンバーが登録
　内容はのちに編集できるようにすること
- タスクの進捗表示
　親タスク、子タスクの進捗状況を表示する
　親タスク：完了,未完了の状態管理と子タスクの完了個数に応じたパーセント表示
　子タスク：未完了,完了,社内レビュー中,レビュー中の状態管理を持たせる
- タスクごとに振り返りの設定
　親タスク：チームリーダーがタスク完了時に振り返りの入力、子タスクにおけるチームメンバーの振り返りを表示
　子タスク：チームメンバーがタスク完了時に振り返りを入力

#### 画面
- 会員登録画面
パスワード,メールアドレス,名前を登録する画面
クラウドの場合、チームリーダーかチームメンバーの権限設定も可能
- メンバーの招待画面
メールアドレスを指定して、招待する画面
- 招待メンバー用会員登録画面
名前、パスワードを登録する画面。
会員登録画面と違い、メールアドレスの確認を行わない
- パスワード設定画面
招待されたメンバーもしくはパスワードを忘れた人ようの新たなパスワードの入力画面
- ログイン画面
パスワードでログインする画面
- プロジェクトの選択画面
プロジェクトを選択する画面
- プロジェクトの登録画面
プロジェクトを新規登録する画面
- タスク登録画面
タスクを登録する画面
- プロジェクト全体のタスク管理画面
タスクの進捗管理、子タスクの追加、振り返りの確認をする画面
振り返りは表示非表示を切り替えれること
- 個人ごとのタスク管理画面
関連する親タスクの表示、子タスクの進捗を管理、振り返りの設定をする画面
- チームリーダーの設定画面（オンプレミスのみ）
登録されたメールアドレスで検索し、チームリーダーを設定する画面
#### データ
本システムでは、以下のデータが作成される
- 会員のメールアドレス名前、各プロジェクトのタスク内容がデータベースに保存されます。
#### 非機能要件
- 表示は１秒以内に行われること
- 100台以上の同時アクセスに耐えられること(オンプレミス版)
JavaScript データ型について

こんにちは　yicodeです。
今日は前回と同じでJavaScriptの説明をしていこうと思います。
前回の記事については次のリンク先から見ていただけると嬉しいです。
リンク先
[JavaScript 変数の宣言方法](https://qiita.com/yicode/items/72832363d19333eb0969)
今日はJavaScriptの型について説明していきます。
# Javascriptは動的型付け言語
プログラミング言語にはコードを書くときに予め型を決めてかくもの（静的型付け言語）と、
コードを書いた後、実行時に型のチェックを行うもの（動的型付け言語）があります。
JavaScripは後者に属します。
# JavaScriptの型の種類
javascriptには以下の7つのプリミティブ型と1つのオブジェクト型が存在します。
|分類|データ型|
|----------|---|
|(Boolean)論理値   |プリミティブ型  |
|(null)値不明      |プリミティブ型||
|(undefined)未定義 |プリミティブ型  ||
|(Number)数値         |プリミティブ型  ||
|(BigInt)長整数      |プリミティブ型||
|(String)文字列      |プリミティブ型  ||
|(Symbol)シンボル       |プリミティブ型 ||
|(object)オブジェクト|オブジェクト型||

## プリミティブ型とオブジェクト型
- プリミティブ型 
変数に直接値が格納されるものである。またプリミティブ値は値を置き換えることはきるが、
直接変更することはできない。（この特性をイミュータブルと呼ぶ）
- オブジェクト型
複数のプリミティブ値またはオブジェクトからなるデータ構造です。
オブジェクトは、直接変更することが可能です。（この特性をミュータブルと呼ぶ）
# まとめ
Javascriptは動的型付け言語である
javascriptには大きく分けて二種類のデータ型がある
(プリミティブ型とオブジェクト型)
# 最後に
今日はデータ型について説明していきました。多分次回もプログラミングの説明をしていきますここが間違っているなどの指摘が
あればすぐに直すのでコメントにて連絡ください。よろしくおねがいします。
nodenvで構築した環境のnodeバージョンを上げる

## アップデートの対象のNodeのバージョンがあるかを確認
`nodenv --list`でインストールしたいバージョンがあるかを確認できる
``` shell
nodenv install --list
# 出力例
# 0.1.14
# 0.1.15
# 0.1.16
# 0.1.17
# ...
```
欲しいバージョンがない場合は nodenv 内部で使われている [node-build](https://github.com/nodenv/node-build) というツールを更新すると最新化される。
Mac環境の場合は以下のコマンドで更新可能。
``` shell
brew upgrade node-build
```

## 対象バージョンをインストール
``` shell
nodenv install xx.xx.xx
# ex: nodenv install 18.14.0　など
```

## .node-versionを更新
```shell
nodenv local xx.xx.xx
# nodenv local 18.14.０　など
```

## 動確
``` shell
node --version
# 出力例
# v18.14.０
```
C#.NETでウィンドウを最前面固定に

# やり方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4ad1f2bd-b429-770f-013a-a60d235a8ef0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/fad167b2-0b2a-1ac9-37f8-dcad644bb343.png)

```c#:サンプルコード
using System.Windows.Forms;

namespace Saizennmendayo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.TopMost = true;

        }
    }
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/545acea0-1bc2-b690-ac58-9c1ba6e1714d.png)

# 最前面に設定したウィンドウが複数開かれた場合

最後に開いたウィンドウが最前面になる。

例えば、下記は…

1. 最前面に設定したウィンドウを開いた。（赤枠）
1. 最前面に設定したウィンドウを開いた。（青枠）
1. ForeFoxをクリックした。

という状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/3e66212f-cabb-d965-bcd8-e09f2845ea03.png)

青枠の方が後に開いたから、それが最前面になる。
赤枠の方も最前面として開いてはいたので、ForeFoxより前になる。

# バージョン

Windows 10 Pro 22H2 OSビルド 19045.2604
Microsoft .NET Framework Version 4.8.04084
RSpecのWARN: Clearing out unresolved specsのトラブルシュート

## 環境
Rails5.2

## 内容
Rspecを実行したところ、下記のエラーが発生しました。
```
WARN: Unresolved or ambigious specs during Gem::Specification.reset:
      diff-lcs (>= 1.2.0, < 2.0)
      Available/installed versions of this gem:
      - 1.5.0
      - 1.4.4
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
```

diff-lcsというgemが、1.5.0と1.4.4の２つのバージョンでインストールされており、RSpecがどちらのバージョンを使うべきか判断つかない状態になっていることが原因のようです。

確かに、２つのバージョンが存在しています。
```
$gem list diff-lcs
*** LOCAL GEMS ***
diff-lcs (1.5.0, 1.4.4)
```

問題の解決方法は、エラーメッセージの中に書かれていました。下記のコマンドを実行すると、複数のバージョンがインストールされている場合、古いバージョンの方を削除してくれます。
```
gem cleanup diff-lcs
```

確かに、古いバージョンのgemが削除されたようです。
```
$ gem list diff-lcs
*** LOCAL GEMS ***
diff-lcs (1.5.0)
```

再び、RSpecを実行すると、エラーは発生しなくなりました。:smile:
AWS-SDK lambda invokeAsyncをinovokeに変更しろくださいの通知をやっと対応したので備忘録てきな

## とりあえず変更

変更前
```
lambda_client.invoke_async(function_name: function_name, invoke_args: param)
```
変更後
```
response = lambda_client.invoke(
    FunctionName=function_name,
    Payload=param,
    InvocationType='Event'
)
```

## なんで非推奨なったのか

##### inovkeAsyncとは
ambda関数を非同期で呼び出すための古いAPI
現在は非推奨になっている

##### なぜ非推奨に
1. コールバックパターンを使用しているため、非同期呼び出しの完了状態を取得する方法が限られている。
1. invokeAsyncメソッドは、リトライやエラー処理を行うための機能が限定的であり、失敗の発生を検知することができないため、実行中のエラーに対処がむずかしいから

みたいです。

### invokenは

invokeAsyncメソッドの代わりにより高度なエラー処理とリトライ機能を提供する新しいAPIであるinvokeメソッド
同期および非同期呼び出しの両方をサポートしているため、invokeAsyncメソッドの代替として使用することができるみたいです。

なので
invokeAsyncメソッドは非推奨になり、代わりにinvokeメソッドを使用することが推奨されているっぽい

コードの`invocation_type`
`Event`を指定することで非同期実行= Asyncのかわり
`RequestResponse`を設定することで同期実行ができるみたいです。

### invokenの機能

##### リトライ機能
Lambda関数が呼び出しに失敗した場合、AWS SDKのinvokeメソッドは自動的にリトライを試みます。
リトライの回数と間隔は、AWS SDKのデフォルト設定に従いますが、カスタマイズすることもできる

##### エラーハンドリング機能
AWS SDKのinvokeメソッドは、Lambda関数がエラーを返した場合に、エラー情報を取得できるようになっている
これにより、呼び出し元のアプリケーションで適切なエラーハンドリングを行うことができる

##### タイムアウト設定機能
Lambda関数が実行を完了する前にinvokeメソッドがタイムアウトした場合、AWS SDKは自動的にリトライを試みます。
この場合、SDKのデフォルト設定に従って、最大3回までのリトライする

## まとめ
ただしデフォルトでリトライやエラーハンドリングするみたいな設定もあるので、追加でLambda関数へのリクエストが増えそうなので
そこんとこ注意っぽいです
分野ワークショップに参加して

私は、2月21日(火)に盛岡市で開催されたenPiTの分野ワークショップに参加した。分野ワークショップには、筑波大学を含めた9校、全14チームが参加した。今回は主に、分野ワークショップで行われたポスターセッションについて振り返る。
分野ワークショップでは、プレゼンテーションとポスターセッションが同時並行で行われていた。私は主にポスターセッションに参加していたが、どのチームのプロダクトもレベルが高く、またプロダクト自体だけでなく開発手法にも工夫が見られた。英単語学習アプリを開発した愛媛大学・岡山県立大学のMiuMiを例にとる。このチームのメンバーの1人は元々情報系以外の学部出身で、開発の経験はほとんどなかったそうである。しかし学部で学んだ知識を活かして、アプリの機能やホームページの配色を考えたという話を聞いた。このように個人の強みを活かして開発を行なっていたチームが多数見られ、非常に勉強になった。
【Flutter】ウィジェットをずらして重ねる方法

# はじめに
Flutterでウィジェットをずらして重ねる方法についてご紹介します。
ウィジェットの重なりをコントロールすることで画面内での複雑なUI表現が可能になります。

# 注意

本記事の内容については、Flutter２についての内容です。
紹介されている`ClipBehavior`等の振る舞いについて、Flutter３以降大きな変更が加えられているようです。


https://docs.flutter.dev/release/breaking-changes/clip-behavior

 
 # 目標
 複数のウィジェットをずらして重ねた状態で表示する。

 # 実装

 Flutterには`Stack`という子要素のウィジェットを重ねてくれるウィジェットが存在します。
 子要素の重なり方は、リストは後の要素が前の要素の上に重なるように表示されます。


```dart:Stackの例
Stack(
  children: [
    Container(
      width: 100,
      height: 50,
      color: Colors.blue,
    ),
    Container(
      width: 30,
      height: 30,
      decoration: const BoxDecoration(
        color: Colors.red,
        shape: BoxShape.circle,
      ),
    ),
  ],
),
```

このままでは上に重なるウィジェットの位置を細かく調節することができません。
そこで`Positioned`という子要素の位置を指定するウィジェットを使用します。

```dart:Positionedを加えた例
Positioned(
  top: 0,
  left: 0,
  child: Container(
    width: 30,
    height: 30,
    decoration: const BoxDecoration(
      color: Colors.red,
      shape: BoxShape.circle,
    ),
  ),
),
```
 
 このとき`Positioned`内に指定する位置の値は、重なりの下のウィジェットが基準となります。
 つまり`top: 0, left: 0`を指定した場合、下側のウィジェットの左上にピタリと重なるように上側のウィジェットは配置されます。

![img_2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119758/062e9bb6-cb94-4733-8125-3b10c40276b8.png)

 位置に指定する値は負の数を取ることができるので、ウィジェットをずらして重ねたい場合、例えば`top: -10, left: -10`のようにマイナスの数値を指定すれば良いことになります。

 ```dart:Positionedにマイナスの値を設定した例
Positioned(
  top: -10,
  left: -10,
  child: Container(
    width: 30,
    height: 30,
    decoration: const BoxDecoration(
      color: Colors.red,
      shape: BoxShape.circle,
    ),
  ),
),
```

ところがこのコードを実行すると、次の図のようにはみ出した部分が切り取られたように表示されてしまいます。

![img_2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119758/9e7b7af3-b01e-83e0-7319-9f0e2eecd48f.png)

この現象の原因は、`Stack`ウィジェットの`clipBehavior`プロパティに`Clip.hardEdge`という値がデフォルトで指定されていることです。
`clipBehavior`プロパティでは、ウィジェットが親要素のウィジェットの領域からオーバーフローする場合の挙動を指定することができます。
はみ出した部分が切り取られないように、値を`Clip.none`に変更します。


 ```dart:sample
Stack(
  clipBehavior: Clip.none,
  children: [
    Container(
      width: 100,
      height: 50,
      color: Colors.blue,
    ),
    Positioned(
      top: -10,
      left: -10,
      child: Container(
        width: 30,
        height: 30,
        decoration: const BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
      ),
    ),
  ],
),
 ```

 このコードを実行した結果は次のようになります。

 ![img_2_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119758/5479288b-0ee2-6b3c-5fc3-d2fa7e800cf2.png)

ウィジェットをずらして重ねることができました。


# おわりに
本記事ではFlutter２において、画面上に複数のウィジェットをずらして重ねる実装方法についてご紹介しました。
この方法を応用すると、例えば未読や通知バッジを任意のウィジェットの上に表示することが可能になります。
topでプロセス監視したいけど負荷はかけたくない

load averageが高騰したけど原因がわからずお蔵入りになってしまったので、今後再発した際に原因追求できるようにプロセスを監視することになった。
`top`でも`-b -n 1`すれば負荷がかからないようにできるので、「topで監視は負荷が@!~#$」とか言われても実装しましょう。負荷については最後の方でまとめています。
「`ps`でよくね？」と思われた方、`ps`使わなかった理由は最後に書きます。

やることは以下の通り。
**1. `top`の結果(上位5件)をログに残す & `日付.log`として`yyyy-mm`というディレクトリにぶち込む**
**2. `cron`で定期実行**
**3.  毎月1日に3か月以上前のものは削除**

では、説明は最低限で実装だけしていきます。

## `top`の結果(上位5件)をログに残す & `日付.log`として`yyyy-mm`というディレクトリにぶち込む
```save_process.sh
#!/bin/sh

LOGDIR=/log/process/`date +%Y-%m`/ #ログ保存先ディレクトリ　yyyy-mm
TOPLOG=${LOGDIR}`date +%d`_top.log #ログファイル　dd_top.log

[ ! -e ${LOGDIR} ] && mkdir -m 777 -p ${LOGDIR} #ログ保存先ディレクトリがなければ作成。 -m 777は必要に応じて変更して。

date +%H:%M:%S >> ${TOPLOG} #top取得の時間をhh:mm:ssで記載
COLUMNS=150 top -b -c -n 1 |head -n 12 |tail -n 6 >> ${TOPLOG} #topの結果（ヘッダーと上位5件）を記載
echo >> ${TOPLOG} #見やすいように1行改行してるだけ。不要なら消しておｋ。
```
## cronで定期実行
`save_process.sh`を作成したら適当なところに置いて、`cron`で定期実行します。
僕は毎分監視するので、cronの記載は以下の通り。
```
*/1 * * * * sh /tmp/save_process.sh
```
`cron`の記載方法は詳しくまとめてくださっている方が↓
https://www.server-memo.net/tips/crontab.html

## 毎月1日に3か月以上前のものは削除
ストレージ圧迫させたくないので削除処理もしっかりと。
```delete_processLog.sh
#!/bin/sh

TODAY=`date +%Y-%m-01` # 当月の1日を文字列として取得
MON1AGO=`date -d "${TODAY} 1 day ago" +'%Y-%m-01'` #1 day agoで前月を取得して、前月の1日を文字列として取得
MON2AGO=`date -d "${MON1AGO} 1 day ago" +'%Y-%m-01'` #1 day agoで前々月を取得して、前々月の1日を文字列として取得
MON3AGO=`date -d "${MON2AGO} 1 day ago" +'%Y-%m'` #1 day agoで前々々月を取得して、前々々月を文字列として取得

rm -r /var/log/process/"${MON3AGO}" #前々々月のディレクトリを削除
```

これも`cron`で毎月1日00:01に実装します。
```
1 0 1 * * sh /tmp/delete_processLog.sh
```

# 諸々の説明
### `top`のコマンドの説明
* **`head`と`tail`を駆使して、ヘッダーを含む上位5件を表示させる**
* **`-c`でCOMMAND列をフルパスに**
* **`-b`(バッチモード)で`cron`で回しても正常に結果が返ってくるようにする**
* **`-n 1`で負荷下げる**
* **`COLUMNS=150`で1行あたりの文字数を増やす(デフォは80のためCOMMAND列の結果によっては見切れてしまう) ※`-w`が使えるなら`-w 150`とかで良いぽい**
```
COLUMNS=150 top -b -c -n 1 |head -n 12 |tail -n 6
```
 ### 負荷
このコマンドでかかる負荷を確認してもゴミカス程度なので問題はなさそう。
```
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
14950 root      20   0 15028 1160  816 R  0.0  0.0   0:00.00 top -bc -n 1
```

# `ps`を使わない理由
> TOPの方は短いスパンでのCPU使用率を表示できるものであり、負荷調査の役に立つ数字です。
PSの方はプロセスが起動してからどの程度CPUを使っているかの割合であり、定常的にサーバーのリソースを多く使っているものを判定するものになるため、負荷調査で使ってはいけない数字になります。
> なので、サーバーの監視用途にPSのCPUは使ってはいけないようです。

とのことです。
https://hacknote.jp/archives/10596/

## 結論：`top`は意外と複雑だった
コマンドラインから打ったら結果返ってくるのに、`cron`で回したら結果が空になったり、
COMMAND列が見切れたり...
パソコンは難しいです。
ロリポップでLaravelを動かす(PHP7.4 / Laravel8)

## はじめに
レンタルサーバー：ロリポップで、Laravelを動かすために実施した作業のメモです。

https://lolipop.jp/

## 前提
- ロリポップに **SSH接続ができるスタンダードプラン以上**

- laravel_appはローカルで開発完了している

- バージョン
 php7.4
 Laravel 8.5.19

- ロリポップ管理画面：ドメインに対するPHP設定 → バージョン7.4に設定

## Laravelアプリをロリポップで動かす手順

### ロリポップへ接続(SSH)

~~~
$ ssh lolipop.jp-XXXXXXXXXXXX@ssh.lolipop.jp -p 2222
~~~


### composerをインストール

homeフォルダで実行する

~~~
# composerをインストール
$ /usr/local/php/7.4/bin/php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"

# 確認
$ php composer.phar -V
~~~


### PHPにPATHを通す

~~~
# bash_profileを編集
$ vi ~/.bash_profile

# bash_profileに以下を記載
export PATH="$PATH:/usr/local/php/7.4/bin"
source ~/.bash_profile

# 確認
$php -v
~~~

### Laravelのインストール

homeフォルダで実行する

~~~
# Laravelインストール(バージョン指定)
php composer.phar create-project --prefer-dist laravel/laravel フォルダ名 "8.5.19"

# 確認
php artisan -V
~~~

### 権限の変更
「storage」と「bootstrap/cache」のパーミッションをそれぞれ変更

~~~
$ chmod -R 777 storage
$ chmod -R 775 bootstrap/cache
~~~

### シンボリックリンクを設定

- Laravelアプリ公開フォルダは、web配下
home/web/laravel_app/public

- 実際のコード群は、homeフォルダ
home/app1/

publicフォルダに、シンボリックリンクをはる。

~~~
$ ln -s $HOME/app1/public $HOME/web/laravel_app/public
~~~

### データベースの作成

ロリポップの管理画面にて実施

![Screenshot_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/ced9ec2a-84d8-8520-a9fb-70dcf1cbf700.png)

### 作成したプロジェクトのコード群を反映

git clone等でファイルを配置する

### .envファイルの修正

~~~
APP_NAME=(プロジェクトの名前)
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=(ドメイン名)

DB_CONNECTION=mysql
DB_HOST=(データベースホスト)
DB_PORT=3306
DB_DATABASE=(データベース名）
DB_USERNAME=(ユーザ名）
DB_PASSWORD=(パスワード）
~~~

### migrate実行

~~~
$ php artisan migrate
~~~

エラーがでないこと、phpMyAdminでテーブルが作成されていることを確認。

### APP KEYを作る

~~~
$ php artisan key:generate 
~~~

## まとめ
- 参考にさせていただく投稿が多く、エラーにかかることなく、とてもすんなりと導入できました(感謝)


## 参考URL

https://qiita.com/yuzuha3ds/items/4c6b7d3f83e88b45d968

https://qiita.com/mukae_tech/items/8d256fb298f877ed36c2

https://zenn.dev/bardothodol/articles/2ef4048fefb0ee
while文

## while文とfor文

 >for文を使って書くよりも変数の数が少なくて済むし直感的
 ただしfor分の方が小回りがきくような印象
 while文→for文で実装すると良いかもしれない
    → 順番とか特になく、理解と使い分けが必要
 while文は直感的だが、処理を書き忘れると無限ループに入ってしまうため注意が必要

> ※ コメントいただいたので修正
for → イテレータ
while → 条件成立の間

```py.qiita.py
#  6 while文
i = 1
for j in range(99):
    i = i + 1 
print(i)

#******************************************
i = 1
while i < 100:
#     i = i +1 は省略できる
    i += 1
#     print(i)

print(i)
```
## breakの使い方
> breakは特定の条件で処理（ループ）を強制終了させることができる
```py.qiita.py
# 　6-2 break
#  break　特定の条件になったらwhile文を強制終了

i = 0
while i < 100:
#     60という値になったら処理を終了する
    if i == 60:
        break
    i +=1
print(i)

# breakの使い方
#  while Trueは常にループするという意味
# 　breakをしてあげないと、無限ループし続ける
j = 0
while True:
    if j == 100:
        break
    j +=1
    
print(j)
```
## continueの使い方
>continueはループの中での特定の条件をスキップすることができる。
そのためある条件における処理をスキップして別の処理に変更することができる

> ※コメントいただいたので修正
```py.qiita.py
#  6-3 continue
i = 0
while i < 100:
#     必ず実行する処理
    i += 1
#     FIzzBuzzの時だけ処理を変える
    if i % 15 == 0:
        print(f'FizzBuzz({i})')
#       continue: ここはなくて良い
    elif i % 3 == 0:
        print(f'Fizz({i})')
 #      continue: ここはなくて良い
    elif i % 5 == 0:
        print(f'Buzz({i})')
 #      continue: ここはなくて良い
    else:
        #         数字の出力
        print(i)
```
> 上のコードをcontinueを使って実装したいなら
```py.qiita.py
#  6-3 continue
i = 0
while i < 100:
#     必ず実行する処理
    i += 1
#     FIzzBuzzの時だけ処理を変える
    if i % 15 == 0:
        print(f'FizzBuzz({i})')
        continue
    elif i % 3 == 0:
        print(f'Fizz({i})')
        continue
    elif i % 5 == 0:
        print(f'Buzz({i})')
        continue

    #　スッキプ時以外に実行
    print(i)
```
Julia: MariaDB のバージョンを表示

## プログラム

フォルダー構造

```text
$ tree -a
.
├── .env
├── config_mariadb.jl
└── server_version.jl
```

```jl:server_version.jl
#! /usr/bin/julia
#
#	server_version.jl
#
#						Feb/24/2023
# --------------------------------------------------------------------
using MySQL

include("config_mariadb.jl")
# --------------------------------------------------------------------
println(stderr,"*** 開始 ***")

host, user, password, data_base = config_mariadb_proc() 
conn =DBInterface.connect(MySQL.Connection, host, user, password)
command = "SELECT VERSION ()"
println(command)
#
results = DBInterface.execute(conn,command)
#
for row in results
	println(row)
end
DBInterface.close!(conn)
#
println(stderr,"*** 終了 ***")
# --------------------------------------------------------------------
```

```jl:config_mariadb.jl
#
#	config_mariadb.jl
#
#						Feb/24/2023
# --------------------------------------------------------------------
using DotEnv
# --------------------------------------------------------------------
function config_mariadb_proc()
	DotEnv.config()
	host=ENV["host"]
	user=ENV["user"]
	password=ENV["password"]
	data_base=ENV["data_base"]
#
	return host, user, password, data_base
end
# --------------------------------------------------------------------
```

```text:.env
host = '127.0.0.1'
user = 'scott'
password = 'tiger123'
data_base = 'city'
```

## 実行結果

```text
$ ./server_version.jl 
*** 開始 ***
SELECT VERSION ()
MySQL.TextRow{true}:
 Symbol("VERSION ()")  "10.11.2-MariaDB"
*** 終了 ***
```

## 確認したバージョン

```text
$ julia -v
julia version 1.8.5
```
Omni.Anim.Peopleなのに人が動かないんです!！

# 前回のおさらい

https://zenn.dev/manyan3/articles/848b910b98786b

https://qiita.com/Manyan3/items/473ab61aacc1e593b165

* リンクは以下のような内容です。
    * Zenn：Carterが走るまでの手順とAnaconda環境
    * Qiita：ハマった内容。振り返り
  
# １．新版IsaacSIM 2022.2.0リリース

* メニューの配置がだいぶ変わりました・・・それに意味はあるのでしょうか？
    * Ubuntu22.04 クラゲ対応と新機能の追加
    * 低スペックマシンでも割と起動は早くなっている！


:::note info
今回の目玉？作業
Omni.Anim.Peopleの追加　Humbleがらみの機能等々（いくつかは22.04必要なので。。。）
:::


# 2．Omni.Anim.Peopleをやります

* きっかけはOmniverse Launcherでのニュースにあったから試してみようと

https://qiita.com/Manyan3/items/473ab61aacc1e593b165


:::note info
補足
* カテゴリにROS2追加してはいるのですが、ここではROS2有効にしなくてもCarterは動くんですよね。
* 味見程度ですので、念のためROS2も入れておきました。

:::

https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/ext_omni_anim_people.html#troubleshooting

### サンプルを呼び出すだけならスイスイ進みます。

:::note warn
注意
* 強いて注意点を挙げるなら、WindowメニューのExtensionのチェック
* 続いて、設定するBiped_SetupとPeopleの設定漏れの有無

:::

**画面を見るとわかるのですが、なんかおかしいとおもいませんか？
なんか氷みたいな板が波打っています。**

* やな予感のまま解説通り進めていきます。
* T字に腕を伸ばした数人の人たちがCarterを邪魔すべく動くのでしょうか？
* 人間の座標軸が違っているので、動かない前提なのでは？？


### 結果、Carterだけがせっせと障害物回避で人間は気を付けポーズ

# 3．まずは人間だけでも歩いてもらいます。

* チュートリアルのスクラッチでは当然のように動かなかったので、調べてみました。

**Matiiiiiiiiiiiiiiiiii !!**

https://www.youtube.com/watch?v=MG3uQwW3t1Q

* MatiさんのチャンネルでOmni.Anim.People を動作させていました。

:::note info
Thanks!
* I can control people by your useful video!
* あ、Youtubeにお礼してきます…

:::

**基本的にはMatiさんの動画の20分以降のステージ作成操作で動作します**

* 結果的に2日かかったのですが、どうもMatiさんの丁寧な操作でハマったようです。
* Biped_Setupのからアニメをとり、人間はpythonとtxtの行動指示で動作するのですが
→保存して、再読み込みしている際にスクリプトが吹っ飛んだ模様です。

```IsaacSIM：コンソール

# 基本的に Navigation Volumeの高さ(Height),形状は自分が作ったフィールドサイズに依存
♯ 私は動画より小さいフィールドだったので0.2,0.3でつくってみました。　   


```

# 4．動作サンプル


https://www.youtube.com/watch?v=5aS7wZEwiu0


**環境によると思いますが、私の環境ではサンプル内の人間がすでに壊れている(または動かない）状態になっていると思われます**

:::note info
注意
* Beta版だけあって、スリープに起こった後に動作しなくなりました。
* いつでも安定動作するといいのですがね~
* もう1回作り直してみると、セーブでもターミナルエラー表示。ログも500MB超
* スクリプトのパーミッション関連の警告を進めて動く例もあれば、動かないことも…

:::
【シェルスクリプト .sh】 RedHat 7  , クーロン、バックアップファイルをLandisk へコピー、定期処理。

### ■用途
・RedHat 7のサーバー上にダンプされるファイルを、シェルスクリプトにてLandiskへバックアップする。

#### ■コード
``` .sh
#!/bin/sh

LOG_FILE="/usr/local/jim/nibkcp.log"

exec > ${LOG_FILE} 2>&1
df -
echo "Backup Start"

mount -t cifs -o username=???,password=zzz //192.168.1.4/ni /mnt

mv /mnt/NewNIbackup /mnt/OldNIbackup

mkdir /mnt/NewNIbackup
\cp -f /var/tmp/ni-backup/ni-dir-1.tar.gz /mnt/NewNIbackup/ni-dir-1.tar.gz
\cp -f /var/tmp/ni-backup/nidb6-db-1.tar.gz /mnt/NewNIbackup/nidb6-db-1.tar.gz
\cp -f /var/tmp/ni-backup/nidb6_files-db-1.tar.gz /mnt/NewNIbackup/nidb6_files-db-1.tar.gz
\cp -f /var/tmp/ni-backup/app-dir-1.tar.gz /mnt/NewNIbackup/app-dir-1.tar.gz
umount /mnt

echo "Backup Finish"
```

##### ・mount

・下記コマンドで、Landisk（共有サーバー）へ、username と password を引数で入れ接続する。
mount -t cifs -o username=???,password=zzz //192.168.1.4/ni /mnt

##### ・cp

cpコマンドの**頭に、\をつける**ことで、**cpコマンドがもつデフォルトの挙動を無効化**している。
Ubuntuのアップデートしたら ssh hostname.local でログインできなくなった事の対策 (avahi-daemonの設定)

Mac の多い環境などで重宝する `mDNS` サービス(DNSサーバが居なくても .local でLAN上ホスト同士が名前解決して通信出来る機能)が、ubuntuのポイントアップデート後に機能しなくなってしまいました。

推測ですが、`初期インストール時と異なるNICを使用している`と発生する気がします。
（今回は、二台とも 10GbE対応マシンだったのですが、セットアップした人が 1G専用ポートの方に刺して作業したっぽい）

`netplan` 周りによりスマートな解決策がありそうな気もしますが、今回は手っ取り早く `avahi-daemon` の設定ファイルを弄ってサービスを再起動して対応しました。
NICを差し替える予定がない限りこれで大丈夫かと思います。


## ubuntuではこのファイルを編集
```bash
sudo nano /etc/avahi/avahi-daemon.conf
```

ファイルの上の方に下記の項目がありますので、一箇所書き換えて保存
```yaml
[server]
#host-name=foo
#domain-name=local
#browse-domains=0pointer.de, zeroconf.org
use-ipv4=yes
use-ipv6=yes
allow-interfaces=enp6s0  # <- このコメント解除して実際に使っているインタフェース名を記載
#deny-interfaces=eth1
#check-response-ttl=no
```

サービスをリスタート
```bash
sudo service avahi-daemon restart
```

これで外部からまた無事に見えるようになりました！


この間 .local では名前解決できませんが、
IP直打ちや、他のインタフェース（ウチではWireguard）経由などでログインして上記対応をすれば .local でのアクセスが復活できます。
composeでSpannableを実装する

# 初めに
今回は従来のSpannableをComposeで実装する方法を紹介していきます
### 本文
実装自体はとても単純で、`compose`自体に似たような機能が生えているのでそれを使うだけです
```kotlin
Text(
    text = buildAnnotatedString {
        append("hoge")
        withStyle(
            SpanStyle(
                color = R.color.red,
                fontWeight = FontWeight.Bold
            )
        ) {
            append("fuga")
        }
    }
)
```
上記のコードを書くとデフォルト表示で`hoge`が表示され、その後ろに赤色太字で`fuga`が表示されるようになります
### 最後に
今回は自分が実装していくのに調べたものを備忘録程度に残しておきました
どなたかの役に立てれば幸いです
OCI コンテナ・インスタンスと標準VMの違い

このシリーズの他の記事は、[オラクル・クラウドの個人ブログ一覧 ](https://qiita.com/letian/items/10152a4fec813c1b7d98)からご覧いただけます。

# 初めに
[以前の記事](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98#6-oci%E3%81%A7-nginx-%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B)で、OCI コンテナ・インスタンスと OCI Compute インスタンス（標準VM）の両方で Nginx コンテナを実行する方法を紹介しました。 今回は両者の違いについて少しまとめてみたいと思います。

__OCI コンテナ・インスタンスでの Nginx コンテナの実行__
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/e8d211c2-9eec-d198-44d3-46136d39931c.png", width="650">
__OCI Compute インスタンスでの Nginx コンテナの実行__
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1121622/35e9ddf5-2002-3e2f-f108-d1789ba69f52.png", width="650">
__比較__
|分類|項目|OCI Container Instance|OCI Compute Instance|
|:--|:--|:--:|:--:|
|プラットフォーム|OSの選択可否|<strong>No</strong>|Yes|
|シェイプ|利用可能のタイプ|CI.Standard.<font color=blue>E4</font>.Flex<br>CI.Standard.<font color=blue>E3</font>.Flex<br>CI.Standard.<font color=blue>A1</font>.Flex|全てのタイプ|
|ネットワーク|パブリック/プライベート・サブネット|両方をサポート|両方をサポート|
||パブリック IPv4 を割り当てるか否か|両方をサポート|両方をサポート|
||インスタンスへの SSH ログイン|<strong>No</strong>|Yes|
|ストレージ|エフェメラル・ストレージ|<font color=blue>15 GB</font> (デフォルト)|No|
||ブロック・ボリュームをアタッチ|No<br>(対応予定あり)|Yes|
||ファイル・ストレージをアタッチ|No<br>(対応予定あり)|Yes|
|コンテナ|複数のコンテナの実行|Yes|Yes|
||インスタンス作成後、コンテナの追加・削除可否|<strong>No</strong>|Yes|
||各インスタンスにはコンテナの上限値|<strong>60</strong>|制限なし|
|レジストリ|OCI レジストリ or 外部|両方をサポート|両方をサポート|
|ロードバランサー|バックエンドに追加|<strong>Yes</strong> (※1)|Yes|
|ライフ・サイクル|状態|<font color=blue>Active</font><br><font color=blue>Inactive</font><br><font color=blue>Deleted</font>|Running<br>Stopped<br>Terminated|
||起動・停止・再起動の可否|Yes|Yes|
|価格|価格表|[リンク](https://www.oracle.com/jp/cloud/cloud-native/container-instances/pricing/) (※2)|[リンク](https://www.oracle.com/jp/cloud/compute/pricing/)|

※1. ロード・バランサーの<strong>作成後</strong>、<strong>プライベート IP を指定</strong>してコンテナ・インスタンスをバックエンドに追加できます。Compute インスタンスの場合、LBの<strong>作成中または作成後</strong>にバックエンドに<strong>直接追加</strong>できます。

※2. コンテナ・インスタンスに割り当てられた<strong>CPUおよびメモリー・リソース</strong>の価格は、 選択したシェイプの<strong>OCI Compute Instancesの価格と同じ</strong>です。 各コンテナ・インスタンスには、<strong>追加料金なし</strong>のデフォルトで<strong>15 GBのエフェメラル・ストレージ</strong>があります。

以上

----
__関連記事__
[オラクル・クラウドの個人ブログ一覧](https://qiita.com/liu-wei/items/10152a4fec813c1b7d98)
[OCI コンテナ・インスタンスでNginxコンテナを実行する](https://qiita.com/liu-wei/items/19b03223e03d82818e7c)
[OCIでNginxのDockerイメージを利用する](https://qiita.com/liu-wei/items/4ec173280cb32fb5e31a) (Compute インスタンス)

__ドキュメント__
[Container Instancesに関するよくある質問](https://www.oracle.com/jp/cloud/cloud-native/container-instances/faq/)