OmniAICreator/Qiita-1.07M huggingface dataset:
[論文解説] Stochastic MuZero: PLANNING IN STOCHASTIC ENVIRONMENTS WITH A LEARNED MODEL

# はじめに

Stochastic MuZeroは、非決定的環境で有効な、確率的なMuZeroです。

モデルベース強化学習(世界系)で代表されるモデルとして、MuZeroが挙げられます。囲碁やチェス、atariなどでは、大きな成果を出しています。しかし、大規模で複雑な環境では、MuZeroの性能には限界があります。
そこで、Stochastic MuZeroが提案されました。

以下、論文のリンクです。

https://openreview.net/pdf?id=X6D9bAHhBQ1


## Afterstates

Afterstatesは、アクションが適用された後、環境が真の状態に移行する前の環境の仮説状態です。
Afterstatesを使用することで、環境にアクションを適用する効果と、アクションに与えられた確率的転移の効果を分離できます。

![Screen Shot 2022-04-11 at 13.32.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/191013eb-e703-4582-485b-f8f417534a1e.png)

## モデル

muzeroで用いられたモデルに対して、新たにAfterstates DynamicsとAfterstates Predictionが追加されました。asはAfterstatesです。cは将来予想される可能な確率的な結果です。

![Screen Shot 2022-04-11 at 13.43.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/c28f2bec-3f20-6163-680d-3c3a691139b0.png)

## 確率的な結果(Chance outcomes)

今回は、確率的な結果も分離を行い、モデル化を行なっています。

## 学習

損失関数は、muzeroと確率的な結果の損失関数を足し合わせたものになります。

![Screen Shot 2022-04-11 at 13.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/07e2c428-7825-bcb1-31ef-d448c4fb2d80.png)

![Screen Shot 2022-04-11 at 13.59.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/99cc33bf-1701-f81a-553e-355cab731767.png)

lはカテゴリカルクロスエントロピーです。


![Screen Shot 2022-04-11 at 13.57.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/fe28993d-8603-6878-eb6c-768a5dfd514d.png)


# MuZeroとStochastic MuZeroの比較

Stochastic MuZeroでは、状態(ゲームから得られた生データを観測、ネットワークから得られた表現空間上のものを状態としています)から次の状態に転移する際、Afterstatesが入っていることがわかります。muzeroでは、単純なカテゴリカル分布で表していました。今回は、その複雑性をニューラルネットワークを用いて、学習させます。

### MuZero

![Screen Shot 2022-04-11 at 14.08.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/b14f1868-6d0a-af86-9a54-0b0ba3b89375.png)

### Stochastic MuZero

![Screen Shot 2022-04-11 at 13.57.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/7ef6123e-ab7b-c280-c4e5-1f469ad76352.png)
【Apache】RewriteCondチートシート

## RewriteCondディレクティブの書式

```
RewriteCond %{変数名} 条件パターン [フラグ]
```

## 変数名
|グループ|変数名|値・意味|
| ---- | ---- | ----|
|HTTPヘッダ|HTTP_USER_AGENT|ユーザエージェント|
||HTTP_REFERER|参照元URL|
||HTTP_COOKIE|クッキー情報|
||HTTP_FORWARDED|プロキシ情報|
||HTTP_HOST|サーバのホスト名|
||HTTP_PROXY_CONNECTION|プロキシを経由しているか否か|
||HTTP_ACCEPT|ブラウザの言語タイプ|
|コネクション＆リクエスト|REMOTE_ADDR|リモートアドレス|
||REMOTE_HOST|リモートホスト名|
||REMOTE_USER|リモートユーザ名(基本認証利用時)|
||REMOTE_IDENT|リモートユーザのID|
||REQUEST_METHOD|リクエストメソッド|
||SCRIPT_FILENAME|スクリプトファイル名|
||PATH_INFO|パス情報|
||QUERY_STRING|クエリ文字列|
||AUTH_TYPE|認証タイプ|
|サーバ内部変数|DOCUMENT_ROOT|ドキュメントルートのパス|
||SERVER_ADMIN|サーバ管理者情報|
||SERVER_NAME|サーバ名|
||SERVER_ADDR|サーバのアドレス|
|SERVER_PORT|サーバのポート番号|
||SERVER_PROTOCOL|プロトコルのバージョン|
||SERVER_SOFTWARE|サーバソフトウェア|
|日時|TIME_YEAR|年|
||TIME_MON|月|
||TIME_DAY|日|
||TIME_HOUR|時|
||TIME_MIN|分|
||TIME_SEC|秒|
||TIME_WDAY|曜日(0:日~6:土)|
||TIME|年月日時分秒|
|特殊|API_VERSION|APIバージョン|
||THE_REQUEST|リクエスト文字列|
||REQUEST_URI|リクエストURI|
||REQUEST_FILENAME|リクエストされたファイル名|
||IS_SUBREQ|サブリクエストか否か|
||HTTPS|HTTPSでのアクセスか否か|

## 条件パターン
|パターン|意味|
| ---- | ---- |
|!|否定|
|<|テスト文字列より上の場合はtrue|
|>|テスト文字列より下の場合はtrue|
|=|テスト文字列と等しい場合はtrue|
|<=|テスト文字列以上の場合はtrue|
|>=|テスト文字列以下の場合はtrue|
|-d|ディレクトリが存在すればtrue|
|-f|ファイルが存在すればtrue|
|-eq|「=」(num値)|
|-ge|「<=」(num値)|
|-gt|「<」(num値)|
|-le|「>=」(num値)|
|-lt|「>」(num値)|
|-F|アクセス可能な有効なパスを指している場合はtrue|
|-l|シンボリックリンクの場合はtrue|
|-s|ファイルが存在かつサイズが0でなければtrue|
|-U|アクセス可能な有効なURLの場合はtrue|
|-x|実行権限がある場合はtrue|

## フラグ
|フラグ|意味|説明|
| ---- | ---- | ---- |
|C|Chain|このルールにマッチしたら、次のルールを評価|
|F|Forbidden|アクセス禁止（403-Forbidden）。[L]フラグと同様、以降のルールは無視される|
|G|Gone|削除（410-Gone）|
|L|Last|マッチしたらRewriteを止めます。以降のルールは無視|
|NC|No Case|大文字小文字を無視|
|NE|No Escape|".", "?", "%"などの特殊文字が"%25″のようにエンコードされるのを防ぐ|
|OR|Or|RewriteCondを複数指定する場合のor指定。指定なしならAND|
|PT|Path Through|Rewriteを終了し、それ以外の処理に移行|
|R|Ridirect|指定したURLにリダイレクト。[R=303]のようにリダイレクトコードも付加できる。[L]フラグと同様、以降のルールは無視される|
Auth0でJWTからmetadataを取得する(React HandsOn)

# はじめに
Auth０がめちゃめちゃ便利だったので、本格的にプロダクトに適用したいなと思っています。プロダクト適用時にJWTのペイロードを定義できるのか、また値設定が簡単にできるのか？という所が気になり、調査してみました。結論から言って、すごい簡単だったので、記事にしています。こんだけの機能が豊富で無料プランで利用できるのは純粋にすごいなと思っています。

# 今回やりたいこと
・JWTのペイロードに「アカウントタイプ」、「ユーザID」を含めること
・ユーザ毎にペイロードの値を付与できること

### JWTとは？ペイロードとは？
JWTとは？
JWTとは「Json Web Token」のことです。JWTの構造は、ヘッダー情報、ペイロード、署名の3つから成り立っています。
ヘッダー情報はその名の通り、JWTの署名検証を実施するために必要な情報。

```json:ヘッダー情報サンプル
{
  "typ": "JWT",
  "alg": "HS256"
}
```

ペイロードとは属性情報(Claim)です。下記例のように、アプリケーションで利用する値です。
```json:ペイロードサンプル
{
  "admin": true,
  "name": "John Doe",
}
```

署名は認証時利用するものです。

```json:署名サンプル
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
```

今回のチケットでは、ペイロードに「アカウントタイプ」、「ユーザID」が追加することが目的。

## ペイロードの定義と値の設定
Auth0にアクセスし、「User Management」の「Users」タブを開く。
Metadataに値を設定する。値はJSON形式で下記のように設定する。
```json:値を設定
{
  "user_id": "db37ab6f-b2cb-d3b1-e867-2638668755c0",
  "user_type": "system_admin"
}
```

※値の設定画像
![スクリーンショット 2022-04-11 14.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/4660dbb8-cc0f-c185-0110-86eb63763a85.png)

# アプリケーション実装（React）
事前に作成したReactのアプリケーションを一部修正する。
※https://qiita.com/kouji0705/items/b80f7cc7316324757ee4　に記載しております。

```javascript:src/App.tsx
import "./App.css";
import { useAuth0 } from "@auth0/auth0-react";

function App() {
  const { isAuthenticated, loginWithRedirect, logout, user } = useAuth0();
  return (
    <div className="App">
      <header className="App-header">
        {!isAuthenticated ? (
          <button onClick={loginWithRedirect}>Log in</button>
        ) : (
          <>
            <button
              onClick={() => {
                logout({ returnTo: window.location.origin });
              }}
            >
              Log out
            </button>
            <div>
             ユーザID:{user!["https://myapp.example.com/user_metadata"].user_id}
            </div>
            <div>
             ユーザタイプ：{user!["https://myapp.example.com/user_metadata"].user_type}
            </div>
          </>
        )}
      </header>
    </div>
  );
}

export default App;
```

## プロジェクト実行
プロジェクト実行後、アプリケーションを開く。
すると、ユーザIDとユーザタイプが表示されていることが分かる。

![スクリーンショット 2022-04-11 14.13.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/adf1bb81-ddae-e668-48ef-4f52a54009b8.png)


■参考

https://dev.classmethod.jp/articles/getting-user-metadata-and-app-metadata-of-auth0-user-in-react-app/
Oracle接続エラー

.NETプロジェクトで原因不明のOracle接続エラーが発生

<BLOCKQUOTE>要求された.NET Framework　データ　プロバイダーが見つかりません。これは、インストールされていない可能性があります。</BLOCKQUOTE>

machine.configの修正で解決

Oracle Provider を追加

<code>&lt;add name="ODP.NET, Unmanaged Driver" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET, Unmanaged Driver" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess"/&gt;</code>
[Python] Google検索結果総数を取得する方法



Chromeでとある検索結果の総数を取得する方法
方法を検索してもパッと出なかったのでこちらでまとめておきます。
例えば、以下はサイトURLでの検索総数を取得する方法です。

### 実行環境
Python 3.9
pip3 22.0.4

```python
from urllib.parse import urlparse
from numpy import result_type
import requests
from bs4 import BeautifulSoup
import time

def count_index():
    """ サイトURLのインデックス数を求める
    > site:<ドメイン名>で検索しクロールした結果の概算検索結果を出力件数
    """

    # リクエストURL
    target_url = 'https://example.com'
    target_domain = urlparse(target_url).netloc

    # Chrome情報
    search_url = f'https://www.google.com/search?q=site%3A{target_domain}'
    headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"}
    
    # リクエスト
    response = requests.get(search_url,headers=headers)
    response.encoding = response.apparent_encoding
    site_info = BeautifulSoup(response.text, 'html.parser')

    # 抽出
    total_results_text = site_info.find("div", {"id": "result-stats"}).find(text=True, recursive=False)
    results_num = ''.join([num for num in total_results_text if num.isdigit()])
    print(results_num) // 例) 632

count_index()

```

検索結果総数は「id="result-stats"」にあります。
注意点は、headerを含めないと上の要素を抽出できません。
また、headerは自身の環境で検索した情報をセットしないと検索結果総数が異なる場合があります。
その場合、```headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36"}```
の```"Mozilla/5.0 ~ Safari/537.36"```の中身を自身の環境に合わせると同じ数値が返ってくると思います。

環境は下記URLにアクセスすると確認できます。
(User-Agentは下記画像の```ブラウザのユーザーエージェント HTTP_USER_AGENT```で取得できます)
https://testpage.jp/tool/ip_user_agent.php

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596022/d7d1a4c4-9500-2c48-4d7f-d4d82f9d770d.png)
↑ココ

つまった方は参考にしてみてください。
CONFIG.xlsxって。。。

## 皆もすなるQiitaといふものを、儂もしてみむとてするなり。

と言う訳で、こん＊＊は！はなっち！です。

【CONFIG.xlsx】
いくらロボットは何でもできる！と言われていても、ファイルに関する位置情報は教えてあげねばならない訳でして。。。それをCONFIG.xlsxに記述し、辞書化して使うってのは、UiPathのREFreamworkに限らず、利活用している事と思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/66086d4c-7d89-8584-ad88-e81a1f928f0d.png)

このEXCELブックに定義した情報は、Dictionary(Of String, Object)型に格納して、ロボット側では、辞書変数名(キー)として、相対する値を取得し、利用するんですね。

それで、ファイルの存在フォルダ、ファイルの格納フォルダなどの情報を、ロボット内部で固定値として持つことなく、簡便な保守性を担保する訳です。
- - -

【開発資産をPUBLISH、そして書換】
PUBLISHする際に、本番実行環境でのCONFIG.xlsxを受領してからPUBLISHすると、Assistantからの実行には簡単で、実行担当者側での見直しもないので、それは好都合なのですが、開発した際の情報がなくなってしまうので、維持保守性では落ちるかな？と考えて、開発時点のCONFIG.xlsxを同梱したままPUBLISHしています。

ですので、実行担当者側で、本番実行環境に合わせたCONFIG.xlsxの内容の書き換えをしていただかなければなりません。

この作業を依頼するにあたって、説明会を開催しています。
・ロボットのインストール
・ロボットの実行方法
・CONFIG.xlsxの内容の説明

これらをメインに行っています。

この説明会をもって、受入試験をしていただくわけなのですが、業務の方がコンピュータに精通している訳ではないので、以下のような事象に遭遇したりします。

- CONFIG.xlsxが捜せない
　⇒確かに階層、深いですよね？…orz
- CONFIG.xlsxが存在するフォルダ中のxamlを消してしまう。
　⇒指導はしているのですが…orz
- フォルダ指定のキーに、フルパスを指定して動かない動かないと騒ぐ
　⇒こちらの説明が足りないのですね…orz
- - -

【不具合対策案】
これらの対策として、以下のような事を考えています。
- CONFIG.xlsxが捜せない
        ロボットに内包するCONFIG.xlsxは必須としますが、ロボットで参照する設定内容を、別のフォルダ位置にあるCONFIG.xlsxを示すようにします。これは実行担当者側との"お約束"が必要ですが、ロボットで必要な情報を、別のフォルダ位置の、実行担当者側が捜しやすい位置にする事で、容易に見直しなんなりをする事が出来ますね。

- CONFIG.xlsxが存在するフォルダ中のxamlを消してしまう。
        「別のフォルダ位置にあるCONFIG.xlsx」を併用する事で、ロボット内部を見せる必要がなくなり、ロボットを構成するxamlファイルの消失が防げますね。

- フォルダ指定のキーに、フルパスを指定して動かない動かないと騒ぐ
        これはもう、辞書化する時点で、チェックをし、エラーがあったら以降の処理をさせない。そのチェック内容設定は、以下のような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669015/9bc861ab-2c35-ce26-162b-544aaa21b11f.png)
"ぴよぴよ_格納位置"のフォルダのチェックをしていないのは、無いければフォルダつくってしまえ！（本当はフォルダ作って、エラーになってもOK!というパラメタ指定）と言う理由から。
"ぴよぴよ_格納ファイル"も同様ですね。

- - - 
【開発時点で有効なキー情報】
実行担当者がCONFIG.xlsxを見た時に、"DEBUGMODEってシステムメンテナンス用だから要らないね？"と、行削除してしまった場合、ロボット側では期待していたキーを参照できなくなってしまうので、異常終了してしまいます。
本来なら"DEBUGMODE"を参照している箇所を削除してからPUBLISHする対応になるでしょうが、それをすると、必要なロジックを間違えて削除してしまう可能性もあり、それはそれで麗しい話です。

CONFIG.xlsxにない、必要なキーは、辞書化したあとに存在チェックをし、存在しなかったら、新たに追加してしまえば楽ですね。


【教訓】
・CONFIG.xlsxに情報を設定してもらうのに、こちらの思惑通りに設定されるとは限らない。
・それを対策するのにも開発コストが掛かるので、設定間違えの無いように、設定内容が、どの業務のアクションに影響するかを事細かに説明してあげられるようにする。
・"DEBUGMODE"のように、業務に影響のない設定値だけど参照しているものは、存在チェックして、補完設定をしてあげる。

- - - 

##おわりに
いかがでした？

今回も読んでいただきありがとうございました！
是非UiPathでのロボ開発の一助になればと思っています。

ありがとうございました！
Prism コードサンプル学習：21-PassingParameters

# Prism コードサンプル学習：21-PassingParameters

## はじめに

以下の記事の続きです。
<https://qiita.com/mngreen/items/5493d8c16245e2fc36e4>

## 21-PassingParameters

本サンプルは、リストビューの要素を選択するとタブコントロールにタブアイテムが追加されるサンプルです。
もしその要素が追加済みであった場合は、その追加済みのタブアイテムがアクティブになります。
まず、サンプル実装の中で重要なポイントとしては、以下のPersonSelectedメソッドです。
リストの選択変更が発生するとNavigationParametersを作成、RegionManagerにパラメーターとして渡しています。
ここで、パラメーターはキーバリューとして任意の数だけ渡せます。

```cs
...

namespace ModuleA.ViewModels
{
    public class PersonListViewModel : BindableBase
    {
        ...

        private void PersonSelected(Person person)
        {
            var parameters = new NavigationParameters();
            parameters.Add("person", person);

            if (person != null)
                _regionManager.RequestNavigate("PersonDetailsRegion", "PersonDetail", parameters);
        }

        ...
    }
}

```

リクエストを受け取るPersonDetailViewModelクラスでは、IsNavigationTargetメソッドでナビゲーションするか判定し、OnNavigatedToメソッドで実際にナビゲーションを実行します。

```cs
...

namespace ModuleA.ViewModels
{
    public class PersonDetailViewModel : BindableBase, INavigationAware
    {
        ...

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            var person = navigationContext.Parameters["person"] as Person;
            if (person != null)
                SelectedPerson = person;
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            var person = navigationContext.Parameters["person"] as Person;
            if (person != null)
                return SelectedPerson != null && SelectedPerson.LastName == person.LastName;
            else
                return true;
        }

        ...
    }
}
```

今回のサンプルの変化点としては、ナビゲーションするときにパラメーターを渡している点です。
入口はこれまでに見たものと同じで[RegionNavigationService.ExecuteNavigationメソッド](https://github.com/PrismLibrary/Prism/blob/7f0b1680bbe754da790274f80851265f808d9bbf/src/Wpf/Prism.Wpf/Regions/RegionNavigationService.cs#L221)から通ります。
この中の[237行目](https://github.com/PrismLibrary/Prism/blob/7f0b1680bbe754da790274f80851265f808d9bbf/src/Wpf/Prism.Wpf/Regions/RegionNavigationService.cs#L237)でパラメーターを渡していることが分かります。
渡されたパラメーターを持つRegionNavigationJournalでは、それらの情報をスタックしているようです。
これまでのサンプルには出てきていませんが、おそらくビューを戻る、あるいは次に進めるといった機能のために登録されているものと考えられます。
上記登録後はOnNavigatedToメソッドを呼び出し、SelectedPersonが切り替えられることでビューが追加、あるいは切り替わります（これまでのサンプルと変わらない作り）。

## おわりに

今回は、NavigationContext.Parametersにわたっているパラメーターを利用しての、タブアイテムが増えていくサンプルを見ていきました。
前回と同じく、大きな流れ（クラス間の関連やメソッド呼び出し）はあまり大きく変わってはいませんでしたが、
一部未知のクラスが含まれており、理解の追いついていない部分が一部ありました。
以降のサンプルで使われていないか確認しようと思います。
次回、[22-ConfirmCancelNavigation](https://github.com/PrismLibrary/Prism-Samples-Wpf/tree/master/22-ConfirmCancelNavigation)について見ていこうと思います。
Macで録画と録音をする方法

## Macで録音する方法を考えていますか？

これを行うために実行できるいくつかの手順を次に示します。まず、コンピュータのデスクトップにあるカメラアイコンをクリックします。そこから、「ビデオの録画」オプションを選択します。録画タイマーを選択して、録画を開始する前に5秒または10秒待つかどうかを決定できます。内蔵マイクまたは外部マイクを使用することも、ビデオキャプチャに「なし」を選択することもできます。記録をフローティングサムネイルとして表示するか、最後の選択を記憶するかを選択することもできます。

## Xbox Game Bar
![nIa74WU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627938/120d7390-76bc-363a-df7b-f3140481cef5.png)
Macでゲームプレイを記録したい場合は、[Xboxゲームバー](https://www.microsoft.com/ja-jp/p/xbox-game-bar/9nzkpstsnw4p?source=lp&activetab=pivot:overviewtab)のキャプチャ機能を使用できます。 Macでゲームプレイを記録するには、アプリケーションを強調表示し、Win+Gを押してゲームバーを開く必要があります。これにより、スクリーンショットと30秒のゲームプレイが記録されます。 [ゲームクリップの終了]オプションから、ビデオの長さを調整できます。アプリケーションを強調表示したら、キャプチャオーバーレイをクリックできます。次に、目的のビデオサイズ、サウンド、およびナレーションを選択できます。

Macでゲームプレイを記録したい場合は、XboxゲームバーがWindows10とWindows11に組み込まれています。このアプリを使用すると、ゲーム、アプリケーション、および画面からコンテンツをキャプチャできます。 Win + Gを押すか、接続されているコントローラーのXboxボタンをタップして開きます。 Win + Alt+Rを押して起動することもできます。次に、[記録]ボタンをクリックします。許可を与えると、録音パネルが開きます。

## FonePaw PC画面録画
![1649649902.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627938/2f4e7536-1bc4-9034-ff55-b555023eeed3.jpeg)
[FonePaw PC画面録画](https://www.fonepaw.com/ja/screen-recorder/) for MACには、さまざまな便利な機能があります。画面キャプチャツール、注釈、およびいくつかの出力設定を備えています。最も推奨される出力オプションにはMP4ビデオがあり、GIF作成もサポートしています。このソフトウェアには、録音を微調整するための基本的な編集ツールも備わっています。以前の記録を見つけて再利用し、将来使用することができます。また、記録中に誤ってソフトウェアを閉じた場合に、保存されていないデータを復元することもできます。

[FonePaw PC画面録画 for MACには、購入前](https://www.fonepaw.com/ja/store/buy-mac-screen-recorder.html)にアプリをテストできる試用版が付属しています。ライブラリフォルダーをクリーンアップしてアプリをアンインストールすることもできます。 Libraryフォルダーには、キャッシュ、設定、およびアプリケーションサポートファイルが含まれています。一部の発行元は独自のアンインストーラーを提供しているため、それらのアプリケーションのWebサイトを確認して、適切なアンインストーラーをダウンロードできます。アンインストールが完了すると、[アプリケーションを自由にダウンロードできます。](https://www.fonepaw.com/ja/screen-recorder/)

## FonePaw PC画面録画を選択する理由
![1649650048(1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627938/d79dd4e5-6396-1890-dc99-45be8ff1add7.jpeg)
Mac用のスクリーンレコーダーを探しているなら、それをインストールする方法を疑問に思うかもしれません。 FonePaw PC画面録画は、画面のアクティビティとWebカメラのビデオを記録するのに役立つアプリケーションです。プログラムのインターフェースは直感的で使いやすいです。その3つのタブ（ビデオレコーダー、オーディオレコーダー、およびスクリーンキャプチャ）により、必要なものを正確に簡単に選択できます。

[FonePaw PC画面録画](https://www.fonepaw.com/ja/screen-recorder/)は、WindowsとmacOSの両方で使用できます。無料試用版をダウンロードして、3分間の録音を保存できます。お金を節約するために、5人のユーザーを対象とする生涯ライセンスまたは家族ライセンスのいずれかのライセンスを購入することもできます。どちらを使用するかを決定したら、最適な設定を選択できます。
[gem fast_jsonapi] の忘備録

## fast_jsonapiとは
Netflixが提供しているgem。JSONのserializer。

#### JSONとは
JSONとは「JavaScriptのオブジェクト記法を用いたデータ交換フォーマット」のこと。

JavaScriptでオブジェクトを作成する際は ``{}``や``[]``などの括弧を使って記述するが、JSONはその記法を元にしている。

```
[
  {"id" : "1", "name" : "tanaka"},
  {"id" : "2", "name" : "nakata"}
]
```
#### serializerとは
``シリアライズ（serialize）``とは、プログラミングでオプジェクト化されたデータを、ファイルやストレージに保存したり、ネットワークで送受信したりできるような形に変換することを言う。

逆に、シリアライズされたデータをプログラミングで扱えるようにオブジェクトの型に復元することを``デシリアライズ（deserialize）``という。

## gem fast_jsonapi
```Gemfile
gem 'fast_jsonapi'
```
``bundle install``した後、ターミナルにて以下のコマンドを入力。

```
rails g serializer Article（モデル名） title contents status（カラム名を列挙）
```
上記コマンドにより、``app/serializers/article_serializer.rb``が生成されるので、モデルに記載している情報と合わせる。

```app/serializers/article_serializer.rb
class ArticleSerializer
  include FastJsonapi::ObjectSerializer

  attributes :title, :contents, :status  # 追記
  belongs_to :user # モデルの設定に合わす
end
```
次にコントローラーを編集する。

```controllers/api/articles_controller.rb
class ArticlesController < BaseController
      def index
        articles = Article.all
        json_string = ArticleSerializer.new(articles).serialized_json
         #↑一覧の取得でもnewを使用する
        render json: json_string
      end
end
```
``postman``で確認してみると、JSON方式でのデータを確認できた。
## fast_jsonapiのテスト
```spec/requests/api/v1/articles_spec.rb
RSpec.describe 'Api::V1::Articles', type: :request do
  describe 'GET /articles' do
    let(:article_num) { 10 }

    before do
      user = create(:user)
      create_list(:article, article_num, user: user)
    end

    it 'returns fincle articles in json format' do
      get api_v1_articles_path, headers: { CONTENT_TYPE: 'application/json', ACCEPT: 'application/json', }

      expect(JSON.parse(body)['data'].count).to eq(article_num)
      expect(response).to be_successful
      expect(response).to have_http_status(:ok)
    end
  end
end
```
**``・create_list``**
複数のインスタンスをまとめて作れるメソッド。
▶︎[RSpecでFactoryBotから複数のインスタンスをまとめて作成する【create_listを使用】](https://qiita.com/kodai_0122/items/e755a128f1dade3f53c6)

**``Accept / Content-Type``**
・Accept
ブラウザが受信可能なデータ形式（MIMEタイプ）をサーバに伝える。

・Content-Type
コンテンツの種別を MIMEタイプで示す
▶︎[HTTP入門](https://www.tohoho-web.com/ex/http.htm#headers)

**``・JSON.parse()``**
JSONオブジェクトをRubyのわかるものに変えるもの。
現状JSON方式にしているので、データの中身は以下のようになっている。
```javascript
#例
{"id":841425152,"email":"example@example.com"}
```
Rubyでのキーと値のペア式はJavaScriptのそれとは違うので、以下のようにしたい。
```ruby
#例
{"id"=>841425155, "email"=>"example@example.com"}
```
そのような時に``JSON.parse()``を利用する。
▶︎[RspecでJSONオブジェクトの値を確認する](https://programming-shop.hatenablog.com/entry/2018/12/31/085804)

## 参考記事
[JSONとは？データフォーマット（データ形式）について学ぼう！](https://products.sint.co.jp/topsic/blog/json)
[Netflix/fast_jsonapi](https://github.com/Netflix/fast_jsonapi)
ITエンジニア(くそデカ主語)なら絶対に理解しておくべき作業フロー

# ITエンジニア(くそデカ主語)なら絶対に理解しておくべき作業フロー

つい先日信じがたいことをプロから聞いたので、
技術情報として役に立たなくなったQiitaに
久々にログインして書きなぐろうと思います


## 発端
```
??? < 手順書.txt(中身はコマンドの羅列だけ)を
渡されてドン引きしてる
```
```
??? < 事前と事後の確認くらいはしような
(ガチ設定用のコマンドしか書かれてなくて世紀末)
```
というお話を聞いたのでこれから無能を増やさないように
オワコンプラットフォームに便所の落書きとして残します

というかこういうのはSIerに入ったら教えてもらうことなんじゃないのか…？
自分の場合は派遣会社だから一度も教わったことないけど


## 結論

先に結論書いときます
手順書やスクリプトはこれを想定して作れ

作れないんなら自分の責任で作業時に常駐して直せるようにしろ
クリティカル作業の場合はそういうことを
***絶対にやるな*** カス

1. 事前作業(変更前の想定した状態や設定かを確認)
1. 変更作業(やりたかったこと、顧客が本当に求めていたもの)
1. 事後作業(変更後の想定した状態や設定になったかを確認)
1. 切り戻し作業(ロールバックしたり元の状態に戻すコマンドなりを使う)


### なんで事前作業が必要なの？

少しは考えろ
疲れた頭や酒をキメたりした状態で前回の作業でやっていたり、
他人が設定変更をしていたりしたら想定通りの状態になるわけないだろ


### なんで変更作業が必要なの？

これは言う必要はないはずだが、わからないなら何しに来たんだ


### なんで事後作業が必要なの？

自称神でさえ欠陥品の人間しか作れないくそ雑魚なんだから
人間が完璧に間違えないことなんてないだろ
46億回  ***考えて***  確認してろ

すべてが想定通りなんて甘いんだよ


### なんで切り戻し作業が必要なの？

事後作業と同じ理由
あとは予期しないバグを引いたりしたら
元に戻せないと死ぬ


## ほかに気を付けるべきことは？

本番と

***全く同じ***

検証環境を作れ
作れないなら客を殴り倒して作らせろ
それでも首を縦に振らないなら瑕疵を担保すんな

妥協ラインを明確にして契約書にかけ


### そうはいっても予算がないから無理といわれるが

本当は求めていない作業なんじゃないかとしか思えないが、
クリティカルなものじゃないから妥協して下記のような
検証環境を提案して費用だしてもらえばいいんじゃねーの
知らんけど

ただ、クリティカルなはずなのにケチるような客は二度と関わるな
即撤退しろ
諸悪の根源だ

1. IPアドレスが重複しないように隔離して、同じホスト名やIPアドレスを使って作る
1. 下位互換や中古機器でほぼ同じ設定や機能があるものを買って対応する
1. 仮想マシンで作れるものはつくる(ベンダーロックインの必要がなければネットワーク機器も仮想でできなくはない)


## なんもわからんので例をくれ

あなたが働いてる会社大丈夫ですか？


### Cisco
IOS-XRとかまともなやつはロールバック機能があるのでこんな切り戻ししなくていい
というか標準でつけろ

* 事前作業
```
ter le 0
sh clock
sh run
sh startup-config
sh int status
sh int bri
```

* 変更作業
```
conf t
int Gi 1/0/1
no shut
end
wr mem
```

* 事後作業
```
sh clock
sh run
sh startup-config
sh int status
sh int bri
```

* 切り戻し作業
```
conf t
int Gi 1/0/1
shut
end
wr mem
```


### Linux

VMならVMのスナップショット使えばいいし、
NILFS2やHammer2などを使ってればファイルシステムのスナップショットを使えばいい
あとは/etcの設定を変えるだけならetckeeperいれるといい
これらがあると切り戻しが楽になる

大した選定基準もないのに実機を使ったり、
xfsやext4が人気だからって理由でスナップショット機能がない
ファイルシステムを使うのはやめろ

* 事前作業
```
uname -an
date
ls -l /var/log
cat /etc/rsyslog.conf
sudo systemctl status -l rsyslog
sudo journalctl -xe -u rsyslog
```

* 変更作業
```
sudo systemctl enable rsyslog
sudo systemctl restart rsyslog
```

* 事後作業
```
uname -an
date
ls -l /var/log
cat /etc/rsyslog.conf
sudo systemctl status -l rsyslog
sudo journalctl -xe -u rsyslog
```

* 切り戻し作業
```
sudo systemctl stop rsyslog
sudo systemctl disable rsyslog
```

## 切り戻しがあった場合はどういう手順になるの？

想定できないならエンジニア向いてないと思う

1. 事前
1. 変更
1. トラブル発生
1. 切り戻し
1. 事後(事前と **同じ** 設定や状態になる)

になるだろ
この切り戻し手順と下記の通常手順は検証で絶対に確認しろ

1. 事前
1. 変更
1. 事後


## ちょっとだけ眺めたサイト
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/s1-basic_configuration_of_rsyslog
http://itdoc.hitachi.co.jp/manuals/3021/3021373110/0015.HTM
https://techracho.bpsinc.jp/yamasita-taisuke/2014_08_14/18762
http://www.tensi.info/home/kensyo-infra
https://it-trend.jp/development_tools/article/32-0033


## 最後に・ファッキンお気持ち

勢いで書いてしまったのですごく内容が汚くてつらい
でも反省はしていない

こういう基本的なことを書いている資料や書籍をまだ見たことがないので
理解に苦しんでいるが、俺がアホなだけで見つけていないだけな気がするので
もしまともな書籍にこういうことがかかれていたら教えてほしい

あと、修正とかはやる気や気が向いた時や余裕があるときに運が良ければやる
Let's Encryptを手動更新した話

OSをCentOS8.5→Almalinux8.5に変更したらLet'sEncrpytの自動更新がうまくいかなくなったっぽい。

仕方ないので手動更新する。以下のサイトを参考にした。
https://dev.classmethod.jp/articles/how-to-use-certbot-with-nginx/

https://inaba-serverdesign.jp/blog/20210331/snap-lets-encrypt-ssl-certificate-update.html

# まず確認

「更新しろ！」というLet'sEncryptからのメールで自体に気づく。
更新をどうやっていたのか前任者から何も聞いていなかったので、まず構成の確認。

とりあえずcertbotというのが必要らしい。さすがに入っているはずなので、あるかないかの確認もこめて以下のコマンドを入力。

```
certbot --version
```
2022/4/11現在はcertbot 1.22.0らしい。
コマンドを打つと1.22.0だったので、とりあえずcertbotはあるし、最新バージョンだった。


# ドメイン名の確認
```
ls /etc/letsencrypt/live
```
コマンドを打つと、REDME 「ドメイン名」が出てきたので、ちゃんとLet'sEncryptのディレクトリなどがあった。

このドメイン名を使って
```
ls -l /etc/letsencrypt/live/ドメイン名
```
とすると、証明書や秘密鍵の最終更新日時が出る。


# 手動更新
```
/usr/bin/certbot renew --post-hook "systemctl restart httpd"
```
-post-hookは証明書期限が30日未満の場合にのみ更新してくれる、とのことで、たぶんいらないけど消してもアレなので入れた。

"systemctl restart httpd"をつけると、更新が終わるとhttpdを再起動してくれるらしい。
他のサイトではnginxを再起動していたが、よくわからないのでhttpd再起動させれば間違いないやろの精神でhttpdを選択した。

コマンド入力後はしばらく待って、つらつら～と並んだ最後に
(success)とあったので多分OK


証明書の更新日時を確認して、今日の日付になっていたので、たぶんOK


# 自動更新なんで止まった？
結局わからない。
たぶんcron？がOSの変更でなんか変になったんだろう。
ひとまず様子見して、手があけば自動更新も復旧させる。
統計的推定と検定をPythonで解く「区間推定（一般母集団で大標本の場合）」(2022.4.11)

# <h1>概要</h1>
先日は、Pythonで「区間推定（正規母集団で母分散未知の場合）」を行いました。コード的には、「区間推定（正規母集団で母分散既知の場合）」と同じくstats.norm.interval 関数を用い母平均の信頼区間を求めるだけです。その引数として「信頼度：alpha」「標本平均：loc」「標準誤差：scale」「自由度：df」を必要としました。95%信頼区間を求める際、基本は標準化得点$Z$について、<br>$P(−1.96≤Z≤1.96)=0.95$<br>が成り立つたちます。今回は母比率の信頼区間を求めるために上手い具合に式を変形して算出します。

## <b>前回の記事</b>
[統計的推定と検定をPythonで解く「区間推定（正規母集団で母分散未知の場合）」](https://qiita.com/tan0ry0shiny/items/71cc816cd9f1793df07d)

今回は、「区間推定（一般母集団で大標本の場合）」について解いていこうと思います。今回も「[とけたろうさんのチートシート](https://toketarou.com/cheatsheet/#toc16)」を使わせて頂きます。今回の問題はアンケート調査になっています。

# <h1>問題</h1>
【問題】20歳〜29歳までの男性会社員300人にアンケートをとったところ，毎朝入浴する人は45人いた。この調査結果は，母集団を20歳〜29歳までの男性会社員全体とし，標本サイズ300の単純無作為抽出に基づくとみなす。20歳〜29歳までの男性会社員全体における毎朝入浴する人の割合（母比率）pの信頼度90％の信頼区間を求めなさい。

# <h1>解答</h1>
今回の記事から、Pythonでの解法を示してから理論的な解法を見ていきます。答えを出すだけならPythonで十分だと思いますが、求めた答えを使う側としては、ちゃんと分かっていて答えを出して欲しいですね。つまり、自分で出した答えが合ってそうかどうか何となくでも分かって報告なり調査なり出来るようにしたいって事です。<br>
話が反れましたね。
## <h2>どういう問題か（問題の分類）</h2>
今回は、母比率の区間推定です。確率分布としては正規母集団を想定していると思いますが、二項分布のサンプル数が大きいので正規分部を近似できるという事だと思います。
## <h2>どのように解けるか（Python）</h2>

```Python
import numpy as np
from scipy import stats
X=45
n=300
p=X/n
#区間推定
low, high = stats.binom.interval(alpha=0.90, n=n, p=p)
print(f"母比率pの信頼区間は{low/n:.3f}≦p≦{high/n:.3f}")
```

母比率$p$の信頼度90％の信頼区間は
$$0.117≦p≦0.183$$
になります。これは「とけたろうさん」の答えとは若干ずれますが、まずは理解優先という事で先に進めます。

次に、このコードの解説をしていきます。今回は二項分布の正規分布近似のため、stats.binom.interval 関数を使いました。これを使うためには、「信頼度：alpha」「標本の大きさ：n」「標本比率：p」が必要になります。
標本比率$p$は、$$\frac{毎朝入浴する人:45}{標本の大きさ:300}=0.15$$
となります。
## <h2>どのように解けるか（解法）</h2>
信頼区間90％を求めるので、
$$P(−1.64≤Z≤1.64)=0.90$$
となります。この時、Z（標準化得点？）は
$$Z=\frac{\frac{X}{n}-p}{\sqrt{\frac{p(1-p)}{n}}}$$
です。以上より、$X$と$n$を用いて、母比率の90%信頼区間は次のように求めることが出来ます。
以上より、信頼区間90％の母比率は
$$
0.116≦p≦0.184
$$
となります。先程の答えと比べると小数点第3位で微妙に違いますが、今回は言及しません。

# <h1>感想</h1>

1. この記事を作ってみて
今回は、統計的推定の簡単な問題その3です。前回までは「母平均の推定」でしたが、今回は「母比率の推定」でした。違いは「標準化得点Z」の求め方くらいだったと思います。母平均と母比率の推定を通して、信頼区間の推定は基本的には
$$
P(-z_{\alpha/2} \leq Z \le z_{\alpha/2})=1-\alpha
$$
で求められると考えています。この時$Z$はその時、想定する確率分布で変わると思っています。
私の表現の仕方に癖があり、受け入れられない方も多くいらっしゃると思いますが、そこは生暖かい目で見守って頂ければと思います。また、間違いの指摘やご意見などありましたら遠慮なく仰って下さい。

# <h1>参考</h1>

1. [とけたろう(2020.4)、二項分布と母比率の区間推定【中学の数学からはじめる統計検定２級講座第10回】](https://toketarou.com/binomial/#toc6)
1. [かめ@米国データサイエンティスト(2020.4)、比率の区間推定を超わかりやすく解説【統計学入門24】](https://datawokagaku.com/ratio_ci/)

<h1>次の記事</h1>

[統計的推定と検定をPythonで解く「母分散の推定（母平均未知）の場合」(2020.4.19)](https://qiita.com/tan0ry0shiny/items/4dbec818f9243d8afd99)
jqueryでタグの絞り込みを実装する

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

# 説明
参考サイトのコードとほぼ同じです。
参考サイト：[jQueryでリスト表示を絞り込む処理を実装する](https://www.tam-tam.co.jp/tipsnote/javascript/post14636.html)

ただやりたかったことと微妙に違い、下記の部分をカスタマイズしました。
#### OR検索ではなくAND検索にする
参考サイトでは複数のタグを選択した時、それらを含む全てのコンテンツが表示されます。今回はそうではなく、選択したタグのみを含むコンテンツを表示させるようにしました。
これはリスト内のタグを配列ではなく個別のdata-tagとして記述することで実現しました。
（data-categoryとdata-tagに名前が分かれてますが今回意味はないです）
```index.html
<li class="list_item" data-category1='りんご' data-tag3='リール' data-tag4='ルイーダ' data-tag13='スコーン'>
```

#### 何も表示するものがない時メッセージを表示する
以下部分を追記しました。コンテンツの数を取得してメッセージを表示させています。
```page.js
//表示されるものがない時の処理
if($('.disnone').length){
 if($('.list_item').length != $('.is-hide').length){ 
	$('.disnone').remove();
 }
 return false;
}else if($('.list_item').length == $('.is-hide').length){
  $('.list').append('<li class="disnone">\u8868\u793a\u3059\u308b\u9805\u76ee\u304c\u3042\u308a\u307e\u305b\u3093</li>');
}
```

#### ALLボタンを押した時にリセットして全て表示させる
以下部分を追記しました。
・ALL以外にチェックが入っていなかったらALLにチェックをつける。そうでなければALLのチェックを外す
・ALLが押されたとき、他のチェックボックスのチェックを外す。コンテンツの非表示を解除する
```page.js
var allBtn = 'input[name="all"]';

~~~省略~~~

//ALLが押された時の処理
 if(!$(searchBox + ' input').is(':checked')){
  $(allBtn).prop('checked',true);
 }
 else{
  $(allBtn).prop('checked',false);
 }

 $(allBtn).on('click', function(){
  $(searchBox + ' input').prop('checked',false);
  $('.disnone').remove();
  $(listItem).removeClass(hideClass);
 });
```

# 参考サイト
https://www.tam-tam.co.jp/tipsnote/javascript/post14636.html
GitとGithubの違いすら分からなかったときに読んだ記事たち

初めてGitを触り、ドキュメントを読んでもGitとGithubで操作の違いがわからず、色んな概念でこんがらがったので、投稿したいと思います。
私が記事を出すまでもなく、非常に丁寧にまとまっているサイトやウェブページが多いのでこれらを紹介したいと思います。
参考になったページはこれらです。
## mainブランチについて ##
Githubではデフォルトのブランチが変更されていたために混乱していました。
特に、初心者の方は記事に沿って動かしていくので、本当はデフォルトがmainブランチであるのに、少し前の記事ではmasterブランチを作るようにガイドされていました。
main?　master?なんだそれとなってしまいかねないために参考までにどうぞ。

[Githubのデフォルトブランチがmainであることに気付かず、ローカルのブランチをmasterのままpushし、エラーが出たときの対処法](https://qiita.com/wa-ma/items/094b75a482e4a1bf0a01)
## Gitのフロー ##
ドキュメントを読んでいても、merge、addとかブランチとかfolkとかなんやねんこれってなってしまうので初心者向けの記事で把握するのが混乱しなくて済むと思います。
これらを読めば、ローカルリポジトリとリモートリポジトリの違いすらよくわからなかったなんてもう遠い過去の話になるでしょう。

・[【初心者向け】Gitで個人開発](https://qiita.com/Ken227/items/822851aaca0fd9b3cf72#git%E3%81%A7%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BA)

・[君には1時間でGitについて知ってもらう(with VSCode)](https://qiita.com/jesus_isao/items/63557eba36819faa4ad9#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E7%AE%A1%E7%90%86%E6%96%B9%E6%B3%95%E3%81%AE%E9%81%95%E3%81%84)

↓ 漫画で理解したい人むけ
・[第1話 リポジトリを作ってコミットしてみよう【連載】マンガでわかるGit ～コマンド編～](https://www.r-staffing.co.jp/engineer/entry/20190621_1?mls=i01_0001_20190719)

## あとがき ##
あとは必要に応じて、検索していってください。
私も全然わかっていないので一緒に頑張っていきましょうね。
PHPのクラスメンバへのアクセス修飾子【個人的なお勉強アウトプット】

# 引用記事
https://php-junkie.net/design/visibility/

PHPも他のプログラムと同じく、アクセス修飾子を使える。
public、protected、private。
上記いずれかをプロパティやメソッド、定数に指定することでアクセス権を定義することができる。

## アクセス権の種類
### public
クラスのメンバ（プロパティ、メソッド、定数）はどこからでもアクセスが可能。
親子関係だろうが、外部クラスからだろうが。

### protected
protectedで宣言されたクラスのメンバ、そのクラス自身と、親子関係にあるクラスのみアクセスが可能。外部クラスからはアクセスできない。

### private
praivate宣言されたクラスのメンバは、そのクラス自身のみがアクセス可能

## アクセス権の決め方
アクセス権の範囲が広ければ広いほど便利に見えるが、影響力の大きさから改変がしにくくなる不便さがあり、余計なアクセス権は想定外の場所の不具合を生む原因にもなりかねない。そのため、できるだけ狭い範囲で作れると良い。

基本はprivateで、privateをベースとして必要な文だけ広げていく。
継承先、あるいは継承もとで呼び出したり上書きしたい場合はprotected。
そのクラスとは関係ない外部からアクセスしたい場合はpublic。

privateの注意点として、本来そのクラスの責務でないものをかけてしまうことがある。
privateメソッドのテストをしたい、他のクラスにも似たようなメソッドがあると感じたら、別のクラスのpublicメソッドとしたほうがよいかもしれない。
Macで重複した写真を削除する方法

Macで重複した写真を削除する方法を自問しているかもしれませんか？

答えは簡単です。Macubeを使用してください。 Macで重複した写真を削除する場合は、[Macube](https://www.macube.com/ja/)の公式Webサイトからアプリケーションをダウンロードするか、Macubeの無料ダウンロードボタンをクリックする必要があります。 Macubeをインストールし、セットアップ手順に従います。

![macube-cleaner-review-9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627938/8908829d-4058-f098-d3bb-311aca154db6.jpeg)
インストールしたら、Macubeを開き、左側のパネルに移動します。 Duplicate Finderをクリックすると、MacubeがMacをスキャンして、複製された写真とファイルを表示します。
![1649646878(1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2627938/93ba5933-0b21-70e8-4a88-ed9ea3418b9e.jpeg)

[Macube Cleaner](https://www.macube.com/ja/pricing/)を購入する前に、試してみてください。プログラムはMacをスキャンして重複ファイルや類似の画像を探し、それらを削除してストレージスペースを解放します。 Macubeの試用版を無料でダウンロードできます。これにより、500MBのデータに制限されます。これは十分な情報に基づいた決定を下すのに十分なはずであり、試用版はインストールとアンインストールが簡単です。 Macube Cleanerには、専門家チーム、マーケティング部門、および顧客に優れたサービスを提供するよう努める顧客サービス部門もあります。

複製した写真を見つけたら、それを削除する準備ができています。手動で削除するか、最高のMac複製写真ファインダーを使用するかを選択できます。または、Finderウィンドウの右上隅にある「+」アイコンを使用して、重複するすべての画像を削除することもできます。 Macubeを使用したくない場合は、Macで重複する写真を手動で選択し、[削除]ボタンをクリックして削除できます。

Macの重複写真警告は、新しいファイルを作成して重要な写真を誤って削除するのを防ぐことができます。多くの場合、写真の重複はファイル名の類似性が原因で発生します。つまり、2つは同一です。 Mac用の最高のMac複製写真ファインダーは、不要な複製を削除するように設計されています。これは、アプリに堅牢なスキャンエンジンと防止アルゴリズムがあり、重要な画像が誤って削除されないように保護することを意味します。アプリはまた、アプリが重要な写真を削除しないことを保証します。

Macに写真をインポートしている場合は、特定の写真が2回コピーされていることにすでに気付いているでしょう。これは、ファイルの名前を変更したか、誤ってファイル名を変更したなど、いくつかの理由によるものです。このような場合、重複する写真ファイルは同じ名前で異なる形式で保存されます。この場合、複製された写真の名前と拡張子は異なります。

[無料の体験版](https://www.macube.com/ja/)があることはうれしいですよね。
WSL2でUbuntuのGUIを起動（メモ）

# WSL2のインストール

- 前提：Windows10 version 2004以降であること
- コマンドプロンプトを管理者権限で開く
- 次のコマンドを入力（デフォルトでUbuntuがインストールされる）
```
wsl --install
```

- 初回起動時にユーザー名とパスワードを設定する

# Ubuntuデスクトップ環境の構築
### Ubuntuのアップデート

- ターミナルで以下のコマンドを入力

```
$ sudo apt-get update
$ sudo apt-get upgrade 
```

### Ubuntuデスクトップ環境のインストール

```
$ sudo apt-get install libgl1-mesa-dev xorg-dev xbitmaps x11-apps
$ sudo apt-get install ubuntu-desktop
```

# Xサーバ環境の構築
### VcXsrvのインストール

- [公式サイト](https://sourceforge.net/projects/vcxsrv/)からインストーラをダウンロード
- 設定はデフォルトのままでOK

### VcXsrvの起動

- XLaunchというアイコンから起動
- 「One large window」を選択
- 「Disable access control」にチェック
- 「Windows セキュリティの重要な警告」が表示されたら、「パブリックネットワーク」にチェックを入れて、「アクセスを許可する」を押す

# Ubuntuデスクトップの起動

```
$ export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0.0
$ sudo service x11-common start
$ sudo service dbus start
$ gnome-shell --x11 -r
```

- これでデスクトップ画面が起動する

### 楽にUbuntuデスクトップを起動する方法（シェルスクリプト作成）

- 前提：VcXsrvを起動しておく

#### 準備編
- Ubuntuで以下のコマンドを入力してviエディタ起動

```
$ vi start.sh
```

- iを押してインサートモードにする
- 以下のコマンドをコピーしてviエディタに貼り付け
```
$ export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0.0
$ sudo service x11-common start
$ sudo service dbus start
$ gnome-shell --x11 -r
```
- escを押す→:wq→Enter
- 元のターミナルに戻ったら以下のコマンドを入力

```
$ sudo bash start.sh
```
- Ubuntuデスクトップが起動する

# 参考
[Windows 10でLinuxを使う(WSL2)](https://qiita.com/whim0321/items/ed76b490daaec152dc69)
[WSLをつかって、Ubuntuのデスクトップ（GUI）をうごかしてみよう](https://ao-tela.com/wsl_gui/)
【未経験・エンジニア転職】面接で使える、優良企業を見分ける３つの質問

# 読んでほしい方
* 未経験からエンジニアを目指そうと思っている方
* 面接、面談を控えている方
* 良い会社でエンジニアのキャリアをスタートさせたい方

# 自己紹介
* 新卒で営業職（IT業界・ソフトウェアテスト）
* エンジニア歴６年
* フロントエンドからサーバーサイド、インフラ、機械学習系の案件を経験
* 採用担当

転職活動ってエネルギー使いますよね。
頑張って内定をもらっても、「イメージと違った！」なんてことになったら残念過ぎます。

そんな結果にならないよう、**面接でそのまま使える質問**を３つ紹介しようと思います。


# 質問１　平均年齢はどれくらいですか？
20代前半など、かなり低い会社は注意してください。
IT業界自体、他業界と比べると低い傾向はありますが、低すぎる場合、
長期的に働いている社員が少ない可能性が高いです。

会社により状況が異なりますが、可能であれば離職率についても確認できると安心です。

# 質問２　未経験採用の方はどのように仕事を進めていますか？
入社後のイメージをしやすくするための質問です。
また、**未経験採用の実績があるかどうかも分かる**お得な質問にもなっております。

先輩社員と一緒に仕事をする、他社のエンジニアと仕事をする、１人で仕事をするのといったパターンがありますが、
おすすめは、「**先輩社員と一緒に仕事をする**」です。

困った時に気軽に質問できますよね。

なぜ他社のエンジニアと仕事をするのがおすすめではないかと言うと、
「**育てる気がないから**」です。
もちろん、業務に必要となる最低限のことは教えてくれると思いますが、それだけです。
**スキルアップ**、**成長**という観点で見ると、おすすめできないです。

１人で仕事をする場合、難易度が高過ぎるタスクが振られたら辛いだけです。


# 質問３　勤務先はどこですか？
自社、自宅、客先（常駐）のいずれかになるケースが多いと思いますが、
おすすめは、「**自社**」です。

他の社員の方ともコミュニケーション取りやすいですし、「**質問しやすい環境**」というのを
重視すると良いかと思っています。

転職後にいきなり客先常駐や在宅ワークになると、
質問しにくいですし、どこの会社に所属しているのかよく分からなくってきます。

ちなみに、弊社ではリモート勤務が普及する以前は、持ち帰り案件を中心に自社のオフィスで仕事をしていました。


# まとめ
端的にまとめると、キャリアのスタート時点では、
平均年齢が**低すぎない**・**先輩社員と一緒**に・**質問しやすい環境**で働けることが望ましいと思っています。

IT業界に興味がある方とのミスマッチが少しでも減ったら幸いです。

弊社は未経験からエンジニアになった方が活躍している会社です。
未経験者採用も実施していますので、ご興味ある方は[こちら](https://www.recruit.nuco.co.jp/)より。
Azure Active Directoryの情報に基づいたAzure VMへのログイン

# Azure VMへのログイン
Azureでの仮想マシンのログインは基本的に作成時の管理者名＋パスワードで行うことが多いと思います。Windows Server 2019/Windows 10 1809以降であれば、Azure ADを認証プラットフォームとしてRDP接続できるようになりました。それに伴い、IAM(RBAC)のロールとして[VMへのユーザログイン]、[VMへの管理者ログイン]というロールが追加されています。これらのロールを付与したユーザはVMへのRDPの認証画面で自身のAAD情報を用いてログインすることができます。ログイン後の権限はRBACで指定します。ログイン元となるデバイスは対象のVMが展開されているAzureテナントに登録されている必要がありそうです。よって接続元PC上でアカウント設定から組織に接続しておく必要があります。

> Azure AD 参加済みの VM にリモート接続できるのは、VM として同じディレクトリに対して Azure AD 登録済み (最低限必要なビルドは 20H1)、Azure AD 参加済み、またはハイブリッド Azure AD 参加済みの Windows 10 以降の PC からのみです。

https://docs.microsoft.com/ja-jp/azure/active-directory/devices/howto-vm-sign-in-azure-ad-windows

# 検証
今回はクライアントPCを想定したVM(Windows 11 Client)からWindows Server VMへのRDPで検証します。

# VMの作成
ここは通常通りVMを作成します。 RDP対象となるWindows Server VM作成時に[管理]からAzureADによるログインを有効化できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/179012af-fcb7-9eb4-37a4-d53825870695.png)

# RBACの追加
下記のログイン権限を付与します。サブスクリプション所有者であっても別で設定する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/6679a590-c191-73d0-7601-b3583658ba9b.png)


# クライアントVM上でテナントに接続
Windows Server VMへのRDP時に利用するログインユーザを使ってクライアントVM上でAADに参加します。ここをRDP時のログインユーザと異なるユーザにしてしまうと接続時にエラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/532d3ba1-2155-361b-72cf-4597ba805319.png)

# Windows ServerへのAADによるログインの検証
通常通りRDPクライアントを立ち上げ、IPアドレスを入力、認証画面が出現します。ここでAzureでRBACを割り当てたユーザ情報(クライアントVM上で組織に接続時に使ったアカウント)でログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/1e402471-d325-9d56-ae83-fed2a4b3178c.png)

接続できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/6fc862ff-23c2-04ba-76c9-a5c5844b15a7.png)

ちなみに、組織への接続に使ったアカウント以外で試してみるとこのような画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205918/d8ad3c79-b748-a129-bcc0-f30604c45ee0.png)

> Your account is configured to prevent you from using this device. For more info, contact your system administrator.

やはり、ユーザ＋デバイスの組み合わせで制御がかかっているようですね。
IPアドレスとMACアドレス (基本情報技術者試験)

現在(2022.04)基本情報技術者試験の勉強で以下の内容を理解していなかった為、復習兼ねて書いてみようと思いました。

# IPアドレス（IPv4）
IPアドレス(<font color="red">I</font>nternet <font color="red">P</font>rotcol address)とはネットワーク通信を行う際に使われるアドレスで<font color="red">機器の住所</font>の様なもの。
一般的に10進数で表示される事が多いが、内部的には32ビットの2進数に全て変換されてネットワークでやりとりされている。

## IPアドレス（IPv4） 【追記：2022年4月18日】
IPアドレスは、ネットワークアドレス部とホストアドレス部の２つをかけ合わせて成り立っている。

<font color="red">ネットワークアドレス部</font>はどのネットワークに属しているかを示すアドレス。
<font color="blue">ホストアドレス部</font>はどのコンピュータかを示すアドレス。

(例)ネットワークアドレス部が24ビット、ホストアドレス部が8ビットの場合
※赤部分がネットワークアドレス部で青部分がホストアドレス部になる。

10進数表記だと<font color="red">192.168.0</font><font color="blue">.1</font>
2進数表記だと<font color="red">11000000.10101000.00000000</font><font color="blue">.00000001</font>

ネットワークアドレス部とホストアドレス部の２つで構成されているIPアドレスはグローバルIPアドレスとプライベートIPアドレスの2種類が存在する。
(IT初心者には難易度高いですよね...僕もですが)

## プライベートIPアドレス
プライベートIPアドレスとはローカルネットワーク上で使えるIPアドレス。
社内だけでやりとりされる場合などの限定的なネットワークで使用される。

## グローバルIPアドレス
グローバルIPアドレスとはインターネットワーク上でも使えるIPアドレス。
各機器に振り分けられているプライベートIPアドレスは、ルータの機能である<font color="red">NAT,NAPT</font>でグローバルIPアドレスに変換をかけてネットワークが接続されている。

# MACアドレスとは
MACアドレス（<font color="red">M</font>edia <font color="red">A</font>ccess <font color="red">C</font>ontrol address)とはネットワーク機器やそれぞれのネットワークアダプタ（通信する入口）に付いている世界に一つだけの識別番号。
IPアドレスは通信する目的地しか示さない為、通信する道中のルートでMACアドレスが識別子として使用される。

アドレスは2進数48桁又は12桁の16進数で構成されている。
前半6桁(1~24桁)はメーカーの固有の番号、後半6桁(25~48桁）は個々の製品の番号からMACアドレスが形成される。

# まとめ
IPアドレスにはグローバルIPアドレスとプライベートIPアドレスの2種類があり、機器の住所的な存在。
NAT,NAPTでプライベートIPアドレスからグローバルIPアドレスに変換され（その逆も然り）外部との通信ができる。
MACアドレスは機器やそのインターフェースに対して固有に振られている番号。

次回はサブネットマスクについて書いていきたいと思います。
# 参照
https://www.cman.jp/network/term/mac/
https://it-biz.online/it-skills/mac_vs_ip/#toc1
https://www.otsuka-shokai.co.jp/words/mac-Address.html
https://engineer-ninaritai.com/mac-address/
https://www.infraexpert.com/study/ip10.html
LaravelのwithによるEagerローディング【個人的なお勉強アウトプット】

## 参考図書
https://www.amazon.co.jp/dp/B07CLLW4MX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

リレーションで値を取り出すのは大変便利だが、そのまま使うとレコードの数が多い場合、DBへのアクセスに余計な負荷がかかっている。

## 前提
PersonモデルとBoardモデルがリレーションしている。
Personモデルには人のレコードが、Boardモデルには掲示板へのコメントがレコードされている。

## 余計な負荷とは
例えば、Person::allで全Personを取得する場合。まずPersonを全部取り出し、そこから一つ一つのPersonに関連付けられているBoardを取り出すというやり方をしている。
投稿されたBoardが10個あったとすると、Board全体を取得するのに1回、それから10個のBoardそれぞれで関連するPersonを取得するにに10回、計11回もデータベースに問い合わせをしている。
これは「N+1問題」と呼ばれている。

## 解決策
withメソッドを使う。
`モデル::with(リレーション名)->get();`
withメソッドを使うと、、、

- 1.Boardだけを取得する
- 2.得られたBoardのperson_idの値をまとめ、それからIDのPersonを取得する。

11回DBにアクセスしていたのが、2回で済む。
【Python】SMILESの分子フィンガープリントへの変換をsklearn風に書く【RDkit】

SMILESの分子フィンガープリントへの変換をsklearnのPipelineに通せるようにsklearn風に書きました。
今回は一例でMACCSkeysに変換する場合です。

```python
class MACCSkeysTransformer(BaseEstimator, TransformerMixin):
    
    def __init__(self, smiles_column_name: str):
        # smilesの構造が書かれた列名
        self.smiles = smiles_column_name
        
    def fit(self, X, y=None):
        # fitでは何もしない
        # fit内で下記transform内のコードを書いてもいいかも
        return self
    
    def transform(self, X):
        # smilesをmaccskeysに変換
        # その際リストに各maccskeysのbitを格納
        df_maccs = X[self.smiles].map(lambda x: list(
            MACCSkeys.GenMACCSKeys(Chem.MolFromSmiles(x))))
        
        # リストに格納されたbitを展開
        df_maccs = df_maccs.apply(pd.Series)
        
        # 列名の変更
        df_maccs.columns = ["maccskey_" + str(i) for i in df_maccs.columns]
    
        return df_maccs
```
データフレーム内の要素のリストを展開する方法は[こちら](https://ja.stackoverflow.com/questions/31783/dataframe%E3%81%AE%E5%90%84%E3%82%BB%E3%83%AB%E3%81%AElist%E3%82%92%E5%88%86%E8%A7%A3%E3%81%97%E3%81%A6%E6%96%B0%E3%81%9F%E3%81%AA%E5%A4%89%E6%95%B0%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)を参照。
.apply(pd.Series)でリストを展開できるのは面白い。

### 実際に使ってみる
データはtox21の化合物データ(データ数8014件)を使用しています。
```python
%%time
mt = MACCSkeysTransformer("smiles")
df_tox_transform = mt.fit_transform(df_tox)

print("列数：", df_tox_transform.shape[1])
display(df_tox_transform.head(2))
```
![スクリーンショット 2022-04-11 11.45.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861630/f2603093-060b-0f00-45a9-c8e47eb5d099.png)
想定通りに変換できてそう。私の環境では変換にかかった時間は約23秒でした。

### 続いてsklearnのPipelineに通してみる

```python
pipe = Pipeline([
    ("mt", MACCSkeysTransformer("smiles")),
    ("ss", StandardScaler()),
])

df_tox_pipe = pipe.fit_transform(df_tox)

print("列数：", df_tox_pipe.shape[1])
print(df_tox_pipe)
```
![スクリーンショット 2022-04-11 11.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861630/6e77e28b-2602-f683-8814-b600d01b81f1.png)
MACCSkeysに変換後、標準化するのもできてそう。

## 最後に
フィンガープリントは様々な種類があるので、適宜コードは変えてください。
Laravelのモデルでリレーションのレコードを持つ持たないの条件で取り出す【個人的なお勉強アウトプット】

## 参考図書
https://www.amazon.co.jp/dp/B07CLLW4MX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

## 前提
PersonモデルとBoardモデルがリレーションしている。
Personモデルには人のレコードが、Boardモデルには掲示板へのコメントがレコードされている。

Boardモデルは投稿者のレコードとなるPersonモデルに必ず関連付けられている。
しかし、Personモデルはそうではない。頻繁に投稿すれば、東欧しない人もあいる。Personモデルは関連するBoardを複数持つ場合もあれば、まったく持たない場合もある。

このような場合、関連するBoardを持っているPerson、または、関連するBoardを持たないPersonを取り出さればいろいろ役に立ちそう。

## 特定のリレーションを持つ
`モデル::has(リレーション名)->get();`

## 特定のリレーションを持たない
`モデル::doesntHave(リレーション名)->get();`

## 実例
値の取得
```app/Http/Controllers/PersonController.php
public function index(Request $request){
$hasItems = Person::has('boards')->get();
$noItems = Person::doesntHave('boards')->get();
$param = ['hasItems' => $hasItems, 'noItems' => $noteItems];
return view('person.index', $param);
}
```

値の表示
```resources/views/Person/index.blade.php
@section('content')
<table>
    <tr><th>Person</th><th>Board</th></tr>
    @foreach ($hasItems as $item)
        <tr>
            <td>{{$item->getData()}}</td>
            <td>
                <table width="100%">
                @foreach ($item->boards as $obj)
                    <tr><td>{{$obj->getData()}}</td></tr>
                @endforeach
                </table>
            </td>
        </tr>
    @endforeach
</table>
<div style="margin:10px;"></div>
<table>
    <tr><th>Person</th></tr>
    @foreach ($noItems as $item)
        <tr>
            <td>{{$item->getData()}}</td>
        </tr>
    @endforeach
</table>
@endsection
```
【Google app script】GASで外したスターがGmail Webアプリ上の受信トレイで反映されない【Star/Unstar】

# 概要
Gmailではスレッドに対してラベル、メッセージに対してはスターや既読を付けることができる

しかし、メッセージについたスターをGoogle app scriptを使って外すとGmailの受信BoxのUI上で反映されていないことを発見し、調査した。

# 再現
状況を再現するコードを用意した。
事前にスターを付けたメールを1件用意しておく

```javascript
function getLatestStarredMail() {
    const threads = GmailApp.search("is:starred");
    const latestMsg = threads[0].getMessages()[0];
    return latestMsg;
}

function traceUnstar(message) {
    const date = message.getDate();
    Logger.log("Date : " + date);

    const subject = message.getSubject();
    Logger.log("Subject : " + subject);

    traceIsStarred(message);

    message.unstar();
    Logger.log("unstar message");

    message.refresh();
    Logger.log("refreshed");

    traceIsStarred(message);
}

function traceIsStarred(message) {
    if (message.isStarred()) {
        Logger.log("starred");
    } else {
        Logger.log("unstarred");
    }
}

function testStarUI() {
    const message = getLatestStarredMail();
    traceUnstar(message);
}
```

testStarUIを実行しても、受信ボックス上の当該メールのスターは外れていないように表示されているがログではきちんとスターが外れている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694714/66184a86-1456-8955-b18d-b55331764cfb.png)

一方でis:starredでサーチするとしっかりスターが外れていることが確認できる。
フィルター機能ではしっかりと反映されている。受信ボックスだけの表示不具合のようだ。

# 過去の報告
同様の報告を探したところ1件見つかった

https://stackoverflow.com/questions/49540711/web-gmail-shows-message-as-starred-even-after-apps-script-unstars-it

しかし、具体的な解決策はなかった。
同スレッド内で公式に報告したとあったので、確認した

https://issuetracker.google.com/issues/77320923?pli=1

ただ、いまだに解決していないようである。4年も前から残り続けている不具合だった。

# 結論
- Webアプリ受信ボックス上でのみGASからStar()やUnstar()したメッセージの状態が反映されない
- Webアプリから見る際はis:starredでフィルターして操作すると間違いがない
Windowsでnodejsの環境構築【安定感抜群】

# あらすじ

Windowsのローカル環境でnodejsを使って開発を行いたいときのベストプラクティスを紹介します。

dockerやWSLを使うのが理想ですが、「マシンスペック的にVMを起動すること自体がおっくうな場合」もしくは、「Windows Server Core などを本番環境に使用する予定」などのための記事とします。

::: note warn
2022年4月現在の最新情報です。
筆者は現在、[Volta](https://volta.sh/)をメインで使用しています。`nvm`は使っていません。
:::

# 前提

下記ソフトウェアがインストール済みとします。

- Windows 10 or Later
- Powershell 7 or Later

::: note warn
もし、他のnodejs用のバージョン完了ツールや、nodejs公式のインストーラーを使用したインストールが行われている場合、事前に全て消しましょう。特に、環境変数は厄介なので、慎重に確認して消しましょう。筆者は、ProgramFilesが２個あることに気が付かず時間を無駄にしました。
:::

# やること

やることは、下記の通りです。

- `nvm`のインストール
- `node`のインストール
- `npm`の更新

::: note info
環境変数`path`は、`nvm`については`nvm`のインストーラーが、それ以外は`nvm`のコマンドで、それぞれ自動的に設定されます。
:::

# nvm

`nvm`をインストールしましょう。

公式サイトからインストールする場合は、こちらから`nvm-setup.zip`をダウンロードします。

https://github.com/coreybutler/nvm-windows/releases/latest

::: note warn
Linux と Mac 用のnvmとは別の開発者によるソフトウェアです。設計思想を始め、完全な互換性は無いことに留意してください。
:::

::: note info
`nvm-update.zip`や`nvm-noinstall.zip`など別の利用方法も用意されていて親切ですね。
:::

chocolateyを使ってもいいと思います。その場合は下記のコマンドを使います。

```powershell
choco install nvm
```

上記のzipファイルを解凍すると`nvm-setup.exe`が入っているので、ウィザードに従ってインストールを進めていきます。この時の注意点として **「インストール中に指定できるディレクトリは、空白文字を含めないように変更」** する必要があります。`nvm use`が空白文字を含むディレクトリを処理できないため、エラーになります。しかもこの時のエラーメッセージは **文字化け** しているため、非常に厄介です。

最終的に、筆者の環境変数は下記の表の状態になりました。
環境変数`path`には、`%NVM_HOME%`と`%NVM_SYMLINK%`が追記されていました。

環境変数名 | 値
:-:|:-:
NVM_HOME | C:\Users\who\AppData\Roaming\nvm
NVM_SYMLINK | C:\nodejs

# node

`nvm`のインストールが終わったら、`node`をインストールしましょう。`nvm install`というコマンドで好きなバージョンをインストールすることができます。このとき、メジャーバージョンで16などを指定すれば、そのマイナーバージョンは最新が入ります。直接`nvm install 16.14.2`などと細かく指定することもできます。

```powershell
nvm install 16 # node のLTSバージョンは現在16なので16をインストール
```

上手くいったら、次に`nvm use 16.14.2`として、インストールしたnodejsの中から使うものを指定します。

```powershell
nvm use 16.14.2
```

# npm

`node`のインストールが終わったら、`npm`を更新しましょう。現在使用している`node`の環境に存在している`npm`コマンドが使えるようになっているはずです。

まず、診断コマンドを実行します。

```powershell
npm doctor
```

この時点で、多くの場合、`npm`の`recomended version`では無く、少し古いバージョンになっていると思います。

そこで、`npm`だけを更新するコマンドを実行します。

```powershell
npm i -g npm
```

もう一度`npm doctor`を実行して、`npm -v`が`ok`になっていれば成功です。

もし、ここで他の項目にエラーが有れば、エラーが無くなるまで`doctor`を繰り返し実行しながら、キレイな状態にしましょう。

# まとめ

要点をまとめます。

1. nvm-windowsをインストール
1. 好きなバージョンのnodeをインストール
1. その環境でnpmを更新
1. npm doctor で診断

`doctor`があるのは非常に心強いですね。`cli`を作る時、もしくは使う時には`doctor`コマンドの有無を重視してもいいかもしれません。

**Excelsior!**
Go言語 パッケージ

## Package
Goのプログラムは、全て何らかのパッケージに属する。
Importによって指定することにより、対象のパッケージが使用できるようになる。
また、１つのパッケージ内で、複数のソースコードファイルを使用してプログラムを定義できる。
変数や関数の頭文字を大文字にすれば、他のパッケージから参照出来るようになる。

## Code
```Go
package main

import (
	"fmt"
	"./calculation"
)

// Main function
func main() {

	// Calculation with functions in the calculation package
	add   := calculation.CalcAdd(10, 5)
	sub   := calculation.CalcSub(10, 5)
	multi := calculation.CalcMulti(10, 5)
	div   := calculation.CalcDiv(10, 5)

	// Output Value
	fmt.Printf("Addition       : %d \n", add)
	fmt.Printf("Subtraction    : %d \n", sub)
	fmt.Printf("Multiplication : %d \n", multi)
	fmt.Printf("Division       : %d \n", div)
}
```
```Go
package calculation

func CalcAdd(x int, y int) int {
	result := x + y
	return result
}
```
```Go
package calculation

func CalcSub(x int, y int) int {
	result := x - y
	return result
}
```
```Go
package calculation

func CalcMulti(x int, y int) int {
	result := x * y
	return result
}
```
```Go
package calculation

func CalcDiv(x int, y int) int {
	result := x / y
	return result
}
```

## Output Sample
~ $ go build -o calc main.go  
~ $ ./calc  
Addition       : 15  
Subtraction    : 5  
Multiplication : 50  
Division       : 2  

## Note
go1.13以降だと、環境変数GO111MODULEを”auto”に設定する必要がある。
$ go env -w GO111MODULE=auto  

## GitHub
https://github.com/GL-Kageyama/Go_Package