OmniAICreator/Qiita-1.07M huggingface dataset:
【JavaScript】Promiseをしっかり理解したい【その1】

## 初めに
今まで非同期処理の実装は`async` `await`を使用してきましたが、根本的な理解ができておらず非同期処理の実装の度に頭にハテナがついて回っています。なのでまずはPromiseの理解を深め、まとめていきたいと思います。

## Promiseとは

>Promise オブジェクトは非同期処理の最終的な完了処理 (もしくは失敗) およびその結果の値を表現します。

PromiseはJavaScriptのビルトインオブジェクトであり、JavaScriptが動作する環境であればどこからでも呼び出すことができます。その実体は非同期処理を抽象化したオブジェクトであり、非同期処理を操作するための仕組みでもあります。

またPromiseはコンストラクタ関数であり、オブジェクトを生成、使用する際には`new`でインスタンス化します。

```js:promiseオブジェクト生成
const promise = new Promise((resolve, reject) => {
    asyncFunc(){...}
});
```

## コールバック関数との比較

非同期処理といえばコールバック関数で行う方法があると思います。

```js:コールバックによる非同期処理
asyncFunc(arg, (error, result) => { 
    // 最初に実行されるべき処理
    if (error) { // コールバック失敗時の処理
        throw error;
    }
    // コールバック成功時の処理
});
```

asyncFuncを実行した時、asyncFunc関数内の最初に実行されるべき処理が完了した後に第二引数で指定したコールバック関数が実行され、処理順番の担保を取ることができます。

### コールバック地獄
上記のようにコールバック関数が１つであれば、まだ簡潔で処理が追いやすいかと思います。しかし、非同期処理が何個もある場合、コールバック関数では入れ子が深くなり何をやっているのか一見した限りではわからないということがあります。このような問題を`コールバック地獄`といいます。

```js:コールバック地獄
syncFunc((data) => {
  // 初めに実行される処理
  nextFunc((data) => {
    // 次に実行される処理
    nextNextFunc((data) => {
      // 次の次に実行される処理
      finalFunc((data) => {
        // 次の次の次に実行される処理
      }); // finalFunc
    }); // nextNextFunc
  }); // nextFunc
}); // syncFunc
```

実際は一つ一つの処理が何行かに渡って書かれるわけですから１つの関数がかなり肥大化してしまい、これに後から手を付けるとなったら、少しだけ現実から目を背けたくなるかと思います。

これをPromiseで記述すると以下のようになります。

```js:Promiseによるコールバック地獄の解消
function asyncFunc(data) {
  return new Promise((resolve, reject) => {
    // 初めに実行される処理
    
    resolve(hoge);
  });
}

// nextFunc以下もasyncFuncと同様にPromiseオブジェクトをreturnする

...

asyncFunc(data).then((result) => {
  return nextFunc(data);
}).then((result) => {
  return nextNextFunc(data);
}).then((result) => {
  return finalFunc(data);
})
```
Promiseを使用する場合、非同期処理を`asyncFunc`のように関数としてまとめます。その関数では、Promiseオブジェクトが戻り値として返されるように記述します。その後の処理の流れはまた次回にまとめたいと思いますが、軽く説明するとPromise内でresolveされた場合、Promiseのインスタンスメソッドである`then`に処理が移ります。そしてそのthenメソッドの中で次に実行したい`nextFunc`関数を実行します。省略していますが`nextFunc`関数でもPromiseオブジェクトをreturnし、Promise内でresolveされ、次のthenメソッドに移る、という流れになりこうして実行の順番を確保することができます。

コールバック関数と比較すると、一つ一つの処理が小分けにされ何が返ってきてから次の関数が実行されるかが明確になり、修正を加える時などに手をつけやすくなったかと思います。処理の順番も追いやすいですね。

### 書き方
コールバック関数は書き方に明確なルールはありません。自由に記述することができます。ただ、それ故に統一性が失われてしまう可能性もあります。先程のソースコードをもう一度確認してみましょう。

```js:コールバックによる非同期処理
asyncFunc(arg, (error, result) => { 
    // 最初に実行されるべき処理
    if (error) { // コールバック失敗時の処理
        throw error;
    }
    // コールバック成功時の処理
});
```

JavaScriptでのコールバック関数の第一引数には`Error`オブジェクトを渡すという慣例があります。ただし、先述した通りコールバック関数には明確なルールはなく、この慣例はあくまでコーディングルールなので開発者によって様々な書き方になります。

対してPromiseには、コールバック地獄の例でも見たように、成功時の処理と失敗時の処理のそれぞれに関数が用意されており、その用意されているメソッド`then`や`catch`以外は使用することができないので、書き方が統一されます。つまり、Promiseで書き方が統一され、Promiseによる様々な非同期処理のパターン化できることがPromiseのメリットの１つになるでしょう。


## まとめ
まだPromiseに関して序盤もいいとこですが、思ったより長くなってしまったので次回投稿に回したいと思います。初めにも書きましたが開発の非同期処理でいきなり`async` `await`を使って実装したため、理解が足りていないところが多く応用がきかないという状況に陥っていたので今回の記事をまとめさせてもらいました。既に実装で使っているからか、このまとめだけでも今まで疑問に感じていたところが解消されたので良かったです。ただ、Promiseの理解、という観点としてまだまだ足りなさ過ぎるので、次回も引き続き同じテーマで学習していきたいと思います。

## 次回
[【JavaScript】Promiseをしっかり理解したい【その2】](https://qiita.com/kum44/items/73c3e993a716ad5812aa)
【Kotlin】onClickListenerのパターンとその使い分け方

#はじめに
　この記事では私がインプットした`onClickListener`の3つの記法と、そのメリットデメリットを記しています。今回記していくのは3パターンですが、私が恣意的にチョイスしただけで、この3つが全てを網羅している事など無いので悪しからず。

##一つ目：クラス全体に掛かるインターフェースを用いる
　MainActivityに実装すると仮定したとき、クラス自体に`View.OnClickListener`のインターフェースを参照します。

```
class MainActivity : AppCompatActivity(), View.OnClickListener {

　　 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button1.setOnClickListener(this)
    }

     override fun onClick(v: View) {
        val b = v as Button
        textView.text = "${b.text} is pushed"   
    }
}
```
この方法のメリットは、**インターフェースから実装するのでミスが減る**という事と、**冗長なボタン処理をonCreate内に書かずに済む**という事、**複数のボタンに同じ処理を簡単に実装する事**などが挙げられます。ボタンごとに異なる処理を書かないといけないときなどは、かえって分かりにくくなる場合もあるので、考えて使う必要があります。

##二つ目：個々のボタンにメソッドを実装する
　各ボタンに`setOnClickListener`メソッドを実装する方法です。

```
class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button2.setOnClickListener {
            val b = it as Button
            textView.text = "${it.text} is pushed"
        }
    }
}
```
この方法は、**複数個のボタンのそれぞれに全く異なる処理を実装させるとき**に便利です。各ボタンそれぞれに処理を書いていくので、処理が同じ複数のボタンがあるときには向きません。また、各ボタンについて書いていくので、全体としてコードが冗長になりがちです。

#三つ目：変数に処理を代入する
　ある変数に`View.OnClickListener`を介して処理を実装します。

```
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val listener = View.OnClickListener {
            val b = it as Button
            textView.text = "${b.text} is pushed"
        }
        button3.setOnClickListener(listener)

    }
```
今回は`listener`という変数に処理を記述し、`setOnClickListener(listener)`でボタンに適用させています。この方法のメリットは、**複数個のボタンに同じ処理を適用させやすい事**や、**そういったケースが複数種類あるときも簡潔に記述できる事**にあります。しかし、処理が複雑になるとonCreate内が冗長になってしまうというデメリットがあります。

#さいごに
　今回は以上三つの方法と、そのメリットデメリットについてまとめました。勿論、細かい記法を変えることでさらにスマートに記述できるかもしれませんが、分かりやすさも兼ねてあの状態で記しておきます。意外とクリック処理を体系的にまとめている記事が無かったので、お役に立てれば幸いです。
Java：ResourceBundleのpropertiesファイルを任意の場所に配置する

# はじめに

JavaでLocateを使用する際に `ResourceBundle` を使用することになった。

そこで `ResourceBundle` 用のpropertiesファイルをresourceディレクトリに配置した際に、対象のファイルが見つからないエラー(java.util.MissingResourceException)が発生したため、任意の場所にpuropertiesファイルを配置するための備忘録を以下に残す。 


## 環境

**▼ ディレクトリ構造**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239591/43ae82dd-dc5d-d630-3a6f-e72b4e218120.png)


`Main.java` にて、日本とアメリカのLocaleを用意し、各ロケール用のpropertiesファイルをresourceディレクトリ直下に配置したが、propertiesファイルが見つからないと言われた。

原因は、クラスパスが以下で参照できないでいた為である。

* `C:\tool\pleiades\workspace\gold\bin`

ちなみに、上記は次の記述で確認可能である。

```java:Main.java

class Main {
	public static void main(String[] args) {
        System.out.println(System.getProperty("java.class.path"));
}
```

余談だが、上記のクラスパスの状態でpropertiesファイルを読み込ませるためには `main` ディレクトリ直下に配置する必要がある。


## 任意の場所にpropertiesファイルを配置して参照させるために

結論から言うと `URLClassLoader` を使用する。

```java:Main.java
class Main {
	public static void main(String[] args) throws MalformedURLException {

        File dicDir = Paths.get(".\\resource").toFile(); // ★1

        URLClassLoader urlLoader; // ★2
        urlLoader = new URLClassLoader(new URL[]{dicDir.toURI().toURL()}); // ★3

		Locale localeJp = Locale.JAPAN;
		Locale localeUs = Locale.US;

		List<Locale> locales =
				new ArrayList<Locale>(Arrays.asList(localeJp, localeUs));

		for (Locale locale : locales) {
			ResourceBundle rb =
					ResourceBundle.getBundle("Source" ,locale ,urlLoader); // ★4

			System.out.println(rb.getString("apple") + rb.getString("orange"));

		}
	}
}
```

任意の場所に配置したpropertiesファイルを参照する手順は以下の通り。

1. ★1でpropertiesファイルを配置する場所を指定する。
2. ★2と★3で1で指定したクラスローダのインスタンスを生成する。
3. ★4で基底名がSourceのpropertiesファイルを参照する。


これで★1のパスを変更することで任意の場所にpropertiesファイルを参照することが出来るようになった。


## おさらい

* propertiesファイルのパスを指定しない場合：実行するjavaと同じ階層に配置
* propertiesファイルのパスを指定する場合　：URLClassLoaderを使用する
nanoでもvimでも常に行番号を表示したい！！

# タイトルの通りnanoとvimで行番号を表示する方法

## 追記
### 2021/01/04
下記の方法ではnanoの行番号を表示できなかったのでnanoの**"下準備"**を追加しました．

## まずはnanoから

### 下準備

```Terminal
$ nano -V
GNU nano version 2.0.6 (compiled 17:24:29, Jun  5 2020)

$ brew install nano

$ nano .zshrc
```

```".zshrc"
alias nano='/usr/local/bin/nano'
```

```Terminal
$ source .zshrc

$ nano -V
GNU nano, version 5.4
```

### 手順0(ホームディレクトリにいる場合はスキップ)

```Terminal
$ cd
```

### 手順1

```Terminal
$ vim ~/.nanorc
```

### 手順2

```Terminal
$ set linenumbers
```

<img width="585" alt="スクリーンショット 2020-07-03 2.37.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563637/a02591d9-e526-55d9-dc74-d7af6f56b286.png">

### 手順3

```Terminal
$ source .nanorc
```

これだけ.

## 続いてvim

### 手順0(ホームディレクトリにいる場合はスキップ)

```Terminal
$ cd
```

### 手順1

```Terminal
$ nano ~/.vimrc
```

### 手順2

```Terminal
set number
```

コメントアウトしたい場合は

```Terminal
" 行番号を表示
set number
```

<img width="585" alt="スクリーンショット 2020-07-03 2.38.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563637/515c64c7-39dc-634b-9199-f1bc6f857948.png">


### 手順3

```Terminal
$ source .vimrc
```

これだけ.

こんな感じで行番号を表示することができるけどコピペしづらくなるかも.
一体いつになったらプログラミングの記事を書けるようになるかな...
haml データベース取得　投稿機能表示


アウトプット用です。
簡単な投稿機能の実装をしていたのですが若干詰まりました。

<img width="1068" alt="7104fd57826d56cd55a226533ee87e28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653208/b8fbaf56-8567-3e85-4fc1-8bb824a19384.png">

下記コードです。

```top_page_controller.rb
class TopPageController < ApplicationController
  def index
    @toppages = TopPage.all
  end

  def new
    @toppage = TopPage.new
  end

  def create
    TopPage.create(TopPage.params)
    redirect_to top_page_index_path
  end

  def show
  end

  private
  def TopPage_params
    params.require(:TopPage).permit(:contents)
  end
end
```
```top_page>index.html.haml
.top
  %ul.top__side
    ジャンル
    %li.top__side__love
      恋愛
    %li.top__side__work
      仕事
    %li.top__side__money
      お金
    %li.top__side__friend
      友人
    %li.top__side__school
      学校
    %li.top__side__other
      その他
  .top__consultation
    .top__consultation__title
      お悩み一覧
    .top__consultation__text
      = top_page.contents
      .top__consultation__text__time
        = top_page.created_at
```

データはパスしているし受け取るカラムも指定しているよな。。。？と思ってましたが
よくみたらtop_pageの定義していない事に気付きeach文を使ってみました

```top_page>index.html.haml
.top
  %ul.top__side
    ジャンル
    %li.top__side__love
      恋愛
    %li.top__side__work
      仕事
    %li.top__side__money
      お金
    %li.top__side__friend
      友人
    %li.top__side__school
      学校
    %li.top__side__other
      その他
  .top__consultation
    .top__consultation__title
      お悩み一覧
  = @toppages.each do |top_page|    ←追記
    .top__consultation__text
      = top_page.contents
      .top__consultation__text__time
        = top_page.created_at
```

すると下記のようになりました。

<img width="1159" alt="7494b2ae155ade0fb54a8b676ea90dd5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653208/3a82c179-aa56-9f53-03cd-02b198a970cc.png">

成功したけどビュー崩れが泣

確かにTop_Page.allで全てデータをもってくるようにコントローラーは記述しましたが
実際の取得はcontentsしか指定してないのに何故全て表示されてしまうのか？

ただcontentsはしっかりとクラス内に表示されていて
何も定義されていないところに　カラム名とデータが表示されています。
何となくhaml側の記述に問題があると思ってます。

ここが直せなかったのでまた明日です。
docker コマンド集

## Use Docker command line client

docker コンテナ実行

```
docker run [image]
image = docker hubなどにあるもの
e.g.) hello-world
```

docker コンテナ実行（インタラクティブモード)

```
docker run -t -i [image] [cmd]
e.g.) docker run -t -i ubuntu /bin/bash
```

docker コンテナ実行(background + Port開放 + name割当)

```
docker run -d -P --name hello-world-app training/webapp python app.py
---
-dはdeamon(background)
-Pはネットワークポートの開放（自動割当）
--nameは名前の割当
---
docker  ps  で確認されて割り当てられたポートで内部からアクセスできる
e.g.)curl http://localhost:<port>/
```

docker コンテナ実行(background + Port開放 + name割当)

```
docker run -d -p 80:5000 --name webapp training/webapp python app.py
---
-pオプションはポート番号を手動で割り振れる
---
docker  ps  で確認されて割り当てられたポートで内部からアクセスできる
e.g.)curl http://localhost:80/
実はこれでもう80番ポートを開放しているので外部からアクセスできる(httpは80番なので、80を省略)
e.g.)http://[このサーバーのグローバルIP]/　←これでブラウザからアクセス可能
```

docker　コンテナ停止

```
 docker stop -t 0 [name]
 nameはimage_nameではなく、docker_psでみれるname
 -t　は停止までの時間。指定しなければ10, 0だと即時終了
```

docker コンテナ実行中確認

```
docker ps
```

docker コンテナ一覧確認(未実行含む)

```
docker ps　-a
```

docker image 削除

```
docker rm [image_layer_name] 
image_layer_name = docker ps -a 出てくるもの
```


docker image 取得

```
docker image pull [image_name]
e.g.) docker image pull ubuntu
```

docker image 取得(特定のver)

```
docker image pull [image_name]:[version]
e.g.) docker image pull ubuntu:14.04
```

docker image一覧

```
docker image ls
```

docker image 調査

```
docker inspect [name]
```

docker image 調査(フィルター)

```
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [name]
```

docker exec（既に起動しているコンテナにコマンド実行)

```
docker exec [name] ps aux
これだと ps auxを実行させる
```

docker exec（既に起動しているコンテナにコマンド実行をインタラクティブモードで)

```
docker exec -it [name] bash
root@249476631f7d:/opt/webapp# ps aux
```

docker ファイルコピー

```
docker cp [origin] [copy]
e.g.) docker cp webapp:/opt/webapp/app.py .
この場合、webappのコンテナの中にあるapp.pyをlocalにコピー
---
e.g.)docker cp app.py webapp:/opt/webapp/
この場合、localにあるapp.pyをwebappのコンテナの指定の場所にコピー
```



## その他
Persisted Volume

```
accessModes
PVのアクセスモードを指定する。アクセスモードは現在以下の3種類。

ReadWriteOnce : 単一Nodeで読み書きが可能
ReadOnlyMany : 複数Nodeで読み込みが可能
ReadWriteMany : 複数Nodeから読み書きが可能
```
PHP composerでext-httpエラーの解決方法

有益な記事がなく苦労したのでメモ

# 環境
PHP7.4(CakePHP3.5)
ローカル(mac mojaba 10.14.6)

# PhpStormで拡張モジュールはcomposer.jsonに書かないと警告が出るらしい
簡単にまとめるとタイトルの通り

ext-httpも例外ではないらしい
> php拡張由来の定数や関数などに依存しているときにcomposer.jsonにその依存が明示されていることを検査するらしい

でもそれを強制するってそんな大切か？って思うんですがw

詳しくは下記記事
https://blog.pinkumohikan.com/entry/warning-ext-json-is-missing-in-composerjson-on-jetbrains-intellij


# ネット上をサーフィンしまくって解決
```bash

  Problem 1
    - The requested PHP extension ext-http * is missing from your system.
      Install or enable PHP's http extension.
```
composerでこのエラーが出た場合はpecl_httpをインストールする必要があった。
PHP組み込み拡張モジュールとは別に、Pecl拡張モジュールというネット上から取得してくる拡張モジュールが存在する
https://www.php.net/manual/ja/install.pecl.downloads.php

Apacheでphpを動かしているとphp.iniでextensionの設定のみでできるような記憶であったが（？）
ローカルの場合はhttpモジュールがないのでインストールする必要がある。

# 実施手順
```bash

$ brew install autoconf
$ brew install m4
$ which m4
/usr/bin/m4 
```
m4の実行パスがMAMPとかのパスになっている場合.bash_profile(.zshprofile)でexportしているPATHで/usr/binをMAMPパスよりも前に持ってくる
php -vでphpのパスが変わってしまった場合も同様に、/usr/binよりも前にphpパスを持って来ればOK

```bash

$ sudo pecl install pecl_http
$ php -v
```
php.iniにextension=http.soが記載されていればOK
php -v などで下記エラーが出る場合はphp.iniでextensionの重複を消す
> PHP Warning:  Module 'raphf' already loaded in Unknown on line 0
> PHP Warning:  Module 'propro' already loaded in Unknown on line 0
> PHP Warning:  Module 'raphf' already loaded in Unknown on line 0

ちなみにphp.iniの場所特定

```bash

$  php -i | grep php.ini 
Configuration File (php.ini) Path => /usr/local/etc/php/7.4
Loaded Configuration File => /usr/local/etc/php/7.4/php.ini
```

参考記事
https://www.php.net/manual/ja/install.pecl.downloads.php
https://www.366service.com/jp/qa/640015a450ba68b8414671db0ac15a48
https://stackoverflow.com/questions/59618142/fixing-m4-on-mac-os-10-14-5
Github DesktopはSSH接続するための公開鍵の登録が不要

### Github DesktopであればSSHキーの作成や登録手順が不要。

Github Desktopプログラム上でGithubアカウントで認証を行うだけで
Githubにあるリモートリポジトリを扱うことができる。

既存のローカルリポジトリも[Add Local Repository]で指定することで
Githubで管理できるようになる。

Github Desktopを利用している場合 .ssh ディレクトリの中には、
Github用のSSHキー『id_rsa』『id_rsa.pub』は存在しない。
htmlテーブルのDOM操作の罠

# 罠とは
htmlのテーブルのdom操作について、罠があります。端的に言いますと、テーブルの木構造のことですが、どうも隠れている要素があり、それを無視してしまうと、うまくDOM操作できません。
通常ですと、以下のhtmlコードについて

```html
<!doctype html>
<html>

<head>
    <title>test</title>
</head>

<body>
    <table id="aaaaa">
        <tr>
            <td>test1</td>
            <td>test2</td>
        </tr>
        <tr>
            <td>test3</td>
            <td>test4</td>
        </tr>
    </table>

    <script type="text/javascript">
        var tbody = document.getElementById('aaaaa').childNodes[1];//tbody
        console.log(tbody);

        var children = tbody.childNodes;
        var tr = children[0];
        tbody.removeChild(tr);
    </script>
</body>

</html>
```
# 木構造の認識違い
木構造はこのようなものかと思われますが、実は違います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658637/d558a632-4053-e753-80ef-401d1fc1679d.png)
実際にはこうです：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658637/8c03ad54-abd2-5004-53e7-3dba30cf21f3.png)
tbodyというのが出てきます。詳しくはhtmlの知識となりますので、ここでは割愛します。
要は上記のhtmlコードで書いてあるように、removeChildをうまいことに正しいDOMオブジェクトをセレクトしないと、エラーが出てきてしまい、子ノードを削除できないのです。

---
ちなみに、上記コードでは、以下の結果が出てきています。

```javascript

console.log(document.getElementById("aaaaa").childNodes);
//結果：NodeList(2) [text, tbody]
```
これはchildNodes[1]を採用した理由です。childNodes[0]を使うと、textノードを選んでしまって、removeChildは到底できなくなりますので、気をつけてください。　
このテキストノードはおそらく改行なのではないでしょうかね。
正確なremoveChild方法はすでに上記コードに記載しました。ご参考まで。
wyジーういぐ？出してほしと思うcss系

常に楽な崩落な方にいく開発者であるが
絵心ないのにフロントとかもやらされると
めっちゃツールにたよりたくなるのだ

それもいろいろな画面サイズに合わせてとかいってきたら
response?つかうの？的なちょっと敷居高くないのか？な嫌な気分になる

一般にみせたら、見せ方（デザイン）で優劣がつくところもあるので
ほんと、いやで、とっかかりにくい。。
基幹系をAgile開発で実施した時の肝３（実践からの気づき）平準化～

**平準化**
平準化とは作業に属人性あるようでは実現できません。この属人性を無くすには開発チーム内でメンバー同士の暗黙知の見える化、情報共有、価値観、ゴールイメージの共有が必要です。その為に先ずはチーム・ビルディングが出来ていることが重要です。

Scrum & XPのかなでチーム・ビルディングを目的としたプラクティスは無い様に見えますが、Scrum Masterの責務として真っ先に行うべき事が、開発チーム、Scrumチームのチーム・ビルディングです。ScrumやXPで用意されているプラクティスを実践していても、このチーム・ビルディングが出来ていなければ、チームは破綻、プロジェクトは失敗します。

チーム・ビルディングには様々な方法が紹介されていますので、皆さまの経験と実績で選択して実施していくのも良いとおもいます。この時に重要なポイントは自律した自主運営が出来るチーム・ビルディングであり、単なるアイスブレイク等で紹介されている安易な方法を適用する事は絶対に避けてください。プロジェクト本来の目標や目的に沿った方向でチーム・ビルディングできるのが良くて、遊び的な仲良しグループをつくることでは無いのです。私はTMS(TOYOTA way Management System)で紹介・実践している、幸せマップとVMB(Visual Management Board)を利用してチーム・ビルディングを行う事を推奨しています。

Scrumのプラクティスでは、開発チームが見積りする手法、タスクの粒度、ペア・プログラミングの運用ルール等で、平準化の効果が期待できます。

見積り手法は各種ありますが、どの手法を採用しても、各メンバーの意見を発する場があるので、その議論をとおして、開発への拘りや実装すべき機能の品質やセキュリティー面等をメンバー相互に理解できます。

この議論の様子を拝見しているだけで、平準化が出来るチームか否かは容易に判断できます。

タスクの粒度に拘ることはとても重要であり、知識や行動の躾といた範囲まで効果を期待できます。
**タイムボックス**という枠をはめることで、頭脳労働、ホワイトカラーといった作業状況、途中成果が見えない作業において、その作業を可視化することが出来ます。
先ずは、一時間という単位が目指す**タイムボックス**、即ち粒度としてください。この時間に見積りで収まるように実施する作業を細分化します。もし、細分化できないとすると、まだまだ理解や知識が足らない事が判ります。出来ない場合には、それより大きな粒度、例えば三時間程度を目安にすすめてください。この作業の細分化（タスク分解）はチーム全員の参画で実施し、どうしたら粒度を細かくできるのか研究、工夫して行ってください。この時間を惜しんで作業を進めてしまうと、知識の平準化の機会を逃すことになってしまいます。

ある、プロジェクトの立ち上げ支援をしていた時に、イテレーションへ入る前（プロダクトバックログが一通り出そろった時点）に**開発チーム全員で全てのバックログをブレインストーミング的なワークショップで見積りを行ってもらいました。**このチームのメンバーは派遣ビジネスが主体のエンジニア、しかも、半数がこのプロジェクトで初顔合わせです。当然、アジャイル開発は初挑戦で、経験や知識もそれぞれバラバラでした。
**チーム・ビルディングとゴールイメージの共有化**を促進する為に、このチームに一週間の期間（実際には５営業日）を設けて、この作業を行ったのです。

この結果、プロジェクトの最初にリスクとそのリスクが軽減する為の行動と時期も明確になりました。しかもチームメンバー全員参画で行った結果ですので、漠然とした不安は消えていました。
その後、一か月半ほど毎週現場を訪問して様子をみていましたが、**全員が情報共有をするやり方**を会得して進めているので、タスクの粒度は１時間程度に収まり、日ごとの作業実績が自信につながり、ユーザーからのレビューにも難なく対処できるように成長しました。

この組織には伏線があったのです。経営者・管理者層からはこのプロジェクトを進める前には、如何にこの組織を解体するか、という議論をしていたそうで、このプロジェクトが始まったと同時に**社内の重点監視対象**という位置づけになり、毎月、品質管理部がこのプロジェクト現場を査察することが行われていました。
しかしながら、現場の多方面の見える化を実践していたのを品質管理部が見て、**「このようなプロジェクト管理は初めてで、透明性が確保されている、何故、社内の他のプロジェクトでは実践できないのか？」**と驚いていたそうです。この品質管理部の査察は数回程度あったそうですが、毎回、褒めの言葉しか出ず、最後には、もう査察の必要は無いので、頑張ってください。との言葉を最後に重点監視対象から外れました。
さらに、その評判が社内を駆け回り、管理者の現場見学が多くなり、プロジェクト終盤では、経営者・管理者層から、この組織を如何に永続させ社内横展開するか、が議論対象になって、**社内評価が１８０°変わって素晴らしいプロジェクトとして進み、プロジェクトが成功裏に終了すると社長賞の栄誉に輝いたそうです。**

チーム全員での知識共有、ゴールイメージの共有は平準化を促進します。従来手法ではこのようなメンバーの振舞、行動は出来ないので知識、作業の平準化は困難です。

**ペア・プログラミングも平準化する為に有効なプラクティスです。**単にペアを決めて実践してもその効果は薄いです。
タイムボックスでドライバーとナビゲーターを交代するだけでなく、ペアの組み合わせも、出来るだけ頻繁に交換します。そして、タスクの取り方も工夫してください。

**プロダクトバックログ・アイテムに対してタスク分解されたもタスクが、一つ、一つ、流れを作っています。**同じペアで、いま終了したタスクの次に作業として取るタスクは、この「流れ」で継続するタスクでは無い、他のタスクを選択します。
一見、非効率とも思える行為ですが、これを意識すると、プロダクトバックログ・アイテム一つを作り上げるのに、開発チーム全員が関われるようになり、特定のペアだけにノウハウが集中する事を抑制します。

出来ない理由を挙げるより、このルールは是非とも実践していただきたいです。ただ、このルールができる背景には、タスク粒度がほとんど一時間程度になっていることが前提条件です。

ある、チームでは作業時間６０分休憩１０分のリズムをもって日々過ごしていました。

企業で「働き方研修」を実施していた時に、そこの研修生が自分の能率と気分転換というテーマで自身の作業能率を計っていました。それによると、同じ内容の仕事をし続けると６０分以上は能率が下がってきて、その後、様々な休憩（気分転換）をとっても、同じ内容の仕事をし続けていると能率が下がるというものでした。
これは一つの研究結果ですが、この結果を、このチームに当てはめると、彼らは自らの能率が一番高くなるリズムで仕事をしていたことになります。ソフトウェア開発で平準化が進み、タスク粒度が均一化されてくると、アウトプットが積みあがる様子がリズミカルになり、まるで開発チームが高度な生産機械の様になってきます。この生産機械といっても主体は人間です。そこには人の知恵による工夫が出来る血が通った生産機械なのです。
Rails こんなこともできるよ中間テーブル

どうもチャンクノです！！
今回は中間テーブルについて書いていきます。

多分基本的に中間テーブルを作成する場合、多対多の両テーブルのidを中間テーブルに持たせると思います。
https://qiita.com/gomasio1010/items/2cff1e11d2cc82fde464
この記事のような感じ。

でも中間テーブルって必ずしもidじゃなくていいみたいです。
自分が今担当している部分の中間テーブルは

```
 create_table :search_condition_areas do |t|
  t.string :area_code
  t.references :search_condition, foreign_key: true
  t.timestamps
 end
```
こんな感じになってます。

このままだと :area_codeがただのstring型のカラムになってしまうので、

```
has_many :search_condition_areas, foreign_key: :area_code, primary_key: :code
has_many :search_conditions, through: :search_condition_areas
```
モデル側でforeign_keyとprimary_keyを指定してあげてます。
これで基本的な中間テーブルを作成した時と同じ状態になりました。

さて、気になるのはこれをcreateする時ですね。

```
def search_condition_params
 params.require(:search_condition).permit(
  :hoge,  :huga, :foo, area_?: []　<= ここ
 )
end
```
ここの?に何が入るかわかりますか？
僕は脳死で area_codes: [] にしました！！！
え、違うの？そんな声が聞こえてきそうですねえ。うんうん。違うんです。
ここは普通に area_ids: [] です。
例えば @search_condition.area_ids とコンソールで叩けばidではなく

```
[83] pry(main)> @search_condition.area_ids
=> ["11101000000", "13101000000", "13103000000"]
```
こんな感じで @search_condition に紐づく中間テーブルが持っているarea_codeが返ってきます。

```
[99] pry(main)> area.search_condition_ids
   (1.8ms)  SELECT `search_conditions`.`id` FROM `search_conditions` 
INNER JOIN `search_condition_areas` ON `search_conditions`.`id` = `search_condition_areas`.`search_condition_id`
WHERE `search_condition_areas`.`area_code` = '13000000000'
=> [3]
```
逆も然り。これは普通にsearch_conditionのidが返ってきます。
〜ids <= この部分は collection_singular_ids このメソッドを使っています。
一対多の時使えるメソッドみたいですね。
https://railsdoc.com/association
ここに色々書かれています🙆‍♂️
https://www.rubydoc.info/gems/activerecord/ActiveRecord%2FAssociations%2FClassMethods:has_many
英語できる人はこっちの方がいいっぽいです。

これがあったので、もしかしてarea_codesじゃなくてarea_idsなんじゃね？って気付くことができました！!

で、ここで気を付けなければいけないのが

``` 
@search_condition.area_ids = @new_search_condition.area_ids
@search_condition.save
```
コントローラーの処理でこのような記述を使用する場合ですね。
どうなると思いますか？

```
@search_condition.area_ids = @new_search_condition.area_ids
```
これ　@search_condition.save の処理が走る前に上記の部分が上書き保存されてしまいます。
どうやらautosaveが自動で走ってしまうみたいです。
accepts_nested_attributes_for を使っている場合必ずautosaveがtrueになってしまうのでどうしようもないっぽいです。

```
User.rb

has_one :search_condition
accepts_nested_attributes_for :search_condition <= 多分ここが原因
```
おそらくですが親テーブルに accepts_nested_attributes_for が使用されていたらautosave: falseは使えないんでしょうね。
なので、ここでは親テーブルが保存されてから子テーブルを上書き保存する処理を書くのがいいのかなーと思います。

```
if @search_condition.save
  @search_condition.area_ids = new_search_condition.area_ids
else
  render "new"
end
```
こんな感じ。
多分もっといいやり方があるんだろうなあ。

ごちゃごちゃと色々書いてきましたが、まとめると

```
・中間テーブルに持たせるものは両テーブルのidじゃなくても良い。
・でもその場合はidを持たせないテーブルにforeign_keyとprimary_keyの記述を忘れずに。
・idを持たせない場合でもコントローラーのパラメーターは必ず~idsにする。
・accepts_nested_attributes_forを使用している場合はautosaveに気を付ける。
```
こんなところですかね😯
あんまり中間テーブルの実装には触れてこなかったのでお勉強になりました🙏
覚えることは山のようにあるなあ、、、。
では今回はこんな感じで！！
間違ってるところとかあったらコメントください！
それでは皆様良きプログラミングライフを🙏
HTMLの「style」プロパティにJavaScriptでstyleを設定する

# はじめに
この1つ前に投稿した[複数の背景画像をCSSで設置する](https://qiita.com/h-naito/items/8409d7bcea50da47fc97)と少し関係します。

背景画像を分割したいという相談を受けました。かつ、JavaScriptで実装する必要があるとの事でした。
そんなわけでサンプルとして実装してみました。

備忘を兼ねて投稿します。

# 実装
## 利用するもの
`HTMLElement.style`プロパティを利用します。
これはHTMLで、インラインでstyle属性を指定したのと同じ状態になります。

## ポイントと注意事項
基本的には、`element.style.backgroundImage='***'`の用に、style部分をテキストで指定すればOKです。(elementはstyleを設定したいHTMLElement)

注意事項としては、

 - `style`につづくstyle属性をキャメルケースで指定する
 - `style`に直接文字列を代入せず`element.style.backgroundImage`とstyle名を指定する必要がある

というところです。

## 表示されない時のチェック事項
- style属性をキャメルケースでしていしているか
- style属性の値が正しい書き方（文字列）になっているか



## 実装例
<p class="codepen" data-height="476" data-theme-id="light" data-default-tab="js,result" data-user="H_Naito" data-slug-hash="pogWNGL" style="height: 476px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Multiple_background_settings">
  <span>See the Pen <a href="https://codepen.io/H_Naito/pen/pogWNGL">
  Multiple_background_settings</a> by H.N (<a href="https://codepen.io/H_Naito">@H_Naito</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 参考
[HTMLElement.style](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/style)
Vueでビルドしても画面が真っ白（Uncaught RangeError: Duplicate use of selection JSON ID cell

## 事象

`npm run serve`を実行して最後までビルドはされるが画面が真っ白になる。

```shell
Uncaught RangeError: Duplicate use of selection JSON ID cell
```

## 解決方法
エラー文をそのままググって検索して出てきたissueを参考。
node_moduleを削除して再度npm installすることで解決。

https://github.com/scrumpy/tiptap/issues/316

原因は正直よくわかってない。

追記
本番機でのみ同エラーが出てしまうので、以下対応をすることで解決した。

```
npm remove tiptap tiptap-commands tiptap-extensions
rm -rf node_modules
npm i -S tiptap tiptap-commands tiptap-extensions
```
GuzzleでのAPI通信先でのデータ取得方法を知りたい

#結論
**POSTで送るなら$_POSTでいいじゃない!!!!!**


```
$postData = $_POST['hoge'];
```

これで取れます。

念の為

```
        if(isset($_POST['hoge'])){
            $hoge = $_POST['hoge'];
        } else {
            // Error return
            return 何らかのエラーコードなりをレスポンスすればよいでしょう
        }
```

とすればきっと良いはず。

半日の時間は何だったのかという己の愚かさと
$_POSTとか数年ぶりに書いたので今もこの書き方で良いのだろうか
という疑問も新たに生まれた


伸びしろと思いたい。



###ここからは元文

#$requestでデータが取れない

```
$request->all();
```

できっとPOSTからのデータは取得出来るはず、、、
そんな簡単に考えていたら、半日ハマってしまっている。

##環境
PHP7系(APIも）
docker

##そもそもAPIは呼び出し側しか触ったことがなかった！
今までサービス内、サービス外、様々なAPIを触って、なんとなくAPIは
リクエストに対してレスポンスをくれるものという考えしかなかったが、
今回受け渡し側を触ることになって、
ど、ど、どどおおやってリクエストデータを取得しているの？

ググっても受け渡し側（リクエスト側）はたくさん出てくるのに対して
レスポンス送る側のAPIってどうなってるの？
・・・わからない

##色々試した

######デバッグ
```
$d = $request->all();
dd($d);
```

######結果
```
array(3) {
  ["hoge"]=>
  string(1) "A"
  ["hogeB"]=>
  string(2) "BB"
  ["hoge_code"]=>
  array(1) {
    [0]=>
    string(12) "hoge-code"
  }
}
<script> Sfdump = window.Sfdump || (function (doc) { var refStyle = doc.createElement('style'), rxEsc = /([.*+?^${}()|\[\]\/\\])/g, idRx = /\bsf-dump-\d+-ref[01 ▶
</pre><script>Sfdump("sf-dump-132360725")</script>
```

なんか配列にちゃんと入ってるけど！けど取れない・・・


##これからまた検索の渦にハマるのだろうか
半日アレヤコレヤ考えても全く進めない。。。
このような場合、レスポンス返す側はどうやってデータを取得するのでしょうか
Gitの「--color-moved」オプションがかなり便利だったの紹介してみる

Gitの `--color-moved` オプションで、 **移動だけの差分をいい感じに表示する** ことができ 、かなり便利だったので紹介してみようと思います。
https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---color-movedltmodegt

ちなみに2年くらい前からあるようですが、最近知りました :innocent: 
https://www.infoq.com/jp/news/2018/04/git-2.17-released

※ 本記事のサンプルでは、Gitのバージョンは2.24.3、シェルはfishを使っています。
# サンプル

例えば以下のようなクラスがあった場合。

```kotlin
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }
}
```

`onOptionsItemSelected` を一番上に移動したい、となった場合、オプション無しの `diff` だと…
<img width="545" alt="スクリーンショット 2020-07-02 14.28.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/0be6d2ed-c085-4132-d443-e529b7f217a7.png">
元の位置にあった `onOptionsItemSelected` の削除と、新しい位置への `onOptionsItemSelected` の追加が表示されることになります。

---

しかしながら、 `diff --color-moved=dimmed_zebra` とした場合は…
<img width="545" alt="スクリーンショット 2020-07-02 14.28.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/62d0d306-b1d2-fdc4-b9ce-9dfa118a1d9c.png">
移動だけの差分なため、グレーアウトされた表示になります…！（かなりわかりやすい:grinning:）

---

さらに便利なところがありまして、ただの移動のつもりが

```
R.id.action_settings -> true
```

を

```
R.id.action_settings -> false
```

に間違って変えてしまっていた場合は…
<img width="544" alt="スクリーンショット 2020-07-02 14.28.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/dcd25c9e-41f1-d3c2-2c53-192e1c973605.png">
移動したところだけはグレーアウト、変更があったところは通常の差分表示、とかなりいい感じに表示してくれます:clap:

オプション無しと `--color-moved=dimmed_zebra` を付けた時を比べてみると一目瞭然。かなり便利では…！

|なし|あり|
|:-:|:-:|
|<img width="550" alt="スクリーンショット 2020-07-02 14.44.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/3d6ed7ab-a64f-868b-c95f-7d5a3a6eaca8.png">|<img width="544" alt="スクリーンショット 2020-07-02 14.28.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/af944415-1baf-5ef5-f27e-68cc9392e248.png">|

# モードは6つ
サンプルでは `dimmed_zebra` を使っていますが、 `--color-moved` のモードとしては
> `no` , `default` , `blocks` , `zebra` , `dimmed-zebra` , `plain` 

の6つを指定可能です。（ `no` はハイライトなし、 `default` は `zebra` と同じなため、実質4つ。）

https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---color-movedltmodegt

個人的には `dimmed-zebra` が一番いいのかなと思いますが、 派生元の `blocks` には
>Blocks of moved text of at least 20 alphanumeric characters are detected greedily.

という条件があり、うまく移動の差分として表示されないケースもあるため、適宜モードを使い分ける必要がありそうです。

# 終わりに
Gitの `--color-moved` オプションで、移動の差分をいい感じに表示できることをご紹介しました。
このオプション自体は2年くらい前からあるようなので、まだまだ知らない便利なオプションがGitにはあるんだなと思いました。
【Creative Cloud】 Launchpadに登録されるCC系アプリを一括非表示にする

# はじめに

Adobe Creative Cloudをインストールすると、多くの不要なエイリアスがLaunchpadに登録されてしまいます。
アプリケーション自体は残しつつも非表示にする方法をメモ \_φ(･\_･)


# 実行環境

Mac OS X 10.15.5を使用 (執筆時点)

```:Terminal
% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.5
BuildVersion:	19F101
```

また、Macに最初からインストールされているsqlite3を使用します。

```:Terminal
% sqlite3 -version
3.28.0 2019-04-15 14:49:49 378230ae7f4b721c8b8d83c8ceb891449685cd23b1702a57841f1be40b5daapl
```


# 手順

ターミナルで直接SQL文を発行して削除していきます。
まずは、Launchpadの情報が格納されているデータベースファイルを指定して開きましょう。

```:Terminal
% sqlite3 ${TMPDIR}../0/com.apple.dock.launchpad/db/db
```

入力すると`sqlite>`と表示され SQL文入力待ちとなりますので、以下のコマンドを入力していきます。

```:Terminal（SQLite）
sqlite> DELETE FROM apps WHERE title='ACCFinderBundleLoader';
sqlite> DELETE FROM apps WHERE title='AdobeIPCBroker';
sqlite> DELETE FROM apps WHERE title='Core Sync';
sqlite> DELETE FROM apps WHERE title='Creative Cloud Desktop App';
sqlite> DELETE FROM apps WHERE title='Creative Cloud Helper';
sqlite> DELETE FROM apps WHERE title='Creative Cloud Installer';
sqlite> DELETE FROM apps WHERE title='CC Troubleshooter';
sqlite> DELETE FROM apps WHERE title='CCXProcess';
```

SQLiteを終了します。

```:Terminal（SQLite）
sqlite> .exit
```

最後にDockを再起動します。
お疲れ様でした！

```:Terminal
% killall Dock
```

# エイリアスを元に戻す方法

```:Terminal
% defaults write com.apple.dock ResetLaunchPad -bool true
% killall Dock
```


# その他
`Creative Cloud` は非表示にせず残しています．
必要な方はこちら．

```
sqlite> DELETE FROM apps WHERE title='Creative Cloud';
```
なんとActiveRecordはDB跨ぎでの関連付けが可能っぽい

業務中に知って驚いたこと。休日に気が向いたら深堀するかも。

# 前提

- `User has_many Posts through UserPosts`という関連付けをしたい。
- `User`テーブルは、`Posts`テーブルと`UserPosts`テーブルとは異なるDBのテーブル。

# 予想
```User.rb
has_many :posts
has_many :read_posts, source: :posts, through: :user_posts
```

なんてasociationをモデル層に書いても流石に`User.read_posts`は取ってこられないだろうと諦めの境地にいた。


# しかしだ。。。

- ActiveRecordがpreloadを使っているのなら、関連付け可能で取ってこれる
- ActiveRecordがeagerloadを使っているのなら、関連付け不可能(生成されるクエリの中テーブルのでJOINを使っているから)


# 詳しいことは時間があったら調べてる予定

[参考](https://texta.pixta.jp/entry/2016/02/10/180244)

memo. includesは、eager_loadとpreloadをよしなに使い分ける
Swift学習要点(随時更新予定)

# 文法編

- 空白(スペース)は、=、+、-などの演算子の前後にはあってもなくてもOKである。但し、前後どちらか一方にしかないとエラーになる

- letもvarも複数の宣言を「;」で区切って1行にまとめて書くことができる
ex) let max_length = 10; var current_length = 5

- 変数var で再代入する際には、「var 」やデータ型はいらない

- 連結ではなく、文字列の中に変数（定数）の値を埋め込むこともできる。\(変数)のように書くことで文字列内に変数を埋め込むことができます。これを変数の「展開」と呼ぶ。


- Bool型の定数や変数の名前は、慣習上”is”から始めることが多い

#Xcode編
- IBはInterface Builderの略

- させたい処理を書くのがIBActionである

- 要素とプログラムを結びつける方法をIBOutletという。IBActionで記した動作とストーリーボード上に配置したパーツとを紐付けるものである。

- Outlet:	UI部品をプロパティとして接続する
Action:	UI部品をメソッドとして接続する

- viewDidLoadの中に書いたコードは、一番最初に実行される。

- label.textに文字列を代入すると実際のラベルの内容が変化する。
開発管理に必要なツールを選ぶ

要件定義もおわって、そこそこ開発しないといけないムードが高まってきました、というときに、設計からテストデプロイ、改修まで、きれいに管理できるツールがないかなと調べたのでそのまとめです（オンプレ縛り、無料縛り、有料縛り）。

# はじめに
とあるプロダクト開発工程を整理していた（[3 tier の サーバーレスなアプリを作るときの作業を抽出する](https://gist.github.com/amemolee/3b980a3cee31fdc7753653373ecb132b)）のですが、開発の周辺のところを抽出したところ、以下の３つを実現するためのツールがほしくなりました。

1. オンラインコードレビューや継続的デプロイができるコードエディタとCI/CD環境を連携する
1. 課題をIssue単位で管理できて、Issue単位にコード修正できるようにする。ガントチャートがあると嬉しい
1. 継続的デプロイができるCI/CD環境を絡める

## オンプレ無料縛り
昔ながらの方法だとこんな感じでしょうか。懐かしい人もいらっしゃるでしょうか。私は懐かしいです。

+ Issue管理：Redmine(ガントチャートのプラグインあり)
+ Code管理：Subversion(Redmineと連携できるのはこれ)
+ Document機能：PukiWiki(プラグインを作ればいろいろ連携できる)
+ Deploy管理/CI：Capistrano（PukiWikiのプラグインか何かでキックする) / Jenkins

## オンライン無料縛り
オンラインで無料のものを探すとこんな感じでしょうか（Github Actionsは使ったことがないのですが）。あまりないので絞り込み易そうです。

+ Issue管理：Trello（ガントチャートがアドオン) / Github Issue
+ Code管理：Bitbucket(無料枠) / Github(今は無料でもPrivateリポジトリOKとのこと）
+ Document機能：OneNote(個人用のMSアカウントを駆使） ※苦肉の選択...。
+ Deploy管理/CI：Github Actionｓ(重量制限あり）

## オンライン有料縛り
オンラインで有料だったらいろいろありそうです（縛るという言葉は変かもしれません）。プラグインとかお金だせばどんどん追加できるのが逆に怖いかもしれません。

+ Issue管理：JIRA(ガントチャートは有料プラグイン) / Backlog (ガントチャートあり） / Github Issue / AWS Code Commit
+ Code管理：Bitbucket / Github / AWS Code Commit(AWS契約する前提)
+ Document機能：Confluence (他システムの資料も統合できる) / Backlog Wiki / Github Wiki(有料版のみPrivateリポジトリで利用できる） / Google docs(G Suite契約する前提)
+ Deploy管理/CI：Github Actionｓ / Bamboo / CircleCI / AWS Code Build(AWS契約する前提)

# 参考
プロジェクト管理ツール調査
https://qiita.com/runmaru/items/1b9db88a853d4a50b723
タスク管理ツールについて検討
https://qiita.com/bonk/items/6b8c282560d20511f16e
バグトラッキングシステム比較
https://qiita.com/toshi0383/items/15671288c66a91a73354
GitHub と Bitbucket 比較 2020/06 時点
https://qiita.com/papettoTV/items/850488b655f4f49555af
情報共有は、なぜGoogle Docsじゃなく、 Confluenceなのか。
https://www.slideshare.net/kajinari/google-docs-confluence-64565985
【保存版】社内wikiツール16選！特徴、機能を徹底比較
https://knowledge-hack.jp/archives/3001#komidashi12
AWS CodeCommitのプルリクエストを使用してコードレビューをリクエストし、コードについて議論する
https://aws.amazon.com/jp/blogs/news/using-aws-codecommit-pull-requests-to-request-code-reviews-and-discuss-code/
GitHub Actions の無料枠を使いきった場合
https://qiita.com/technote-space/items/7b2694786f577c823fc1
【比較まとめ】おすすめのCIツール10選。チームの開発効率をアップするのに最も良いのはどれ？
https://goworkship.com/magazine/ci-tool-comparison/
Github Actionsにて自動的にデプロイする環境作成(Webサイト編)
https://qiita.com/taptappun/items/4a8f7ecaa3f91cb21be9

# おわりに
それでは、さくっとツールを選択して（していただいて）、ごりごり開発、てきぱき管理、さくさくリリース、に専念しましょう！

以上
anacondaをインストールした後PATHを通すのに躓いた話

pythonの勉強のためanaconda3をインストールして、pythonを実行しようとしたら躓いた話。

anaconda3はインストール時にPATHを通すかどうか聞かれるがチェックを入れ忘れたままインストールしてしまったので、手動でPATHを設定しなければならなくなりました。

#PATHの通し方（Windows10） 
Windows10ならPATHの設定は以下の手順でできます
・検索ボックスで「環境変数を編集」で検索
・「Path」を選択→「編集」
・「新規」を押してインストールしたディレクトリを追加
　自分は「E:\Apps\anaconda3\」にインストールしたため、ここを追加しました
・ついでにpip.exeのある「E:\Apps\anaconda3\Scripts」も追加

#PATHを通した結果...
以上でPATHが通ったため、コマンドラインで「python -V」でPATHが通ったか確認。
うまくいっていればインストールしたpythonのバージョンが表示されるはずが、なぜか「Microsoft Store」のpythonのインストールページに飛ばされる...

なぜだ...

「環境変数を編集」を見てもちゃんと正しくパスが追加されているし、再起動も試したが効果なし...

#解決策
Microsoft StoreからインストールしろというMicrosoftのいやらしい販売戦略かとも思ったりしつつ四苦八苦して、ようやく原因がわかりました。

「環境変数を編集」のPathの編集画面で、pythonのパスより上に「%USERPROFILE%\AppData\Local\Microsoft\WindowsApps」があったのでした。
環境変数は上から順に適用されるようで、anaconda3フォルダのpython.exeよりもMicrosoft Storeのpythonの検索が先に実行されてしまっていたようでした。

ということで、追加した2つのパスを上へ移動して、コマンドラインで「python -V」を実行したところ、無事にpythonのバージョンが表示されました。

#基本的だけど見落としがち
anacondaのPATHの設定について書いてあるぺージは結構あったのですが、パスの順番について触れているところはなかったので、同じ状況に陥った人がいたら役に立ってほしいと思いました。
IMのドキュメント内にある様々な関数をまとめてみる その3

#IM開発備忘録

##IMのドキュメント内にある様々な関数をまとめてみる その3

###関数ボックスのユーザ情報関数

Formaには関数ボックスなるものが存在し、その中にFormaがサポートする様々な関数が存在する。
それらを駆使することで、比較的簡単にクライアント処理などを作り出すことができる。
バグもほぼない（私は確認したことがない）ので安全かつ高速に使える

その内のユーザ情報関数を以下にまとめる


####user(ログインユーザコードの取得)

ユーザ：青柳辰巳(ユーザコード：aoyagi、ユーザ名：青柳辰巳)で実行した場合

```js
user()
```

画面アイテムには**「aoyagi」**と表示されます。



####username(ログインユーザ名の取得)
ユーザ：青柳辰巳(ユーザコード：aoyagi、ユーザ名：青柳辰巳)で実行した場合

```js
username()
```
画面アイテムには**「青柳辰巳」**と表示されます。


####loginGroup(ログイングループIDの取得)
ユーザ：青柳辰巳(ログイングループ：default)で実行した場合

```js
loginGroup() 
```
画面アイテムには**「default」**と表示されます。



####locale(ログインユーザのロケールIDの取得)

ユーザ：青柳辰巳(ロケール：ja(日本語))で実行した場合

```js
locale()
```

画面アイテムには**「ja」**と表示されます。


####encoding(ログインユーザのエンコーディング情報の取得)

ユーザ：青柳辰巳(エンコード：UTF-8)で実行した場合

```js
encoding()
```
画面アイテムには**「UTF-8」**と表示されます。


####mail(ログインユーザのメールアドレスの取得)

ユーザ：青柳辰巳(メールアドレス：aoyagi@intra-mart.jp)で実行した場合

```js
mail()
```
画面アイテムには**「aoyagi@intra-mart.jp」**と表示されます。


####mblmail(ログインユーザの携帯メールアドレスの取得)

ユーザ：青柳辰巳(携帯メールアドレス：aoyagi-mobile@intra-mart.jp)で実行した場合

```js
mblmail()
```
画面アイテムには**「aoyagi-mobile@intra-mart.jp」**と表示されます。



###他の記事

IMのドキュメント内にある様々なAPIをまとめてみる その１
https://qiita.com/ChrisKasahara/items/c3187249112e7114aa12

IMのドキュメント内にある様々なAPIをまとめてみる その２
https://qiita.com/ChrisKasahara/items/ac038ce0b704574ada16

IMのドキュメント内にある様々なAPIをまとめてみる その３
https://qiita.com/ChrisKasahara/items/b2b5724af834b85d6269
FP32の値をNビット量子化した場合のSN比は6N [db]となることの確認

# この記事について

量子化処理において、量子化前の値が持つ値域を効率よくカバーするように量子化ステップを設定すると、量子化誤差に対するSN比が約$6×N(bit)[dB]$になることを確認します。

音響や信号処理などでよく知られているように、あるリニア信号を量子化した際に、量子化ビットが1ビット増えるごとにSNが$6[dB]$改善します。

FP32で学習された機械学習モデルをエッジデバイスに搭載する場合などに用いられる量子化において、効率よく量子化できているかの目安にもなると考えられます。

# 検証

## 理想的なケース

適当な値域を設定してFP32の値を複数生成し、それらをINT8(8bit量子化)した場合のSN比の計算します。この場合、指定した値域内でFP32は均等に生成されます。量子化の最小単位となる量子化ステップもこの値域をもとに算出します。このような理想的な場合のSN比の期待値は$6\times8(bit)=48[dB]$です。

```c:検証プログラム
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 0.0～1.0の乱数を生成
float rand_norm(){
    float r;
    r = rand();
    r /= (float)RAND_MAX;
    return r;
}

int main(void){
    const int EXP_NUM = 1000;     // 乱数のサンプリング回数
    const float MAX   = 1000;     // 値域の最大値
    const float WAYS  = 256;      // 量子化のパターン数(Nビット量子化の場合 → 2^N)
    const float Q     = MAX/WAYS; // 量子化ステップ
    
    double sn  = 0;               // 平均SN比
    
    int i;
    for(i=0;i<EXP_NUM;i++)
    {
        float sample;
        float quanted_sample;
        double err,mse;
        
        // 0～MAXの値域でFP32の値を生成し
        // ステップQで量子化した値とのSNを計算する
        //-------------------------------------------
        sample = rand_norm()*MAX;            // 量子化前の値をサンプリング
        quanted_sample = floor(sample/Q)*Q;  // 量子化後の値
        
        err = sample - quanted_sample;
        mse = sqrt(err*err) + 10e-6;         // MSEを計算
        
        sn  += 20*log10(sample/mse);         // SN比を計算
    }   
    sn  /= EXP_NUM;  // 平均化
    
    printf("SN=%f db\n", sn);
    return 0;
}
```

実験結果は以下のようになり、期待値通りとなります。

```
SN=48.630352 db
```

## 量子化ステップが最適でない場合

上記は、FP32の値がとる値域がわかっている想定で検証しました。量子化前のFP32の値が0～MAXまでの値域を持つと想定して量子化ステップを設定しておきながら、実際はそれよりも量子化前のFP32の値が散らばる値域が狭い場合はSN比が期待値より劣化します。

検証プログラムで用いた0.0～1.0の乱数を生成するプログラムを下記のように変更して、1bit分、値域を狭くしてみます。

```c
float rand_norm(){
    float r;
    r = rand() >> 1;     // 生成される乱数を1bitシフトする(値域を狭くする)
    r /= (float)RAND_MAX;
    return r;
}
```

量子化ステップは0～MAXの値域を想定して設定したままにしています。そのため、検証結果は1bit分である$6[dB]$だけ先の結果より劣化するようになります。

```
SN=42.780143 db
```

このように期待されるSN比よりも劣化している場合は、無駄に広いダイナミックレンジをカバーしようとして量子化ステップを必要以上に大きくとりすぎて解像度が低下してしまっている可能性があることを示しています。

FP32の範囲は大きな値域をカバーしますが、一般に、量子化対象の値がこの値域全域に一様に分布するようなことは稀です。そのため、FP32を量子化する場合は、以下の事を検討する必要があります。

- 量子化対象の数値群がどのような分布をしているかを確認する
- 分布範囲の多数をカバーするように値域を設定する
- 設定した値域から量子化ステップを算出する
模写コーディング FaceBook ログイン画面 その2

#模写コーディング

##模写するサイト
FaceBook ログイン画面
https://www.facebook.com/

##作成時間
その１：3時間
その２：5時間半
計：8時間半

##環境構築
・Google Chrome（ブラウザ）
・Visual Studio Code（コードエディター）

##模写する上でのルール（引用）
1.文字のコピペはOK
2.フォントの種類は何でもOK
3.少しのズレはOK
4.背景画像も入れる
5.角丸やフォントの大きさも近いものにする
6.レスポンシブデザインにも対応する

https://codelearn.jp/articles/mosya#1HTMLCSS

##進捗

<img width="1440" alt="スクリーンショット 2020-07-02 22.39.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662094/d8549be4-1422-ed88-922c-4359ea5107d7.png">

途中で形にはなっていたのが、
細かいところのレイアウトが違っていて
（特にpaddingやmargin)
中々妥協できずに時間がかかってしまった。

##今回の模写を通して
marginの相殺の理解が浅かった。
marginは計算しながらつけるようにしていく。
marginやpaddingが、どの値がより正確かを探すのにも、デベロッパツールは重要であることを知った。

画像からカラーコードを算出してくれる以下のサイトはとても便利
模写したいサイトをスクショしてサイト内に貼り付けるだけ。
https://lab.syncer.jp/Tool/Image-Color-Picker/

##次回
まだ、細かいところのスタイルが当てきれてないので、そこから始める
(cursorや元サイトでリンクになっている部分）

Javascriptを使って、新しいアカウントを作成をクリックした際に、モーダルウィンドウとしてアカウント作成画面を表示する。
（positionやtranslateについてドットインストールで復習しながら）

必須入力事項のエラーの出し方と正規表現のインプットをする。

レスポンシブデザインへの対応は後回し。
以上

もっとスムーズにコードを書けるようになりたい。。。
モデル駆動形アプリのフォームに埋め込んだキャンバスアプリは、ModelDrivenFormIntegrationコントロールでレコードの情報にアクセスできる

行き詰まったので書いときます。でも、よく見たらDocsに書いてあった＼(^o^)／

https://docs.microsoft.com/ja-jp/powerapps/maker/model-driven-apps/embedded-canvas-app-add-classic-designer

モデル駆動形アプリにて、通常のカスタマイズより柔軟にUIを作り込みたい場合があります。
その際、選択肢の一つとして、フォームにキャンバスアプリを埋め込むことができます。

以下みたいな感じです。
\![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/a02fd845-9893-33b0-7f5b-ecaeb4b842a8.png)

ちゃんとフォームで表示しているレコードの情報も渡せています。
このレコードの情報にアクセスするときは、ModelDrivenFormIntegrationというコントロールのItemというプロパティでアクセスできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/f4254bd6-56e1-7f31-f21c-cfb00114f9ee.png)

ModelDrivenFormIntegrationのDatasourceプロパティをみると、普通にエンティティを指定しているから、[@Accounts]でアクセスできるのかと思ったらできなくて、ちょっと苦しみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/f7cbcc50-7653-252d-0729-e918e093e797.png)

結論的には、

(○)ModelDrivenFormIntegrationコントロール
(×)エンティティ(Accountsなど)

です！

また、モデル駆動形アプリ⇒キャンバスアプリでデータ渡すだけではなく、キャンバスアプリからモデル駆動形アプリの特定の処理を呼び出せるみたいですね。というか、呼び出せました。

https://docs.microsoft.com/ja-jp/powerapps/maker/model-driven-apps/embedded-canvas-app-actions

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/2454436e-eb6b-da15-8d02-a4ed4b2fde2c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287381/fc2185a0-fa6d-464e-ccb2-9195eb287810.png)

全部Docsに書いてあることだったけど、まあいいか。
【PowerShell】パスが通っていない外部コマンドにパイプする小技

地味にハマったので。

### パスが通っている場合

Scoop でインストールすればイイ感じに設定してくれるので実行ファイル名だけで簡単に呼び出せます。

```PowerShell
ls -name | peco.exe
```

`.exe` なしで `ls -name | peco` とさらに簡略化することもできますが、実行ファイルであることを明示しておいたほうが安心なので個人的には残すことが多いです。

### パスが通っていない場合

#### パターン A: パスが固定

フルパスを指定します。
このときに引用符で囲んでしまうと文字列扱いになってエラーになります。

```PowerShell
ls -name | C:\Users\tools\peco\peco.exe
```

#### パターン B: パスを動的に指定したい

ハマったのはこのパターン。

自作ツールをクラウド経由で同期して複数PCで使いたいとき、 PC によって変わるユーザー名部分に自動変数 `$env:USERNAME` で対処しようとしたのですが、 `"C:\Users\$($env:USERNAME)\Dropbox\tool\mytool.exe"` などと引用符で変数展開しようとすると上記の通り文字列扱いになって正常に動作しません。
`Start-Process` にパイプしてもエラーとなり、それなら `-ArgumentList` を使えばと思っても配列はただの空白区切り文字ととしてパラメータに渡されるらしく、期待する動作は叶いません。

正解は下記でした。

```PowerShell
ls -name | & "C:\Users\$($env:USERNAME)\Dropbox\tool\mytool.exe"
```

実行演算子（ call operator ）の `&` を使えばよかったようです。スクリプトブロックの実行にばかり使っていた盲点でした（ [参考サイト](https://ss64.com/ps/call.html) ）。

`&` 単体で google 検索に引っかからずに苦戦していたところ、この記号が “ampersand” ということを知りました。検索スキルという意味でどちらかというとこの学びのほうが大きかったというオチ……。
ターミナルからの【Gitコマンド】

## はじめに
某プログラミングスクールに通い、SES企業に転職しました。
ここでは主にスクールで学んできた事と、実際に業務を初めた際のギャップや、備忘録などを記載し、自身の知識定着を目的に書いて行こうと思います。

## プログラミングスクールで学んだ事
Ruby on Rails、Javascriptを用いたフルスクラッチのアプリケーション開発及びAWSを用いたデプロイ

主な開発実績

- Haml
- SCSS
- Ruby
- Ruby on Rails
- JavaScript
- jQuery
- GitHub
- AWS

上記技術を用いた複合的機能の企画・実装を行いました。

## つまずいた事
- Git Hubでの管理は、Git Hub Desktopの使用はしない事
 - Git Hub Desktopを使用した場合、意図しないマージが発生する可能性があるため、SESとして働く場合、ターミナル上から直接コマンドを実行する必要があり、GUIに頼りきりだったため、コマンドの理解度が低かった。
- Dockerを利用して開発環境下で確認する事
 - Ruby on Railsを利用している場合は、rails sでローカル環境のサーバーを立ち上げていたが、Dockerの利用方法を調べるのに時間がかかった。

## 備忘録
備忘録を兼ね、以下のgitコマンドを復習しておきます。

```ruby:gitコマンド

git init
#新たにGitで管理したいディレクトリで実行すると、Gitで管理できるようになる

git branch -a
#今いるブランチを確認

git add
#対象ファイルをインデックスに追加

git status
#状態を確認

git diff --cached
#git add した後に変更点を確認

git commit
#インデックスに追加されている変更修正をコミット、別途コメントを入力

git push origin ブランチ名
#commitしたファイルをリモートブランチにpush

git checkout ブランチ名
#ブランチへ切り替える

```

## さいごに
スクールを卒業しても、まだスタート地点にさえ立っていない印象が強かったです。
実施する事に必要な事は積極的に情報を仕入れる必要があると再認識しました。
自分用　API叩く時確認すること

###リクエストの種類
GET,POST
###リクエスト方法
どのパラメーターをurlに含めるのか

###リクエストヘッダーのパラメーター
json指定やAuthorization,accept

###リクエストボディの中身,形式
jsonなのか,encode_formなのか

###認証方法
OAuth確認

####会計freeeの請求書発行API

```ruby
def make_invoice
  uri = URI.parse(BASE_URL + '/api/1/invoices')
  http = Net::HTTP.new(uri.host,uri.port)
  http.use_ssl = uri.scheme === "https"
  params = INVOICE_PARAMS
  headers = MAKE_INVOICE_HEADER
  req = Net::HTTP::Post.new(uri.path)
  req.body = INVOICE_PARAMS.to_json
  req.initialize_http_header(headers)
  response = http.request(req)
  res_hash = JSON.parse(response.body)
end
```

ヘッダーとボディをリファレンスで注意深く確認

```ruby
MAKE_INVOICE_HEADER = {
  "accept" => "application/json",
  "Authorization"=> "Bearer #{ACCESS_TOKEN}",
  "Content-Type" => "application/json"
}

INVOICE_PARAMS = {
  "company_id": COMPANY_ID,
  "issue_date": Date.today,
  "due_date": Date.new(Time.now.year, Time.now.month, -1),
  "partner_id": PARTNER_ID,
  "booking_date": Date.today,
  "description": "#{Date.today.month}月分請求書",
  "invoice_status": "draft",
  "partner_display_name": "株式会社freeeパートナー",
  "partner_title": "御中",
  "partner_contact_info": "営業担当",
  "partner_zipcode": "012-0009",
  "partner_prefecture_code": 4,
  "partner_address1": "湯沢市",
  "partner_address2": "Aビル",
  "company_name": "freee株式会社",
  "company_zipcode": "000-0000",
  "company_prefecture_code": 12,
  "company_address1": "ＸＸ区ＹＹ１−１−１",
  "company_address2": "ビル 1F",
  "company_contact_info": "法人営業担当",
  "payment_type": "transfer",
  "payment_bank_info": "ＸＸ銀行ＹＹ支店 1111111",
  "message": "下記の通りご請求申し上げます。",
  "notes": "毎度ありがとうございます",
  "invoice_layout": "default_classic",
  "tax_entry_method": "exclusive",
  "invoice_contents": [
    {
      "order": 0,
      "type": "normal",
      "qty": 1,
      "unit": "個",
      "unit_price": 1,
      "vat": 8000,
      "description": "備考",
      "tax_code": 1,
      "account_item_id": ACCOUNT_ITEM_ID
    }
  ]
}
```

日々精進
【WSL2】Windows10のUbuntu GUIを利用してGatsbyでHello Worldまで

Gatsbyのhello-worldがWindows10ではできなかったので、Ubuntu経由で構築できるのかを確かめてみます。
公式チュートリアル：https://www.gatsbyjs.org/tutorial/

##Ubuntuの環境構築
以前の記事から始めてください。
[【初心者向け】WSL2を利用してWindows10 HOMEでUbuntuを利用する方法](https://qiita.com/neneta0921/items/3d97b1aec820a58460f7)

この記事が終わったら、まだUbuntuにはブラウザが入っていないので、追加でインストールします。

###Firefoxをインストールする
以下のコマンドを実行して、Firefoxをインストールします。

```powershell:SHELL
$ sudo apt install firefox
```

##0.Gatsbyの基礎：[公式サイト](https://www.gatsbyjs.org/tutorial/part-zero/)
###Nodeをインストールする
以下のコマンドを実行して、Nodeをインストールします。

```powershell:SHELL
$ sudo apt update
$ sudo apt -y upgrade
$ sudo apt-get install curl
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.1/install.sh | bash
```

.bash_profile にPATHを追記します。

```powershell:SHELL
$ echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bash_profile
$ echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.bash_profile
$ echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.bash_profile
$ source ~/.bash_profile
```

これで`nvm --version`を実行するとバージョンが表示されます。
次にNPMをインストールします。

```powershell:SHELL
nvm install 10
nvm use 10
```

### Gatsby CLIをインストールする
以下のコマンドを実行して、Gatsby CLIをインストールします。

```powershell:SHELL
$ npm install -g gatsby-cli
```

##Gatsbyサイトを作る
以下のコマンドを実行します。

```powershell:SHELL
$ gatsby new hello-world https://github.com/gatsbyjs/gatsby-starter-hello-world
```

ここまでできたら、Ubuntuのデスクトップを立ち上げます。Xlunchを起動し、次のコマンドを実行します。

```powershell:SHELL
$ startxfce4
```

以降は仮想デスクトップでコマンドを実行するときは「%」をつけます。

```powershell:Terminal
% cd hello-world
% gatsby develop
```

Firefoxから`http://localhost:8000/` にアクセスすると、下記の画面のように`Hello world`が表示されます。

![202007021432.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643170/9fc3af92-e1bf-07af-d5a9-8692165942bd.png)

簡単ですが、以上です。
こんな単純なことがWindows10ではできないので、不便ですがこの環境で構築します。
小数部に残された末尾のゼロを除去する、カウントする

```cs

private void button_Click(object sender, EventArgs e)
{
    // 除去する
    Debug.WriteLine(truncate_trailing_zeros(1040000.00M)); // -> 1040000
    Debug.WriteLine(truncate_trailing_zeros(1050000.00M)); // -> 1050000
    Debug.WriteLine(truncate_trailing_zeros(10.0000400M)); // -> 10.00004
    Debug.WriteLine(truncate_trailing_zeros(10.0000500M)); // -> 10.00005

    // カウントする
    Debug.WriteLine(count_trailing_zeros(0.4400M)); // -> 2
    Debug.WriteLine(count_trailing_zeros(1.0000M)); // -> 4
    Debug.WriteLine(count_trailing_zeros(1.0001M)); // -> 0
    Debug.WriteLine(count_trailing_zeros(100.00M)); // -> 2
}

public static decimal truncate_trailing_zeros(decimal value)
{
    return value / 1.0000000000000000000000000000M;
}

public static int count_trailing_zeros(decimal value)
{
    return (decimal.GetBits(Math.Abs(value))[3] >> 16 & 0x0FF) - (decimal.GetBits(truncate_trailing_zeros(value))[3] >> 16 & 0x0FF);

    /*var decimal_part = decimal.GetBits(Math.Abs(value))[3] >> 16 & 0x0FF;

    var last = -1;
    for (int i = 0; i <= decimal_part; i++)
    {
        var sample = (decimal)Math.Pow(10, -i) * (decimal)Math.Pow(10, i);
        var current = decimal.GetBits(value / sample)[3] >> 16 & 0x0FF;

        if(last == current)
        {
            return i - 1;
        }
        last = current;
    }

    return decimal_part;*/
}
```