OmniAICreator/Qiita-1.07M huggingface dataset:
mixamo→Unityへインポートしたモデルのテクスチャがない場合の対処法

実行環境はUnity2019.1.4
モデルに埋め込まれているはずのテクスチャが反映されてないぞ〜〜？？という人向け。
(mixamoからdlする時にwithout skin設定になっていたらそもそもだめなので、そこは要注意)

# まず結果から
- importしたassetのインスペクタを開いて、Materialsタブを開く
- Import Materialsにチェックを入れる
- Texturesの`Extract Textures...`を押す
- インポートしたアセットが入っている**フォルダ**(ここ重要)を選択する
- モデルに埋め込まれているテクスチャが反映される
- _やったぜ_

# 何に困っていたのか
- モデルにテクスチャが反映されていない
- pngファイルからメッシュぽいものを作成してあてようとしてみたり
- `extract textures`を試そうにもどのファイルも選択不可になってたしどうすりゃええんじゃ…

# どうしたら解決したか
やけくそでフォルダを選択してみたらいけた
~~早く言ってよ~~
ファイルサイズの大きいイベントログ（Event Log）の取得方法

#初めに
ログインユーザが数千ユーザいる大規模なSalesforce環境において、各ユーザが何の画面にアクセスしどのようなデータにアクセスしたかログの取得を要件として挙げている案件は少なくないはずです。

将来的にユーザ数が増え、ログが数十GBになった場合でも、Salesforceでは標準機能で分割（時間毎）と圧縮(gzip変換）の両方を利用することができます。
（ちなみに時間毎に分割する方法は、去年の６月にリリースされたとのことです。）

# Salesforceの標準機能
分割（日毎や時間毎）も圧縮（gzip形式）もログ種別やリクエスト毎に選択することができます。
Salesforce内で両方（時間別、日別）保存されておりますので、抽出条件で指定して選択することができます。
 
## SOAP Login機能でログイン
説明 ：SOAP API のLogin機能を使ってアクセス用のアクセストークンを取得する

```
curl -X POST -H "Content-Type: text/xml; charset=utf-8" -H "SOAPAction: login"  -d @login.xml https://test.salesforce.com/services/Soap/u/45.0
```

```login.xml
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance\">
  <env:Body>
    <m:login xmlns:m="urn:partner.soap.sforce.com" xmlns:sobj="urn:sobject.partner.soap.sforce.com">
      <m:username>#UserId</m:username>
      <m:password>#Password</m:password>
    </m:login>
  </env:Body>
</env:Envelope>
```

## イベントログ一覧取得
説明：インターバルが[時間毎]のイベントログファイルUrlを取得します。

```
curl -H "Content-Type: text/xml; charset=utf-8" -H  "Authorization:Bearer  {AccessToken}" https://{instance_url}.salesforce.com/services/data/v45.0/query/?q=SELECT+EventType+,+Id+,+Interval+,+Sequence+,+CreatedDate+FROM+EventLogFile+WHERE+Interval+=+'Hourly'+Order+by+CreatedDate
```
※ {AccessToken}は、SOAP APIで取得したトークンを使用してください。
※Attributes.urlにエンドポイントが設定されています。
 
##ログファイルダウンロード

```
curl -H "Authorization: Bearer {AccessToken}" -H "Accept-Encoding: gzip" -H "Content-Encoding: gzip" -H "X-PrettyPrint:1" -H "Accept-Charset: UTF-8" -o outputLogFile.gzip https://{instance_url}.salesforce.com/{イベントログ一覧取得のAttributes.urlの値}/LogFile
```
※gzip形式でダウンロードされますので、解凍処理が必要になります。

#最後に
いかがだったでしょうか？
Salesforce標準の機能を知っていれば簡単にダウンロードできます。
思い付きで突然振られたお客様からの質問でもササっと回答できたらスマートですね（笑）。
では

##参考リンク
[公式ドキュメント：1 時間ごとのイベントログ取得によるアクティビティの可視性の改善 (正式リリース)]
(https://releasenotes.docs.salesforce.com/ja-jp/summer18/release-notes/rn_security_em_eventlogfile_hourly.htm)
[公式ドキュメント：cURL を REST で使用して大きなイベントログファイルをダウンロードする]
(https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_event_log_file_download.htm)
[公式ドキュメント：イベントログファイルのダウンロードと視覚化]
(https://trailhead.salesforce.com/ja/content/learn/modules/event_monitoring/event_monitoring_download#Tdxn4tBK-heading4)
Mincraft-piにサバイバルモードのパッチ適用（Raspbian Buster）

Raspbian Buster環境でminecraft piのサバイバルモードのパッチを適用したので、その際の覚書です。

#■環境
モデル：ラズパイ 3B+
OS：Raspbian　Buster（July 2019）

#■サバイバルモードの導入手順
ターミナルを起動し、まずbsdiffをインストール。
`sudo apt-get install bsdiff`

パッチファイルのダウンロード先へ移動。
`cd /opt/minecraft-pi`

パッチファイルのダウンロード。
`sudo wget https://www.dropbox.com/s/iutdy9yrtg3cgic/survival.bsdiff`

パッチファイルを適用。
`sudo bspatch minecraft-pi mcpipatched survival.bsdiff`

パッチに実行権限を付与。
`sudo chmod +x mcpipatched`

libGLESv2.soのパスを通す。
`export LD_LIBRARY_PATH=/opt/minecraft-pi/lib/brcm/:LD_LIBRARY_PATH`
※コンソールから起動する場合、.bashrcにこのコマンドを追加しておくと、都度実行する必要がなくなります。

#■起動方法
ターミナルでサバイバルモードを起動する。
`/opt/minecraft-pi/mcpipatched`

#■アプリケーションランチャーからの起動設定
メニュー > 設定 > Main Menu Editorを開く。
ゲームのメニューに「新しいアイテム」を追加。
Name:Minecraft Pi Survival(名前は自由に設定できます）
Command:以下のコマンドを設定
`env LD_LIBRARY_PATH=/opt/minecraft-pi/lib/brcm/:LD_LIBRARY_PATH /opt/minecraft-pi/mcpipatc`

アイコンを設定する場合はこちら
/usr/share/pixmaps/minecraft-pi.png

これでランチャーからサバイバルモードが起動できるようになります。

#■参考サイト
https://www.fabshop.jp/mincraft%E3%80%80%E7%AC%AC%EF%BC%93%E5%9B%9E%E3%80%80pi-edition%E3%81%AE%E3%82%B5%E3%83%90%E3%82%A4%E3%83%90%E3%83%AB%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AF%E3%82%A2%E3%83%AA%EF%BC%9F/
https://blog.ko31.com/201710/raspi-minecraft-survival/
SVN(Subversion)とは何か + 用語解説

会社で初めてSVNを使用しているが、用語がよくわかっていないため調べたことをまとめます。

#SVN(Subversion)とは何か
オープンソースの集中型バージョン管理システム。正式名称はApache Subversion。
公式サイト：http://subversion.apache.org/

###バージョン管理システム
ソースコードや様々なデータを管理するために用いられるシステム。
特に複数人で行う開発現場では、一つのソースコードを複数人が操作し、**「誰が」「いつ」「何を」「どこを」**追加/変更/削除したかがわからなくなってしまう。何か障害が発生した場合に後からソースコードを遡ろうとしても上記のような履歴が残されていないと大幅な手間が発生する。それらを回避する仕組みがバージョン管理システムである。

###集中型（クライアント・サーバ型）
クライアント（要求側）とサーバ（提供側）の役割に分離するコンピュータネットワークのソフトウェアモデル。SVNではサーバで管理しているソースリポジトリに対し、クライアントから作業コピーを要求し受け取り編集して、またサーバに編集内容（差分）を送っている。

#主要な用語
###リポジトリ(repository)
ソースコードやファイルの変更内容を格納する場所
###リビジョン(revision)
リポジトリの状態を示すバージョンの番号。コミットする毎に1プラスされていく。
###チェックアウト(checkout)
リポジトリからディレクトリツリーの内容を取得する処理。「作業コピー」と呼ばれるディレクトリツリー構成がクライアント側に作成される。
###作業コピー(working copy)
チェックアウト実行の結果としてローカル環境に保持するディレクトリツリー構成。ユーザが取得した作業コピーに対して変更作業を行い、それをリポジトリに対してコミットすることで変更内容を反映させる。
###コミット(commit)
変更した作業コピーをリポジトリに反映させること。
###競合(conflict)
特定のファイルに複数のユーザが同時に変更を加えようした時に起こる現象。一般的にファイル編集前にロックをかけることで競合することを防ぐ。
###ロック(lock)
指定したファイルやディレクトリを他のユーザに操作されないように独占すること。
###タグ(tag)
直訳すると「札」。指定したリビジョンで構成されるファイルにつけるラベルのこと。開発の現場ではリリースのタイミングで、例えば「release_20190730」のようにタグをつけて管理することが多い。
###トランク(trunk)
直訳すると「木の幹」。開発の主流となる部分。
###ブランチ(branch)
直訳すると「枝」。トランクから枝分かれすること。具体的には、開発の主流であるトランクに大規模な変更などを行う場合やバグなどの検討などトランクに対してすぐには反映でいなかったり、しばらく分けておきたい場合などで利用することが多い。最終的にトランクに変更点を反映させる（マージ）ことがほとんど。
###マージ(merge)
変更の内容をあるブランチから他のブランチに移動させること。メインの開発用ブランチをサブシステムのの開発用ブランチにマージさせたり、その逆であったりする。
###更新(update)
ローカル環境の作業コピーがリポジトリの最新リビジョンより古いリビジョンになっている可能性がある場合、リポジトリから差分ファイルを取得し、作業コピーを最新化する同期作業。
WEB画像の拡張子、webp(うぇっぴー)

**webp(うぇっぴー)について**

Webp（うぇっぴー）という画像形式をご存知でしょうか。
Googleが開発しているオープン静止画フォーマットで、「.webp」という拡張子です。
意外にも2010年から開発されている画像形式です。

特徴としては、JPEGと比較して、２５％〜３４％小さくなる。
それなのに、画像が綺麗で軽い。
透過画像にもできて、アニメーションもできる。

**ブラウザの対応（2019年７月２８日時点）**
<img width="1424" alt="スクリーンショット 2019-07-28 17.15.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392317/97b15b52-8a6f-92ec-78cf-dd67821f1d84.png">

Chromeでの対応のみになっている。今後、他のブラウザでも対応できるようになっていくとのこと。

**webp(うぇっぴー)の画像作成方法**

オンライン上での変換が一番時間簡単にできる。
また、webp⇨jpg変換についても、ファイルコンバーターなどを使用しオンライン上から変換が行える。

参考
https://qiita.com/hashimoto-1202/items/d31928004d76455c94bd
https://webkikaku.co.jp/blog/htmlcss/webp-how-to-use/
VS Code でWPF（何もないウィンドウ）を作成してみた

## 環境
#### .NET Core 3.0(SDK 3.0.100-preview7-012821)をＤＬし、インストールする
（dotnet-sdk-3.0.100-preview7-012821-win-x64.exe）

## プロジェクト（？）の作成
#### 空のフォルダ（＝プロジェクト名）を作成し、作成したフォルダをVS Codeで開く
今回「%WS_ROOT%\wpfExample01」で行った

## アプリケーション（？）の作成
#### VS Codeのターミナルで下記コマンドを実行する
```
PS %WS_ROOT%\wpfExample01> dotnet new wpf
The template "WPF Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on %WS_ROOT%\wpfExample01\wpfExample01.csproj...
  %WS_ROOT%\wpfExample01\wpfExample01.csproj の復元が 267.9 ms で完了しました。

Restore succeeded.
```
#### ```tree /f```コマンドで生成されたファイルの一覧を確認
```
プロジェクトルート（%WS_ROOT%\wpfExample01）
│  App.xaml
│  App.xaml.cs
│  MainWindow.xaml
│  MainWindow.xaml.cs
│  wpfExample01.csproj
│
└─obj
        project.assets.json
        wpfExample01.csproj.nuget.cache
        wpfExample01.csproj.nuget.dgspec.json
        wpfExample01.csproj.nuget.g.props
        wpfExample01.csproj.nuget.g.targets
```


## アプリケーション（？）の実行
「ctrl」＋「F5」で実行
「環境の選択」が表示されるので「.NET Core」を選択

VS Codeに下記ポップアップ（右下）が表示される
```Required assets to build and debug are missing from 'wpfExample01'. Add them?```
「yes」ボタンをクリックする

起動しない場合、フォルダの作成からやり直す。または、「launch.json」を削除し、「ctrl」＋「F5」で再度実行してみる

```
> Executing task: C:\Program Files\dotnet\dotnet.exe build %WS_ROOT%\wpfExample01/wpfExample01.csproj /property:GenerateFullPaths=true /consoleloggerparameters:NoSummary <


.NET Core 向け Microsoft (R) Build Engine バージョン 16.3.0-preview-19329-01+d31fdbf01
Copyright (C) Microsoft Corporation.All rights reserved.

  %WS_ROOT%\wpfExample01\wpfExample01.csproj の復元が 75.96 ms で完了しました。
  You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview
  wpfExample01 -> %WS_ROOT%\wpfExample01\bin\Debug\netcoreapp3.0\wpfExample01.dll
```
を表示後、何もないWindowが開く

## その他
[.NET Core 3.0 (Preview 6) の新機能](https://docs.microsoft.com/ja-jp/dotnet/core/whats-new/dotnet-core-3-0)には、「dotnet new winforms」コマンドもコンソールで実行するように書かれているが、今回実行していません。
【UE4】AI Perception を頭の向きと一致させる

#お知らせ
2020-12-31 
Get Head Loc Rot関数の実装画像を差し替えました。ただしサンプルプロジェクトの方は変更していないため、差し替えた画像を参考に修正してください。

参考資料のリンク先の動画が非公開になったことで閲覧不可になったため削除しました。

#はじめに
AI Perceptionについては以下の記事を参照。
[【UE4】AI Perception の紹介と使い方](https://qiita.com/Dv7Pavilion/items/741402f4da609ec595a2)

公式の紹介ページ（最近更新されたらしいです）
[Artificial Intelligence - AI Perception](https://docs.unrealengine.com/ja/Engine/ArtificialIntelligence/AIPerception/index.html)

AI Perceptionの向きはRoot Componentの回転を使用しているため必ずしも頭の回転と一致するわけではありません。
例えば敵兵士がパトロール中に左右を向くアニメーションを再生しても、Root Componentそのものが回転しているわけではないので、プレイヤーとバッチリ目が合っても「視野内に入った」と知覚してくれません。

下の画像は赤色の枠が敵を表し、オレンジの矢印は向いている方向、緑の矢印はAI Perceptionの方向を示しています。
![デフォルトのAIPerception.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/1cd04d02-1e91-ecd2-8044-5a0263274ee5.png)

この問題を修正するにはC++で **GetActorEyesViewPoint関数** をオーバーライドする必要があります。

#プロジェクトはこちら
記事の内容を実装したプロジェクトをアップしています。
Version 4.22.3
https://1drv.ms/u/s!Au-8FqgREBKZiBrXYXOlaXcBj8v9?e=oT5PzR

#修正してみよう！
GetActorEyesViewPoint関数をオーバーライドするためにAIControllerクラスを親としたC++クラスを追加します。

無事に生成＆コンパイル出来たら、ヘッダ側に以下のように追記します。

```cpp
public:
	UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "PerceptionExtended")
		void GetHeadLocRot(FVector& OutLocation, FRotator& OutRotation) const;

	virtual void GetActorEyesViewPoint(FVector& out_Location, FRotator& out_Rotation) const override;
```

CPP側には以下のように追記します。

```cpp
void クラス名::GetActorEyesViewPoint(FVector& out_Location, FRotator& out_Rotation) const
{
	GetHeadLocRot(out_Location, out_Rotation);
}
```

---

C++側はこれで終了です。
次はBlueprintImplementableEventとして宣言した **GetHeadLocRot関数** をブループリント側で実装します。

最初にCharacterクラスを親としたブループリントを作成し、メッシュやアニメーションブループリントを設定します。
![設定終了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/29531f26-b922-fa1a-c934-e7998075b02a.png)

Meshコンポーネントの子として **Scene Component** を追加します。
追加したScene Componentを選択し、Detailsパネル（詳細パネル）の **Sockets - Parent Socket** の虫眼鏡マークをクリックし、Headボーンを選択します。
追加したScene Componentがアニメーションと追従することを確認したら、Scene ComponentのRotationを調整します。
![HeadSocketの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/e5d4acdc-aac1-2674-5814-554e2578ea60.png)

AI Controllerの設定を忘れずに行います。
![AI Controllerの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/ea3904f0-7f2b-fef0-c016-96c569b15bbe.png)

---

次にC++で作成し、GetActorEyesViewPoint関数をオーバーライドしたAI Controllerクラスを親としたブループリントを作成します。

Event GraphでOn Possessイベントを呼び出し、返り値PossessedPawnから上で作成したAIキャラクターブループリントへキャストし、返り値を変数へ格納します。
![AIキャラクターブループリントへのキャスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/0856145c-d252-65c1-35cf-0bdae4e61607.png)


My BlueprintパネルのFunctionsから **Overrideボタン** をクリックし、一覧から **GetHeadLocRot** を選びます。
選んだら自動でGetHeadLocRotタブが開かれるので次のようにノードを配置します。
![GetHeadLocRotの実装.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/edde0c85-2a13-d527-dbf2-705cf25c8a58.png)


Add Componentで **AI Perception Component** を追加して、AI Sight Configを設定します。
![AIPerceptionコンポーネントの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104467/61bf8e35-5374-290a-7336-a4b1a3799aea.png)


---

以上でAI Perceptionが頭の回転と一致するようになりました。

#参考資料

なし
Raspbian Busterの初期設定覚書

Ruspberry Pi（以下、ラズパイ）3B+を再セットアップする事態になったので、OSのイメージをダウンロードしようとしたらBusterが入手できるようになっていたので、初期設定についてまとめておきます。


#■環境
モデル：ラズパイ 3B+
OS：Raspbian　Buster（July 2019）
Bluetoothキーボード：ELECOM TK-FBP102
マウス：有線USBマウス
 
#■Bluetoothキーボードの接続
手持ちのキーボードがPS2接続のものとBluetooth接続のものしかなかったので、最初にBluetoothキーボードの接続を行いました。
このキーボードはFnキー＋Tabキーでペアリングを行います。
画面右上のBlutoothのアイコンから「AddDevice」を開くと
特に問題なくラズパイ側でキーボードを認識していたので、
これを選んで接続。

#■初期設定ウイザード
特に躓くことはないと思うので割愛。
piユーザーのパスワード設定が初期設定ウイザードに含まれましたね。
最後のSoftware Updateが長いです。
パッケージリストの更新をやっています。

ここで一度OSリブート。
なお、リブート後、Bluetoothキーボードは自動的に接続されました。

#■日本語入力環境整備
・以前はMozcのパッケージをインストールが必要でしたが、Busterではインストール済みでした。
・日本語入力へ切替るキーの設定
　メニュー　＞　設定　＞　Fcitx設定　＞　入力メソッドの設定　＞　全体の設定（タブ）を開きます。
　ホットキーの「入力メソッドのオンオフ」をクリックすると、ポップアップが出るので、切替に使用するキーを押します。
　これで、日本語入力ができるようになります。

#■キーボード配列の設定
JIS配列のキーボードとは認識されなかったので、手動で設定しました。
上記と同様「Fcitx設定」から「入力メソッド」のタブを開き、
左下の「＋」をクリックし「キーボード-日本語」を追加します。
そして、もともとあった「キーボード-US」は「－」をクリックして削除。

ちなみに｜（パイプ）の入力ができないと思ったらshift+fn+￥（BackSpaceの左隣）でした。

キーバイドを変更する方法はこちらが参考になります。
https://qiita.com/macinjoke/items/746c0c0adb74cfdeb9e7

#■SSH有効化
ターミナルで以下のコマンドを実行し、Configuration Toolを起動します。
`$sudo raspi-config`
「5 Interfacing Options」>　「P2　SSH」を選択し、＜はい＞を選ぶとSSHが有効化されます。

参考
https://qiita.com/hikobotch/items/a33fc77114a4963cc68b

#■IPアドレス固定
DHCPサーバー（ルーター）側で、特定のIPアドレスを割り当てるように設定したので、ラズパイ側は特に設定しませんでした。


#■イメージバックアップ
こちらを参考に。
https://itdecoboconikki.com/2017/02/16/raspberry-pi-backup-img-make/
ローン返済のシミュレーションができるスクリプトを作った

# 1. はじめに
このスクリプトは一定期間で利子がつくローンの返済金額を計算することができます。
具体的には、借入額と返済回数と金利を入力することで、毎回の返済額・金利分・残額を出力することができます。
実際のローン返済の方法にもとづいて、元利均等返済と元金均等返済の両パターンに対応しています。

インストールはこちらから。
https://github.com/shion-0412/Interest-calculation

#2. 開発環境
mac OS
ターミナル

#3. 用語説明
**返済回数**
返済を行う回数。返済が毎月ならば月数、毎年ならば年数のように数えてください。
返済期間が10年で毎月返済する場合、返済回数は120です。

**金利**
残額に対して一定期間で乗算される比率のことです。
単利と複利の2つの方式がありますが、ローンの場合は金利込みの残額に対してさらに金利がかけられる、複利方式です。

**元利均等返済**
毎回の返済額が、おしなべて同額となる返済方式です。
返済の目処が立てやすいですが、返済総額は増えます。

**元金均等返済**
毎回の返済額のうち、元金の額が一定となる返済方式です。
初期の返済額が高額になりますが、利子分の返済額が少なく抑えられます。

#4. 使い方

```:元金均等返済
##入力##
python repayment.py gankin
type the principal (yen): [借入額]
type the number of repayment: [返済回数]
type the interest rate (%): [一回あたりの金利]
##出力##
time--repayment--interest--remains
[回数]---[返済額]--[金利分]--[残額]
Total repayment: [返済総額] yen.
 Total interest: [利子総額] yen.
```

```:元利均等返済
##入力##
python repayment.py ganri
type the principal (yen): [借入額]
type the number of repayment: [返済回数]
type the interest rate (%): [一回あたりの金利]
##出力##
time--repayment--interest--remains
[回数]---[返済額]--[金利分]--[残額]
Every repayment: [毎回の返済額] yen.
Total repayment: [返済総額] yen.
 Total interest: [利子総額] yen.
```

#5. 注意
ナニワ金融道を読んで思いつきで作りました。
ガチでローンの見積もりがしたい人は銀行に行ってください。
【Rails】 RSpecでNoMethodErrorと言われた人へ

#エラーの内容
ターミナルで```bundle exec rspec```を実行すると以下のような文が表示されてしまい、テストの判定が行われませんでした。

    undefined method `build' for #<RSpec::ExampleGroups::User::Create:~~~~~>

    undefined method `create' for #<RSpec::ExampleGroups::User::Create:~~~~~>

#解決法
##1. spec以下にフォルダを作成する
"spec/support/factory_bot.rb"を作成します。
##2. factory_bot.rbに次の内容を記述する
```factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
```
##3. rails_helper.rbで2のファイルを読み込む
```rails_helper.rb
require 'support/factory_bot'
```

ここまで終えて、もう一度```bundle exec rspec```を実行したところ、無事にテストコードの判定を行うことができました。
#参考
[Stack Overflow「```undefined method `build' for #<RSpec::ExampleGroups::UserName:>```」](https://stackoverflow.com/questions/49389275/undefined-method-build-for-rspecexamplegroupsusername/49393192#49393192?newreg=8b78b45e921a49279d9719353a109161)

以上を参考に解決することができました。ありがとうございます。
#さいごに
前例探しに手間取ったので、記事として残します。同じエラーに遭遇した方の参考になれば幸いです。なお、理屈についてはいまの私では説明できないため、未来の私への覚書も兼ねています。
vue.js elementui 複数フォームを使う

vue.jsで 1ページで複数のフォームを for 文などで繰り返し使う。

考え方としては
親vue から子vueをfor文で読み出す。
その際に 変数 id や title などを渡す。

ってな感じでしょうか。


まずは親vueからコンポーネントを読み出しましょう

```Yumeanswershow.vue

<div v-for="(v,key) in list" style="display: block;margin-top: 15px;">
    {{v.id}} : {{v.title}}
    <yumeansweradd-component :id="v.id" :title="v.title"></yumeansweradd-component>
</div>


//略
export default {

components: {// 非同期で読み込み
    'yumeansweradd-component': () => import('./YumeansweraddComponent.vue')
},

```



今度は 子 vue

```YumeansweraddComponent.vue

<template>

    <div>

        <el-form :model="form" :rules="rules" ref="form">
            <el-form-item :label="id + title" prop="message">
                <el-input type="textarea" v-model="form.message" :rows=5></el-input>
            </el-form-item>
            <el-form-item>
                <div class="t-c">
                    <el-button type="primary" @click="submitForm('form')">登録</el-button>
                </div>
            </el-form-item>
        </el-form>

    </div>


</template>

<script>

    import axios from 'axios'


    export default {
        props: ['id','title'],//親要素から id を取得
        data() {
            return {
                form: {
                    message:'',
                },
                rules: {
                    message: [
                        { required: true, message: '入力してください', trigger: 'change' }
                    ],
                },

            };

        },

        created () {
            // console.log("idは" + this.id);
        },

        methods: {

            submitForm(formName) {

                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        console.log("送信しました");
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });

            },


        }


    }

</script>





```



以上。
Vue.jsについての基礎(インストール)

#はじめに
おはようございます。こんにちは。こんばんは。
ワタタクです。
今回はVue.jsについて見けいけたらいいなと書いています。

では早速参ります。
#Vue.jsとは？
[公式サイト](https://jp.vuejs.org/index.html)

>Vue.js（ヴュージェイエス）、またはVueは、Webアプリケーションにおけるユーザーインターフェイスを構築するための、オープンソースのJavaScriptフレームワークである。他のJavaScriptライブラリを使用するプロジェクトへの導入において、容易になるように設計されている。一方で高機能なシングルページアプリケーション（SPA）を構築することも可能である。

[chromeの拡張機能のvuejs-devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)を入れて置くと便利。
#環境構築
*今回はCDNを使わず<font color="red">vue-cli</font>を使います。*
##nodeがインストールされているか確認する

```console
$ node -v
v11.2.0
```
もし、コマンドを叩いてもversionが表示されなかったら[node.js](https://nodejs.org/ja/)をインストールしてください。
以下も確認して置いてください。

```console
$ npm -v
6.9.0
```
##vue.jsのインストール
上記のことを確認したら、いよいよvue.jsをインストールしていきます。

```console
$ npm install -g vue-cli
```
成功すれば以下を確認してください。

```console
$ vue -V
3.1.1
```
確認できれば次のコマンドを実行してください。

```console
$ vue init webpack test-vue
```
<font color="red">*※test-vueの部分はプロジェクト名&ディレクトリ名になります。*</font>
いろいろ聞かれますが、全部EnterでもOKです。
実行が終わったら下記を実行してください。

```console
$ cd test-vue
$ npm run dev
```
localhost:8080にブラウザからアクセスしてみてください。Vueアプリケーションの土台ができており、
下記の画面が表示されるはずです。

<img width="775" alt="test-vue.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116696/c7a1d30f-25b2-7eca-1122-36f68433cbe2.png">

これで環境構築は終了です。
お疲れ様でした。
#最後に
最後まで読んでいただきありがとうございました。
もし、間違い等、アドバイス、ご指摘等有れば教えていただけたら幸いです。

今後はVuex,Nuxt.jsについて触れていきたいと思います。
Git使い方メモ

# はじめに

gitとGitHubを勉強して、自分なりに実際に使用してみたので、その流れをメモしておきたいと思います。

# git管理の開始

## GitHubの操作
リポジトリ作成
まず、GitHub上でリモートリポジトリを作成します。
GitHubのRepositories欄の「New」ボタンから作成できます。
<img width="950" alt="new repository1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311225/34b2d6a4-5e8f-2526-f177-ea3ad31ef8f0.png">
リポジトリ名を入れれば作成できます。
<img width="760" alt="new repository2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311225/484434b3-4a3e-715e-06f1-3020252ec1a6.png">

## git操作
既にあるファイルの管理を始める場合は、管理するファイルがあるディレクトリに移動後に、`git init`コマンドを実行します。

```
git init
```
次に、`git remote`コマンドでリモートリポジトリを登録します。
以下のコマンドによって、originというの名前でリモートリポジトリにアクセスできます。

```
git remote origin "アドレス"
```
以下のコマンドで現在登録しているリモートリポジトリを確認できます。

```
git remote -v
```

# ブランチの操作
`git branch`コマンドでブランチを作成できます。

```
git branch "ブランチ名"
```
以下のコマンドで、ブランチの一覧を確認できます。
`-a`オプションをつけることで、リモートブランチを含めて確認できます。
また、`*`がついているものが現在のブランチになります。

```
git branch
git branch -a
```
作成したブランチに移動するには、`git checkout`コマンドを使用します。
`-b`オプションをつけることで、ブランチの作成しつつ移動できます。

```
git checkout "ブランチ名"
git checkout -b "ブランチ名"
```
不要なリポジトリは、`git branch -d`で削除できます。

```
git branch -d "ブランチ名"
```
リモートブランチの場合は、`git push --delete`コマンドになります。

```
git push --delete origin "ブランチ名"
```

# ファイルの管理
ここからはファイル修正後の話です。

修正したファイルをインデックスに登録します。
簡単に言うと、コミットするファイル一覧みたいなものです。
`git add`コマンドで登録します。

```
git add "ファイル名"
```
`git status`で現在の変更を確認できます。

```
git status
```
次にファイルをローカルリポジトリにコミットします。
デフォルトだとvimでコメント入力が起動するので、`i`で入力モード、
入力後は、`esc`で入力モード終了、`:wq`で保存して終了します。

```
git commit
```
最後に、リモートリポジトリにプッシュして反映します。

```
git push origin "ブランチ名"
```

# プルリクエスト
リモートリポジトリにプッシュされた内容を別のブランチにマージする際に、プルリクエストを送ります。
GitHubのPull requests欄の「New pull request」を押します。
<img width="1009" alt="pullrequest1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311225/e1943ef4-2655-068e-1f1f-eb8558652296.png">
マージ元とマージ先のブランチを指定して、「Create pull request」を押して、必要項目を入力すると作成できます。
<img width="1050" alt="pullrequest2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311225/05b3802e-3bec-11cd-ba39-f06fdb180082.png">



# GitHubの内容を取得
まず、取得したいブランチに移動します。

```
git checkout "ブランチ名"
```
`git pull`コマンドでリモートリポジトリの内容をローカルに反映します。

```
git pull origin "ブランチ名"
```

# 参考URL
以下の方の記事にコマンドがまとまっていて参考にしました。
[【Git】基本コマンド](https://qiita.com/konweb/items/621722f67fdd8f86a017)
[基本的なGitコマンドまとめ](https://qiita.com/2m1tsu3/items/6d49374230afab251337)
VR内にオーバーレイでブラウザを持ち込む

#注意
**Embedded Browserは任意のサイトを見るための作りではないようです。**
**「信頼できないコードを読み込まないように」とドキュメントに書かれていますし、Chromiumのバージョンは古く、Googleにアクセスすると更新するように表示が出ます。**
**自作のHTMLやjavascriptを読み込む、信頼できるサイトのみを読み込むようにしてください。**

#紹介
ちなみに、別のアセットを使った完成品を配布している方がいます。
こちらはIE11です。
VROverlayWebView
https://github.com/Narazaka/VROverlayWebView

#手順
1 この記事のとおりに作る

空間タップできるVRオーバーレイアプリケーションをUnityで作る【コーディングなし】
https://qiita.com/gpsnmeajp/items/3b67223f7f11bb6d93c3

2 このアセットを買う
ZEN FULCRUM LLC - Embedded Browser
https://assetstore.unity.com/packages/tools/gui/embedded-browser-55459

3 Assets/ZFBrowser/Prefabs/Browser (GUI)を、Canvasに突っ込む

4 以下のコードを書き、Browser (GUI)のPointer UIGUI(Script)を置き換える。
この際、Inspector上で
・Enable Touch Inputをオンに
・EasyOpenVROverlayには、OverlaySystemを突っ込む

```cs:MyBrowserUI
//gpsnmeajp 2019
//These codes are licensed under CC0.
//http://creativecommons.org/publicdomain/zero/1.0/deed.ja
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ZenFulcrum.EmbeddedBrowser;

public class MyBrowserUI : PointerUIGUI
{
    public EasyOpenVROverlayForUnity EasyOpenVROverlay;
    public Vector2 PointerPositionLeft = Vector2.zero;
    public bool IsClickLeft = false;
    public Vector2 PointerPositionRight = Vector2.zero;
    public bool IsClickRight = false;

    protected override void FeedTouchPointers()
    {
        if (EasyOpenVROverlay.LeftHandU >= 0 && EasyOpenVROverlay.LeftHandV >= 0)
        {
            PointerPositionLeft = new Vector2(EasyOpenVROverlay.LeftHandU, EasyOpenVROverlay.LeftHandV);
        }
        IsClickLeft = EasyOpenVROverlay.tappedLeft;

        if (EasyOpenVROverlay.RightHandU >= 0 && EasyOpenVROverlay.RightHandV >= 0)
        {
            PointerPositionRight = new Vector2(EasyOpenVROverlay.RightHandU, EasyOpenVROverlay.RightHandV);
        }
        IsClickRight = EasyOpenVROverlay.tappedRight;

        FeedPointerState(new PointerState
        {
            id = 10 + 0,
            is2D = true,
            position2D = PointerPositionLeft,
            activeButtons = IsClickLeft ? MouseButton.Left : 0,
        });
        FeedPointerState(new PointerState
        {
            id = 10 + 1,
            is2D = true,
            position2D = PointerPositionRight,
            activeButtons = IsClickRight ? MouseButton.Left : 0,
        });
    }
}
```

5 実行して、VR空間にブラウザが現れればOK

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">VRの中にブラウザを持ち込むの自分も作ってみている。<br>前にEmbedded Browserというアセットを買ったのでそれを使用。デスクトップとは別に動いている。<br>(※セキュリティ上難があるため、このままの機能で公開はしません)<a href="https://t.co/S7QZyqCWKp">https://t.co/S7QZyqCWKp</a> <a href="https://t.co/xsLdNC8Xp3">pic.twitter.com/xsLdNC8Xp3</a></p>&mdash; Segmentation Fault (@Seg_Faul) <a href="https://twitter.com/Seg_Faul/status/1155382705321738241?ref_src=twsrc%5Etfw">July 28, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Swift：Timer.scheduledTimerとDipatchQueue.main.asyncAfterの細かい違い

n秒後に〇〇の処理を行うというようなプログラムを書く際，`Timer.scheduledTimer`や`DipatchQueue.main.asyncAfter`を使うことになると思いますが，この２つには処理タイミングにズレがあるようです．

- `Timer.scheduledTimer`はn秒後に（他の処理に割り込んででも）正確に処理が行われる
- `DipatchQueue.main.asyncAfter`は最低n秒待ってから処理が行われる

つまり，Threadを指定して正確にn秒後にある処理をさせたい場合は，

```swift
Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { (t) in
    DispatchQueue.main.async {
        // 処理
    }
}
```

という風にTimerの中でThreadを指定してやる必要がありそうです．
openFrameworks(0.10.1)をgithubからインストール

# はじめに
[openFrameworks][1]を[github][2]から取ってきてからexampleにあるプロジェクトを実行するまでにしたこと
インストールの手順は[レポジトリ][3]に書いてあることを0.10.1用に変えてMacとWindowsにインストールするだけ

## 実行環境
Mac: Xcode 10.2.1
Widnows: Visual Studio 2017

## 共通部分1
まずopenFrameworksをgithubからclone
MacはTerminal, windowsはGit Bashで実行

```bash
git clone https://github.com/openframeworks/openFrameworks.git
git checkout refs/tags/0.10.1
git submodule update --init --recursive
```

```http://ci.openframeworks.cc/libs``` から任意のバージョン(今回は0.10.1)のMacならosx, Windowsならvs2017をダウンロードして```scripts/osx(vs)```に置く

## Mac編
libのダウンロードのところだけコメントアウトして実行

```bash:scripts/dev/download_libs.sh
<< COMMENTOUT
for PKG in $PKGS; do
    download $PKG
done
COMMENTOUT
```


```terminal:
cd scripts/osx
bash download_libs.sh
```

## Windows編
powershellの初期状態ではpowershellスクリプトを実行出来ないのでポリシー変更

```
# powershell(管理者権限で実行)
Set-ExecutionPolicy RemoteSigned
```

libのダウンロードのところだけコメントアウトして実行

```powershell:scripts/vs/download_libs.ps1
<#
If(Test-Path "$pkg") {
    echo "Deleting old package"
    Remove-Item $pkg
}

echo "Downloading $url to $scriptPath\$pkg"
$client.DownloadFile($url, "$scriptPath\$pkg")
#>
```

```powershell:
cd scripts/vs
powershell download_libs.ps1
```

## 共通部分2
[openFrameworks][1]のdownloadからprojectGeneratorを持ってきて実行(projectGeneratorのビルドが上手く行かなかったので)
projectGenerator.app(.exe)を実行し，以下の手順を実行

```
1. openFrameworks pathを設定
2. Advanced optionsをチェックするとupdate multiple
3. Update path:examplesを指定し，update multipleボタンを押すと生成
4. .xcodeproj(.sln)からプロジェクトを開き，実行
```

[1]:https://openframeworks.cc/
[2]:https://github.com/openframeworks/openFrameworks
[3]:https://github.com/openframeworks/openFrameworks/blob/master/INSTALL_FROM_GITHUB.md
「WEBを支える技術」のまとめ1

「Webを支える技術」のまとめです


###1章 Web概論


##リソースとは

・リソースとは、Web上に存在する情報である
・世界中の無数のリソースとは、それぞれURLで一一意の名前を持つ
・URLを用いることで、プログラムはリソースが表現する情報にアクセスできる

サーバととクライアントの間でリソースのやり取りが発生することを、「リソースの表現」と言う。

1つのリソースは複数の表現を持つことが出来る。
-HTMLやPDFなど、、

また、リソースには「状態」があり、時間の経過で状態を変化させることが出来る。
そして、状態が変化すると、リソースの表現も変化する。

#RESTとは

・クライアント／サーバ
・ステートレスサーバ
・キャッシュ
・統一インターフェイス
・階層化システム
・コードオンデマンド
の６つを組み合わせたアーキテクチャスタイルのこと

####クライアント／サーバ
Webが通信するときに使用されるアーキテクチャスタイル。HTTPとういうプロトコルを用いて通信する。クライアントがサーバに対してリクエストを送り、サーバがレスポンスを返す。
クライアントとサーバに分離させることによって、単一のコンピュータで処理を行わなくても済むようになっている。

####ステートレスサーバ
クライアント/サーバに最初に追加するアーキテクチャスタイル。
クライアントサーバにアプリケーション状態を管理しないことを意味します。
逆に、HTTPをステートフルにするのが、Cokkieを使用したセッション管理である。
クライアント／サーバにステートレス性を導入すると、アーキテクチャスタイルは「クライアント/ステートレスサーバ」になる。

####キャッシュ
リソースの鮮度に基づいて、一度取得したリソースをクライアント側で使いまわす方式。
サーバとクライアント間の通信を減らすことで、より効率的に処理ができる。しかし、古いキャッシュを利用してしまい、情報の信頼性が落ちてしまうことがある。
キャッシュを追加したアーキテクチャスタイルは、「クライアント/キャッシュ/ステートレスサーバ」と呼ばれる。

####統一インターフェース
URLで指し示したリソースに対する操作を、統一した限定的なインターフェースで行うアーキテクチャスタイルのこと。
例えば、HTTP1.1では、GETやPOSTなど、8個のメソッドに限定されている。この制約のおかげで全体のアーキテクチャがシンプルになるだけでなく、クライアントとサーバの実装の独立性が向上する。
統一インターフェースを追加したアーキテクチャスタイルは「統一/クライアント/キャッシュ/ステートレスサーバ」と呼ばれる。

####階層化システム
統一インターフェースの利点の一つに、システム全体が階層化しやすいということがある。
例えばWebサービスでは、サーバとクライアントの間にロードバランサを設置して負荷を分散したり、プロキシを設定してアクセスを制限したりします。
クライアントからすると、サーバもプロキシも同じインターフェースで接続できるので、接続先がサーバからプロキシに変わったことを意識する必要がない。これは、サーバやプロキシなど、各コンポーネント間のインターフェースをHTTPで統一しているから実現できる。
このようにシステムをいくつかの階層に分離することが出来る。
階層化システムを追加したアーキテクチャスタイルは「統一/階層化/クライアント/キャッシュ/ステートレスサーバ」と呼ばれる。

####コードオンデマンド
プログラムコードをサーバからダウンロードして、クライアント側でそれを実行すること。
コードオンデマンドの利点は、クライアントプログラムに予め用意していた絹だけでなく、新しい機能を拡張していけることにある。
ただし、コードオンデマンドを利用すると、ネットワーク通信のプロトコルの可視化の低下に繋がることだ。
コードオンデマンドを追加したアーキテクチャスタイルは「統一/階層化/コードオンデマンド/クライアント/キャッシュ/ステートレスサーバ」と呼ばれる。

RESTはアーキテクチャスタイルなので、システムを設計する際には、そのシステムのアーキテクチャを作らなければならない。
RESTを構成するスタイルのうち、いくつかを使用しないこともあり得る。


##RESTの二つの側面
RESTは、ハイパーメディアと分散システムにより、世界的な成功を収めた。

###RESTとハイパーメディア
リソースをリンクで表現することで、1つのアプリケーションを表現するという考え方。RESTの基幹となる思想である。
ハイパーメディアを用いたアプリケーションは、リソースのURLさえ分かれば、そのアプリケーションが提供しているリソースを他のアプリケーションでも簡単に再利用出来るという利点がある。
リソースをリンクで接続することで1つのアプリケーションを構成するという考え方は、「接続性」とも呼ばれる。

###RESTと分散システム
RESTに基づいたWebでは、統一インターフェースによってインターフェースが固定されているため、互換性の問題が発生しない。
リソースで適応できるHTTPメソッドは常に固定であり、HTTPを実装したクライアントであれば同じように接続できる。


##まとめ
WebはRESTという分散ネットワークシステムの理論があったからこそ、ここまで成長したとも言える。
個別のWebサービスやWeb APIがRESTfulになると、Webは全体として良くなる。
以降の章で、THHP、URI、そしてHTMLなどのハイパーメディアフォーマットをどのようにRESTfulに使うか、どのように設計するのかを見ていく。
gulp v4 で typescript + sequelize を transpile する

## sequelize も typescript で記述したい

sequelize v5 で `typescript` もサポートしたので、まるごと `typescript`化してトランスパイルにチャレンジしてみました。`sequelize` の標準構成である `config/config.json` も使いつつ、`models/*.ts` を`dist/` 配下へトランスパイルして配置したいと考えました。

しかし、標準の `tsc` では `typescript` のファイルをトランスパイルしてくれますが、`*.json` などのファイルは指定した `outDir`へは配置してくれません。何事もなければ `./src` 配下でファイルを作って、実行に必要なファイルを `./dist`へ配置するようにしたいと願ったとき、`tsc`だけでは対処できないのでした。

## gulp を使おう

そこで、タスクランナーである `gulp` の出番です。対象のファイルや機能毎に、個別にタスクを割り当ててバッチ処理を行えます。いわゆる `make` のようなものです。`javascript` で記述できるので、自由度も高いですね。

さて、元のディレクトリ構成はこんな感じです。`migrations` はマイグレーションでしか利用しないので、トランスパイルも不要ですし、`sequelize-cli` の吐き出すものをそのまま利用しています。実行時に必要なのは `./src/models` と `./src/config/config.json` です。

```bash
src
├── index.ts
├── config
│   └── config.json
├── migrations
│   └── 20190728*.js
├── models
│   ├── index.ts
│   ├── schema.ts
│   └── *****.ts
└── seeders
```

実行時の `./dist/` ではこのようなディレクトリ構成になってほしいわけです。

```bash
dist
├── config
│   └── config.json
├── models
│   ├── index.js
│   ├── schema.js
│   └── *****.js
└── index.js
```

## gulp のタスクを実装して実行しよう

まず、必要なモジュールを入れておきます。

```bash
npm install --save gulp-cli gulp gulp-typescript typescript
```

gulp v4 になって、書き方もだいぶモダンになったので、それに合わせてタスクを書いてみます。
構成ファイルが複数になるのは切ないので、トランスパイルには `tsconfig.json` ファイルの内容を利用するようにしています。

```javascript:gulpfile.js
const { src, dest, parallel, series } = require('gulp');
const ts = require('gulp-typescript');
const tsconfig = require('./tsconfig.json');

const config = {
  output: 'dist/',
  json: {
    source: 'src/**/*.json'
  }
}
const typescript = () => {
  return src(tsconfig.include)
    .pipe(ts(tsconfig.compilerOptions))
    .pipe(dest(config.output))
}

const json = () => {
  return src(config.json.source)
    .pipe(dest(config.output))
}

exports.typescript = typescript;
exports.default = series(parallel(typescript, json));
```

こんだけ。注意点は `typescript()` 内の `.pipe(dest(...))` が必要なこと。

```bash
npx gulp
```

でどうぞ。

参考情報:
[gulp-typescript](https://www.npmjs.com/package/gulp-typescript)
テキストリンクボタン

追加CSSに

```
.btn-simple {
  display: inline-block;
  padding: 0.3em 1em;
	/*↑余白*/
  text-decoration: none; 
	/*↑文字装飾*/
  color: #498CB6;
	/*↑テキストの色*/
	 border: solid 2px #67c5ff; 
	/*↑四角の太さ・四角の色*/
	border-radius: 3px; 
	/*↑四角の丸*/
}
.btn-simple:hover {
  color: #498CB6
}
```
を入力。次に、WordPressの編集画面に飛び、テキストエディタを選択します。
<img width="804" alt="スクリーンショット 2019-07-28 15.59.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/24b41f8b-2096-1b98-1b4e-04619d78b9f7.png">
そしてボタンを入れたい場所に

```
<p style="text-align: center;"><a class="btn-simple" href="https://www.google.com" target="_blank" rel="noopener">ここを変える</a></p>

```
と入力して「プレビュー」や「投稿」を押して確認すると、
<img width="901" alt="スクリーンショット 2019-07-28 15.58.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/b6940b9b-3425-af13-dcb3-dc0df527e1a7.png">
とボタンが作成されました。
色を変えたい場合は『color:』の後ろ部分を変えてください。その他にも自由にカスタマイズすることができるので、色々と試してみてください。
そしてそのボタンを押してみると、
<img width="1280" alt="スクリーンショット 2019-07-28 16.07.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/371552/71ad4c54-39f0-9ac1-ebaa-bf40f74d9e2a.png">
Googleのページに飛びます。
これは先ほど、テキストエディタで入力した
『href="https://www.google.com"』
の中がGoogleのホームページのアドレスだからです。この『""』の間を自由に変更してください。
文章の部分は、『ここを変える』の部分を変えてください。
Ack.vim でビジュアルモードで選択した文字列から直接コード検索する

## はじめに

プロジェクト内でコードの検索をかけるときに、[Ack.vim](https://github.com/mileszs/ack.vim) をよく使っています。その Ack.vim で、ビジュアルモードで選択した部分を直接検索する方法を調べたので、簡単にまとめます。

## 課題

今まで Ack.vim でコード検索をするときは、以下のような手順を踏んで実行していました。

* 検索したい文字列をビジュアルモードで選択してヤンク
* `:Ack ` と入力した後にヤンクした文字列をペースト
* Enter キーを押して実行

しかし上記の手順を何度も繰り返していると、段々と億劫になってくるところがありました。

そのため、以下のような手順で検索をかけられると楽になるなと思い、方法を探していました。

* 検索したい文字列をビジュアルモードで選択
* ショートカットキーで選択した文字列に対して `:Ack` を実行

## tl;dr

[Using Ack.vim on visual selection - Stack Overflow](https://stackoverflow.com/questions/28011155/using-ack-vim-on-visual-selection) にやりたいことそのものが紹介されていました。

以下のコマンドを `.vimrc` に追記することで実現できました。

```vim
vnoremap <Leader>g y:Ack <C-r>=fnameescape(@")<CR><CR>
```

## やっていること

上記についてそれぞれやっていることを記載します。

コマンド|詳細
:--|:--
`vnoremap {lhs} {rhs}`| ビジュアルモードのとき、キー入力 `{lhs}` を `{rhs}` に割り当てる
`<Leader>g`| 特殊文字列 `<Leader>` と `g` の組み合わせ。(`mapreader` に何も設定していない場合、`<Leader>` はバックスラッシュが使用される)
`y`| 選択文字列をヤンク
`:Ack`| `Ack` コマンド実行
`<C-r>=`| このコマンド以降で実行された式の評価値を利用する
`fnameescape(@")<CR>`| 選択した部分をエスケープして Enter 
`<CR>`| Enter

こちらによって、検索したい箇所を選択してから`<Leader>g` を入力するだけで、`Ack` を実行できるようになりました。

※ `@"` の部分がビジュアルモードで選択されている部分を表しているようなのですが、なぜこの文字列で表せるのかまでは調べきれませんでした。。

## おわりに

普段良く使うコマンドのキー入力を減らすことができると、より負担が軽くなることを感じました。他にも何度も使っているコマンドを見つけたら、より便利になる方法を探してみたいと思います。

## 参考

* [Using Ack.vim on visual selection - Stack Overflow](https://stackoverflow.com/questions/28011155/using-ack-vim-on-visual-selection)
* [map - Vim日本語ドキュメント](https://vim-jp.org/vimdoc-ja/map.html#:vnoremap)
Android Instant Apps を試してみた (unity)

# 前提
- [Google Play Instant と Unity でインスタント ゲームを作成する](https://developers-jp.googleblog.com/2019/04/creating-an-instant-game-with-google-play-instant-and-unity.html)
    - [play-instant-unity-plugin](https://github.com/google/play-instant-unity-plugin) 0.10
- unity 2018.4.4f1
- android studio 3.4.2
    - Google Play Instant Development SDK 1.7.0

# Android Instant Appsってなんだろう?
- アプリのサブセットをインストールせずに「今すぐ試す」ものです。
    - ストアに「今すぐ試す」ボタンが付きます。
    - 有料アプリの無料体験版にできます。
    - 「Install版がストアにない状態」=「Instant版だけ」では使えません。
- アプリ中にインストールボタンを付けられるので、インストールの導線になります。
- 「アプリを起動するリンク」を作ることもできます。
    - Webアプリのような感じで使えます。
    - ただし、端末側で許可設定が必要です。

※あくまでも私の理解です。

# 準備
- 基本的には、上記の[Googleの記事](https://developers-jp.googleblog.com/2019/04/creating-an-instant-game-with-google-play-instant-and-unity.html)に従います。
- [play-instant-unity-plugin](https://github.com/google/play-instant-unity-plugin) をプロジェクトに導入します。
- android studio に Google Play Instant Development SDK を導入します。

# できること
- ビルド自体は、[公式記事](https://developers-jp.googleblog.com/2019/04/creating-an-instant-game-with-google-play-instant-and-unity.html)通りに進めれば、容易にできます。
    - サイズ制限がある以外に違いはありませんし、テストする分にはサイズ制限もありません。
    - PlayerSettings以外は、何も変えずともビルドできます。
- InstantとInstallを切り替えてビルドできます。
    - `PLAY_INSTANT`というシンボルを使って、条件コンパイルできます。
- InstantAppを(実/仮想)デバイスに送って起動できます。
- コンソールへアップロード可能なInstant版APKが作れます。
- 容量制限がありますが、InstantからInstallへデータを引き継げます。([CookieApi](https://developers.google.com/android/reference/com/google/android/gms/instantapps/PackageManagerCompat#setInstantAppCookie(byte[])))
- アプリサイズ制限をオーバーしていても、テストトラックで試すことはできます。

# できないこと
- InstantとInstallでPlayerSettingsを切り替えてくれません。
    - Instantでは、いくつかのPlayerSettingsが強制されます。
    - プロジェクトやブランチを別にするなどの工夫が必要です。
- エディタ環境では、InstantからInstallへのデータ引き継ぎができません。
    - `try {CookieApiで保存/取得} catch {PlayerPrefsで保存/取得}`として、エディタ上でシミュレートしました。
- Android App Bundleをサポートしていません。
    - もちろん、InstantとInstallの混成aabを作ることもできません。
    - これのせいで、サイズ制限を超えられませんでした。

# 留意点
- サイズを減らすために、複数のPlayerSettingsに対して更新が提示されます。
    - いくつかは強制のようで、更新しないとビルドできません。
        - 更新しなくてもビルドできるものもありました。
    - 推奨通りに更新されたものを元に戻したい場合は、PlayerSettingsで個別に直すことになります。
    - ビルドタイプをInstallに切り替えても、元に戻りません。
        - InstallとInstantで設定を別にしたい場合は、プロジェクトやブランチを別にすることになるでしょう。
- Install版は、Instant版より大きなビルド番号でなければなりません。
    - ツール側で混成aabがサポートされれば、同じビルド番号でも良いものと思われます。
- InstantからInstallへのデータ引き継ぎ(CookieApi)には、容量制限があります。
    - 保存可能なサイズは`CookieApi.GetInstantAppCookieMaxSizeBytes ()`で取得可能です。
- テスト機のGoogle設定で、「バックアップ」⇒「アプリのデータ」の「自動復元」を切っておきましょう。
    - インストール直後にデータが復活するので、データの引き継ぎが阻害されます。

# 結論
- aabの生成がサポートされるまでは厳しいです。
【Kotlin】LocalDateTimeで2つの日付を比較し、日数の差分を取得する

# はじめに
日付/時間を扱うAPIには

* 日付のみを保持する`LocalDate`
* 時刻のみを保持する`LocalTime`
* 日付と時刻の両方を保持する`LocalDateTime`

があり、やりたいことに合わせて適切なAPIを使うわけですが、
**日数の差分を取得するためには、`LocalDateTime`で日付を比較する方法がスマートだと感じた**ので、ここにメモしておきます。

※なお、「日付」の比較ということで当初は`LocalDate`の`compareTo`メソッドを使っていたのですが、下記記事に書いた通り、意図しない結果になることがありました。

[【Kotlin】LocalDateで2つの日付を比較し、日数の差分を取得する - Qiita](https://qiita.com/orimomo/items/c15fff517701a56b0cd9)
[【Android】LocalDate#compareToで日付を比較する際の注意点 - Qiita](https://qiita.com/orimomo/items/1c59409673f9c8a4df91)

# コード
非常にシンプルで、`ChronoUnit.DAYS.between`を使うことで日数の差分が取得できます。
（`LocalDateTime`と`ChronoUnit`はThreeTenABPライブラリのものを使っています。）

```kotlin
val now = LocalDateTime.now() //2019-07-28T15:31:59.754
val day1 = LocalDateTime.parse("2019-08-28T10:15:30.123")
val diff = ChronoUnit.DAYS.between(now, day1) // diff: 30
```

## `ChronoUnit`とは
`ChronoUnit`は日付、時間などを操作するための「単位」を集めた列挙型です。
1日の概念を表す`DAYS`の他にも、1時間の概念を表す`HOURS`、1マイクロ秒の概念を表す`MICROS`、1世紀の概念を表す`CENTURIES`など、多くの単位が定義されています。

詳細：[ChronoUnit (Java Platform SE 8)](https://docs.oracle.com/javase/jp/8/docs/api/java/time/temporal/ChronoUnit.html)

# 参考
* [LocalDateTime (Java Platform SE 8)](https://docs.oracle.com/javase/jp/8/docs/api/java/time/LocalDateTime.html)
* [Javaで２つの期間より差を検出する。 - m_shige1979のささやかな抵抗と欲望の日々](http://m-shige1979.hatenablog.com/entry/2017/03/10/080000)
Pythonで文の日本語判定を行う

100文字程度の短い文が日本語かどうかを判定したい場合があります。
単純な方法として、ひらがな、もしくは、カタカナが含まれているかどうかを見ることで、近似的に判定することができます。

```python
import re
def is_japanese(str):
    return True if re.search(r'[ぁ-んァ-ン]', str) else False 
```

厳密にはこの方法では不十分です。
漢字だけの日本語文もあれば、英文中に顔文字としてカタカナが使われたりすることもあります。
それでも、これだけで必要十分な篩い分けができるので重宝している方法です。
対象とする文書群や問題によっては有効であるかと思います。
Pythonのrequests_futureの実行方法による速度比較

Pythonの`requests_futures`の実行方法によって速度が変わる。
`requests_future`を使うときは、sessionを一度にまとめて作って、後から評価するようにしないと並列で動かない。多分

**テストコード**

```python
from concurrent.futures import ThreadPoolExecutor
from requests_futures.sessions import FuturesSession
import requests
import time

session = FuturesSession(executor=ThreadPoolExecutor(max_workers=30))

num_links = 100
links = [f"http://example.com/{_}" for _ in range(1,num_links)]

fs = []
print(f"requesting to {num_links} links")
t1 = time.time()
for l in links:
    f = session.get(l)
    fs.append(f)
t2 = time.time()
print(f"push to pool w/ requests_future: {t2-t1} sec")

for f in fs:
    f.result().status_code == 200
t3 =time.time()
print(f"eval in pool w/ requests_future: {t3-t2} sec")

for l in links:
    f = session.get(l)
    f.result().status_code == 200
t4 = time.time()
print(f"eval everytime w/ requests_future: {t4-t3} sec")

for l in links:
    r = requests.get(l)
    r.status_code == 200
t5 = time.time()
print(f"eval everytime w/ requests: {t5-t5} sec")
```

**実行結果**

```shell
requesting to 100 links
push to pool w/ requests_future: 0.08985710144042969 sec
eval in pool w/ requests_future: 0.9865047931671143 sec
eval everytime w/ requests_future: 24.10741138458252 sec
eval everytime w/ requests: 44.42911386489868 sec
```
MacのVisual Studio Code(VSCode)にAnacondaの仮想環境を指定する

MacにインストールしたVSCodeにAnacondaの仮想環境を設定する手順が分からなかったのでメモ

※VSCodeインストール済み、Python For VSCodeもインストール済みであることが前提。

##### 仮想環境の状態を調べる

```bash
$ conda info -e
# conda environments:
#
base                  *  /Users/user_name/anaconda3
py36_hoge                 /Users/user_name/anaconda3/envs/py36_hoge
```
ここではpy36_hogeを利用したいとします。

#####  VSCodeに仮想環境のパスを設定します。
ワークスペースのみに適用します。

1. code -> 基本設定 -> 設定 を選択。
2. ワークスペースの設定タブを選択し、設定の検索に python.pythonPathを入力します。
   /Users/user_name/anaconda3/envs/py36_hogeを設定。
3. VSCodeを終了し、再度VSCodeを開き、デバッグ実行すると、指定した仮想環境でプログラムが実行されました。
Qiita(36) の検索の仕様が不明

Qiitaの検索で、自分の記事でうまく検索できなかった。

 ＜この記事は書きかけです。順次追記します。＞
 This article is not completed. I will add some words in order.
# 1. 「人工知能は人間を超えるか kaizen」

で出てくるのは３件

<img width="692" alt="スクリーンショット 2019-07-28 15.05.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/936298e7-e746-08d8-268f-a4a3e9b33291.png">

仮説・検証（36）機械学習・深層学習でできること、できないこと。仮説１０個。
https://qiita.com/kaizen_nagoya/items/41a567f149f78145fd4c

製造業における機械学習
https://qiita.com/kaizen_nagoya/items/fbe846de16f74bea1d6f

情報工学の専門家に読んで欲しい月刊「技術士」の記事544
https://qiita.com/kaizen_nagoya/items/29ea1465cc228de17ca6


# 2.「人工知能は人間を超えるか kaizen_nagoya」

で出てくるのは5件

<img width="689" alt="スクリーンショット 2019-07-28 15.06.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/4cf7d148-dbbe-8646-984b-ac3bbe44ebea.png">

上記に加えて

「人工知能は人間を超えるか　ディープラーニングの先にあるもの」　松尾豊
https://qiita.com/kaizen_nagoya/items/4a34f36e306309bab2fc

「量子コンピュータが人工知能を加速する」参考文献一覧
https://qiita.com/kaizen_nagoya/items/ca3043e6dd3c99c99ca4

# 考察
言語屋としては、２は１の部分集合のはず。
１の方が集合としては大きい方が嬉しい。

違いは、

kaizenはIDと一致しないが、kaizen_nagoyaはIDと一致する。

IDと一致する場合には、ID検索を先にしているのかもしれない。

Qiita(0)Qiita関連記事一覧（自分）
https://qiita.com/kaizen_nagoya/items/58db5fbf036b28e9dfa6

プログラマが知っていると良い「公序良俗」
https://qiita.com/kaizen_nagoya/items/9fe7c0dfac2fbd77a945

一覧の一覧( The directory of directories of mine.) Qiita(100)
https://qiita.com/kaizen_nagoya/items/7eb0e006543886138f39

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong. 
# 文書履歴(document history)
ver. 0.01初稿　20230525
ver. 0.02 ありがとう追記　20230715
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
python 内包表記 使えるテンプレート

自分のPCのipアドレスの取得
nicのアドレスを取得

```ifconfig.py
import netifaces as n
icmp = lambda x: [*map(int, x.split('.'))]
nn=sorted([n.ifaddresses(i)[n.AF_INET][0]['addr'] for i in n.interfaces() if n.AF_INET in n.ifaddresses(i)],key=ipcmp)
print(nn)
```
ラムダ式は、アドレスをソートするためにstringからintに変換している

``` result.txt
['127.0.0.1', '192.168.1.10']
```
#よく使う内包表記
##自分のいるネットワークの一覧表
### 無料wifiでやらないでください。

```myNet.py
from kamene.all import *
import requests,json
mac=lambda m:(requests.get('http://macvendors.co/api/%s'% m).json()['result'])['company']
ipcmp = lambda x: [*map(int, x[0].split('.'))]
net=sorted([(x[1][ARP].psrc,x[1][ARP].hwsrc) for x in arping('192.168.1.*', timeout=1, verbose=0)[0]],key=ipcmp)
for x in net: print("%-16s %-20s %-20s"%(x[0],x[1],mac(x[1])))
```

```result.txt
192.168.1.1      xx:xx:xx:3f:8a:21    Mitsubishi Electric Corporation
192.168.1.11     xx:xx:bc:2d:e4:77    PEGATRON CORPORATION
192.168.1.90     xx:xx:92:10:3c:f6    SEIKO EPSON CORPORATION
192.168.1.108    xx:xx:eb:97:47:1a    Raspberry Pi Foundation
192.168.1.111    xx:x:xeb:97:47:1a    Raspberry Pi Foundation
192.168.1.119    xx:xx:2d:68:24:3d    Espressif Inc.      
192.168.1.151    xx:xx:77:17:5d:70    HangZhou Gubei Electronics Technology Co.,Ltd
192.168.1.155    xx:xx:8e:a7:d8:3a    Espressif Inc.      
192.168.1.160    xx:xx:42:75:18:71    HangZhou Gubei Electronics Technology Co.,Ltd
192.168.1.161    xx:xx:42:63:0d:93    HangZhou Gubei Electronics Technology Co.,Ltd
192.168.1.199    xx:xx:xx:21:11:fd    SNOM Technology AG  

```
VSCode + Pipenv で Python Invoke をデバッグする

## TL;DR
`pipenv run which invoke` の結果を `launch.json` の `program` に指定

## 概要
サクッと CLI ツールを作るときには [Python][python] + [Invoke][invoke] が便利です。
Invoke を解説する記事はたくさんあるので、この記事では省略します。
本記事では、 VSCode で Invoke を用いた開発をする際にデバッグする方法を解説します。

## 環境
* [Python 3.7.3][python]
* [Pipenv 2018.11.26_2][pipenv]
* [Invoke 1.2.0][invoke]
* [Visual Studio Code 1.36.1][vscode]

コードは [Github][github] に置きました。

[python]: https://www.python.org/
[pipenv]: https://docs.pipenv.org/en/latest/
[invoke]: http://www.pyinvoke.org/
[vscode]: https://azure.microsoft.com/ja-jp/products/visual-studio-code/
[github]: https://github.com/lasta/study-pyinvoke

## デバッグ対象のコード
デバッグ対象として、フィボナッチ数の計算プログラムを用意しました。
`num` で受け取った数番目のフィボナッチ数を返却します。

```python:tasks.py
#!/usr/bin/env python

from invoke import task


@task
def fibonacci(c, num):
    n = int(num)
    if n < 0:
        print("[Error]: num must be natural number or 0.")
        exit(1)

    print(calculate_fibonacci(n))

def calculate_fibonacci(num: int) -> int:
    if num < 0:
        raise ValueError("num must not be negative.")
    
    if num == 0:
        return 0
    
    if num == 1:
        return 1

    n_2 = 0 # fib[n-2]
    n_1 = 1 # fib[n-1]
    n = 1 # fib[n]

    for _ in range(1, num):
        n = n_2 + n_1
        n_2 = n_1
        n_1 = n
    
    return n

```

また、下記のコマンドで仮想環境を作成し、 invoke をインストールしました。

```console
$ cd path/to/project
$ pipenv --python 3.7
$ pip install invoke
```

## VSCode の設定

### 仮想環境
`Pipfile` が存在するディレクトリで `code .` を実行することで、 VSCode は自動的に仮想環境を認識します。

<img width="379" alt="vscode-pipenv.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13008/2972b172-7902-98e8-2a86-b0df8b3771b6.png">


### デバッグ
Debug -> Configure or Fix `launch.json` でデバッグ環境の設定を開きます。

<img width="1050" alt="open-debug-config.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13008/826f0151-6411-83f9-0a78-2e95369b327d.png">

`launch.json` の `.configurations[]` にデバッグの設定を追加します。
今回は `invoke fibonacci --num 10` をデバッグ実行するような設定にします。

`invoke` を用いたプログラムは `tasks.py` を `python` コマンドで直接起動せず、 `invoke` コマンドで起動します。
そのため、デバッガに指定するプログラムファイルは `tasks.py` ではなく `invoke` 自身になります。

`invoke` コマンド自身は Python プログラムになります。
`invoke` 自身は仮想環境にて管理されているため、下記のコマンドで探します。

```console
$ pipenv run which invoke
```

この結果を `launch.json` の `program` に指定することで、デバッグ実行可能になります。

```json
{
    "name": "Python: Debug invoke fibonacci --num 10",
    "type": "python",
    "request": "launch",
    "program": "path/to/invoke", // `pipenv run which invoke` の結果を挿入
    "console": "integratedTerminal",
    "args": ["fibonacci", "--num", "10"]
}
```

<img width="1135" alt="after.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13008/7bf9f1c7-7b27-0da7-b1bb-23e807d58655.png">

これで Invoke を用いたプログラムも VSCode でデバッグ実行できるようになりました。

## まとめ
今回は Invoke を用いたプログラムを VSCode でデバッグする方法を紹介しました。
Invoke に限らずエントリポイントをラップする種のライブラリも同様の方法でデバッグ実行可能になります。
ゲートウェイ設定にハマる


わたしは片手間に、サーバやネットワークを やらされております。
（専門外なのに・・・）
先日、サーバのネットワークが つながらなくて困りました。

## 困った現象

ある Linux(CentOS7) サーバについて、もともと次の設定で運用していました。
※ 以下のＩＰアドレス等は、架空のものです。

>
>ifcfg-em1（``未使用``）
>ifcfg-em2 (192.168.1.10)（ローカルアドレス。使用中。）
>

つまり、サーバは外部に公開せず、ローカルで使っていました。
これに、グローバルアドレスを追加で有効にしたのです。

>
>ifcfg-em1 (12.34.56.78)（グローバルアドレス。``使用開始！``）
>ifcfg-em2 (192.168.1.10)（ローカルアドレス。使用中。）
>

ところが、グローバルアドレスに対して PING が通らないのです。
グローバルの ``ifcfg-em1`` は確かにＵＰしているのに、です。

## PING で調べる

いろいろ調べると、不思議な現象を確認しました。
グローバルアドレスと同じセグメントからなら PING が通ることに気づきました。

例えば、設定したグローバルアドレスが ``12.34.56.78`` なら、
``12.34.56.80`` の別サーバからは PING が通るのです。

（しかしセグメント外の、例えば自分のＰＣからは PING が通りません。）

さらに不思議なことに、まったく同じ設定の別のサーバでは、
グローバルアドレスに PING が通るのです。

別のサーバというのは、ＯＳや基本設定（２種類のネットワークを使う）は
同じで、ＩＰアドレスだけが異なるサーバのことです。

私はこの正常サーバと、今回の異常サーバで何が違うのか、
いろんなコマンドを投入して調べました。

## ファイル比較で相違点を発見

ようやく相違点を発見しました。
正常／異常サーバで、``GENERAL.DEFAULT`` なるものが違っていました。

異常サーバのグローバルアドレス

```
# nmcli c s em1
    ：
GENERAL.DEVICES:  em1
GENERAL.STATE:    アクティベート済み
GENERAL.DEFAULT:  いいえ
    ：
```

同じく異常サーバのローカルアドレス

```
# nmcli c s em2
    ：
GENERAL.DEVICES:  em2
GENERAL.STATE:    アクティベート済み
GENERAL.DEFAULT:  はい
    ：
```

上記は異常サーバですが、正常サーバでは、
はい／いいえ がどちらも反転していたのです。
（グローバル側が「はい」、ローカル側が「いいえ」でした。）

さらに、ルーティングテーブル？（←ゴメン よく知らないの）の順番も
違うことに気づきました。（ローカル側が上に表示されていました。）

```
# ip route

default via 192.168.1.1 dev em2 proto static metric 102
default via 12.34.56.1 dev em1 proto static metric 101
```

これも正常サーバでは、順番が逆でした。

## ＯＳによるゲートウェイ設定の違い

冒頭に述べたとおり、わたしは片手間にサーバを担当しています。

以前は CentOS5 を扱っていて、ゲートウェイの設定箇所は
``/etc/sysconfig/network`` の１ヶ所でした。

今回の問題のサーバは CentOS7 で、ゲートウェイは
ネットワークごとに複数箇所で設定できるようです。つまり、
``/etc/sysconfig/network-scripts/ifcfg-em1`` でも設定できるし、
``/etc/sysconfig/network-scripts/ifcfg-em2`` でも設定できます。

なので、**「グローバル／ローカル 両方にゲートウェイを設定するんだな」**
と理解していました。実際それで、問題なく運用しているサーバもありました。

しかし もしかしたら、それは たまたま上手くいっていただけかもしれません。
よくよく考えたら、ゲートウェイが複数ってのは妙です。
サーバから外部に通信するとき、ゲートウェイは１つで十分だからです。

もし２つあれば、どちらかを優先して、もう一方は使われないんじゃないか・・・？
その使われないほうが、グローバルアドレスのゲートウェイなのでは・・・？
だから外部から PING が通らないんじゃないか・・・？

おぼろげながら原因が見えてきました。
ただ残念なことに、どんなコマンドで修正すればよいか分かりませんでした。

コマンドはあきらめ、設定ファイルを直接 修正することにしました。
（ネットでは、設定ファイルの直接の修正は非推奨で、
コマンドを使えとありましたが、私には それしか方法がありませんでした。）

``/etc/sysconfig/network-scripts/ifcfg-em2``（ローカルアドレス）の
ゲートウェイの行を削除し、サーバを再起動しました。

```
    ：
DEVICE=em2
ONBOOT=yes
IPADDR=192.168.1.10
PREFIX=24
GATEWAY=192.168.1.1   ← ← ← 削除
    ：
```

## 結果は・・・？

グローバルアドレスに対して PING が通りました！！
（よかったよかった）

やはりゲートウェイを複数 設定していて、ローカルの方が優先されていたから、
グローバルのほうが無視されていたようです。

それにしても、疑問が残ります。
複数のゲートウェイを設定していて、グローバルアドレスに つながるサーバもあります。
（この場合はローカル側のゲートウェイが無視されているはず。）

どちらを優先するか、どう決めているのでしょう？？？
そういえば、正常／異常サーバの違いがありました。

正常サーバでは、グローバル／ローカルアドレスを、最初から両方ＵＰしていました。
一方 異常サーバでは、最初 ローカルアドレスのみをＵＰしていて、
後でグローバルアドレスを追加でＵＰしました。違いといえば それくらいです。

:thinking: :thinking: :thinking:

この対応のために、１日無駄にしてしまいました。
サーバ専門の担当者を雇ってほしい・・・。