OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】スライドショーレスポンシブ対応

# 仕様
- 表示されるのは1枚
- スライドが最後までいくと最初に戻りループさせる
- 現在のスライドに対応するポインタを表示

# html
slideとdotの数は同じにする

```index.html
<div class="slideshow">
    <div class="slide-contents" data-slide="0">
        <div class="slide slide0 active" style="background-image: url({{image-path}})"></div>
        <div class="slide slide1" style="background-image: url({{image-path}})"></div>
        <div class="slide slide2" style="background-image: url({{image-path}})"></div>
    </div>
    <div class="dots">
        <div class="dot dot0 active"></div>
        <div class="dot dot1"></div>
        <div class="dot dot2"></div>
    </div>
</div>
```

# css
画像のサイズは16:9とする

```style.css
.slideshow {
  width: 90%
  position: relative;
  overflow: hidden;
}

.slideshow .slide-contents {
  position: relative;
}

.slideshow .slide-contents .slide {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}

 .slideshow .slide-contents .slide:before {
  content: '';
  display: block;
  padding-top: 56.25%;
}

 .slideshow .slide-contents .slide.slide0 {
  display: block;
  position: relative;
}

.dots {
  margin-top: 15px;
  display: flex;
  justify-content: center;
}

.dots .dot {
  width: 10px;
  height: 10px;
  background-color: #ccc;
  border-radius: 50%;
  margin-left: 10px;
}

.dots .dot:first-child {
  margin-left: 0
}

.dots .dot.active {
  background-color: blue;
}
```

# 処理のフロー
1. 現在のスライド番号を取得し、次のスライド番号を計算する
2. 次にアクティブになるスライドにactiveクラスを付け替える（ポインタも同様）
3. アクティブにしたスライドをフェイドインで前面に表示する
4. 現在のスライド番号を更新する

１〜４を繰り返す

```slideshow.js
/*
  selector baseのcssセレクタ
  interval 次のスライドに切り替わる時間
  animationTime スライド切り替え時のアニメーション時間
*/
const slideshow = (selector, interval = 2600, animationTime = 1000) => {
  const INTERVAL = 250;
  let slideCount = 0;
  let slideBase = $(selector);
    if(!slideBase.length) {
      return;
    }
  let slideContents = slideBase.find('.slide-contents');
  let slideLen = slideContents.find('.slide').length;

  // アクティブのスライド番号を取得
  const currentNum = () => {
    return slideContents.data('slide') || 0;
  }

  // スライド番号をノーマライズ
  const normalizeSlideNum = (num) => {
    if(num == slideLen) {
      return 0;
    } else if(num < 0) {
      return slideLen - 1;
    } else {
      return num;
    }
  };

  // スライドのjqueryオブジェクトを取得
  const getSlide = (num) => {
    if(num == 'active') {
      return slideContents.find('.slide.active')
    } else {
      return slideContents.find(`.slide${num}`)
    }
  };
  
  // 実行
  const run = () => {
    var nextNum = normalizeSlideNum(currentNum() + 1);
    slideCount = slideCount + 1;
    getSlide('active').removeClass('active');
    getSlide(nextNum).addClass('active');
    slideBase.find('.dots .dot.active').removeClass('active');
    slideBase.find(`.dots .dot${nextNum}`).addClass('active');
    // チラツキ防止のため一度hiddenにしてからフェイドインさせる
    getSlide(nextNum).hide().css('z-index', slideCount).fadeIn(animationTime);
    slideContents.data('slide', nextNum);
    setTimeout(run, interval)
  };

  run();
};

slideshow('.slideshow');
```
docker+php laravel5.66

docker+php laravel5.66

phpの中にはいる（YAMファイルを作成した場所に移動する。
cd C:\Users\shimizu\Desktop\docker

最初にComposerを使用し、Laravelインストーラをダウンロードします。

composer global require "laravel/installer"

ララベルいれる
composer create-project --prefer-dist laravel/laravel blog "5.6.*"

php用のテストウェブサーバを立ち上げるにはララベルプロジェクトの中に入らないとダメ
php artisan serve

なぜか上手くいかないので、コンポーザーと一緒に入れたNginxで見ると

マウント先
/host_mnt/c/Users/shimizu/Desktop/docker/server

ポート
80/tcp
localhost:80

見れた！
SEO(Search Engine Optimization)

平成31年春期 午前問題73

SEOの説明はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/d653b28f-18f2-00d4-4ddc-ce93ed98da99.png)


１、SEO(Search Engine Optimization)とは、
Webサイトを制作するときに、Googleなどの検索エンジンの検索で上位に表示されることを目指してページやサイト全体を最適化することをいいます。

具体的な施策には、
　・上位表示を狙うキーワードを意識した文章にする
　・Webサイトの更新頻度を増やす
　・良質なコンテンツページを増やす
　・外部のWebサイトからのリンクを増やす
　・ページの表示速度を速くする
　・ユーザビリティ、アクセシビリティに配慮した設計を行う
などがあり、検索エンジンがランキングを決定する際のシグナルとして用いられていると考えられている要素を強化し、検索アルゴリズムで高評価を得ることを目標とします。

検索結果における1ページ目(1～10位)と2ページ目(11～20位)では、5倍以上の集客数の差が生じるといわれており、ECサイトにとっては上位に表示されることが売上の増加に直結するためSEOはWebマーケティングにとって重要な意味を持っています。


２、レコメンデーションrecommendation
ECサイトにおいて，個々の顧客の購入履歴を分析し，新たに購入が見込まれる商品を自動的に推奨する機能


３、アフィリエイトの説明（affiliate）
Webページに掲載した広告が契機となって商品が購入された場合，売主から成功報酬が得られる仕組み
アフィリエイトとは、インターネットを利用した広告宣伝のひとつで成果報酬型の広告のことです。 ウェブサイトの閲覧者がウェブサイトに掲載している広告主の商品あるいはサービスなどを購入し、生じた利益に応じて広告を掲載したウェブサイトに成功報酬を与える一連のインターネット広告手法のことです。

４、検索連動型広告(リスティング広告)の説明
検索エンジンを運営する企業と契約し，自社の商品・サービスと関連したキーワードが検索に用いられた際に広告を表示する仕組み


ーーーーーーーーーーーーーーーーーーーーーーーーーー
補足
SEOポイズニングの説明はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/68b07f59-bd80-ddb1-bc03-3548fe5309a4.png)


５、SEOポイズニングとは
マルウェア（不正な動作を行うようプログラムされたソフト）やコンピュータウィルスが仕込まれたホームページを人気キーワードで上位表示させ、アクセスしてきたユーザーの個人情報を不正に取得したり、ウィルスに感染させたりといった悪質な行為を指します。
検索エンジンの検索結果に、他のホームページと同じように表示されてしまうため一見しただけでは見分けがつきにくく、更に対策も追いついていないのが現状です。

SEOポイズニング【SEO poisoning】とは、検索エンジンの検索結果の上位に不正なサイトのページを表示させ、気付かず閲覧した人に詐欺サイトへの自動転送やコンピュータウイルスなどが仕込まれたページを送信する攻撃手法。


６、SSL(Secure Sockets Layer)の説明
顧客のクレジットカード番号などの個人情報の安全を確保するために，インターネット上で情報を暗号化して送受信する仕組みである。

７、SNS(Social Networking Service)の説明
参加者がお互いに友人，知人などを紹介し合い，社会的なつながりをインターネット上で実現することを目的とするコミュニティ型のサービスである。

８、SNS検索
SNSに立ち上げたコミュニティの参加者に，そのコミュニティの目的に合った検索結果を表示する。
SNSを最適化することでアクセスを集める施策としてSMO(Social Media Optimization，ソーシャルメディア最適化)という言葉があります。

９、ウォードライビング(War Driving)の説明
車などで移動しながら，無線LANのアクセスポイントを探し出して，ネットワークに不正侵入する。

１０、IDSやIPSの説明
ネットワークを流れるパケットから，侵入のパターンに合致するものを検出して，管理者への通知や，検出した内容の記録を行う。

・IDS（不正侵入検知システム）とは？
IDSはIntrusion Detection Systemの略称で、不正侵入検知システムとも呼ばれます。

インターネットに公開するサービスでは、それに対する通信はファイアウォールでは接続許可の扱いとなるため、正常な通信と異常な通信は区別なくアクセスされることになります。

そこで、IDSを設置することで、通信を監視します。
また、もし異常があれば管理者へ通知することで、異常な通信をブロックするなどの対処をするきっかけ（トリガー）となります。

・IPS（不正侵入防止システム）とは？
IPSはIntrusion Prevention Systemのことで、不正侵入防止システムとも呼ばれます。

IPSはIDSより一歩進んで、異常な通信があれば、管理者へ通知するだけでなく、その通信をブロックするところまで動作します。
したがって、管理者が異常に気づいてから対処するのと異なり、迅速な対処が可能となります。


参照：

https://www.ap-siken.com/kakomon/26_aki/q73.html
https://www.ap-siken.com/kakomon/29_aki/q37.html
https://www.itpassportsiken.com/kakomon/01_aki/q29.html
https://www.itpassportsiken.com/kakomon/27_haru/q19.html

SEOポイズニング
http://e-words.jp/w/SEO%E3%83%9D%E3%82%A4%E3%82%BA%E3%83%8B%E3%83%B3%E3%82%B0.html

アフィリエイトの説明（affiliate）
https://webtan.impress.co.jp/g/%E3%82%A2%E3%83%95%E3%82%A3%E3%83%AA%E3%82%A8%E3%82%A4%E3%83%88

IDS、IPS
https://www.shadan-kun.com/blog/measure/303/#01
sshの際に毎回　Enter passphrase for と聞かれる際の対処方法

公開鍵を設定してせっかくパスワードなしで入れるようになるはずなのに、毎回
Enter passphrase for /home/user/.ssh/id_rsa: 
と聞かれる場合の対処方法です。
鍵を登録する必要があるようです。

```
$ ssh-agent
$ eval `ssh-agent`
$ ssh-add ~/.ssh/id_rsa
```

うまくいくと鍵を生成した際のパスワードを聞かれるので入力してください。
その後sshでパスワードなしで接続できるか確かめてください。
Function Builderで `Cannot convert value of type XXX`

Xcode11.6までは単一の引数でFunction Builderが動作しないようです。

具体例を示します。
Int型を引数にとり、その合計を返すFunction Builderを実装します。

```Swift
@_functionBuilder
struct Builder {
    
    static func buildBlock(_ components: Int...) -> Int {
        print(#function)
        return components.reduce(0) { $0 + $1 }
    }
    
}

func sum(@SumBuilder _ body: () -> Int) -> Int {
    body()
}
```

次のように実行します。

```Swift
print("-- start --")
let a = sum {
    1
    2
    3
}
print(a)
let b = sum {
    7
}
print(b)
print("-- end --")
```

すると、Function Builderは一度しか実行されていません。
単一引数の場合はFunction Builderが動作していないようです。

```
-- start --
buildBlock(_:)
6
7
-- end --
```

**そのため、引数の型と戻り値の型が一致しないFunction Builderは単一引数ではコンパイルエラーになります。**

以下、単一引数で動作しない例です。
引数にString型を取りInt型に変換して合計を返すFunction Builderです。

```Swift
@_functionBuilder
struct StringSumBuilder {
    
    static func buildBlock(_ components: String...) -> Int {
        return components.map { Int($0) ?? 0 }.reduce(0) { $0 + $1 }
    }
    
}

func stringSum(@StringSumBuilder _ body: () -> Int) -> Int {
    body()
}
```

```Swift
let c = stringSum {
    "1"
    "2"
    "3"
}
// 6

let d = stringSum {
    "7" // Cannot convert value of type 'String' to closure result type 'Int'
}
```

`d`へ代入する式はString型`"7"`はコンパイルエラーとなります。

## 解決策

これはコンパイラの問題のようで、Xcode12 beta3では修正されています。
コンパイラが修正されるのを待つ以外は、引数の型と戻り値の型を一致させFunction Builderが動作せずとも辻褄が合うようにする必要がありそうです。
bashからzshへ変更

## はじめに

Macのシェルがbashからzshに変わったと聞いたんですが、
手元のMacのiTerm2を起動するとbashのままだったので、
zshに変更してみました。

その時のメモを残しておきます。

<手元のMac>
os: macOS Catalina　バージョン 10.15.6
terminal: iTerm2 build 3.3.12

## iTerm2を起動するとメッセージが出てる

```
The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
```

https://support.apple.com/ja-jp/HT208050
に詳しく書いてありました。しかも、日本語！ありがたい。

## 現在使ってるシェルを調べる

```
$ echo $SHELL
```

で調べられるみたいです。
私のMacでは

```
/bin/bash
```
と表示されました。

## デフォルトシェルをzshに切り替える

上記のメッセージに書いてった下記のコマンドを叩きます。

```
$ chsh -s /bin/zsh
```
パスワードを聞いてこられるのでパソコン(Mac)のパスワードを入力します。

よし、シェルが変わったかどうか調べます。

```
$ echo $SHELL
/bin/bash
```

うーん。。。bashのままですね。

ターミナルを一旦閉じて、開き直してみます。
↓
今度は上述のメッセージが表示されませんでした。

```
% echo $SHELL
/bin/zsh
```

おぉ、zshに変わってますね。

コマンドを入力する左側に表示されている記号も
$ から % に変わってますね。

## 設定ファイルを移植します。

[Appleの記事](https://support.apple.com/ja-jp/HT208050)に書いてありました。

> bash プロファイルを使って、環境変数、エイリアス、パス変数の設定などをしている場合は、それに相当する zsh のプロファイルを使うように切り替えてください。たとえば、以下のような場合が考えられます。
> 
> .zprofile は .bash_profile に相当し、ログイン時 (SSH ログインも含む) に実行されます。
> .zshrc は .bashrc に相当し、新しいターミナルセッションごとに実行されます。

### .bash_profile -> .zprofile

私のMacの「~/.bash_profile」ですが、

```
if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi
```
とだけ書かれてました。
書いた記憶はないですが、とりあえずこれをこのままコピーするのも変ですよね。

```
if [ -f ~/.zshrc ]; then
  . ~/.zshrc
fi
```
と書き換えて「~/.zprofile」に書き込みました。

### .bashrc -> .zshrc

~/.bashrc  の内容を　~/.zshrc  というファイルにコピペしました。

## おわりに

まだ、zshになったから何がどうなのって所まで理解できてませんが、
徐々に色々と勉強してみようと思います。

おわり。
Railsアプリのタイムゾーンを日本時間に統一する

考慮すべきタイムゾーンは以下の4つ

- Rubyプロセス
    - `Time.now`等に影響
- config.time_zone
    - `Time.zone.now`等に影響
- config.active_record.default_timezone
    - DBから受け取った時刻をどのタイムゾーンとして解釈するか
- DB
    - SQL文の`NOW()`等に影響

## Rubyプロセス
### 開発環境(Docker)
`Dockerfile`に`ENV TZ Asia/Tokyo`を追加して対応

### 本番環境
環境変数に`TZ = Asia/Tokyo`をセットして対応

## config.time_zone
### 共通
```config/application.rb
config.time_zone = 'Tokyo'
```

## config.active_record.default_timezone
### 共通
```config/application.rb
config.active_record.default_timezone = :local
```

## DB
開発環境、本番環境それぞれのDBに接続し、以下のクエリを実行

```sql
ALTER DATABASE db_name SET timezone TO 'Asia/Tokyo';
```

Postgresの場合の書き方なので、DBの種類によっては書き方が違うかも。
DBに再接続すると反映されています。
`rails:db:migrate`を実行するとタイムゾーンも元に戻ってしまいますが、そもそもRailsでSQL文を書くことも少ないのでまあ良いでしょう。
docker-compose.ymlに環境変数を設定する方法もあるみたいですが、うまくいきませんでした。

## 参考
- [Railsタイムゾーンまとめ - Qiita](https://qiita.com/aosho235/items/a31b895ce46ee5d3b444)
【GCP】ServiceAccountを使ってプロジェクトにメンバーを追加する

GCPプロジェクトに招待されてない！！
でも、ツールで使うサービスアカウントは見つけた。
サービスアカウント経由でプロジェクトに参加できないかな・・・？

そんな時の備忘録。

# サービスアカウントでGCPにログイン

公式資料：https://cloud.google.com/sdk/gcloud/reference/auth/activate-service-account

```
% gcloud auth activate-service-account email@hogehoge-project.iam.gserviceaccount.com --key-file=./hogehoge-project-123456789.json --project=hogehoge-project
```

keyfileが必要。
emailアドレスはkeyfileに書いてる。
projectidもemailアドレスから推測できた。
サービスアカウントは roles/owner 権限でした。

# アカウント追加

公式資料：https://cloud.google.com/sdk/gcloud/reference/projects/add-iam-policy-binding

```
% gcloud projects add-iam-policy-binding hogehoge-project --member=user:tsuyoshi.hori@hogehoge.com --role=roles/owner
```

確認コマンド

```
% gcloud projects get-iam-policy hogehoge-project
```

この時点でブラウザからプロジェクトが選択できました。

# サービスアカウントからログオフ

公式資料：https://cloud.google.com/sdk/gcloud/reference/auth/revoke

```
% gcloud auth revoke
```

あらためてログインが必要です。

```
% gcloud auth login
```
Nuxt.jsでURLスキームを利用してAndroidアプリを起動

Nuxt.jsでWebページを作成した場合の、URLスキームでのAndroidアプリ起動方法をまとめておきます。

# nuxt-user-agentを導入

Android端末かの判定に [nuxt-user-agent](https://github.com/fukuiretu/nuxt-user-agent) を使用します。
下記コマンドで、Nuxt.jsのプロジェクトにインストールしてください。

```bash
npm install -S nuxt-user-agent
```

`nuxt.cofig.js` ファイルに、設定を追加します。

```nuxt.config.js
modules: [
  'nuxt-user-agent'
],
```

# middlewareの作成

ユーザーエージェントを判定して、アプリ起動やストア移動を行うmiddlewareを作成します。
`const ANDROID_SCHEME = 'sample://app';` の部分で、Androidアプリを起動するURLスキームを指定しています。

```middleware/launch-app.js
export default (context) => {
  const ANDROID_SCHEME = 'sample://app';
  const isFromAndroidOs = context.$ua.isFromAndroidOs();

  if(isFromAndroidOs) {
    document.location = 'intent://#Intent;scheme=' + ANDROID_SCHEME + ';end';
  }
}

```

上記のmiddlewareを使用したいページで、middlewareの読み込みを行います。
例として、 `pages/index.vue` で読み込みを行っています。

```pages.index.vue
<script>
export default {
  middleware: 'launch-app'
}
</script>
```

# Androidアプリ側にアプリ起動用のURLスキームを設定する

Androidアプリ側に、Nuxt.jsで作成したWebページから起動するためのURLスキームを設定します。
マニフェストファイルに下記を追記するだけです。
`sample://app` でアプリが起動するように設定しています。

```AndroidManifest.xml
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- 追加ここから -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="sample" android:host="app" />
            </intent-filter>
            <!-- 追加ここまで -->

        </activity>
    </application>
```

これらの設定が終わると、Androidアプリがインストールされた端末でWebページを表示した際に、アプリが起動するようになります。
searchsortedの使い方

#1 この記事は何？
要素が順番に並んだ配列に対して、ある要素を挿入したい場合に挿入すべき場所を取得したい。


#2 使用例

```python:test.py
df = pd.DataFrame({"A":[1,3,7,8,9]})

print(df)
print(df.A)

a0=df.A.values.searchsorted(5, side='right') # a0 = 2
a1=df.A.values.searchsorted(3, side='right') # a1 = 2
a2=df.A.values.searchsorted(3, side='left')  # a2 = 1

print(a0)
print(a1)
print(a2)
```

<img width="734" alt="105.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/1fe8194a-03bb-124a-3fab-1224aada7310.jpeg">
symfonyのapi-platformでNo item route associated with the type "App\Entity\クラス名"

# はじめに

api-platformを使っていて、躓いた部分のメモです。

# 問題

Symfonyのapi-platformで開発をしていて、<code>No item route associated with the type "App\Entity\クラス名"</code>というエラーが表示された。


# 状況

MySQLのViewで作成したテーブルなので、ReadOnlyのつもりで、collectionOperationsのGETのみとして以下の設定を行った。

```php
/**
 * @ApiResource(
 *     collectionOperations={
 *      "get"
 *     },
 *     itemOperations={
 *     },
 * )
 * @ORM\Entity(repositoryClass=hogehoge::class, readOnly=true)
 * @ORM\Table(name="view_hogehoge")
 */
```

以下の画面でも正常に表示されているので良さそうな感じ。

![2020-08-13_11h55_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/72a09aa4-7bed-0fbe-2984-2c4f4c319e05.png)

しかし、実際にAPIを呼び出すと、エラーを吐く

![2020-08-13_11h57_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133291/64054102-5c13-c0da-9504-9ef398a298c3.png)

# 回答

アノテーションの以下の書き方がダメ。
Issuに上がっていた。
https://github.com/api-platform/core/issues/3501

```php
 *     itemOperations={
 *     },
```

こちらのように書くと動作する

```php
/**
 * @ApiResource(
 *     collectionOperations={
 *      "get"
 *     },
 *     itemOperations={
 *         "get"={
 *             "method"="GET",
 *             "controller"=NotFoundAction::class,
 *             "read"=false,
 *             "output"=false,
 *         },
 *     },
 * )
 * @ORM\Entity(repositoryClass=hogehoge::class, readOnly=true)
 * @ORM\Table(name="view_hogehoge")
 */
```

# 言い訳

R/Wできるテーブルで使っているので、R/Oの場合にちょこっと書き方を変えたら躓いてしまった。

しかも、利用者が少ないのか、日本語での回答がなかったので書いてみました。
【SwiftUI】@Bindingや@Stateをつけたプロパティをイニシャライザで初期化する

# Error: 'self' used before all stored properties are initialized

こんな感じで素直にイニシャライザを定義してしまうと、上記のエラーが発生します。

```swift:WrappedTextField.swift
struct WrappedTextField: View {
    private var placeholder: String?
    @Binding private var textContent: String
    
    init(placeholder: String? = nil, textContent: String) {
        self.placeholder = placeholder
        self.textContent = textContent
        // Swift Compiler Error
        // 'self' used before all stored properties are initialized
        // Return from initializer without initializing all stored properties
    }
    
    var body: some View {
        TextField(placeholder ?? "", text: $textContent)
            .multilineTextAlignment(.center)
    }
}
```

# 解決方法

Property Wrapperをつけたプロパティを初期化するには、暗黙的に定義される`_textContent: Binding<String>`を使用する必要があります。

```swift
@Binding private var textContent: String
    
init(placeholder: String? = nil, textContent: Binding<String>) {
    self.placeholder = placeholder
    self._textContent = textContent
}
```

イニシャライザを自分で定義しなければ、呼び出し側では自動的に引数の型がBinding<String>となるため、Property Wrapperのことを意識しなくても使えるのですが、カスタムのイニシャライザを用意する場合は、Property Wrapperについて知っておかないといけません。

# 参考

[Property Wrapper 入門](https://qiita.com/kymmt/items/a8fa17d12f63a74ac123)
【Vim】編集中ファイルのリネームをショートカットで簡単にする設定

## 背景
- vim編集時でもファイルリネームをしたい時に、以下の点で気になったため、可能であるのか調査。
  - 長いコマンドではなく、キーバインドを利用してショートカット風に短くしたい。
  - `:w`のような保存処理を忘れたとしても、自動で行えるようにしたい。
  - 対話的に処理を行えるようにしたい。
- そこでLeader機能を利用して、簡単リネーム設定を記述していく。

## 手順
- vimrc(設定ファイル)を開く。

```bash
vim ~/.vimrc
```

- 下記の内容を`.vimrc`へ書き込む。

```vim:~/.vimrc
" leader設定
" 「スペースキー + 他キー」で利用できるようにする。
let mapleader = "\<Space>"

" リネーム関数呼び出し
" vim上で「スペースキー + n」でリネーム処理が行えるようにする。
map <leader>n :call RenameCurrentFile()<cr>

" リネーム関数定義
function! RenameCurrentFile()
  let old = expand('%')
  let new = input('新規ファイル名: ', old , 'file')
  if new != '' && new != old
    exec ':saveas ' . new
    exec ':silent !rm ' . old
    redraw!
  endif
endfunction
```

- vim内で設定読み込み。

```vim
:source ~/.vimrc
```

- 試しに変更したいファイルをvimで開き、「**スペースキー + n**」で下記のように変更して、問題なければ完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/ae563e24-a9f3-84f6-fa3a-597588227515.png)

## 参考
- [編集中ファイルのファイル名を変更する](https://vim-jp.org/vim-users-jp/2009/05/27/Hack-17.html)
- [map・Leaderドキュメント](https://vim-jp.org/vimdoc-ja/map.html)
部品化とテスト_メモ_20200813

#部品化とテスト


**１．テストにより品質を確認する**

　　　　テスト、試験を行わなければ品質が高いか、完成しているかを判断できません。
　　　　
　　　　開発が行われる際は、テストまで終わって初めて完成と言えます。
　　　　仮に間違いが一つも含まれていないプログラムであってもそのことがテストで検証されていなければ
　　　　完成とは言えないのです。

　　　　テストという工程は一見誰でもできるんじゃないかという見方もされがちですが
　　　　エンドユーザーに引き渡す際に最後の砦となる大事な工程なのです。
　　　　「こんなもんでいいか」という考えから再テストになるという事案も筆者はよく耳にします。

**２．埋もれるエラー**

　　　　自分1人だけで開発している単一クラスの小さなプログラムなら、テストはとても簡単です。
　　　　コマンドなどで何度か動かしてみれば問題があるかどうかはわかるでしょう。

　　　　一方で開発現場などの数十～数百のクラスで構成されているような大きなプログラムの場合、
　　　　テストは格段に難しくなります。
　　　　実行してみてエラーが発生した場合、巨大なプログラムのいったいどこに問題があるのかを
　　　　判断するのはとても難しいことだからです。

　　　　例えると広大な砂漠の中からオアシスを探すようなものですね。
　　　　プログラムが大きくなればなるほどエラーを見つけるのは難しくなります。

![コメント 2020-08-13 110316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687164/269acb00-bb7b-1a9d-fa6a-c6fdce16ecbc.png)



**３．部品化**

　　　　２で分かるように、大きなプログラムを一度にテストしようとすると大変です。
　　　　つまり、複数のクラスから構成されているプログラムを一度にテストする、ことが大変なのです。

　　　　一気にテストするということはよほどのことがあってもほとんどないでしょう。
　　　　実際の開発現場では下記の図のように、
　　　　**「単体テスト」「結合テスト」「総合テスト」**という段階を踏んで少しずつテストを進めます。

![コメント 2020-08-13 110317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687164/1c9911e3-3d81-e27d-a7df-de8d0cde4bd8.png)


**４．チームでの開発**※筆者のメモのようなものなので興味がない、知ってるわという方は読み飛ばしてください。

　　　　上の説明でもあった通り、大きなプログラム開発になればなるほどたくさんの開発者が必要となります。
　　　　よくコミュニケーション力があるかなども問われることがありますがなぜかを考えてみましょう。

　　　　Aさんはすごく技術力がありますがコミュニケーションがとりずらく、進捗やトラブル報告があいまいです。
　　　　それに会社に来ないこともあります。

　　　　一方Bさんはプログラム開発の経験が浅く、勉強中といった感じです。
　　　　しかし、報告連絡相談は欠かさず人柄がよくコミュニケーションがとりやすい人です。
　　　　欠席率も低いです。

　　　　さあここでどちらのエンジニアが必要とされやすいでしょうか。
　　　　技術力だけで言うならAさんのほうが必要とされそうですね。
　　　　しかし、大体の開発現場で必要とされるのはBさんのような開発者です。

　　　　なぜ技術力ではおとっているのにBさんなんだと思われる方もいるかもしれません。
　　　　その理由はチームで開発を行うからです。趣味でプログラムを作るのではなく、チームで協力して
　　　　大きなプログラムを作るからです。

　　　　部品化して作業をすることもですが、ソロプレイをしてしまうといくら技術力があってもということですね。


以上、どうでしたでしょうか。
また、間違っている知識などがございましたらご指摘いただければ幸いです。
最新版OpenPBSをCentOS6にインストールしてクライアントノードとして動かす

### 前提
* 既にあるPBSサーバ (192.168.1.1 : pon) に新しいクライアントノード (192.168.1.2 : suke) を追加する
* サーバはCentOS7だが（あまり関係ない）追加したいクライアントはCentOS6
* 最新版のOpenPBSを想定
* pon と suke は **必ず** 同一サブネットにいること　

### 以下、新規PBSクライアント suke での作業
### Python>=3.6 を IUS Community Project リポジトリ からインストール

- リポジトリ追加して python36-devel インストール
- CentOS6 の```python``` は ```/usr/bin``` に 2.6 だかが入ってるけど、これを上書きしてしまうと```yum```自体やらなんやらが動かなくなる可能性有り
- ```/usr/local/bin``` と ```/usr/local/lib``` に ```python36``` として置くことにする

```
# yum install -y https://repo.ius.io/ius-release-el6.rpm
# yum install -y python36-devel.x86_64
# cd /usr/local/bin
# ln -s /usr/bin/python3* .
# ln -s python36 python3
# cd /usr/local/lib
# ln -s /usr/lib/python3* .
```

### swig 3 を python36 に絡めてインストール
- ソースを取得　http://swig.sourceforge.net/download.html

```
$ cd swig-3.0.12
$ ./configure --with-python3=/usr/local/bin
$ make
# make install
```

###OpenPBSのソースを取得
- サーバ pon のPBSと同じバージョンを入手、バージョン確認の方法はサーバ上で ```qstat --version```
- https://github.com/openpbs/openpbs/releases

### INSTALL を読んで依存関係をチェックし、足りないのを入れる
```
$ cd openpbs-master
$ less INSTALL
```

- ```For CentOS-7 systems you should run the following command as root:``` とか書いてあるけどCentOS6でも同じ
- 今回の場合、自分が入れたのは
 
```
# yum install -y libtool hwloc-devel autoconf libX11-devel \
      libXt-devel libedit-devel libical-devel postgresql-devel \
      tcl-devel tk-devel expat-devel openssl-devel libXext libXft
```     

### OpenPBS インストール！
- ```--prefix=/opt/pbs``` とかが流行ってるようだけど面倒なのでしない。お好きに。

```
$ ./configure --with-python=/usr/local --with-swig=/usr/local
```

- もし ```checking for libical... configure: error: libical headers not found.``` 等のエラーが出たら、```ical.h``` が、```/usr/include``` でなく、```/usr/include/libical``` に入っているのかも。下記のようにしてから再度 ```./configire```

```
$ cd /usr/include
$ ln -s /usr/include/libical/* .
```

configure が通ったら

```
$ make
# make install
# /usr/local/libexec/pbs_postinstall
```



- 最後の ```libexec/pbs_postinstall``` で、```/etc/pbs.conf```, ```/etc/init.d/pbs```や、```/var/spool/pbs``` ディレクトリが作られる

### OpenPBS設定
```
# vi /etc/pbs.conf
 ... 省略 ...
# cat /etc/pbs.conf
  PBS_SERVER=pon
  PBS_START_SERVER=0
  PBS_START_SCHED=0
  PBS_START_COMM=0
  PBS_START_MOM=1
  PBS_EXEC=/usr/local
  PBS_HOME=/var/spool/pbs
  PBS_CORE_LIMIT=unlimited
  PBS_SCP=/usr/bin/scp

# vi /var/spool/pbs/mom_priv/config
 ... 省略 ...
# cat /var/spool/pbs/mom_priv/config
  $clienthost pon

# cat /etc/hosts
  192.168.1.1    pon
```

### OpenPBS起動
```
# /etc/init.d/pbs start
$ /usr/local/bin/qstat     ### test
```

### 以下、PBSサーバ pon での作業
- クライアントノード suke を追加
- 導通がちゃんとしてればマシンの情報を自動で取れる

```
# cat /etc/hosts
  192.168.1.2   suke
# qmgr
Qmgr: create node suke
Qmgr: p n suke
  create node suke
  set node suke state = free
  set node suke resources_available.arch = linux
  set node suke resources_available.host = suke
  set node suke resources_available.mem = 99194464kb
  set node suke resources_available.ncpus = 24
  set node suke resources_available.vnode = suke
  set node suke resv_enable = True
  set node suke sharing = default_shared
```
- suke が待つべきキューを追加してあげよう

```
Qmgr: set node suke resources_available.Qlist = SMALL
```

以上
PowerShell の return は変数に格納したほうがエラー処理的に安全だという話

いわゆる early-return というものを PowerShell でやろうとしたときにハマったのでメモ。

## 環境
```

Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
OS                             Microsoft Windows 10.0.18362
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

```

## 経緯

PowerShell では見出しが重複した csv を `ConvertFrom-Csv` しようとするとエラーが出ます。

```
PS> cat .\target.csv
AA,AA,BB
10,20,30
40,50,60

PS> cat target.csv | ConvertFrom-Csv
ConvertFrom-Csv: The member "AA" is already present.
```

しかし次の関数を実行してみると……

```PowerShell
function func1 {
    if($true){
        return (cat target.csv | ConvertFrom-Csv)
    }
    Write-Output "ここは出力されてほしくない"
}
```
![コメント 2020-08-13 113407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/ee53ba72-c451-11aa-e2cd-0cf08b4e7be3.png)
　!?

どうも return に失敗すると **return 処理が無視されて** 以降の行に処理が移っている様子。`-ErrorAction` パラメータに `Stop` を指定しても関係ないようです。

```PowerShell
function func2 {
    if($true){
        return (cat target.csv | ConvertFrom-Csv -ErrorAction Stop)
    }
    Write-Output "ここは出力されてほしくない"
}
```
![コメント 2020-08-13 113444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/d46d9810-bdc3-7c60-6cf0-6794de976729.png)


明示的に `Write-Output` するとその行でエラーとして処理が止まるようです。しかし記述を簡略化するための early-return で文字数が増えるのは本末転倒……

```PowerShell
function func3 {
    if($true){
        cat target.csv | ConvertFrom-Csv | Write-Output
        return
    }
    Write-Output "ここは出力されてほしくない"
}
```
![コメント 2020-08-13 113517.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/77353be8-96d4-ff76-15dc-27bfffdf1c96.png)


変数に格納するようにしたらちゃんとエラー扱いになりました。少し記述が減ります。

```PowerShell
function func4 {
    if($true){
        $ret = (cat target.csv | ConvertFrom-Csv)
        return $ret
    }
    Write-Output "ここは出力されてほしくない"
}
```
![コメント 2020-08-13 113548.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/1561f6f1-1a74-7885-728f-db201dc28202.png)


変数に格納すればよいことがわかったので、 `return $()` とするのが最も簡単ですね。

```PowerShell
function func5 {
    if($true){
        return $(cat target.csv | ConvertFrom-Csv)
    }
    Write-Output "ここは出力されてほしくない"
}
```
![コメント 2020-08-13 113616.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501098/041f8843-85c7-0116-ce0a-53750fc513f2.png)

結局、`$` 1つ加えるだけで良かったのでした（しかし Qiita のシンタックスハイライト的にはエラー…？）。

## 結論

**return 内容は変数に格納するべし。**

return 処理自体がなかったことになるのは結構な罠ですね。[ドキュメント](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7) にも `()` はその中をすべて評価してから以降にパイプするという以上の説明がないので慌てました。心臓に悪い……。
【Java】switch文のcaseに文字列入れる場合は定数式にする必要がある 

結構今さら感があると思うのだが、知らなかったので自分用のメモ。
すぐ忘れそうだが。 

# こんな例はコンパイルエラーになります

例えば

```java
public class SwitchTest {
    static final String ddd = "ddd";
    static String ccc = "ccc";
    public static void main(String[] args) {

        String bbb = "bbb";

        final String eee = "eee";

        switch(args[0]) {
            case "aaa":
                System.out.println("aaa");
                break;
            case bbb:
                System.out.println("bbb");
                break;
            case ccc:
                System.out.println("ccc");
                break;
            case ddd:
                System.out.println("ddd");
                break;
            case eee:
                System.out.println("eee");
                break;
            default:
                System.out.println("default");
                break;
        }
    }
```

というコードを書いたとする。 
しかし、これはコンパイルエラーになる。
ちなみに以下のようなエラーが出る。

```shell

SwitchTest.java:14: エラー: 定数の文字列式が必要です
            case bbb:
                 ^
SwitchTest.java:17: エラー: 定数の文字列式が必要です
            case ccc:
                 ^
```

要するにcaseにいれる文字列は「定数」でなければならない（final句が必要）ということのようだ。
実際、ddd（``static final``）とeee（``final``）はコンパイルエラーとして抽出されていない。
また、caseに直接文字列を書く（``"aaa"``）と、ここでいう「定数」の扱いになるらしくてコンパイルエラーとして抽出されない。
まあ「変数」じゃあないもんね。。

なお、コンパイルエラーとして返ってきた出力をそのまま使っているので「定数」というキーワードを持ち出しているが、正確に言うとこれは「定数」という呼称？表現？ではないようだ。 
この辺は[ここ](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28)に書かれている。
Constant Expressionだから日本語にすると「定数式」というのが正しいのかな？
例えばこれによると``+``を用いた演算も「定数式」にあたるらしく、

```java
...
    case "aaa" + "xxx":
        System.out.println("aaa+xxx");
        break;
...
```

こういうのもコンパイルは通る。
ただ結合対象にfinalがついてない変数（例えば上記で言うbbb）を使って``"aaa" + bbb``とかするとやっぱりコンパイルエラーになる。

switch文を文字列で使うことがあんまりなかったので今まで知らなかった。
勉強になりました。（？）
MinikubeをBrewでインストールしてもパスに通らない時の対応方法

# まずは結論。
* brew link minikube
を打つと良い。

## 順を追って説明
brewでminikubeをインストールしてうまくいった。（と思ったが）

```
$brew install minikube
```

ただ、minikube startしようとしても、そもそもminikubeコマンドがパスに通っていない。

```
$minikube start
```

もう一回インストールしようとすると、brew linkをうつ必要があったぽい

```shell
$brew install minikube
Updating Homebrew...
Warning: minikube 1.12.3 is already installed, it's just not linked
You can use `brew link minikube` to link this version.
```

打ってみる。
```
$brew link minikube
Linking /usr/local/Cellar/minikube/1.12.3... 3 symlinks created
```

ちなみに、メモリ指定が0MBになってしまっていた模様。
```shell
$minikube start
~中略~
💣  Requested memory allocation 0MB is less than the usable minimum of 1024MB
```

指定してみる。
```
$minikube start --memory=1024MB
```

## 振り返り
最近minikubeを使っていなくて、アンインストールしたかも覚えていないけれど、再度使おうとしたときなどに発現するのか、どういった状況で発生するかは不明。
GCPのコマンド(SDKコンポーネント群)の一覧

## コマンド構成
```
# gcloud {GROUP指定} {操作} {ターゲット} {オプション}
# ex) [a]というインスタンスを作成
gcloud compute instance create a
```

## SDKコンポーネント群一覧
### SDKに含まれる
|コマンド名|名称|内容|
|:--|:--|:--|
|gcloud|Default set of gcloud commands|全ての基本になるコマンド群。認証やコンポーネントアップデートを司る。以下で紹介する以外の全てのコマンドを行える|
|(core)|Cloud SDK Core Libraries|全ての基本になるコア機能ライブラリ|
|gsutil|CLoud Storage Command Line Tool|ClouStorage専用のコマンド。コピーやsyncなどの処理が可能|
|bq|BigQuery Command Line Tool|BigQuery専用のコマンド|

### SDKに含まれない
|コマンド名|名称|内容|
|:--|:--|:--|
|kubectl|kubectl|GKE専用コマンド。gcloud components update kubectlのように、gcloudコマンドを使ってインスロールする|
|gcd-emulator|Cloud Datastore Emulator|クラウドデータストア をエミュレートするコマンド群|
|pubsub-emulator|Cloud Pub/Sub Emulator|クラウドPub/Subをエミュレートするコマンド群|
|alpha|gcloud Alpha Commands|alpha扱いのコマのdが利用可能になる「gcloud alpha {xxx}」のように使用する|
|beta|gcloud beta Commands|beta扱いのコマンドが利用可能になる「gcloud beta {xxx}」のように使用する|
|app-engine-java|gcloud app Java Extensions|GAE Java用のライブラリ、開発環境など|
|app-engine-python|gcloud app Python Extensions|GAE Python専用のコマンド、開発環境|
AR Foundation 4.0 以上でカメラが表示されないときの対応

## 何があったか

[Android用ARCore拡張機能のクイックスタート](https://developers.google.com/ar/develop/unity-arf/quickstart-android) の通りに動かしたのにカメラが表示されずに真っ暗！！
カメラのパーミッション確認も表示されない。

※下記画像が実行時の画面です。
<img width="300" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/7467813c-9fde-fd32-d920-d60caab6001d.png">

## 環境

- Windows 10 Pro Version.1909
- Unity 2019.4.7f1
- ARCore Extensions for AR Foundation v1.18.0

## 発生手順

1. [Android用ARCore拡張機能のクイックスタート](https://developers.google.com/ar/develop/unity-arf/quickstart-android) の通りに、package.jsonファイルを選択してインストール
2. AR Fundation と ARCore XR Plugin のバージョンを確認すると、preview.6 - 3.1.0 
3. [Android用ARCore拡張機能のクイックスタート](https://developers.google.com/ar/develop/unity-arf/quickstart-android) に下記のように記載があるため、preview.6 - 4.1.0 にアップデート

    > ・AR Foundation package version 4.0.0.
    > ・ARCore XR Plugin package version 4.0.0.
    > You may encounter compatibility issues if you do not use these versions.

4. Hierarchy から Main Camera を削除
5. Hierarchy に AR Session Origin と AR Session を追加
6. [Android用ARCore拡張機能のクイックスタート](https://developers.google.com/ar/develop/unity-arf/quickstart-android) の通りに、プロジェクトを設定

## 解決方法

- XR Plug-in Management の Plug-in Providers を設定
    1. Project Settings > XR Plug-in Management を選択
    2. Plug-in Providers の ARCore のチェックを入れる

<img width="600" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/ba0c3b05-00c4-0b1f-8b60-fc8a03bbc769.png">

## XR Plug-in Management の Plug-in Providers について

[About AR Foundation | AR Foundation | 4.0.2](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.0/manual/index.html) に下記のように記載がありました。

> Provider plugin setup
> Provider plugins must be enabled before AR Foundation can use them. XR Plugin Management provides a UI to enable specific plug-in providers for each target platform.

![](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@4.0/manual/images/enable-arcore-plugin.png)
IQ Bot Community Edition A2019.15 新機能 (OCRエンジン追加、カスタムロジック追加)

2020年8月11日に[A2019.15 Community Edition (ビルド 5931) がリリース](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/release-notes/release-a2019-15.html?_LANG=jpjp)されました。A2019.15自体には新機能はほとんどないのですが、IQ Bot Community Editionには大きな変更が2点ほどあるようです。ちなみに、機能自体はIQ Bot Version 11.3.4.2と同等のようです。

* ABBYY以外のOCRエンジン (Tesseract4、Microsoft Azure、Google Cloud) がサポートされるようになりました。
* [カスタムロジック](https://qiita.com/IQ_Bocchi/items/1d8e7c77ad47e838476c)として使えるPython/pandasライブラリが増えました。

※ IQ Bot Community Editionの特徴と制限については、 @IQ_Bocchi さんの記事『[IQ Botのコミュニティ版が今日（2020.4.23）復活！！](https://qiita.com/IQ_Bocchi/items/63cc4ec70d1c73a8b280)』を参照してください。
※ IQ Botってそもそも何？という人はこちらの記事をご覧ください。: 『[IQ Botとは](https://autodojo.hatenablog.com/entry/IQBot)』

# IQ Bot Community Editionを触ってみる

### 最初のオプションの設定
IQ Botには、A2019 Community Editionのホーム画面からアクセスできます。IQ Botのホーム画面で「始める」ボタンをクリックすると、「ラーニングインスタンス」が作られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/6d0bdc5e-1ca4-9223-3c2c-07fbef78d5e5.png)
**※ IQ Bot Community Editionのナビゲーションウィンドウは「ホーム」と「ラーニングインスタンス」のみで、Enterprise版にある「ドメイン」「BOT」「管理」はありません。**

しばらく「インスタンスを作成中」の画面が出ます。少し時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/db50a098-0df7-b710-089f-cf21a5377def.png)

ラーニングインスタンスができると、以下の画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/030d60c4-bed6-6c29-d7e1-72925d75a1f0.png)

ドキュメントタイプ ([ドメイン](https://qiita.com/IQ_Bocchi/items/a10df61cc7f070e93db1)) は、いろいろなものが用意されていますが、すべて英語のフォームです。Community Editionでは使えるものが制限されていますが、日本語で使う上では関係ありません。これらの定義済みフォームは言語は英語しか選択できません。「その他」を選択すると日本語を含む様々な言語が選択できるようになるので、これを選びましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/e9bb70d0-4d18-b40c-5913-28cfae23ad10.png)

ドキュメントタイプを設定すると、追加のオプションが指定できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/8df01021-1120-0d54-b45d-dd0eb2100d8f.png)

画面の一番下にOCRエンジンの選択オプションがあります。以下の通り、ABBYY以外のオプションが追加されているのがわかりますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/916ee404-5dbf-66ed-bf05-df00da227a0a.png)

### インスタンスを作成して分析してみる
必要なオプションを設定し、ドキュメントのアップロードや読み出したいフォームフィールドの設定を完了して「インスタンスを作成して分析」ボタンをクリックすると、分析の画面に移ります。しばらく時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/9bbf2f27-9c67-06f4-ff14-ead1923ac39e.png)

分析が完了すると、以下の画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/c2c326f8-6829-77e7-de67-e0e8888a0414.png)

### 本番環境にプッシュ
ここでトレーニングを継続するか、本番環境 (ここでは「プロダクト環境」という単語になっている)にプッシュするかを選択できます。
本番環境にプッシュしてRPA側から使えるようにするには「プロダクト環境に設定」のトグルボタンをONにします。

ONにすると、しばらくして設定が完了します。

### RPA側から使ってみる
RPAのBot編集画面に戻って新規Botを作成して、IQ Bot関連のアクションを検索してみると、いくつか利用可能になっています。クラウド上、またはローカル上のファイルの処理や、事前処理を行うためのアクションが準備されています。アクションの詳細パネルで「Learning Instance name」のドロップダウンから、先ほど本番環境にプッシュしたラーニングインスタンスが選択可能になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479715/16756675-8af4-5e64-bb67-9dfd7c3f5bf7.png)


これで本番環境で使えるようになりました。
[C#] BenchmarkDotNetをUbuntu18.04で動かそうとした時のメモ

Ubuntu18.04 on WSLでMonoのベンチマークを取ろうと試行錯誤した際のメモです。

# 環境

## Monoのインストール

[公式サイト](https://www.mono-project.com/download/stable/#download-lin)に従って設定します。

```bash
sudo apt install gnupg ca-certificates
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
sudo apt update
```

そして、mono-completeをインストールします。

```bash
sudo apt install mono-complete
```

単に`mono`コマンドを実行してエラーがなくても、アセンブリが不足する可能性があるので、`mono-complete`にします。
アセンブリが不足していると、例えば下記のようなエラーになります。

```
CS1069: The type name 'Console' could not be found in the namespace 'System'. This type has been forwarded to assembly 'System.Console, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' Consider adding a reference to that assembly.
```

## .NET Coreのインストール

今回は.NET Coreの結果を比較するために、.NET Core SDKをインストールしておきます。
もう覚えていませんが、公式サイト通りにやればできたはず。

# ベンチマークコード

## .csprojファイル
ターゲットフレームワークは`<TargetFrameworks>`のみで、`<TargetFramework>`は含めません。
Monoはnet48をサポートしていないという情報を見かけたので、net472にしました。

```xml
<TargetFrameworks>netcoreapp3.1;net472</TargetFrameworks>
```

## Config

Configクラスに、Monoと比較用の.NET Core 3.1を追加します。

```css
AddJob(Job.ShortRun.WithWarmupCount(1).WithIterationCount(1).WithRuntime(MonoRuntime.Default));
AddJob(Job.ShortRun.WithWarmupCount(1).WithIterationCount(1).WithRuntime(CoreRuntime.Core31));
```

## 各ベンチマークコード

クラスに`[DisassemblyDiagnoser]`を付与しているのであれば、Monoはサポートしていないので外します。

こんなエラーになります。

```
DisassemblyDiagnoser supports only .NET Core 3.0+
```

## ビルド

Windows側で行います。
これは単に私がMono環境下でのビルドの知見が無いためです。

# 実行

## 場所
面倒なので、Windowsでビルドした一式をWSL側にコピーします。(`\\wsl$`を使うのが良いでしょう)
プロジェクトファイルを/tmpに置いてはいけません。
こんなエラーになります。

```
Assembly BenchmarkVsReleasedVersion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null is located in temp. If you are running benchmarks from xUnit you need to disable shadow copy. It's not supported by design.
```

## Monoで実行
Windowsでの実行と同様に、一番クラシックな環境で実行するので、`mono`コマンドで実行します。

```
sudo mono bin/Release/net472/Benchmark.exe
```

`sudo`で実行する必要があります。
普通に実行するとこんなエラーになります。

```
Failed to set up high priority. Make sure you have the right permissions. Message: Invalid data
```

以上でベンチマークが取れるようになりました。
Panolens.jsで簡単にパノラマを作成する

# 概要

[Panolens.js](https://pchen66.github.io/Panolens/)というフレームワークを使って簡単にパノラマを作成します。


# Panolens.jsとは

Panolens.jsはパノラマを作ることができるフレームワークです。[Three.js](https://threejs.org/)を元に作っているようです。

# 作成

後々いろいろな機能を追加していくことを考えてHTMLとCSSとJSをそれぞれ別のファイルに分割します。

```html:index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <link rel=stylesheet href="style.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/panolens@0.11.0/build/panolens.min.js"></script>
</head>

<body>
  <div id="container"></div>
  <script src="panorama.js"></script>
</body>

</html>
```

```css:style.css
html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    margin: 0;
}

#container {
    width: 100%;
    height: 100%;
}
```

```js:panorama.js
var container, panorama, viewer;

container = document.querySelector('#container');
panorama = new PANOLENS.ImagePanorama('https://i.imgur.com/wTCPouq.jpg');

viewer = new PANOLENS.Viewer({container: container});
viewer.add(panorama);
```


# 結果

全てのファイルの編集をした後に**index.html**を開くとこのような感じでパノラマを見ることができます。

![スクリーンショット (102).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338279/43424f56-88f1-2939-8a0e-920a10bfb54e.png)

マウスでスライドするとパノラマも回転します。


# 参考

https://qiita.com/mehdi/items/a3d29cd0729c55c016b6
https://i.imgur.com/ (画像)
Xamarin.FormsでAndroidアプリ開発③　開発したアプリをスマホで実行。躓きポイントは、共有ランライム！

アプリ開発が終わったので、あとはAPKファイルをスマホで実行するだけ！と思っていたのですが、少し躓きました…。
今回手順を追ってしっかり説明していこうと思います。

# ビルドの設定

1. まずはソリューションエクスプローラーの[ソリューション名].Androidを右クリックしてオプションを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/05e30ce0-c475-4cd2-9a25-021b17d03ebb.png)

2. Androidオプションの「共有ランタイムの使用」をオフに。**ここが重要です！**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/0f3858c7-9dca-db91-ec79-2a278e2ce93d.png)

これがオンになっている時は、Visual Studioインストール時に勝手にインストールしてくれた「MONOランタイム」と呼ばれるアプリを動作させるためのプラットフォームで実行するようになるのですが、Androidの実機にはMONOランタイムは入っていないため、起動ができません。

3. この状態で改めてデバッグします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/daf90f13-da86-989d-df3f-a18d5b51e5dd.png)

4．APKファイルは[インストールフォルダ]\\[ソリューション名]\\bin\\Debugに生成されています。あとはこちらをスマホに入れるだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672017/8a1fdb4a-6401-4752-283a-d06da5c502d9.png)

実機へのインストール方法は以下に記載していますので、こちらもご覧ください。
[Androidアプリ開発の第一歩　Android実機での起動](https://qiita.com/yasu006/items/7db0f0f7cf3ca07780bb)

# Visual Studio(Xamarin.Forms)での開発の感想
## 良かった点
- 何といってもマルチプラットフォームで開発できる点（Windows,iOSは試してないけど、たぶん行ける）
- C#で開発できる（別途C#を勉強中だったので、私にとってはありがたいです）

## もう少し、な点
Android単体で見ると、Android Studioの方が開発はしやすいかと感じました。特に、画面開発などはボタンやテキストボックスをドラッグ＆ドロップで配置できるAndroid Studioに対し、Visual Studioではできない。。正確には機能はあるのですが、Xamarin.Formsに対応していない。そのほかにもボタンをダブルクリックしたいときに、勝手にクラスを作ってくれたりする機能も本来あるのですが、それもXamarin.Formsには対応していません。ちょっとかゆいところに手が届かないかなぁと感じました。


# 関連記事

- [Xamarin.FormsでAndroidアプリ開発①　Visual Studioのインストール](https://qiita.com/yasu006/items/1c29af89bce513245d6a)
- [Xamarin.FormsでAndroidアプリ開発②　サンプルアプリ作成](https://qiita.com/yasu006/items/c55c123d489e66897bf6)
- Xamarin.FormsでAndroidアプリ開発③　開発したアプリをスマホで実行。躓きポイントは、共有ランライム！（今日はここです）
プライベートネットワーク環境からAzure BLOBへ読み書きする際にやったことまとめ

はまったのでまとめ。
これをやると、「nginx は DNS問合せ結果をキャッシュして、再起動されるまで更新しない」事象にあたるので、別途考慮が必要。


# 概要
### 要件
- プライベートネットワーク環境にあるクライアント （A） から Azure BLOB（パブリックエンドポイント） （B） 上へ、ファイルをダイレクトに転送したい
-  （A）→（B）

### 環境的制約
- （A）は直接インターネットへは出ていけない
- （B）はパブリックエンドポイントを持ち、Express Route 上に構築された Azure VM （C） からのみアクセス可

### 解決方法
- （C）上にリバースプロキシを構築して、（A）からのリクエストを転送する
- （A）→（C）→（B）

# やったこと
### クライアント（A）
hosts ファイルでクライアントを騙す。これをやることでクライアントは（C）を意識せずに（B）と会話できるようになる。

``` /etc/hosts:/etc/hosts
[（C）のプライベートIPアドレス] [（B）のストレージアカウント].blob.core.windows.net
```

### Azure VM（C）
nginx （Windows版）でリバプロ構築。nginxインストール手順・起動手順等は割愛。
ローカルの443番ポートに来たTCPリクエストを（中身を見ないで）upstream側に飛ばす。

``` nginx.conf

worker_processes  1;

error_log  C:\\nginx\logs\error.log;
error_log  C:\\nginx\logs\error.log  notice;
error_log  C:\\nginx\logs\error.log  info;
error_log  C:\\nginx\logs\error.log  warn;

pid        C:\\nginx\logs\\nginx.pid;

events {
    worker_connections  1024;
}

# リバプロ設定追加
stream {
	upstream azureblob {
		server [（B）のストレージアカウント].blob.core.windows.net:443;
	}

	server {
		listen 443;
		proxy_pass azureblob;
	}
}
```


# はまったポイント
nginx に http を解釈させようとして、「クライアントからのリクエストは http で、バックエンドが https なんだがどうやるんだ？」となっていた

# 青天の霹靂
nginx は stream という機能により L3 スイッチ 的な挙動をすることができる！（ http を解釈しない）

# やればよかったと思ったこと
時間的に余裕がなくて後回しにしていたが、先にやっていればこんなにはまらなかったかも、というもの。

- テスト環境が圧倒的に足りなかった
- Azure BLOB で提供されている REST API を知らなさすぎ
- Azcopy 仕様を知らなさすぎ
- nginx を知らなさすぎ

# 何をしたか

最終的に暗闇から抜け出せたのは nginx の本を読んだことだった。
公開設定でbitriseを利用する時の注意点

# Pull-Requestでキャッシュが使えない
**GitHubリポジトリがパブリックリポジトリになっている場合**Pull-Requestではキャッシュが利用できません。
パブリックリポジトリは誰でもPull-Requestを作成することができ、キャッシュへの不正アクセスを防止するために意図された動作のようです。
Pull-Requestをトリガーとした場合、PushもPullも利用できません。


# 環境変数`GIT_REPOSITORY_URL`のプロトコルが変わる

<img width="390" alt="スクリーンショット 2020-08-13 15.23.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14646/cb94ab72-d065-66ad-f96f-0422d7478e06.png">

**BitriseのPrivacy設定がパブリックになっている場合**リポジトリのURLが`https`プロトコルとなります。


<img width="962" alt="スクリーンショット 2020-08-13 10.33.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14646/cc1c8052-9efb-e1c2-8507-e43050150556.png">

一方、プライベート設定の際は `ssh`プロトコルとなります。
<img width="681" alt="Bitrise 2020-08-13 10-47-47.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14646/13ce1580-cb31-d510-15ac-878fbf9fd2df.jpeg">

この違いはPull-Requestの静的解説ツール[Danger](https://danger.systems)を利用する際に問題になります。
Dangerが内部で期待するリポジトリのURLはssh形式です。
そのため、パブリックリポジトリでDangerを利用する際はBitriseが用意しているDanger用のステップを利用するのが無難です。
https://github.com/xogroup/bitrise-step-danger

自前でDangerをキックしたい場合は環境変数`GIT_REPOSITORY_URL`をssh形式に上書きすれば動作しますが、その後のステップにどう影響するかは個々に判断が必要かと思います。
【超初心者向け】プログラミングの「関数」というものの概念

# はじめに
この記事はプログラミング超初心者向けに小学生にでもわかるように詳細は省いて、あえて正確性を持たせずに書いてあります。
そのため、大学前期のプログラミング入門授業が最近終わり、関数があんまりわからなかったって人にはぴったりな内容かと思いますが、詳しい方が読むと、ムムッ？と思う部分もあるかもしれません。ご容赦ください。
関数を学ぶうえで一番理解が難しい部分は返り値のところだと思いますので、返り値の部分は特に気合を入れて読んでもらえると。
最後の部分でpythonコードが書かれていますが、少しでも他の言語をかじったことが有る人なら絶対に読めるので見てみてください。一部python特有の記述で「def」という記述がありますが、「def」とは関数を定義していることを表しています。


# 関数って何？引数？戻り値？？？？
皆さん。一旦関数から離れてお昼ごはんについて考えましょう。
皆さんは今日のお昼ごはん何を食べましたか？
私は、冷凍パスタを食べました。
あれって手軽で便利なのにめちゃめちゃ美味しいんですよね。
冷凍されたパスタを取り出し、電子レンジに入れて温めスタート。
温め終わったら、一度ちゃんと温まっているかチェックして、ちゃんと温まっていたらレンジから取り出して、お皿に盛り付けて完成。(あれってまだ凍っていることありません？)

今の流れが、関数を扱う上での一連の流れです。
詳しく見て行きましょう。以下の図を見てください。
電子レンジと関数を照らし合わせると以下の通りになります。
![仮想スピーカー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679107/858ba373-e60a-28b8-bc60-e1c56fef40b2.jpeg)
- 冷凍されたパスタ＝引数
- 電子レンジ＝関数
- 温められたパスタ＝返り値
- 温まっているか確認するだけの部分＝print文

## 関数
関数というのは、よく以下のような説明がされます。
「関数とは、決められた処理を行う命令のこと。」
この決められた処理というのは、入力に関わらず、毎回決まった処理をすることを言います。
今回の電子レンジの例であれば、入力が冷凍パスタであろうが、冷凍シュウマイであろうが、前日の残り物であろうが、温めるという処理を必ず行っています。
他にも洗濯機であれば洗濯物が服であろうが、タオルであろうが、洗うという決められた処理を行う関数といえるわけです。
このように、ロボットのように何が起きても同じ処理を繰り返すものを関数といいます。

## 引数
引数とは、関数への入力のことを言います。
電子レンジは中に冷凍パスタを入れて使います。
この冷凍パスタのことを引数と呼びます。
プログラミングに慣れていないと、入力と言いたくなりますが、頑張って引数と呼ぶことに慣れましょう。

## 返り値
返り値とは、関数の出力のことを言います。
今回の場合は、温められて電子レンジから取り出されたパスタのことを言います。
通常return文を使うことで取り出します。
return文を使わない場合、取り出しがされないため、温められたまま電子レンジの中に放置されることになってしまいます。
プログラミングに慣れていないと、print文との違いがわからなくなってしまいがちですが、print文は取り出しているわけではありません。
きちんと温まったかどうかを確認しているだけで、電子レンジから取り出しているわけではないので、食べれるわけではないのです。
ですので、関数から取り出して利用したいと思った時は、return文を使いましょう。
使わなくても、見るだけで良ければprint文を使いましょう。

## 実践的な利用方法
ここで、もう少しプログラミング風に考えていきます。
例えば毎回入力された数字に10を足すという処理を行う関数があるとします。
その関数は5が入力されれば15を出力するし、121が入力されれば131を出力します。
このとき5や121のことを引数と呼び、15や131のことを返り値とよびreturnを使うことで取り出します。
先程の電子レンジの例と照らし合わせるとこんな感じです。
![仮想スピーカー (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679107/90fbbc58-fc15-59e3-f7c8-db55cf67ed67.jpeg)
実例をpythonコードで見ていきます。

```python
def plus10(hikisuu):
	kaeriti = hikisuu + 10
	return kaeriti

a = plus10(5)  
b = plus10(121)

#aには15が入ります。
#bには131が入ります。
```

plus10という関数が5や121を引数として動かされています。
その返り値がaやbという変数に格納されています。
ここで、aやbという変数の役割について説明をしていなかったので、電子レンジの例で見ていきましょう。
皆さん電子レンジから冷凍パスタを取り出したら、そのパスタをお皿に盛り付けますよね？
このaやbはつまりお皿なわけです。
関数の返り値で計算結果を出力したとしても、関数の外の変数（お皿）に格納しなければ使えないわけです。

# まとめ
プログラミングを始めたばかりだと、関数は非常に扱いにくく感じるかもしれません。
そのため関数なんか使わなくてもいいやと思うかもしれませんが、関数に慣れるととても便利なものであると気づきます。
今回例で使った、電子レンジや洗濯機も、最初それらを作るのが困難な時代では、温めるという行為を行うだけで鍋にいれて火にかけていましたし、洗濯であれば手洗いでしたが、電子レンジや洗濯機が作れるようになってからは、もうそれらが無い生活なんてありえませんよね。
関数もそれと同じなので、この記事でイメージを持つことができましたら、あとはひたすら関数を使う練習をしてみてください。
PDM(Product Data Management)、FMS(Flexible Manufacturing System)、MRP(Material Requirements Planning)、SCM(Supply Chain Management)

平成31年春期 午前問題72

PDM(Product Data Management)の目的はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/c75d66c7-5704-3c31-9e17-3e33f4e036fa.png)

１、PDM(Product Data Management)は、
「製造情報管理」という意味で、設計図面、部品構成表、コスト情報、技術仕様などの設計・開発に関連する様々な情報をシステムで一元管理する考え方です。これまで各部門に散在していたデータが共有されることにより、開発期間の短縮や開発コスト削減などの効率化が期待できます。

PDM（Product Data Management）とは、設計時に作成するCADなどの製品データや、BOM（部品表）などの設計技術に関する情報を一元管理する、製品情報管理システムです。

設計ではCADを使うのが一般的ですが、CAD以外の製品データも多数存在します。仕様書などの文書、設計データ、設計や生産の日程など、作成アプリケーションも異なるデータが膨大にあり、管理も一苦労です。しかし、PDMを導入することで、製品ごとにデータを一元管理することが可能になります。

・PLM（Product Lifecycle Management）とは、製品のライフサイクルを通して、製品情報をトータルで管理するシステムを指します。

製品のライフサイクルとは、企画・設計開発・生産準備・生産計画・製造・販売・廃棄などを指し、調達軸からみた調達や、販売軸からみた販売計画や保守なども含まれます。

PLMとPDM
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/31d93034-8b11-cce3-9bb8-741bcac2931d.png)



２、FMS(Flexible Manufacturing System)の目的
NC工作機械，自動搬送装置，倉庫などを有機的に結合し，コンピュータで集中管理することによって，多品種少量生産に対応できる生産の自動化を実現する。

多品種・小ロット生産に対応した、柔軟な生産システムのこと。消費者ニーズの多様化に伴い、生産ラインでは生産製品の固定化をせず、柔軟性を持たせた生産の自動化が進められている。FMSはそういった状況でも、商品によって生産設備を大幅に変更することなく、一定の範囲内で類似品や複数の製品を、需要の変動に応じて混流生産できるシステム。

３、MRP(Material Requirements Planning)の目的
製品の生産計画に基づいてその生産に必要な資材の所要量を展開し，これを基準にして資材の需要とその発注時期を算出する。

４、SCM(Supply Chain Management)の目的
部品の供給から製品の販売までの一連のプロセスの情報をリアルタイムで交換することによって，在庫の削減とリードタイムの短縮を実現する。


参照：
https://www.ap-siken.com/kakomon/31_haru/q72.html

FMS
https://kotobank.jp/word/FMS-1601

PDMとは何か？
https://backlog.com/ja/blog/what-is-pdm/
IoT活用におけるディジタルツイン(digital-twin)

平成31年春期 午前問題71

IoT活用におけるディジタルツインの説明はどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/d05c4255-4eb2-11a0-3694-e9ddac75b3dd.png)

１、デジタルツインとは、
そのまま「デジタルの双子」を意味します
デジタルツインとは、物理世界（現実世界）に実在しているものを、デジタル空間でリアルに表現したものを指します。

フィジカル空間の情報をIoTなどを活用して、ほぼリアルタイムでサイバー空間に送り、サイバー空間内にフィジカル空間の環境を再現します。このサイバー空間上に物理世界の情報を全て再現することから“双子（ツイン）”と表現されているというわけです。

デジタルツインの環境を活用することで、フィジカル空間のモニタリングを行える他、シミュレーションなどを行うことができます。つまり、このサイバー空間でシミュレーションを行った結果から、現実世界における将来の故障や変化を予測できるというわけです。この点がデジタルツインで最も大きく期待されている点だといえます。

※フィジカル（英: physical）とは、肉体的、身体的という意味を指す語。
※デジタルツイン　digital-twin　


２、3Dプリントサービス
インターネットを介して遠隔地に設置した3Dプリンタへ設計データを送り，短時間に複製物を製作すること


３、デュプレックスシステム
システムを正副の二重に用意し，災害や故障時にシステムの稼働の継続を保証すること
BCP対策の一つとしての、フォルトトレランスの考え方の説明である。

４、スマートウォッチやスマートグラス　smart watch or smart glass
自宅の家電機器とインターネットでつながり，稼働監視や操作を遠隔で行うことができるウェアラブルデバイスのこと
IoT活用によるスマートホームの説明と考えられる。

５、IoT (Internet of Things) は、
コンピュータなどの情報通信機器だけでなく様々なものに通信機能をもたせ、インターネットに接続することによって自動認識や遠隔計測を可能にし、大量のデータを収集・分析して高度な判断サービスや自動制御を実現することである。





参照：

デジタルツイン
https://monoist.atmarkit.co.jp/mn/articles/1808/08/news043.html

https://www.ap-siken.com/kakomon/31_haru/q71.html

http://fast-macro.com/Johosyori/h31HaruKoudo/h31HaruKoudo-28.html