OmniAICreator/Qiita-1.07M huggingface dataset:
yaml-cppを使って実験パラメータの管理する


## C++でパラメータの管理をしたい！
卒論でC++を使ってる時、パラメータをヘッダファイルにマクロ定義して動かしていたが、**値を変えるたびにコンパイルが必要で、プログラムが大きくなるとコンパイル時間も長くなり困った**ので、パラメータをyamlで管理して、引数として渡すことにした。良さげなライブラリがないか探すと[yaml-cpp](https://github.com/jbeder/yaml-cpp)を見つけたので、始め方を記録として残す。


## ディレクトリ構成
```bash
$ tree
.
|-- CMakeLists.txt
|-- build
|-- config
|   |-- conf_1.yaml
|   `-- conf_2.yaml
`-- src
    `-- main.cpp

$
```

## CMakeLists.txtに以下を追加
READMEに従ってCMakeLists.txtを編集する。やってることはリポジトリをクローンしてリンクするようにするよってだけ。

```diff:CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(main)

set(CMAKE_CXX_STANDARD 11)

+include(FetchContent)

+FetchContent_Declare(
+  yaml-cpp
+  GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
+  GIT_TAG yaml-cpp-0.7.0 # Can be a tag (yaml-cpp-x.x.x), a commit hash, or a branch name (master)
+)
+FetchContent_GetProperties(yaml-cpp)

+if(NOT yaml-cpp_POPULATED)
+  message(STATUS "Fetching yaml-cpp...")
+  FetchContent_Populate(yaml-cpp)
+  add_subdirectory(${yaml-cpp_SOURCE_DIR} ${yaml-cpp_BINARY_DIR})
+endif()

add_executable(main
    src/main.cpp
)

+target_link_libraries(main PUBLIC yaml-cpp::yaml-cpp) # The library or executable that require yaml-cpp library
```

## 使ってみる

### 想定するyamlファイル
以下のようなyamlファイルを読み込んで面積を計算する。
```conf_1.yaml
size: 2000
range_x:
  min: -10.0
  max: 10.0
range_y:
  min: 100.0
  max: 200.0
```

### プログラム本体

- YAML::LoadFile : yamlファイルの読み込み
- 値の取り出しはoperator[]からのasメソッドでできるみたい（STLにも対応している←嬉しい）
```main.cpp
#include <iostream>
#include <vector>
#include <string>
#include <map>

#include "yaml-cpp/yaml.h"

using std::vector;
using std::string;
using std::map;
using std::cout;
using std::endl;

int main(int argc, char** argv)
{
    const auto conf_file = string(argv[1]);
    YAML::Node config = YAML::LoadFile(conf_file);

    // 値を取り出す
    const auto size = config["size"].as<int>();
    const auto range_x = config["range_x"].as<map<string, double>>();
    const auto min_y = config["range_y"]["min"].as<double>();
    const auto max_y = config["range_y"]["max"].as<double>();

    // coutで出力できる
    cout << config << endl;

    const auto width = range_x.at("max") - range_x.at("min");
    const auto height = max_y - min_y;
    const auto s = width * height;

    cout << "------" << endl;
    cout << "Area size: " << s << endl;

    return 0;
}

```

### 実行結果
```bash
$ cd build
$ cmake ..
$ make -j4
$ ./main ../config/conf_1.yaml
size: 2000
range_x:
  min: -10.0
  max: 10.0
range_y:
  min: 100.0
  max: 200.0
------
Area size: 2000
$
```

## まとめ
他にもOpenCVやBoostにも入っているみたいなので、すでにそれらを使っている場合はそちらを使いましょう。今回、どちらも使っていない環境でしたのでyaml-cppを使ってみました。[yaml-cpp](https://github.com/jbeder/yaml-cpp)は簡単にはじめられて、使い方もシンプルなので、yamlでパラメータを管理したいけど、今使ってるライブラリには入ってないよ... って人は検討してみてください。
【Kotlin*Spring】登録画面作成



# 本記事の内容

以下図のような、メニュー画面から開かれる登録画面を表示する際のControllerの記載について下記に記す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202056/997b4212-3285-17d2-56d7-af1908654ec6.png)







## ■Controllerクラス
```kotlin:AccountController.kt
@Controller
class AccountController {

    @GetMapping("/account/form/") 
    fun init(model: Model, form: AccoutnCreateForm) {
        // View返却（templates配下のHTMLファイルを指定）
        return "account/userCreateForm"
    }
}
```
※``(model: Model, form: AccoutCreateForm)``と記載することで、formをModelに格納してくれる。HTML側で使用する際の属性名はクラス名の先頭文字が小文字になったもの。

ちなみに@ModelAttributeを付与することで、以下のようにも書ける

```kotlin
@Controller
class AccountController {
    // Handlerメソッド実行前にFormをモデルに詰める。
    @ModelAttribute
    fun setUpForm(): AccoutnCreateForm {
        return new AccoutnCreateForm()
    }

    @GetMapping("/account/form/") 
    fun init(model: Model) {
        return "account/userCreateForm"
    }
}
```

## ■Formクラス
```kotlin:AccountCreateForm .kt
data class AccountCreateForm implements Serializable (
    private const val serialVerisionUID = 1L // セッションスコープで扱う場合必須
    // ユーザ名
    val userName: String,
    // 電話番号
    val tel: String,
    // メールアドレス
    val email: String,
)
```

## ■HTML
```html:userCreateForm.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">
<head
  th:replace="common/head :: head_fragment(title = 'ユーザー新規登録', scripts = ~{::script}, links = ~{::link})"></head>
<body>
  <div class="container">
    <div th:if="${validationError}" th:each="error : ${validationError}">
      <label class="text-danger" th:text="${error}"></label>
    </div>
    <h1>登録画面</h1>
    <form th:action="@{/user/confirm/}" th:object="${accountCreateForm}" th:method="post">
      <div class="form-group">
        <label>ユーザ名<span class="text-danger">※</span></label>
        <input type="text" th:field="*{userName}" class="form-control">
      </div>
      <div class="form-group">
        <label>電話番号<span class="text-danger">※</span></label>
        <input type="text" th:field="*{tel}" class="form-control">
      </div>
      <div class="form-group">
        <label>メールアドレス<span class="text-danger">※</span></label>
        <input type="text" th:field="*{email}" class="form-control">
      </div>
      <br />
      <div class="text-center">
        <a href="/user/menu/" class="btn btn-secondary">キャンセル</a>
        <input type="submit" value="　確認　" class="btn btn-primary">
      </div>
    </form>
  </div>
</body>
</html>
```


## ★フォームオブジェクトとHTMLフォームの紐づけの方法
- formタグの``th:object属性``に「modelAttribute」に追加したフォームオブジェクトの属性名を指定
- 各入力項目の``th:field属性``にフォームクラスのプロパティ名を指定
```html
<form th:action="@{/user/confirm/}" th:object="${accountCreateForm}" th:method="post">
      <div class="form-group">
        <label>ユーザ名<span class="text-danger">※</span></label>
        <input type="text" th:field="*{userName}" class="form-control">
      </div>
      <!--/* 中略 */-->
```
今更インターフェースを使いだした

# 始めに
この記事は覚えた内容をアウトプットした記事ですが、日記見たいな気分で書いています。
誤字脱字や覚えた内容が間違っている可能性があるので予めご了承ください。

# 参考にしたリンク
https://qiita.com/muniel/items/669a82ef9cb336985bd8#%E3%81%BE%E3%81%A8%E3%82%81

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

# インターフェースでつまづいた事？
・メソッドの実装を強制させる事が出来るくらいのイメージ感だった
・利用するタイミングがよく分からなかった

# インターフェースのメリット
・似たような処理を減らせる
・数値管理

# インターフェースのデメリット
・クラスが増える（デメリットかも？）
・明示的な実装にしないとどれがインターフェースなのか分かりにくくなる

# 実装したコード
・インターフェース
```C#
public interface IMoveable
{
    /// <summary>
    /// 移動に関する処理を行う
    /// </summary>
    public void Move();
}
```
・インターフェースを持っているクラス
```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utility;

public class StateActionManager : MonoBehaviour, IMoveable
{
    void IMoveable.Move()
    {
        Debug.log("Move !!");
    }
}

```
後はIMoveableをGetComponentや何かしらで取得する事が出来れば他クラスでも利用する事が出来ます。似たような処理を書く時に便利だと思います。

他にも数値だけを管理するインタフェースも作成すると便利です。
・インタフェース
```C#
public interface IMoveParameter
{
    /// <summary>
    /// 移動速度
    /// </summary>
    public float MoveSpeed { get; }
}
```

・インターフェースを持っているクラス
```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Utility;

public class StateActionManager : MonoBehaviour, IMoveParameter
{
    private float moveSpeed = 3;
    float IMoveParameter.MoveSpeed => moveSpeed;
}
```
先ほどと同じようにこのクラスのインターフェースを参照すると同じ数値が返ってきます。
もう一つ良いと思う所は他クラスからは数値を変更する事が出来ないとかですかね。

# 結論
・似たような処理を減らせて便利
・キャラクターの数値管理とかにも便利
（あくまで個人的にそう思っただけです。）

# 追記
明示的に実装したインタフェースを利用する方法がないかなと調べた所ありました。

https://qiita.com/TsuyoshiUshio@github/items/ee1b0669839a95b229e0
今日のトリビア MS-EdgeとGoogle Chromeのショートカットキーはほぼ同じ

# OSは Windows
MACはちょっと使ったことがないので...
なお、Edgeは(新)Edge以降。つまりChromiumエンジンを使用している。
# EdgeとChromeを同時使用していると
Chromeのつもりで入力した命令がEdgeでも有効に動いている。

# 気づいている人はいる
[閲覧履歴に気をつけてブラウザーを使う (ショートカット キー)｜クリエアナブキのちょこテク](https://www.crie.co.jp/chokotech/detail/658/)
例えばシークレットモードや履歴は同じである。

[Chrome と Edge のキーボードショートカット比較と一覧表 - パソコントラブルＱ＆Ａ](https://www.724685.com/weekly/qa230607.htm)
> Q.ブラウザーの Google Chrome と Microsoft Edge でキーボードショートカット（ショートカットキー）に違いはありますか？
A.回答ほぼ同じですが、いくつか違って片方だけのものあるので総合まとめと比較一覧表を作りました。

## というかFireFoxも
[10 Keyboard Shortcuts That Work in Chrome, Edge, and Firefox Browsers - ON - Kingston](https://microage.ca/kingston/10-keyboard-shortcuts-that-work-in-chrome-edge-and-firefox-browsers/)
>Google Chrome、Microsoft Edge、Mozilla Firefox は、現在使用されている最も人気のあるデスクトップ Web ブラウザーの 3 つです。  これらには、より効率的に作業できるようにする多くのキーボード ショートカットが用意されています。  幸いなことに、3 つのブラウザーすべてで同じショートカットの多くを使用できるため、ショートカットを覚えやすくなります。
 まだ使用していない場合に試してみるとよい、時間を節約する 10 のキーボード ショートカットを以下に示します。

 # (新)EdgeとChromeはわからないではないが
 この２つはエンジンが同じChromiumなのでショートカットキーが同じだということは十分ありうる。
 FireFoxはエンジンは違うが、ブラウザ同士で競争があるため、操作性で違いがないようにしてきていると思う。
 つまり一種の競争均衡が生まれているようだ。
Chromeをバージョン123にアップデートしてからpdfが読みづらくなった

# 概要
2024年3月，Chromeをバージョン123にアップデートしました。
アップデート後にpdf形式の文書を閲覧してみると，文字が薄く読みづらい状態になっていました。
この記事では，pdfの表示を元に戻す方法を述べます。


# 方法
- ブラウザ上で “chrome://flags/” にアクセスする
- “Use Skia Renderer” の項目を “Disabled” に変更する

  ![chrome設定画面スクショ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2571090/1b71962b-baf7-8818-d675-fc83fb23756f.png)

- ブラウザを再起動する


文書表示の比較画像です。
![pdf表示比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2571090/e785d527-cee9-4081-ea33-190a86e00147.png)
Apple Watchで開発者モードに入れなくなったときの話

- M3のMacbookAirが出たので早速買い換えたところ、xcodeでAppleWatchが繋がらなくなってしまい、AppleWatchの初期化等をしてもどうにもならなかったので、ネットで調べたところ、海外サイトの言うとおりに対応したらうまくいったので紹介する。
- 下図は、日本語翻訳した内容。

![Screenshot_20240311-182841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2733720/6ac2cd12-730b-a4db-7d9a-42f871436126.png)

- ネタ元

https://forums.developer.apple.com/forums/thread/718634?page=2
「エネ アン ペ ケ ヤ ケラミㇱカリ。」をアイヌ語Universal Dependenciesで解析する

[昨日の記事](https://qiita.com/KoichiYasuoka/items/8e8798e458aa064db427)の例文に対応する「エネ アン ペ ケ ヤ ケラミㇱカリ。」を、[esuparの助け](https://qiita.com/KoichiYasuoka/items/56e4e60f42d654bab672)を借りつつ、アイヌ語Universal Dependenciesで解析してみた。

```
# text = エネ アン ペ ケ ヤ ケラミㇱカリ。
1	エネ	ene	ADV	副詞	_	2	advmod	_	_
2	アン	an	VERB	自動詞	_	3	acl	_	_
3	ペ	pe	NOUN	名詞	_	5	obj	_	_
4-5	ケ	_	_	_	_	_	_	_	_
4	ㇰ	k=	PART	人称接辞	_	5	nsubj	_	SpaceAfter=No
5	エ	e	VERB	他動詞	_	8	advcl	_	_
6	ヤ	ya	SCONJ	接続助詞	_	5	mark	_	_
7-8	ケラミㇱカリ	_	_	_	_	_	_	_	SpaceAfter=No
7	ㇰ	k=	PART	人称接辞	_	8	nsubj	_	_
8	エラミㇱカリ	eramiskari	VERB	他動詞	_	0	root	_	_
9	。	.	PUNCT	記号	_	8	punct	_	_
```

![Shimoji9-25ain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/62c46668-8786-8aec-ea07-c8ff47b2726b.png)

何といってもヤヤコシイのは、一人称単数主語の「ㇰ」(k=)が、直後の動詞「エ」あるいは「エラミㇱカリ」とアンシェヌマンを起こして、「ケ」「ケラミㇱカリ」になってしまっている点だ。縮約の一種だとみなせば、何とかUniversal Dependenciesで書けるのだが、それにしてもヤヤコシイ。

また、「エラミㇱカリ」は他動詞なので、本来は目的語を必要とするのだが、この文では「エネ アン ペ ケ ヤ」全体を受けている。とすると、advcl (連用修飾節)ではなくccomp (節目的語)で繫いだ方が、あるいは適切なのかもしれない。一方、[昨日の記事](https://qiita.com/KoichiYasuoka/items/8e8798e458aa064db427)の例文との比較を考えるなら、advclの方がいいような気もする。何とも悩ましい。

ただ、私(安岡孝一)が見る限り、少なくともこの例文に関しては、アイヌ語とイラヴ語でかなり言語構造が違う。残念ながら、アイヌ語Universal Dependenciesの知識は、イラヴ語への転用が難しそうである。どちらも日本国内の言語のはずなのに、なかなか大変だなぁ。
【YouTube Data API v3】run_console()エラーが出るときの解決方法

## はじめに
備忘録
タイトルの通りです。
どなたかのお役に立てれば幸いです。

## 解決方法

Pythonでの、OAuth2.0認証のためには以下のモジュールが必要ですが、バージョンを指定しないとうまく動作しないことがあるようです。

```bash
pip install google-api-python-client==1.7.2
pip install google-auth==1.8.0
pip install google-auth-oauthlib==0.4.1
pip install google-auth-httplib2==0.0.3
```

:::note
また、GCPでのOAuthクライアントIDを作成するときに「ウェブアプリケーション」を選択すると、リダイレクトによる認証時にアカウント選択画面が表示されません。
「デスクトップアプリ」等を選択すると表示されます。
:::
BootstrapのDropDownメニューで苦戦した記録

### 背景 
本記事は、BootstrapのDropDownメニューで動作がおかしかったり、開かない、閉じないなどいろいろ問題が多すぎて、整理しました。

### 間違った認識の整理
1. 必要なjsはなにか？
1. 組み合わせで動作がいろいろ変わる
1. HTMLの書き方も2通りある
1. 情報が混乱、chatGPTも正確なアドバイスもらえず


### 前提条件
同じページに、DropDownメニューだけではなく、navバーも共存していること
DropDownメニューが正常動作した場合は、Navバーが動作しなくなることが発生
また逆も発生！！！

### 結論
1. navバーの動作前提は以下のバンドル（bootstrap.bundle.min.js）を読み込ませるのが必須
```html
<script src="{{ url_for('static', filename='/js/bootstrap.bundle.min.js')}}"></script>
```
2.DropDownメニューは、jquery版からJavaScriptで書き直し（ある意味では、Javascriptは便利）
JQueryを使うと3行で書ける
```javascript
$(document).ready(function () {
        $('.dropdown-toggle').dropdown();
    });
```
JavaScriptだといっぱい書かないといけない
```Javascript
document.addEventListener('DOMContentLoaded', function() {
    var dropdownToggleList = document.querySelectorAll('.dropdown-toggle');
    dropdownToggleList.forEach(function(dropdownToggle) {
        dropdownToggle.addEventListener('click', function() {
            var dropdownMenu = dropdownToggle.nextElementSibling;
            if (dropdownMenu.classList.contains('show')) {
                dropdownMenu.classList.remove('show');
            } else {
                // Close all other dropdowns
                var openDropdowns = document.querySelectorAll('.dropdown-menu.show');
                openDropdowns.forEach(function(openDropdown) {
                    if (openDropdown !== dropdownMenu) {
                        openDropdown.classList.remove('show');
                    }
                });
                dropdownMenu.classList.add('show');
            }
        });
    });

    // Close dropdown when clicking outside
    document.addEventListener('click', function(event) {
        var isDropdownTarget = Array.from(dropdownToggleList).some(function(dropdownToggle) {
            return dropdownToggle.contains(event.target);
        });
        
        var dropdownMenus = document.querySelectorAll('.dropdown-menu');
        dropdownMenus.forEach(function(dropdownMenu) {
            if (!dropdownMenu.contains(event.target) && !isDropdownTarget) {
                dropdownMenu.classList.remove('show');
            }
        });
    });
  });
```
HTML本体は
```html
<div class="container mt-5">
  <div class="dropdown">
    <button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
      Dropdown Menu
    </button>
    <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
      <a class="dropdown-item" href="#">Item 1</a>
      <a class="dropdown-item" href="#">Item 2</a>
      <a class="dropdown-item" href="#">Item 3</a>
    </div>
  </div>
</div>

<!--　不要　嫑-->
<!-- <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> -->
<!-- <script src="{{ url_for('static', filename='/js/bootstrap.min.js')}}"></script> -->
<script src="{{ url_for('static', filename='/js/dropdown.js')}}"></script>
<script src="{{ url_for('static', filename='/js/bootstrap.bundle.min.js')}}"></script>
```
### 注意点
※JQueryで作成前提のページには向かない
そろそろたくさんあるAI製品をいじってみるか。

ちまたには数千という数のAIサービスが出ているらしく、その中でも得に便利そうなものがキュレーションされてきましたね。

https://qiita.com/yoshiwatanabe/items/886aa164998140a55e56

ある程度ほとぼりが冷めたし、注目を集めているサービスを見てみることにしました。

なお、この投稿は完全に自分向けで、評価の基準も「自分にとって便利かどうか」だけです。普通に感想を書くつもりでしたがせっかくなので★を付けてみた、というだけです。

| AIプロダクト      | 自分的評価 |感想・意見| 
|---------------|-------------------------|-------------------------|
| character.ai  |　★☆☆☆☆　　　 |　アニメのキャラとかと話せるということで「ゾロ」と話してみたけどいまいちゾロっぽくなかった。他のキャラもあまり自分に役に立ちそうにない。オリジナルキャラも作れるけど、GPT作った方が早いような気がする                       |    
| Gemini | ★★★☆☆ | 言わずとしれた、Googleのサービス。ChatGPTにもある音声再生、Geminiの語りも悪くないですね。いままではChatGPTだけでやってきましたが、そろそろ他のモデルも使っていこうと思います。 |
| Poe        　　　　　　　　　|　★★☆☆☆☆　|いろんな生成AIモデルを試すのに最適かもしれません。GPT4などの最新のモデルは有料ですが、それ以外はポイントを使い切るまでは利用できます。ちょっとしたプロンプトで結果が上手くいかないときなどに他のモデルを「ちょい試し」するのに便利そうです。  |
| Claude  | ★★★☆☆　|最近GPT4超えと評価の高いAIモデルとサービス。UIのデザインはおしゃれだけど、既存の会話のリストが見当たらない（どこかにあるんでしょうけど）-- ちょっと直観的じゃないかな。無料で使えるモデルの日本語がかなり自然なので、ChatGPTなどでハマった時に、こちらの応答もチェックしてみようと思う。 |
| CrushOn | ★☆☆☆☆ | なんだろう、ライトノベルのような雰囲気。仮想のキャラとお話する感じの使い方かな。自分にはあまり使い道はなさそうです。 |
| Chub.ai | ★☆☆☆☆ | これもいまいち使い道はなさそうです。(会社からのアクセスはブロックされているので、そういう種類のサービスです）|
| NovelAI | ★☆☆☆☆ | 小説や物語を書くのが好きな人にはよいサービスかも。自分にはあまり意味ないです。 |
| MaxAI.me| ★★★☆☆ | ブラウザ拡張なのでどんなページを表示していても使えるようです。ユースケース的には便利そう。特にMediumのページの内容をサクッと要約するのに便利だと思うけど残念ながら要約は有料版にしかない。費用も決して安くないのですぐに課金という気分にはなれず。ただし、ページの内容をどんどん英語から日本語に翻訳できる機能はかなり便利です（これは無料機能、しかもPDFも翻訳してくれます）。当面の間ブラウザ拡張は入れたままにしておきす。 |
| CandyAI | ★☆☆☆☆ | バーチャル彼女（彼氏）と会話できる、みたいな機能ですね。自分には必要ないですが、需要はかなりあるでしょうね。 |
| Speechify | ★★★★☆ | ブラウザ拡張でウェブページを読み上げてくれます。（Kindle本などもサポートされています）。それだけなら別にどうということはないですが、読み上げがとても自然で、しかもいろんな人物（男性・女性、年齢など）の口調や声で読み上げてくれます - まだ無料版・有料版の違いが分かっていないので有料機能かもしれませんが。これは記事を読む時に、注意を持続できる。さらに英語の発音の練習にもなる。これはかなり使えますね。残念なのは日本語対応していないことですね。 | 
| Otter.ai | ★☆☆☆☆ | 文字起こしツール。自分は今のところユースケースはないけれど、学生さんが講義やディスカッションを記録して後で読み返したりとか、インタービューを録音しておくとか、人によってはとても便利かもしれません。話者を聞き分けて文字にしてくれるのは助かりますね。私の場合、仕事でTeamsを使うし、話者を分けた文字起こしはすでにあるので必要ないです。 |
| liner | ★★☆☆☆ | ５秒で価値が分かるか、というとそうでもない。多分、使ってみると賢いと思える機能が出てくる予感。ただUIは普通にChatから始まるし、他のProも要はGPTのような特化したモデル。これは同じプロンプトを投げてみてどういう結果になるかを見てみないと評価しずらい。一応キープします。 |
| DREAMGF | ★☆☆☆☆| バーチャルAI彼女ですね。僕は要らないです。 |
| Photomyme | ★☆☆☆☆| 古い写真をエンハンスするサービス。特化してますなぁ。たまに気が向いたら昭和の写真をキレイにしたいとか思うかもしれないけど、いつも使うサービスではないです。 |
| Civitai | ★★★☆☆ | 自分はLeonardo.ai をかなり使い込んでいたんですが（去年の今頃は毎日練習していた）それと似たり寄ったりですね。特にこれじゃなきゃ、という機能もちょっと触っただけでは見当たらない。 |
| Leonardo.ai| ★★★★☆| 単に慣れている、というだけかもしれませんが、お世話になりましたしこれからも使います。 |
| Midjourney | ★★★★☆| これがすごいのはわかっているけど有料ってこととDiscordのアカウントということで（今もそうなのかわからないけど）使うのは延期してました。実際のところ無料で使える画像生成サービスがいっぱいあるのでそれで物足りなくなったら使ってみよう、ぐらいの気持ちです。また別の機会にじっくり腰を据えて使いたいので今のところは放置。 |
| nightcafe | ★★★☆☆| どうやらちょうど１年前に使っていたようです。UIはかなりすっきりしていて使いやすい印象。アニメーションにする機能も簡単です（これはPro機能で、無料の場合はクレジットをすぐに使ってしまう）。画像は同じプロンプトでもいろんなサービスのモデルを試すのが良いので、これはまた使わせてもらいます。 |

今日はここまで。
後日、残りを続けます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103139/9a38c693-6960-4c0d-6edf-55b5954e624c.png)
マインクラフトで球体構築物の実装

## マインクラフトで、RCONのコマンドを発行し、球体の構築物を作ります。

### 1.NugetでCoreRCONを導入してください。

### 2.実装
以下、半球の構築物を作るコマンドを吐き出します。
縦に、半分に切れた半球で仲が中空になっていますので、中に入ることができます。

for文の終了条件180を360に変えると、球体になると思います。

```csharp:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MinecraftBall
{
    internal class CadPoint
    {
        public int x;
        public int y;
        public int z;

        public CadPoint(int x, int y, int z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }

    internal class Ball
    {
        public List<CadPoint> points = new List<CadPoint>();
        public Ball(int r)
        {
            for (int i = 0; i < 180; i++)
            {
                double rad1 = (2 * Math.PI * i) / 360;
                double zz = r * Math.Cos(rad1);

                for (int th = 0; th < 180; th++)
                {
                    double rad2 = (2 * Math.PI * th) / 360;

                    double xx = r * Math.Sin(rad2) * Math.Sin(rad1);

                    double yy = r * Math.Cos(rad2) * Math.Sin(rad1);
                                        
                    points.Add(new CadPoint((int)xx, (int)zz, (int)yy));
                }
            }
        }
    }
}

```

ドライバは以下のようになります。

```csharp:
using MinecraftBall;
using System.Net;
using System.Runtime.CompilerServices;


int r = 50;

var ball = new Ball(r);

var point = ball.points;

int x = 600;
int y = 40;
int z = 600;

var ipAddress = IPAddress.Parse(<ip-address>);
ushort port = <port>;
var password = <username>;
var connection = new CoreRCON.RCON(ipAddress, port, password);

await connection.ConnectAsync();

string bl = "stone";

foreach (var s in point)
{
    string str = string.Format("setblock {0} {1} {2} minecraft:{3}", s.x + x, s.z + y, (s.y) + z, bl);
    string respnose = await connection.SendCommandAsync(str);

    Console.WriteLine(str);
    Console.WriteLine(respnose);
}

Console.WriteLine("end");

await connection.SendCommandAsync("/time set day");
```

さいごに

球の表面積の座標を求めるアルゴリズム自体は、もしかしたら、球の表面積の大きさそのものを求めたり、証明をしたりする用途に使えるかもしれません。お時間があれば、ぜひ、[こちら](https://qiita.com/tsukuba3/items/20cc2beec781b4317ad7)もご覧ください。
-bash: /bin/rm: Argument list too long

`-bash: /bin/rm: Argument list too long` というエラーは、rmコマンドを使用して非常に多くのファイルを一度に削除しようとしたときに発生します。シェルはコマンドライン引数の最大数に制限があり、この制限を超えるとエラーが発生します。

### findコマンドを使用する

```sh
find . -type f -name "*.txt" -exec rm {} +
```


### xargsを使用する

```sh
find . -type f -name "*.txt" | xargs rm
```
MyBatisのSQLログからSQLを生成する

# SQL生成ツールを作成する
HTML+JSでローカル実行できるようにする。

"bind"ボタン　　　　… queryとparameterを結合
"make select"ボタン … INSERT句のqueryとparameterからSELECT句を生成

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="qBwReJz" data-user="fujisystem" 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/fujisystem/pen/qBwReJz">
  Generate SQL queries with MyBatis logs.</a> by fujisystem (<a href="https://codepen.io/fujisystem">@fujisystem</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
【Docker Compose】Dockerコンテナ・イメージ・ボリュームをまとめて消す方法

## はじめに
備忘録
タイトルの通りです。
どなたかのお役に立てれば幸いです。

## 方法

:::note warn
ボリュームも消すコマンドのため、注意して実行してください。
永続化したいデータがある場合はバックアップを取るなどしてください。
:::

```bash
# dockerコンテナ、イメージ、ボリュームをまとめて消す
$ docker compose down --rmi all
```
reject(&:empty?)と正規表現などを駆使して配列をいじる場合、grepが良さそう

## 課題
数字の文字列の配列として返却されるbook_idsを、整数の配列に変換し、さらに重複を除去したい。

```book_ids.rb
["1", "2", "2"]
```

## アプローチ1
rejectメソッドを使用して空の要素を除去し、selectメソッドで数値のみを含む要素を選択し、最後にmapメソッドで整数に変換し、uniqメソッドで重複を除去する方法。

```rb
book_ids = book_ids.reject(&:empty?).select { |id| id.match?(/^\d+$/) }.map(&:to_i).uniq
```

こんな感じです。
ただ、このままだとパッと見何をしているかわからず、もう少し工夫できそうです。

使えそうなメソッドがないか探し、Enumerable#grepが良さそうだなと思ったので、正規表現をそのまま活用して良い感じにできないか考えてみました。
https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/grep.html


## アプローチ2
grepメソッドを用いて数値のみを含む要素を選択し、その後mapメソッドで整数に変換し、uniqメソッドで重複を除去しました。

```rb
book_ids = book_ids.grep(/^\d+$/).map(&:to_i).uniq
```

マッチしなければ空の要素も一緒に排除されるので、こんな感じにすると一行でも読みやすくて良いと思いました。

## 測定
```rb
require 'benchmark'

book_ids = (1..100000).to_a.map(&:to_s)

Benchmark.bm do |x|
  x.report("reject & select:") do
    book_ids.reject(&:empty?).select { |id| id.match?(/^\d+$/) }.map(&:to_i).uniq
  end

  x.report("grep:") do
    book_ids.grep(/^\d+$/).map(&:to_i).uniq
  end
end
```

測定結果は見づらかったので、ChatGPTくんに頼んで表にしてもらいました。

| 方法              | 実行時間 (秒) |
|-------------------|-------------|
| reject & select   | 0.02796     |
| grep              | 0.01484     |

若干アプローチ2の方が速かったですね。

## 余談

他にも、重複があらかじめ多いとわかっている場合は`uniq`を先にするなどの工夫ができそうです。

また、grepは次のような機能を持っています。

>ブロックとともに呼び出された時には条件の成立した要素に対してそれぞれブロックを評価し、その結果の配列を返します。マッチする要素がひとつもなかった場合は空の配列を返します。

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/grep.html


ですから、mapの部分もこれでできそうですね。ただ、自分はアプローチ2のままの方が読みやすかったので採用しました。

間違いやより良い方法があれば、ぜひアドバイスいただけると嬉しいです。

EnumerableはGoldの時によく出てきたので、こちらのリンクも掲載します。
[【2023年12月版】Ruby Gold v3 受験記 + 参考リンク集](https://zenn.dev/yuki82511988/articles/6c81d97c5e5fee)
【Docker Compose】Networkの確認＆削除する方法

## はじめに
備忘録
タイトルの通りです。
どなたかのお役に立てれば幸いです。

## Networkの確認

`docker network ls`コマンドでネットワーク一覧を表示します。

`docker-compose.yml`で、
```docker
networks:
  network:
    name: sample_network
```
のように書いている場合、出力は以下のようになります。

```bash
＄ docker network ls
NETWORK ID     NAME            DRIVER    SCOPE
e635d0d8923d   bridge          bridge    local
bdb92225ddba   host            host      local
525777c8bd4f   sample_network  bridge    local
4cfd2f0ac727   none            null      local
```

## Networkの削除

`docker network rm`コマンドを使ってネットワークを削除します。

```bash
$ docker network rm sample_network
$ docker network ls
NETWORK ID     NAME            DRIVER    SCOPE
e635d0d8923d   bridge          bridge    local
bdb92225ddba   host            host      local
4cfd2f0ac727   none            null      local
```

Dockerコンテナが動いている場合、エラーが出力されます。

```bash
$ docker network rm sample_network
Error response from daemon: error while removing network: network hugr__apache_db id 13b10e6841f9bf63c3e885bfd669176acefa325c44699f5710932078040e6476 has active endpoints
```

`docker compose down`コマンドで一度止めてから、`docker network rm`コマンドを実行します。

```bash
$ docker compose down
$ docker network rm sample_network
```
ViでGit操作メモ

### 前提条件
Xcodeを使わずターミナルから直接修正したい場合
### メモ：バージョン変更
1. Githubから資源クローン
2. ブランチを作成、ブランチに移動 git clone -b 作成したブランチ git branch
3. grep -nr "MARKETING_VERSION" ./*
4. vi [スペース]変更したいファイルのパス 
例）vi ./iOS/AppName.xcodeproj/project.pbxproj
5. viに移動したら、スラッシュ/検索したい場所 ※大文字注意、スペースいらない
例）/MARKETING_VERSION
6. Nで検索結果に飛ぶ
7. 変更したい箇所にカーソルを合わせてR→変更したい文字を入力(R→2)
8. 全て変更し終わったら、:wq→Enter
9. あとは従来通り、diffって変わったことを確認してコミットなどに進む
【Excel】大量のデータやSQL文作成など

大量の文字列をカンマ区切り（CSV）にしたい時とか、SQL文作りたい時とか、Excel（スプレッドシート）で作ってました。

TEXTJOIN関数がおすすめです。
``` excel:TEXTJOIN関数
=TEXTJOIN(区切り文字,空のセルを無視するか,結合したいセル)

２要素目（空のセルを無視するか）：TRUE or FALSE
３要素目（結合したいセル）：範囲指定でも１セルずつ指定でも
```

# TEXTJOIN関数を利用したINSERT文作成
データ型に合わせてクォートつけたりつけなかったりするにはもう一手間必要ですが、省略します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736028/302240f6-bb06-d087-2d9e-f98cee5d8b99.png)


# ダサいけど分かりやすいver
項目間に区切り文字を入れたりしておくとただ結合（CONCAT）するだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736028/4d2ef0ad-d9d2-a47f-0b89-22e2679dc7e2.png)

# 終わりに
同じような操作を何度も繰り返す、とか同じような形式のものを大量に作る、とかは効率化を考える癖をつけたほうがいいですね。
当たり前のようで、意外と愚直にやってる人も多く・・・。
Githubよく使うコマンドのメモ


- クローン~プッシュ
https://qiita.com/yukiyoshimura/items/7aa4a8f8db493ab97c2b

git clone -b 作成したブランチ
ローカルのファイルを更新
git diff
git status
git add -A
git commit -m "任意のコメント"
git push origin ブランチ名
作成されるURLに飛ぶ

- ブランチ名の変更
https://qiita.com/shungo_m/items/4218e70751375b4bfeec

- git commitのviでよく使うコマンド(commitに-mをつけ忘れた場合)
 保存して終了
 　“ :wq”と入力！
LookerStudio：テキストに年度を足して日付フォーマットに変換

## LookerStudio テキストに年度を足して日付フォーマットに変換

- 1/不要なテキストを除外
https://support.google.com/looker-studio/answer/7583225?hl=ja
```
CASE 
    WHEN LENGTH(日付テキスト) = 10 THEN SUBSTR(フィールド名, -6, 4)
    WHEN LENGTH(日付テキスト) = 9 THEN SUBSTR(フィールド名, -5, 3)
    WHEN LENGTH(日付テキスト) = 8 THEN SUBSTR(フィールド名, -4, 2)
    ElSE "Other"
END
```

- 2/日付から今年度を抽出
https://support.google.com/looker-studio/answer/9702570?hl=ja&sjid=17178363230398134398-AP
```
EXTRACT(YEAR FROM 日付)
```

- 3/今年度を日付テキストに足す
https://support.google.com/looker-studio/answer/7583443?hl=ja&sjid=17178363230398134398-AP
```
CONCAT( 2/日付から今年度を抽出 ,"/",1/不要なテキストを除外)
```

- 4/テキストを日付フォーマットに変換
https://support.google.com/looker-studio/answer/9739156?hl=ja&sjid=17178363230398134398-AP
```
PARSE_DATE("%Y/%m/%d",3/今年度を日付テキストに足す)
```

- 5/当日に表示されたデータのみ取得
https://support.google.com/looker-studio/answer/7583307?hl=ja&sjid=17178363230398134398-AP
```
IF (DATE_DIFF(日付　, 4/テキストを日付フォーマットに変換) = 0, "true", "false")
```
- ","を含むテキストを除外
https://support.google.com/looker-studio/answer/10220936?hl=ja&sjid=17178363230398134398-AP
```
	WHEN REGEXP_CONTAINS(フィールド名, ",") = True THEN "Other"
```
【JavaScript】openでコントローラーのメソッドを呼んだ後にタブ名を設定する【ASP.NET】

JavaScriptのopenメソッドでコントローラーのCreatePDFメソッドを呼び出し、PDFファイルを別タブで開く処理を作った。

```js:JavaScript
function openFile() {
    let newWindow = open("/Home/CreatePDF");
}
```

```cs:C#
public class HomeController
{
    [HttpGet]
    public IActionResult CreatePDF()
    {
        // PDF作成処理
        ...
    
        return File(fileContents, "application/pdf");
    }
}
```

この状態だと、タブ名がコントローラーのメソッド名（CreatePDF）になってしまう。

以下のようにdocument.titleを設定したところ、最初の数秒は反映されるが、PDFの読み込みが終わったタイミングでタブ名がCreatePDFに書き換わってしまった。

```js:JavaScript
function openFile() {
    let newWindow = open("/Home/CreatePDF");
    newWindow.document.title = "タブ名";
}
```

## 結論
onloadとsetTimeoutを組み合わせ、PDFの読み込みが完了してから0.5秒後にタブ名を設定することで実現できた。(秒数は要調整)

```js:JavaScript
function openFile() {
    let newWindow = open("/Home/CreatePDF");
    newWindow.onload = function () {
        setTimeout(function () {
            newWindow.document.title = "タブ名";
        }, 500);
    };
}
```
Salesforce認定アドミニストレーター過去問+時々解説　Q11 ~ Q20

## Q11. 特定の項目に必ず一意のデータが入力されるようにするためには, どの設定が必要ですか？ 次から2つ選べ.

A 入力規則
B データ型
C ユニーク
D 必須項目

解答: C, D

解説: データが一意であるために「ユニーク属性」を有効化し, 必ず入力してもらうために「必須項目」の[値の入力を必須にする]にチェックを入れる.

## Q12. Web-to-リードを取り込み, 自動で情報送信者にメールを送信したいと考えているとき, リードの「国」情報に応じた言語でメールを自動返信するにはどのような設定が必要？

A 単一のメールテンプレート、トランスレーションワークベンチ、自動レスポンスルールの設定
B 言語ごとのメールテンプレート、ワークフローアラート
C 言語ごとのテンプレート、割り当てルール
D 言語ごとのメールテンプレート、自動レスポンスルールの設定

解答: D

解説: リードが作成されたタイミングでメールを自動送信したい場合は, リード自動レスポンスルールの設定をする必要がある. このルールの条件で値に国を指定し, メールテンプレートで選択すれば国に応じたメールの自動送信が可能になる.

## Q13. 新規ユーザーを作成する際, 管理者が必ず確認する必要があるものを3つ選べ.

A マネージャが設定されている
B ロールが設定されている
C ユーザ名がメールアドレスの形式である
D ユーザ名が全てのSalesforce組織で一意である
E プロファイルが選択されている

解答: C, D, E

解説: 承認者の設定でマネージャを設定することは可能だが必須ではなく, また, ロールの設定もライセンスによっては必須じゃないので非選択.

## Q14. レコードタイプを作成する前にビジネスプロセスを作成する必要があるのはどのオブジェクト？

A リード
B キャンペーン
C ソリューション
D 商談
E ケース

解答: A, C, D, E

解説: Lightning環境だとA, D, Eの設定だけだが, classic環境に切り替えるとCも存在する.

-- 複数のビジネスプロセスの管理 公式ヘルプ --
https://help.salesforce.com/s/articleView?id=sf.customize_processes.htm&type=5

## Q15. カスタムレポートタイプによって定義される要素を2つ選択してください.

A レポート作成時に列として使用できる項目
B レポートの形式
C レポート作成時に使用できるオブジェクト
D レポート結果に表示されるカスタム集計項目

解答: A, C

-- カスタムレポートタイプについて --
https://mrhappyneet.com/sfdc-custom-report-type/

## Q16. Salesforce for Outlookを使用して同期した後, 「私の未解決の項目」に表示される可能性があるものを2つ選択せよ.

A 取引先に割り当てられていない取引先責任者
B 取引先責任者に割り当てられていないケース
C レコードに関連付けられていないメモ
D レコードに関連付けられていないメール

解答: A, D

解説: Salesforce for Outlookはメールやカレンダーデータを「取引先責任者」, 「行動」および「Todo」へ連携する. メールの差出人は「取引先責任者」, メールの内容は「行動」「Todo」に自動参照され連携されるが, OutlookとSalesforceが自動照合できなかった項目は「私の未解決の項目」に表示される.

## Q17. どの機能が, ユーザーのSalesforceにログインする能力を制限するか？

A ログイン時間
B パスワードポリシー
C 信頼できるIP範囲
D ログインIP範囲

解答: A

解説: ログインIP範囲による制限は, 接続場所に対する制限であってユーザー個人のログイン能力を問うている設問の解答としては不適切. パスワードポリシーも文字数や組み合わせなどパスワードの内容に対する制限なので非選択. 設問の通りユーザー個人に対するログイン能力は, プロファイルから設定できる「ログイン時間帯の制限」によって制限される. 

## Q18. 各取引先レコードに次の情報を表示する必要があるとする.
 ・受注商談の金額合計
 ・進行中商談の金額合計
 この場合, どの機能を使用しますか？

A クロスオブジェクト数式
B 関連リストの集計項目
C 積み上げ集計項目
D ワークフロー項目自動更新

解答: C

解説: 積み上げ集計項目は従オブジェクトの金額項目を集計して, 主オブジェクトに表示することができる.

## Q19. レポートの条件付き強調表示はどの情報を強調表示することができますか？次から3つ選べ.

A カスタム集計項目
B テキスト項目値
C 総計値
D 集計値

解答: A, C, D

解説: 条件付き書式設定は, 集計値, 総計値, もしくはサポート内で作成するカスタム集計項目に背景色をつける機能である.

## Q20.商談フェーズに新しい値を追加したが, 追加した値がユーザーに表示されない. 対策は何が考えられますか？

A 追加した値の「有効」フラグを確認する
B 商談のページレイアウトを見直す
C レコードタイプに割り当てたセールスプロセスに値を追加する
D レコードタイプの選択リストに値が追加されていない

解答: C

解説: 商談でセールスプロセスを利用している場合, セールスプロセスごとに選択リスト値を変更することが可能. 追加した商談フェーズをセールスプロセスの選択リスト値に含めていなかったために表示されていなかった.

## Q21~Q30
https://qiita.com/taiga-shiokawa/items/fc8ccacecc0c232bba0b
Windowsエクスプローラーの検索窓からVSCodeを開く方法

Windowsエクスプローラーで作業中のフォルダーを直接VSCodeで開きたいことがあります。この記事では、エクスプローラーの検索窓に「vscode」と入力するだけ[^1]で、表示中のフォルダーをVSCodeで開くための設定方法を紹介します。

[^1]: 「右クリックで開く方法があるのだから、この記事の設定方法などは必要無い👹！」という主張はごもっともです(誰に言ってる笑)。ただ、たまに自分の使っているPC環境で右クリックで開く方法が使えないPCがあり、バイパス的に他の方法でも開けるようにしておいた方が便利で楽しいと思ったので、この記事の方法で設定することにしました。

## 必要なもの

- 以下のソフトウェアがインストールされたWindowsの作業用PC
  -  [Visual Studio Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code)
  -  基本的なテキストエディタ（Windows標準のメモ帳でOK）

## 手順 1: スクリプトの作成

1. 任意のテキストエディタを開きます（メモ帳でも構いません）。
2. 次のコードをコピー＆ペーストしてください。
　（久しぶりで忘れてましたが、`@echo off`は実行中のスクリプト内のコマンドを非表示にするコマンドです。）

```batch
@echo off
code .
```

3. このファイルを「vscode.bat」という名前で保存します。保存場所は、`C:\scripts\`など、後で覚えやすい場所にしてください。このパスは後で環境変数に追加します。(私は、自分ルールとしてPC移行の際に自分のユーザープロファイルフォルダー配下を移動することにしているので、同じような考えの方には`%USERPROFILE%\scripts\vscode.bat`をお勧めします。)

## 手順 2: PATH環境変数にスクリプトの場所を追加

1. スタートメニューを右クリックし、「システム」を選びます。
2. 「システム情報」を下にスクロールし、「システムの詳細設定」をクリックします。
3. 「環境変数...」ボタンをクリックします。
4. 「システム変数」の中から「Path」を探し、選択して「編集」をクリックします。
5. 「新規」をクリックし、スクリプトを保存したディレクトリのパス（例：`C:\scripts\`）を追加します。
6. すべてのウィンドウで「OK」をクリックして閉じます。

## 手順 3: 実行

セットアップが完了しました。これで、エクスプローラーのアドレスバーや検索窓に「vscode」と入力し、Enterキーを押すと、現在のフォルダーがVSCodeで開かれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518221/5610107c-5bb9-a7ab-b8a5-d63e07a3d13c.png)

## 注意点

- この方法の実行には、VSCodeがシステムのPATHに追加されていることが前提です。
- システムの設定やセキュリティポリシーによっては、期待通りに動作しない可能性があります。
- VSCodeを起動中は黒い画面が表示されてしまいます(ちょっと格好悪いです😅)。この一時的に表示される黒い画面自体を消す方法をご存じの方は、コメント欄で教えていただけますとありがたいです。

## 参考
- [「コマンド プロンプト」を「エクスプローラー」から開く最速の技 ～えっ、ソコ？ - やじうまの杜](https://forest.watch.impress.co.jp/docs/serial/yajiuma/1504991.html)
【Jetpack Compose】状態管理のためにremember、rememberSaveableの違いとSaverの活用

Jetpack Composeにおける`remember`、`rememberSaveable`、そして`Saver`の使用と、それらが状態管理にどのように役立つのかについて詳細に解説します。

### `remember`とは？

- **目的**: Composable関数内で状態を保持するために使用されます。

- **特徴**: `remember`はコンポジションが破棄されるまで（例えば、Composable関数がナビゲーションによって画面から削除される、アクティビティが破棄されるなど）その状態を保持します。

- **限界**: アクティビティの再作成（デバイスの回転やバックグラウンドからの復帰など）では状態が保持されません。再作成時には初期化コードに戻ります。

### `rememberSaveable`とは？

- **目的**: `remember`と同様に状態を保持しますが、アクティビティの再作成を越えて状態を保持することができます。

- **特徴**: `rememberSaveable`は、システムによる再作成（デバイスの回転など）後も状態を復元するために内部的に保存されたインスタンス状態を使用します。

- **用途**: UIの状態（ユーザーの入力や選択など）をアクティビティの再作成を越えて保持したい場合に適しています。

- **カスタムクラスの保存**: `Saver`インターフェイスを使用して、カスタムクラスや複雑な型の状態を保存・復元するロジックを定義します。

### `Saver`とは？

- **目的**: `rememberSaveable`によるカスタムクラスの状態保存を可能にします。

- **機能**: カスタムクラスをシステムが理解できる形式（例: リストやマップ）に変換（シリアライズ）し、その後、これらの形式から元のカスタムクラスのインスタンスを復元（デシリアライズ）します。

- **使用方法**: `rememberSaveable`の`saver`パラメータにカスタム`Saver`のインスタンスを指定します。

### 状態管理の流れ

1. **単純な状態（プリミティブ型など）**: `remember`や`rememberSaveable`を使用して状態を保持します。`remember`は一時的な状態保持に、`rememberSaveable`は永続的な状態保持に適しています。

2. **カスタムクラスや複雑な状態**: `rememberSaveable`とカスタム`Saver`を組み合わせて使用します。これにより、アクティビティの再作成を越えて状態を復元することが可能になります。

### まとめ

Jetpack Composeにおける状態管理は、`remember`、`rememberSaveable`、`Saver`を適切に使い分けることで、ユーザーインターフェイスの動的な挙動やアクティビティのライフサイクルを越えたデータの保持を効果的に実現できます。これらのツールを理解し、適切に使用することで、優れたユーザー体験を提供するアプリケーションを構築することができます。

### コード例を用いたまとめ

```kotlin
@Composable
fun CraneEditableUserInput(
    hint: String,
    caption: String? = null,
    @DrawableRes vectorImageId: Int? = null,
    onInputChanged: (String) -> Unit
) {
    // Codelab: Encapsulate this state in a state holder
    var textState by remember { mutableStateOf(hint) }
    var isHint = true

    CraneBaseUserInput(
        caption = caption,
        tintIcon = { !isHint },
        showCaption = { !isHint },
        vectorImageId = vectorImageId
    ) {
        BasicTextField(
            value = textState,
            onValueChange = {
                textState = it
                if (!isHint) onInputChanged(textState)
            },
            textStyle = if (isHint) {
                captionTextStyle.copy(color = LocalContentColor.current)
            } else {
                MaterialTheme.typography.body1.copy(color = LocalContentColor.current)
            },
            cursorBrush = SolidColor(LocalContentColor.current)
        )
    }
}
```

例えば上記の関数があった時に、textStateに変更が入ると、CraneEditableUserInputは再実行されます。その時、ローカル変数であるisHintは初期値（true）に戻りますが、textStateはrememberなので初期値に戻りません。

画面が回転した時も同様の挙動になります。


次に、Activityが破棄された時、textStateはrememberなので破棄されます。状態を保持したい場合はrememberSaveableに変更する必要があります。

そして、rememberSaveableにカスタムクラスを入れたい時（ListやMapや複数の値を持つクラスなど）にSaverが登場します。

```
rememberSaveable(saver = CustomSaver) { ... }
```

のようにすると、カスタムクラスの保存が可能になります。

余談ですが、static変数（companion object内の変数など）はどこからでも参照可能なのに対して、rememberSaveableは定義されたComposable関数内でのみ使用可能です。
gitbucketからgithubにリポジトリを移行してみた

## はじめに
gitbucketで管理していたリポジトリをgithubに移行した手順の備忘録です。
## 移行方法
プライベートなリポジトリの移行だったため、私は以下の手順で移行しました。
1. 移行先のgithub新規リポジトリを作成する
https://github.com/new
1. 移行元のgitbucketリポジトリを一度ローカルにクローンする
　```
git clone --bare https://gitbucket.hogehoge/fugafuga.git
　```
 ※``--bare``オプションを使うことで完全コピーのリポジトリをクローン可能
 ※このとき認証情報を聞かれるので、gitbucketのユーザー名とパスワードを用意しておく
1. クローンしたローカルの場所に移動する
　```
cd fugafuga.git
　```
1. 1で作成したgithubリポジトリに向けてプッシュする
　```
git push --mirror https://github.com/hogehoge/fugafuga.git
　```
  ※``--mirror``オプションを使うことでミラーリポジトリをプッシュ可能
  ※このとき認証情報を聞かれるので、gitbucketのユーザー名とトークンを用意しておく（**パスワードではないので注意**）
  ※トークンは (https://github.com/settings/tokens) で作成する（今回のリポジトリの移行ではプライベートリポジトリの権限さえあれば良いので、適当にNoteと有効期間を設定してrepoにチェックをつけるだけでOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641495/0686c03d-5d9a-ecb0-c2a5-05487fa9e77c.png)
1. 任意: githubリポジトリにデータ移行が出来たことを確認して、ローカルのリポジトリを削除する

## まとめ
プライベートなリポジトリでも簡単に移行できました。
今回は移行元がプライベートリポジトリだったので一度クローンしてプッシュしましたが、
パブリックリポジトリであればリポジトリのインポート (https://github.com/new/import) を使ってみるのも良さそうですね。

参考: https://docs.github.com/ja/repositories/creating-and-managing-repositories/duplicating-a-repository
AWS認定学習記(現在6冠)

## AWS認定学習記

①AWS認定をオンライン受験する際に、試験官（英語）を選択するメリット
　・[AWSのAssociate試験の試験官言語を英語にしたら凄く良かった](https://qiita.com/subaru44k/items/d08907a9a01ed80929cd)

②AWS認定を受験するモチベになった記事
　・[AWS認定11冠達成したので振り返りと個人的ロードマップを考えてみた](https://qiita.com/handy-dd18/items/d21d914bf1c475d777f2)
　・[【最速】既婚子持ち社会人のクラウド初心者でも、1ヶ月半でAWS資格11冠制覇できる方法](https://qiita.com/mrpepper/items/64039b828c82e12ad35f)

③学習教材の選択理由
　・[AWS12冠者によるCloudLicense (旧TechStock)とCloudTechの徹底比較](https://kyoukara-infra.com/cloudlicense-vs-cloudtech/)

④学習教材
　・[CloudTech](https://kws-cloud-tech.com/)
　・[AWSエンジニアロードマップ2023](https://qiita.com/KurokawaKouhei/items/3836802fc3a0286f668f)

⑤学習目的
・合格実績が自信とプレッシャーになり、やり抜く力が向上する
・特定分野を短期間に体系的に学べる
・錯覚資産（実務を積むための足掛かり）

⑥受験結果
【取得チェッカー】
| 資格 | 合格日 | 点数 |
|:---:|:----------:|:---:|
| CLF | 2024/04/07 | 821 |
| AIF | - | - |
| SAA | 2024/04/28 | 723 |
| SOA | - | - |
| DVA | 2024/07/27 | 763 |
| DEA | - | - |
| MLA | - | - |
| SAP | 2024/06/15 | 785 |
| DOP | 2024/06/29 | 784 |
| ANS | - | - |
| SCS | - | - |
| MLS | - | - |

【受験タイムライン】
| 資格 | 受験日 | 結果 | 点数 |
|:---:|:----------:|:-----:|:---:|
| SAA | 2022/11/18 | 不合格 | 574 |
| CLF | 2024/03/23 | 不合格 | 687 |
| CLF | 2024/04/07 | 🎉合格 | 821 |
| SAA | 2024/04/28 | 🎉合格 | 723 |
| SOA | 2024/05/12 | 不合格 | 706 |
| SOA | 2024/06/14 | 不合格 | 706 |
| SAP | 2024/06/15 | 🎉合格 | 785 |
| DOP | 2024/06/29 | 🎉合格 | 784 |
| DVA | 2024/07/27 | 🎉合格 | 763 |
| SOA | 2024/07/28 | 🎉合格 | 725 |

⑦合格後の感想

・CLF
　初めての認定合格で嬉しい
　試験の難易度は高くないが、試験問題を解かなければ合格は難しい

・SAA
　登竜門合格で嬉しい
　今までの学習方法が正しかったと実感
　次、どのレベル（アソシエイトorプロフェッショナル）を受験するか迷う

・SAP
　初めてのプロフェッショナル合格で嬉しい
　SAP合格後、アソシエイト資格の試験問題が簡単に見え、学習スピードが上がるためこのタイミングで受験してよかった
　問題の文章量、サービスの範囲が広いため、学習にはある程度の時間が必要

・DOP
　プロフェッショナルコンプリートで嬉しい
　SAA、SAPと異なる観点から出題される
　今までの学習も役に立つが、今まで触れてこなかったサービス（Code〜系）が出題される感覚

・DVA
　合格当時はAWS認定が全10資格だったため、半分取得で嬉しい
　DOPを合格しているからといって、簡単ではなかった
　
・SOA
　過去２回落ちていたため、やっと取得で嬉しい
　1番テキトーに受験勉強していたため、合格点ギリギリも納得。（SOAはなんかやる気出なかった）
　ちなみに２回落ちているが、１回目は受験中に強烈な腹痛、２回目は受験中に強烈な眠気に襲われていたため、それがなければ合格していたと思われる。
 　そういった事もあり、SOAには呪われていると思う。
jboss/keycloakが無くなったので、bitnami/keycloakを構築してみる

# まえがき
jboss/Keycloak を使っていたが、2024/3/20に確認したらdockerイメージが公式から消えてるやん！ということが判明。
代用品を探してところ、bitnami/Keycloakが使っているユーザが多いのでこれで構築しようと思った。

[2024/3/20時点] jboss/keycloakが無い・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750683/b8568ae0-1457-b376-c13f-2ed8d24c37fc.png)

## やりたいこと
認証データは一時的な開発用のものなのでDB構成は気にせず、とりあえずKeycloakを動かしたい。

## 参考
[Bitnami package for Keycloak](https://hub.docker.com/r/bitnami/keycloak/#!)

## docker-compose.yml ポイント
* bitnami/Keycloakは、jboss/Keycloakみたいにイメージ起動だけで動かない。postgresが必要。
* imageバージョンはlatestだと、数年立ったら動かないことも考慮してバージョン固定。
* jboss/Keycloakのポートが18080だったので、80→18080に変更。
````
version: '3.8'
services:

  postgresql:
    image: bitnami/postgresql:16.2.0
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
      - POSTGRESQL_USERNAME=bn_keycloak
      - POSTGRESQL_DATABASE=bitnami_keycloak

  keycloak:
    image: bitnami/keycloak:23.0.7
    ports:
      - "18080:8080"
    environment:
      - KEYCLOAK_CREATE_ADMIN_USER=true
      - KEYCLOAK_ADMIN=root
      - KEYCLOAK_ADMIN_PASSWORD=root
    depends_on:
      - postgresql
````

## docker-compose 実行
````
docker-compose build
docker-compose up
````

## 出来上がり
ブラウザで`localhost:18080`にアクセスすると、Keycloakページが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750683/896e3b95-1cbc-3e4a-3d7a-1c48a4693f3f.png)
【ChatGPT有＋DALL-E3】で、指定した対象物が変になる話。


　どうも、カーブミラーです。

　今回は、指定した対象物が変になる話を書きます。私流の対処方法も書きますよ😄

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　ニュースはありませんよw

　本題です。

　指定した対象物が
　　変になることはあるかと
　　　思います。

　例えば、
　　油揚げが、厚揚げ豆腐に
　　　なるとか。
　　　　（こんなものを
　　　　　　描こうなんて思わない？w）

　ほかにも
　　いなり寿司、
　　　おはぎ、
　　　　雛人形、
　　　　　茶運び人形
　　　　　　などなど。

　数えるのも
　　大変なほどです。

　なぜ描けないのか？

　それは
　　ChatGPTとDALL-E3が
　　　英語圏（特にアメリカ圏）の
　　　　サービスだからでしょうね。

　言葉は知っています。
　　でも、それと画像が
　　　結びついていない。
　　　　あるいは、詳細なことは
　　　　　知らないのです。

　だから
　　形状が食い違うとか
　　　大きさがデカいとかの
　　　　問題になるわけです。
***
　対処方法としては
　　いくつかあるかと
　　　思います。

　ひとつ。（ガチャに頼る方法です）
　　リトライを
　　　何度か繰り返す。

　ひとつ。（あまり効果はない）
　　形状や大きさを
　　　指定する。

　ひとつ。（冗談ではなく）
　　諦めるw

　ひとつ。（使える）
　　対象物に
　　　よく似たものを
　　　　指定する。

　とりあえず、
　　この四つですね。
　　　ほかにもあったかもですが
　　　　思い浮かびません。
***
　ふつうは、
　　ChatGPTに“修正して”と
　　　何度も指示するかと思います。

　それは
　　正解であり、
　　　不正解でもあります。

　そして
　　プロンプトを確認すると、
　　　ChatGPTは
　　　　きちんと仕事を
　　　　　していることが
　　　　　　わかります。

　問題は、
　　DALL-E3に
　　　“それが伝わっていない”
　　　　あるいは
　　　　　“間違って伝わってしまう”
　　　　　　ということなのです。
***
　では
　　どうするのか？

　例えば、
　　よくあることなのですが、
　　　“日本人女性”と伝えると
　　　　ほぼ“日本髪を結った和服女性”
　　　　　が生成されます。

　　しかも
　　　背景に、日本の庭園が。

　そういう風に
　　DALL-E3は学習して
　　　しまっているわけです。
　　　　“これには、これが”
　　　　　という感じに。

　“日本人女性”の先頭に
　　“現代の”と付けると
　　　現代女性が
　　　　ふつうの髪型に
　　　　　ふつうの洋服姿で
　　　　　　描画されます。
　　　　　　　背景もそれなりに。

　日本刀も
　　おかしくなりやすいものです。

　柄が長かったり、
　　鞘が柄のように
　　　なっていたり。

　こちらは
　　ガチャ要素が多く、
　　　リトライを繰り返すしかない。
***
　では
　　いなり寿司は
　　　どうするのか？

　たいていは
　　ふつうのお寿司のように
　　　シャリの上に、
　　　　ネタが載っている
　　　　　というものになります。

　いなり寿司は
　　本当に難しい課題です。

　まず第一に
　　油揚げを描けない。
　　　厚揚げを揚げたものになりますw

　第二に
　　カラーです。
　　　“きつね色”と指定すると
　　　　キツネさんが登場しますw

　第三に
　　形状です。
　　　ふつうに、寿司になりますw

　これらを
　　どうすれば描けるのか？
***
　まず、カラーですが
　　これは“オレンジブラウン”を
　　　指定します。

　次に
　　油揚げを描く。
　　　これも大変。
　　　　出てきた厚揚げを
　　　　　“薄い”と付けて描画。
　　　　　　それで調整。

　で、形状ですが
　　俵型が通じない(泣)

　こうして
　　頑張ってみて
　　　結果、諦めました😭

　ここは、
　　違う形状で
　　　良しとすることに。
***
　こんな風に
　　うまくいったり
　　　いかなかったり
　　　　ですねw

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
MyBatis/iBatisの同値検証におけるバグの分類

前回の記事「[MyBatis/iBatisの同値検証、sqlmapファイル（動的SQL）自体を単体テストする方法](https://qiita.com/5zm/items/583a934056f79a5d55c5)」で同値検証の方法は説明しましたが、既存バグもそのまま引き継ぎますね、ということでバグが何に起因するのか整理しました。今回は単なるポエムになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195748/46df2da6-0e76-4b0e-17fd-f12029eea9b3.png)
![MyBatis2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195748/3680a8e4-65e7-ea85-bd8e-784580fbff2d.jpeg)

下の２つ「変換NG」、「出力SQL　同値NG」はiBatisからMyBatisへの変換作業におけるプロセスの問題です。iBatisのSqlMapファイルのタグには属性によってオプショナルな動作を制御するものがあります。タグの使われ方を調査し、そのプロジェクトにおける使われ方のパターンを整理すれば対応できます。また、調査をするとたまに現行のコーディング規約に沿っていないものが発見されたりもします。

問題は真ん中の「出力SQL　構文NG」です。現行で利用しているiBatisのSqlMapファイルなので、これはまずいのですが、動的SQLが複雑（SQL自体がとても大きい、入れ子の階層が深い等）であったりすると、テストをしていないということが発覚したりします。

論理的に説明すればどこにバグの原因があるのか明確です。既存ソースコードの変換（マイグレーション）は大規模システムではWillと需要がある分野ですが、既存ソースコードの品質がしっかり担保されていることが前提です。完璧なマイグレーションとは、ある意味、バグも含めて現行仕様を踏襲していると言えるかも知れませんね。
Taichiでランク多態性の関数の書き方




# ランク多態性とは

さまざまな階数のテンソルを処理できる性質を私はランク多態性と呼んでいます。

なお、正式な用語ではないと思います。
こちらのスレッドの発言をそのまま使わせてもらっています。

https://github.com/arogozhnikov/einops/issues/22#:~:text=nice%20to%20write-,rank%20polymorphic,-code%20and%20there%27s

## einopsの例
たとえば以下のeinopsコードはランク多態性があります。
```py
rearrange(x, "b ... -> b (...)")
```
このコードは、テンソル`x`の形状を以下のように変更します。
(b, d1, d2, ..., dn)　→　(b, d1 * d2 * ... * dn)
※ b：バッチサイズ、d1、d2、...、dn：他の次元
例：x:(10, 3, 4, 5)　→　(10, 60)

明示したb軸以外はどのような形状でも処理できる柔軟性があります。


# Taichiとは
Taichiは、GPU並列処理をPythonで記述できるライブラリです。コンピューターグラフィックスでの利用が想定されています。

https://www.taichi-lang.org/


# Taichiでランク多態性の関数の書き方

以下のようにすると、さまざまな形状のテンソルを処理できます。
`upper_dims = ti.static(t.shape[:-2])`がポイントです。
`t.shape`は`ti.static`に記述することで、Taichiコードのコンパイル時にPythonスコープで処理しています。
なお、Taichiスコープで処理すると、`upper_dims`がコンパイル時に定数ではなくなります。すると、`ti.ndrange`には実行時変数を渡すことができないのでエラーになります。

参考　言語リファレンス　https://docs.taichi-lang.org/docs/language_reference

```python
import taichi as ti
ti.init()

@ti.kernel
def tmp(t:ti.template()):
    "t : tensor with shape of [... a b]"
    print("case: rank", len(t.shape))
    upper_dims = ti.static(t.shape[:-2])
    a,b = ti.static(t.shape[-2:])
    for I in ti.static(ti.ndrange(*upper_dims)):  # unrolled serial loop
        for i,j in ti.ndrange(a,b):  # parallel loop
            t[*I,i,j] = ti.random()
            print(*I, i, j, ":", t[*I,i,j])

t = ti.field(ti.f32, shape=(2,2,2))
tmp(t) #3
t = ti.field(ti.f32, shape=(2,2,2,2))
tmp(t) #4
```

出力例
```
case: rank 3
0 0 0 : 0.443271
0 0 1 : 0.658814
0 1 0 : 0.749135
0 1 1 : 0.650376
1 0 0 : 0.948321
1 0 1 : 0.177689
1 1 0 : 0.346885
1 1 1 : 0.772146
case: rank 4
0 0 0 0 : 0.476790
0 0 0 1 : 0.989344
0 0 1 0 : 0.668613
0 0 1 1 : 0.716511
0 1 0 0 : 0.748498
0 1 0 1 : 0.891527
0 1 1 0 : 0.252390
0 1 1 1 : 0.172357
1 0 0 0 : 0.697397
1 0 0 1 : 0.212697
1 0 1 0 : 0.038212
1 0 1 1 : 0.613680
1 1 0 0 : 0.370585
1 1 0 1 : 0.226127
1 1 1 0 : 0.529289
1 1 1 1 : 0.482478
```
Pythonで「正規表現にマッチした文字列を新しい文字列に置換する(Pattern.sub, Pattern.subn)」の動作を確認してみた

# 概要

Pythonで「正規表現にマッチした文字列を新しい文字列に置換する(Pattern.sub, Pattern.subn)」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/regex/index10.html

# 実装

以下のファイルを作成しました。
```sample.py
import re

msg = 'Border is Red, Box is red, Line is RED'
pattern = re.compile(r'Red|RED')

result = pattern.sub('red', msg)
print(result)

import re

msg = 'Border is Red, Box is red, Line is RED'
pattern = re.compile(r'Red|RED')

result = pattern.subn('red', msg)
print(result)

import re

msg = 'Red Blue Yellow Pink Green White'
pattern = re.compile(r'\b[a-zA-Z]+?\b')

result = pattern.sub('***', msg)
print(result)

import re

msg = 'Red Blue Yellow Pink Green White'
pattern = re.compile(r'\b[a-zA-Z]+?\b')

result = pattern.sub('***', msg, 2)
print(result)

import re

msg = '次の会議は 2020-12-03 です'
pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')

result = pattern.sub(r'\1年\2月\3日', msg)
print(result)

import re

msg = 'Product is AE-42'
pattern = re.compile(r'(?P<cate>[A-Z]{2})-(?P<code>[0-9]{2})')

result = pattern.sub(r'Category=\g<cate>/Code=\g<code>', msg)
print(result)

import re

msg = 'Border is Red, Box is Green, Line is BLUE'
pattern = re.compile(r'\b[a-zA-Z]+?\b')

def replaceStr(m):
    s = m.group(0)
    return s.lower()

result = pattern.sub(replaceStr, msg)
print(result)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
Border is red, Box is red, Line is red
('Border is red, Box is red, Line is red', 2)
*** *** *** *** *** ***
*** *** Yellow Pink Green White
次の会議は 2020年12月03日 です
Product is Category=AE/Code=42
border is red, box is green, line is blue
```

# まとめ

何かの役に立てばと。
github actionsとは？

# 経緯
オンプレでアプリの開発をすることになりました。

その際、自動デプロイで本番環境とステージング環境ができればみんな楽に動作確認ができる！

そんな思いから、以前使っていて少し馴染みがあったgithub actionsを調べた記事です。


# github actionsとは？
github actionsとは、ビルド、テスト、デプロイを自動化してくれるCICDのプラットフォームです。

例えば、以下のようなことが可能です。
- リポジトリのpull requestをビルドしてテスト
- マージされたpull requestを運用環境にデプロイ
- issuesの作成とともに適切なラベルの付与を追加
- pushしたら自動でpull requestを作成

まさにやりたいことができそうです！

ちなみに、pushしたら自動でpull requestを作成するワークフローも作成したので、後ほど記事にしたいと思います。

## github actionsの用語
### Workflows
github actionsの実行ファイルのこと。
1つ以上のジョブを自動実行する。

yamlファイルにより定義され、リポジトリ内の `.github/workflows`ディレクトリの中に格納される。

### Event
例えば、pull requestが作成された時、issuesが開かれた時、pushされた時など、どのような時にワークフローが動いて欲しいかを決める。

また、スケジュールに従って、APIで、手動で、ワークフローを動かすことができる。

### job
実行してほしいコマンドやスクリプトの一連をまとめたもの。

また、実行してほしいコマンドやスクリプトをステップという

通常、ジョブは依存関係がなく、並列で処理されるが、他のジョブとの依存関係も構成できる。

ジョブが他のジョブに依存する場合は、ジョブが完了するまで待ってからもう一つのジョブが実行される

### action
githubからのgitリポジトリのpull、ビルド環境に適したツールの設定やクラウドプロバイダーの認証設定をやってくれるもの。便利機能。

基本的に、すごい人が作ってくれたリポジトリがあるので、それを活用して複雑で頻繁な作業を簡略化できる。

独自のアクションを記述することも、人が作ったアクションを見つけることもできる。

https://github.com/marketplace?category=&copilot_app=false&query=&type=actions&verification=


## runner
ワークフローを動かすサーバーのこと。

各ランナーでは、一度に1つのジョブを実行できる。

Ubuntu Linux、Microsoft Windows、macOS ランナーが提供される。



# 参考文献
https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions
アクセルキャンプ復習動画（３ 13 2）Roblox Lua　関数を使ってみよう　その②　引数 

```lua
local function create_block(pos)
	local block = Instance.new("Part", game.workspace)
	block.Position = pos
	block.Size = Vector3.new(5, 5, 5)
	block.Anchored = true
end



--5 5 5の地点
create_block(Vector3.new(5, 5, 5))
-- 10 20 30の地点
create_block(Vector3.new(10, 20, 30))
-- 20 10 12の地点
create_block(Vector3.new(20, 10, 12))



```
Google Cloud Storage のクラス、S3との対比

Google Cloud 勉強中のメモ

## Cloud Storageのクラス

Google Cloud のストレージサービス、Cloud Storage には用途によって異なるストレージクラスが用意されている

https://cloud.google.com/storage/docs/storage-classes?hl=ja

* Standard ストレージ
    * 標準のストレージクラス
    * 読み込み・書き込み頻度の高いデータに向いたクラス
    * マルチリージョン、デュアルリージョン、シングルリージョンのリージョンポリシーを選択できる
* Nearline ストレージ
    * 最小保存期間は30日
    * 読み込み・書き込みが月に１度程度のデータに向いたクラス
        * 月に一回分析やアップデートがあるなど
* Coldlineストレージ
    * 最小保存期間は90日
    * 読み込み・書き込みが四半期に１度程度のデータに向いたクラス
* Archiveストレージ
    * 最小保存期間は365日
    * 長期間にわたって保存する必要があるデータに向いている
        * 監査目的のために＊年間保存義務があるログデータ、など

## S3との比較

Amazon S3と比較すると
https://aws.amazon.com/jp/s3/storage-classes/


* Stanrdardストレージ ≒ S3標準
* Nearalineストレージ ≒ S3 標準 – 低頻度アクセス
* Coldlineストレージ ≒ S3 Glacier Instant Retrieval
* Archiveストレージ ≒ S3 Glacier Deep Archive

ぐらいのイメージかな