OmniAICreator/Qiita-1.07M huggingface dataset:
Javaの例外処理２：throws キーワードとthrowとの違い、スタックトレース

## throwsキーワード
メソッドの中で例外が発生した場合、同じメソッドの中でキャッチせずに、メソッドの外へ投げることができる。
例外を送出する可能性のあるメソッドを作成する場合、メソッドの宣言で次のように**throwsキーワード**を使う。
```
戻り値 メソッド名(引数) throws 例外オブジェクトの型 {
  例外を投げる可能性のあるメソッドの内容
}
```
例外処理をメソッドの中で行わず、呼び出し元で対処してほしいときに使用する。

**throwとの違い**
・throwは、例外を意図的に発生させて、例外処理を実行させることができる。
・throwsは、メソッド内で例外が発生した場合、自身のメソッド内でcatchするのではなく呼び出し元に例外を投げる。（呼び出し元でtry-catch文の準備をしておく必要があり）

### 例文
```:例外クラス
class InvalidAgeException extends Exception{
  InvalidAgeException(String message){
    super(message);
  }
}
```
```:設計図クラス
class Person{
  int age;
  void setAge(int age) throws InvalidAgeException{
    if(age < 0){
      throw new InvalidAgeException("年齢にマイナスの値が指定されました");
    }
    else{
    System.out.println("年齢は" + age + "歳です");
    }
  }
}
```
```:実行用クラス
public class ExceptionExample7{
  public static void main(String[] args) {
    Person p = new Person();
    try{
      p.setAge(-5);
    }
    catch(InvalidAgeException e){
      System.out.println(e);
    }
  }
}
```
```:出力結果
InvalidAgeException: 年齢にマイナスの値が指定されました
```
**InvalidAgeExceptionクラス**
例外オブジェクトのExceptionクラスを継承して独自の例外オブジェクトに宣言。

**Personクラス**
setAgeはメソッド年齢を設定するメソッドで引数で渡された値が負の数の場合（0未満の場合）、InvalidAgeExceptionオブジェクトを生成して例外を投げる。
メソッドの宜言にthrows InvalidAgeException と記述してあるのでこの例外を内部で処理せすに、呼び出し元に投げる。
この場合呼び出し元はtry-catch文を記述しているExceptionExample7クラスになる。

**ExceptionExample7クラス**
Personクラスのオブジェクトpを生成してtry文の中でsetAgeメソッドを呼び出している。
引数に負の値が設定されたのでPersonクラスの「void setAge(int age) throws InvalidAgeException」の記述で「throw new InvalidAgeException」の例外が呼び出し元にであるExceptionExample7クラス投げられてキャッチする。
「catch(InvalidAgeException e)」で例外をキャッチして例外の内容が出力される。

**このようにすることで、意図しない値(マイナスの年齢)を設定しようとしたときにも、対応できるようになる。**


## スタックトレース
**スタックトレース**とは、実行中のコンピュータプログラムにエラーが発生した際に、直前に実行していた関数やメソッドなどの履歴を表示すること。
```:例文
class SimpleClass{
  void doSomething(){
    int array[] = new int[3];
    array[10] = 99;
    System.out.println("doSomethingメソッド終了");
  }
}

public class ExcepentionExample5{
  public static void main(String[]args){
    SimpleClass obj = new SimpleClass();
    try{
      obj.doSomething();
    }
    catch(ArrayIndexOutOfBoundsException e) {
      System.out.println("例外をキャッチしました");
      e.printStackTrace();
    }
  }
}
```
```:出力結果
例外をキャッチしました
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3
        at SimpleClass.doSomething(ExcepentionExample5.java:4)
        at ExcepentionExample5.main(ExcepentionExample5.java:13)
```
上記のプログラムではSimpleClassクラスのdoSomethingメソッドの中で、配列のインデックスが範囲を超えて使用されているので例外が投げらているがメソッド内部にはtry-catch文がない。
しかしExceptionExample5クラスでSimpleClassクラスのmainメソッド内でオブジェクトobjを生成してtry - catch文を記述しているので例外が投げられキャッチしている。

catchブロックの「ArrayIndexOutOfBoundsException」は配列のインデックスとして存在しない要素を指定した場合にエラー通知をする例外オブジェクトでprintStackTraceメソッドは「スタックトレース」を出力する。引数eにはエラー内容の分が代入される。

e.printStackTrace();とする事で1行目にはエラー内容の分が、2行目の"at"以降には、どこでエラーが発生したか、3行目以降も"at"が続き、どこでエラーが発生したのかが表示される。2行目は実際にエラーが発生した場所だが、3行目以降はエラーが発生したメソッドを呼び出した場所が表示される。



##  参考記事
https://magazine.techacademy.jp/magazine/19045#ta-toc-3

https://style.potepan.com/articles/28547.html#throwthrows
ソフト設計に疎いMATLABユーザーにオブジェクト指向設計のいいところを布教する記事

# ポエムです

クラス化に関する記事を2つ書き終えて、根本の疑問がおそらく解決していないと思ったので、書きます。

# オブジェクト指向は変数を操作するプレイヤーを設定すること。

オブジェクト指向ってつまり何?と言われたらこう答えます。

前の記事でも書きましたが、あなたは神ではないので、せっかく作った変数を勝手に書き換え、エラーや意図しない結果を引き起こし、激怒することもしばしばあると思います。もしかしたら間違った結果を得ているのに気づいていないかも。

ことあるごとに関数ファイルを作成しておくことは非常にいいことで、正常な値を関数に投げ込めば、出力の正確さは保証されるでしょう。便利な関数を作成したら、汎用的に使えるように整えて、自作の関数群に追加しておけば、何かの時に役に立ちます。研究開発中の制御モデル・最適化モデル・シミュレーションアルゴリズムなど、こういった一般的なメソッドは関数ファイルを作り共有すべきでしょう。

しかし、プロジェクト内でその関数を扱う際、引数と出力の管理はあなたがすべて責任を持たねばなりません。
関数Aに入れた引数とその出力は、互いにリンクしたものであって、片方だけを勝手に変更することは、先に書いたエラーや誤計算の元です。変更してほしくない数字は変更できないようにしたいのです。

この時に変数の変更などを管理してくれるプレイヤーがクラスです。

# クラスには使命を与える

クラスには、プロジェクト内でのある程度の役割を与えます。例えばデータに対して適当な近似関数を導出する・ノイズを除去する・シミュレーションを行うなど、どれくらいのスコープを任せるかは自由ですが、一目して理解できる程度の仕事を任せます。

クラスには仕事を達成するための変数を内部のメンバ変数という形で保持し、できるだけprivate変数で外部からの変更をシャットアウトさせます。

他のクラスと共有した方が良さそうなもの、メンバ変数として保持するのはクラスの指名から外れるようなものは、メンバ関数の引数にしたりして、境界をはっきりさせます。

こうしておくと、「このクラスを使えば、関数を直で使うより用途は狭いかもしれないが、安全に目的を達成できる。」という状態にできます。うまく汎用的なクラスが作成できたら、研究メンバなどに共有しましょう。

# 終わり

暇ができたので短いポエムを書きました。また思うことがあったら追加するかもしれません。
Visual Studio Codeの穴場拡張機能(改)

<h2>Bracket Pair Colorizer終了</h2>
<a href="https://qiita.com/KLaboratory/items/46a536839a32a7efcbe8">前回</a>Bracket Pair Colorizer(Bracket Pair Colorizer2)はあまり使いやすい拡張機能ではないので、お勧めしないことを書きましたが、その後Bracket Pair Colorizerが拡張機能からVSCodeの標準機能になりました。しかし、機能的にはさほど進歩はなかったようなのでこれだけでは足りないと思います。

<h2>BracketHighlighterとScoperの設定改善</h2>
Bracket Pair Colorizer(括弧の色分け)を補完する機能拡張として、Bracket HighlighterとScoperを紹介させていただきましたが、実は前回の設定では致命的な欠点が出てしまいます。

HEX値で色を設定すると透明度が設定できないので、たとえば選択範囲の着色などが反映されません。これはこれで非常に使いづらいです。
<img src=https://camo.qiitausercontent.com/b6ffa80db78189068fa1b6287e2b30cbfb3115fb/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3538383639322f30643663633831382d303339302d653738622d316234392d3966303864663862323934622e706e67>
ここで、どこかを選択してドラッグしても表示されないのでわからないのです。

"BracketHighlighter.backgroundColor": "#666666"
"scoper.highlightColor": "#666666"
これが前回に紹介した設定ですが、これを
"BracketHighlighter.backgroundColor": "rgba(102,102,102,<strong>0.2</strong>)"
"scoper.highlightColor": "rgba(102,102,102,<strong>0.2</strong>)"
というように、rgba設定にします。最後のパラメータが透明度なので、0.2～0.5くらいで見やすいように調整するといいと思います。
一意性のバリデーションをかける

# 属性の値を一意にバリデーションをかける
```rb
class Holiday < ApplicationRecord
  validates :name, uniqueness: { scope: :year,
    message: "発生は年に1度である必要があります" }
end
```
### 出典
https://railsguides.jp/active_record_validations.html#uniqueness:~:text=class%20Holiday%20%3C%20ApplicationRecord%0A%20%20validates%20%3Aname%2C%20uniqueness%3A%20%7B%20scope%3A%20%3Ayear%2C%0A%20%20%20%20message%3A%20%22%E7%99%BA%E7%94%9F%E3%81%AF%E5%B9%B4%E3%81%AB1%E5%BA%A6%E3%81%A7%E3%81%82%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%22%20%7D%0Aend
 
これを使ってみる

## case_sensitiveオプション
一意性制約で```大文字小文字を区別する```か、または```データベースのデフォルトの照合順序（collation）を尊重```するかどうかを定義できます。このオプションはデフォルトで、```データベースのデフォルト照合順序を尊重```します。

#### 出典
https://railsguides.jp/active_record_validations.html#uniqueness:~:text=%E4%B8%80%E6%84%8F%E6%80%A7%E5%88%B6%E7%B4%84%E3%81%A7%E5%A4%A7%E6%96%87%E5%AD%97%E5%B0%8F%E6%96%87%E5%AD%97%E3%82%92%E5%8C%BA%E5%88%A5%E3%81%99%E3%82%8B%E3%81%8B%E3%80%81%E3%81%BE%E3%81%9F%E3%81%AF%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E7%85%A7%E5%90%88%E9%A0%86%E5%BA%8F%EF%BC%88collation%EF%BC%89%E3%82%92%E5%B0%8A%E9%87%8D%E3%81%99%E3%82%8B%E3%81%8B%E3%81%A9%E3%81%86%E3%81%8B%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82%E3%81%93%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%A7%E3%80%81%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E7%85%A7%E5%90%88%E9%A0%86%E5%BA%8F%E3%82%92%E5%B0%8A%E9%87%8D%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

## これにもメッセージオプションをつける
```rb
validates :name, {presence: true,
                    length: { in: 1..10, message: "ユーザー名を1文字以上から10文字以下で入力してください。"},
                    uniqueness: {message: "既に同じユーザー名があります。"}}
```
### 表示された。
```can't be blank```
```既に同じユーザー名があります。```
```can't be blank```

#### 気づき
他のエラーメッセージが表示されているようだ。
これはまた対処することになるだろう。
これから頑張ろう。
AOS 8.xの特徴

# サービスモジュールの自在にインストールすることができる

再起動せずにアップグレードとダウングレードができるダウンロード可能なサービスモジュールを提供している

# クラスタリング

複数のMDをIPsecトンネルを使って接続する。そうすることで、１つのMDに障害が発生したとしても、問題なく動くような設計にしている。

最大12個のノードを設定できる。

7200シリーズ、7000シリーズ、VMプラットフォームに対応している。

# マルチゾーン

- APが異なるゾーンにある複数のコントローラに接続する設定のこと。
- ゾーンというのは、Mobility Masterとかで管理されているネットワークアーキテクチャのこと
- つまり、Mobility Masterで管理されたネットワークアーキテクチャがたくさんあって、それら複数のアーキテクチャにAPがつながっているイメージ。

例えば、社内用のSSID、ゲスト用のSSIDを作って、それぞれのネットワークアーキテクチャを別々にするときに使える。社内は、可用性を充実させたアーキテクチャにして、ゲスト用は、簡単なものにするとかできる。

# SD-Branch

クラウドからネットワークをいじれる機能のこと。例えば、トラフィックの可視化、デプロイ、セキュリティ導入、自動化など

SD WANとの違いは、セキュリティを導入できるか、あとSD-BRANCH=SD WAN + SD LANということ。つまり、LAN内のネットワークトラフィックなりをいじれる。

# Dynamic segmentation

デバイスごとにロール(セグメント)を割り当てて、細かくアクセス権限を与える。こうすることでセキュリティを高める。

ClearPassを使うことで、クラウドからアクセス権限をコントロールすることができる。

# The Aruba Solution

データの流れは以下のようになっている。

ユーザーのネットワーク認証👉暗号されたデータがAPに到達👉GREトンネルを通ってトランザクションがコントローラに到達👉複合化👉データをファイアウォールに通す👉WANに流す

1つのGREには、ロールごとにトンネルがそれぞれある。そして必ず、keep-aliveトンネルが存在している。

keep-aliveトンネルを通って、トンネルのステータス情報が流れる。こうすることで異常検知できる。

# Remote AP & VIA Deployment Model

- USBを使うことでバックアップアップリンクをとれる
- RAP/VIA Deployment Modelのほとんどは分割トンネル転送モードを使用しています。このモードでは、企業のトラフィックのみをコントローラに転送し、企業以外のトラフィックはローカルでブリッジされます。(企業以外のトラフィックは、そのままインターネットに飛ばされるということ)
【TypeScript】reflect-metadataを用いてDI

# はじめに

以下2つの続きです。

- [Re:【TypeScript】非情報系卒の駆け出しエンジニアなりにDIするコードをvanillaで書いてみた](https://qiita.com/masayasviel/items/e6542986802024fcf974)
- [PythonでDIするコードを書いてみました。](https://qiita.com/masayasviel/items/158705d07c2360293fd7)

限界を試したくてvanillaで頑張りましたが、難しかったので一度[reflect-metadata](https://www.npmjs.com/package/reflect-metadata)を使ってDIを実現しました。
一番折れた理由は後述します。

# tsconfig

この2つを有効化してください。

```json
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  }
}
```

`emitDecoratorMetadata` というパラメータがあり、これがないとreflect-metadataが上手く動いてくれなかったのが折れた理由です。

# 実装

```ts
import 'reflect-metadata';

type constructor<T> = {
    new (...args: any[]): T;
};

class DependencyInjection {
    private static instance: DependencyInjection;
    container = new Map<constructor<any>, constructor<any>[]>();
    instance = new Map<any, constructor<any>>();
    constructor() {}
    static register(target: constructor<any>, params: any[]): void {
        if (!DependencyInjection.instance) {
            DependencyInjection.instance = new DependencyInjection();
        }
        DependencyInjection.instance.container.set(target, params);
    }
    resolve() {
        const keys = Array.from(DependencyInjection.instance.container.keys());
        keys.forEach((ctor) => {
            const targetDependencies = DependencyInjection.instance.container.get(ctor);
            if (targetDependencies == null || targetDependencies.length === 0) {
                this.instance.set(ctor, new ctor());
            } else {
                const instances = targetDependencies
                    .map(cls => this.instance.get(cls))
                    .filter((x): x is constructor<any> => x != null);
                this.instance.set(ctor, new ctor(...instances));
            }
        })
    }
}

const injectable = () => {
    return (target: constructor<any>): void => {
        const params: any[] = Reflect.getMetadata('design:paramtypes', target) || [];
        DependencyInjection.register(target, params);
    };
};
```

# 使ってみる

```ts
@injectable()
class A {
    constructor() {}
}

@injectable()
class B {
    a: A;
    constructor(a: A) {
        this.a = a;
    }
}

@injectable()
class C {
    a: A;
    constructor(a: A) {
        this.a = a;
    }
}

@injectable()
class D {
    b: B;
    constructor(b: B) {
        this.b = b;
    }
}

@injectable()
class E {
    c: C;
    d: D;
    constructor(c: C, d: D) {
        this.c = c;
        this.d = d;
    }
}

@injectable()
class F {
    b: B;
    e: E;
    constructor(b: B, e: E) {
        this.b = b;
        this.e = e;
    }
}

const dependencyInjection = new DependencyInjection();
dependencyInjection.resolve();
console.log(dependencyInjection.instance);
```

## 実行結果

```
Map(6) {
  [class A] => A {},
  [class B] => B { a: A {} },
  [class C] => C { a: A {} },
  [class D] => D { b: B { a: A {} } },
  [class E] => E { c: C { a: A {} }, d: D { b: [B] } },
  [class F] => F { b: B { a: A {} }, e: E { c: [C], d: [D] } }
}
```

# 終わりに

自分の中で、これでDIは一区切りつきました。
あざました。

# 参考

- [DIコンテナの実装を理解して、軽量 DI コンテナを自作しよう](https://qiita.com/sadnessOjisan/items/d05e35e34d2d1fb7e844)
Rails – 子テーブルで最小/最大の値を持つレコード1件ずつだけを親テーブルにJOINする

いちどIDを得ておく必要があるかもしれない
2クエリで実現できそうだ

```rb
children_ids = Child.group(:parent_id).maximum(:created_at).values # e.g [6,35,68]

Parent.joins(:children).merge(Child.where(id: children_ids)).select("parents.*, children.*")
```

maximum を minimum に変えれば最小のレコードをだけをJOINする 



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
今更ながらWebAssembly触ってみました

# 発端

昔Rust触ったときは(個人的に馴染まないという意味で)微妙な感じがしたのですぐやめてしまったのですが、Linuxカーネル開発においてもRustが採用されるなど、非常に興味深いのでいつか勉強しなおそうと思っていました
普段Web系のプログラマーとして働いており、Web系の技術としてWebAssemblyも気にはなっていましたが手を出していなかったのですが、Rustでwasm作れるじゃん？ということでこの度ちょっと環境を整えてみました

# やったこと

https://developer.mozilla.org/ja/docs/WebAssembly/Rust_to_wasm

ほぼコレの前半部分

## ソースコード一式

https://github.com/m-m-n/rust-wasm-sample

Dockerでサクっと見れるようにしてみました
Docker初心者なのでより良いDockerfileの書き方ありましたら教えてください

## wasmビルド手順

Dockerfile見ると明確です
やることまとめておけて便利ですね

具体的な手順としてはRust環境整えたら(今回これはDockerのRustイメージ使ってるので省略)

```
cargo install wasm-pack
```

して

```
cargo new --lib /path/to/somewhere
```

みたいな感じでプロジェクトの雛形を生成します

今回はDockerfileで上記をやった後にホスト側にあるコードをコピーするようにしています
コードを書いたら

```
wasm-pack build --target web
```

でビルドします
ビルドすると `/path/to/somewhere/pkg` というディレクトリに色々生成されており、このビルド成果物がブラウザから呼び出されます

## Webサーバー構築

これもDockerでサクっとやっちゃいます
nginxのイメージを使います

nginxのイメージのデフォルトのドキュメントルートは `/usr/share/nginx/html` になってるようなので、先程の成果物をドキュメントルート以下に配置し、ブラウザでアクセスできるようにします

```
mkdir /usr/share/nginx/html/wasm
cp /path/to/somewhere/pkg/prj_bg.wasm /usr/share/nginx/html/wasm/
cp /path/to/somewhere/pkg/prj.js /usr/share/nginx/html/wasm/
```

みたいなことをやりますが、今回Dockerのマルチステージビルドを使ってるので先にビルドしたところからコピーしてます

# 動作確認

```
docker-compose up --build
```

上記コマンドで無事にコンテナが起動したら `http://localhost:20080` にアクセスしてみます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426191/a1449bf4-e93c-8e58-897c-3fc85a921c1e.png)

無事にアラートが表示されました
JavaScriptからRustで記載したgreetメソッドを実行し、RustのgreetメソッドからはJavaScriptのalertメソッドを実行してブラウザにアラートが表示されています

ちなみにRustの方で `alert` となってるところを `confirm` に書き換えればブラウザにconfirmのダイアログが表示されます！

# 最後に

これで簡単にRustを使ってWebAssemblyの確認を行う環境が手に入ったので、色々弄ってみようと思います
Dockerfileにwasmerのインストール工程が入ってますが今回使ってないので、wasmerも調べてみようと思います

---

それでは良いwasmライフを
MySQLのインデックスによるチューニング(備忘録)

SQLの高速化にあたって、インデックスをはることで高速化できるケースがある。

## インデックスとは
辞書の索引のようなもので、特定のレコードへのアクセスを高速で行える。
インデックスを使わない検索は、一旦データを全て持ってきて、その中からwhere句に合う物を選ぶため時間がかかる。
インデックススキャンは、データの一部しか読み込まないため処理時間を短くできる。

## インデックス作成の目安
1. `JOIN`がある場合
主キー、外部キーにインデックス追加
（mysqlでは外部キー制約で自動的にインデックス付与される）

2. `WHERE`がある場合
大量データを返すなら絞り込み対象のカラムにインデックス追加

3. `GROUP BY`などの集計処理がある場合
集計対象のカラムにインデックス追加

4. `ORDER BY`がある場合
`ORDER BY`対象カラムにインデックス追加

ただし必ず効果検証することで有効かを判断すること。

## その他インデックスを使うべきケース
- データ量が多い（約1万件以上）場合
- 絞り込めるデータの割合が全データと比較して少ない場合
  - 絞り込めるデータ量の割合が15%未満の場合は、インデックススキャンを用いるというのが一つの目安。
  - DB全体を読み込む方が早いとSQLが判断すると、フルスキャンが行われる。
  - ケースバイケースなので、処理速度はよく検証すること。
- `MAX()`、`MIN()`を用いる場合
- インデックスユニークスキャンを使える場合
  - テーブル内のユニークな一件をインデックスを用いて検索し、一件見つかれば処理が終了するため高速
```
　　　　  /* 主キー、ユニークキーによる絞り込み */
 　　  SELECT * FROM users
 　  　WHERE id = 1;
```

※きちんとインデックスが使われているかは、SQL文の頭に`EXPLAIN`をつけて確認する。
```
 　　EXPLAIN SELECT * FROM tableA
 　　WHERE col_a = 1;
```

## インデックスが活用できていないケース
- 索引列を加工している
    - インデックスのあるカラムに何らかの計算がされている場合インデックス利用できない。左辺はカラムだけにする。
```
　　　　/* GOOD　*/
 　　SELECT * FROM tableA
 　　WHERE col_a * 1.1 > 100;

 　　/* BAD　*/
　　　　SELECT * FROM tableA
 　　WHERE col_a > 100 / 1.1;
```

- 索引列に関数を使っている

- 否定形を使っている

- 複合インデックスの場合に、`OR`を使っている
```
　　　　/* nameとageにインデックスを作成*/
  
　　　　SELECT * FROM customer
 　　WHERE name = "佐藤" AND age = 25; # インデックス利用できる

  SELECT * FROM customer
 　　WHERE name = "佐藤" OR age = 25; # インデックス利用できない
```
- 複合インデックスの場合に、列の順番を間違えている
```
　　　　/* nameとageにインデックスを作成*/
  
　　　　SELECT * FROM customer
 　　WHERE name = "佐藤"; # インデックス利用できる

  SELECT * FROM customer
 　　WHERE name = age =25; # インデックス利用できない

　　　　SELECT * FROM customer
 　　WHERE age = 25 OR name = "佐藤"; # インデックス利用できない
```

- `LIKE`の中間一致・後方一致を使用している
    - 後方一致、中間一致はインデックス利用できない。（辞書の索引と同じ。）
```
　　　　/* インデックス利用できる　*/
 　　SELECT * FROM tableA
 　　WHERE name LIKE "佐藤%";

 　　/* インデックス利用できない　*/
　　　　SELECT * FROM tableA
 　　WHERE name LIKE "%佐藤";

  SELECT * FROM tableA
 　　WHERE name LIKE "%藤%";
```

- カラムのデータ型を間違えている
    - 文字列のカラムなのに`'`,`"`をつけなかったり、逆に数値のカラムにつけたりすると暗黙の型変換が行われてインデックスが利用できない。
```
　　　　　　　/* BAD(int型のカラムにクォートをつけてる）　*/
    SELECT * FROM customer
    WHERE customer_id = '1';

　　　　　　　　/* GOOD　*/    
　　　　　　　　SELECT * FROM customer
    WHERE customer_id = 1;
```

## 注意
不要なインデックスは領域を無駄に使用して、SQLが使用するインデックスを判断するための時間を要するので、適切・適度に使用すること。

## 参考
[MySQLリファレンスマニュアル](https://dev.mysql.com/doc/refman/8.0/ja/mysql-indexes.html "MySQLリファレンスマニュアル")
Googleスプレッドシートのフィルタで「次を含むテキスト」をAND条件やOR条件で複数指定したいあなたに

こんにちは。

自分のためのメモということで小ネタを残しておきます。

## やりたいこと

Googleスプレッドシートにデータをフィルタする機能がある。

以下のようなデータがあったとして

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/69ee3d79-9149-ade4-017a-8b06c2fc0bb7.png" width="400px">

`gmail.com` だけを表示するように「条件でフィルタ」すると

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/95128952-e391-3250-1dfd-03f3cd76b3ab.png" width="400px">

こうなる。とても便利。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/afa29586-539e-6197-1168-949c15efa2df.png" width="400px">

この「次を含むテキスト」などでフィルタするときに **複数の条件をAND条件かOR条件で指定** したい。

ついでに正規表現も使いたい。

## 解決策

「カスタム数式」というのを使うといけた。

`=OR(REGEXMATCH(B:B, "gmail.com"), REGEXMATCH(B:B, "hotmail.com"))` と指定すると「 `gmail.com` を含む、または、 `hotmail.com` を含む」という条件になる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/dcc945e8-f11f-936c-0224-3a2e3cb8e5f8.png" width="400px">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/70b5ad6b-7a8e-64e3-7d39-a6a6f9a7e38d.png" width="400px">

ちなみに `B:B` というのはフィルタする対象の列全体を表しているようで、 `<対象の列>:<対象の列>` という書き方をすれば良さそう、たぶん。

`OR` を `AND` にするとAND条件にできる。

## おまけ

### NOT

`AND` や `OR` があるので `NOT` も使える。

`=OR(REGEXMATCH(B:B, "gmail.com"), NOT(REGEXMATCH(B:B, "hotmail.com")))` と指定すると「 `gmail.com` を含む、または、 `hotmail.com` を含まない」という条件になる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/bba188af-e4b6-2bfc-c182-6d148d56a5b0.png" width="400px">

### 正規表現

正規表現も普通に使える。

`=REGEXMATCH(B:B, "^b.+@yahoo.com$")` と指定すると「 `b` で始まって `@yahoo.com` で終わる」という条件になる。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/388b9146-c490-fda5-24fe-bca693fbc9fe.png" width="400px">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42238/b04c6f50-52c3-fa9c-188c-124249256984.png" width="400px">
ANY演算子

# ANY演算子
ANY演算子を使用すると、```「等しい（=）」だけでなく、引数で渡された値といずれかが「対象 < 引数の値」```であるなど、```「=」以外の比較述語（=、!=、<>、<、<=、>、>=）```を使用した比較を一度にすることができます。
副問い合わせについて詳しくは後述しますが、SQLでは、SQL文中にSELECT文を記述してその結果を元のSQL文で利用することができ機能があり、そのSQL文中に記述するSELECT文のことを副問い合わせといいます。

``` 	
対象 比較述語 ANY (副問い合わせ)
```
### 出典
https://tech.pjin.jp/blog/2020/12/28/%E3%80%90sql%E5%85%A5%E9%96%80%E3%80%91any-all%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%AB%E3%82%88%E3%82%8B%E6%9D%A1%E4%BB%B6%E6%8C%87%E5%AE%9A/#:~:text=ANY%E6%BC%94%E7%AE%97%E5%AD%90%E3%82%92,ANY%20(%E5%89%AF%E5%95%8F%E3%81%84%E5%90%88%E3%82%8F%E3%81%9B)

### 実践
```
SELECT * FROM 在庫リスト
WHERE カテゴリ = ANY
(SELECT カテゴリ FROM 在庫リスト WHERE 名前='地面に沈む羽');
```

実行結果
| 商品番号 | 名前         | カテゴリ | 単価  | 在庫 | 商品タイプ | 
| -------- | ------------ | -------- | ----- | ---- | ---------- | 
| １       | 時の卵       | 空想商品 | 12345 | ２   |            | 
| ３       | 地面に沈む卵 | 空想商品 | 1200  | ４   |            | 

#### 出典
https://ichilv.com/sql-any/#:~:text=SELECT%20*%20FROM%20%E5%9C%A8%E5%BA%AB,4
MySQL – GROUP BY で最小/最大の値を持つレコード1件ずつだけに絞り込む

# クエリの例

サブクエリでいちどIDリストを得てからWHEREに渡すと良さそうだ

```sql
SELECT * FROM examples WHERE id IN (
  SELECT MIN(id) FROM examples GROUP BY name
);

```

# 結果

```
id | name
-- | --
1 | Alice
1 | Bob
1 | Carol
```

# テーブル

```
id | name
-- | --
1 | Alice
2 | Alice
3 | Alice
1 | Bob
2 | Bob
3 | Bob
1 | Carol
2 | Carol
3 | Carol
```

```
CREATE TABLE examples (
  id INT,
  name VARCHAR(255)
);

INSERT INTO examples (id, name) VALUES (1, "Alice");
INSERT INTO examples (id, name) VALUES (2, "Alice");
INSERT INTO examples (id, name) VALUES (3, "Alice");

INSERT INTO examples (id, name) VALUES (1, "Bob");
INSERT INTO examples (id, name) VALUES (2, "Bob");
INSERT INTO examples (id, name) VALUES (3, "Bob");

INSERT INTO examples (id, name) VALUES (1, "Carol");
INSERT INTO examples (id, name) VALUES (2, "Carol");
INSERT INTO examples (id, name) VALUES (3, "Carol");
```

# 補足


MINをMAXに変えればidが最大値のものを得る


# Fiddle

https://www.db-fiddle.com/f/6azxWAoK6S5Hxf3DYGgNg6/3


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
バグ報告のためのtemp記事

将来的には消す予定です。

[< と >　で囲われた範囲でインラインコードがインラインコードとして扱われない #413](https://github.com/increments/qiita-discussions/discussions/413)

`あああ`
<`あああ`
< `あああ`
`あああ`>
`あああ` >
<`あああ`>
< `あああ` >
正規化

# 第一正規化とは？
p304 非正規化の表から、繰り返しの部分を取り除いたもの
### 出典
https://gihyo.jp/book/2020/978-4-297-11781-8

p86 一つのセルの中には一つの値しか含まない
### 出典
https://www.shoeisha.co.jp/book/detail/9784798124704

# 第二正規化とは？
部分関数従属している列を切り出したもの
### 出典
https://gihyo.jp/book/2020/978-4-297-11781-8

* p93 主キーの一部の列に対して従属する列がある場合、この関係を```部分関数従属```と呼びます。
これに対して、主キーを構成するすべての列に従属関性がある場合を```完全関数従属```と呼びます。第二正規化とは、テーブル内で```部分関数従属を解消し、完全関数従属のみをテーブルに作る```ことなのです。

### 出典
https://www.shoeisha.co.jp/book/detail/9784798124704

# 第三正規化とは？
主キー以外の列に関数従属している列を切り出したもの
### 出典
https://gihyo.jp/book/2020/978-4-297-11781-8

* テーブルに内在する段階的な従属関係のことを```推移的関数従属```と呼びます。
* 非キー列は、キー列に対してのみ従属するようになり、推移的関数従属もなくなる。

### 出典
https://www.shoeisha.co.jp/book/detail/9784798124704

### 気づき
一つも登録されていない値を他のテーブルに登録することができる。

### 推移的関数従属性
　関数従属性が推移的に行われている、即ち（1）```X→Y、（2）Y→Z、（かつX→Zでは無い）```を全て満たす性質を、推移的関数従属性と呼びます。
#### 出典
https://atmarkit.itmedia.co.jp/ait/articles/1703/01/news181.html#:~:text=%E3%81%84%E3%82%8B%E3%80%8D%E3%81%A8%E3%81%84%E3%81%84%E3%81%BE%E3%81%99%E3%80%82%EF%BC%89-,%E6%8E%A8%E7%A7%BB%E7%9A%84%E9%96%A2%E6%95%B0%E5%BE%93%E5%B1%9E%E6%80%A7,%E6%80%A7%E8%B3%AA%E3%82%92%E3%80%81%E6%8E%A8%E7%A7%BB%E7%9A%84%E9%96%A2%E6%95%B0%E5%BE%93%E5%B1%9E%E6%80%A7%E3%81%A8%E5%91%BC%E3%81%B3%E3%81%BE%E3%81%99%E3%80%82,-%E5%8D%88%E5%BE%8C%E3%81%A7%E6%A5%B5%E3%82%81%E3%81%A6
[初学者向け] Ruby 論理演算子を理解する

 ## 本記事について
 
本記事は、Rubyを学び始めた私自身が「？」となった**論理演算子**について、
学んだ内容をまとめます。
私と同じく「？」となった初学者の皆さんがこの記事を読むことで
理解できるようになることを目的とします。経験の浅い私ならではのシンプルな文章が、
皆さんの理解の一助になることを願います。


### 論理演算子とは？

そもそも論理演算子とは？　Google先生に聞いてみると、下記とのこと。
>「論理演算子とは、「真」と「偽」の２つの値だけで行う計算(論理演算)を表す
記号のことです。」

いまいちピントこない。というのが私の第一印象です。

私が腹落ちした、もう少し噛み砕いた表現にすると、

**「論理演算子とは、複数の条件式を組み合わせた条件式の真偽を教えてくれる記号」**

例えば、下記の2つの条件式があったとします。

条件式1 a > b
条件式2 a > 10

ここで論理演算子を用いれば、

- 条件式1を満たす、かつ条件式2も満たす場合
- 条件式1と条件式2のいずれかを満たす場合

のように、複数の条件式を組み合わせた条件の真偽を結果として出すことができます。
以降で実際の論理演算子と具体例を紹介します。

### 論理演算子の種類

Rubyには以下の論理演算子が用意されています。

| no.| 論理演算子|記入例|意味 | 
|:--:|:----:|:----------:|:-------|
|1|&& | a && b |aとbがどちらも真の場合→真　それ以外→偽 |
|2| &#124;&#124;  |a &#124; &#124; b|aとbの少なくとも1つが真の場合→真　それ以外→偽&nbsp;|
|3|!| ! a| aが真の場合→偽、偽の場合→真| | |

#### 　具体例
シンプルな例をもとに、各論理演算子を見てみましょう。

**1.　a&&b（abどちらも真の場合→真）**
下記の場合、ab共にtrueなので、比較演算子&&の結果は、**true**となります。
また、その結果（＝true)がcに代入されている状態です。
```diff_ruby
a = true
b = true
c = a&&b
puts c.class  # ==>実行結果は[TrueClass]となる
```
一方で、下記の通り、b = falseとした場合、ab共に真という条件は満たさなくなるので、
論理演算子&&の結果は、**false**となります。
```diff_ruby
a = true
b = false
c = a&&b
puts c.class  # ==>実行結果は[FalseClass]となる
```
言うまでもありませんが、a=false,b=falseの場合→FalseClassとなります。

**2.　 a||b　(abの少なくとも1つが真の場合→真）**
下記の場合、ab少なくとも1つが真を満たすため、論理演算子||の結果は、**true**となります。
```diff_ruby
a = true
b = false
c = a||b
puts c.class  # ==>実行結果は[TrueClass]となる
```
一方で、下記の通り、ab共にfalseとした場合、
当然ですが、ab共に真という条件は満たさなくなるので、
論理演算子&&の結果は、**false**となります。
```diff_ruby
a = false
b = false
c = a||b
puts c.class  # ==>実行結果は[FalseClass]となる
```

**3.　 !a　(aが真の場合→偽、偽の場合→真）**
下記の通り、aが真、偽の場合、それぞれ逆の結果となります。

```diff_ruby
a = true
b = a!
puts b.class  # ==>実行結果は[FalseClass]となる

a = false
b = !a
puts b.class # ==>実行結果は「TrueClass」となる
```

### 最後に

以上、論理演算子「&&」「||」「!」を紹介しました。
まだまだ拙い文章ですが、今後も自身が学んだ内容を簡単にまとめていきたいと思います。
最後まで読んでいただき、ありがとうございました。
なんかよくわからないけど、Rでrglライブラリを使う方法



```R
options(rgl.useNULL=TRUE)
library(rgl)

plot3d(dat)#datは3次元データ
rglwidget()
```

普通、rglは実行すると別途ウィンドウを呼ぶが
この方法だと、R studio内の右下に3d散布図を表示させる。

素人なので、適当な予想だけど、rglはxcodeが必要で
それをインストールしていない人の回避方法が上記なのかな。
できたので、何でも良いけど。

参考
https://stackoverflow.com/questions/68517734/how-to-install-the-rgl-package-in-macos-big-sur
GraphQL でユーザを選択してデータ取得

作成：2023年1月8日
・本記事は次の記事の続きです「[React Navigation でプロフ画面を追加](https://qiita.com/RYO_/items/3f700f3ba63f6dc4a9be)」
・React Native + Expo + Amplify + NativeBase + React Navigation でアプリ試作してます。

# GraphQL でフィルター

[現状のコード](https://github.com/ryoyuki6/native-base-amplify20230101/blob/qiita20230107/App.js)では、GraphQL でユーザ3人分(taro,jiro,hanako)のデータをまとめて取ってきて、 data[0] で指定して jiro のデータを表示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/2f811a92-90ed-2b58-1dff-f4483da2a731.png)

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/68a01129-9b4f-5dbd-4c96-d81c9c998373.png">

それを、GraphQL のフィルターを使ってログインしたユーザ(user.username)のデータだけ取ってきて表示するようにします。graphqlOperation を使います。
```javascript:App.js
 async function fetchData1() {
    const opt = {
      filter: {name: {eq: user.username}},
    };
    API.graphql(graphqlOperation(listPeople,opt)).then(values=> {
      setData1(values.data.listPeople.items);
    });
  }
```

# ログイン情報からユーザ情報を取得

App.js に次のコードを追加します（App.jsのgithubリンク：[qiita20230108](https://github.com/ryoyuki6/native-base-amplify20230101/blob/qiita20230108/App.js)）
```javascript:App.js
function HomeScreen() {
...
  const { user, signOut } = useAuthenticator((context) => [context.user])
...
            {`Welcome, ${user.username} !!!`}
...
function ProfileScreen() {
...
    const opt = {
      filter: {name: {eq: user.username}},
    };
```

taro でログインすると taro の情報が表示される様になりました。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/80ff70c2-82ca-088d-de38-8244f61bcb86.png"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/d5d008c1-9080-61bb-ea4f-7717a39e45ca.png"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/cc60995a-2311-b5ae-e362-9ae385d76ccc.png">

jiro でログインすると jiro の情報が表示される様になりました。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/0a12d6ba-52c6-ae51-3f93-b93b14ef7298.png"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/a58a7a12-6ea9-ab03-c4c4-061cc76e9d94.png"><img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298045/b2c69ffe-7074-1209-6014-af05802214df.png">

以上です。

参考
[Access Authenticated User](https://ui.docs.amplify.aws/react-native/connected-components/authenticator/headless#access-authenticated-user)
Ubuntu20.04で右クリックで新しいドキュメント

# 「端末」を開く
以下のような方法で「端末」を開く
・「アクティビティ画面」から開く
・「アプリケーション画面」から開く
・[Ctrl]+[Alt]+[T]を押す

# コンテキストメニューから空のドキュメントを作成dできるようにする
「端末」で
`touch ~/テンプレート/空のドキュメント`

# 参考にしたサイト
https://sicklylife.hatenablog.com/entry/2018/07/15/232709
WindowsによるPython入門 #02: 変数

# はじめに

今回は第二回目として、変数を解説します。

# YouTube動画

[WindowsによるPython入門 (第二回) 変数](https://youtu.be/hSyO1CnKNVg)

# 変数とは 

Python の変数は、「値を参照するもの」です。
下図の左のイメージではなく、右のイメージが正解です。
変数 a が整数値 10 を保持しているのではなく、整数値 10 を変数 a が指し示しています。
よく、「Python の変数は箱ではなく、ラベルである」と例えられます。
変数が参照しているのは正確に言えば、「値」ではないのですが、詳細は後の回で再度解説します。

![variable_image.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629087/4420a5ee-7748-f455-e440-d2ed53ecfe7b.png)

具体例を見てみます。
変数 a に整数値 1 を代入します。この時に、変数 a が定義されます。a に 2 を足します。式の結果として、1 + 2 で 3 が返ります。
次に、変数 a に文字列 "neko" を代入します。変数 b に "inu" を代入します。a と空白と b を足すと、文字列 'neko inu' が返ります。

```py
>>> a = 1
>>> a + 2
3
>>> a = "neko"
>>> b = "inu"
>>> a +  " " + b
'neko inu'
```

また、定義していない変数を使用するとエラーになります。

```py
>>> c
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'c' is not defined
```

# 変数の型に関して

次に、変数の型に関して見てみます。
型を確認するには、type() 関数を使用します。
a に 1 を代入します。type() 関数を使用して、変数 a の型を調べると int (整数型) が返ります。
a に "neko" を代入します。type() で調べると、str (文字列型) が返ります。
ここで、「型」の情報を持っているのは、「変数」 a ではなく、「値」の方です。つまり、type(a) で調べているのは、変数 a が指し示す値の型を確認している事になります。

```py
>>> a = 1
>>> type(a)
<class 'int'>
>>>
>>> a = "neko"
>>> type(a)
<class 'str'>
```

# 変数の命名規則

変数名として以下のものが利用可能です。
- アルファベット (a-z, A-Z)
- 数字 (0-9)
- アンダースコア (_)
- ユニコード文字

以下、公式ドキュメントです。

[2.3. 識別子 (identifier) およびキーワード (keyword)](https://docs.python.org/ja/3/reference/lexical_analysis.html#identifiers)

厳密に言えば、アルファベットや数字やアンダースコアもユニコード文字です。
但し、ユニコード文字は、バージョン管理システムなど他のアプリで不具合を起こすケースがありますので、推奨しません。
また、変数名の文字列の長さとして長さ制限はありません。

さらに、以下は変数名として使用出来ません。

- 数字で始まる変数名
- 予約語を変数名とする

具体的に確認します。
以下は、OK です。

```py
a = 1
var1 = 2
num = 3
abcdefghijklmnopqrstuvwxyz0123456789 = 4  # 長い変数名
π = 3.14                                  # ユニコード文字を含む
文字 = "テスト1"                           # ユニコード文字を含む
a文字 = "テスト2"                          # ユニコード文字を含む
```

以下は、NG です。エラーになります。

```py
1num = 1  # 数字で始まっている
if = 2    # if が予約語
for = 3   # for が予約語
```

また、以下の変数名を使用してもエラーにはなりませんが、使用が推奨されません。
アンダースコアで始まる変数名は特殊な場合に使用されます。

- アンダースコア 1 つで始まる変数
- アンダースコア 2 つで始まる変数
- ビルトイン関数名 (予め定義されている関数)

```py
_var = 1   # アンダースコア 1 つで始まる
__var = 2  # アンダースコア 2 つで始まる
sum = 3    # sum がビルトイン関数名
id = 4     # id がビルトイン関数名
```

# おわりに

以上、変数のまとめでした。
次回は、具体的な型に関して見ていきます。
Xcodeで新しいフォルダの作成方法

普段はAndroidのエンジニアをしてますがKMMについて調べたり、試したりしてこの前久しぶりにXcodeを開いて触っていたのですが、フォルダの作成方法を忘れてました。
時間を使ってしまったので忘れないように記事として残します。


# 新しいフォルダの作成方法
Xcode上のフォルダなどの上で右クリックをします。

NewGroupをクリックします。

以上です！

新しいファイルを作るときなどはNewFileにするのでNewFile内を色々探してました。。。

![スクリーンショット 2023-01-08 15.06.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/a4c13065-b2a2-436b-4a8b-02b26153f641.png)
Ansibleにおける辞書(dictionary)型データのキー並び順をソートしないで表示

参考:
[teratail: ansible の yaml で要素を読み込んだ順序で出力したい](https://teratail.com/questions/321820)

上の内容を知らなかったので紹介。

# debugモジュールではキーの並び順は通常ソートされて表示される



## playbook例

定義時にはname:が先頭であっても

```yaml:site.yml
---
- hosts: localhost
  tasks:

  - debug: var="files"
    vars:
      files:
      - name: file1
        path: "/etc/foo.conf"
        content: hoge
        owner: foo
        group: foo
        mode: '0644'
```



## 出力例

表示時にはキーでソートされて元先頭だったname:などは見つけにくくなってしまう。

```
$ ansible-playbook site.yml
...

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => 
  files:
  - content: hoge
    group: foo
    mode: '0644'
    name: file1
    owner: foo
    path: /etc/foo.conf
```




# キーの並び順をソートしないで表示する

to_nice_yaml(sort_keys=false)フィルターを利用する

## playbook例

```yaml:site.yml
- hosts: localhost
  tasks:

  - debug: var="files|to_nice_yaml(sort_keys=false)"
    vars:
      files:
      - name: file1
        path: "/etc/foo.conf"
        content: hoge
        owner: foo
        group: foo
        mode: '0644'
```

## 出力例

```
...

TASK [debug] *********************************************************************************************************************************************************************************
ok: [localhost] => 
  files|to_nice_yaml(sort_keys=false): |-
    -   name: file1
        path: /etc/foo.conf
        content: hoge
        owner: foo
        group: foojinja2
        mode: '0644'

...
```
キーの順序が保存され、name:が先頭となっている。
JSONの場合にはto_nice_json(sort_keys=false)が使用可能。

# 環境

- Fedora Linux 36 (Workstation Edition)
- ansible Version: 7.0.0
- ansible [core 2.14.0]


フィルター適用後の\nをログ上でも改行させるため、community.generalコレクションを導入し、ansible.cfgにてstdout_callback = community.general.yamlとしている。

```ini:ansible.cfg
[defaults]
#verbosity = 1
stdout_callback = community.general.yaml
```

[Ansibleのdebugモジュールにおいて\nを改行した状態で表示する](https://qiita.com/hiroyuki_onodera/items/6c4602967bc039c3337d)




# 参考
[teratail: ansible の yaml で要素を読み込んだ順序で出力したい](https://teratail.com/questions/321820)
https://github.com/ansible/ansible/issues/76638
BlenderでMMDモデルを触るメモ

blenderの勉強を兼ねて色々触っているのでメモ

# mmd_tools
https://github.com/UuuNyaa/blender_mmd_tools
MMDモデルのインポートやBlender上での操作に必要


# 他入れると良さげなアドオン
### Bezier Utilities(ベジェユーティリティ)
https://github.com/Shriinivas/blenderbezierutils
ベジェ曲線の操作が直感的になる

# 操作についてわかりやすい動画
ポージングについてはこの動画がめちゃくちゃわかりやすくて捗りました。
https://www.youtube.com/watch?v=9UvBhrUZWO4

# 画面４分割それぞれ操作できるようにする

画面４分割は通常下記のように分割され、ユーザー以外の部分は視点の回転不可となる。

トップ　　|　ユーザー
――――――――――
フロント　|　ライト

ただ、自分はライトの部分を左からの視点にしたかったので方法を探したら、
画面４分割中はビュータブに四分割表示の項目が追加され、「回転をロック」のチェックを外すことで、
ユーザー以外の視点も回転できるようになる。

![2023-01-08_21h49_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929962/c6377db9-5f8b-c06b-289c-5c9cc0da8e1e.png)



# モーフツールの値の調整部分が消えた（表示されていない）

モーフツールを使って衣装の表示などを切り替えられるが値の調整部分が消える事がある。
（なにかいじったかな・・・？）

その場合にはMMDタブ > モデル設定 > 組み立て > モーフのボタンをポチると表示される。

![2023-01-08_14h49_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929962/dd4fd5bf-011a-d611-64e6-451a2e1bde7e.png)

# ショートカットキー
### Alt + Ctrl + Q
3Dビューポートで画面4分割

### Iキー
キーフレームの挿入

### Aキー
全選択

### Shift + Space + G
オブジェクトの移動

### Shift + Space + R
オブジェクトの回転
クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ⑤Amazon Rekognition(モデル作り直し)


[クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ①データ取得](https://qiita.com/satsukiya/items/3c19310f06475e15cd0f)
[クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ②アノテーション追加](https://qiita.com/satsukiya/items/eb7cb2b26ce689c066b2)
[クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ③Amazon Rekognition(学習編)](https://qiita.com/satsukiya/items/f1620ac0dbc79528323b)
[クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ④Amazon Rekognition(推論編)](https://qiita.com/satsukiya/items/cd61f771e375a33287cc)
の続きです。

このあと、APIを使ってローカル上で動画内の物体検出をしようと思ったのですが、F1値が0.21とかなり低かったためか検出の精度も低かったので、モデルを作り直そうと思っています。

ここでは、精度が低く出たと思われる問題点と修正方法について書こうと思います。

# Cause of lower F1 Score

##### 学習データにアノテーションなしの画像を含めていた
[クラッシュロワイヤルに出てくるゴブリンをトラッキングしたった ①データ取得](https://qiita.com/satsukiya/items/3c19310f06475e15cd0f)で１秒に画像フレームを1枚出力していた関係で、ゴブリンがいないデータが200枚中約20枚ありました。学習しても意味ないです:sweat_smile:

##### 画像内に学習不要な部分があった。
スマホから動画を生成していることと、このゲーム自体縦型でプレイするものだったので動画自体のサイズが合ってなかったことも問題です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/8c38a1a8-fc8a-a9e0-cc1c-e453fcb4dfa7.png" width=640>

中央の部分をトリミングするだけでもだいぶ違うと思います。

##### できるだけキャラクター全体が表示されている画像を選ぶ
アノテーションをしていて気づいたこととして、下記のことでキャラクターと重なって全体が表示されないことがありました。

- キャラクター上のレベル
- キャラクターを置いたときの文字と時計
- タワーの裏側
- キャラクター同士が重なっている

|||
|-|-|
|![000811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/588c0b09-a1a3-4daf-8e4b-7569c6214338.png)|時計で見えない|
|![006968.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/00bfc76e-1fe6-7bfd-3728-1d40e8dff949.png)|文字で見えない|


そのため、できる限りキャラクター全体が表示されている画像を選びたいです。


# effective course

アノテーションする画像を集める方法として、

1. 1秒間隔の画像フレーム取得をやめて全てを取得する。
1. 必要な部分だけをトリミングして残す
1. キャラクター全体が表示されている画像を選ぶ (目標500枚)

の3つのことをすればいいと思います。


# movie to images

動画を読み込み、トリミングした画像フレームをフォルダに集約するスクリプトを書いたった。
スマホ表示部分は `(TOP, LEFT)=(0,710) (BOTTOM)=(1080, 1210) (Height, Width)=(1080, 500)`なので `frame[:, 710:1210]` にすればOK。 

```python
import argparse
import cv2
import os
import datetime


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("--src", default="src.mp4", help="入力動画ファイル")
    args = parser.parse_args()

    #保存先フォルダパス
    output_dir_path = "output_{}".format(
        datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
    os.mkdir(output_dir_path)

    video_capture = cv2.VideoCapture(args.src)

    # 元動画のフレーム数を取得しておく
    frame_count = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT))

    for i in range(frame_count):
        if not video_capture.isOpened():
            break

        retval, frame = video_capture.read()

        if retval is False:
            break
        frame_gray = frame[:, 710:1210]

        image_path = os.path.join(output_dir_path, f"{i:06d}.png".format(i))
        cv2.imwrite(image_path, frame_gray)

    video_capture.release()


if __name__ == "__main__":
    main()

```

# To Be Continued
このあとは、ゴブリンが表示されている画像を500枚集めて再度アノテーションを追加し、再び学習してモデルを作ります。F1 Scoreがどのくらい精度が上がるか気になります。
Rails 制作中アプリのアプリ名を変更する

# １．はじめに
2作目のポートフォリオを制作中にアプリ名を変更したくなったため、やり方を調べて対応しました！
その記録を残しておきます。

# ２．前提条件
#### 開発環境
Ruby：ruby 3.1.2
Rails：Rails 6.1.6.1
OS：Windows11 Home
統合開発環境：Cloud9
ソースコード管理：GitHub

#### やりたいこと
railsアプリケーション名の変更


# ３．手順
#### ①バックアップ
万が一の事態に備えて、アプリ名を変更する前にバックアップを取っておく。
１）GitHubから対象のアプリを開く。
２）「<>Code▼」を押して、LocalからsshのURLをコピーする。
３）ローカル環境にcloneして、仮置きディレクトリに格納する。
   ※仮置きディレクトリ名は、後ろに2を付ける等なんでもOK！
```
git clone 対象アプリのURL
```


#### ②Railsアプリ名称変更
Railsのファイル名変更はGemfileを入れることで簡単に行える！

１）アプリ名を変更したいアプリのGemfileに下記を記述する。
```
gem 'rename'
```
２）Gemfileをインストールするためにターミナルに下記を記述する。
```
bundle install
```
３）ターミナルに下記を記述し、アプリ名を変更する。
```
rails g rename:into <変更後の名前>
```

#### ③GitHubのリポジトリ名変更

GitHubのリポジトリ名を変更しないとGitHubとの繋がりが持てないので、これも変更していく。

１）GitHubにアクセスし、「Settings」を押下する。

２）「Repository name」に変更後の名前を入力し、「Renameボタン」を押下する。

３）ローカルのリモートリポジトリ設定を変更する。
→まず、現在のリモートリポジトリ設定を確認する。
```
$ git remote -v
origin  <リモートリポジトリーのURL> (fetch)
origin  <リモートリポジトリーのURL> (push)
```

→次に、リモートリポジトリー設定を変更する。
```
git remote set-url origin <変更後のURL>
```

→最後に、リモートリポジトリー設定が変更されているか確認する。
```
$ git remote -v
origin  <変更後のURL> (fetch)
origin  <変更後のURL> (push)
```

# ４．最後に
意外に簡単で一安心しました。
今回はQiitaを書きながら取り組んだので時間がかかりましたが、次からは５～10分程度でできそうです！
最後まで読んでくださり、ありがとうございました！
制約、IN述語

### DDLとは？
https://qiita.com/masatom86650860/items/e9dc8c98e1c355acbcbe#ddl%E3%81%A8%E3%81%AF

### CHECK制約
CHECK制約は、テーブルにデータを（挿入も含む）更新する際に条件を満たすか検証し、もし満たさない場合はエラーにしてしまう機能になります。
#### 出典　(check 制約で検索）
https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0136#:~:text=CHECK%E5%88%B6%E7%B4%84%E3%81%AF%E3%80%81%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AB%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%EF%BC%88%E6%8C%BF%E5%85%A5%E3%82%82%E5%90%AB%E3%82%80%EF%BC%89%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AB%E6%9D%A1%E4%BB%B6%E3%82%92%E6%BA%80%E3%81%9F%E3%81%99%E3%81%8B%E6%A4%9C%E8%A8%BC%E3%81%97%E3%80%81%E3%82%82%E3%81%97%E6%BA%80%E3%81%9F%E3%81%95%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AF%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%86%E6%A9%9F%E8%83%BD%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

　ある列の取りうる値の範囲を制限するための制約
#### 出典
https://www.shoeisha.co.jp/book/detail/9784798124704

CHECK制約【check constraint】チェック制約 / 検査制約
#### 出典
https://e-words.jp/w/CHECK%E5%88%B6%E7%B4%84.html#:~:text=CHECK%E5%88%B6%E7%B4%84%E3%80%90check%20constraint%E3%80%91%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E5%88%B6%E7%B4%84%20/%20%E6%A4%9C%E6%9F%BB%E5%88%B6%E7%B4%84

### 検査制約とは？
https://qiita.com/masatom86650860/items/e9dc8c98e1c355acbcbe#%E6%A4%9C%E6%9F%BB%E5%88%B6%E7%B4%84

### 検査制約（CHECK）
売上表で個数は整数で１０個以下でなければならないというような定義です。
```
　　　CREATE TABLE 売上表
　　　(
　　　　商品 ・・・.
　　　　個数 INTEGER CHECK(個数<=10),
　　　　・・・,
　　　);
```
#### 出典
http://www.kogures.com/hitoshi/webtext/db-ddl-dml-dcl/index.html#:~:text=%E6%A4%9C%E6%9F%BB%E5%88%B6%E7%B4%84%EF%BC%88CHECK,%2C%0A%E3%80%80%E3%80%80%E3%80%80%E3%80%80%E3%83%BB%E3%83%BB%E3%83%BB%2C%0A%E3%80%80%E3%80%80%E3%80%80)%3B

### IN述語
OR演算子の省略形。
選択対象としたい値が増えるにつれてSQLも長大になり、読みにくくなることです。こんな時に```IN(値,...)```という形式で書き換えることができる。

### OR演算子
条件においての```または```を表す。

#### 出典
https://www.shoeisha.co.jp/book/detail/9784798144450
[vue3] Pluginsデレクトリにおいてのvalidationの使い方について

各コンポーネントに書いていたValidationをpluginsデレクトリを作成しそこに記載したところ同じ書き方では動かなかったので、記事にします。

下記の感じでpluginsとしてデレクトリを切りその中にvalidation.tsを作成した。
↓↓↓↓↓↓↓↓↓↓↓↓↓
![スクリーンショット 2023-01-08 14.10.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/e2e4c9fd-798a-33e7-5278-e65c1614962c.png)

元々は下記でバリデーションがかかっていたんだけど、pluginsディレクトリにそのまま同じ記述を移動させたところ、こんな感じで動かなくなりました。
![スクリーンショット 2023-01-08 14.14.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/4e0a5479-530b-4ddf-373f-ad1b74f92138.png)
![スクリーンショット 2023-01-08 14.17.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/94b63f27-efc8-1121-1aa6-006856fb7ab0.png)

困ったなということで、公式ドキュメントを確認。
https://nuxt.com/docs/guide/directory-structure/plugins

![スクリーンショット 2023-01-08 14.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/a61e500c-9874-5248-221e-4bb84e9bf5dd.png)

見るからに書き方が違うので、変更を実施。
最終形が下記です。
↓↓↓↓↓↓↓↓↓↓↓
※バーリデーション部分
![スクリーンショット 2023-01-08 14.21.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/90f77bd0-5181-fcdc-7284-a5eba439432c.png)

```
export default defineNuxtPlugin(() => {
    return {
        provide: {
            //この中にバリデーションを書く！！
        },
    }
})
```

※呼び出し先（バリデーションを実際に使っているところ）
![スクリーンショット 2023-01-08 14.32.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/44abae3b-113e-4f72-61e6-d925c5680e85.png)
![スクリーンショット 2023-01-08 14.34.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2931766/2005654c-cc9e-a601-1c64-f68b76596cb2.png)

```
//32行目で先ほどvalidation.tsで記載した内容をとってきてます。
//schemaの前に"$"をつけることを忘れないで。付けないと動かないよ。
//ここの書き方は公式と同じなので見比べてください。{ $hello }が{ $schema }になっただけ。

const { $schema } = useNuxtApp()
```

以上です。
Vue.jsの対象の変数の値が変更されたときに処理を行いたい

## 結論
下記のようにコーディングすると、vm.flagの値が変更されたタイミングで、watchのhandler内の処理が実行される。

```vue
var vm = new Vue({
  el: '#app'.
  data: {
    message: '',
    flag: false
  },
  watch: {
    flag:
      handler() {
        this.message  = "flagが" + this.flag + "に変更されました。";
      }
  }.
  methods: {
    switch: function() {
      this.flag = !this.flag;
    }
  }
});
```
Google Analyticsのクイックスタートガイド

## 概要
- [Google Analytics](https://marketingplatform.google.com/about/analytics/)はwebサイトのアクセス解析サービス。
- [Google Analytics](https://marketingplatform.google.com/about/analytics/)の登録方法と簡単な使用法を説明する。

## Google Analyticsに登録し、Googleタグを取得する。
[Google Analytics](https://marketingplatform.google.com/about/analytics/)をブラウザで開き、「さっそく始める」をクリック
　　↓
Googleアカウントでログインして、「測定を開始」をクリック
　　↓
アカウント名（例えば、Googleアカウントなど）を入力し、データ共有設定（特に問題がなければ推奨のまま）を選択して、「次へ」をクリック
　　↓
プロパティ名（例えば、サイト名など）を入力し、タイムゾーンは日本、通貨は日本円を選択して、「次へ」をクリック
　　↓
ビジネス情報を適当に選択して、「作成」をクリック
　　↓
利用規約が表示されるので「同意する」をクリック
　　↓
希望するメール配信を選択して（選択しなくてもよい）、「保存」をクリック
　　↓
データ収集するプラットフォームを確認してくるので「ウェブ」をクリック
　　↓
ウェブサイトのURLとストリーム名（サイト名）を入力して、「ストリームを作成」をクリック
　　↓
タグを設置する方法を確認してくるので、「手動でインストールする」をクリック
　　↓
Googleタグが表示されるのでコピー
　　↓
コピーしたスクリプトをhtmlファイルの`<head>`の直後にペースト

ここまでの作業を行ったindex.htmlの例を以下に示す。`<!-- Google tag (gtag.js) -->`から`</script>`までがGoogleタグ。aaaaaはストリームごとに異なる。

```html
<!doctype html>
<html>
  <head>
    <!-- Google tag (gtag.js) -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-aaaaa"></script>>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());

      gtag('config', 'G-aaaaa');
    </script>
    <meta charset="utf-8">
    <title>Sample of index.html</title>
  </head>
  <body>
    <p>Hello Google Analytics!</p>
  </body>
</html>
````

## 取得済みのGoogleタグを確認する。

[Google Analytics](https://marketingplatform.google.com/about/analytics/)をブラウザで開き、「アナリティクスにログイン」をクリックして、Googleアカウントでログイン
　　↓
左下の「管理」をクリック
　　↓
アカウントとプロパティを選択（いずれも一つであれば自動的に表示される）
　　↓
「データストリーム」をクリック
　　↓
ストリームを選択（一つであれば自動的に表示されるのでクリック）
　　↓
「タグの実装手順を表示する」をクリック
　　↓
「手動でインストールする」をクリック
　　↓
Googleタグが表示される

## Googleタグを追加で取得する。
[Google Analytics](https://marketingplatform.google.com/about/analytics/)をブラウザで開き、「アナリティクスにログイン」をクリックして、Googleアカウントでログイン
　　↓
左下の「管理」をクリック
　　↓
アカウントとプロパティを選択（いずれも一つであれば自動的に表示される）
　　↓
「データストリーム」をクリック
　　↓
「ストリームを追加」をクリックして、「ウェブ」を選択
　　↓
通知が表示されるので、「はい」をクリック
　　↓
ウェブサイトのURLとストリーム名（サイト名）を入力して、「ストリームを作成」をクリック
　　↓
タグを設置する方法を確認してくるので、「手動でインストールする」をクリック
　　↓
Googleタグが表示されるのでコピー
　　↓
コピーしたスクリプトをhtmlファイルの`<head>`の直後にペースト

ここまでの作業を行ったindex.htmlの例を以下に示す。`<!-- Google tag (gtag.js) -->`から`</script>`までがGoogleタグ。aaaaaはストリームごとに異なる。

```html
<!doctype html>
<html>
  <head>
    <!-- Google tag (gtag.js) -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-aaaaa"></script>>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());

      gtag('config', 'G-aaaaa');
    </script>
    <meta charset="utf-8">
    <title>Sample of index.html</title>
  </head>
  <body>
    <p>Hello Google Analytics!</p>
  </body>
</html>
````
Windowsのバッチファイルでヒアドキュメントのあれこれ

# はじめに
バッチファイルでヒアドキュメントのようなことをするサンプルです。
例として、ヒアドキュメントをrubyに渡して実行させています。

# 改行の環境変数の遅延展開を使った場合（OK）
改行を環境変数LFで定義して、遅延展開で含めたものをechoすると複数行で表示される。
バッチファイルでは^の次の文字はそのままの文字として使われるので、^の次の文字である改行がLFの値として設定される。（^＋改行+改行+改行）

```batch
@echo off
setlocal enabledelayedexpansion
set LF=^


echo ^
puts a=1!LF!^
puts a+1!LF!^
puts a+2

echo ===
set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2

echo !STR!
```

```batch
puts a=1
puts a+1
puts a+2
===
puts a=1
puts a+1
puts a+2
```

# 改行ありの環境変数値をechoで出力してパイプで渡す場合（NG）
改行を含む環境変数値をechoしても1行目しか渡されない。
```batch
@echo off
setlocal enabledelayedexpansion
set LF=^


echo ^
puts a=1!LF!^
puts a+1!LF!^
puts a+2!LF!^
 | ruby

echo ===
set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2

echo !STR! | ruby
```

```batch
1
===
1
```

# 改行ありの環境変数値をsetで出力してパイプで渡す場合（OK）
setコマンドなら複数行を渡せるが注意が必要。
* 「環境変数名=」が表示されるのでその部分を1行目にしてmoreで読み飛ばす。
* setに指定した名前で始まるすべての環境変数が出力されるため、名前の重複がないようにする。
* 
```batch
@echo off
setlocal enabledelayedexpansion
set STR1=XXX
set LF=^


set STR=!LF!^
puts a=1!LF!^
puts a+1!LF!^
puts a+2

set STR | more +1
echo ===
set STR | more +1 | ruby
```

```batch
puts a=1
puts a+1
puts a+2
STR1=XXX

===
1
2
3
Traceback (most recent call last):
-:4:in `<main>': uninitialized constant XXX (NameError)
```

# 環境変数を読み込めるコマンドを使ってパイプ渡し（OK）
echoの代わりに環境変数を読み込めるコマンドを使って標準出力する。パイプを使わなくてもrubyならevalで実行できる。
```batch
@echo off
setlocal enabledelayedexpansion
set LF=^


set STR=^
puts a=1!LF!^
puts a+1!LF!^
puts a+2

ruby -e "puts ENV['STR']" | ruby
echo ===
ruby -e "eval(ENV['STR'])"
```

```batch
1
2
3
===
1
2
3
```

# ヒアドキュメントのサブルーチン化（OK）
call :labelによるサブルーチンでのヒアドキュメント。

```batch
@echo off
setlocal enabledelayedexpansion

call :HEREDOC "%~f0" VAR1 & goto :VAR1
puts a=1
puts a+1
puts a+2
:VAR1

echo !VAR1!
echo ===
set VAR1 | more +1 | ruby

call :HEREDOC "%~f0" VAR2 & goto :VAR2
puts a=10
puts a+1
puts a+2
:VAR2

echo !VAR2!
echo ===
set VAR2 | more +1 | ruby

exit /b

:HEREDOC
set FILE=%1
set VAR=%2
set FLAG=N
for /f "usebackq tokens=1* delims=" %%I in (`more %FILE%`) do (
	set WORK=%%I
	if "!WORK!" == "!WORK::%VAR%=!" (
		if "!FLAG!" == "Y" set %VAR%=!%VAR%!^

%%I
	) else (
		if "!FLAG!" == "Y" goto :END_HEREDOC
		set FLAG=Y
	)
)
:END_HEREDOC
exit /b
```

```batch
puts a=1
puts a+1
puts a+2
===
1
2
3

puts a=10
puts a+1
puts a+2
===
10
11
12
```

# バッチファイルの後方にスクリプトを配置（OK）
バッチファイル内にキーワードを書き、そのキーワードから後ろにスクリプトを書く。
キーワードの位置はfindstrで行番号を取得し、moreでそれ以降を読み取る。
```batch
@echo off
for /f "usebackq tokens=1 delims=:" %%I in (`findstr /n /b :script "%~f0"`) do set N=%%I
more +%N% "%~f0"
echo ===
more +%N% "%~f0" | ruby
exit /b
:script
puts a=1
puts a+1
puts a+2
```

```batch
puts a=1
puts a+1
puts a+2
===
1
2
3
```

# 番外：改行なしの1行渡し（OK）
複数行にこだわらず、改行なしの1行で渡す方法もある。
^の後の文字はそのまま使われるため、|の前に空白が必要。
```batch
@echo off
echo ^
puts a=1;^
puts a+1;^
puts a+2;^
 | ruby
```
```batch
1
2
3
```
適当に完全に理解するためのChatGPT入門

## 導入
「何か凄いAIらしい」と巷で噂のChatGPTがリリースされてから一ヶ月が経過しました。
まだ一ヶ月弱しか経っていないのにふと周りを見るとエンジニアは凄い凄いとTwitterで叫んでいます。ネットでは連日記事ランキングに居座り、概要は知らなくても話題になっていることはわかってきました。触る時間はないが概要は知りたくなってきた。

今回はそんな人向けに記事を出します。専門用語はできるだけ使わず説明をするので、試しに斜め読みをしてみてください。

## 概要
OpenAIという団体が作ったAIで、質問文を送ると回答が帰ってきます。このAIは色々なことを知っているので、ジャンルに関わらず回答してくれます。効率的な英語の学習方法から晩御飯の作り方まで教えてくれます。

### 得意なこと
ChatGPTくんは過去から引っ張ってきた膨大な学習データに基づいて回答してくれます。なので肌の保湿方法や革靴の弱点など、一般論を伝えることが得意です。また、精密な回答を必要としないアイデア出しも得意です。「○○についての案をn個列挙してください」と言えば、数秒でn個列挙してくれます。膨大な学習データがあるので翻訳も得意です。雑に英文を投げれば日本語に翻訳してくれるでしょう。

### 苦手なこと
ChatGPTくんは過去から引っ張ってきた膨大な学習データに基づいて回答してくれます。なので直近の出来事については学習していないので答えることができません。例えば、現時点でのビットコインの価格の解析は、取得できないので解析できません。また、ネットワークにも繋がっていないので、リアルタイムで取得することもできません。また、曖昧な要件のまま回答するのは苦手なようです。「面白いギャグを答えてほしい」「なんかいい感じにしてほしい」というような、部下にしたら泣いてしまうような質問を行うのはやめたほうが良いでしょう。また、知らないことも過去の学習データから予測して動いてしまうので、現状では厳密に間違ってはいけないものを質問するのはやめた方が良いです。

## 結局何に使えそうなの？
### 大量データの分析
主に大量なデータの分析に使えそうだと考えています。例えば100人に対して行ったイベントで、コメントペーパーに生年月日を書いてもらったとします。イベントが終わった後、どの年代の人が多いかを質問することで、イベントの客層を知ることができます。自由記述欄にどういうことが書かれているかをざっくり解析することもできます。

### 多言語の勉強ツール
膨大な学習データを基に、高性能な翻訳を行うことができます。ただ翻訳だけする場合はDeepLの方が使いやすいかもしれませんが、自分の英文の添削や細かいニュアンスの違い、特定の単語のユースケースや参考にできそうな例文の作成などにはとても有用に使えます。

### 開発の手助け
単体テストの作成、リファクタのアイデア出し等はもう既に利用ケースとして存在します。これは記事を作ったことがあります。環境構築はすっとばして普通にやってみてください。
https://zenn.dev/saldra/articles/721db78f9bb8ff

## 何に使えなさそう？
精度云々の話はいずれ上がるので無視をしたとして、何ができないかを考えたのですが、「無から新しいひらめきを出す」はAIには難しいと思います。あくまでも対話型AIなので、人間のインプットがなければ何もアウトプットしません。そのため、促されてアイデアを出すことはありますが、インプットがない状態での「ふとした思いつき」はまだまだ人間が担うと考えています。これは限界性というよりは性質の話なので、もしかしたら変わる可能性はあり、断言もしませんが自分はそう考えています。

以上、ChatGPTの完全理解記事でした。もし気になった方がいたらやってみてください。

また、この記事に関してや質問がある方は以下Twitterまでお問い合わせください。

https://twitter.com/sald_ra