OmniAICreator/Qiita-1.07M huggingface dataset:
初心者向けコルーチンの代わり？UniTask(UniRx.async)を使い方

#自己紹介
こんにちはゆずです。@Yuzu_Unity


#はじめに
この記事はUnityのコルーチンを扱える人が
UniTask(UniRx.async)を扱えるようになればいいと思って書いています。
非同期処理以外については触れていません。
UniRxは全く関係ないです。
この記事ではUniRxについては記述しません。

#こういう人向け？
複数フレーム待つ動作を頻繁に使いたい人？
セーブデータなどのIO関係を触る人
コルーチンに戻り値が欲しいと思っている人
C#7.0で色々使えるようになりたい人

#環境構築編
C#7.0環境   IDEであればVisualStudio2017 Rider等

Unity2018.3以上

GitHubでUniTask(UniRx.async)
https://github.com/Cysharp/UniTask
もしくは　AssetStoreでUniRxダウンロード(現在はGitHub版推奨　UniRxとUniTaskは分離されるみたいです。)
https://assetstore.unity.com/packages/tools/integration/unirx-reactive-extensions-for-unity-17276
※UniRxとは別物ですが同じパッケージに入っている

.NET 4.xモードにする（Player Settings→Other Settings）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/a586b503-2f43-3179-fe86-0838d7985b1f.png)

#UniTaskとは
C#7.0でasync/await Taskを扱えるようになったが,
Unityが公式でサポートしておらずこのままではコルーチンの代わりとして扱えないので
それを解消するライブラリです。
つまり逆に入れないと思ったように動かないと思ったほうがいい⁉
（Taskがメインスレッドで動いていないので、メインスレッドで動くTexture2D.EncodeToPNGなどは動作しませんでした。）

#使い方
書き方

    実行 関数名();
    関数 async void 関数名() { }

    実行 await 関数名();
    関数 async UniTask 関数名() { }

    実行 変数 = await 関数名();
    関数 async UniTask<戻り値の型> 関数名() { }



の3つ
IEnumerator と　async void　が大体同じです。

##例 
* コルーチン


```c#

    void Start()
    {
        StartCoroutine(TestCoroutine());
    }
    IEnumerator TestCoroutine()
    {
        //WWWクラス定義
        WWW www = new WWW("http://urx3.nu/QwZk");
        //wwwダウンロード開始
        yield return www;
        Debug.Log("Complete");
    }

```
* UniTask

```c#
//using UniRx.Async;

    void Start()
    {
        TestUniTask();
    }
    
    async void TestUniTask()
    {
        //WWWクラス定義
        WWW www = new WWW("http://urx3.nu/QwZk");
        //wwwダウンロード開始
        await www;
        Debug.Log("Complete");
    }
```

ほとんど変わらないですね
IEnumeratorがasync
yield returnが await
という感じですね

これではメリットがあまりわからないので複数フレーム待機、戻り値ありにしてみましょう

```c#
//using UniRx.Async;
   async void Test()
    {
        //TestUniTask終了まで待つ
        int a = await TestUniTask();
        Debug.Log("Complete");
    }


    async UniTask<int> TestUniTask()
    {
        //5フレーム待つ
        await UniTask.DelayFrame(5);
        return 3;
    }

```

複数フレームはコルーチンだと1フレームのループ処理になり
無駄な処理が挟まれて結構重かったりしますね。

#キャンセル処理
UniTaskの最大のデメリットです

コルーチンではStopCoroutine()もしくは
コンポーネントをOFFで止まることができました。

UniTaskはコンポーネントをOFFにしても止まりません！！
なのでゲームオブジェクトを消しても動きつづけます。

キャンセル処理に関してはここを参照してください
https://qiita.com/toRisouP/items/4445b6b9bf00e49eb147#%E3%82%AD%E3%83%A3%E3%83%B3%E3%82%BB%E3%83%AB%E5%87%A6%E7%90%86

キャンセル処理するならコルーチン現役ですね…

#まとめ
停止が面倒なので
普通のゲーム制作のみであればコルーチンのほうがいいが
複数フレーム待つ動作を頻繁に使うのであればUniTask

セーブデータ、AssetBundleのダウンロード書き込み等
IO関係はUniTaskを使うほうがC#に用意されている非同期系が使えるので良い

要は併用しようという感じですかね！

また、ここには書いていませんがマルチスレッドプログラムもかけるのでそこに関してはゲームでも実用できるかと思います。
C#jobsystemの制約は少しめんどくさいですしね
朝礼を有意義に！！

#朝礼を有意義に！！
朝礼ってぶっちゃけ面倒で無駄な時間だなと思うことはありませんか？
自分は無駄な時間だと新卒の頃からずっと思っていました。

そんな中、現在２名のマネジメントしております。
やり方を考えれば朝礼は必要な時間になると考え実践したので内容をまとめようと思います！

***マネジメントは２人一緒ではなく、別々で見ております。***
→理由は、個人それぞれ性格や持ち味があるので各々の進捗に合わせるスタイルにしたいと考えました。

ちなみにIT人材紹介業の営業職です。

##昨日の振り返り
昨日のスケジュールの動きなのを再度アウトプットする。
そこで何かしら改善点があったら指摘します。

##訪問先で何を得たのか
ただ訪問先に行くだけは無駄なので、『訪問先が求めている事は何か？』
又は『何を学び感じたか』をアウトプットする。
自分の口から話す事で脳へのインプットできると思います。

##営業数字の進捗確認
昨日のスケジュールの中でどのくらい営業行動が出来たか確認します。
各々数字は前後しますが、どんな根拠でその数字になったのか。
改善点があれば考えてもらったりヒントを共有する。

##今週と来週の行動指針や目標に対する行動指針
今週のスケジュールを再度確認し、今週や来週の行動が目標に向かっているのか？
もしくは、何か別の意図があってスケジューリングをしているのかを確認する。

##おまけ
仕事の話だけだと、視野が狭まるのでニュースやコラム、交流会で知り合った人の
話などとお互いにアウトプットし合うのはいいのではないでしょうか？

#まとめ
いかがでしたでしょうか？
実践してまだ１ヶ月ですが、以下の効果が現れていると感じました。

```
・相談を遠慮せず出来るようになっている
・仕事の流れを毎日確認出来るので、わからない点や課題を引き出す事ができる
・何かあったら必ず相談してくれるような信頼関係を構築出来ている
・思考能力が上がり、成長スピードが早い
```

以上、あくまで自分が体感している事であるのと元々のキャラクター
でその結果を出している可能性はありますが一つ参考いただければと思います。
github+markdown+UMLクラス図という条件ならBOOSTNOTE一択だと分かりました。

プログラムを作り始める前にクラス図を書いて処理の分割案を検討しようと思ったのですが、MarkdownでUMLのクラス図を書けるものが判らず、ちょっと調べました。

候補は以下です。

* [BOOSTNOTE](https://boostnote.io/ja/)
* typora
* haroopad

結論を言うと、boostnote一択でした。

シーケンス図だけなら他のエディタも使えそうでしたが、クラス図となると、まともに表示できるのは今のところ、boostnoteのみ。

* ○ [BOOSTNOTE](https://boostnote.io/ja/)
* ☓ typora（化ける）
* ☓ haroopad（まったく表示されない）

他にも、他のエディタと比べてBOOSTNOTEの良いところはたくさんあります。第一印象として目についた差は以下です。

* フォントが自由に指定できる
* エディタ編集と同時にMarkdown表示ができる
* 日本語対応
* ゴミ箱がある

一言で言うと細やかで完成度が高い印象です。
MacにAtomエディタを導入する方法

**この記事は、Atomエディタのダウンロードから日本語化までをまとめています。**
## Atomエディタのインストール
- ホームページへアクセスします。
- https://atom.io
- 「Download」をクリックし、ファイルをダウンロードします。
- ダウンロード完了後、Atomアイコンが出現します。
- アイコンをクリックし、エディタが開きます。

## Atomエディタの日本語化
- 「Welcome Guide」の「Istall a Package」を選択します。
    - もしここで、「Welcome Guide」が出現しない場合は、メニューバーの「Help」「Welcome Guide」を選択することで表示されます。
- 「Open Installer」をクリックし、「japanese」と入力します。
- 「japanese-menu」をインストールします。
- メニューバーなどが日本語化されていることを確認してください。
    - この時点で日本語化されていない場合、Atomエディタの再起動をしてください。

以上となります。

Atomでは豊富なPackageが魅力的です。
次回はAtomでのテーマ(エディタの見た目)を変更する記事を載せたいと思います。
Ansible Playbookでlocalhostに接続できない問題を解決する

Ansible Playbookをlocalhostを対象に実行しようとすると、以下のエラーが発生しplaybookが実行できなかった。

```terminal
$ ansible-playbook -i inventory playbook.yml

PLAY [all] ***********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:(****).
Are you sure you want to continue connecting (yes/no)? yes
fatal: [localhost]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.\r\nroot@localhost: Permission denied (publickey,password,keyboard-interactive).", "unreachable": true}

PLAY RECAP ***********************************************************************************************************
localhost                  : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0
```

調査したところlocalhostで実行するときには`--connection local`オプションを実行時につけると良いらしい。

```terminal
$ ansible-playbook -i inventory playbook.yml --connection=local

PLAY [all] ***********************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************
ok: [localhost]

TASK [helloworld : Hello World!] *************************************************************************************
ok: [localhost] => {
    "msg": "Hello World!"
}

PLAY RECAP ***********************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```
Salesforce LWCの3つ デコレータの①

引用　https://base.terrasky.co.jp/articles/zpT4b
Salesforce特有のデコレータは3つデコレータはJavaScriptの標準機能です。デコレータをご存じない方のためにお伝えすると、Javaでいうアノテーションと同じようなもので、メソッドなどに機能（たとえばログ出力など）を追加する際に使います。LWCではSalesforce特有のデコレータが3つ（@api、@track、@wire）用意されています。それぞれの役割が直感的にわかるようにしたのが下の図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398746/b29c7a14-2217-477f-2d1c-6982ff818489.png)
　　　　　　　　　　　Salesforce特有のデコレータ早わかり図
@track
画面とJavaScriptを連携するためのデコレータです。画面での変更、たとえば入力に対して反応させたい場合に使用します。Apexでいうprivateメソッドのように自コンポーネント内でのみ使用することができます。 

@api
@trackとほぼ同じです。JavaScriptで定義したメソッドを他のコンポーネントでも参照したい場合に使用します。@trackと併用することはできません。 

@wire
JavaScriptの変数とApexのメソッドを紐づけたいときに使用します。
rails c がLoadErrorになった時の解消法

# 現象
railsで開発をしていて、`rails c`,`rails console`を打った時に何故か以下のエラーが。

```terminal
dlopen( ~/.rbenv/versions/2.5.0/lib/ruby/2.5.0/x86_64-darwin17/readline.bundle, 9): Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError)
  Referenced from: ~/.rbenv/versions/2.5.0/lib/ruby/2.5.0/x86_64-darwin17/readline.bundle
  Reason: image not found - ~/.rbenv/versions/2.5.0/lib/ruby/2.5.0/x86_64-darwin17/readline.bundle
```
# 対応
Gemfileにgem 'rb-readline' を追加してインストールすれば治る模様。
以下参考になりました
[rails consoleでreadline(LoadError)が出た場合の対処](https://qiita.com/ko2ic/items/7fc4ccf943de52078737)
[rails consoleコマンドがLoadErrorでエラーになったときの解消法](https://qiita.com/roki1801/items/7e4a371ae0b9ba928f55)

Gemfileの編集

```ruby:Gemfile
~
gem 'rb-readline'
~
```
インストール

```terminal
$ bundle install
```

再度実行

```terminal
$ rails c
```

無事成功。

```terminal
Loading development environment (Rails 5.1.6)
irb(main):001:0> 
```

# 原因
Homebrewにインストールされていたreadlineを更新しちゃったことが原因っぽい。
以下の記事が参考になりました。
[Rails consoleがreadlineの原因でうまく読み込めなかった](https://qiita.com/k-shinto/items/eb67936ee143d2981827)

```terminal
$ brew info readline
/usr/local/Cellar/readline/7.0.3_1 (46 files, 1.5MB)
  Poured from bottle on 2018-05-19 at 14:48:10
/usr/local/Cellar/readline/8.0.0_1 (48 files, 1.5MB)
  Poured from bottle on 2019-06-06 at 21:32:09
```

前のバージョンに戻しても上手くいくようです。

```terminal
$ brew switch readline 7.0.3_1
Cleaning /usr/local/Cellar/readline/8.0.0_1
Cleaning /usr/local/Cellar/readline/7.0.3_1
Opt link created for /usr/local/Cellar/readline/7.0.3_1
```
再度実行して成功。

```terminal
$ rails c
Running via Spring preloader in process 584
Loading development environment (Rails 5.1.6)
irb(main):001:0>
```
Hyperstackでbrowser非表示のmodelの属性値をclipboardへコピー

#### 親コンポーネントで#find_byで取得したmodelをparam に受け取って、リンククリック時にclipboardへコピーしたい。

- TEXTAREAをマウントしてmodelの属性値をvalue(またはdefaultValue)に入れておいても、TEXTAREAを style で隠すと、element.select か copy がうまく動作しなかった。

- リンククリック時に TEXTAREA要素を追加、select、copy、removeするのでは、属性値が取得できなかった。

### 解決法
catmandoさんから、コメント欄に解決法をいただきました。ありがとうございます！
@OneUser.name.loaded? を利用して、ロードが完了してからリンクが表示されるようにします。

```ruby
class ClipTest < HyperComponent
  param :one_user

  render(DIV) do
# 'name'がロードされるまで空の文字列を表示する
    return '' unless @OneUser.name.loaded?

    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(@OneUser.name)
      end
  end

  def copy_to_clipboard(text_to_copy)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not　' unless supported}supported.")
    return unless supported

    textarea = $$.document.createElement('textarea')
    copy_from = $$.document.body.appendChild(textarea)
    copy_from.textContent = text_to_copy

    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
    copy_from.remove
  end
end
```

### 試行錯誤
textarea要素をマウントしておく方法では、display: 'none' で表示しないようにしておくと、select か copyがうまく動作しなかった。

```ruby
class ClipTest < HyperComponent
  param :one_user

  render(DIV) do
    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(textarea_id)
      end

    TEXTAREA(id: textarea_id, 
             defaultValue: @OneUser.name,
             style: { display: 'none'})   # 隠してマウントしておく
  end

  def textarea_id
    "textarea-#{@OneUser.id}"
  end

  def copy_to_clipboard(element_id)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not ' unless supported}supported.")
    return unless supported

    copy_from = $$.document.getElementById(element_id)
    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
  end
```

これでリンクをクリックすると、puts で "copy to clipboard : <@OneUser.nameの値>" が正常にコンソールに出力されるのだが、クリップボードにはコピーされない。

TEXTAREAの styleを、{ display: 'block' }にした場合は、クリップボードへのコピーが正常にできた。

after_mount で属性をロードさせておいて、リンククリック時にTEXTAREA要素を追加。

```ruby
class ClipTest < HyperComponent
  param :one_user

  after_mount do
    @OneUser.name
  end

  render(DIV) do
    A(href: '') { '名前をclip' }
      .on(:click) do |evt|
        evt.prevent_default
        copy_to_clipboard(@OneUser.name)
      end
  end

  def copy_to_clipboard(text_to_copy)
    supported = $$.document.queryCommandSupported('copy')
    puts("copy to clipboard is #{'not　' unless supported}supported.")
    return unless supported

    textarea = $$.document.createElement('textarea')
    copy_from = $$.document.body.appendChild(textarea)
    copy_from.textContent = text_to_copy

    puts("copy to clipboard : #{copy_from.textContent}")
    copy_from.select
    $$.document.execCommand('copy')
    copy_from.remove
  end
end
```

after_mount がないと、copy_to_clipboardの puts で "copy to clipboard : " とだけ出力された。引数のtext_to_copy に属性値が渡っていない。
この方法では、nameがロードされる前にリンクがクリックされた場合に問題が起きる。
アプリ内ブラウザ(WebView)を導入する際の留意点【随時更新予定】

アプリ内ブラウザ(WebView)を導入する際の留意点をまとめました。自分用のメモ書きですが、随時アップデートし読みやすくする予定です。

- 表示対象のサイトにtarget="_blank"や mailto: などにリンクがないか。タブ（別ウインドウ）の概念がないwebviewではtarget="_blank"のリンクは動作しないし、メーラーも立ち上がらない。確かURLスキームもうまくハンドリングできない気がする（要確認）。
- アクセス許可するホワイトリストを設けるか否か  
リンクを辿って全く関係ない外部サイト（場合によってはアダルトサイトなども）を表示できてしまうことを良しとするか。制限したい場合はアクセスを許可するドメインやURLをホワイトリストとして管理する。
  - 自分たちで管理できない外部サイトに遷移させるリンクはWebToで遷移させるようにしたほうがベター。この場合にWEB側とアプリ側でI/F仕様を取り決める必要がある。
- 画面遷移を許可する場合は、「進む」「戻る」などのナビゲーションは自前で実装してあげないと不便なので留意する。
- `<input type="file">` などファイルアップロードさせるフォーム要素は正常に動かないケースがありそう（調査中）
- Webview内のリンクや画像を長押し等すると、サブメニュー（画像を保存とか）が表示される。Webviewコンテンツをアプリライクに見せたい場合や、WebviewのURL等をオープンにしたくない場合は隠す処理を入れてあげたほうがよい。
- Basic認証をサポートするにはプラスアルファの実装が必要かも。
- Androidの場合、通信エラーなどで当該画面が表示できない場合は、標準のエラー画面（ドロイドくんのいる画面）が表示されてしまう。アプリの世界観が崩れるので避けたいところではある。避けたい場合は独自のエラー画面を作成する。
- Androidの場合、JSのalertやconfirmメソッドがそのまま動作しないケースがある模様  
cf. https://denen.hatenablog.com/entry/2019/02/26/Android_%E3%81%AE_WebView_%E3%81%A7%E3%82%82_alert_%E3%82%84_confirm_%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F  
cf. https://ja.stackoverflow.com/questions/12986/webview%E3%81%A7javascript%E3%81%AE%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%95%E3%81%9B%E3%81%9F%E3%81%84
C# から参照設定なしで Excel を操作する

## はじめに

参照設定をしないだけで、Excel がインストールされていないと動作しません。

## サンプル

Excel を開いて、別名で保存するだけです。
インスタンスの生成、プロパティの設定・取得、メソッドの呼び出しの一通りはあるので、後は応用かと。

```C#:Program.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            object app = null;
            object books = null;
            object book = null;
            try
            {
                app = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
                app.GetType().InvokeMember("DisplayAlerts", BindingFlags.SetProperty, null, app, new object[] { false });
                books = app.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, books, null);
                book = books.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, book, new object[] { @"c:\hoge.xlsx" });
                book.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod, null, book, new object[] { @"c:\poge.xlsx" });
                book.GetType().InvokeMember("Close", BindingFlags.InvokeMethod, null, book, null);
                app.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, app, null);
            }
            finally
            {
                if (book != null && Marshal.IsComObject(book))
                {
                    Marshal.FinalReleaseComObject(book);
                    book = null;
                }
                if (books != null && Marshal.IsComObject(books))
                {
                    Marshal.FinalReleaseComObject(books);
                    books = null;
                }
                if (app != null && Marshal.IsComObject(app))
                {
                    Marshal.FinalReleaseComObject(app);
                    app = null;
                }
            }
        }
    }
}
```

## おわりに

諸事情により、動作確認できないので、動かなかったらごめんなさい。

## お知恵を拝借したい

せっかくなので、Application、Books、Book クラスを作って参照設定と同じ実装できるようにしようと思ったのですが、実装方法が分からず悩んでます。

各クラスのコンストラクタで、生成したインスタンスをクラス変数に格納しておいて、各メソッドでクラス変数の InvokeMember を呼び出す実装を考えました。
この場合、以下のように実装したのですが、 Workbooks のコンストラクタは呼ばれないため、Workbooks クラス内で、クラス変数に app.Workbooks の値を格納できないでいます。

```C#:困った
Applicationapp = new Application();
Workbooks books = app.Workbooks;
books.Open(@"c:hoge.xlsx");
```

以下の実装だと、処理する度に books と this のどっちを使うか判断せにゃならんし。。。
（※これも諸事情により動作確認できないので、そもそも動くかも分からないです。）

```C#:一応は考えてみた
public class Workbooks 
{
    private object books;
    public void Open(string path)
    {
        object o = this.books != null ? this.books : this;
        o.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, o, new object[] { path });
    }
}
```
Squidをリロードするansible-playbook

Amazon Linux 2(Systemd)で動いている Squid のログ出力フォーマットを変更する際に、
Squidをリロードする必要がありました
その時のplaybookです

Systemdモジュールを使ってsquid.serviceをリロードしています
debugで結果(nameとstate)を出しています


```yaml

- hosts: Proxy_DEV
# ------------------------------------- #
  user: ec2-user
  become: false
  tasks:
    # ------------------------------------------------ #
    - block:
      - name: reload squid
        systemd:
          name: squid.service
          state: reloaded
        register: result_cmd
        become: true

      - name: print result
        debug: msg="{{ result_cmd.name }} is {{ result_cmd.state }}"

```

Systemd モジュール
https://docs.ansible.com/ansible/latest/modules/systemd_module.html

debug モジュール
https://docs.ansible.com/ansible/latest/modules/debug_module.html


最終系・・・

```yaml
- hosts: Proxy

# ------------------------------------- #
  user: ec2-user
  become: false
  tasks:
    - block:
      - name: check vars(config.json)
        debug: msg= "{{ inventory_hostname }}"

      - name: copy squid.conf from local to remote host
        copy:
          src: ./put_squid/squid.conf
          dest: /etc/squid/squid.conf
          owner: root
          group: squid
          mode: 0640
          backup: yes
        become: true
        register: result_copy
        when:
          - not ansible_check_mode
      
      - name: reload squid
        systemd:
          name: squid.service
          state: reloaded
        register: result_cmd
        become: true
        when:
          - result_copy.changed == true

      - name: print result
        debug: msg="{{ result_cmd.name }} is {{ result_cmd.state }}"

      - name: print result(file)
        local_action:
          module: copy
          content: "{{ result_cmd.stdout }}"
          dest: "./ansible_logs/{{ inventory_hostname }}/fetch-config.log"
        when: 
          - not ansible_check_mode
      
      #tags: [ 'never',  'exec_config' ]

```
スマホアプリの要件定義で考慮すべき項目【随時更新予定】

スマートフォンのネイティブアプリの開発を行う際に特有の、要件定義に盛り込んでおくべき内容をまとめます。自分向けメモのためやや殴り描きですが、随時更新しもう少しちゃんとまとめ直す予定です。

# サポート端末

- サポート対応OS、バージョン、インストール可能な最低OSバージョン
- タブレットへのインストール可否
- サポート対象の画面サイズ（特にAndroidは画面サイズの種類が多いため）

# UI関連

- ポートレートビュー（横表示）への対応有無
- split view（タブレットやAndroid7?以上で複数アプリを並べて表示させる機能）への対応有無
- タブレットの場合に、iPadの互換表示モード（？）を利用するのか、ユニバーサルアプリとしてリリースするのか。
- OSのUI設定についてどこまでサポートするか
 - OS設定のフォントサイズ  
 ※何も考えずに実装すると、iOSはOSのフォントサイズ設定に依存せず独立して描画され、AndroidはOS設定に影響を受ける。
 - （Androidのみ）システムフォントの設定
 - （Androidのみ）ビューの拡大表示 
 - （Androidのみ）デフォルトキーボードの設定
 - （Androidのみ）Adaptive Iconへの対応（Android8以上） cf. https://qiita.com/ryo_mm2d/items/bc2807670eedc71630b9
- 画面サイズが大きい（タブレットとかの場合に）どのように拡大させるか。要素自体を引き伸ばすのか、要素間のマージンで幅を調整するのか。後者の場合は、どこの要素間でマージンを設けるのかなどを明示化するため、画面サイズごとにデザインパターンを何パターンかつくることもある。
- 幅や高さが固定の要素に対して文字数が超過した場合に、文字列の一部を「...」と省略表示とするのか、要素内に文字が収まるよう自動縮小させるのか（※設計時に要素ごとに検討した方が無難かも）
- （iOS13以降）ダークモードへの対応方針
- カラーユニバーサルデザイン（ https://www.asobou.co.jp/blog/web/cud ）への対応有無

# トラッキング

- トラッキングの計測対象は何にするのか。screen_viewのみ？screen_viewを取得する場合はスクリーンクラスの定義も行なうのか？ボタンタップなどのイベントも取得するのか？
- クラッシュレポート（Crashlyticsなど）の導入有無を決める。ストアのコンソールでも確認できるが専用のツールを入れたほうが詳細な情報が取得できる。

# セキュリティ

* iCloudなどにアプリ内保持項目もバックアップさせるかどうか

## コーディング規約

* Android  
日本スマートフォーンセキュリティ協会『Android アプリのセキュア設計・セキュアコーディングガイド』【2018年9月1日版】
https://www.jssec.org/report/20180901_securecoding.html
* iOS  
https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Introduction.html

# その他

- URLスキーム、Universal Links（iOSのみ）の有無
かんたんRails新規プロジェクト作成手順(2回目以降の人向け)

久しぶりに自作Railsアプリでも作ろうかと思ったら、
環境構築が意外と面倒で嫌になってきた。

ググって出てくる情報も、玉石混交としていて、
今の自分にフィットしない(当然)

また同じ苦労をしたくないので、半分自分用メモとして残しておくことにする。
あと、**なるべくミニマムな手順** を目指す

# ゴール
Yay! You’re on Rails!

# 本記事の対象読者
半分自分用だけど、以下に当てはまる人には役に立つかも。

- 以前Railsでアプリを作ってgithubで公開した。
- 同じ環境で久しぶりに作る。
- セキュリティとかベストプラクティスとかは置いといて、  
とりあえず動く状況を作りたい。

# かんたんRails新規プロジェクト作成メモ
## 目次
見出しだけ表記。以下の記載だけで事足りる人はここだけ見てね。

1. とりあえずgithubにリポジトリを作る
2. 作成したリポジトリをローカルにclone
3. rbenvで利用するrubyのバージョンを決める
4. bundle init & Gemfileのrailsコメントアウト解除 & bundle install
5. rails new
6. database.ymlを編集
7. bin/rails s & Yay! You’re on Rails!

## 1. とりあえずgithubにリポジトリを作る
とりあえずgithub。草の足しにもなるぞ。

ここさえ押さえておけば、後々しくじっても何とかなる気がするので、
めんどくさがらずに新規リポジトリを作る。

<img width="1434" alt="スクリーンショット 2019-06-08 14.35.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283780/73034bde-8df3-a7a4-8127-be2606d378b2.png">


この時点でPJ名も決めてしまう。

## 2. 作成したリポジトリをローカルにclone
そのまま！ 説明割愛。
決めたPJのディレクトリができる。

## 3. rbenvで利用するrubyのバージョンを決める
```
$ rbenv local 2.6.3
$ ls -a
.		..		.git		.ruby-version
$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
```
## 4. bundle init & Gemfileのrailsコメントアウト解除 & bundle install
とりあえず `bundle init`。Gemfileができる。
```
$ bundle init
Writing new Gemfile to /Users/kp/work/rails-base/rails_base/Gemfile
```

Gemfileを開いて、`#gem rails`のコメント削除。
```
$ vi Gemfile # gem railsのコメントアウト解除
```

bundle installする。(installは省略できる)
実際はもっとログが長い。
```
$ bundle
The Gemfile specifies no dependencies
Resolving dependencies...
Bundle complete! 0 Gemfile dependencies, 1 gem now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

## 5. rails new
`rails new`で新規プロジェクトを作成
```
# Railsアプリ作成時
$ bundle exec rails new . -d postgresql # postgresql利用時

# Rails api作成時
$ bundle exec rails new . -d mysql --api# mysql利用時
```

### rails new "." について
"."を使うとカレントディレクトリにそのままプロジェクトを作成できる。
無駄がなくて良い。

詳細は以下の通り。
https://qiita.com/morikooooo/items/b46cd35638f21079fc4a

### -d オプションについて
これをやっておかないと、database.ymlの設定が面倒臭いので、あらかじめやっておく。
DBはMySQLでもPostgreSQLでもSQLiteでも好きなものを。

### --path vendor/bundle について
最近、`--path vendor/bundle` はやらなくても良いのではないか？
という議論を見かけた。

https://qiita.com/jnchito/items/99b1dbea1767a5095d85

やらなくて良さそうな事はやらない ＆ @jnchitoさんが言っているという観点で、
せっかくだから俺は`--path vendor/bundle`はやらないぜ！
(いずれ上の記事はちゃんと理解する)

## 6. database.ymlを編集
この辺りは使うDBによって違う。何もしなくて良い場合もある。
とにかく `bin/rails db:create`が上手くいけばOK！
割愛！

## 7. bin/rails s & Yay! You’re on Rails!
`bin/rails s`を実行 & localhost:3000にアクセスし、
以下の画面が表示されたら完了！

## おまけ. git commit & git push
`git commit` & `git push`も忘れずに。

# 最後に
とりあえずの暫定手順なので、更新していきたい。
特にDocker込みの手順にしたい。
あなたはelmでSPAをわかってしまいたいのか？

elmという単語を(少なくとも私の周りでは)よく聞くようになり、今までフロントエンドを敬遠していた人までもがelmを初めて楽しい！という声が上がるのはelmを推し続けてきた身からはとても嬉しいものです。しかし、一方でelmを学ぶ初期の段階でRoutingやモジュール分割([elm-spa-example](https://github.com/rtfeldman/elm-spa-example))に手を出してしまいelmはSPA(Single Page WebAapplication)が難しい、情報が少ないと嘆く人たちを少なくない人たち見てSPAに関する記事を書くと思い立ちました。・・・が残念ながらこの記事では**elmにおけるSPAの手法は一切説明しません**。この記事では私がブラウザアプリケーションにおける要件と技術選定の基準を載せようと思います。そして、この記事の最後に到達してしまった方には、elmにおける「みなさんが思う」SPAをする手法を説明する記事へのリンクを残そうと思います。


# 1枚の静的ページ

ランディングページ(LP)などの美しい・かっこいいデザインの何の動きもない、もしくはほんの少し動きがあるページです。こんなページではelmはおろか、JavaScriptも極力使わないと思います。ロジックがないのですもの。

# 複数の静的ページ

ポートフォリオによく見られる昔ながらのホームページスタイルです。リンクによって繋がれた複数の「見た目」。「Home」「Works」「About」などのページでしょうか？ 確かにリンクによって遷移するリロードをSPAによってかっこよく見せたいのかもしれません。ただ、一度見たページはキャッシュされローディングにそこまでのストレスはユーザは感じないのかもしれません。GitHub Pagesでは以下の構成にするだけで要件を満たせてしまいます。

```
- docs
    - index.html
    - works.html
    - about.html
```

もしや頑張るべきなのはマークアップやスタイリングで、elmではないのかもしれません・・・。

# 1つの動的なページ

これはサーバからHTML, JavaScript, CSSが読み込まれた あとは、それ以上リソースがブラウザのリロードによって読み込まれない 動きが求められるページです。定義どおりの「SPA」になります。イメージとしてはWEBアプリケーションよりもネイティブのアプリケーションの体験に近いものがあると思います。例えばペイントツールはいろんなボタンを押すことで機能が切り替わったり、見た目が変わったりします。描いた絵が保存され続けたり、昔の絵を引っ張ってきたりは、どちらかと言うとローカルストレージやFirebase・DBにお仕事になります。どうでしょう？ 「ブラウザ」の「進む」や「戻る」をペイントツールで使いたいでしょうか？(Undo, Redo機能ではありません) このとき、ほぼライブラリの仕様のみで解決するのであれば、JavaScript, 場合によっては TypeScriptを選択します。しかし、複雑なビジネスロジックやデータ構造を活用する事例であれば、間違いなくelmを選択するでしょう。しかし、**Routing機能やモジュール分割は極力避けます。** なぜなら複雑ですから・・・。(elmに限らず)

# 複数のエントリーポイントを持つ1つの動的なページ

「画面の見た目が切り替わること」の要件ではありません。あるコンテンツに対して一度にアクセスしたい。これはつまり、URLを直打ちしてもEmailからリンクで飛んできても、いつどんなときでもある状態を返したい時、このときはSPAをしっかり設計する必要があります。例えば、ホテルに予約をすることが出来るサービスで自分の泊まる宿の説明ページにアクセスするのに、ホームから会員ページを辿って、予約一覧に飛び、宿の詳細に飛んでやっと見れる。そんな体験よりは、予約完了EmailやLINEなどのリンクから一発で飛びたいですよね？ そんな従来のWebページの体験をリロード無しで届けたい。そんなあなたには、elmでのSPAのやり方をご紹介しましょう！ 

[elmでSPAをわかってしまおう](https://qiita.com/ababup1192/items/eb7dec810a3173683b06)
MacにRuby on Rails開発環境を構築する方法(Ruby2.4.1 Rails5.2.2) 

#OS
macOS Mojave
ver 10.14.6


##Homebrewのインストール
[Homebrew](https://brew.sh/index_ja)

```
＄ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

rubyのバージョンを確認

```
$ ruby -v
> ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]
```

brewを使用して最新のrubyをインストールする

```
$ brew install rbenv ruby-build
```

インストールされたことを確認する

```
$ rbenv --version
> rbenv 1.1.1
```
bash_profileを編集する

```
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile
$ source ~/.bash_profile
```
インストール可能なrubyのバージョンを確認する

```
$ rbenv install -l
```
希望するバージョンを指定してインストール

```
$ rbenv install 2.4.1
```

```
$ rbenv versions
> * system (set by /Users/user/.rbenv/version)
  2.4.1
```
rbenvのバージョンを切り替える

```
$ rbenv global 2.4.1
```
rubyがインストールされたことを確認する

```
$ ruby -v
> ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin18]
```
##bundlerのインストール

```
$ gem -v
> 2.6.11
```
bundlerをインストールする

```
$ gem install bundler
> Fetching: bundler-2.0.1.gem (100%)
Successfully installed bundler-2.0.1
Parsing documentation for bundler-2.0.1
Installing ri documentation for bundler-2.0.1
Done installing documentation for bundler after 5 seconds
1 gem installed
```
bundlerのインストールを確認する

```
$ bundler -v
> Bundler version 2.0.1
```
##Railsをインストール

```
$ gem install rails
```
インストールされたことを確認

```
$ rails -v
> Rails 5.2.2
```
Android向けアプリ内課金（Google Play Store）でテスト確認までにはまったポイント

Android向けアプリのアプリ内課金を作っていて、テスト確認するまでにはまったポイントを自戒も込めてメモしておきます。

そもそものBillingの実装の仕方についてはこのあたり公式ドキュメントとQiitaなど参考ページをご確認ください。

https://developer.android.com/google/play/billing/billing_overview
https://developer.android.com/google/play/billing/billing_testing
https://qiita.com/knkj28/items/91ff37dedc767463459b
https://qiita.com/takahirom/items/4d597b00f500efb3dc7f
https://qiita.com/intel_au/items/0d3266d028c788f3ac2d#課金するgoogleアカウントを事前にデベロッパーコンソールから設定しておく必要があるhttps://www.masaibar.com/entry/play_billing_library_codelab#fn-2d90fbfe
http://akai0ringo.blog.shinobi.jp/android/androidのアプリ内課金処理


# はまったポイント1

一番はまったのが、BillingSDKなどを使って一通り実装をした後、動かしてみると `startServiceConnection` や `onBillingSetupFinished` で `responseCode=0` が返ってきているにもかかわらず、 `querySkuDetailsAsync` の中に、自分が定義したSKUのリストが返ってきてくれないというところでした。

特に
https://qiita.com/knkj28/items/91ff37dedc767463459b#自分が定義した商品idを使う
この辺りをよく読んでから作業をすればよかったのですが、ひとまず自分のアイテムではなくてもいいやと考えて、リクエストするプロダクトIDを`android.test.purchased` のようなテスト用に用意されているものに変えてみたところ正常に情報が取得できたところで、問題がプログラム部分ではないのではないか、ということに気づきました。

## 対応ポイント

まず、一番大きな原因だったのが`テスター`の扱いでした。
商品登録をするためにAPKをいったんアップロードする必要があったり、というあたりは気づいて手続きしていて、内部テスターとして自分のアカウントも登録していたのですが、そのテスト登録したAPKについては内部公開するところまで手続きができていませんでした。
このため、テスター登録自体が有効ではない（オプトインが完了していなかった）状態だったので、いくらやっても有効な商品リストが取れない、という状態でした。

![screenshot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45794/8748f490-5fce-8db6-f71a-ef9095368cd9.png)

結果としてみてみると、Google Play Consoleのアプリのリリース画面で、左側のメニューに表示されるチェックがすべてグリーンになり、右側の「内部テストとして限定的な公開を開始」のボタンがクリックできる状態になるまで情報を登録する必要がありました。
この状態に持っていくためには、ストアに公開する情報も一通り登録する必要があるため、`アプリアイコン`や`ヘッダー画像` `スクリーンショット`なども登録する必要があります。
またアプリ内で設定しているパーミッション次第では、プライバシーポリシーのページのURLを設定する必要もあるかもしれません。

このあたりの情報を一通り設定してアプリを公開手続きした後、数十分すると、Console上でオプトインURLが確認できるようになるのでそのURLをテスター登録しているアカウントに送って、オプトイン手続きまで完了して、初めて、商品情報を取得することができました。

--- 
# はまったポイント2（追記）

上の問題をクリアした後、いざ購入処理、と進めてみたところ、何をクリックしても「このバージョンのアプリは、Google Playを通じたお支払いはご利用になれません。詳しくはヘルプセンターをご覧ください。」というエラーが…

## 対応ポイント

参考URLを見ていただければ書いてあるのですが、アカウントをGoogle Developer Console上で「テスト用のアクセス権がある Gmail アカウント」として登録する必要がありました。
参考ページの記述自体は最初から読んではいたのですが、設定場所が見つからず、「Consoleのバージョンが変わって設定が不要になったのかな？」などと考えてしまっていましたが、何のことはない、「設定＞デベロッパーアカウント＞アカウントの詳細＞ライセンステスト」と進むためには、まず最初に「すべてのアプリ」の、Consoleトップページに戻す必要があるだけでした。
アプリを選択した、個別設定画面の中からは直接は「設定」ページに進めません。（と思います）

このライセンステストのアカウント設定については、設定の反映まで数時間待つような必要はなく、設定直後から普通にテスト購入ができるようになりました。

--- 

チームでやっているとこのあたりの情報は把握できて当たり前かもしれませんが、個人で調べながらやっているとなかなか情報が少なくて気づけないポイントなんじゃないかと思いましたのでまとめてみました。
どなたかの助けになれば幸いです。

--- 

### ついでにもう１ネタ

これだけだとあまりにも何なので、取得した商品の並び替えについて。
商品を価格別に並べようと思った時、例えば、価格帯が `1,000` `300` `500` となっている場合、普通にsku.priceで並べ替えをすると、文字列のため、このままの順番で並んでしまいました。

~~~
        skuDetailsList.sortBy { it.priceAmountMicros }
~~~

とやることで、値段の昇順に並んでくれました。
俺俺Git運用手順(git-flow導入)

### 前提
* 個人開発の小規模プロジェクト
* 使うツール、サービス
    * GitHub
    * Sourcetree
    * git-flow

### git-flow導入
* ブランチ管理を一定のルールで縛るので楽になる。
* git-flow導入はリポジトリ作成後も大丈夫なようです。
  * [Sourcetreeを使って既存のリポジトリをgit-flowにする](https://qiita.com/rema424/items/1758fa72221fb973f2c6)

### 運用
* 基本ブランチ
    * master(本番)
    * develop(開発)
* なにか機能追加したいな~
    * issue書く。(小さいものは書かない。)
    * git-flowでdevelopから新規Featureを作成
        * 名前は機能名を入力(単語の区切りはアンダーバー)
        * developにマージ
* 本番でバグでたな~
    * issue書く。
    * masterからhotfixブランチを切る
        * 命名はissue番号で書く。
        * master, developにマージ
【自分用メモ】Javascript(ES6)のrest演算子とspread演算子について

最近Javascript(ES6)の学習をしており、今日もいくつか文法を習ったのでメモ程度に残しておきます。

####rest演算子

例えば配列ではなく、以下のようにいくつもの数字の合計を求めたいが、数字がどんどん増えていくときに、いちいち引数の部分を修正していくのは現実的ではない。

```js
function addNumvers(a,b,c,d,e,f){
 const numbers = [a,b,c,d,e,f] //配列にする
 return numbers.reduce((sum,number) => {
 return sum + number;
},0);
}

//この中の数字が可変的であるとする
addNumbers(a,b,c,d,e,f)
```

そんなときにrest演算子が使えて、引数のところに(...numbers)を記述する。
これにより、入ってきた数値を配列に変換し、配列として、関数の中で使うことができる。

```js
function addNumbers(...numbers){

//reduceで合計値を求める
 return number.reduce((sum,number) => {
   return sum + number;
},0);
}


addNumbers(1,2,3,4,5,6,7); //いくらでも数字を増やしても大丈夫
```

####spread演算子

このような配列があり、配列を組み合わせて一つの配列にしたいとする。

```js

const defaultFruits = ['りんご','バナナ'];
const userFavoriteFruits = ['オレンジ','ぶどう'];

//ES5までの記述。concatを使う。
defaultFruits.concat(userFavoriteFruits);
//結果
['りんご','バナナ','オレンジ','ぶどう']

//spread演算子は、以下のような記述をし配列を一つにする。
[...defaultFruits,...userFavoriteFruits]

//結果
['りんご','バナナ','オレンジ','ぶどう']
```

####spread演算子の利点
以下のように、要素を追加して新しい配列を作ることができるところ。

```js

[...defaultFruits,'新しい要素',...userFavoriteFruits]
//結果

['りんご','バナナ','新しい要素','オレンジ','ぶどう']
```

直感的にわかりやすい。
Rails new するだけで、なぜかローカルのPostgreSQL環境につながってしまう話

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">今の環境、<br>bin/rails new . -d postgresql<br>だけで、ローカルのpostgresqlに接続できちゃってる。<br><br>database.ymlとかいじってない。<br><br>-d postgresql が初期設定やってくれているのは分かる。<br>でもusernameとかpasswordも設定してないのに<br>何で繋がるの？<br><br>postgresqlユーザ名がデフォルトだからとか？</p>&mdash; kppaz (@kpinput) <a href="https://twitter.com/kpinput/status/1137247450228330496?ref_src=twsrc%5Etfw">2019年6月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

という問題に遭遇。

`database.yml`で、
ユーザ名もパスワードも設定していないのに、
普通に`db:create`とか出来てしまう。

個人開発の環境で、
RailsからDBにアクセスはできるので直ちに実害は無いけど、
気持ち悪いので調査。

結論としては、以下2つの組み合わせっぽい。

- Rails database.ymlデフォルト動作
- HomebrewからPostgreSQLをインストールした際のデフォルト設定

## Rails database.ymlデフォルト動作
特にdatabase.ymlでusernameもpasswordも設定していない場合、
Railsは以下のような動作をするらしい。

```ruby:database.yml
  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user that initialized the database.
  username:
```
端的に言うと、
`usernameが設定されていない場合は、
DBの初期設定を実施したOSのユーザ名を使うよ、`
という感じだと思う。

多分通常は、PCのユーザ名辺りが使われるんだろう。
なるほどなるほど。

## HomebrewからPostgreSQLをインストールした際のデフォルト設定
usernameを設定しなくても、有効なPostgreSQLのユーザ名を指定してくれるのは分かった。

でもPostgreSQL側で設定しているはずのpasswordが無視されているのは納得いかない！

で調べた所あっさり理由は見つかった。

> HomebrewでPostgreSQLをインストールすると
> pg_hba.conf に記載される初期設定では、 接続を無条件で許可する というせっていになっている。
https://qiita.com/Mitsunori_Tsukada/items/383a7b7124e3c4d9c82f

何だそりゃまじかー。

確かにこんな感じになっていた。

```pg_hba.conf
# CAUTION: Configuring the system for local "trust" authentication
# allows any local user to connect as any PostgreSQL user, including
# the database superuser.  If you do not trust all your local users,
# use another authentication method.

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
```

コメント含めて、めっちゃ書いてあるね。

### まとめ
- コメント有能。ちゃんと読むべき。
- PostgreSQLの基本設定項目くらいは知っとかないとな。。。

特にPostgreSQLはこの設定知っていれば瞬殺だった気がする；；
51歳からのプログラミング　備忘　jquery　で　google.maps Infowindow　の要素を操作　カスタマイズ

jqueryやjavascriptで、google.mapsで使うinfoWindowの要素を操作。
とりあえず、cssで初期設定を変更

最初、infoWindowの要素を補足できなかったのですが、
非同期処理を参照していたことが原因。
infoWindow生成後に参照することで解決。


cssでinfoWindowの要素を設定
--
```html:css
<style>
/* 吹き出し下の　下三角（▼）を操作*/
.gm-style-iw::after
    {display:none;
     /* background:rgba(255,255,255,0.7) !important;*/
    }


/* 吹き出し部の、スクロールバーを除く*/
.gm-style-iw-d
    {overflow:unset !important}


/* 吹き出しの背景の余白を調整（スクロールバーを削ったので、余白を入れて見栄えを整える*/
.gm-style-iw-c
    {paddind-right:12px  !important;
     padding-bottom:12px !important;
    }


/* infoWindowの背景色*/
.gm-style-iw
    {background-color:rgba(255,255,255,1) !important}
</style>
```

InfoWindowのロードイベントで処理
--
大変に参考になりました。ありがとうございます。
>https://lab.syncer.jp/Web/API/Google_Maps/JavaScript/InfoWindow/domready/

`infoWindow.addListener( "domready", function{});`
イベントリスナーを設置して、infowindow読み込み後に要素を取得して操作すればOKでした。
やったね！
ROC曲線&AUCとは？

##はじめに

こんにちは！
今回はクラス分類のために作ったモデルの精度が本当に良いものなのか調べるための概念を紹介したいと思います。
論文とまではいかないにせよ、研究結果をプレゼンで発表したい時などに使えますのでぜひチェックしてみてください。
AIに興味がある**医学生**や**医師**の方などにもぜひ読んでいただきたい記事となっています！

#今回のモデル。
![IMG_2859.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405324/c5cec14b-3258-90f7-21af-8b828a884f25.jpeg)

下手な絵ですみません。。。
ある病気を例にとって考えてみます。
イガイガしているのが病気で、笑顔なのが健康な状態だとしましょう。
この疾患の有無で2クラス分類した時に「これは病気だ」とAIが判断する確率を陽性率とすると、**「真陽性率＝AIが陽性と判断した中で本当に病気がある人の割合」**、**「偽陽性率＝本当に陰性の人をAIが陽性と判断した割合」**と定義できます。
#ROC曲線とAUC

では先ほどのモデルにおいて、陽性率が0.7以上のものを陽性とみなすとしましょう。
すると

![IMG_2860.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405324/6ea57a4c-abf4-d0b3-3929-4ee7ade99a76.jpeg)
このように赤い線で線引きができます。
ROC曲線とは**「この基準となる確率(pとする）以上のものを陽性とみなす」**という風に設定した場合の真陽性率を縦軸に、偽陽性率を横軸にとって点をプロットし、その基準となる確率を変えていくことでできる曲線です。
この場合、偽陽性率は1/4、真陽性率は2/3となるのでこんな点がプロットできます。
![IMG_2861.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405324/5cb15164-bfb7-906b-b850-770323c33536.jpeg)

pが小さくなると縦軸も横軸も値が上昇するので点は右上に進んでいきます。
このAIの分類精度が高い時は縦軸の方が上昇が早いので、グラフは早い段階で右上に上昇していきます。

そのようにしてできた曲線の下の部分の面積を**AUC(Area Under Curve)**と言います。つまりは、AUCが大きいほどそのAIは優れた精度で分類ができていると言えるのです。

##AUCを自動計算

さて、ここまで読んでいただけた方は薄々気づいているかもしれませんが、AUCはどのように算出するのでしょうか？
手計算で積分？
いや、決してそんな面倒な手間はいりません
**scikit-learn**でチャチャッと求めてしまいましょう。

```python
import numpy as np
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt

#健康な状態を「0」、病気を「1」としてリストに格納
y = np.array([0,0,0,0,1,1,1])
#それぞれの陽性率もリストに格納
pred = np.array([0.1,0.2,0.3,0.8,0.5,0.7,0.9])
#AUCの出力
print(roc_auc_score(y, pred))
#ROC曲線の描出
roc = roc_curve(y,pred)
fpr, tpr, thresholds = roc_curve(y,pred)
plt.plot(fpr, tpr, marker='o')
plt.xlabel('FPR: False positive rate')
plt.ylabel('TPR: True positive rate')
plt.grid()
```

今回用いたデータで試すとこのようなコードになります。
実行すると、、、

![スクリーンショット 2019-06-08 16.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405324/bbc8c123-edb6-dd4e-d468-a191e61ef47a.png)

こんなグラフがAUCとともに描出されるはずです！
AUCの最大値は1なので、0.8333...はまずまずかな？という精度です。
0.90を超えたあたりから優れたモデルと言えるのではないでしょうか。

##終わりに
いかがだったでしょうか？
このようにして簡単にAUCもROC曲線も求められますので、AIを開発したはいいけど結果のまとめ方に困っているなんて方はぜひ役立ててください！

最後に、医学生である僕が所属しているツカザキ病院眼科AIチームのページも見ていただけたら幸いです！ぜひご覧ください！
[ツカザキ病院眼科AIチーム DeepOculus](https://qiita.com/organizations/deepoculus)

僕が書いた記事もいくつかリンクを貼っておきます。
[10分で分かるAIの歴史](https://qiita.com/cr-fun/items/adf0f7f405eeebc42a50)

[プログラミングやディープラーニングの勉強、何から手をつければ良い！？](https://qiita.com/cr-fun/items/90fa4fa39cf1269e38d9)

では、また次の記事で！
SpringBootでHelloWorld

##環境
* Mac Mojave 10.14.5
* IntelliJ IDEA
* JDK 1.8
* Gradle

##プロジェクトの作成
まずはプロジェクトを作成します。
**新規プロジェクトの作成**をクリックします。
![スクリーンショット 2019-06-07 21.51.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/fc37d722-5777-21de-c87f-b38a409dbace.png)

**Gradle**と**JDK**を選択し、**次へ**を押します。
<img width="932" alt="スクリーンショット 2019-06-07 22.01.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/f4705cd1-ba93-d0fe-3ef7-c0a63ae8b1f8.png">

**グループID**と**アーティファクトID**を入力し、**次へ**を押します。
・グループID：HelloWorld
・アーティファクトID：HelloWorld
<img width="932" alt="スクリーンショット 2019-06-07 22.16.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/c2428a3f-d0ed-e6f1-6d0c-d8b0e3ea2dd0.png">

保存した際、Gradleでの依存解消を自動で行うよう、**自動インポートを使用する**にチェックを入れ、**次へ**を押します。
<img width="940" alt="スクリーンショット 2019-06-07 22.16.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/b2ade4f5-203c-03fe-c231-043791c0033d.png">

**プロジェクト名**を入力し、**完了**を押します。
・プロジェクト名：HelloWorld
![](https://i.imgur.com/k8d8yeW.png)

下記ポップアップが出た場合は**許可**を押します。
<img width="415" alt="スクリーンショット 2019-06-07 22.17.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/ce59b576-afa5-2a13-4700-b2ab34e1830b.png">


##アプリケーションの作成
では、実際にSpringBootを使ってブラウザ上でHelloWorldを表示するプログラムを書いていきましょう。

(プロジェクトRoot)/src/main/javaを右クリックし、新規クラスを作成します。
.（ドット）で区切ったパッケージ名も含め、名前にクラスを指定します。
**名前：** jp.example.Application
![](https://i.imgur.com/jzBQ7rH.png)

importするとエラーが発生するので依存関係を解消します。
<img width="589" alt="スクリーンショット 2019-06-08 15.34.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247661/373f3a6e-719d-f50f-b1f1-bd8b6b21a830.png">


```groovy:build.gradle
plugins {
    id 'java'
}

group 'HelloWorld'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.3.RELEASE'
}
```

プロダクトコードを書いていきます。

```java:Application.java
package jp.co.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
```

```java:HelloController
package jp.co.example;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/")
    public static String Hello(){
        return "Hello World!";
    }
}
```

実行し、以下アドレスへアクセスします。
http://localhost:8080/

ブラウザ上でreturnした文字列が出力されればOKです。
![](https://i.imgur.com/4oVvHs1.png)
URLスキーム経由でローカルプログラムを実行する

## はじめに

HTML の リンクをクリックするとローカルPC内のアプリを実行する方法です。

### カメラの起動の例

```html:camera.html
<!DOC TYPE HTML>
<html>
<body>
    <a href="microsoft.windows.camera:">カメラを起動</a>
</body>
</html>
```

## 任意のアプリを実行可能にする

### レジストリの設定

下記記述の凡例

- 【キー】
- 「値」

```:設定内容
HKEY_CLASSES_ROOT
└【{任意の名前}】
　　├「(規定)」URL:{任意の名前}
　　├「URL Protocol」
　　└【shell】
　　　　└【open】
　　　　　　└【command】
　　　　　　　　└「(規定)」{実行したいファイルパス}
```
```:例
HKEY_CLASSES_ROOT
└【Qiita】
　　├「(規定)」URL:qiita-test
　　├「URL Protocol」
　　└【shell】
　　　　└【open】
　　　　　　└【command】
　　　　　　　　└「(規定)」d:\temp\test.bat
```

### HTML の記載

```html:qiita_test.html
<!DOC TYPE HTML>
<html>
<body>
    <a href="qiita-test:">独自キーのアプリを起動</a>
</body>
</html>
```

## おわりに

メモしていたのものを掘り起こしただけの覚書なので、有意性をあまり分かってないで書いています。
知見のある人からフォロー頂ければ嬉しいです。
競技プログラミング(C++)で使われる基本的な入力取得

競技プログラミングをやってみようと思ったのですが、
毎問題で入力取得の記述に時間を取られるのがいやなので、
基本的な入力取得をまとめました。


# 入力

```input.txt
1
2 
3 4 5

5
1 2 3 4 5

3 4
1 2 3 4
5 6 7 8
9 10 11 12

1,2,3

string1 string2
string3
```

# C++で記述した入力取得

```main.cpp
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
    //cinでファイルから読込
    ifstream in("input.txt");
    cin.rdbuf(in.rdbuf());


    //cinの高速化
    cin.tie(0);
    ios::sync_with_stdio(false);
    

    //通常の入力
    int a,b,c,d,e;
    cin >> a;
    cin >> b;
    cin >> c;
    cin >> d;
    cin >> e;
    cout << a << "," << b << ","<< c << ","<< d << ","<< e << endl;


    //数指定の入力
    int N;
    cin >> N;
    cout << N << endl;

    int n[N];
    for(int i = 0; i < N; i++){
        cin >> n[i];
        cout << n[i] << flush;
        i != N-1 ? cout << "," : cout << endl; ///一連の数字をカンマ区切りにし最後に改行を加える
    }


    //縦横の個数指定の入力
    int H,W;
    cin >> H;
    cin >> W;
    cout << H << "," << W << endl;

    int box[H][W];
    for(int i = 0; i < H; i++){
        for(int k = 0; k < W; k++){
        cin >> box[i][k];
        cout << box[i][k] << flush;
        k != W-1 ? cout << "," : cout << endl; //一連の数字をカンマ区切りにし最後に改行を加える
        }
    }


    //カンマ区切りの読込
    int f,g,h;
    cin >> f;
    cin.ignore();
    cin >> g;
    cin.ignore();
    cin >> h;
    cout << f << "," << g << ","<< h << endl;
    

    //文字列の読込
    string str[3];
    cin >> str[0];
    cin >> str[1];
    cin >> str[2];
    cout << str[0] << "," << str[1] << ","<< str[2] << endl;

    return 0;
}
```

# 出力結果
```out
1,2,3,4,5
5
1,2,3,4,5
3,4
1,2,3,4
5,6,7,8
9,10,11,12
1,2,3
string1,string2,string3
```

## 補足説明
### cinでテキストファイルから読み込む
引用:[cin でテキストファイルから読み込み](https://qiita.com/_meki/items/559ff91f3e695de5600f)

以下の記述を頭につけることでcinの入力元をキーボードでなく
テキストファイルからにすることができます。
ローカルでテストする際に入力をいちいち打つのはめんどくさいが、
提出するコードは極力変えたくたいときに使うといいで。

```cpp

    //cinでファイルから読込
    ifstream in("input.txt");
    cin.rdbuf(in.rdbuf());
```

### cinの動作を高速化
引用:[tshitaの備忘録Ⅱ C++入力の速度測定](http://tatanaideyo.hatenablog.com/entry/2014/10/24/214714)
以下のおまじないを書くとcinの動作が早くなるらしい。
scanfを使うともっと早いみたいだが、競プロ初心者のうちはそこまでこだわらなくても大丈夫かと思っている。

```cpp

    //cinの高速化
    cin.tie(0);
    ios::sync_with_stdio(false);
```
リンクタグの作り方

こんにちは！未来電子テクノロジーインターン生の西尾です！
今日は、HTMLでリンクの貼り方についてご紹介します！

#リンクタグとは
リンクタグとは、WEB上で文字や画像を囲んでリンク先を指定するHTMLタグです。

```html
<a href="参照するリンク先のＵＲＬ">アンカーテキスト</a>
```

上記が基本です。

リンクをクリックした際に通常は現在表示しているページが切り替わってリンク先の新しいページへと移動しますが、現在のページを開いたままの状態で外部サイトを参照する場合は、

```html
<a href="参照するリンク先のＵＲＬ" target="_blank">アンカーテキスト</a>
```
で表すことができます。

リンクには、外部リンクと内部リンクがあります。
ホームページ内の他のページにリンクする場合は内部リンク、外部のサイトへリンクする場合を外部リンクと言います。

#まとめ
今回は、リンクタグの作り方をまとめました。
HTMLでリンクを貼り付けたいときはこの記事を参考にしてみてください。
atcoder 茶色レートを目指して １話

#はじめに
このサイトでは私が灰色レートから茶色レートなるまでをまとめていきたいと思います。

#目標
夏休みまでに茶色レートになりたい。できればもっと速くなりたいな

#活動報告
今回はABC121のC問題が面白いと風の噂を聞いたので取り組んでみることにしました。
使用言語はc++です。
・[ABC121:C問題](https://atcoder.jp/contests/abc121/tasks/abc121_c)
問題の詳しい内容は上記のサイトを見てくださるとありがたいのです。今回の問題を要約するとAの配列の中で小さい順に選んでいってM本を超えないように調整しようという感じになります。
今回の問題の難しいところはA,Bを別々の配列に入れていき、Aの方を昇順にソートしてしまうと適切な本数と値段ではなくなることだと思います。そこでstd::pairというテンプレートクラスを知りました。
pairに関してはc++のリファレンスを見ていただくと詳しい内容がわかると思いますが簡潔に説明すると、２つのデータを１つのデータとして扱えてソートができるものです。（間違えていたらすいません）
よって今回の問題はまさにうってつけですね。
こちらが今回提出したソースコードになります。
[ザキのソースコード](https://atcoder.jp/contests/abc121/submissions/5821289)
今回の問題ではpairの１つ目のところを昇順にソートをすればいいので、
```
std::sort(ab.begin(),ab.end());
```
でできちゃいます。
以上が活動報告になります。
#終わりに
これからも気が向いたらatcoderの問題を解いて、このサイトにまとめていきたいと思います。日本語の間違いや説明不足の部分などがあると思いますが温かい目で見ていただくとありがたいです。
コンテナへのsshログイン時に環境変数を反映させる方法（Docker, kubernets）

Dockerでsshログインする際に環境変数が反映されない課題の解決法。sshを使用するコンテナは機械学習の環境構築用を想定。
(pythonとpycharmnでsshログインして使用、など）

###1.背景と課題
一般にDockerfileで環境変数を使う際は、ENVを使う。

```
#ENV 環境変数名 パス
ENV SPARK_HOME /usr/local/spark
```
しかし、Dockerやkubernetsへsshでログインすると、この記法ではPATHなど一部の環境変数が反映されない課題がある。

名前が被らない環境変数は/etc/environmentに記入することで対応可能。

```
RUN echo "export SPARK_HOME=/usr/local/spark"  >> /etc/environment
```
しかし、PATHなど元々存在する環境変数にはこの方法が通用しない。

対策として~/.ssh/environment を使う方法が散見されるが、この方法はsshコマンド実行直後にしか環境変数は反映されない。
###2.原因
PATHなどの環境変数が反映されない問題はssh経由のBash起動時に.bashrcを読み込まない事が原因である。
###3.対策
.bash_profileにを作成して.bashrcを読み込ませて対策を行う。

```
#.bash_profileを作成し、.bashrcを読み込む（シェルスクリプト）
RUN echo "if [ -f ~/.bashrc ]; then  . ~/.bashrc;  fi" >>~/.bash_profile
# 環境変数の書き込み（PATHへ/usr/local/spark/binの追加)
RUN echo "PATH=${PATH}:/usr/local/spark/bin" >> ~/.bashrc
```
rootユーザー以外の場合は出力先を下記に書き換える

```
 /home/ユーザー名/.bash_profile
 /home/ユーザー名/.bashrc
```

以上
WordPressの開発環境をDockerで立ち上げると遅すぎる問題とその対策

# TL;DR

- Docker for mac でローカルのボリュームをマウントすると非常に動作が遅い
- 解決策として、頻繁に更新されるものだけをボリュームとしてマウントし、それ以外はDockerイメージ内に入れてしまう
- 副作用としては、上記でマウントしたボリューム外のファイルを更新するのがすこしだけ厄介
  - ただし、それは別途マウントすればいいだけなので、そこまで大きな問題ではない

# 経緯

WordPressの開発環境(PHP,MySQL)をホストOS直下に入れたくなかったし、Gitリポジトリにコードの形で残しておきたかったので、Dockerで開発出来るようにしていた。 以前使っていたのは https://phpdocker.io/ の `docker-compose.yml` および Dockerfile 系の一式

しかし、PHPの様々なスクリプトファイルを読み出す処理とDocker for macのvolumesでホストOS側のディレクトリをマウントする仕組みの相性が悪く困っていたので、解決した。

原因であるDocker for macのvolumesが遅い問題はこの辺の記事がわかりやすいかと https://blog.hanhans.net/2017/05/23/docker-for-mac-slow/
cachedを使えば良いｎかもしれないけれど、この記事では別な方針で解決している。

# 方法と実際のコード

`TL;DR` に書いた通りで、頻繁に更新されるファイルだけをボリュームとしてマウントすればいいし、それ以外はDockerイメージに入れてしまえばここまで遅くならない。
私が開発している案件ではWordPress本体コードも全てGitリポジトリ以下に置いている(※ただしwp-config.php等は本番サーバーとは異なるものがリポジトリに入っている)が、すこしだけ変えればテーマのみをリポジトリで管理しているような案件でも使えるはず。

```docker-compose.yml
version: "3.1"
services:
  wordpress:
    build: .
    volumes: 
      # theme以下はbuild時だけでなく更新かけたいのでVOLUMEで入れてる
      - ./wordpress/wp-content/themes/mytheme:/var/www/html/wp-content/themes/mytheme
      - ./wordpress/wp-content/uploads:/var/www/html/wp-content/uploads
    ports:
      - "80:80"
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    volumes:
      - mysql:/var/lib/mysql
      - ./mysql-initdb.d:/docker-entrypoint-initdb.d
    # Set max_allowed_packet to 256M (=32505856)
    command: --max_allowed_packet=32505856
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_ROOT_PASSWORD: ''
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
  mysql:
```

```Dockerfile
# Dockerfile
FROM wordpress:php7.2-apache

# 基本的には手元のwordpressを入れなおす
ADD ./wordpress /var/www/html

# 注意: .dockerignore の存在を忘れないこと。
```

```sh
# .dockerignore
wordpress/wp-content/uploads
wordpress/wp-content/themes/mytheme
```

# おわりに

こんな感じで、ローカル確認が遅すぎてもはやステージングサーバーに毎回送った方が早いんじゃないかというレベルで微妙な気持ちになる開発環境が改善しました。うれしい。

僕は普段はPHPあんまり書かなくて、色々な制約から仕方なくWordPressを触ってるんですが、そういう人って結構多い気がするし、そういう人はDockerで環境をコンテナに押し込みたいと思うんですよね。

Laravelとか使ってるPHP案件でも同様に使えると思う。 特にvendor以下をイメージに入れるだけでも速度面はかなりのメリットがありそう。
Ubuntu18.04+Anaconda 環境のプロキシ設定メモ

#目的
プロキシ設定でよく躓くのでメモ

{proxy.address.hoge}と{port number}のところは適宜変えてください
##apt

cd #ホームディレクトリに戻る
cd /etc
cd apt
vim apt.conf
で
apt.confに

``` 
Acquire::ftp::proxy "http://{proxy.address.hoge}:{port number}/";
Acquire::http::proxy "http://{proxy.address.hoge}:{port number}/";
Acquire::https::proxy "http://{proxy.address.hoge}:{port number}/";
```

を書き込み、保存する（そのままだとRandomlyなので：wqで保存できない。自分は:w !sudo tee %で強制書き込みしてる）

##git
CUIから直接

```
git config --global http.proxy http://{proxy.address.hoge}:{port number}
git config --global https.proxy http://{proxy.address.hoge}:{port number}
```

を書いて実行する。

##anaconda
Anaconda がインストールされているフォルダまで行く（何も設定してない場合は”cd ”で行くホームディレクトリにある）
cd anaconda3
vim .condarc

テキストエディタが動作する（いじってない限り何も書かれていない）ので

```
proxy_servers:
    http: http://{proxy.address.hoge}:{port number}
    https: http://{proxy.address.hoge}:{port number}
```

を書いてescキー→:wqで保存して終了

##環境変数に追加したい
mecabのmecab-ipadic-neologd辞書をインストールする時に環境変数にプロキシを追加しないと最後まで行かない
CUIから

```
export http_proxy=http://{proxy.address.hoge}:{port number}
export https_proxy=http://{proxy.address.hoge}:{port number}
```

シェルを閉じると消えるっぽい？
打ったかどうかわからなくなったら

```
export -p
```

で環境変数一覧が出るのでその中になかったらまたexport http_proxy=~~~を打ち直してください
ionicで環境構築する方法

#ionicで環境構築する方法

・Crodovaのインストール

```
npm install  -g  cordova
```

・ionicのインストール

```
npm install -g  ionic
```

・プロジェクトの作成

```
ionic start [project name] [template]
```

・サーバーの立ち上げ

```
ionic serve
```

・Android studio もしくはXcodeでビルド

```
ionic build [android or ios]
```

以上です。
特定文字の間を取得するときの正規表現

pinzu_1.png　という文字列から
pinzu　と
１　という文字列を抜き出したい時の
正規表現が難しかったのでメモ。
pythonで試していますが、正規表現なので他の言語でも
もちろん応用できるかと。

#上手くいかないパターン
pinzu_1.pngとう文字列内の「pinzu」は、
先頭から「\_」の間となります。
先頭を表す文字は「^」なので、マッチパターンは
'^.*_'
でいいかなーと思って動かしてみましたが結果は…

```python.py
>>> import re
>>> re.search('^.*_', 'pinzu_1.png').group()
'pinzu_'
```
「\_」まで入ってきちゃいました…。

#上手くいくパターン
正規表現には「先読み」「後読み」というのがあります。
今回のパターンはそれを利用すると上手くできました！

|表記|意味|
|:--:|:--|
|(?=abc)|先読み|
|(?!abc)|否定先読み|
|(?<=abc)|後読み|
|(?<!abc)|否定後読み|

```python.py
>>> import re
>>> re.search('^.*(?=_)', 'pinzu_1.png').group()
'pinzu'

>>> re.search('(?<=_).*(?=\.)', 'pinzu_1.png').group()
'1'
```
やりたいこと通りにプログラムが動くと嬉しいですね！

参考）[Pythonで正規表現を使ってみた](https://qiita.com/shimajiri/items/fe41c693c6623c50c0c2)
PowerShellでファイル名を一気に変更する方法

## 経緯

お客さんに提出するファイルを整理する際に、たくさんのファイル名の変更をする必要に迫られたため、「これPowerShellで簡単にできるんじゃね？」と考え調べてみた。

## どうやればできた？
下記で一気に変更できた。

```PowerShell:PowerShell
dir | rename-item -newname { $_.name -replace '古い文字列','新しい文字列' }
```


## 実行例
テスト用にテキストファイルを適当に5つ作成する。
フォルダ内のファイルすべての名前の頭に文字列"add"を追加する。

```PowerShell:PowerShell
dir | rename-item -newname { $_.name -replace '^','add' }
```

## 所感
PowerShellを使うとごみプログラム作らなくても容易に、ファイル操作ができそう！