OmniAICreator/Qiita-1.07M huggingface dataset:
Controlled ComponentとUncontrolled Component

<h2>Controlled Component</h2>
Controlled Component：FormのElementをstateにて管理すること。(＝<b>Reactにより、管理される</b>)

```react
import React from 'react'
import { useState } from 'react';

export default function ControlledComponent() {
    // stateを定義する。引数は初期値を定義。
    const [name, setName]=  useState('');
    const [essay, setEssay]=  useState('Please write Essay');

    function handleChange(event) {
        // synthetic Eventを受け取る
        setName(event.target.value); // setState(更新する値)
    }

    function handleEssayChange(event) {
        // synthetic Eventを受け取る
        setEssay(event.target.value); // setState(更新する値)
    }
    
    function handleSubmit(event) {
        // synthetic Eventを受け取る
        alert(`name: ${essay}, essay: ${essay}`);
        event.preventDefault(); // prevent to default work(in this case, prevent to reload)
    }
    return (
        <form onSubmit={handleSubmit}>
            <label>
            Name:
            {/* value={stateを定義する} */}
            <input type="text" value={name} onChange={handleChange} />
            </label>
            <label>
　　            {/* value={stateを定義する} */}
                Essay: <textarea value={essay} onChange={handleEssayChange} />
            </label>
            <input type="submit" value="Submit" />
        </form>
    )
}

```

<h2>Uncontrolled Component</h2>
Uncontrolled Component：Controlled ComponentはReactによりformのvalueが管理されますが、そうではない場合(valueが読み取り専用の場合、type="file")はReactがformのvalueが分からないため、refというattributeを使用します。

```react
import React, { userRef } from 'react'

export default function UncontrolledComponent() {
    // fileInputRefはUncontrolledのため、明示的にreferenceであることを定義する。
    const fileInputRef = useRef(null); 
    function handleSubmit(event) {
        event.preventDefault();
        alert(
            `Selected file - ${fileInputRef.current.files[0].name}`
        );
    }
    return (
        <form onSubmit={handleSubmit}>
            <label>Upload file:
            {/* uncontrolled component場合、reactはcomponentの値を参照できません。
            しかし、refをcomponentに付与するとcomponentのvalueがrefに込められます。 */} 
            <input type="file" ref={fileInputRef} /> 
            </label>
            <br />
            <button type="submit">Submit</button>
        </form>
        );
}

```
【JavaScript】JSONデータのデコード・エンコード

# 何の記事か
JSONファイル``.json``のデータをデコード・エンコードする手法をまとめました。
ここで、**デコード**というのはJSONデータをオブジェクトに変換すること、**エンコード**というのはその逆を表します。

# デコード
以下のようなJSONファイルがあったとします。
```json:example.json
[
  {
    "country":"Japan",
    "food":"sushi",
    "famous_place":["Tokyo","Osaka","Nagoya"]
  },
  {
    "country":"korea",
    "food":"kumuchi"
  }
]
```
``JSON.parse()``を記述することで、JSONファイルからデータをデコードし、インスタンスとして使うことができます。
```javascript
const fs = require("fs");
const jsonData = JSON.parse(fs.readFileSync("example.json"));
```
``require("fs")``は、Node.jsのファイル扱う用のモジュールを記述しています。
```javascript
console.log(jsonData[0].country); //Japan
console.log(jsonData[0].famous_place[1]); //Osaka
```
という風に簡単にメンバを呼び出すことができます。ちなみに、UTF8でデコードしたいときには、引数に``'utf8'``を追加します。
```javascript
const jsonData = JSON.parse(fs.readFileSync("example.json",'utf8'));
```
のように指定すればよいです。

# エンコード
構造体をJSONデータにエンコードするには、``JSON.stringify()``を使います。
```javascript
var myStructure = {
  Japan: {
    food:"sushi",
    famous_place:["Tokyo","Osaka","Nagoya"]
  },
  Korea: {
    food:"kumuchi",
    number: 999
  }
};

var jsonData = JSON.stringify(myStructure);
//{"Japan":{"food":"sushi","famous_place":["Tokyo","Osaka","Nagoya"]},"Korea":{"food":"kumuchi","number":999}}
console.log(jsonData);
```
``JSON.stringify()``は引数として関数を持つことができ、構造体をJSONデータにエンコードする際の条件付けなどが可能です。この関数は**replacer**と呼ばれています。
せっかくなので、``example.json``に書き込んでみます。
```javascript
const fs = require("fs");

function replacer(key,value){
  if (key === 'Japan') {
		return undefined;
	}
	return value;
}

var myStructure = {
  Japan: {
    food:"sushi",
    famous_place:["Tokyo","Osaka","Nagoya"]
  },
  Korea: {
    food:"kumuchi",
    number: 999
  }
};

var jsonData = JSON.stringify(myStructure,replacer);
fs.writeFileSync("./config/example.json",jsonData);
```
replacerでデータを選択的に取り出すことができたようです。
```json: example.json
{"Korea":{"food":"kumuchi","number":999}}
```
このままでは``example.json``の中身が見づらいと思います。実はもう1つ引数を追加することができて、それによってエンコードの具合が変わります。
```javascript
var jsonData = JSON.stringify(myStructure,replacer,"\t");
```
という風に、最後に``"\t"``を付け加えることで、いい感じに改行してくれます。
```json:example.json
{
	"Korea": {
		"food": "kumuchi",
		"number": 999
	}
}
```
今回は以上です。
【Xcode】SwiftFormatのPlugin使ってみた

# はじめに
https://qiita.com/SNQ-2001/items/c56658193d54c040c1fb

前回はSwiftPMでビルドした時に実行されるようにしました。
別の方法で導入することでボタンで実行できるみたいなのでやってみました。

https://github.com/nicklockwood/SwiftFormat#trigger-plugin-from-xcode

# やりかた
### SwiftPMで導入
以下のURLをコピーします。
```
https://github.com/nicklockwood/SwiftFormat
```
① 「File」を選択します
② 「Add Packages...」を選択します
![スクリーンショット 2023-01-14 21.38.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7c8e5920-da64-79fb-a141-7561df70d520.png)

③ テキストフィールドに先ほどコピーしたURLをペーストします
④ 「Add Package」を選択します
![スクリーンショット 2023-01-14 21.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2c32c0c3-6146-29b6-c0d8-f44be5c5d70d.png)

⑤ 何も選択せず「Add Package」を選択します
![スクリーンショット 2023-01-14 21.44.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e1045a4a-a9e9-29b4-5d78-dd04cdecfa01.png)

### 使う
SwiftFormatを使えてるか確認するためにコードをめちゃくちゃにしておきます笑
```swift:ContentView
import SwiftUI

struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
```
① プロジェクトを右クリックします
② 「SwiftFormatPlugin」を選択します
![スクリーンショット 2023-01-14 21.51.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/80ad7831-6a8c-3270-c17b-432da387ecb3.png)

③ 「Run」を選択します
![スクリーンショット 2023-01-14 21.53.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/f6154fdc-ffff-9ea6-f70b-32b664010781.png)

:::note info
Argumentsに引数を設定する事ができます。
![スクリーンショット 2023-01-14 21.55.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b1a5fe09-cc6b-6f11-7f1f-d2c841b52bd3.png)
:::

ビルドします。
![スクリーンショット 2023-01-14 22.37.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8812df35-7089-5bf3-4baf-c59d7ef20327.png)

元通りになりました！！！
![スクリーンショット 2023-01-14 22.36.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/38630f6b-e29a-9baa-e6f7-20f6990e0168.png)


# おわり
今回のようなプラグインをSwiftPMで使ったのが初めてだったので驚きました。
そのうち自分でも作ってみたいです
【Flutter】 Windowsでのflutter docker「Unable to find bundled Java version.」の修正

# 概要

WindowsでFlutter環境構築をしていたら、flutter docker実行に「Unable to find bundled Java version.」というエラーが出てました。

```
>flutter doctor
[√] Flutter (Channel stable, 3.3.10, on Microsoft Windows [Version
    10.0.19045.2486], locale ja-JP)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.4.4)
[!] Android Studio (version 2022.1)
    X Unable to find bundled Java version.
[√] VS Code (version 1.74.3)
[√] Connected device (3 available)
[√] HTTP Host Availability

! Doctor found issues in 1 category.
```


直す方法を調べてみるとMac向けの方法は見つかるものの、Windows向けの方法がなかなか見つからなかったので、備忘録として修正方法を記事に残します。



# 修正方法



```
cd C:\Program Files\Android\Android Studio
rmdir /S /Q jre
mklink /D "jre" "jbr"
```


# 参考

参考にさせていただいたのは以下issuesです。(というか答え)
https://github.com/flutter/flutter/issues/106674
【WebXR Device API】WebAR の「Hit Test」・「Anchors」などを Androidスマホでサクッと試した際のメモ

この記事は、「以下のツイートの動画の内容 ＝  Androidスマホで WebAR の特定の機能を試したもの」などに関するメモです（※ 主にアクセスしたページのメモ）。

https://twitter.com/youtoy/status/1614223688009920515

こちらの、別の　WebAR のサンプルも試しました。
![Immersive AR Sessionのお試し](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/d73e0518-5c25-2ab9-8dd3-5c7ce34eac67.png)

## 自分が試した 2つのデモの URL
上記の動画・画像で示していた、WebAR のサンプルを試すことができる URL を、まずは以下に掲載します。

●Hit Test with Anchors
　https://immersive-web.github.io/webxr-samples/hit-test-anchors.html

●Immersive AR Session
　https://immersive-web.github.io/webxr-samples/immersive-ar-session.html

## WebXR Device API に関するメモ
ここで、今回試した技術の一部について、関連するページなどをメモしておきます。

今回試した内容は、以下の「WebXR Device API」に含まれる内容です。

- WebXR Device API
   - [W3C のページ](https://www.w3.org/TR/webxr/)
   - [MDN のページ](https://developer.mozilla.org/ja/docs/Web/API/WebXR_Device_API)
   - [Chrome Platform Status](https://chromestatus.com/feature/5680169905815552) のページ

WebXR は VR に関するものと、AR に関するものとがありますが、今回試したのは AR に関するものです。

### 試せるサンプル
WebXR の VR・AR の機能を試そうと思った場合、便利なページの 1つに、以下があります。

●WebXR - Samples
　https://immersive-web.github.io/webxr-samples/
![WebXR - Samples](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a95803ef-d2bb-f55e-ec80-c0ef86291087.png)

自分が今回試していたサンプル 2つも、このページに掲載されています。具体的には、以下の画像のように、説明とともに関連リンクが掲載されています（数字の右にあるタイトル部分が、自分が試したサンプルへのリンクになっています）。

![Immersive AR Session](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/beb49f6f-4bf4-bf84-c3e2-2cb5b63ee8d7.png)
![Hit Test with Anchors](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/1f5bb9bd-80b1-6821-d20e-4308f5bf669c.png)

### 「Hit Test with Anchors」で使われていた技術の関連リンク
冒頭に、動画で掲載していたほうの「Hit Test with Anchors」について、もう少しメモを残します。デモのタイトルに含まれている「Hit Test」と「Anchors」について、それぞれ関連するリンクのメモです。

●WebXR Hit-test - Chrome Platform Status
　https://chromestatus.com/feature/4755348300759040
●hit-test/hit-testing-explainer.md at main · immersive-web/hit-test
　https://github.com/immersive-web/hit-test/blob/main/hit-testing-explainer.md
![hit-test](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/50a69485-e756-04f9-02f5-45171718bd49.png)

●WebXR Anchors - Chrome Platform Status
　https://chromestatus.com/feature/5129925015109632
●anchors/explainer.md at master · immersive-web/anchors
　https://github.com/immersive-web/anchors/blob/master/explainer.md
![anchors](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fb6d9725-8886-237c-b4f7-a32401fb9de8.png)

## その他のリンクのメモ

●Immersive Web Developer Home
　https://immersiveweb.dev/
Seleniumを使わずに自動ログインする

# 概要
とある事情で毎度のことIDとPASSを入力しなければいけないサイトがある...
自動でログインをしたいが、seleniumを使うのはスマートじゃない...
そこで、こんな力技が可能なんじゃないか...という話。
万能ではない上にあまり良い方法ではないので、よく考えて使いましょう。自身の戒めも兼ねて。
# 準備
題材としてニコニコ動画を使います。

[ログイン画面](https://account.nicovideo.jp/login) を開いてページをダウンロードします。
ログイン - ニコニコ.htmlとログイン - ニコニコ_filesが取得できますので、前者を複製してbase.htmlなどとしておきます。
# 実装
やることは「ダウンロードしたログイン画面のhtmlに、ログイン情報と自動でフォームを送信するスクリプトを追記して、開く」です。

powershellで書くと以下の通りです。

```powershell
$cred = Get-Credential

$input_id =  '<input id="input__mailtel" type="text" name="mail_tel" value="{0}">' -f  $cred.UserName
$input_pass =  '<input id="input__password" type="password" name="password" value="{0}">' -f (ConvertFrom-SecureString -SecureString $cred.Password -AsPlainText)

$login_html =  Get-Content 'base.html'

$login_html = $login_html -replace '<input id="input__mailtel" type="text" name="mail_tel" value="">', $input_id
$login_html = $login_html -replace '<input id="input__password" type="password" name="password">', $input_pass
$login_html = $login_html -replace "<form", '<form name="added_name"'
$login_html = $login_html -replace "</form>", "</form><script>document.added_name.submit();</script>"

$path = './ログイン - ニコニコ.html'
$login_html > $path
Invoke-Item $path
sleep 1
Remove-item $path
```
やっていることとしては
1. base.htmlを次の通り編集する。
    - `<input>`要素に`value="ID"or"PASS"`とIDとPasswardを直接書き込む
    - `<form>`要素に適当に名前をつける（`name="added_name"`）
    - `<form>`をsubmitするように`<script>`を追加
2. base.htmlでログイン - ニコニコ.htmlを上書き
2. ./ログイン - ニコニコ.htmlを開いて、すぐ消す

`sleep 1`は開く前にファイルが消されるのを防止するためです。
# まとめ
パッと書いたものなので、その点ご容赦願います。
`<form> <input>`で記載されているログイン画面があればよく、ニコニコ動画や楽天はそれでした。
こんな単純なサイトは少なくなりました...がこういうことをしたくなる環境では、そうでもないのではないでしょうか。
【BLOCS】オリジナルのバリデーションルールを作る

# バリデーションルール

Laravelは `required` や `max` など色々なバリデーションを、デフォルトでかけることができます。しかし、案件によってはオリジナルなバリデーションルールを追加したい場合もあります。Laravelでオリジナルのルールを作成して、BLOCSで利用する方法を紹介します。

:::note info
この記事では、Laravel11の実装方法を紹介します。Laravel10以前では、Laravelのオリジナルルール作成方法が異なりますのでご注意ください。
:::

# Laravelでオリジナルのルールを作る

artisanでオリジナルのルールを作ります。

```sh
php artisan make:rule Myrule
```

作成したルールを編集して、オリジナルのルールを作ります。今回は倍数の検証をするオリジナルのルールを作ります。

汎用性を持たせるために、コンストラクタで倍数を検証する数字を設定できるようしました。BLOCSテンプレートの`data-lang` で指定したメッセージが、`$message`に自動でセットされます。

```php:app\Rules\Myrule.php
    private $num;
    private $message;
    
    public function __construct(string $num, string $message)
    {
        $this->num = intval($num);
        $this->message = $message;
    }
```

次に、検証を通過する条件を設定します。`$value`に入力値がセットされますので、条件を決めます。オリジナルルールの作成は以上です。

```php:app\Rules\Myrule.php
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (intval($value) % $this->num === 0) {
            return;
        }

        $fail($this->message);
    }
```

# BLOCSのテンプレートで設定する

テンプレートでルールを指定します。デフォルトのバリデーションルールと併用することもできます。`data-lang` で、エラーメッセージを設定します。

```html:create.blocs.html
<input type="number" name="multiple" data-validate="bail|required|integer" />
<!--
    !multiple="Myrule:5"
    data-lang="5の倍数を入力してください。"
-->

@error("multiple") <div class="invalid-feedback">{{ $message }}</div> @enderror
```

# コントローラーでバリデーション実行
:::note info
コントローラーが、ベースコントローラーを継承している時は不要です。
:::

テンプレートで指定するだけでは、入力フォームへのバリデーションはかかりません。指定したバリデーションとメッセージを、フォームリクエストや`validate`メソッドに渡してバリデーションを実行します。今回は、フォームリクエストでバリデーションを実行しました。

```php:app\Http\Requests\BookRequest.php
    public function rules()
    {
        return \Blocs\Validate::rules('books.create');
    }

    public function messages()
    {
        return \Blocs\Validate::messages('books.create');
    }
```

バリデーションの動作確認です。5の倍数以外を入力すると、エラーメッセージが表示されます。

![スクリーンショット 2023-01-14 16.50.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962814/9ebe6b1b-bdd6-072e-54b9-9632baa27522.png)

# おわりに

今回は、オリジナルのバリデーションルールを作りました。プログラマーの労力を減らせる工夫を色々と取り入れてBLOCSを開発しています。PHP初学者や、プログラムに苦手意識のある方に特にオススメです。最後まで読んでいただき、ありがとうございました！

# 関連サイト
1. [サービスサイト](https://blocs.jp)
2. [GitHub](https://github.com/blocs/blocs)
3. [Packagist](https://packagist.org/packages/blocs/blocs)
お前らのtarの使い方は間違っている

# TL;DR
圧縮 **c**reate **f**ile
```bash
tar cf hoge.tar.gz hoge
```
解凍 e**x**tract **f**ile
```bash
tar xf hoge.tar.gz
```
`tar`で検索すると**z**や **-** を使った例が散見される。本当は必要ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/5b645a4b-1d22-f004-2ef8-6fc268b8deed.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/c8d0de8a-85b3-5043-b3c4-1cc5334dffb1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/14349934-87b2-3883-3ed0-c85e27719609.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/86e08b53-be03-c832-f578-680b139c5cc0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/142dd58b-2199-6c98-c7e0-0d3308a769b5.png)
Ruby1

# 問題
```Ruby
puts hash.keys
puts hash.values
```
上記のメソッドを実行した時に

```Ruby:ターミナルの表示
one
two
three
1
2
3
```

とターミナルに表示されるような変数hashを作成するためのコードをシンボルを使って記述してください。

<br>
<br>
<br>

# 模範解答

```Ruby
hash = { one: 1, two: 2, three: 3 }
```

<br>
<br>

# 【解説】
シンボルを使ったキーの記述方法は、キーの後にコロン:をつけて定義します。
```Ruby:使用例
hash = { キー: 値}
```

ハッシュをシンボルで記述すると、コード上では文字列のように見えていますが、内部的には数値として処理されます。数値として扱われるので、PC内での処理速度が速くなることと文字列としての役割も果たします。
シンプルで見やすいため、ハッシュのキーにはシンボルを用いることが多いです。

<br>

ハッシュのキーを取得するにはkeysメソッド、値を取得するにはvaluesメソッドを使用し取得します。

オブジェクト.keysで、ハッシュに含まれるキーを取得します。

```Ruby:キーの取得
hash = { one: 1, two: 2, three: 3 }

puts hash.keys
one
two
three
```

オブジェクト.valuesで、ハッシュに含まれる値を取得します。

```Ruby:値の取得
hash = { one: 1, two: 2, three: 3 }

puts hash.values
1
2
3
```
Julia言語で湯婆婆を実装した

今更ながら、こちらの記事
https://qiita.com/Nemesis/items/c7192a7c510788d2cba2
が震源の、「プログラミング言語で湯婆婆」をやりました。言語はJuliaです。

# 実装
```julia
function yubaba()
    println("契約書だよ。そこに名前を書きな。")
    name = readline()
    println("フン。$(name)というのかい。贅沢な名だねぇ。")
    newName = rand(name)
    println("今からお前の名前は$(newName)だ。いいかい、$(newName)だよ。分かったら返事をするんだ、$(newName)!!")
end
```

# 実行例
![スクリーンショット 2023-01-14 21.43.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113311/3dd58370-376e-fb92-6464-d8e0ab1713f1.png)
Googleプロジェクト管理：ステークホルダー分析

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a1cc3407-8d1d-b37c-1d3a-50bf9ea5159f.png" width="800">

# ステークホルダー分析とは

プロジェクトにとってステークホルダーとの関係性は重要です。一次および二次ステークホルダーがいかにプロジェクトマネージャがプロジェクトのゴールと成果を定義するのに役立ちます。

- 一次ステークホルダーとは、プロジェクトの成功によって直接的に利益を得る人たち
- 二次ステークホルダーとは、プロジェクトの成功によって間接的に影響を受ける人たち

このように様々な人がプロジェクトに関わることで、混乱することがあります。

そこで、ステークホルダー分析が役に立ちます。

***<font color="MediumVioletRed">『ステークホルダー分析とは、すべてのステークホルダーを視覚的に表したもの』</font>***

ステークホルダー分析は、サプライズを回避し、必要なパートナーシップを構築し、適切な人を適切なタイミングで関与させるのに役立ちます。

ステークホルダー分析がうまくいけば、成功のチャンスと潜在的なリスクをすべて把握することができ、どのステークホルダーがどのような責任を負っているかを示すことができ、重要な会話に適切な人を参加させることができるため、プロジェクトを通じて必要なサポートを得るための鍵となります。

# ステークホルダー分析のための3つのステップ

1. プロジェクトが影響を与えるすべての利害関係者を ***<font color="MediumVioletRed">リストアップ</font>*** する。 このリストを作成する際、自問自答してください。
    - このプロジェクトに投資しているのは誰か？
    - このプロジェクトの影響を受けるのは誰か？
    - このプロジェクトに貢献しているのは誰か？
1. 各ステークホルダーの ***<font color="MediumVioletRed">関心度や影響力</font>*** を把握する。利害関係者の関心度や影響度が高ければ高いほど、プロジェクトを通じて彼らのニーズを優先させることが重要になります。これは、下記に紹介するパワーグリッドを使って、可視化します。
1. ***<font color="MediumVioletRed">ステークホルダーの参加能力を評価</font>*** し、彼らを 巻き込む方法を探す。
    - ある人は、より多くの意見やタッチポイントを持つ積極的なステークホルダー
    - ある人は、ハイレベルな最新情報のみを好み、日常的な関わりを持たない受動的なステークホルダー

### パワーグリッド

パワーグリッドを使って、各ステークホルダーのプロジェクトに対する重要度を割り出し、その関心度と影響力を測定します。通常、グリッド上のステークホルダーの位置は、プロジェクトにおける積極的な役割を決定する。関心度や影響力が高いほど、そのステークホルダーはプロジェクトの成功にとって重要であることを意味します。彼らのサポートがなければ、プロジェクトがうまく着地する可能性は低いでしょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/31ee06c8-e79b-992e-6181-df1870f6ac8b.png" width="700">

| カテゴリ | 意味 |
| :--- | :--- |
| Key Players | 主要なステークホルダーをうまく管理するには、望ましい結果を得るために、彼らと密接に連携することが必要です。 | 
| Meet their Needs | 影響力は大きいが関心の低いステークホルダーがいます。これらのステークホルダーを管理するためには、彼らと相談し、彼らのニーズを満たすことが必要です。彼らの意見やインプットは、プロジェクトにとって重要です。製品担当ディレクターは、影響力は高いですが、日々の活動には関与していないため、関心度は低くなります。 | 
| Show consideration | これらのステークホルダーには、プロジェクトに関する最新情報を提供することで、彼らへの配慮を示すとよいでしょう。彼らが発言権を持つことはまずないでしょうが、情報を提供し続けることは重要です。例えば、カスタマーサポートチームは、新製品について顧客と直接仕事をするため、影響力は低いものの、高い関心を持つかもしれません。 | 
| Monitor | ステークホルダーの中で最も重要度が低いですが、重要でないわけではありません。ただ、このプロジェクトにとって、それほど重要でないということかもしれません。ですから、このプロジェクトでは、主に彼らをモニターし、常に把握しておきたいのです。 | 

プロジェクトに賛同してもらうためには、 ***<font color="MediumBlue">影響力の大きいステークホルダーに特に注意を払い、彼らがプロジェクトに参加していると感じられるようにする</font>*** 必要があります。プロジェクトが彼らの目標達成にどのように役立つかを説明し、後々何か問題が発生した場合には、彼らのサポートを得ることができるようにしたいものです。
Unityでフォルダをお気に入りする方法とおすすめお気に入り機能アセットの紹介

# フォルダをお気に入りにする方法
![スクリーンショット 2023-01-03 17.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104976/f344f495-acee-c926-60dd-df5d17f9265c.png)
UnityにはFavoritesという機能があります。これは一般的に検索した内容を保存しておくという機能ですが、Favoritesのところにお気に入りしたいフォルダをドラッグ＆ドロップすることでフォルダもお気に入りにすることができます。
しかし、問題点として、これらのお気に入りのデータはPCの共通のデータとして保存されるため、一つのプロジェクトしか触らない場合以外ではフォルダのお気に入りとしては使い勝手が悪いです。複数のプロジェクトにまたがる場合は別途アセットが必要です。

# UnityTools-FavoritesAsset
こちらのアセットでは別のwindowになりますがドラッグ＆ドロップによるフォルダ、アセットの登録が可能で、お気に入りのグループ化もできるアセットです。(画像は下記リンクからの引用)
![129484724-dda7322e-3049-4762-996c-79ea88906584.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104976/2e75b04e-3c33-95bf-108c-9a9b41b06bda.gif)


https://github.com/MasyoLab/UnityTools-FavoritesAsset
Get通信とPost通信の実装の違いをSpringBootで解説してみた

<h1>Get通信とPost通信の違い</h1>
<p>この記事では、Get通信、Post通信におけるURLの違いと、パラメータの受け取り方をメインに扱います。<br>
   Get通信、Post通信とはなんぞや？という方や、Get通信やPost通信の使い分けに関して知りたい！という方は記事の対象外となります。あらかじめご了承ください🙇‍♂️</p>


<h2>URLの違い</h2>

Get通信は、URLに対して、クエリ(パラメータ)を設定することができます。
URLの<b><font color="blue">?</b>が「ここからがパラメータの始まりだよ〜」という意味を示しています。
値の渡し方は【パタメータ名=値】で渡されます。
<b><font color="blue">&</b>でパラメータを複数渡しています。
```
URL(Get通信)
　/test?id=1&name=test
```

Post通信はパタメータをURLにくっつけずに、値を渡す方式です。
formタグの中の要素を渡すことができます。
```
URL(Post通信)
　/test

<!-- nameタグがパラメータ名、valueタグが値になります。 -->
<form method="post">
    <input type="hidden" name="id" value="1" />
    <input type="hidden" name="name" value="test" />
</form>
```

<h2>サーバー側でパラメータを受け取る方法(SpringBoot)</h2>
■Get通信の場合(/test?id=1&name=test)

```java:TestController.java
@Controller
@RequestMapping
public class TestController {
    @GetMapping("/test")
    public String test(@RequestParam("id") String id, @RequestParam("name") String name){
        // 以下省略
        return "index";
    }
}
```

■Post通信の場合(/test)
```html:index.html(thymeleaf)
<!-- th:objectでPost通信で渡したいJavaオブジェクトを指定できる。先頭は小文字にする。 -->
<form method="post" th:object="test">
    <input type="hidden" name="id" th:field="id" value="1" />
    <input type="hidden" name="name" th:field="name" value="name" />
</form>
```
```java:Test.java
import lombok.Getter;
import lombok.Setter;

public class Test{

    @Getter
    @Setter
    private String id;

    @Getter
    @Setter
    private String name;
}
```

```java:TestController.java
@Controller
@RequestMapping
public class TestController {
    @PostMapping("/test")
    public String test(@ModelAttribute Test test){
        // 値の1が入ってる。
        String id = test.getId();
        // 値のnameが入ってる。
        String name = test.getName();

        return "index";
    }
}
```

<h2>まとめ、参考</h2>
<p>ざっくりですが、Get通信、Post通信の実装の違いをSpringBootを使って解説してみました。<br>
間違いなどありましたら、お気軽にご指摘をお願いします！<br><br>
■参考にしたサイト<br>
<a href="https://blog.senseshare.jp/get-post-method.html">GET／POSTの違い＆実際の使い分け方</a>
<br>
<a href="https://qiita.com/kanataxa/items/522efb74421255f0e0a1">GETとPOSTの違いについて</a>
</p>
WebGL1にて スマホだと変数が初期化されない




<br><br><br>

 https://qiita.com/yuji_yasuhara/items/237a571b9ba8be3d0cbd

先日、上記記事を参考にUnityroomでスマホ用ゲームを作って遊んでいた。
https://unityroom.com/games/trafficknightneo

２Dなアクションゲームで、クリアしたらスコアランキングが呼び出されて、ハイスコアのアップロードなどできるようにした。
ちょいちょい遊んでくれた人がいたようで、うれしく思っていたのだが、一位のスコアがおかしな値になっていた。
自分の想定では、スコアは1000~2000程度であるはずが、1位の人のスコアは9960ほどだった。

検証してみると、スマホで遊んでいる状態でゲームオーバーになってもスコアが初期化されず次のゲームに引き継がれてしまっていた。
困った理由としては、Unity上のエミュレートでは問題ない。ＰＣブラウザで遊んでみても問題ない。しかしスマホだと変数が初期化されなかった。
public staticな変数に0を再代入してリセットとする処理だったのだが、なーぜか０がはいらねえ。

なんでじゃぁ！！！

まあスマホブラウザで動かすのは非推奨だからね。しょうがないね。


# 環境
Macbook pro 2020 Ventura
Unity 2020.3.18f1
Microsoft Visual Studio Community 2019 Version 16.11.15
スマホ･･･LG V60 ThinQ


# 対応
ゲームオーバーになったら別のシーンを挟む。
真っ黒背景にNowLoading･･･とだけUIテキストを置いて、そいつに「1秒後元のシーンに飛ぶ処理」をStart()に記述したスクリプトをアタッチ。あとは空っぽ。

とりあえずこれで変数が初期化されるようになった。
理由は知らん。動けばOK。センキューUnity。センキューUnityroom。
Pythonでの音声信号処理 (6) ダミーデータを鳴らす

## やりたいこと
ダミーデータを鳴らすこと

## やってみた
音といえば、A（ラ）の音を使うことが多いようなので、A = 440 Hz で試してみる。

```p6.py
# -*- coding: utf-8 -*-
import sys
sys.dont_write_bytecode = True

from pydub import AudioSegment
from pydub.playback import play
import Dummy as dmy

def main():

    smpl = 44100 # サンプリングレートは44.1kHz
    sec = 2      # 2秒分

    wavA = dmy.makeWave(440, smpl, sec, 32, 0, 1)

    aud = AudioSegment(
            wavA.astype("int8").tobytes(),
            sample_width=1,
            frame_rate=smpl,
            channels=1
    )

    play(aud)

if __name__ == '__main__':

    main()
```

環境にもよると思いますが、Windowsで実行したところ
![ERR06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850619/926d9a46-465f-bbe5-e282-b81f00fb34dd.png)
というエラーが出てしまいました。

ファイルの権限がない状況にも見えますが、フォルダ自体は存在していて書き込み権限もあり、
調べてみると、不可避な既知不具合っぽい謎現象で、

```
py -m pip install pyaudio
```

で pyaudio をインストールすることで回避できるようです。

ということで、無事に、ラの音を出すことができました。

## 補足
Dummy.pyはここにあります。
https://qiita.com/u1tym/items/3e2be5364e83df1b7792
iOS16.2、iPadOS16.2でスマートホームの新標準「Matter」を試してみた

# はじめに

iOS16.1でスマートホームの新標準「Matter」に対応しました。

https://developer.apple.com/apple-home/matter/

# M5StackをMatterデバイスとして動かす

Matterのサンプルコードのビルド環境の構築は前提となる条件(ある程度のリソーススペックが求められる)や準備作業が必要なので、M5StackでMatterのサンプルを動かすだけなら、ESP Web Toolsを使用してブラウザ(ChromeのWeb Serial)経由でインストールするのが楽です。

https://qiita.com/kitazaki/items/548abb35431f215df919

# 構成プロファイルは不要

説明を読むと構成プロファイル(EnableMatter.mobileconfig)をインストールする手順になっていますが、インストールは不要でした。

https://developer.apple.com/forums/thread/708637

https://github.com/project-chip/connectedhomeip/blob/ab028397daec2c3053998bf56624aa40da76a7fa/docs/guides/darwin.md

# ホームハブが必要

Matterデバイスをホームアプリに登録しますが、Matterデバイスを操作するためにはホームハブが必要になります。
ホームハブはiPad、Apple TV、HomePodを使用することができます。(今回はiPadを使用しました)

![スクリーンショット 2023-01-14 19.59.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4c9ed5d0-5390-aea4-3926-b1012ea11dcc.png)

## ホームハブへの登録手順

ホームアプリを起動して「アクセサリを追加」を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/893c0f4e-f520-2473-6c0b-55c2989c5308.png" width="50%">

M5Stackの画面にQRコードを表示し、iPadのカメラからQRコードをスキャンします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/211af821-d9a4-010d-3fac-4dca170a3bb2.png" width="50%">

認定されていないアクセサリと表示されますが、「このまま追加」を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6d18fded-4238-78c9-ad8a-f39ca8cea0e3.png" width="50%">

ホームハブを有効にしていない場合、エラー「ホームハブが必要です」が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/51601bd6-86be-4122-f38e-7e3e909c5856.png" width="50%">

「詳しい情報」を押すと説明が表示されます。(Matterのアイコンが表示されています)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/470a9081-1550-8158-18db-b8f74e8d9737.png" width="50%">

「OK」を押してホーム画面に戻り、「設定」→「ホーム」を選択し、「このiPadをホームハブとして使う」を有効にします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c04412b0-31a4-6778-7dd9-2dc510f2e529.png" width="50%">

もう一度「アクセサリを追加」を実行すると、Matterデバイスを登録できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1215f69b-2603-ef7d-6e09-fc063547c4e6.png" width="50%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/23cf9345-8fd5-8197-14f1-56dfb1833adf.png" width="50%">

ホーム画面から「設定」→「一般」を選択すると、「Matter対応アクセサリ」として表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/4ad753b8-b949-27fb-9b7f-4437020e357b.png" width="50%">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/6509b90b-4953-ea26-328d-f6224caffeb6.png" width="50%">

# ホームアプリからMatterデバイスを操作する

ホームハブとして設定したiPadからMatterデバイスを操作できるのはもちろんのこと、iCloudアカウントが同一であればiPhoneのホームアプリからホームハブ(iPad)経由でMatterデバイスを操作することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/bb462bb1-74a2-de5b-cbe7-3abd91b3f99f.png" width="30%">

https://youtube.com/shorts/hODlbTZ2f0U?feature=share

https://youtu.be/jRWIS8Tf0_s
Windows 10 の Cortana をアンインストールする（削除）方法

# アンインストール手順

- Windows PowerShellを管理者権限で実行します。

![](https://storage.googleapis.com/zenn-user-upload/9c59532fb185-20230114.png)

- 下記のコマンドをコピペして実行します。

```shell
Get-AppxPackage -allusers Microsoft.549981C3F5F10 | Remove-AppxPackage
```

- 実行完了↓

![](https://storage.googleapis.com/zenn-user-upload/8610ee2d8db2-20230114.png)

- ctrl + C で Cortana を起動して見ると、何も出てきません、これで削除はできました。
Seleniumで偽装が無駄な理由

## 簡単に判明します
規約違反を犯してSeleniumでアクセスしている皆さん。
バレてますよ!!!!!
UA偽装だとかIP偽装だとかがありますが、JavaScriptをもってすれば簡単に検出することができます。

```JavaScript:example.js
if (navigator.webdriver) {
    alert("Webdriverを検出しました");
}
```

BANされない為にもSeleniumを使用しての規約違反は絶対にやめてください。
またこれに対する対策を講じてもreCAPTCHAによって検出される可能性も否めないので、利用規約は遵守しましょう。


## 注意
この記事は規約違反を推奨するものではありません。
皆さんで絶対に規約を守って素晴らしいインターネット空間を切り開いていきましょう。
Xcode+Realmでのユニットテスト

Realmを使っているプロジェクトでユニットテストを行おうとしたときに若干ハマったので書きます。
コンパイルが通らなかったり、通ってもテストとは関係のないところで足止めを食らったので、その時やったことの備忘録です。

# 環境（投稿時）
- MacBook Air M1, 2020
- macOS Ventura 13.1
- Xcode: `14.2`
- Realm: `10.33.0`
- RealmDatabase: `12.13.0`

# 準備
基本的には以下のサイトに従います。

https://www.mongodb.com/docs/realm/sdk/swift/test-and-debug/

ユニットテスト用のファイルを作ると、以下のようなファイルが作られるはずです。

```swift
import XCTest

final class UnitTest: XCTestCase {

  override func setUpWithError() throws {
    // Put setup code here. This method is called before the invocation of each test method in the class.
  }

  override func tearDownWithError() throws {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
  }

  // 以下略
}

```

前述の公式の説明に従えば、以下のように記述することで、ユニットテスト用のRealm環境でテストを行うことができます。
つまり、実機やシミュレータでのテストに影響が出ません。
また、テスト後に破棄されるためクリーンアップについても気にする必要がありません。

```swift
// ...
  override func setUpWithError() throws {
    super.setUp()
    Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
  }
// ...
```

これで、`let realm = try? Realm()`等で作ったユニットテスト用のrealm環境と、実機やシミュレータ上のrealmの環境が分離されます。
あとはテスト用の関数を追加していき、テストを行えばおk、のはず…。

# トラブルシューティング

## `import RealmSwift`ができない
テスト用のターゲットにRealmのライブラリをリンクしていないことが原因です。
TARGETS > (ユニットテスト用のターゲット) > Build Phases > Link Binary LibrariesでRealmを追加します。
注意としてはRealmSwiftは **追加してはいけません** 。（次で書きます）


## テスト実行時にRealmにオブジェクトを追加できない
~~以下のようなエラーメッセージが出た場合、~~

> ~~Object type (クラス名) is not managed by the Realm. If using a custom `objectClasses` / `objectTypes` array in your configuration, add (クラス名) to the list of `objectClasses` / `objectTypes`. (RLMException)~~

~~これは、一つ前でも少し書きましたが、**RealmSwiftをリンクしていることが原因です**。
前述の公式のチュートリアルにも書いてはあります。~~

> ~~Don't link the Realm Database framework directly to your test target. This can cause your tests to fail with an exception message "Object type 'YourObject' is not managed by the Realm." Unlinking Realm Database from your test target should resolve this issue.~~

~~ここで言われている "Realm Database framework" をてっきりRealmのことだと思い、RealmSwiftをリンクしてRealmをリンクしないようにしてたのですが、そのせいで何時間かハマりました。
**RealmSwiftはリンクせず、Realmだけをリンクしましょう**。
ぶっちゃけこの記事ではこれを書きたかっただけです。~~

### 2024/04/20追記

この項目について、状況が変わっていたので追記します。

- Realm: `10.49.2`
- RealmDatabase: `14.5.2`

**上記環境では、 `RealmSwift` もリンクする必要がありました**。
リンクしない場合、以下の画像のように、 `Realm` を呼んだときに `SIGABORT` します。
![スクリーンショット 2024-04-20 21.51.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674335/fc4863e3-5d1f-f6ff-0ab2-a87b42b33cbd.png)

---

他にもつまずいたら追記していきます。
共有エッジを持つポリゴン境界線の破線間隔を均一に表示する

**実行環境**
Windows10
Python 3.9.5
geopandas 0.10.2
shapely 1.8.0

## はじめに
GIS ソフトなどで行政界を破線で表示したいのに実線になってしまうことが多々あります。

![r2ka13101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1409923/a014bd04-a2ad-6b01-d3c3-202f1961604d.png)

上の図は、[e-Stat 政府統計の総合窓口](https://www.e-stat.go.jp/) からダウンロードした国勢調査統計の小地域データを破線で表示したものです。

シェープファイル形式の東京都千代田区のポリゴンデータを [ArcGIS Pro](https://www.esri.com/ja-jp/arcgis/products/arcgis-pro/overview) で表示しています。

見てわかる通り、破線間隔が場所によってバラバラで美しくありません。

この現象は、隣接するポリゴン境界上に２本の破線が重なっているため発生します。

なお、隣接するポリゴンのない境界の破線間隔は均一になっています。

## 対策
ArcGIS Pro のテクニカルサポートに記事が載っていました。

https://support.esri.com/ja/technical-article/000023970

「ポリゴン境界シンボルを同期する」方法と「ポリゴン フィーチャをライン フィーチャに変換する」方法が載っています。

ただし上記の方法を行う場合、ArcGIS Pro の3つのライセンスのうち最高ランクの Advanced ライセンスが必要になり敷居が高いです。

そこで本記事では、GIS ソフトのツールを使わずに破線間隔を均一に表示する方法について書きたいと思います。

処理としては、ポリゴンから「重なりのないライン」への変換になります。

※実際は ArcGIS Pro の Basic ライセンスでも、「同じ2つのポリゴンデータを入力としてラインタイプでインターセクト」すると、破線間隔を均一に表示できるようです。（ただし、重なるラインの数は倍になります）

## コード
使用する python ライブラリは [geopandas](https://geopandas.org/en/stable/) と [shapely](https://shapely.readthedocs.io/en/stable/index.html) です。

先述の千代田区のポリゴンを入力ファイルとしています。

``` py
"""
geopandas 0.10.2
shapely 1.8.0
"""
import geopandas as gpd
from shapely.ops import linemerge

shp_poly = r'r2ka13101.shp'
shp_line = r'r2ka13101_line.shp'

# ポリゴン読み込み
gs_poly = gpd.GeoSeries.from_file(shp_poly)

# ラインに変換
gs_line = gs_poly.boundary

# ジオデータフレームに格納
gdf = gpd.GeoDataFrame({'geometry': gs_line})

# クリーニング（ディゾルブしてからシングルパートに分解）
gdf = gdf.dissolve().explode(index_parts=True)

# 共有線をマージ（頂点の並びをそろえるためにノーマライズ）
lines = linemerge([line.normalize().coords for line in gdf['geometry']])

# シェープファイルに出力
gpd.GeoSeries(lines).to_file(shp_line)
```

## 確認
変換前後のデータを破線表示しています。

![r2ka13101.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1409923/7d56bba8-59c4-f9a7-bb34-930abe409a0e.gif)

変換後の破線間隔が均一になっていることが確認できました。

## 最後に
GIS ソフトで破線間隔を均一に表示するために、ポリゴンを「重なりのないライン」に変換する方法について書きました。

行政界は破線や一点鎖線で表現されることが多いので、実線にならないように注意したいところです。
ラズパイからLINE Messaging APIにメッセージを送信させてみた

# なぜ作ろと思ったのか
今日はゴミ捨ての日とか、体重計乗りなさいだとか、傘持った？みたいな通知をしてくれるリマインダー機能がほしかった。
アプリを入れても見ないけど、LINEなら見るだろうと思って作ってみた。
タイトルにラズパイからと書いてあるが、何から送っても良い。

# LINE Messaging API
LINE公式アカウントを作成して、そのアカウントから利用者（お友達）にメッセージを送信したり応答したりすることができる仕組み。
今回は通知するだけで応答機能は作らない。気が向いたら作って別の記事にします。

## 料金とメッセージ送信数
無料プランでは、毎月1000通のメッセージを送ることができる。個人利用ならフリープランで十分だろう。

https://www.linebiz.com/jp/service/line-official-account/plan/

# アカウントを作成してログイン

https://developers.line.biz/ja/services/messaging-api/

以下まで進める
- LINEアカウントもしくはLINEビジネスアカウントでログイン。
- プロバイダ登録

# チャネルを登録
以下入力して登録。登録後も変更できます。
| 項目 | 入力 |
|:-|:-|
| チャネルの種類 | Messaging API |
| プロバイダー | プロバイダ名を選択 |
| 所在地 | 日本 |
| アイコン | とりあえずなしで |
| チャネル名 | 好きなチャネル名(Bot名)を入力 |
| チャネル説明 | チャネルの説明文を入力 |
| 大業種 | 当てはまるものを選択 |
| 小業種 | 当てはまるものを選択 |
| メールアドレス | メールアドレスを入力 |
| プライバシーポリシーURL | 個人利用かつ任意なので入力しなかった |
| サービス利用規約URL | 個人利用かつ任意なので入力しなかった |

# お友達になる
チャネルのMessaging API設定のタブにQRコードがあるので、読み込むとお友達になれます。
ボットのベーシックIDを検索して友達追加でもいけそうです。

# アクセストークンを取得
作成したLINEbotのアクセストークンを取得します。
パスワードと同じように重要な情報ですので、他人に見られない場所に記録しておきます。

# 送信してみる
メッセージの送信はこちらを参考にする。

https://developers.line.biz/ja/reference/messaging-api/#send-push-message

Webhookの仕組みで送信できるようである。
`{channel access token}`に先程取得したアクセストークンを入力。
`U4af4980629...`の部分は、作成したチャネルの基本設定に記載されている、「あなたのユーザーID」を入力する。
参考ページに記載されているリトライキー(`-H 'X-Line-Retry-Key: {UUID}' \`)は任意のため記載しなくてもいい。
```
curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "to": "U4af4980629...",
    "messages":[
        {
            "type":"text",
            "text":"Hello, world1"
        },
        {
            "type":"text",
            "text":"Hello, world2"
        }
    ]
}'
```
１度のリクエストで最大５回メッセージが送れるようである。

上記curlコマンドをshellscriptで作成してもよし。
PythonやGoなどの他の言語のサンプルも乗ってるので、好きに作ってみたら良いと思う。
Webhookなので、POST送信できればどこからでも送れそう。

# cronで定期的に通知させてみる
## shellscriptを作成する
```console:terminal
# mkdir /usr/local/src/linebot
# vi /usr/local/src/linebot/diet.sh
```
```shell:training.sh
#/bin/bash
curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "to": "U4af4980629...",
    "messages":[
        {
            "type":"text",
            "text":"筋トレして体重計に乗ろう！"
        }
    ]
}'
```
最後にカンマをつけてしまうと送信失敗するかも。注意しよう。
```
        {
            "type":"text",
            "text":"筋トレして体重計に乗ろう！\nそしてお風呂に入って寝よう！"
        },
```
改行コードは¥nではなくて、\nなので間違えないように。

## cron設定する
cronは、以下の順番で並ぶ。
分　時　日　月　曜日　コマンド
```console:terminal
# crontab -e
```
21時で設定した。
```config:cron設定
0 21 * * * sh /usr/local/src/linebot/diet.sh > /dev/null 2>&1
```

### (参考)> /dev/null 2>&1について
cronを実行すると、標準出力される内容が実行ユーザーにメールが飛ぶ仕様。
スクリプトによっては、定期実行してたらメールの量が大量になってディスクを圧迫してしまう、なんてことも！
このスクリプトは何も出力がでないかもだけど、とりあえず入れておく。
Linuxの環境変数設定：起動から有効（bashの場合とcshの場合）

## bash
### /etc/profile
bashのログインから実行する。全てのユーザーは参照する可能、基本の環境変数を設定する。<br>
環境変数の設定方法<br>
1. /etc/profileを開く(vi /etc/profile)
2. 環境変数設定を追加：export [環境変数]=[値]
3. 保存

## csh
### /etc/csh.login
/etc/csh.loginはcshの「/etc/profile」。<br>
環境変数の設定方法<br>
1. /etc/profileを開く(vi /etc/profile)
2. 環境変数設定を追加：setenv [環境変数] [値] ("="がない)
3. 保存

## ターミナルの値
いまのターミナルはbashかcshの表示方法：<br>
+ env：全ての環境変数を表示して、SHELLの値を見える。
+ echo $SHELL：直接にSHELLの値を表示できる。
webpackの構築に関する、自分用メモ

#トラゼミさんの自分用メモ

```webpack.config.js


const path = require('path');
module.exports = {


  // モジュールバンドルを行う起点となるファイルの指定
  // 指定できる値としては、ファイル名の文字列や、それを並べた配列やオブジェクト
  // 下記はオブジェクトとして指定した例
  entry: {
    bundle: './src/index.ts'
  },


  // モジュールバンドルを行った結果を出力する場所やファイル名の指定
  //　今いる階層と同じところにある、distが出力先のパスになる
  output: {
    path: path.join(__dirname, 'dist'), // "__dirname"はファイルが存在するディレクトリ
    filename: '[name].js'  // [name]はentryで記述した名前（この設定ならbundle.jsというファイルになるという事）
  },


  // import文でファイル拡張子を書かずに名前解決するための設定
  // 例...「import World from './world'」と記述すると"world.ts"という名前のファイルをモジュールとして探す
  resolve: {
    extensions:['.ts','.js'] // Reactの.tsxや.jsxの拡張子も扱いたい場合は配列内に追加する
  },


  devServer: {
    contentBase: path.join(__dirname, 'dist'), // webpack-dev-serverの公開フォルダ
    open: true // サーバー起動時にブラウザを開く
  },


  // モジュールに適用するルールの設定（ローダーの設定を行う事が多い）
  module: {
    rules: [
      {
        // 拡張子が.tsのファイルに対してTypeScriptコンパイラを適用する
        // Reactで用いる.tsxの拡張子にも適用する場合は test:/\.(ts|tsx)$/,
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
}
```
CKA に合格したので体験記を書いてみた 

# はじめに
2022/12にCKAを受験して合格しました。
8月にCKADに合格したあと少し期間を空けて、10月から勉強を開始したときにやったことを今回は記載します。
前回の記事は以下です。
[CKADに合格したので体験記を書いてみた](https://qiita.com/xyzCity/items/ac870dcb0a75f81ecce6)

# 試験の内容
ここはCKADと変更なし。
問題文にあるリソースを作成したり、すでにリソースはあるけど上手く動作しないから解決してください、といった内容になります。
実際に画面上でコマンドを打って解くので、実務に生きやすいかもしれません。

# 前提知識
CKADに合格した後での受験となります。

# 難易度
CKADと比較して、被る内容がかなり多い印象。
CKADの追加要素として以下を学んでおけば合格出来るかもしれません。
* [kubeadmのインストール](https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)
* [kubeadmを使ったクラスターの作成](https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)
* [各種アップグレード方法](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)
* [etcdのバックアップとリストア](https://kubernetes.io/docs/tasks/administer-cluster/configure-upgrade-etcd/)

# 勉強方法
みんな大好きUdemyで勉強しました。その他はほとんどやってません。（勉強量としては4週くらいしたかな？）
動画を見て、確認テストをする形式になります。 **いちいち自分で環境を用意しなくていいのが何より嬉しい！**
実際のテストさながらに画面を使って問題を解くので、慣れという意味でもかなり効きましたね！
この中に出てくるテストの難易度自体も本番とかなり似通っていたんじゃないかなと。
Litning Labははっきり言って試験以上の内容なので、 **ぶっちゃけやらなくても大丈夫です。** 
あとネットワーク周りを結構こってりとやらされますが、 **正直試験にはあまり関係なかったような印象があります。**

音声は英語ですが、最近日本語字幕が付いたため問題なく勉強可能思います。（機械翻訳のためたまにエキサイト翻訳されますが…）

https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/

# 試験で使ったテクニック
よく使うコマンドはまとめておくと楽になります。
この辺のコマンドは試験Tipsとして公式のサイトにも乗っているので是非覚えてください！
```
alias k=kubectl
export dry = --dry-run client -o yaml
```

ちなみにコンテキストの切り替えはコマンドを全て公式が問題文の中に用意してくれています。

# 受験方法
自分は下記から申し込みました。
英語が出来るならJPの付いていないお安い方で受けることも可能です。こちらも詳細はCKADの記事にて。

https://training.linuxfoundation.org/ja/certification/certified-kubernetes-administrator-cka-jp/

当日は他のリモート試験と同じく、「政府発行の身分証明書を提示」し、「部屋の中の様子全体をカメラに映す」ように指示されます。
壁、天井、机回り、机の下、キーボードの下を **かなりゆっくり写さないと怒られます。**
僕の場合、背後に段ボールを割と積んでいたりしましたが、それは特に何も言われませんでした。

机の上は身分証明書、マウス、キーボード以外はないようにしました。（ラベルのないペットボトルの水は許されるようです）

# おわりに
kubernetes関連の勉強は一旦これくらいで一区切りでいいかな、と思っています。
次はAWSかなぁ～。
Googleプロジェクト管理：チーム編成とプロジェクト内役割

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/a1cc3407-8d1d-b37c-1d3a-50bf9ea5159f.png" width="800">

# チーム編成するための意思決定方針

チームにふさわしい人を選ぶことは、大きな課題であり、すべてのプロジェクトマネージャーが真剣に取り組むべきことです。プロジェクトで仕事をするのは彼らなのだから、適切な人材を揃えたいと考えるでしょう。

### 要求される役割

まず、プロジェクトマネージャーは、各タスクを完了するためにチーム内で必要となる役割をリストアップします。プロジェクトマネージャーがプロジェクトの開始、計画、実行、完了までの全体的な責任を負うのと同じように、各役割の人はプロジェクトのライフサイクルの中で特定のタスクに対して責任を負います。

### チームサイズ

タスクが明確になったら、プロジェクトマネージャーはチームに何人必要かを決定します。これは、プロジェクトの規模によって大きく異なります。小規模なプロジェクトであれば、3〜4人で納期通りに成果物を完成させることができますし、大規模なプロジェクトであれば、数十人のチームを編成することもあります。

チームの規模を適切に設定することは、さまざまな理由から重要です。例えば、プロジェクトに多くの人が参加すると、コミュニケーションが難しくなることがあります。そのため、誰かが重要なことを見逃してしまう可能性が高くなります。また、チームの人数が少なすぎると、すべてのタスクをこなすのに十分な人数が確保できない可能性があります。

### 必要なスキル

プロジェクトマネージャーは、それぞれの役割にふさわしい人を決めるために、スキルについて慎重に考える必要があります。

プロジェクトマネージャーは、チームの全員が仕事に適したスキルを持っていることを確認する必要がありますが、スキルは教えることができることも忘れてはいけません。最初は特定のスキルを持っていなかったとしても、チームにとって最適な人材である可能性もあります。その人は、前向きな姿勢と細部へのこだわりを持っているのかもしれません。ただ、もしチームメイトに必要なスキルがない場合は、プロジェクトの遅延を招かないよう、時間内にトレーニングを行うことが重要です。


### 空き状況、モチベーション

また、プロジェクトマネージャーは、チームメイトを選ぶ際に、各人のアベイラビリティや、与えられたタスクをこなすモチベーションがあるかどうかも考慮しなければならない。例えば、チームにとって大きな戦力となる素晴らしいサイトマネージャーがいたとしても、その人がすでに別の大きなプロジェクトに参加している場合は、あなたのプロジェクトに参加する時間がないかもしれません。また、たとえ時間があったとしても、このプロジェクトが昇進に必要な知名度を与えてくれるとは思えないかもしれません。モチベーションは、優れた仕事をするための重要な要素です。

やる気のある人を選ぶのは良いことですが、もちろん、いつもリソースを選べるわけではありません。時には、別のマネージャーやチームリーダーが、ただ人を役割分担させることもあるかもしれません。そんなとき、与えられたリソースで最高の仕事をするのがプロジェクトマネージャーの仕事です。


:::note info
チーム作りの初期段階から、多様性を重視する必要があることを心に留めておいてください。多様性のあるチームでは、誰もが自分のユニークな職業や個人的な経験を活かして、より成功するプロジェクトに貢献することができるのです。

これを効果的に行うには、チームビルディングの初期段階において、チームメンバー間の信頼関係を構築するために時間を割くことが重要です。お互いを理解しているチームメンバーは、互いを信頼し、異なる視点を安心して共有したり、競合する視点を提供したりすることができます。
:::

# プロジェクト内役割を定義する

### プロジェクトスポンサー

プロジェクトの責任者であり、プロジェクトが合意した価値をビジネスに提供することを保証する人である。プロジェクトの全過程において、重要なリーダーシップを発揮する。プロジェクトに資金を提供することもあります。スポンサーは、おそらくマネージャーや主要なステークホルダーと直接コミュニケーションをとることになるでしょう。


### チームメンバー

運営の中心的存在です。彼らは、日々の仕事をこなし、プロジェクトを実現する人たちです。

### 顧客・ユーザー

顧客は、成功裏に着地したプロジェクトから何らかの価値を得る人たちである。プロジェクトは顧客に有用なものを提供することを目的としているので、通常、顧客のニーズがプロジェクトの要件を定義する。顧客はプロジェクトの買い手と考えることができる。

あるプロジェクトでは、顧客とユーザーの両方が存在する状況があり、この2つを区別する必要があります。簡単に言うと、ユーザーとは、あなたのプロジェクトが生み出す製品を最終的に使用する人たちのことです。

例えば、あるソフトウェア会社が、インスタントメッセージのアプリケーションでチーム間のコミュニケーションを可能にするソフトウェアを開発しました。
- このソフトウェアを購入したのは企業ABCであり、彼らは顧客である。
- ユーザーは、インスタントメッセージアプリケーションを毎日使用する企業ABC内のすべての人たちです。

### ステークホルダー

プロジェクトに関わるすべての人、つまりプロジェクトの成功に既得権を持つ人たちです。

- 一次ステークホルダー: プロジェクトの完了によって直接利益を得ることを期待する人々
- 二次ステークホルダー: 仲介的な役割を果たし、プロジェクトによって間接的に影響を受ける人々

二次的なステークホルダーは、請負業者や協力会社のメンバーかもしれませんが、一次的なステークホルダーも二次的なステークホルダーも、プロジェクトマネージャーがプロジェクトのゴールと成果を定義するのに役立ちます。

### プロジェクトマネージャー

プロジェクト全体を計画、組織、監督する人物です。それがあなたです。
PrePoMaxによる円孔をもつ長方形板の応力計算（ShellモデルとSolidモデルによる）

# はじめに
PrePoMaxを使って円孔をもつ長方形板の応力計算を行いました。モデルはFreeCADで作成しています。

# FreeCADによるモデルの作成
図1に示す円孔をもつ長方形板の1/4モデルをFreeCADでスケッチします。

<img width="600" alt="Fig.1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/abad3037-d56a-e9c7-004d-ce3f34bd6918.jpeg">

図1　円孔をもつ長方形板とその1/4モデル（破線部）

作成したスケッチから、厚さ1mmにPadしたモデルと、スケッチのエッジをFaceに変換したモデルを作成して、それぞれSTEPファイルにエクスポートします。
FreeCADで作成したモデルはこちらにあります。Pad.stepとface.stepというファイルです。

https://github.com/repositoryfiles/RectangularPlateWithCircularHole

# PrePoMaxによるSolidモデルの応力計算
 
PrePoMaxにPadのモデルをインポートします。
メッシュを作成します。メッシュの最大サイズは2mmとします。
境界条件は、対称面に垂直な変位を0とし、板の端面にSurfaceTractionとして4000Nを加えます。材料は鋼（ヤング率210000MPa、ポアソン比0.3）です。このモデルは幅が1/2ですので、実際には8000Nの力を加えたことに相当します。
メッシュと境界条件を設定したようすを図2に示します。

<img width="600" alt="スライド3.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/7e9b5022-0be1-0cbe-3d89-8cb38804f671.jpeg">

図2　ソリッドモデルのメッシュと境界条件

応力の計算結果を図3に示します。板の長手方向の垂直応力は穴の縁で最大値884MPaで、穴から遠い位置（X=11.78mm、Y=84.21mm）では4000Nを断面積（幅20mm×厚さ1mm）で割った値200MPaとなっていることが分かります。

<img width="600" alt="スライド4.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/e600989b-c525-48cc-2217-c6dcbd0661b3.jpeg">

図3　ソリッドモデルの長手方向の垂直応力の計算結果


# PrePoMaxによるShellモデルの応力計算

PrePoMaxにFaceのモデルをインポートします。
メッシュと境界条件をSolidモデルと同様に設定します。ただし、対称面の境界条件については、対称面に垂直な変位を0とすることに加えて、対称面が回転しない条件が必要になります。[ハーフモデル（対称条件）の設定方法｜CAEトピックス](http://www.jikosoft.com/cae/topic04.html)などに説明が載っています。ここでは、表1のように設定します。

表1　Shellモデルの対称面における境界条件
|パラメータ|長さ方向断面  |幅方向断面  |
|---|---|---|
|U1  |0 mm  |Unconstrained  |
|U2  |Unconstrained  |0 mm  |
|U3  |Unconstrained  |Unconstrained  |
|UR1  |Unconstrained  |0 rad  |
|UR2  |0 rad  |Unconstrained  |
|UR3  |0 rad  |0 rad  |

メッシュと境界条件を設定したようすを図4に示します。

<img width="600" alt="スライド5.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/d6485f66-0e4d-e66e-7665-504e0833ade9.jpeg">

図4　シェルモデルのメッシュと境界条件

応力の計算結果を図5に示します。板の長手方向の垂直応力は穴の縁で最大値843MPaとなり、穴から遠い位置（X=10.58mm、Y=93.27mm）では200MPaとなっていることが分かります。Solidモデルと同様な結果が得られました。

<img width="600" alt="スライド6.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/ab44f6dd-14a9-9bac-a72a-ff0a1df9bba3.jpeg">

図5　シェルモデルの長手方向の垂直応力の計算結果

最後に、シェルモデルにおいて、表1のUR1～UR3をすべてUnconstrainedとして計算した結果を図6に示します。比較のため、表1の回転拘束した結果を図7に示します（図7は図5の見る方向を変えたものです）。対称面に回転拘束をしない場合、対称面で板が曲がってしまうことが図6から分かります。

<img width="600" alt="スライド8.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/4e72a81b-20e9-95cc-eaca-54ae9ced6906.jpeg">

図6　シェルモデルにおいて、対称面の回転拘束をしなかった場合の計算結果

<img width="600" alt="スライド7.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/72e108e9-ffc5-fc7f-26bf-17772d144f93.jpeg">

図7　シェルモデルにおいて、対称面を回転拘束した場合の計算結果（図5の見る方向を変えたもの）
テスト84

```vb
Public Function testC(ByVal arg As Range)
'シート上で「元に戻す」処理ができるようにするためには、シートのイベント
'で処理を作るのではなく、セルに「=testC(C1)」などのように入力するユーザー
'定義関数を使うとよい(あと条件付き書式も上手く使う)...“〆(ﾟωﾟ*)ｶｷｶｷ

Application.Volatile
Application.ScreenUpdating = False
Application.EnableEvents = False

With ThisWorkbook.Sheets("テスト1")

    If .Range(arg.Offset(0, -1).Address).Value = 1 Then

        testC = 1
        
    Else

        testC = 2
        
    End If

End With

Application.EnableEvents = True

Application.ScreenUpdating = True

End Function
LU分解

ライブラリが豊富でない言語でLU分解したかったため、コードを作成することになった。
個人的に見やすく、書きやすいPythonでコードを作成してから、同じコードを別の言語で作成することにした。
以下がその作成したPythonコード。

## ソースコード

```python
import numpy as np

def lu_decomposition(a):
  length = len(a)
  l = np.eye(length)
  u = np.zeros((length,length))

  for i in range(length):
    for j in range(i):
      l[i,j] = a[i,j]
      for k in range(j):
        l[i,j] = l[i,j] - l[i,k] * u[k,j]
      l[i,j] = l[i,j] / u[j,j]

    for j in range(i, length):
      u[i,j] = a[i,j]
      for k in range(i):
        u[i,j] = u[i,j] - l[i,k] * u[k,j]
  return l,u

a = np.random.rand(5,5)
l, u = lu_decomposition(a)
print(a)
print(l)
print(u)
print(l.dot(u))
print(l.dot(u) == a)
```

## 出力結果
```
[[0.81391896 0.1476644  0.14297368 0.29154456 0.20082125]
 [0.58814889 0.47336317 0.85443161 0.50634996 0.73427392]
 [0.3060707  0.74831109 0.80533407 0.42147219 0.98555506]
 [0.78881249 0.7541937  0.67006895 0.85316669 0.52989888]
 [0.05798169 0.22727099 0.64835561 0.50293417 0.91297261]]
[[ 1.          0.          0.          0.          0.        ]
 [ 0.72261358  1.          0.          0.          0.        ]
 [ 0.37604566  1.88944704  1.          0.          0.        ]
 [ 0.9691536   1.66662873  1.07893841  1.          0.        ]
 [ 0.07123767  0.59115362 -0.29079903  0.68459484  1.        ]]
[[ 0.81391896  0.1476644   0.14297368  0.29154456  0.20082125]
 [ 0.          0.36665888  0.75111688  0.2956759   0.58915775]
 [ 0.          0.         -0.66762614 -0.24682583 -0.20314528]
 [ 0.          0.          0.          0.34414316 -0.42745376]
 [ 0.          0.          0.          0.          0.78394202]]
[[0.81391896 0.1476644  0.14297368 0.29154456 0.20082125]
 [0.58814889 0.47336317 0.85443161 0.50634996 0.73427392]
 [0.3060707  0.74831109 0.80533407 0.42147219 0.98555506]
 [0.78881249 0.7541937  0.67006895 0.85316669 0.52989888]
 [0.05798169 0.22727099 0.64835561 0.50293417 0.91297261]]
[[ True  True  True  True  True]
 [ True  True  True  True  True]
 [ True False  True False False]
 [ True  True  True  True False]
 [ True False  True  True  True]]
```
誤差が多少出てしまうのはご愛嬌。

LU分解では使用するメモリを省略するために、L行列とU行列を一つの行列にまとめることがあるが、今回は動作確認がしたかったため、別の行列にしている。

# 参考
https://ja.m.wikipedia.org/wiki/LU%E5%88%86%E8%A7%A3#:~:text=%E6%95%B0%E5%AD%A6%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E8%A1%8C%E5%88%97%E3%81%AELU,%E3%82%92%E6%B1%82%E3%82%81%E3%82%8B%E3%81%93%E3%81%A8%E3%82%92%E3%81%84%E3%81%86%E3%80%82

# 次回
https://qiita.com/lVlEK0/items/9238b50396e3c1bf48af
GithubのリポジトリURLとトークンを混ぜるのが面倒なので、すぐできるサイトを作った

# 作ったサイト
* サイト：　
    https://honokiyuto.github.io/github-token-url-fusion-site/
    <img width="400" alt="サイトのスクショ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918864/0dc319ab-3451-5769-8eaf-7d8a864fde03.png">

* リポジトリ：　

https://github.com/dachscafe/github-token-url-fusion-site

# 動機
* 確かに、GitHubのリポジトリはトークンを使えばアクセスできる。
* Privateリポジトリだけど、サーバ上で ``git clone``等をしたいとき、よくこの手を使う（以下の記事が参考になる）。

https://blog.stu345.com/github-clone_using_token

* でも、以下の文を作成するのがめんどくさい。コピペだのなんだのして、スペルミスして・・・がよく起こる。ので作りました。

> https://{GIT_USER}:{GIT_TOKEN}@github.com/{GIT_REPOSITORY}
paiza.ioでelixir その168

# 概要
paiza.ioでelixirやってみた。
環境を調査してみた。

# サンプルコード

```
:erlang.processes 
|> length
|> IO.inspect

Application.loaded_applications()
|> IO.inspect

Application.get_all_env(:ex)
|> IO.inspect

Application.spec(:logger)
|> IO.inspect

```

# 実行結果

```
47
[
  {:logger, 'logger', '1.12.3'},
  {:compiler, 'ERTS  CXC 138 10', '7.5.2'},
  {:elixir, 'elixir', '1.12.3'},
  {:kernel, 'ERTS  CXC 138 10', '6.5.1'},
  {:stdlib, 'ERTS  CXC 138 10', '3.11.2'}
]
[]
[
  description: 'logger',
  id: [],
  vsn: '1.12.3',
  modules: [Logger, Logger.App, Logger.BackendSupervisor,
   Logger.Backends.Console, Logger.Config, Logger.Filter, Logger.Formatter,
   Logger.Handler, Logger.Translator, Logger.Utils, Logger.Watcher],
  maxP: :infinity,
  maxT: :infinity,
  registered: [Logger, Logger.BackendSupervisor, Logger.Supervisor,
   Logger.Watcher],
  included_applications: [],
  applications: [:kernel, :stdlib, :elixir],
  mod: {Logger.App, []},
  start_phases: :undefined
]
```

# 成果物

https://paiza.io/projects/TCBBvcFveo4oobVFD0l3IQ


以上。