OmniAICreator/Qiita-1.07M huggingface dataset:
Google Cloud Functionsのログ出力（とハマったこと）

# やりたいこと
- 言語：Python
- Google Cloud FunctionsでStack Driver Loggingにログを出力したい。
- ドキュメントを見ると `print` でやれって書いてある
  - https://cloud.google.com/functions/docs/monitoring/logging?hl=ja#functions-log-helloworld-python
- とはいえログレベルは設定したい

# やったこと
- google-cloud-loggingを使う
  - requirements.txtに `google-cloud-logging==1.14.0` を追記

```python
# Imports the Google Cloud client library
import logging
from google.cloud import logging as glogging

client = glogging.Client(project=os.environ['PROJECT_ID'])
handler = client.get_default_handler()
cloud_logger = logging.getLogger('cloudLogger')
cloud_logger.setLevel(logging.INFO)
cloud_logger.addHandler(handler)

def test_method(request):

  print('== start ==')

  try:
    cloud_logger.info('Info Message')
    cloud_logger.warn('Warn Message')
    raise Exception
  except Exception:
    cloud_logger.error('Error Message')
    raise Exception

  print('== finish ==')

```

# 実行、しかしログが出ない
- なんにも出ない。

<img width="744" alt="1_test.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254900/9cc36457-2429-7e1a-3e9a-bfa9a7644ac1.png">

<img width="1426" alt="2_log.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254900/bf80b09c-2aa4-c8ae-de8f-c5e7f2dd44cd.png">


# 原因（想像）
- `print` にしても結果は変わらず・・・
- どうやらGoogle Cloud Functionsはcrash（=異常終了）するとそこまでのログを出力してくれない
  - ドキュメントのどこかに記述があるのだろうか・・・・
- なのでExceptionが出たらcatchして最終的に `sys.exit()` するように変更

```python
import sys
# 中略
  try:
    cloud_logger.info('Info Message')
    cloud_logger.warn('Warn Message')
    raise Exception
  except Exception:
    cloud_logger.error('Error Message')
    sys.exit()

  print('== finish ==')
```

# 再実行、そしてエラー
<img width="1950" alt="3_log.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254900/a5c799e1-4898-3dbf-6452-a3aab5ae3097.png">


- `Failed to submit 3 logs.`
- `google.api_core.exceptions.PermissionDenied: 403 The caller does not have permission`

 とな


# Google Cloud Functionsのサービスアカウント
- ドキュメントを見るとGoogle Cloud Functionsのデフォルトサービスアカウントは `PROJECT_ID@appspot.gserviceaccount.com` （App Engine default service account）になると記載がある。どうやらプロジェクト編集者のロールを持っているらしい。
    - https://cloud.google.com/functions/docs/concepts/iam?hl=ja#runtime_service_account
    - SAを見るとたしかにそんなものが生まれてる。
- 自分の環境を見ると・・・・ない！
  - なぜか無くなっていた模様

# 解決策
- 専用のSAを作成してGoogle Cloud Functionsへ紐付け。
- ちゃんとログが出るようになりました
    - エラーレベルがinfoとerrorしかないのはなぜだろう・・・
<img width="1199" alt="4_log.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254900/db48d0f3-965d-915d-92ee-46b52bc8f4de.png">


# 振り返り
- ドキュメントはちゃんと読もう
  - 書いてなかったかもしれないけど
- 横着してデフォルトのSAを使わず、ちゃんと必要な権限をもったSAを作成して利用しよう
- Cloud Functionsは**落とさない**。正常終了させる
- 稼働状況をモニタリングするならerror件数ではなくログのerrorメッセージ数を見る（しかないのだろうか・・・？）
[flutter]はじめてのflutter[FlutterSDK編]

#目的

WEBとアプリの比較から自分のやりたい方向性を掴む。

##今日やること

・flutterの環境構築

参考）https://flutter.dev

##Flutter SDKの取得とパスを通す
公式ドキュメントを参考に進めます。
Get startedからMacOSを選択し、System requirementsで要件を満たしているか確認します。
Get the Flutter SDKの中を進めていきます。

<img width="247" alt="Screen Shot 2020-07-08 at 21.40.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/654c8a1c-27e5-7eca-e53f-81ee65563acc.png">

DL後、ターミナルでパスを通します。

```
vi .zshrc
```

※bashであれば、

```
/.bashrc
```

vimが開きました。
編集モードにするため、iを押して、

```
export PATH="$PATH:[PATH_TO_FLUTTER_GIT_DIRECTORY]/flutter/bin"

```

※PATH:[PATH_TO_FLUTTER_GIT_DIRECTORY]は、flutterを格納したディレクトリを選ぶ。
追加後、esc　を押下、

```
:wq　
```
で保存。
参考）　https://flutter.dev/docs/get-started/install/macos#update-your-path

次に、AndroidStudioとXcodeのインストール。

続きは次回！
【自分メモ】BigQuery MLのチュートリアルやってみた

# はじめに
[国勢調査データに基づいた分類モデルの構築と使用](https://cloud.google.com/bigquery-ml/docs/logistic-regression-prediction?hl=ja)をやってみた。

# 大まかなStep
1. モデル作成
2. モデル評価
3. モデルを使って予測

## 1. モデル作成
### ステップ 1: モデルを格納するためのデータセットを作成する。
> 最初のステップとして、モデルを格納する BigQuery データセットを作成します。

### ステップ 2: データを確認する。
> このステップでは、データセットを確認して、ロジスティック回帰モデルのトレーニング データとして使用する列を特定します。

### ステップ 3: トレーニング データを選択する。
> 次に、census_adult_income テーブルに対してクエリを実行して、2 項ロジスティック回帰モデルのトレーニングに使用するデータを準備します。 このステップでは、関連性のある特徴を特定し、その後のクエリで入力データとして使用するためにビューに保存します。

### ステップ 4: ロジスティック回帰モデルを作成する。
> ステップ 4 では、CREATE MODEL ステートメントを使用してロジスティック回帰モデルを作成します。

## 2. モデル評価
### ステップ 5: ML.EVALUATE 関数を使用してモデルを評価する。
> 次に、ML.EVALUATE 関数でモデルの性能に関する統計を取得します。

## 3. モデルを使って予測
### ステップ 6: ML.PREDICT 関数を使用して回答者の所得を予測する。
> 最後に、ML.PREDICT 関数を使用して、特定の国勢調査回答者の所得階層を予測します。
URLはブロックされています: リダイレクトURIがアプリのクライアントOAuth設定でホワイトリストに追加されていないため、リダイレクトできませんでした。クライアントとウェブOAuthログインをオンにして、すべてのアプリドメインを有効なOAuthリダイレクトURIとして追加してください。

ググって1ページ目に出なかったら積極的に残していくスタイル。たとえそれが公式ドキュメントを読みましょうとしか言いようがないことだとしても。

>
URLはブロックされています: リダイレクトURIがアプリのクライアントOAuth設定でホワイトリストに追加されていないため、リダイレクトできませんでした。クライアントとウェブOAuthログインをオンにして、すべてのアプリドメインを有効なOAuthリダイレクトURIとして追加してください。


Facebookログインを実装しようとした時に、これが出てきたら、https://firebase.google.com/docs/auth/web/facebook-login
ここのページの準備のところを読んでください。


公式ドキュメントを読みましょうということに尽きるのですが、ドキュメントを読まず

```
yarn create next-app --example with-firebase-authentication with-firebase-authentication-app
```

とかでテンプレから作ってそこからちょっとFacebook認証加えてさくっと動かそうとしたら動かなくてエラーメッセージでググってもなかなか解決法が出てこず時間を無駄にする自分のような人がいるかもしれないので残します。


公式ドキュメントを読みましょう。
A2019 Community Editionの「アップグレード」バナーを閉じるブックマークレット

Community EditionがA2019.14にアップデートされてから、以下のような黄色いバナーが出るようになりました。
個人的にはスケジュール実行機能や優れた管理機能、Bot Insight等も使えるEnterprise版にぜひアップグレードをお勧めしたいのですが、特に不要かつ毎日のように使う方には邪魔な表示になります。
しかしながらこのバナー、Xボタンが右端にあり押しにくいので、BookmarkletでXボタンを押す方法を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/cf74906d-e67a-4853-9afc-690106a23ddf.png)

まず、F12キーを押してXボタンのソースコードを把握します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/5106db40-315d-93a8-80d3-cb2fb6a16a7f.png)
icon aa-icon aa-icon-misc-message-system-level-close icon--animate-none というクラス名のspanタグで囲まれた部分がこのボタンのようです。

以下のようなjavascriptのコードで、クラス名を元に該当するエレメントを探して、指定したアクションを実行することが出来ます。
今回はicon aa-icon aa-icon-misc-message-system-level-close icon--animate-none というクラス名で該当するエレメントを探して、その上でクリックさせています。
これでXボタンを押せるはずです。

```
javascript:(function(){let a=document.getElementsByClassName("icon aa-icon aa-icon-misc-message-system-level-close icon--animate-none");a[0].click();})();
```

Webブラウザのブックマークバーにブックマークを作成し、URL部分を上記のコードに入れ替えます。
名前も適当に付けます。

以下のようにすると、Control Roomを開いてすぐに押せると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/9e532f44-2c3d-e192-d2e7-ff05445f15ed.png)
bootstrap導入方法

1　bootstrapの公式を開く　https://getbootstrap.com/docs/4.5/getting-started/introduction/

２　公式の「Get started」をクリック。（ダウンロードかリンクへのアクセスかの２通りの利用方法があるが、特別な理由がない限り下記の方法でのリンクアクセスで良い。わざわざダウンロードしてPCの容量を圧迫する必要はない。）

３　IntroductionのQuick startの真下にある、CSSのCopy-paste the stylesheet <link> into your <head> before all other stylesheets to load our CSS.と書かれた直下のコード　```<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css　以下略```をコピー。

４　自分の作りたいアプリ等のhtmlファイルに貼り付ける。
```<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ホゲホゲ</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet"　←ここから、
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">　←ここまでが貼り付けたコードです。
  <style>
```
５　これで準備は完了。
特徴として、class名に　ナビバーならclass="navbar-nav、各種ボタンならclass="btn btn-primary　などの対応したclass名が必要になり、それによって上記のlink relのアクセス先から対応したcssを読み取ってナビバーやボタンなどを表示できるようになる。ハンバーガーメニューもある。
いずれも、準備後はbootstrap公式に記載された、自分がほしい機能の項目に書いてあるコードをコピーしてhtmlに貼り付けるだけですぐに使える。

また、bootstrapはグリッドメニューにも対応しており、画面を縦に１２分割したカラム分けをすることができる。（短冊のように画面を縦割りで管理できる）
分割ごとにブロックを作ることもできる。（ぷよぷよをイメージしてもらうとわかりやすい）
これによってレスポンシブデザインにも対応していて、PC・タブレット・スマホそれぞれに対応した画面表示になってくれる。公式サイトにも使われているから、公式の画面を縮めてみればわかる。
（ハンバーガーメニューは、スマホ並みに画面（ウィンドウ）を縮めないとハンバーガーメニューが表示されないようなので、縮めていないと「ハンバーガーメニューのコード貼り付けたのにでない‥！？」となるので注意。
AWS S3のオブジェクトロックの機能

S3のオブジェクトロックは削除されないように保護する機能です。

作成されたオブジェクトをコンプライアンス上の要請などで削除や変更できないように制限をかけられます。オペレーションミスを防止する目的ではなく、削除の意図を持って削除しようとする人から保護します。


# ロックの対象

オブジェクトに対してロックします。バケット全体に対してではありません。

オブジェクトに対する設定というのは特定のKeyの特定のバージョンに対する設定です。特定のKeyに対してロックをかけても、そのKeyに対して引き続き上書き変更や削除を行うことはできます。あくまでロックをかけたそのバージョンを削除できないということです。また、上書きしてできた新しいバージョンにはロックの設定は引き継がれず新規オブジェクトと同じ扱いです。

この機能を使うにはバケットのオブジェクトロックの機能が有効となっている必要があります。


# バケットのオブジェクトロック有効化

バケットに対する設定の注意事項：

- バケットのオブジェクトロック有効化はバケット作成時にのみ設定可能。あとからの変更は不可
- バケットのオブジェクトロック有効化をするには同時にバージョニングも有効化する必要あり
- オブジェクトロック有効化されているバケットはバージョニングを止めることができない
- バケットのオブジェクトロックが有効化だからといって直ちにバケット内すべてのオブジェクトがロックされるわけではない


## バケット作成時の画面

オブジェクトロックを有効化するかどうかのみです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/0f747c8b-9c7e-be50-1d7e-c2959777f219.png)

この他に、オブジェクトに対する設定(ロックをかけるかどうかや、モード、保持期限)のデフォルト値をバケットに対して設定できます。デフォルト値はバケット作成後のPropertiesの画面で設定します。あとから変更もできます。


# オブジェクトに対する設定

オブジェクトロックは2つの機能があります。片方だけ使うことも両方同時に使うこともできます。

- リテンションモード (retention mode)
- リーガルホールド (legal hold)

リテンションモードにはさらに2つのモードがあります。これはどちらかを選択して使います。

- ガバナンスモード (governance mode)
- コンプライアンスモード (compliance mode)

つまり次のうちのいずれかになります。

- オブジェクトロックをかけない
- リテンションモードのガバナンスモード
- リテンションモードのコンプライアンスモード
- リーガルホールド
- リテンションモードのガバナンスモードで、かつリーガルホールド
- リテンションモードのコンプライアンスモードで、かつリーガルホールド


## ロックを解除できる条件

- リテンションモードのガバナンスモード
    - 保持期限が到来すると自動で解除
    - IAMでガバナンスモード解除の権限を持っているユーザまたはロールが解除操作
- リテンションモードのコンプライアンスモード
    - 保持期限が到来すると自動で解除
- リーガルホールド
    - IAMでリーガルホールド解除の権限を持っているユーザまたはロールが解除操作


## リテンションモードとリーガルホールドの比較

違いは期限があるかどうかです。

リテンションモードは保持期限を設定します。保持期限がすぎたら、リテンションモードが解除されます。

リーガルホールドは無期限です。

どちらも削除できないようにロックされる効果は同じです。

リテンションモードは生成され続けるオブジェクトを一定期間保持する義務がある場合に便利です。

リーガルホールドは事件・事故・訴訟が起きたときに証拠を保全する必要がある場合に便利です。解決するまで無期限に特定のオブジェクトを保護できます。

リテンションモードとリーガルホールドを同時に設定していた場合は、リテンションモードの保持期限をすぎるとリテンションモードのみが解除され、リーガルホールドはそのままです。つまり保持期限を過ぎてもロックされたままです。

リーガルホールドはIAMでリーガルホールド解除の権限を持っていれば解除が可能です。


## ガバナンスモードとコンプライアンスモードの比較

違いは期限内にロックを解除できるかどうかです。

ガバナンスモードは期限内であってもIAMでガバナンスモード解除の権限を持っていれば解除が可能です。

コンプライアンスモードは期限内に解除することはできません。たとえroot権限であっても解除できません。


## オブジェクトのPropertiesの画面

リテンションモードの選択とリーガルホールドの設定は独立しています。リテンションモードをガバナンスモードまたはコンプライアンスモードにすると、解除される日付（期限）を設定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/1330120c-e672-2ed6-66f5-7348dba0e3f7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/117bf98a-9f49-cd56-2b69-b620bf02b65d.png)


## バケットのPropertiesの画面

リテンションモードのデフォルト値を設定できます。保持期限は日数で設定します。リーガルホールドはデフォルトで有効にすることはできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/da6a1c96-84ef-4779-0241-5f984105bf9e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/590ce1b5-472a-621f-453a-4f1c3144012e.png)

以上。
貼り付けて、ENTERを押すだけのへぼいやつ

タイトルどおり
指定した回数だけ「CTRL+Vをして、ENTERを押す」をするだけのツールです。
くだらないものですがどうぞ。。。

[ctrl+V+Enterのgithub](https://github.com/tensai-man/ctrl-v-enter)

Accessのテーブルでクエリをつくるほどでもない
入力作業で活躍するかもです。

今なら「貼り付けて、下を押すだけ」のツールもつけています。
Gitで覚えたコマンドを書いていく

# 注意書き
勉強しながらメモした物です。
間違っている点があるかもしれませんので、
使用する場合は参考程度にしてください。

なおコマンドのオプションについて省いている部分があります。


# Gitじゃないが使うコマンド
## cd

「change directory」の略で、ディレクトリを移動する。

	cd （相対パス　or　フルパス）

## ls
「list segments」の略で、ファイルやディレクトリ情報を表示する

	ls

## mkdir
make directory」の略で、ディレクトリを新規作成する

	mkdir ディレクトリ名

## rm
「remove」の略で、ファイルやディレクトリの削除をする

	rm ファイル名

## cat
「concatenate」の略で（猫じゃないの！？）、ファイル結合や閲覧で使用する

	cat ファイル名

# Git コマンド
詳細後日記載予定
## git config
### git config --global user.name "GitHubのユーザー名"
### git config --global user.email GitHubに登録したメール@example.com
### git config --global core.editor "エディタ名 --wait"


## git status

## git commit
通信要件がHTTPS/TLSだったらCRLアクセス用のHTTP通信も必要じゃないのか

或るクラウド管理サービスが「うちのSaaS管理ソリューションはHTTPS/TLS接続でここのサーバーへのインターネットアクセスだけしか必要としないからセキュア！安心！（ファイアウォール設定も）簡単！」とか宣伝していたので、「TLSアクセスがあるってことはサーバー証明書の失効確認のためにCRLにアクセスする特定URLへのHTTPアクセスが必要になるんとちゃうんかい」と聞いてみたら速攻で「それは、その通り・・・」と返して通信要件を増やされた。

その反応自体はスピーディーで好感が持てるのだけど、通信要件はHTTPS/TLSでこのサーバーだけにアクセス許可が必要！とか謳っているサービスとか、CRL用の通信要件を忘れてるサービスは他にも一杯ありそうだなと思った次第。

ていうか、自分が知らないだけでCRLのチェックは無効が最近の業界のデフォだったりするんだろうか。
ラズベリーパイを遠隔で操りたいんだ！！

#はじめに
今回の記事ではラズベリーパイを遠隔で動かせる方法を調べたのでその方法を紹介します。ラズベリーパイで何をし良いのか分からないけど、何かしたいと言う人は最後まで見ていってください。
#ラズベリーパイの設定
まずコマンド**LXTeminal**を開きます(左端から四番目)。そうしたら

```ターミナル
pi@raspberrypi:~ $ 
```
このような画面が出て来ると思うのでここに**sudo raspi-config**と入力して下さいそうすると<img width="660" alt="スクリーンショット 2020-07-08 21.54.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/c66d8894-a663-8e46-7514-52580432161a.png">
このようなウィンドウに変わるので、矢印キーで５を選択してエンターを押して下さい。そうしたら、<img width="658" alt="スクリーンショット 2020-07-08 21.58.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/bacede32-0a30-0afe-2399-01b162a592ce.png">
上のような画面が出て来るのでそうしたらまた同じように矢印で３を選択してエンターを押して下さい。最後にこの様な画面が出るのではいを選択してエンターを押して下さい。<img width="656" alt="スクリーンショット 2020-07-08 22.05.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/7fb9cca4-cd23-5776-eaba-c9e149cb693d.png">
そうするとラズベリーパイの右端から五番目に**VNC**のアイコンが現れると思うのでそこを右クリックして下さい。そこから**Options...**をクリックすると<img width="672" alt="スクリーンショット 2020-07-08 22.14.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/77eb3b16-0ade-298d-07f2-1d98d589ab65.png">この様なウィンドウが現れます(もしVNC passwordになっていなかったら自分で変更して下さい)。次に**Apply**を押すと遠隔操作する時に必要なパスワードを設定しろと言われるのでパスワードを設定してたらOKを押して閉じて下さい。後、言い忘れてましたが右上から三番目の所にカーソルを持って行くと8桁のIPアドレスが表示されるのでそれをメモって置いて下さい接続する時に使います。
#リモート接続（mac）
ここまでくればもう一息です初めに**Spotlight**を開きます。開き方は簡単⌘とスペースを同時に押すだけです。そしたらそこに**画面**と入力してEnterを押して下さい。これで画面共有アプリが開けました。そしたらそこにIPアドテス（数字の途中にあった**点**も入力する様にして下さい）を入れて、先のパスワードを入力すれば無事に接続できます。![スクリーンショット 2020-07-08 22.34.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/d8a91f72-61f2-ae11-66c6-bf33b668073b.png)
#最後に
最後まで見てくれてありがとうございます。これからもラズパイ関連の記事も書いていく予定なのでよかったらフォローして下さい。もし間違いを見つけたら気軽にコメントで教えて下さい。前回の記事ですよけれ一緒に読んで下さい。
[ラズベリーパイを起動したらやるべき３つの事](https://qiita.com/lat-uni/items/20a2f15321111f09479a)
☆初投稿：TECH CAMP学習、個人アプリ作成①、駆け出しエンジニア

# TECH CAMPに通い出して
初めて投稿させていただきました。
TECH CAMPの夜間コースに通い出して３ヶ月が経ちました。
カリキュラムではわからないことも沢山あり、その都度Googleで調べたり、メンターさんに質問したりと、苦労も沢山ありました。エラーを繰り返しながらも、無事に動いたときというのは何とも言えない喜びもありました。

諸々、何とかこなし、いよいよ個人アプリ開発となりました。

正直、現在も試行錯誤の連続でありますが、やはり自分のやっていることというのは、時間がたつと忘れてしまうこともありますので、自分が苦労して解決したことなどは記録していった方がよいと考え、投稿させていただきました。

まだまだ不慣れであり、かつ知識も未熟なため、書いてあることが間違っていることもあるかもしれませんが、はっきりいって投稿することに意味があるのだと思いましたので、間違っているところははっきり指摘していただけたら嬉しいです。


個人アプリの作成時、viewを表示させようとしたのですが
まずは以下のエラーがありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613470/f922822e-3b03-62ea-58d7-8fa2855349fe.png)


原因はhamlの導入ができていませんでした。
なのでGemfileに

『gem 'haml-rails'』

を入力して
ターミナルにて

『bundle install』

を実行、その後すでにあるerbをhamlに変換

『rails haml:erb2haml』

すると「would　you like〜」と出てくるので「y」を入力
これでエラーは解決しました。
RealVncとラズベリーパイとIpV6と私

#ラズベリーパイで外部接続したい！！
と思い、RealVncを使用してみました。おおーつながるぞと思い大満足！！（ちなみにwin10のパソコンからです。）
しかし、しばらくして接続するとつながらない！！パソコンを再起動するとつながらない。パソコンをスリープから立ち上げるとつながらない。
あれ、なんでと思いつつ原因探し...

調べていくと、ラズベリーパイを再起動してみると、どんな時でもつながるようになるみたい。

なぜ？？なぜ？？と思い、再度原因を探す。

すると、家はIpV6だったと思い出す。それが原因では！！

ラズベリーパイで左上のwifiマークを右クリックで、Wireless & Wired NetWork Settingを選択し、disable Ipv6をチェックし、ipを固定。

再度、挑戦。

これで、いつでも接続できるようになりましたとさ。

おそまつさまです。
Tensorfrowで画像分類など学習してみる（手書き文字認識編１）

前回の記事[「TensorFlowで画像分類など学習してみる（環境構築編）」](https://qiita.com/kazuboy/items/faba3e3cd70720408193)の続きになります。
前回は環境構築編を書きましたが、今回から画像分類について複数回に分けて書いてみます。
MNISTの手書き文字の画像を利用して分類について書いていきます。MNISTのデータは世界中で利用されており、機械学習・ニューラルネットワークの一歩として多数のドキュメントが存在します。（手書き文字の画像を扱うのはプログラミングでいうところのHello world的なものです）

参考：[MNIST](http://yann.lecun.com/exdb/mnist/)はこちらになります。

第1弾は、データの読み込み・データの確認までを書いていきます。


## 前提/環境
前提となる環境とバージョンは下記となります。
・Anaconda3
・Python3.7.7
・pip 20.0
・TensorFlow 2.0.0

この記事ではJupyter Notebookでプログラムを進めていきます。コードの部分をJupyter Notebookにコピー＆ペーストし実行することで同様の結果が得られると思います。注：バージョンが異なったり、他ツール（Google Colaboratoryなど）では検証していませんので動作しないケースがあります。

##順伝播型ニューラルネットワークを作る
MNISTの手書き文字セットを順伝播型ニューラルネットワークによって分類するということを目標にして
Tensorflowと機械学習に触れて理解していきたいと思います。

###順伝播型ニューラルネットワーク（feedforward neural network）とは
ニューロンが層のように並び隣接する層の間でのみ結合するネットワークです。入力されたデータは
順方向にのみ伝播していきます。
・データが逆に伝播することはない
・隣接するニューロンへのみデータが伝播する。
・各層のニューロンは隣接する前方のすべてのニューロンからデータを受け取る
・同一層のニューロンからはデータを受け取ることはない
というものです。

![順伝播型ニューラルネットワークの図.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659138/da33999c-ed93-0448-c4e9-68bb941509e3.png)


##順伝播型ニューラルネットワークのTensorFlow・Kerasを使った実装
入力層・中間層・出力層がそれぞれ1つである3層のニューラルネットワークを構築します。まずはデータのロードから進めていきます。

###実装その1　MNISTデータのインポート

```python:code
import tensorflow as tf
from tensorflow.keras.datasets import mnist

#ヘルパーのライブラリ読み込み。画像を表示する場合に利用します。
import numpy as np
import matplotlib.pyplot as plt

(x_train, y_train), (x_test, y_test) = mnist.load_data() # データロード
```

TensorFrowではMNISTのデータを扱うモジュールがあり簡単にロードすることができます。
MNISTの手書き文字データセットは0～9の数字が手書きで書かれた画像とラベルのデータです。画像はそれぞれ28×28ピクセルの大きさで、各ピクセルは灰色の度合いを表す0～255の値で表現されています（白は255、0が黒を表します）。ラベルのデータは整数で表現されています。
読み込んだデータは、x_train,y_train,x_test,y_testとして扱うことができます。

x_train, y_train は学習用データ、x_test,y_testは評価用データとなります。

###実装その2　データを観察する
データの内容を見ましょう。
__データサイエンスにおいてはデータの傾向や内容を事前にみておくことが重要です。必ず見ることにしましょう。__

```python:code
print('x_train.shape:', x_train.shape)
print('x_test.shape:', x_test.shape)
print('y_train.shape:', y_train.shape)
print('y_test.shape:', y_test.shape)
```

結果
x_train.shape: (60000, 28, 28)
x_test.shape: (10000, 28, 28)
y_train.shape: (60000,)
y_test.shape: (10000,)

MNISTのデータは70000枚分のデータですが、60000枚分が学習用、1万枚分が評価用のデータとなります。この後モデルを作り、学習していきますが、すべてのデータを学習に利用するのではなく、一部データを評価用として利用します。
x_train ・・・60000枚の画像データ（28×28）
x_test・・・10000枚の画像データ（28×28）
y_train・・・60000枚分のラベルデータ
y_test・・・10000枚分のラベルデータ

実際にデータの画像がどのようなものであるか確認します。

```python:code
plt.figure()
plt.imshow(x_train[0])
plt.colorbar()
plt.grid(False)
plt.show()
```

結果
![手書き文字.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659138/efae3c5c-2f90-72c9-b892-646675c177f6.png)

上記のような画像が表示されればOKです。

もう一つラベルデータの内容も確認しましょう。

```python:code
print(y_test)
```
結果
[7 2 1 ... 4 5 6]
上記のようなデータ構造になっています。

##まとめ
MNISTのデータに利用は簡単にできます。データをロードして内容を見るということで、この後のプログラムなどが理解しやすくなると思います。

###　2020年7月9日修正
ソースコードないで修正しました。tensorflow.python.keras.datasets　とimportを記載していましたが、tensorflow.keras.datasetsへと修正しています。動作に問題はありませんができるだけ現状で行われる記載に修正しました。
Javascriptで作る「シューティングゲーム開発入門」学習記

#Javascriptで「シューティングゲーム」を作る方法を学ぶ
「ゲーム開発」は「ゲームエンジン」を利用して行うのが主流だと思っていたけど、「Javascript」で作られた「シューティングゲーム」を見てからは、「自分も作ってみたい!」と思い始めたので、作る方法を学ぶことにしました。
## 「シューティングゲーム」作りに必要な機能
「横スクロール型」のゲームを想定すると「必要な機能」は、

- 「自機・敵・ミサイル」などの座標位置の管理
- 「自機と敵」「ミサイルと敵」の当たり判定
- 「ゲームスコア」の管理

などですが、他にも

- 自機
- 敵
- 背景
- スコア

などの「画像素材」が必要になります。
デザインセンスが「ゼロ」なので、これが一番の問題だったり・・・

## 「シューティングゲーム」の機能の作り方

既に作り方は公開されていて、

↓こんな感じのシューティングゲームが作れます。
![シューティングゲーム](https://www.programming-fun.net/assets/images/top/simple_app_dev_3.gif)

機能がすごくシンプルなので、アレンジしていろいろと機能を追加していきたい。

例えば、

- ミサイルの弾道を変える
- 敵の種類を増やす
- 動きに追従するサブ機を追加する
- ボス敵を作る

など、どんどんやりたいことが増えてきました。

想像していたよりプログラムがシンプルだったので、いろいろ触りながら学んでいきたいと思います。
[→シューティングゲーム開発](https://www.programming-fun.net/article/article_93.html)
transitionの復習

#はじめに
cssのtransitionについて勉強したので復習としてまとめました。
Web制作やる人は押さえておきたいプロパティです。

#transitionの例
transitionの使い方は以下のようになります。（一例）

```
// transitionは1行でまとめると、
transition: all 1s ease 2s;

// transitionを構成する詳細プロパティ
transition-property: all; // 変化対象のCSS
transition-duration: 1s; // 変化の開始から終了までの時間
transition-timing-function: ease; // 変化の仕方
transition-delay: 2s; // 変化がいつ始まるか(遅延)
```

#まとめ
transitionは忘れやすいプロパティなので、復習としてまとめました。
明日も頑張ります。
[PHP]Guzzleの基本的な使い方をパブリックAPIと絡めて説明してみる

#今回の題
最近、API系の記事を３連投しました。
１回目→[[PHP] Zoom APIを利用してミーティングを作成する]
(https://qiita.com/kuzira_vimmer/items/d64f15447cb556eafd3b)
２回目→[[PHP] YouTube APIの利用（動画情報の取得）]
(https://qiita.com/kuzira_vimmer/items/dfd9f4febaec11851c06)
３回目→[[PHP] Messaging APIを使ったLINEbotで色々試してみる]
(https://qiita.com/kuzira_vimmer/items/ad485a9365c2c23f0465)

そして、１回目、２回目の投稿で**「Guzzle」**という、HTTPリクエストをシンプルな記述で行える大変便利なライブラリを使用しました。
今回は、この**Guzzleの基本的な使い方をAPIと絡めて**まとめていきます。

#インストール
Guzzleは以下のコマンドでcomposerを通して簡単にインストールすることができます。

```terminal
$ composer require guzzlehttp/guzzle
````

いや、まずcomposerが無いよって人は先にこれです。

```terminal
$ curl -sS https://getcomposer.org/installer | php
```

参考　[Guzzle公式 インストール手順]
(http://docs.guzzlephp.org/en/stable/overview.html#installation)


#基本的な使い方

- インスタンスの作成

```php
<?php
require('vendor/autoload.php');

use GuzzleHttp\Client;

$client = new Client();

```
composerのオートロードでvendor配下のライブラリをロードし、useを使ってエイリアスを作成。
Clientオブジェクトのインスタンスを変数$clientに作成します。


## 例：パブリックAPIにGETリクエストしてみる

アクセストークンを必要としないパブリックAPIを探してきましたのでそれを利用します。
仮想通貨取引サイト「bitFlyer」が公開しているパブリックAPIです。
[bitFlyer APIリファレンス](https://api.bitflyer.jp/docs/api)

####APIについて解説

APIにはエンドポイントという、APIにアクセスするためのURIがあり,
APIを使用するときはまず対象のAPIのリファレンスを読みエンドポイントを探します。
これから使用するbitFlyerのパブリックAPIのエンドポイントも、[bitFlyer APIリファレンス](https://api.bitflyer.jp/docs/api)に載っています。

見ると、bitFlyerでの現在のビットコインの情報各種を取得できるエンドポイントがありました。
これ⬇︎
**https://api.bitflyer.jp/v1/ticker**

マーケットの一覧を取得できるエンドポイントもありました。
これ⬇︎
**https://api.bitflyer.jp/v1/markets**
※ブラウザからアクセスしてもjson形式で表示されるのでアクセスして確認してみてください。


比べて見てみるとこのURIの違いは、
`https://api.bitflyer.jp/v1`以下のパスが、
「ticker」なのか
「markets」なのか、
だけです。
Guzzleは、この共通のURI`https://api.bitflyer.jp/v1`の部分をbase_uriとしてインスタンス作成時の引数として配列で受け取ります。

```php
$client = new Client(['base_uri' => 'https://api.bitflyer.com/v1/']);
```

そしてそれ以下の、「ticker」や「markets」などのパスは、requestメソッドの第２引数として渡します。第１引数はそのリクエストのメソッドを指定します。

```php
$response = $client->request('GET', 'ticker');
```
帰ってきたリクエストのbodyを確認するにはこう。

```php
$response = $client->request('GET', 'ticker');
$result = $response->getBody()->getContents();
```
###ビットコインの情報各種を取得するコードの完成形
```php
<?php
$client = new Client(['base_uri' => 'https://api.bitflyer.com/v1/']);
$response = $client->request('GET', 'ticker');
$result = $response->getBody()->getContents();
print_r($result);
```
これでOK。


#curlでやるとこんな感じ

```php
<?php
$url = 'https://api.bitflyer.jp/v1/ticker';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
$result = json_decode($json, true);
print_r($result);
curl_close($ch);
```

#一言
本当に基本的な部分だけまとめてみました。
もっと複雑なリクエストも行えますので、興味のある方はぜひ調べてみてください！！

#参考
[Guzzle 公式](http://docs.guzzlephp.org/en/stable/index.html)
ubuntuのshとbashで環境変数内の改行記号\nの扱いが違う

ホストからdockerコンテナに環境変数経由でjsonデータを渡し、echoとリダイレクトでファイル化してアプリから読み込もうとした。
結果、以下のエラーが発生。
> Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value

原因は、jsonの中に入っていた環境変数`\n`を、shのcatでファイル化したこと。
shではなくbashにしたら解決した、という話。

# shとbashの比較

ホストからコンテナに環境変数経由で`\n`が入ったjson文字列を渡し、echoで表示してみる。

## bashの場合

```sh
$ docker run -e TEST="{ \"value\":\"hoge\nhuga\npiyo\" }" -it ubuntu /bin/bash
root@36d386fa2f27:/# echo ${TEST}
{ "value":"hoge\nhuga\npiyo" }
```

jsonとして正しいフォーマットを維持したままファイル化できる。

## shの場合

```sh
$ docker run -e TEST="{ \"value\":\"hoge\nhuga\npiyo\" }" -it ubuntu /bin/sh
# echo ${TEST}
{ "value":"hoge
huga
piyo" }
```

このままリダイレクトしてファイル化し、アプリを読み込むと、不適切な改行でエラーになる。

bashからshに切り替えても同じように壊れてしまうので、shは取り出すときに`\n`をエスケープしてくれない様子。

```sh
$ docker run -e TEST="{ \"value\":\"hoge\nhuga\npiyo\" }" -it ubuntu /bin/bash
root@3dd58b596f66:/# echo ${TEST}
{ "value":"hoge\nhuga\npiyo" }
root@3dd58b596f66:/# /bin/sh
# echo ${TEST}
{ "value":"hoge
huga
piyo" }
```

# ちなみにCentOSの場合

```sh
$ docker run -e TEST="{ \"value\":\"hoge\nhuga\npiyo\" }" -it centos /bin/sh
sh-4.4# echo ${TEST}
{ "value":"hoge\nhuga\npiyo" }
```

CentOSであれば、shでも特に問題なくjsonが復元できる。
他にも、Debian系であってもイメージによっては普通に動いた。

変なところでハマってしまった。
Vuex StoreのModule分割

# はじめに
Vuex便利ですよね！Vueでサービス作る上で欠かせない機能だと思います。
ただ規模が大きくなるにつれ肥大化が否めません。
そこでstoreをmoduleという単位で分割する方法、さらにそれらを別ファイル管理する方法を記載します。

# module管理
まずmoduleで区切っていないストアの例を見てみましょう

```js:src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    userId: '',
    username: '',
    introduction: '',
    postArticles: [],
    notices: [],
    articles: [],
    articleId: '',
    popularArticles: [],
    searchAricles: [],
    followUsers: [],
    star: 0,
    help: [],
    topCarousel: [],
  },
  mutations: {
    saveUserInfo(state, userInfo) {
       ...
    },
    saveArticles(state, articles) {
       ...
    },
    saveStar(state, star) {
       ...
    },
    ...
  },
  actions: {
    loadUserInfo(context, authInfo) {
       ...
    },
    loadArticles(context) {
       ...
    },
    postArticles(context) {
       ...
    }
    ...
  },
  modules: {
  }
})
```

いかがでしょうか？
現状`ユーザー情報`, `記事情報`, `その他資材情報`が入り乱れている状況です。
まだなんとなく追えますが、さらに機能追加された場合確実に訳が分からなくなります。

そこでModule区分です、上記ストアを機能事に分離できます。
分離することでどこになんの機能があるのか一発でわかるためコードのみやすさが格段に上がります。
また1ファイルあたりのコード量が増える懸念もあるので、Moduleごとにファイルを分けることもオススメです。

以下のような感じです

```
// ファイル構成
src/store/index.js // modulesの読み込み
src/store/modules //modulesの設置
```

```js:src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import { user, article, material } from './modules';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    user,
    article,
    material,
  },
});
```

```js:src/store/modules/index.js
import user from './user';
import article from './article';
import material from './material';

export {
  user,
  article,
  material,
};
```

```js:src/store/modules/user.js
export default {
  namespaced: true,
  state: {
    userId: '',
    username: '',
    introduction: '',
    followUsers: [],
    star: 0,
  },
  mutations: {
   ...
  },
  actions: {
   ...
  },
};
```

```js:src/store/modules/article.js
export default {
  namespaced: true,
  state: {
    postArticles: [],
    articles: [],
    articleId: '',
    popularArticles: [],
    searchAricles: [],
  },
  mutations: {
   ...
  },
  actions: {
   ...
  },
};
```

```js:src/store/modules/material.js
export default {
  namespaced: true,
  state: {
    help: [],
    topCarousel: [],
    notices: [],
  },
  mutations: {
   ...
  },
  actions: {
   ...
  },
};
```

このように区分することで今後のストアの増加にも対応できます。
現時点で必要なさそうでも導入は早めが楽です、是非導入のご検討いかがでしょうか？
Railsでhtml.erbのclassを条件付きで追加する方法



#概容


下記のクラスに「ある条件」の時だけクラスを追加したいとする。



```ruby 

<div class="container">
</div>
``` 

例えば今回は`users_controller`の時だけクラスを追加するとする。
その場合の条件式は下記のようになる。

```ruby

<div class="container<%= ' user-container' if controller_name = 'users' %>">
</div>
```

###※注意
追加したいクラス名の先頭文字の前はスペースを開けること。

```

正しい： <%= ' user-container' if・・・
間違い： <%= 'user-container' if・・・
```


このような条件付きで`class`を追加することによってその条件下のみでCSSでスタイルの変更や上書きができるようになるのでぜひ覚えておきたい。
productionとdevelopmentをなぜ使い分けるのか

## railsになんでわざわざdevelop（開発環境）とproduction（本番環境）を使い分けているのか判明したので記録

相変わらず表面的な知識なので、誰かツッコミを入れてくれると嬉しいです。
それではいってみよーーーーーー！！！！！

###development（開発環境）
- 長所

エラーが発生すれば、詳細を表示してくれたりする。

- 欠点

詳細を表示してまうと、ソースコード情報が外に漏れちゃうからセキュリティ的な脆弱性がある


###production（本番環境）
- 長所

エラーが発生してもコードの詳細を表示しいひんから、安全性・安定性が高い

- 欠点

エラーが起こっても、「何か例外が発生したよ」ぐらいしか教えてくれない
（最初どうやってエラー見るねんって焦った）


###まとめ
セキュリティの観点から、本番デプロイ時には**production**でrailsを動かす必要があるんやね！
初心者が書く！macOS catalina に postgreSQL をインストールしてrails6.0.3.2で使えるようにするまで

プログラミングとmacの初心者です。
わからないなりに、色々調べて非常に時間を要したので
自分の覚書として念の為に書いておこうと思った次第ですが、
もし間違った記載など有りましたら玄人の方にご指摘いただけると本当に助かりますm(-_-)m
玄人以外の方も、出来ないなどご相談があれば、可能な限り対応します。※可能な限りですよ^^;
宜しくおねがいします。

---
## まずはhomebrewでpostgresqlをインストールして初期設定
ターミナルで以下を実行。場所はどこでも良いみたいです。
私は前に作ったprojectsフォルダで実行しました。
この後の作業は特に記載がなければ全てターミナルで行っています。

```
% brew install postgresql
```
そして以下が初期設定らしいです。

```
% initdb /usr/local/var/postgres -E utf8
```

## 起動して設定確認
まずは起動。

```
% brew services start postgresql
```
以下でEncodingがUTF8になってればOKだそうです。ひょっとしたら初期設定しなくてもなってるのかも？？

```
% psql -l
```
そして終了。

```
% brew services stop postgresql
```
## ここはpostgreを使いやすくする設定（だそうです。）
ホームフォルダ直下にある　.zshrcをvscodeで編集しました。
具体的には以下を追記。

```
export PATH="/usr/local/opt/postgres:$PATH"
export PGDATA="/usr/local/var/postgres"
```
そしてターミナルから以下を実行すればpostgreが起動します。

```
% source ~/.zshrc #変更した設定を適応。
% postgres
```
LOG:　〜
LOG:　〜
LOG:　〜
みたいな画面ならOKだそうです。
control+cで止まります。

## ここからはrailsの設定です。
rails _6.0.3.2_ new コマンドで好きなアプリを適当に作って下さい。ただしもちろん
 -d postgresql　を忘れずに^^

.gitignoreにdatabase.ymlなどこのタイミングで追加して
その後にローカルとリモートのリポジトリを作ろう！

configフォルダ内のdatabase.ymlの設定とデータベース作成権限を持ったuserの作り方
※<任意のusername>は好きな名前です。私は今回、rootにしました。

```ruby:config/database.yml
default: &default
  adapter: postgresql
  encoding: utf8 #utf8に変更
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <任意のusername> #追加
  password: #追加
  host: localhost #追加
```

```
# ターミナル
% brew services start postgresql #まずは起動
% createuser <任意のusername> -d # 消すとときは dropuser <任意のusername>
```

ここまで終わったら % rails db:create (もちろん任意のフォルダで)でできると思います。

## おすすめGUI
私にはPosticoというソフトが使いやすかったです。
無料で使っていますが、そんなに高くないので
購入してもいいかもしれません^^
完全無料のPSequelは私にはうまく使えませんでした^^;


## その後にあったエラー対処法
postgres -D /usr/local/var/postgres
で、バージョンを確認
brew postgresql-upgrade-database
でアップデート
$ npm run watch しようとしたら Sorry, there's a problem with nodist. Couldn't resolve node version ～～～と出たときの対処法

# 課題
```
$ npm run watch
```
しようとしたら
**Sorry, there's a problem with nodist. Couldn't resolve node version spec %s: %s 4.5.0 Couldn't find any matching version**
と怒られた。

なんでだろうと調べたりいろいろ試したりしましたが小1時間ほどハマり心優しい同僚に助けてもらったので覚書しておきます。
池田さんありがと。

# 対処法

**1. nodeのバージョンを確認する**

```
node -v
v0.0.0
```

**2. .node-version（node-dev-env/.node-version）を開いて記載されているバージョンを確認する**

私の場合「v11.13.0」と記載されていました。
このバージョンとnode-v したときのバージョンを合わせてやります。

**3. 今適用されているnode.jsのバージョンを確認**

```
$ nodist
  (x64)
> 4.5.0  (C:\xampp\htdocs\hogehoge.jp\node-dev-env\.node-version: v4.5.0)
  10.15.1  (global: 10.15.1)
  11.0.0
  11.13.0
``` 
つまり現在のnode.jsのバージョンが4.5.0になってしまっている。（私の場合11.13.0も一応存在はしました）


**4. v11.13.0がなければインストール**

``` 
$ nodist + v11.13.0
``` 

**5. v11.13.0がインストール済になったので切り替える**

```
$ nodist v11.13.0
v11.13.0
v11.13.0 (global)
```

 
**6. node.jsのバージョンが切り替わったか確認しましょ**

```
$ node -v
v11.13.0
```
これで切り替え完了！

**7. 頼む、動いてくれ！**

```
$ npm run watch
```

**8. それでも動かなかったとき**

魔法の呪文
（使用中の node にあったバージョンの npm をインストールしてくれます）

```
$ nodist npm match
```
**9. それでもまだ動かなかったとき**

おまじない
（npm config スクリプトの設定でパスを先頭に追加）

```
$ npm config set scripts-prepend-node-path true
```
からの

```
npm config list
```

で

```
; userconfig C:\Users\whatthehell\.npmrc
scripts-prepend-node-path = true
```
が追加されていることを確認します。
そして

```
npm run watch
```

# 終わり
ここまでの手順でわたしは動きました。


#### 参考：
nodist 環境下で npm script 使用時にエラー – blog
[https://www.namu-ws.com/blog/dev/nodist-npm-script-error](https://www.namu-ws.com/blog/dev/nodist-npm-script-error)

npm がどうしてもエラーになってしまったら - Qiita
[https://qiita.com/tana08/items/d50212a1919308cc1480](https://qiita.com/tana08/items/d50212a1919308cc1480)

Laravel-Mixコンパイル時のcode ELIFECYCLEエラーに対応する - Qiita
[https://qiita.com/ishizukih/items/9673e709832dacaa5155](https://qiita.com/ishizukih/items/9673e709832dacaa5155) 

nodistでnode.jsのバージョン管理をする | IT王子の技術ブログ
[https://www.it-ouji.com/2019/10/26/nodist%E3%81%A7node-js%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%92%E3%81%99%E3%82%8B/](https://www.it-ouji.com/2019/10/26/nodist%E3%81%A7node-js%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%82%92%E3%81%99%E3%82%8B/)
Jetson SDK ManagerをUbuntu 20.04で使う(Jetson TX2)

# SDK ManagerがUbuntu20.04に対応していない

![164535.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414948/1b2af97c-2b3e-50f0-6506-84a45802d4af.jpeg)

みんな大好きJetson

Jetson TX2等のNvidia系エッジデバイスの初期設定を行う際，Linux OSを導入したHost PCよりJetsonをセットアップするのですが，SDK ManagerがUbuntu 20.04に対応していません(2020/7/8現在)．Ubuntu 18.04あたりを利用すれば問題なく動くのですが，手元に20.04しかなく，新たにインストールするのも面倒なのでUbuntu 20.04でSDK Managerを利用する方法を探りました．
結果的にはUSB BootででもUbuntu 18.04を用意した方が早かった気もしますが手順的には難しくなかったので紹介します．

# 準備
セッティングの流れ等はUbuntu 18.04を利用する場合と全く同じです．SDK Managerの導入やTX2と
Hostの接続などは適宜調べて進めてください．

# 解決策
`/etc/os-release` を弄れば解決します．VERSION_ID の項目を20.04から18.04に変更してやればOKです．
デフォルトではUbuntu20.04では

```
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```

のようになっているのを

```
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="18.04" # 変更
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

```

のように変えてやればSDK Managerが起動します．
自身のOS versionを偽装している訳ですのでかなり強引な策ですがこれで一応なんとかなります．

# 他の問題
Jetsonのセットアップを進めていると OS Flashの段階で`/usr/bin/env` にPythonがないと怒られてしまいました．この問題にはどうやらPython2系をホストにインストールすることで解決するそうです．
現状aptでpythonを入れると2系列が入るので

```
$ sudo apt update
$ sudo apt install python
```
でPython環境をインストールしてやります

確認

```
$ python -V
Python 2.7.18rc1
```

Python2.7が入っているのが確認できます．
ここまで対応すれば，無事エラーなくセットアップを終えることができました．

# 余談
フォーラムを見る限りSDK Managerが20.04に公式対応するのは「検討中だが計画にない」とのことです．それにしてもJetsonは初期設定が面倒ですねえ，nanoだともっと楽にできたりするのでしょうか．
Community Edition A2019.14 リリースノート和訳

気まぐれですが、新バージョンが出たので、気分転換にリリースノートの新機能の部分だけ和訳します。
非公式なノートなので、[原文](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/release-notes/release-a2019-14.html)も出来るだけチェックするようにしてください。


#新機能
##複数のBotの同時編集が可能に
レコーダーパッケージが複数のデスクトップセッションに対応しました。同じControl Room（サーバー）の複数のWebブラウザのタブ、もしくはウィンドウを開いて、複数のBotを同時に編集することが出来ます。

##ユニバーサルレコーダーの新機能
ユニバーサルレコーダーがSAP バージョン730,740と760 patch 5に対応し、オブジェクトをキャプチャできるようになりました。
複数の接続（ユーザーアカウント）やセッションを1度の接続で使用するようなSAPアプリケーションにおいても自動化が出来るようになりました。
Google Chromeブラウザにおいて、ズームレベルが100%でなくてもオブジェクトをキャプチャーし記録＆実行できるようになりました。

##「データベース」パッケージの新機能 (Service Cloud case ID: 00537047)
接続アクションでExcelデータベースに接続できるようになりました。
Export to data tableアクションでデータベースからレコードを取得し、テーブル変数に格納できるようになりました。

##Active Directlyパッケージが更新されました
グループや組織をまたいでのユーザ管理が出来ます。
ユーザーやグループ、OU(Organizational Unit)の作成、編集、削除などといった中央管理が可能になります。

##Excelセルの表示形式に対応しました。（数値、パーセンテージ、通貨、科学、日付など）
「Excelの基本操作」の「1つのセルを取得」や「複数のセルを取得」アクションと、「Excelの各行に対して」と指定したループを使って、表示形式が設定されたセルから値を取得することが出来るようになりました。
例えば、通貨の表示形式のセルから値を取得する場合、通貨の記号が保持されます。

##Excelの指定したレンジに対して自動化タスクを実行する事ができるようになりました。
「セルを設定」「セルに移動」「セルを削除」アクションにおいて、指定したレンジのセル全てに適用することが出来るようになりました。

##PDFパッケージアクションの追加
複数のPDFファイルを1つのPDFファイルに統合することが出来ます。

##ターミナルエミューレーターパッケージが、チェコと米国2コードページ（文字コード）に対応しました
「接続」アクションで、使用するターミナルタイプやコードページが選択できます。

##レコード変数がスキーマに対応しました
新たにレコード変数を作成する際に、スキーマを設定できるようになりました。これにより各フィールドの順番や格納するデータの型を定義することが出来ます。

##Bot Agentの自動アップデートが設定できるようになりました
Control Roomのadmin権限を持ったユーザーが、各デバイスのBot Agentを自動的に新しいバージョンにアップデートするかどうか、設定できるようになりました。
旧バージョンでは、各デバイスのBot Agentをアップデートするのに、それぞれのデバイスにログインして作業する必要があり、より長いダウンタイムをもたらしていました。

Enterprise A2019 Cloud版とCommunity Editionでは、Bot Agentの自動アップデートオプションはデフォルト設定でオンになっています。
オンプレミス版ではデフォルト設定ではオフになっています。

##Ifとループパッケージに新しい「条件」が追加されました。
辞書＞キーを確認 を使用すると、指定したキーが特定の値と比較して、指定した条件に該当する場合のに実行されます。
※ループはLoop TypeがWhileの場合のみ使用可能

##CSV/TXTアクションとファイルに記録アクションで、新しいエンコードに対応しました。
UTF-16LE エンコードオプションにより、byte order mark (BOM)付きUnicodeに対応できるようになりあした。
CSV/TEXT > 開く アクションで、このオプションを設定すると、Read(現在"既読"という名前のアクション）やループアクションで読み取る際にBOMを無視してくれるようになります。
また、ファイルに記録アクションでこのオプションを選択すると、ファイルの先頭にBOMを付与してくれます。

## Run as user to default device mapping in Workload automation (Service Cloud case ID: 00563115)
Workload automation now allows 1:1 mapping of the Run As user with default devices when these devices are part of a device pool. Therefore, you can select default devices that are mapped to a Bot Runner to avoid auto-login failures in environments where the security policy does not allow for auto-login, or the devices are outside of the domain.
※こちらは手元の環境で試せなかったので、ひとまず保留。
C++命名規則一覧

| 対象                   |ルール                                             | 例                   |
|:----------------------:|:-------------------------------------------------:|:--------------------:|
| ファイル名             | 全小文字 + アンダースコア区切り                   | my_favorite_file     |
| 型名                   | 最初大文字 + 大文字区切り                         | MyFavoriteClass      |
| 一般変数               | 全小文字 + アンダースコア区切り                   | my_favorite_value    |
| クラスのデータメンバ   | 全小文字 + アンダースコア区切り+末尾アンダースコア| my_favorite_member_  |
| 構造体のデータメンバ   | 全小文字 + アンダースコア区切り                   | my_favorite_member   |
| 定数                   | 最初k + 次大文字 + 大文字区切り                   | kMyFavoriteConst     |
| 関数                   | 最初大文字 + 大文字区切り                         | MyFavoriteFunction   |
| 名前空間               | 全小文字                                          | myfavoritescope      |
| 列挙型                 | 最初k + 次大文字 + 大文字区切り                   | kMyFavoriteEnum      |
| マクロ                 | 全て大文字 + アンダースコア区切り                 | DONT_USE_MACRO       |


[Google C++ スタイルガイド](https://ttsuki.github.io/styleguide/cppguide.ja.html) に準拠
ADFS：証明書利用者のメタデータの更新ができない


## 現象
ADFSとOffice365のフェデレーションをセットアップしたところ、Microsoftの証明書利用者信頼「Microsoft Office 365 Identity Platform」の左側に「×」印が表示される。
どうやらフェデレーションメタデータの監視に失敗したようで（メタデータURLから自動更新する設定だった）、とりいそぎ確認のため「URLのテスト」を実行する。
すると今度は「フェデレーションメタデータの取得に失敗。プロキシサーバを確認してください」とのエラーメッセージ。
えっ？！プロキシ？？
うーん。。。WAPも設定していないし、IEからメタデータのURLは叩けるんだけどなあ。。。


## 原因
WindowsServer2016の問題でした。
>Windows Server 2016の10月リリース（ビルド：10.0.14393 N / Aビルド14393）を使用している場合、証明書利用者信頼を追加するか、メタデータファイルで証明書利用者信頼を更新しようとすると、奇妙なエラーメッセージが表示される場合があります。HTTPsソースからであっても、以前に保存したローカルXMLファイルであっても、次のメッセージが表示されます。
[Microsoft公式ドキュメント](https://docs.microsoft.com/en-us/archive/blogs/pie/adfs-2016-cannot-addupdate-relying-party-from-the-gui-from-metadata-files)

## 解決方法
PowerShellで直接ADFSの設定しちゃいましょう！
GUIからの操作のみこのエラーが発生するみたいです。

##### 証明書利用者信頼の追加（オンラインメタデータ）
```
Add-AdfsRelyingPartyTrust -Name "追加する証明書利用者の表示名" -MetadataUrl "https://[証明書利用者信頼のドメイン]/app/federationmetadata/2007-06/federationmetadata.xml"
```
##### 証明書利用者信頼の追加（ファイルメタデータ）
```
Add-AdfsRelyingPartyTrust -Name "追加する証明書利用者の表示名" -MetadataFile "C:\Temp\FederationMetadata.xml（メタデータの置き場所）"
```
##### 証明書利用者信頼の更新
```
Update-AdfsRelyingPartyTrust -TargetName "更新する証明書利用者の表示名" 
```



## おわり
「プロキシサーバを確認してください」と出ているもんだから、プロキシ関連の設定をすみずみまで確認してしまい、大分足踏みさせられました。
ちなみに今回はすでにADFSに登録されている証明書利用者のメタデータ更新でエラーになりましたが、新しく証明書利用者を追加しようと[ADFSの管理]>[証明書利用者信頼の追加]ウィザードで操作しても、メタデータのインポート時に同様のエラーが発生するみたいです。
Windows10(2004)のWiFiではTKIPが無効になっているっぽい?

# Windows10(2004)のWiFiではTKIPが無効になっているっぽい?

## 環境
+ Windows10 Pro (1909 &#8594; 2004)
+ 無線LANルーター(2005年発売。WPA2には非対応)

## 現象
+ Windows10を1909から2004にアップグレードしたら、WiFiがつながらなくなった。
+ タスクトレイアイコンからSSIDは選択できるものの、キーを入力しても「接続できません」となるだけ。
+ もちろんSSIDとキーに間違いないことは何度も確認している。
+ ルーター側の無線暗号化を解除しても不変。

## 調査結果
実はハードウェア側のWiFiドライバ周りに少し問題があり、アップグレード時にWiFiの設定が消えていたので最初はそちらを疑っていたが、ドライバを入れ替えても解決できなかった。

WiFi接続先を手動で設定しようとしてみたら、WPAが選択できずWPA2のみなので、タイトルの通りの疑念を抱いた。

公式発表にはないが、[Windows10がTKIPを切り捨てる](https://meterpreter.org/microsoft-will-completely-ban-wi-fi-wep-and-tkip-in-windows-10/)という話は、噂レベルでは存在するようだ。

## 対応・検証
無線LANルーターをWPA2(AES)対応のものに交換したところ、復旧した。

その後もキーを入力しても「接続できません」という表示が出ることがあり、他にも原因がある可能性が出てきた。ルーター側のSSIDを非公開にしていると再接続に支障が出るようで、そちらの方に原因があるかもしれない。

反復しているうちに再接続に成功することがあり、一時的な問題だったかどうかは分からない。だが、ルーター側がTKIPだったときにはいくら繰り返しても接続できない状態から改善しなかったし、接続が成立したルータの暗号化設定をAESからTKIPにしたら、はっきりと暗号化強度が弱いと表示され接続できなくなったので、TKIPからAESにしたことには効果があったのではないかと考えている。

## 試さなかったこと
たまたま使わないWPA2対応ルーターがあったが、なければ無理矢理[TKIPを指定して接続する方法](https://qiita.com/jansnap/items/c6ed5b22e080910658a4)を試したかもしれない。

## 考察
タスクトレイアイコンからではなく手動で接続先を設定する時にWPAが選択できなくなっているのは、[Windows8.1の時代から](https://answers.microsoft.com/ja-jp/windows/forum/all/windows81-wpa/5da9907f-5515-407e-9a3a-506808897124)既にそうなっていたらしい。それでもこれまでは、タスクトレイのアイコンをクリックして表示される一覧から設定すればWPA-PSK(TKIP)でも自動判別して接続してくれたが、これからはそういう親切?は期待できないということになる。

WPA-PSK([TKIP](https://ja.wikipedia.org/wiki/Temporal_Key_Integrity_Protocol))はもはや[安全でないとされている](https://ascii.jp/elem/000/004/004/4004070/)ので、SSLが廃止されてTLSに移行したようになるのはやむを得ないとは思う。不親切と言うよりMicrosoftの~~余計な~~親心ということかもしれない。

15年前のものと思われるルーターをまだ使っていた方も大概だと言われても仕方がないものの、ネットワーク回線が不通になったPCでは原因の検索すら困難になることを考えれば、アップグレード時にWiFiの接続を調べて警告するぐらいのことはして欲しいと思った。


## 改訂履歴(表現の修正を除く)
+ 2020/07/08: 初版
+ 2020/07/09: 全体的に少し加筆・改訂
+ 2020/07/10: 環境依存の問題の可能性
+ 2020/07/12: 検証などを追加
Unityのwebcamtextureが遅すぎる問題の解決策

#Unityのwebcamtextureが遅すぎる

webcamtextureで取得した映像がものすごく遅延するので，Python経由でWebカメラの映像を取得してみました
明らかに遅延減ってるし画質も良くなった気がします
気が向いたら加筆します


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">webcamtextureで取得した映像がものすごく遅延するので，Python経由でWebカメラの映像を取得してみました<br>明らかに遅延減ってるし画質も良くなった気がしますね<br>左：Unity標準のwebcamtextureで取得した映像，右：PythonでFlaskサーバ立ててOpenCVで取得した画像をストリーミングした映像 <a href="https://t.co/1IvTWKMX8Z">pic.twitter.com/1IvTWKMX8Z</a></p>&mdash; さいんす(signs) (@signs0302) <a href="https://twitter.com/signs0302/status/1270673090129756160?ref_src=twsrc%5Etfw">June 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Flatpakアプリケーションで日本語入力ができない? 原因は、Fcitx。

私の今の環境は、Lubuntu 18.04である。

Flatpakは、GNU/Linux環境用のパッケージマネージャである。ソフトウェアをサンドボックス内で実行できることから、開発者は、個別のディストロ用に別々のパッケージを作る必要がないため、UbuntuやDebianで、aptを使ってインストールするより、最新版のソフトウェアを取得できる場合が多いのだ。

しかしながら、Flatpakを利用したソフトの多くで、日本語入力ができない現象に見舞われた。あとからというわけではなく、Flatpakアプリをインストールして、最初からである。

ちなみに、私は、Lubuntuに、IceWMを入れて使っているため、一部画像が通常のLubuntuと異なる。

#原因は、Fcitx
原因は、Fcitxであった。
どうやら、Fcitxの持つ仕組みと、Flatpakのサンドボックス特性が、相性が良くないらしい。

#簡単な解決法 : IBusに切り替えよう。
Fcitxでダメなら、IBusではどうだろうか。IBusに切り替えたところ...なんと正常に使えるようになった。よって、FcitxからFcitxに乗り換える手順を説明する。

##IBus (と、それ用のMozc)のインストール

```shell
sudo apt install ibus ibus-mozc
```

##インプットメソッドの設定
まず、インプットメソットの設定を開く。端末を開き

```shell
im-config
```

すると、以下のようなウィンドウが開く
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648261/2a8873e5-340e-3f99-e701-4b0876611788.png)
OKを押して進もう。すると
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648261/d5a164d2-7428-3a7f-85ef-5ebaa0ef18be.png)
推奨はされていないが、とりあえず、Yesを選択。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648261/bf994113-fa2e-3d66-0f64-6f7d5b733ae6.png)
こうなるので、ibusを選択してOK
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648261/ca653357-05fc-cecc-e852-6c5d7f2093f2.png)
最後に、こうなる。これで、基本設定は完了だ。適用するには、一旦ログアウトして、再度ログインすれば良い。

###再ログインしたら
ログインすると、右下のバーに、キーボードのアイコンが現れているので、それを右クリック。そして、設定を開く。
設定画面になるので、「入力メソッド」タブに移動。「追加」を押して、一応、「日本語」キーボードを追加する。そして、英語キーボードを削除。

そして、とりあえず、テキストエディタでも開いて、入力しようとしてみよう。しかし...私の場合、英語配列のままだった。
この場合一旦ログアウトして、再度ログインすれば、ちゃんと日本語配列になっていた。半角/全角を押せば、日本語入力もできる。

#最後に
これで、Flatpakアプリにおいても、日本語入力が可能になった。

#Lubuntu 20.04では?
Lubuntu 20.04では、Fcitxでも、正常に日本語入力ができるようである。
もうじき、Lubuntu 18.04のサポートが終わるので、これを機に、20.04にアップグレードしてみてはいかがだろうか。ちなみに、Lubuntu 18.04から、20.04へのアップグレードは、大きな変更のため、update-managerによるアップグレードができない。そのため、新規再インストールとなる。
Docker&Rails環境で、gemを永続化させる

# 本記事について（お断り）

この記事は、しがないプログラミング初心者がお勉強よろしくプログラミング・技術に触れるべく、行ったことの備忘録として書き綴ったものです。ご了承ください。
ご指摘は甘んじて受け入れます🙇‍♂️


# 起こったこと

とあるプロダクトでおもむろに`docker-compose up`してたら、

```bash:
...
web_1  | Bundler::GemNotFound: Could not find gem 'rspec-rails' in any of the gem sources listed in your Gemfile.
...
myapp_web_1 exited with code 1
```

と怒って勝手に出て行ってしまった。
おかしい、確かにインストールしたはずのgemがないとは、、、

一度落として、再度`docker-compose build`すると問題なく動いた。
まあこれでもいいんだけど、毎回ビルドしてコンテナ起動するのは面倒だと思う。

調べてみると、volumeの永続化を行うことで、こうした問題が解消されるとのこと。

# docker-compose.ymlの修正

現在のファイルの中身。

```yml:docker-compose.yml
ersion: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

これを書き加える

```yml:docker-compose.yml
ersion: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
      - gem_data:/usr/local/bundle # <= ココと
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  gem_data: # <= ココ。
```

パスは、コンテナの中に入って確認できます。

```bash:
$ docker-compose exec web bash
$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 3.0.3
  - RUBY VERSION: 2.6.5 (2019-10-01 patchlevel 114) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/bundle
  ...（略）

```

これでgemを永続化する環境を構築できたことになります。
試しに、gemを追加、

```ruby:Gemfile
+ gem 'rails-erd'
```

その後、`bundle install`してみます。

```bash:
$ docker-compose exec web bundle install
```

そして、一度コンテナを削除した後に再度起動してみます。

```bash:
$ docker-compose down
$ docker-compose up
```

<img width="400" alt="Rails6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563494/fe8adc68-3108-ac58-e1bb-ebfa5e4f682d.png">

問題なくコンテナを起動できました！

コンテナ削除前にインストールしたgemもちゃんと入っています。

```bash:
$ docker-compose exec web bundle list |grep 'rails-erd'
  * rails-erd (1.6.0)
```


#参考
今回の作業にあたり、以下のページを参考にさせていただきました。とても勉強になりました。ありがとうございます🙇‍♂️

[https://nishinatoshiharu.com/datavolume-for-gem/](https://nishinatoshiharu.com/datavolume-for-gem/)
UiPath カスタムアクティビティでプロジェクトディレクトリを取得する話

#UiPath カスタムアクティビティでプロジェクトディレクトリを取得する話

UiPathで`Environment.CurrentDirectory`を設定すると、プロジェクトフォルダのパスが取れると思いきや
カスタムアクティビティの場合は、プロジェクトフォルダではなく、カスタムアクティビティが格納されている
nugetのフォルダが取れてしまい、予期せぬエラーに悩まされたので、忘れないうちに投稿します。

#お約束事項（免責事項）
この記事は2020年6月時点の情報を基に作成しております。
記事の内容は私個人の見解であり、所属する組織の公式見解ではありません。

## Environment.CurrentDirectory
### プロセスのプロジェクトの場合
繰り返しになりますが、UiPathでProcessのプロジェクトでは、
Environment.CurrentDirectoryを指定すると
Main.xamlが格納されているプロジェクトフォルダが取得されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/57b880ea-9914-1671-4286-34f8060fa550.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/a382dc17-216e-2389-d968-5f30933d0cc9.png)

### ライブラリのプロジェクトの場合
UiPathでLibraryのプロジェクトとして
Environment.CurrentDirectoryを指定すると
Studio実行上では、プロジェクトのフォルダが取得されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/40d1f53c-83ce-e564-6c45-80533e4e520c.png)

**そのため、問題が無いように勘違いしてしまいます。**

## 問題の表面化
問題が発生することに気づくのはここからです。

UiPathでカスタムライブラリーをパッケージ化し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/49a80346-1e4a-c81f-e8e9-56a6bbc83589.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/7cbec1a9-def9-7e6f-2a55-50611d21b382.png)

先ほどのプロセスのプロジェクトで、カスタムライブラリーを追加し
実行すると、以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/e72a5fe9-e800-5d28-e1f4-ee77e86150e2.png)

## 対策方法
やり方は、いろいろありますが私がお勧めする簡単なやり方を紹介します。

### 1. カスタムライブラリーのプロジェクトを開く
先ほどの、カスタムライブラリーのプロジェクトを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/991fb7c8-f17a-bb3f-1041-062e289736fe.png)


### 2. 引数を追加する
`In_ProjectPath`のように、引数を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/1a5aa7ac-7a15-e6b7-002e-281a2dc7ef87.png)

折角なので、注釈もつけてあげましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/90a61964-fa8c-e39e-742e-760dd70b8a04.png)

### 3. 既定値の設定
**ここが最大のミソになります。**
既定値に、`Environment.CurrentDirectory`を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/60f6205b-bcfd-2b32-81c9-02612bca7e36.png)

### 4. 引数の値を表示
最後に、メッセージボックスの内容を引数の値が表示されるように変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/4f6f0bb1-d250-08ae-fd07-d043701b071f.png)

## 実行
### (事前確認)ライブラリーのプロジェクトでStudio実行
変更内容を確認するため、ライブラリーのプロジェクトでStudioから実行します
ライブラリのプロジェクトフォルダーが取得されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/9d2fbc91-583b-61dd-eeef-72c3146db86b.png)

### プロセスのプロジェクトでStudio実行
本題のプロジェクトフォルダに切り替えて、修正したライブラリを更新し
カスタムアクティビティを使ってみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/8edc8915-04b5-2313-2c52-027a3460991c.png)

## まとめ
- Environment.CurrentDirectory は、必ずプロジェクトフォルダを示すとは限らない
    - プロセスのプロジェクトで実行した場合、プロセスのプロジェクトフォルダが取得できる
    - ライブラリーのプロジェクトで実行した場合、ライブラリーのプロジェクトフォルダが取得できる
    - **カスタムライブラリーを使用したプロセスプロジェクトを実行した時**に、プロジェクトフォルダでないライブラリが格納されたフォルダーが取得される
- 対処方法
    - ライブラリのカスタムアクティビティで、引数を追加し既定値に`Envoroment.CurrentDirectory`を設定する