OmniAICreator/Qiita-1.07M huggingface dataset:
https.onCall()で認証情報を利用する


Functionsで使えるようになったhttps.onCall()はAuthenticationでの認証データをそのまま利用できるので便利とは聞いていましたが、実際に試したことなかったので簡単に試してみます。

## Functions側

* データの受け取り（関係ないけど）
* 通常の認証
* Custom Claimの利用

をチェックできるようにしてみました。

```js:index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

//Auth Test用
exports.authTest = functions.https.onCall((data, context) => {
    //クライアント側で投げたデータはdataに入ってくる（未使用）
    const name = data.name;
    //認証情報はcontextに入ってくる
    //もし認証してたら
    if (context.auth) {
        //Custom Claimのadminがtrueだったら
        if (context.auth.token.admin) {
            return "Hello admin user";
        } else {
            return "Hello authed user";
        }
    } else {
        //エラーはちゃんとエラーをスローする。第一引数は決まった値じゃないとだめ
        throw new functions.https.HttpsError('permission-denied', 'Auth Error');
        // return "Auth Error";
    }
})
```

エラーコードは[こちらのサイト](https://firebase.google.com/docs/reference/functions/providers_https_.html?hl=ja#functionserrorcode)にあるものじゃないとだめっぽい。
本当の？エラーはcodeがinternalで返るみたい。

## Custom Claimの設定

Custom ClaimはAdmin権限じゃないと付与できない。とりあえずローカルで付与用のスクリプトを書いてみます。
特定のUIDを指定してadmin=trueとします。

```js:setCustomClaim.js
const admin = require('firebase-admin');

admin.initializeApp({
    credential: admin.credential.cert('/path/to/key.json),
    databaseURL: 'xxxxxxxxxx.firebase.com',
});

const uid = "aXG33d99AwfVmrxxxxxxxxxx";

(async () => {

    try {
        const res = await admin.auth().setCustomUserClaims(uid, { admin: true });
        console.log("set custom claim");
    } catch (e) {
        console.log(e);
    }

})()
```

## クライアントからの利用

クライアントからアクセスしてみます。これもスクリプトで試します。

```js:callFunction.js
const firebase = require('firebase');

const firebaseConfig = {
    apiKey: "xxxxxxxxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxxxxxxx.firebaseapp.com",
    databaseURL: "https://xxxxxxxxxx.firebaseio.com",
    projectId: "xxxxxxxxxx",
    storageBucket: "xxxxxxxx.appspot.com",
    messagingSenderId: "xxxxxxxxxxx",
    appId: "xxxxxxxxxxxxxxxx",
    measurementId: "xxxxxxxxxxxxxx"
};

firebase.initializeApp(firebaseConfig);

const db = firebase.firestore();
const functions = firebase.functions();

const shopSignUp = functions.httpsCallable("authTest");

(async () => {

    try {
        //ログイン
        const authResponse = await firebase.auth().signInWithEmailAndPassword('test@test.com', 'testtest');
        //ログイン成功
        if (authResponse.user) {
            //関数呼ぶ
            const callResponse = await shopSignUp({ name: 'foo' })
            console.log(callResponse);
        }
    } catch (e) {
        console.log(e);
    }

})()
```

簡単ですが、以上です。
Gitbookで「Invalid file descriptor to ICU data received.」が出てPDF出力できない場合の対処方法

こんばんは。morifujiです。GitBookを最近業務で使いはじめたんですが、PDF出力でエラーがでたのでそれを解決しました

## 問題

事前にgitbookをREADMEなりqiitaなりに従って、npmでインストールし brew caskでCalibreをインストールしている状態です

```
$ npm install -g gitbook-cli
$ brew cask install Calibre
```

この状態でPDFを出力をすると

```sh
$ gitbook pdf
...略
warn: "options" property is deprecated, use config.get(key) instead 
```

途中で固まりました。 `gitbook pdf --log info` で出力を見ると `Invalid file descriptor to ICU data received` これが原因そう

```sh
debug: [1218/194620.605118:ERROR:icu_util.cc(177)] Invalid file descriptor to ICU data received.
```
## 原因・対処方法

gitbookが依存しているcalibreのバージョンが4.xに上がったが、gitbookがそれに対応できていないためのようです。確かに調べてみたらgitbookは最終更新1年前。calibreが4.0になったのは2019年10月でした。

なのでcalibre のバージョンを4.xから3.xにする必要があるそうです。

```sh
# 一旦削除
$ brew cask uninstall Calibre
# 3.8.0をインストール。urlはgithubのコミット履歴から拝借
$ brew cask install https://raw.githubusercontent.com/Homebrew/homebrew-cask/0609402ee984aa887752a205b3086191aed1385e/Casks/calibre.rb
```

ちなみに、Calibreは公式サイトからdmgファイルでインストールできますが、それではダメでした

## 参考

- https://stackoverflow.com/questions/58498643/no-result-or-error-when-using-gitbook-pdf
- https://github.com/Homebrew/homebrew-cask/blob/0609402ee984aa887752a205b3086191aed1385e/Casks/calibre.rb
BlenderのテクスチャカラースペースをデフォルトでNon-Colorにする

#テクスチャのカラースペース
シェーダーエディターにテクスチャを配置したとき、RoughnessやMetallicなどはカラースペースを**Non-Color**にする必要があります。
逆にsRGBのままでいいのはBaseColorやSubSurfaceColorなど限定的で、毎回たくさんのノードでカラースペースを変えなければならず面倒くさいですよね。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552567/ec7ad537-b8e5-8794-017b-eb1e422fa565.png)

#config.ocioを編集
`Blenderインストールフォルダ¥2.xx¥datafiles¥colormanagement¥`
の中に**config.ocio**というファイルがあります。
これをテキストエディタで開くと、

    # Default color space for byte image
    default_byte: sRGB

という項目があります。sRGBをNon-Colorに書き換えて保存します。

    # Default color space for byte image
    default_byte: Non-Color

Blenderを再起動しシェーダーエディターに画像をドラッグアンドドロップすると、デフォルトでカラースペースがNon-Colorになっています。

##アップデートすると消えるかも
私はデイリービルドを使っているのでポータブル版なのですが、当然新しいバージョンを落とすたびにconfig.ocioを上書きする必要があります。インストールして使っている方もアップデートによって上書きされる可能性があります。デフォルトがsRGBに戻っていても慌てずに編集し直しましょう。バックアップを取っておくのも手です。
terraform のバージョンアップを渋っている人への追い打ち

# はじめにというか情報の紹介

この記事は[terraform Advent Calendar 2019](https://qiita.com/advent-calendar/2019/terraform)の18日目の穴埋め記事です。
予定外で記事書くの大変なので参加登録しておいて期日までに記事あげてこないのほんとどうにかして欲しい。。。

さて、昨日も[やっつけ記事](https://qiita.com/raki/items/66b3b8df5d1d2558a008)だったけど、今日はさらにやっつけですｗ

[こちらのページ](https://jvndb.jvn.jp/ja/contents/2019/JVNDB-2019-013027.html)をご覧いただいて、速やかに terraform のバージョンアップをしましょう。というだけです。

英語苦手なのでアレですが、暗号化アルゴリズムの脆弱性問題があって、 v0.12.17 以前のバージョンには問題があるから、v0.12.18にバージョンアップしてね、ということです。

もし身近にバージョンアップを渋ったりめんどくさがったりするような不逞の輩がいる場合には、この情報を元にコンプライアンスを前面に押し出し作業見積もりを提出して速やかにバージョンアップしていきましょう。

バージョンアップで明るい未来。いいですねｗ
VSCodoでターミナルを使う ❏VSCode❏

最近知った便利な機能

VSCode上で`command(⌘) ＋ バッククォート(｀)`を押すと、ターミナルが表示される。
<img width="1440" alt="スクリーンショット 2019-12-18 16.12.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529651/4a89ae3c-d40e-0390-7c22-b9cd42524edf.png">


`rails db:migrate`や`cd xxx`でフォルダ移動、
二分割にして片方は`rails s`など
普通にターミナルの機能を使えます。

<br>
僕はエディタとターミナルをいちいち切り替えて操作していました。
作業効率が2倍になった。。
もっと早く知りたかった。。。

<br>
ではまた！
SAP CP(トライアル) の CF で Docker を使ってみようとしたら、うまく行かなかった話

# はじめに

この記事は [SAP Advent Calendar 2019](https://adventar.org/calendars/3908) の12月19日分の記事として執筆しています

こんにちわ、株式会社ＫＹＯＳＯでエンジニアをしている上田といいます。
よろしくおねがいします。

本記事は、Cloud Foundry は、 Docker Image に対応していると聞いて
SAP Cloud Platform へデプロイを試みて失敗したときのトラブルシュートです。

デプロイが出来ない理由は、`トライアル環境で試したから！` と推測するまでの問題点と解決策をまとめました。

トライアル以外の環境での実施、またはトライアル環境であっても時期次第で成功する可能性があることをご理解ください。
「いやいや、自分はトライアル環境でも成功したよ！」と言った成功体験等ございましたら
お話等伺えましたら嬉しく思います。

# 環境

- SAP Cloud Platform( trial ): Cloud Foundry
- PC: Macbook Pro(2017)
- CFコマンド: cf version 6.35.2+88a03e995.2018-03-15

## 問題１

cfコマンドの接続先(API エンドポイント)が間違っている

自分の場合、会社のCloudFoundry環境 を利用していたこともあり
cfコマンドは、トライアルとは別のAPIエンドポイントに接続している状態でした。

### 解決策

以下のコマンドで APIエンドポイントの変更すれば解決

    cf login -a <APIエンドポイントのURL>

または

    cf api <APIエンドポイントのURL>
    cf login

APIエンドポイントのURLは、SAP Cloud Platform Cockpit から確認出来ます。
![スクリーンショット 2019-12-19 09.29.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303235/7a421313-e0cd-d6c4-94ee-44f976ccbfd8.png)


## 問題２

cf コマンドを実行した際のエラー内容が不明

### 解決策

`CF_TRACE=true`を環境変数に設定して、詳細なログが見えるようにする。

環境変数`CF_TRACE` の値を `true` にすると、
CloudFoundry を操作するためのAPI呼び出しが見えるようになるので
どのステップでエラーが発生しているのか、コンソール上に表示されます。

## 問題３

SAP CP で Docker Image のデプロイが出来ない

### 解決策

以下のコマンドで、Diego( Cloud Foundry のコンテナ管理システム )を有効にする。

    cf enable-feature-flag diego_docker

トライアル環境では、初期状態として Diego が無効な状態のようで、明示的に有効化する必要があるようです。
※このコマンド実行時に権限不足で実行出来ないことが発覚、 トライアル環境では Docker Image の利用は出来ないと判断しました。。。

### エラー内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303235/e7cb2fdc-39f1-8f47-5b5d-f35643811b78.png)

# 最後に
流石にトライアル環境で Docker 利用は考えが甘かったかなと反省しつつ
自分が遊ぶ環境を会社に買ってもらえないかチラ見する所存です。

# 参考URL
- [Cloud Foundry CLI Reference Guide](http://cli.cloudfoundry.org/ja-JP/cf/)
- [Deploy an application using Docker Container onto SAP Cloud Platform Cloud foundry](https://blogs.sap.com/2018/11/21/can-i-deploy-an-application-using-docker-container-onto-scp-cloud-foundry.-really/)
- [Cloud Foundry にアプリケーションを push する際の典型的な10のエラー](https://www.slideshare.net/nota-ja/cloud-foundry-push-10)
- [Getting started on SAP Cloud Platform with a docker image](https://blogs.sap.com/2019/01/29/getting-started-on-sap-cloud-platform-with-a-docker-image/)
- [Using Docker in CFAR](https://docs.cloudfoundry.org/adminguide/docker.html)
UIButtonのアイコンのダークモード対応

#背景

ダークモード対応を行う際、単純にボタンのTextColorだけを変えるとこうなります🤯
<img width="414" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-19 at 11.36.43.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/b022e416-4b3e-76f2-a088-a428af3d1227.jpeg">

デザイナーさんも忙しそうだし、ボタンに設定してる単色アイコンくらいならコードで色を変えた方が楽なのでは…？
ということで、UIButtonのカスタムクラスを作成することにしました。

#やってみる
こちらが今回作ったものです。
ボタンのアイコンとテキストを別な色で設定したい人向けです。

### カスタムクラスを用意する
まず`@IBInspectable`でStoryboardから色を設定できるようにします。
そして画面を表示している途中でモードを切り替えた時のために`draw()`の中で色を変更します。
ついでにハイライトの色もセットしておきます。

```swift

class IconButton: UIButton {
    @IBInspectable var iconColor: UIColor?

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        self.setTitleColor(self.currentTitleColor.withAlphaComponent(0.5), for: .highlighted)

        if let image = self.image(for: .normal), let iconColor = self.iconColor {
            self.setImage(image.tint(color: iconColor), for: .normal)
            self.setImage(image.tint(color: iconColor.withAlphaComponent(0.5)), for: .highlighted)
        }
    }
}

extension UIImage {
    func tint(color: UIColor) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, 0)
        color.setFill()
        let drawRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        UIRectFill(drawRect)
        self.draw(in: drawRect, blendMode: .destinationIn, alpha: 1)
        let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return tintedImage
    }
}
```
### Storyboardで設定する
ボタンのCustomClassに先ほど作成したクラスを設定します。
<img width="414" alt="スクリーンショット 2019-12-18 11.57.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/c42a01c5-a694-7819-13b7-9b14e412bcae.png">
iconColorに画像の色(ダークモード対応済みのもの)を設定します。
<img width="414" alt="スクリーンショット 2019-12-19 11.26.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/d3eaaba7-84c0-c151-ed55-2f5d4235290d.png">




#できました
###ライトモード
<img width="414" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-19 at 11.28.48. jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/1487302f-640c-a958-1b3a-5ecb06cc5f19.jpeg">

###ダークモード
<img width="414" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-19 at 13.24.30.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/702aa62b-7104-8b06-2a42-a4eb43d1708d.jpeg">

ハイライトはそれぞれこんな感じ
<img width="414" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-19 at 11.28.49 2.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/0c5894c3-361c-5dcc-19be-1c46e54edead.jpeg">

<img width="414" alt="Simulator Screen Shot - iPhone 11 Pro Max - 2019-12-19 at 11.29.01 2.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221224/97e67ad2-9214-9522-c887-a3362b60745b.jpeg">


完成👏



#本当は…
SF Symbolsを使えばサクッとダークモード対応ができるみたいなので、もし可能であればそちらを使った方が良いかもしれません。
https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/
やさしさあふれるATコマンド入門

[SORACOM Advent Calendar 2019](https://qiita.com/advent-calendar/2019/soracom2)１９日目の記事です。
今日は、ソラコムのSIMをUSBモデムに挿して通信する時に使う`AT（エーティー）コマンド`がどのようなものかについて、お話ししたいと思います。

# きっかけ

ソラコム認定デバイスのUSBモデムを使って通信する時、[各種デバイスで SORACOM Air を使用する](https://dev.soracom.io/jp/start/device_setting/)にある`setup_air.sh`というスクリプトを実行すると、それだけで簡単にインターネットに繋がるのですが、その中身がずっと気になっていました。どうやら`ATコマンド`というものを叩いているようなのですが、私には謎の文字列の羅列にしか見えず、なかなか興味を持てないまま月日が経ちました。
そんな中、技術書典というイベントで`ATコマンドカルタ`というものが販売されていたので、これを買って眺めているとATコマンドに興味が湧いてきて、その勢いで書いたのがこのブログになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377165/fa148e93-7d17-91dc-8bb7-a7391efd682c.png" width=80%>

これを見て、「ふむふむ、コマンドごとに何か意味があるのね。これってWindowsやLinuxのコマンドみたい。こうして見ると分かりやすいかも。」と思いました。

# ATコマンドって何？

`コマンド`とは機械に何かを実行させる命令のことで、やって欲しいことを伝えると機械がそれを実行し、必要に応じて結果を返すものです。例えば身近な例ですと、「OKグーグル　明日の天気教えて」とか「アレクサ　何か音楽かけて」と伝えることがコマンドに相当します。
同じように、USBモデムに対して「ショートメッセージ（SMS）送って」とか「USBモデムのメーカーを教えて」などの命令を伝えるためのコマンドが`ATコマンド`なのです。下の図で言うと、Raspberry PiからUSBモデムに対してATコマンドで命令するイメージです。SIMを挿したUSBモデムをRaspberry Piに挿しただけでは通信ができず、通信するためにはATコマンドが必要なのです。

![USBモデムの利用イメージ](https://docs.google.com/drawings/d/e/2PACX-1vT22FP9n0O3EVvrhTEhJtGmWcNOuwYc9ymPySIztwVn3yRaLOnJEc7Rnk5uMgDlmduvX7Zni3Y9dcEJ/pub?w=480&h=240)

具体的なATコマンドの例として、`ATI`というコマンドを見てみましょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377165/a401a8c0-e6fc-f043-3f23-9ed5734cc522.png" width=60%>


`ATコマンド`は全て`AT`から始まるのですが、このATは`ATtention`、つまり「注目！」のような意味なので、これはまさに先ほどの「OKグーグル」や「アレクサ」に相当します。そして`AT`の後の`I`が命令に相当し、今回のケースだと「モデムの製造情報を教えて」という要求になります。

# どんなコマンドがあるの？

`USBモデムに挿さっているSIMのIMSIを教えて！`

    AT+CIMI
    295050910xxxxxx

コマンドの結果で返されるIMSIは、SORACOMのユーザコンソールで見れるコレです。

![ユーザコンソール](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377165/a12f8733-6094-7378-4bea-1562c9a5df7d.png)


`USBモデムのメーカーやモデル名を教えて！`

    ATI
    Manufacturer: huawei
    Model: MS2372h-607
    Revision: 21.328.02.01.00
    IMEI: 8670230301xxxxx
    +GCAP: +CGSM,+DS,+ES

実際に使っていたモデムはこれです。
<img src="https://soracom.jp/wp-content/uploads/2019/07/products_ms2372h.png" width=50%>

`電波状況を教えて`

    AT+CSQ
    +CSQ: 25,99

数字が電波状況を表しているそうです。

他にもモデムとやり取りするためのコマンドはたくさんあります（カルタが出来るくらいなので）。また、標準規格で定義されているATコマンドの他に、モデムの種類ごとに独自のATコマンドが用意されているようなケースもあります。

# で、結局どうやって繋げてるの？

`setup_air.sh`スクリプトにあるATコマンドだけ取り出すと、こんな感じです。

    AT+CFUN=1
    ATZ
    AT+CGDCONT=1,"IP","$1"
    ATD *99***1#

カルタで見るとこんな感じ。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377165/a448f9ca-d1b3-9a46-24d5-7fc0d9ad9a9a.png" width=60%>

これをざっくり一言で言うと、「無線通信が可能な状態にして、設定を初期化した後、接続のための設定をしてから指定した番号にダイヤル接続する」という感じの命令をUSBモデムにしていることになります。この命令をすることで、SORACOMに接続できているのですね！

# 次のステップ
今回は、ATコマンドに興味を持って頂くことにフォーカスして、詳細や手順は一切省きました。このブログを見て頂き、`実際に自分でもコマンドを叩いてみたい！`・`数字が電波状況を表しているそうって、、もっと正確に！`と思われた方は、ぜひこちらのブログをご覧ください！

- [SORACOM を使って学ぶ AT コマンド](https://bearmini.hatenablog.com/entry/at-command1)
- [日本でもグローバルでも利用可能なUSBドングルタイプのLTEデバイス「MS2372-607」の取り扱いを開始しました！](https://blog.soracom.jp/blog/2018/08/17/ms2372/)

それでは、「ATコマンドのこと知りたいなら、まずはやさしさあふれるこのブログを見るといいよ」と言われる日が来ることを願って投稿！
git clean で管理外のGitサブディレクトリを消す

`git clean -fd` で消えない子達を消す方法。

## 例

Gitリポジトリの中に別のリポジトリを持ってきていると、`git clean -fd` では以下のようになって全ては消せない。

```
$ git clean -fd
Skipping repository sub-repo/
```
ありそうな状況としては、submoduleの検討段階とか？

## Conclusion
`git clean -ffd` で全消しできる。

## git clean help を読む
`git clean -f` の説明によると、`-f`だけだと`.git`のあるディレクトリは消さないので`f`2つ付けろと書いてある。

```
-f, --force
    If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or
    directories unless given -f, -n or -i. Git will refuse to delete directories with .git sub directory or file unless a
    second -f is given.
```

## 参考

https://github.com/gitlabhq/gitlab-ci-runner/pull/141
バーチャルキャストで凸の人が来た時に「いらっしゃいませ！」って言わせてみる

#はじめに
本記事はVCIアドカレ2019の19日目の記事です。
[VCIアドカレ2019](https://qiita.com/advent-calendar/2019/vci)

#いらっしゃいませ！
バーチャルキャストでは凸者さんが来ると、サウンドが流れます。
それとは別にVCIで凸者さんが来た時に「いらっしゃいませ！」って流れるVCIを作っ
てみました。
実際には「ラジカセっぽい」に入ってる機能の一つです。

#どうやってやるのか？
**凸者さんが来た時にだけ音声を再生する。**

書くとこれだけですが、意外と気づかない方が多かったりしたようです。
「ラジカセっぽい」のテストしているときに、どうやるの？って何度か聞かれまし
た。

特に変わったことはしていないので、気づいた方も居ると思います。
分かりやすく書き換えてみましょう。

**プログラム実行時に一度だけ音声を再生する**

種明かしはこれだけです。

#VCIのしくみ
VCIは出し方と部屋にいる方、全員に読み込まれそれぞれの環境で実行されます。
その時に、所有者、VCIオーナーなどで実行制限をかけて動かしています。
そして凸した方は出ているVCIを読み込んで自分のVキャス環境で実行が始まります。

そして、全員が必ず実行するプログラムの部分に、変数の初期化が有ります。
（無い場合もありますが・・・）
全員が必ず実行する変数の初期化、その下にでも音声再生入れておけば、全員が一度
実行します。

#実際にLuaで書いてみる
音声再生だけが入ったVCIを作成すれば、凸者が来た時に音声を流すVCIのできあ
がりです。
一応、音量だけはパラメータにして調整するときに分かりやすくしておきます。
Luaで書くとこれだけです。

```Lua:TEST.lua
local Volume=0.08 --Volumeの値は元ファイルの音量により調整すること
vci.assets.audio._ALL_PlayOneShot("いらっしゃいのファイル名",Volume)
```

VCIのオブジェクトに関しては初期のキューブでも良いので、音声ファイルをUnity上
で割り当ててください。

#いろいろな使い方
実際には他の処理と組み合わせるので、StateやEmitなんかと組み合わせていろいろ
な処理を行ったします。

「ラジカセっぽい」、「コメビュ」ではこんな事をやっています。

・ラジカセっぽい：「いらっしゃいませ」音声、BGMのリプレイ
・コメビュ：凸者のカウント

いろいろ組み合わせれば、アニメの再生やオブジェクトの処理なんかも条件を付ける
事ができますね。

#おわりに
アイディアとしては、凸者さんが入った時に侵入者の警報サイレンが鳴ってみたり、
ゼロ地点で爆発起こしてみたり・・・。
あまりやりすぎないようにしましょう。

以上。
Neo4jを利用して日頃の感謝を目に見える形へ

#Salesforceオブジェクトのリレーション関係をneo4jで視覚化する
前回のadventに利用したneo4jを実際のデータを使用して触ってみようと思います。
使用するものとしては、neo4j , Salesforce , Thanks Go , JavaScript

## Salesforceとは
Salesforce(以下sfdc)はセールスフォース・ドットコム社が提供するクラウド型の営業支援（SFA）・顧客管理（CRM）システムです。
また、App Exchangeを通して様々なサードパーティアプリをアドオンすることが可能です。
今回は、サードパーティアプリのThanks Go(自社製品)を利用してThanks Cardを送り合った人間のリレーション図を作成していきたいと思います。

## Thanks Goとは
セールスフォース上で、感謝の気持ちを贈りあうサンクスカードを実現。
同僚への「ありがとう！」が自然と飛び交うことで、同僚同士のエンゲージメントの向上と
見えづらい業務の可視化が可能です。
[Thanks GO製品ページ](https://phoneappli.net/product/service/thanksgo/)

## 今回作成するもの

sfdc上のユーザーをneo4j上にnodeとして登録
Thanks Goからsfdcユーザー同士の感謝の関連性を取得、
それをneo4jのユーザーのnodeへ紐付ける。

## SFDCから使用する情報の取得


はじめに、sfdc上の情報を取得します。
情報の取得方法は,SOQLと呼ばれるqueryをREST APIで実行して取得します。
[参考ページ](https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/dome_query.htm)
実際のSOQLクエリは以下です。(フィルター条件は各自で設定してください。)
```SELECT Id , Username , LastName , FirstName , Name FROM User```

また、同様にThanks Goから投稿情報を以下のSOQLで取得します。

```SELECT Id , CreatedDate , thanksgo_pa__MentionedUser__c , thanksgo_pa__PostedUser__c FROM thanksgo_pa__PeerBonusPost__c ORDER BY CreatedDate DESC Limit 2000```

今回は人同士の繋がりのみ欲しいので　thanksgo_pa__PostedUser__c　,　thanksgo_pa__MentionedUser__c(どちらもsfdcユーザーIDが入っています)を作成日の降順で取得しています。


## neo4jにsfdcユーザーのnodeを作成する。
取得したユーザー情報をneo4jに以下Cyper queryで流し込みます。
```Create (User${count}:Person{sf_id:"{sfdcユーザーID}",name:"${氏名}"})```
結果が以下の画像になります。
<img width="1001" alt="スクリーンショット 2019-12-18 15.41.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/123fcf4d-756c-63b0-0f29-bb23d85b9617.png">

dummy[数字]のnodeがたくさん作成されていることが確認できます。
nodeの持つ情報は、sfdcユーザーIDと氏名情報(今回はdummyにナンバリングを付与しています)

## thanks cardの送受信情報でneo4j上にリレーションを作成。

今回は、thanks cardの送受信を有効グラフで表現します。
また、複数の送受信があった場合は、リレーションにweightとして回数を付与します。

既にリレーションが存在する場合と、存在しない場合を以下Cyper queryで区別し存在する場合には重みを1追加します。

```match (n:Person{Id:"{送信者のセールスフォースID}"})-[r:thanks_to]->(p:Person{Id:"${受信者のセールスフォースID}"}) set r.weight=r.weight+1 return r```

neo4jでリレーションが作成されていない場合は以下が実行されるよう実装を行います。

```match (n:Person{Id:"{送信者のセールスフォースID}"}),(p:Person{Id:"{受信者のセールスフォースID}"}) create (n)-[r:thanks_to{weight:1}]->(p)```

最終的に作成されたリレーション図がこちらとなります。
全てを出力するととても多くなるので自分を中心に出力しています。
```MATCH p=(n:Person{Id:"{自身のsdcユーザーID}"})-[r:thanks_to]->() RETURN p LIMIT 25```
<img width="495" alt="スクリーンショット 2019-12-18 15.51.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/46b74cbe-8745-87de-37c1-5b255b6d3a39.png">

また、重みが多い順(親密度順？？)に出力することもできます。
```MATCH (n:Person{Id:"00510000007qfblAAA"})-[r:thanks_to]->(p) RETURN n.name,r,p.name Order by r.weight desc```
<img width="871" alt="スクリーンショット 2019-12-19 9.14.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/fabfa0e0-d6c3-58b5-4f94-fedcbc055694.png">


## 最後に

neo4jを使用することでグラフィカルに感謝の関連性を出してみましたが、
リレーションにコメント情報を付与して特定のエキスパートなどを検索なども出来そうで、
色々とやれそうなことがありそうかと思いました。
#Stripe dashboard we can easy to find customer, subscription, invoice and others with id search. no need to type URL and combine id.

![image](https://user-images.githubusercontent.com/13635059/71041616-dad81400-216c-11ea-8785-f300b635fb9b.png)
![image](https://user-images.githubusercontent.com/13635059/71041617-db70aa80-216c-11ea-9208-12de91946d98.png)


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2853








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[Copy & Paste] 都道府県

DropDownList 都道府県一覧

C# 都道府県一覧をサーバー側で生成したい時用

```c#

public static List<SelectListItem> GetPrefecturesList(string prefecture)
{
  var prefectures = "北海道,青森県,岩手県,宮城県,秋田県,山形県,福島県,茨城県,栃木県,群馬県,埼玉県,千葉県,東京都,神奈川県,新潟県,富山県,石川県,福井県,山梨県,長野県,岐阜県,静岡県,愛知県,三重県,滋賀県,京都府,大阪府,兵庫県,奈良県,和歌山県,鳥取県,島根県,岡山県,広島県,山口県,徳島県,香川県,愛媛県,高知県,福岡県,佐賀県,長崎県,熊本県,大分県,宮崎県,鹿児島県,沖縄県";
  var listOfPrefectures = prefectures.Split(",");

  var selectListOfPrefectures = new List<SelectListItem>();

  foreach (var p in listOfPrefectures)
  {
    selectListOfPrefectures.Add(new SelectListItem()
    {
      Value = p,
      Text = p,
      Selected = (prefecture == p) ? true : false
    });
  }

  return selectListOfPrefectures;
}
Macで '/Library/Developer/CommandLineTools' is a command line tools instance って言われた

* macOSMojave
* バージョン10.14.6

雑メモ。

ターミナルで下記のように言われた。

>
$ opendiff 
xcode-select: error: tool 'opendiff' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

そこで

>
$ ls -la /Library/Developer/CommandLineTools/
total 0
drwxr-xr-x  6 root  admin  192  8 15 11:16 .
drwxr-xr-x  4 root  admin  128  9  8 17:43 ..
drwxr-xr-x  5 root  admin  160  7 13 13:44 Library
drwxr-xr-x  3 root  admin   96  7 13 13:11 Packages
drwxr-xr-x  4 root  wheel  128  8 15 11:16 SDKs
drwxr-xr-x  7 root  admin  224  7 13 13:44 usr
$ xcode-select -p
/Library/Developer/CommandLineTools

と環境を見てみたが、何が問題なのかよくわからんかった。

ググって出てきたこの記事
http://shinriyo.hateblo.jp/entry/2018/02/17/IonicのiOSのビルドのエラー

を参考にして
>
$ sudo xcode-select -switch /Library/Developer/CommandLineTools
$ sudo xcode-select -r

とやってみたら、
>
$ opendiff 
2019-12-19 08:37:14.020 opendiff[53779:3245168] too few arguments
2019-12-19 08:37:14.024 opendiff[53779:3245168] usage: opendiff file1 file2 [-ancestor ancestorFile] [-merge mergeFile]

使えるようになった。
なお、どういう原理で問題が解消したかは把握してない。

今回の記事は以上です。
VSCodeのESLintのautofixがうまく動いてなかったので設定を変えた

![Screenshot from 2019-12-19 08-29-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17669/66be714e-5bfe-d89c-5af9-fc578711646f.png)

```
The setting is deprecated. Use editor.codeActionsOnSave instead with a source.fixAll.eslint member.
```

とエラーが表示されていたので下記のように変えたら動いた。

```
  "editor.formatOnSave": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.fixAll.tslint": true,
    "source.fixAll": true
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
```

`eslint.validate` は `autoFix: true` がデフォルトになったようだ。

別のPCだと同じ設定でも動いてた気がするので、これがすべての環境での解決策になるのかは怪しいかもしれない。
Event Coalescing to improve performance 

この記事が[Angular #2 Advent Calendar 2019
](https://qiita.com/advent-calendar/2019/angular-2) ２３日目の記事です。

# Event Bubbling の性能の問題

下記のHTMLコードを見ましょう。

```html
<div (click)="doSomething()">
  <button (click)="doAnotherThing()">Button</button>
</div>
```

[Event Bubbling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture) のため、DivのなかのButtonをクリックしたら、両方のEvent ListenerがTriggerされます。この２つのEvent Listenerが全部Change Detectionを実行します。実際がこのようなケースでChange Detectionを一回だけ実行したいです。特にこのようなケースがAngular MaterialとかUI ライブラリで結構普通のケースですので、性能改善したいです。

# 実行順番

まず上記のケースでEvent ListenerとChange Detectionの実行順番を見ましょう。

```typescript
export class AppComponent {
  doSomething() { // event listener for parent div
    console.log('event listener for parent div');
  }
  doAnotherThing() { // event listener for inner button
    console.log('event listener for inner button');
  }
}
```

そして、Zone.jsがEvent ListenerをMonkey patchされましたので、下記のような感じのコードになりました。

```
function eventHandler(...) {
  try {
    realHandler(...); // doSomething あるいはdoAnotherThingのDelegate
  } finally {
    applicationRef.tick();
  }
}
```

そしたら、Buttonをクリックするとき、実行の順番が下記のようになりました。

```
event listener for inner button
applicationRef.tick
event listener for parent div
applicationRef.tick
```

実際ほしいのは

```
event listener for inner button
event listener for parent div
applicationRef.tick
```

です。

## 解決方法

Change Detectionを同期ではなく、非同期で実行することです。

```typescript
isChangeDetectionScheduled = false;
function eventHandler(...) {
  try {
    realHandler(...); // doSomething あるいはdoAnotherThingのDelegate
  } finally {
    if (isChangeDetectionScheduled) {
      return;
    }
    isChangeDetectionScheduled = true;
    requestAnimationFrame(() => {
      isChangeDetectionScheduled = false;
      applicationRef.tick();
    }); 
  }
}
```

のような感じのコードでChange DetectionをrequestAnimationFrameのSchedulerで実行させ、そしてもしScheduleされたTaskがあったら、スキップして、なかったら、Scheduleするということです。

## 設定方法

bootstrapModuleのとき、かきのOptionを設定することができます。

```typescript
platformBrowserDynamic().bootstrapModule(AppModule, {ngZoneEventCoalescing: true})
```

## 副作用

このオプションをTrueにしたら、もともと同期のChange Detectionが非同期になりました、普通のアプリケーションには影響がないですが、Google 内部でのEdge Caseで同期のChange Detectionが求めるテストケースがあるらしくて、それ以外が特に既存のアプリケーションには影響ないはずです。
この機能がすでに最新バージョンで使えますので、なにか問題が発見されたら、ぜひAngular RepoにIssueを提出ください。

以上です。

どうもありがとうございました！
C++ のWebアプリサーバ フームワーク一覧

ちょろっと調べた程度の情報です。

# Oat++

- [Website](https://oatpp.io/)
- ソースコード ― [GitHub](https://github.com/oatpp/oatpp)



# CWF

- [Website](https://www.cppwebframework.com/)
- ソースコード ― [GitHub](https://github.com/HerikLyma/CPPWebFramework)
自然言語処理をしてみよう！…で、一番初めにエラーで止まった原因「文字コード」

自然言語処理をやろう！
と思ったとき、プログラムはいろんなものを参照しながらやっとできたものの
テキストを開いたりするときにエラーが書かれて先へ進めず…。

プログラミング初心者…、訳も分からず調べたら文字コードの問題だったらしいので
解決策としてまず最初に出会ったのが、テキストを開くとき文字コードを指定するというもの。

エディタで調べてみると、「shift_jis」で書かれているようなので
じゃぁ、まずはそれをやってみようかな。

##文字コードを指定してテキストを開く

始めのこの部分を

```Python3
f = open(uencode.txt)
```
次のように変更

```Python3
import codecs
f= codecs.open(unencode.txt, 'r', 'shift_jis')
```

わーい、読み込めた！と思ったら今度は自然言語処理で書いていたプログラムはUTF8を求めていたようで、他の所でエラーが出てしまった…。

なら、テキストで書かれている文字コードをUTF8に変えたものを作ってしまおう。

##文字コードを変換してテキストを保存

今回はたくさんのテキストを変換したかったので、一つのファイルにまとめてそのファイルに入っているすべてのものを変換します。

```Python3
# -*- coding:utf-8 -*-
import codecs
import os

path=os.getcwd()
encode_path = os.path.join(path, 'encode')#変換後のファイルを保存するパス
unencode_path=os.path.join(path, 'unencode')#変換前のファイルが存在するパス

for name in sorted(os.listdir(unencode_path)):
    f = open(os.path.join(unencode_path,name))
    # 変換前（Shift_JIS) ファイルのパス
    shiftjis_path = os.path.join(unencode_path,name)

    #変換後(UTF8)ファイルのパスが無かったら作る
    if not os.path.exists(encode_path):
        os.makedirs(encode_path)

    utf8_path = os.path.join(encode_path,name)

    # 文字コードを utf-8 に変換して保存
    f = codecs.open(shiftjis_path, "r", "shift_jis")
    f_utf = codecs.open(utf8_path, "w", "utf-8")
    for row in f:
        f_utf.write(row)
    f.close()
    f_utf.close()
```


これでやっと自然言語処理のプログラムが通るようになった(*'ω'*)

###おまけ~文字コード~
今回shift_jisとutf-8しか使わなかったけれど、他の文字コードもプログラム内ではどう指定できるのか少し調べてみました。

|文字コード|プログラム中の指定|
|:---:|:---:|
|Shift-JIS|shift_jis|
|UTF-8|utf-8|
|ASCII|ascii|
|EUC-JIS|euc_jp	|

###おまけ~文字コードの判定~
エディタを開いて文字コード確認していて、面倒だなぁと思っていたのですが
プログラムで確認できるんですね…。

```Python3
import chardet

with open( sample.txt, 'rb') as f:
    sample = f.read()
print(chardet.detect(sample))
```
実行結果：{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

これ利用したら、多くのテキストファイルの中から該当する文字コードで書かれたものだけ変換とかできて便利そう(*^-^*)

##参考
[Pythonと文字コード](https://www.kabipan.com/computer/python/unicode.html)
軽量DDDは有りか？

[レガシーをぶっつぶせ。現場でDDD！2nd 「インプット＜アウトプット！」](https://genbade-ddd.connpass.com/event/156060/)のクロージングワークショップの中で議論した内容を簡単にまとめた記事になります。

インプット＜アウトプットということで、初めてですが少しでも残ればと思い投稿します。

# 結論：軽量DDDは有り！
結論から書いてしまいますが、クロージングワークショップの結論としては**軽量DDDは有り**という雰囲気で終わりました。

増田（[@masuda220](https://twitter.com/masuda220?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor)）さんにファシリテートしてもらいながら、インプット＜アウトプットということで、一人一回以上の発言をルールとして議論していきました。

以下に簡単にですが、議論した内容を記載します。
（ホワイトボードの写真撮り忘れました・・・。）

### そもそも軽量DDDとは？
- DDDのValueOvject、Entity、Repositoryなど技術的な部分のみを取れ入れDDDを行うという実践ドメイン駆動設計（IDDD）の中で、アンチパターンとして語られているもの。
- コアドメイン、サブドメイン、境界付けられたコンテキスト、ユビキタス言語などを意識していないもの。

キーワードは以下の表の通り

|戦術的|戦略的|
|:--|:--|
|値オブジェクト|コアドメイン|
|エンティティ|サブドメイン|
|リポジトリ|境界付けられたコンテキスト|
||ユビキタス言語|

その他のキーワードとして

- クリーンアーキテクチャ
- オニオンアーキテクチャ
- オブジェクト指向
- トランザクションスクリプト

### 実際、軽量DDDは有りだと思うかどうか？
- 有りだと思っている。値とロジックを一緒にしておくことでオブジェクト指向的になり、コードは整理される。

### DDDとオブジェクト指向の違いは？
- DDDもオブジェクト指向の一種ではないか。DDDはその中でもドメイン部分に注力する。
- そのせいかファイルの入出力などはトランザクションスクリプト的な書き方になりがち...。

### クリーンアーキテクチャやオニオンアーキテクチャを適用しないとDDDにならないか？
- アーキテクチャとDDDは切り離して考えられる。
- 違うアーキテクチャを採用してもDDDをすることは可能。

### 軽量DDDから重量（？）DDDに移行できるのか？そもそも境界線は？
- コアドメインやサブドメインを意識してクラスを考え始めたらちゃんとしたDDDではないか。
- ユビキタス言語を活用して、ドメインエキスパートと話ができたらDDDではないか。

### ドメインエキスパートがいないとちゃんとしDDDはできないか？
- ドメインの分析はドメインエキスパートが必要。
- ユビキタス言語を浸透させていくためにもドメインエキスパートの存在が必要。
- ただ、スタートアップのプロジェクトの場合、ドメインエキスパートがいないのでは...？

### ラスト2分増田さんより一言
『エヴァンス本の中ではむしろ値オブジェクトなどの戦術的な部分があった上で、戦略的な部分が考えられると明確に書かれている。私もそちらの考え。』
<font color="LightSlateGray">※もっと色々言いたかったみたいですが、一人一回以上の発言のルールのために、控えていたご様子（笑）
</font>
## 感想
個人的には「軽量DDDは有り」と思って、議論に参加していました。
理由は単純でコードをきれいに書きたいと考えているとどうしても戦術的な部分に力が入ってしまうという思いからでした。
そして難解なエヴァンス本の中でも値オブジェクトとかエンティティってわかりやすく、エンジニアとしてはやってみたいと思うじゃないですか（笑）

今回議論の中で、他の方々も基本的には「軽量DDDは有り」と思っている方が多かったように思います。
同じような悩みや思いの共有ができて、参加して非常に良かったです。
今後も継続してこういったワークショップには参加していきたいと思います。
そして、腹落ちさせるためにも少しでもアウトプットしよう！・・・という気持ち。

### 謝罪
完全に記憶だけを頼りに書いたので、抜け漏れ、間違いあるかもしれませんが、ご容赦ください。
当日参加されていた方で、明らかな間違いに気づいた点があればコメントください。
GCPのIAM Roleどれ設定すればええねん問題

# Permission Error 地獄

```
Error: Permission iam.serviceAccounts.signBlob is required ...
```

ふむふむ、Permissionがないっていってるんやな。適切なPermissionをつければ動くのだろう。

=> googling...

**なるほど、よくわからん！！**

なんか適当にそれっぽいの含んでそうな権限を付与したら動くようになった！

えいや！

```
Error: xxxxxxx@appspot.gserviceaccount.com does not have storage.objects.get access to ...
```

(´；ω；｀)

またなんか出た。

=> googling...

**なるほど、よくわからん!!**

```
Error: xxxxx@appspot.gserviceaccount.com does not have storage.objects.create access to ...
```

...勘弁してください...

てなことよくありませんか？
私はよく起こります。

そのたびにわからないながらもググって、おなじようなエラーに直面した人の解決方法見て、

> Storage Admin をIAMで付与すると動きました！

とかを鵜呑みにして、「これ本当に適切なのだろうか？？？」とか思いながらも、とりあえず動かすためには書かれていた権限を付与したり、最悪Project Ownerとか付与したりしてモヤモヤとしていました。
ドキュメント見ても、権限 **storage.objects.create** がどんなことができるかとかそういうことしか書いてなくて、
**これだ!**という確信がないままIAMでRoleを設定することになります。

苦節数年…やっと解法を得たので共有しておきます。

# Permissionに対応するRoleが何か調べる方法

* GCPのConsole > IAM & admin > Role と進みます。
<img width="500" alt="スクリーンショット_2019_12_19_8_05.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/e9c3cba7-c931-8f48-4f07-3075d17e6a66.jpeg">

* 検索種別にPermissionを
<img width="343" alt="Roles_–_IAM___admin_–_ideodora-aqmap2-1_–_Google_Cloud_Platform.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/a610ba15-3c06-26fa-ddc9-58c8e982386f.jpeg">

* 必要とされるPermissionで検索
<img width="739" alt="スクリーンショット 2019-12-19 8.08.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/572c551b-02ab-eb71-5f80-ea7ca5056a1a.png">

すると、なんということでしょう。該当するPermissionを含んだRole達がずらりとリストされます。
title部をクリックすると、このRoleに割当てられているPermissionが一覧で確認できます。
<img width="208" alt="Storage_Object_Admin_–_IAM___admin_–_ideodora-aqmap2-1_–_Google_Cloud_Platform.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/2a1d8355-3736-3273-6380-0d14c98026f4.jpeg">


後は、この中から妥当なRoleを決めて、IAMに設定すればOKです。

<img width="706" alt="IAM_–_IAM___admin_–_ideodora-aqmap2-1_–_Google_Cloud_Platform.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37209/cf96f2c8-3b07-71d0-1cf3-f552e8ea7fda.jpeg">

# 選択すべきRole

おそらくですが、なるべく権限範囲の狭いRoleを付与するのが適切だと思われます。
先の例だと、```Storage Admin```までは実は必要なく、```Storage Object Admin```があれば、
```storage.objects.get``` ```storage.objects.create``` をカバーしているので```Storage Object Admin```の方が適切かと。

```iam.serviceAccounts.signBlob``` だと ```Service Account Token Creator``` かな？

とりあえず、何でも Project Owner からは卒業しましょう！（汗
プロジェクト管理の課題と解決（2）プロジェクト管理ツール開発の追い風

**「『プロジェクト管理に課題なんて無い』と言う方がいたら会ってみたい」**とまで思ってしまうほど、個人的にプロジェクト管理には多くの課題を感じています。自社で開発・使用しているプロジェクト管理ツールにだって、「もっとこうだったら良いのにな。」と思うところも多々あり…。

前回の[「プロジェクト管理の課題と解決（1）『必要なものは造る』と自社でプロジェクト管理ツールをつくった話」](https://qiita.com/Kapi-Ten/items/1b0c519a46dec806d026)では、どういった想いや背景で[プロジェクト管理ツール『Time Krei』](https://timekrei.tenda.co.jp/)の開発をしたかという事を振り返ってみましたが、今回は**プロジェクト管理ツールの開発に大きな影響をもたらした『工事進行基準』について**まとめてみます。

##追い風になった『工事進行基準』

2009年4月の事業年度から**ITベンダーの会計処理に原則的に適用されることになった『工事進行基準』**は、2008年にリリースされた[『Time Krei』](https://timekrei.tenda.co.jp/)の追い風になったと言えます。この動きは業界全体の働き方の意識を底上げするような潮流となりました。

**『工事進行基準』とは長期的なプロジェクトにおける会計基準のうち、売り上げを期毎の進捗に合わせて分散計上する方式のこと**を言います。決算日ごとに人件費などの原価と売り上げが計上されるため、プロジェクトの終了時にまとめて計上するやり方（工事完成基準）に比べて、不採算などが発見されやすくなり、企業会計の透明性が保たれるという大きなメリットがあります。

建設業や海外のSIer（エスアイアー／System Integrator）では広く採用されていたものの、それまで『工事完成基準』（プロジェクトが完了し検収を受けた段階で収益を計上する）が主流だった国内のソフトウエア受託開発事業での適用は、多くの戸惑いを生み出したことでしょう。

**売り上げ、原価総額、決算日における進捗度の三つの要件について信頼性をもって見積もるということは、プロジェクト管理の厳格化を意味**し、今までの企業間の関係や契約における慣例の見直しを迫られる事案も多く出てくるからです。

##当時は8割以上が未対応。進まない『工事進行基準』の適用

『工事進行基準』は、全世界の企業会計の基準を統一するコンバージェンスへ対応（自国基準をできるだけIFRS（国際会計基準）に寄せること）の中の一つです。

日本では、企業会計基準委員会と国際会計基準審議会（IASB）の共同プロジェクトの第一回会議が2005年に実施されたそうですが、『工事進行基準』の適用が2009年4月ということは、もし第1回の会議でスケジュールが決まっていたとしてもその準備には4年もありません（実際には準備期間は「1年あった」と小耳にはさみましたが…1年て短くない？）。

『原則適用』であるので、規模が小さいプロジェクトや先の三つの要件（売り上げ、原価総額、進捗度）をきちんと見積もれないのであれば適用はしないということになります。テンダの取締役が2010年のインタビューで『工事進行基準』について、「『今後どうなっていくのかと窺っている』という状態。」と答えている通り、当時、すでに対応が完了していると答えた企業は全体の2割未満に留まっていました。8割以上の企業は、対応しなくてはいけないと理解しつつも、すべてをルール通りに対応することは難しい状態だったのではないでしょうか。

 ISOやコンプライアンスに関しての規制が非常に高まっている時期ということもあり、「管理する」ということにコストをかけ整備しなくてはいけないが、工事進行基準対応も必要で業界全般的に手が足りない、回っていないという状況です。 

また、『工事進行基準』自体の定義が非常に曖昧だということも、実行に移すのに迷いを生む状況を作り上げていました。どの水準までやらないといけないのかなどが非常に曖昧であるために、初速が弱まっていたのでしょう。

しかし、収益の根拠が明確にされる必要があるため、**『工事進行基準』がきちんと適用できないということは経営管理上の問題と言えます。**そのため、経営者や管理者の意識の底上げにつながり、また少しでもわかりやすく、個々の担当者がそれぞれの数値を正しく登録していくことで『工事進行基準』に対応することができる**[『Time Krei』](https://timekrei.tenda.co.jp)は、経営者の目線で見てもインフラ的なツールである**と言えました。

##（今回のまとめ）追い風もあれば、逆風もある

前回の「ワークライフバランス」に続いて、今回の『工事進行基準』の適用は、「きちんと新しい基準に沿って管理しなければならない」、つまりは担当者一人一人が自分のタスクをきちんと登録すれば自動的に計算・管理をしてくれるツールである[『Time Krei』](https://timekrei.tenda.co.jp)のアドバンテージを説明するにはとても良い状況だったと言えます。

これだけ聞いていると、時流を読み流行にも乗ってとても良い船出をしているかに見える「プロジェクト管理ツール」の開発ですが、考えることは皆同じでこの後はどんどん似たような製品がリリースされていくのです。

レッドオーシャン（まではいかない？）化が進むと重要なのは、「課題を解決する必要最低限な機能がきちんと機能するか」という基礎工事と、さらに利用者に対して他社に比べて優位な点があると提示できるか、といったところでしょうか。

次回はさらに細かく[「プロジェクト管理ツール」の機能について考えていきたい](https://qiita.com/Kapi-Ten/items/b74577dbfc5da3ceec3c)と思います。

もし、[テンダ](https://www.tenda.co.jp/)の[プロジェクト管理ツール『Time Krei』（タイムクレイ）](https://timekrei.tenda.co.jp/)にご興味をお持ちの場合は、是非一度[サービスサイト](https://timekrei.tenda.co.jp/)をご覧ください。
letを使った遅延処理、shared_examples

#letを使った遅延処理

```spec/system/tasks_spec.rb
require 'rails helper'

describe 'タスク管理機能', type: :system do
  describe '一覧表示機能' do
    let(:user_a) {FactoryBot.create(:user, name: 'ユーザーA', email: 'a@example.com')}
    let(:user_b) {FactoryBot.create(:user, name: 'ユーザーB', email: 'b@example.com')}

    before do
      FactoryBot.create(:task, name: '最初のタスク', user: user_a)
      visit login_path
      fill_in 'メールアドレス', with: login_user.email
      fill_in 'パスワード', with: login_user.password
      click_button 'ログインする'
    end
    context 'ユーザーAがログインしてる時' do
      let(:login_user) { user_a }
      
      it ~~~~ do
      end
    end
    context 'ユーザーBがログインしている時' do
      let(:login_user) { user_b }
      
      it ~~~~ do
      end
    end 
  end
end
```

このように先にログイン処理の大枠を書いておいて、contextごとにletで具体的なlogin_userの値を指定してる。

また、user_a,user_bの作成はbefore do end の外側で行ってる。

また、ログイン処理の大枠も、moduleに定義して他のファイルでも使い回せるようにした方がいいかも。


#shared_examples
文字通り、exampleを定義して他でも簡単に使い回せるようにしよーってこと。
shared_contextのexample版


```spec/system/tasks_spec.rb
require 'rails helper'

    before do
      FactoryBot.create(:task, name: '最初のタスク', user: user_a)
      visit login_path
      fill_in 'メールアドレス', with: login_user.email
      fill_in 'パスワード', with: login_user.password
      click_button 'ログインする'
    end
   
    shared_examples_for 'ユーザーAが作成したタスクが表示される' do
      it { expect(page).to have_content '最初のタスク' }
    end

    describe '一覧表示機能' do
      context 'ユーザーAがログインしてる時' do
       let(:login_userA) { user_a }
       it_behaves_like 'ユーザーAが作成したタスクが表示される'
      end
    end     
```

このようにdescribeよりも前にexampleを定義して使い回す。
これもmoduleのファイルを作ってそこに定義した方が良さそう。
LeetCode: 941. Valid Mountain Array 


# 問題の要約
- 与えられた配列要素の数値の大小が一つの山を形成するか判定する問題
- 必ず登りから入り、その後必ず下る。水平(同じ数値の連続)は許容しない。

# 問題
[問題へのリンク](https://leetcode.com/problems/valid-mountain-array/description/)

# 回答　その１
- 最初に頂上位置を求め、その左右に勾配があるかを確認

```cpp
bool validMountainArray(vector<int>& A) {
    int max_i = 0;
    if (A.size()<3) return false;

    for (int i = 0; i<A.size(); i++) 
        if (A[i] > A[max_i]) max_i = i;

    if (max_i == 0 || max_i == (A.size() - 1)) 
        return false;

    for (int i = max_i; i<A.size() - 1; i++) 
        if (A[i] <= A[i + 1]) return false;		

    for (int i = max_i; i>0; i--) 
        if (A[i - 1] >= A[i]) return false;

    return true;
}
````
````math
時間計算量：O(N)、空間計算量(1)
````
- 配列長が短すぎないかと頂上位置が先頭または末尾ではないかのチェックを入れた。
- 提出にて Acceptされたが、冗長感あり。Runtime=36 ms、Memory=10.5 MBと普通な結果でした。
ゆったりした時間が味わえる癒しのライト「ゆらりめらり」

# 制作背景
意外と休憩するための道具がないと思って作りました。
暇な時、休みたい時、ネットサーフィンをすることが多いとは思いますが、もっとぼーっとする時間が増えてもいいのではないかと思ってます。

# 内容
焚き火をモチーフにしたライトです。
大きく分けて、シェード部分とLED部分でできています。
二つの機能が実装されています。
### 揺らめき機能
加速度により、光が点滅。

### 息吹きかけ機能
気圧により、輝度が上がる


## デモ
https://youtu.be/SvrVBnri1oo
※実際は、焚き火の音はしません。

## 外装
イラレで図面を作成し、レーザーカッターで骨組みを制作。
そこに糸を規則的に巻きつけました。
![8a97f0c5ef6b40ad7355c57fef3af0ad.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420554/37b6a5a8-5faa-623e-d4e1-6fd4263d9faf.jpeg)


## 光の制御
マイコンで光の制御をしています。
入力：加速度センサー、気圧センサー
出力：LED

## 終わりに
クラウドファンディングも実施しているのでもしよかったらご覧ください！
https://camp-fire.jp/projects/view/211769?list=watched

次は @karu  さんです！
Ionic with Zone.js

この記事は [Ionic Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ionicframework) 20日目の記事です。

# Ionic with Zone.js

この記事は前日のMeetupで発表したものです。

## Ionic4 + Zone.js 0.9.1 でのパフォーマンス低下

Ionic4 (Angular)でZone.js 0.9.0から0.9.1にアップグレードしたあとで、動きが遅くなりました。調査したところ、`Change Detection`の回数が多くなっていたことがわかりました。その理由を説明させていただきます。

### Ionic 4 の仕組み

Ionicはバージョン４からStencilを利用して、すべてが`WebComponent`になりました。

![Screenshot from 2019-12-19 00-09-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109004/7c4b5cc9-1dc0-4f57-92fa-be4a6cdf9eec.png)

そして、Zone.jsは0.9.1から`WebComponent`のAPIを全部`monkey patch`しました。下記のようなイメージです。

![Screenshot from 2019-12-19 00-35-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109004/7bf1df20-9c97-0041-e52f-60e97c16a131.png)

その結果、WebComponentがangular zoneに自動的に入りました。このPatchはWebComponent用ですが、Angular Application用ではありません。

しかし、Ionicの場合、すべてのComponentはWebComponentであると同時に、普通のAngular Applicationでもあります。つまり、IonicのComponentが普通のAngular ApplicationのComponentとしてラップされているため、すでにangular zoneの中に入っています。

その結果、なにかInputが変更する場合、

- Angular ApplicationによるAngular ZoneのChange Detection
- Zone.js PatchされたCustom Elements APIのChange Detection

両方がTriggerされ、パフォーマンスが低下します。

### 解決案

解決方法はZone.jsのPatchを無効化することです。

やりかたとしては、一つの`zone-flag.ts`をつくって、

```typescript:zone-flag.ts
(window as any).__Zone_disable_customElements = true;
```
をいれます。

そして、`polyfilles.ts`に

```typescript:polyfilles.ts
import './zone-flag';
import 'zone.js/dist/zone'; // Included with Angular CLI.
```
をいれて、zone.jsのCustomElements APIのPatchを無効化します。

以上です。
どうもありがとうございました！
vyos installation and first config memo

# vyos installation and first config memo

## Objectives:

- personal memo

## Target System:

- ESXi 6.7

## Install:

### 1. Download iso file:

- vyos-rolling-latest.iso
    - https://downloads.vyos.io/?dir=rolling/current/amd64
- vyos-1.1.8-amd64.iso
- vyos-1.1.8-amd64.ova
    - https://downloads.vyos.io/?dir=release/legacy/1.1.8

### 2. Create VM and Boot:

- Example
    - Guest OS: Debian GNU/Linux 9 (64-bit)
    - CPUs: 1
    - Memory: 2 GB

### 3. Install VyOS:

- https://vyos.readthedocs.io/en/latest/install.html

```
vyos login: vyos
Password: vyos

vyos@vyos:~$ install image
```
- Choose "S"
```
What console should be used by default? (K: KVM, S: Serial, U: USB-Serial)? (Default: K) S
```
```
vyos@vyos:~$ show version
Version:          VyOS 1.2-rolling-201912180217
Built by:         autobuild@vyos.net
Built on:         Wed 18 Dec 2019 02:17 UTC
Build UUID:       -
Build Commit ID:  c12a8da143d67f

Architecture:     x86_64
Boot via:         livecd
System type:      VMware guest

Hardware vendor:  VMware, Inc.
Hardware model:   VMware Virtual Platform
Hardware S/N:     -
Hardware UUID:    -

Copyright:        VyOS maintainers and contributors
```

- Power Off and remove ISO, then boot from disk image

```
vyos@vyos:~$ poweroff
```

### 4. Basic Configurations:

- https://vyos.readthedocs.io/en/latest/quick-start.html

```
show interfaces
configure
# set interfaces ethernet eth0 address 192.168.100.207/24

```
- https://vyos.readthedocs.io/en/latest/services/ssh.html

```
# set service ssh port 22
```
- https://vyos.readthedocs.io/en/latest/system/host-information.html

```
# set system host-name vyos01
# show system host-name
```

```
# set protocols static route 0.0.0.0/0 next-hop 192.168.100.4
# show protocols static route
```
```
# set system name-server <IP>
```
### 5. SNMP Configuration

```
# set service snmp community public authorization ro
# set service snmp community public network 192.168.100.0/24
# set service snmp trap-target 192.168.100.131 community public
# commit
# save
```
日本ディープラーニング協会　E資格（E検定）　勉強日記

2020年2月の日本ディープラーニング協会　E資格を取るための勉強日記となります。

###あなたは誰？
総合商社に勤める、プログラムが比較的好きな普通のサラリーマン。
周りはエクセルのマクロが使える人が5％いるかいないか程度。Python？なにそれ？ぴちょん？

会社を見回しても、データ人材として採用された人が数人？十数人？いる程度。うちの会社にこの資格を持っている人間がいるのだろうか…
総合商社といっても世の中との断絶を感じます。

###なぜ資格を取得する？
箔をつけるため。「東大卒」みたいな。結局まわりもほとんどプログラムをやらないし、ある程度AI系のプログラムができることを簡単に伝えるすべがない。すこしプログラムがわかる人に「あ、この人、機械学習やディープラーニングに関する最低限の知識はあるんだ」と思ってもらえることが狙い。

まぁ、実際にそういうケースが今後の人生で何回あるか大変疑問なのですが（それほどまでに、仕事でプログラミングをやる機会がない）。

あと単純に資格試験を勉強するのが好きというのもあります。

###どこで認定とった？
E資格を受験するためには、JDLA認定プログラム の合格が必要。じゃっかんお金の匂いもします。とりあえず値段で
AIジョブカレ (AIJobColle)
https://www.aijobcolle.com/dl/
に行きました。

機械学習コース、数学コース、ディープラーニングコースの3つを選択。E資格のためには仕方ない。ただ、機械学習とディープラーニングの知識は当初ほとんどなかったため、講義自体はとても勉強になりました。先生に恵まれた面もあると思います。値段が安い分、講義時間もあまり多くなく（？）、その分密度の高い内容になっていたと思います。
Slackで講義資料と講義動画が共有されるので、家でも十分勉強できます。
生徒数は15人ほどでしょうか、講師との距離が近く質問もしやすいと思います（Slackで質問コーナーもあり）
（jQuery,rails）特定のview(url)でグローバル変数を定義

こんにちは！

この前個人アプリを作成しているときにjs（jquery）とgem 'gon'について少しハマったのでご紹介しようと思います

なににハマったかと言うと、特定のビューの中で使用するjsの変数をグローバル変数として指定したく、jsのグローバル変数にgem'gon'で指定した値を代入したところ、アクションの外でエラーが出てしまい、他のjsファイルの実行の妨げになってしまったのです（ちょっと何言ってるかわかりづらくてすみません）

もう詳しい方ならこの一文を見ただけで察しはついているのではと思いますが、この時の状況と解決を簡単にご紹介します


# 'gon'とは
railsのコントローラで定義した変数をjs内で使用できるようにしてくれるgemです
https://qiita.com/s_nakamura/items/5d153f7d9db1b1190296

# グローバル変数とは
```〇〇.js
test_global = hogehoge
$(function() {
   //処理
});
```
このようにjsの関数の外に変数を定義すると、どこでも使える変数を定義することができます（グローバル変数）
また、関数の中であっても'var'など付けず、変数名のみで変数を指定しても、グローバル変数として定義することができます

# 起こったこと

```〇〇.js
test_gon = gon.test_gon
$(function() {
   //この中で上記のグローバル変数を使いたい 
});
```
私はこんな感じでグローバル変数を定義しました
すると、このjsファイルが実行されるビューにいるとき（gonで変数を指定しているアクションを実行したとき）は問題ないのですが、それ以外のビューにいる場合エラーになってしまいます

よく考えればわかることですが、アクション外では当然gon.test_gonは定義されていないのでエラーとなるのです

えぇ・・といってもグローバル変数にしないとやりたいことが実装できない・・
と考え、ググっていたところいい条件分岐のやり方がありました

# 解決

```〇〇.js
if(document.URL.match("/urlの文字列")) {
  //指定する文字列がURLに含まれる場合に実行する内容
  test_gon = gon.test_gon;
}
```

こんな感じで指定してあげると、特定のビューで使用するグローバル変数を定義してあげることができます

ちなみに

```〇〇.js
if(document.URL.match("/urlの文字列|/urlの文字列")) {
  //指定する文字列がURLに含まれる場合に実行する内容
  test_gon = gon.test_gon;
}
```

こうやって書くと、例えば/文字列/:test_id/文字列/:gon_id/のようなurlを指定することもできます
https://haayaaa.hatenablog.com/entry/2019/02/17/144329

本当jsてなんでもできちゃうのね

ともあれ指定できてよかったです

# ※追記
できたと思ったのですが、ページ遷移後直後のアクションで、「NaN」が表示されてしまっていました。
原因は遷移後直後にグローバル変数が読み込まれてなかったためです・・

もし同じような現象がある方は下記で解消するかもしれません。
上記の〇〇.jsの記述に

```
$(document).on('turbolinks:load', function() {
  if(document.URL.match("/urlの文字列|/urlの文字列")) {
  //指定する文字列がURLに含まれる場合に実行する内容
  test_gon = gon.test_gon;
});
```

でこんな感じで囲うとうまくいきました。
あと、この追記を記載する前は、グローバル変数に「var」をつけて指定していましたが、turbolinksで囲う場合は「var」をつけず指定しないとローカルな変数となって別の関数の中で使用できなくなってしまいます。
もし編集前のこの記事を参考にしている方がいらっしゃいましたらすみませんでした・・

参考としてください！！
【画像処理100本ノックに挑戦】Q.25. 最近傍補間

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.25. 最近傍補間
> 最近傍補間により画像を1.5倍に拡大せよ。

関数のスケール変換の式をそのまま使うだけです。普段はバイリニア補間等を使うので実装したことはありませんが、簡単ですね。問題文記載の式は間違っているので注意が必要です(x/ax->x/a,y/ay->y/aが正しい)。

```c++
int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();

	double a = 1.5;
	int Width = width * a, Height = height * a;

	PPM ppm2(Width, Height);
	for(int j=0; j<Height; j++)
		for (int i = 0; i < Width; i++)
		{
			ppm2(i, j, 'r') = ppm(std::round(i / a), std::round(j / a), 'r');
			ppm2(i, j, 'g') = ppm(std::round(i / a), std::round(j / a), 'g');
			ppm2(i, j, 'b') = ppm(std::round(i / a), std::round(j / a), 'b');
		}
	ppm2.Flush("out.ppm");
	return 0;
}
```
![imori.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/e3e35c3d-b57e-9f17-7c6e-9f7eb59aae83.png) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/94c0ca1f-0f11-431a-2b84-f03c34ede28b.png)
【画像処理100本ノックに挑戦】Q.24. ガンマ補正

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.24. ガンマ補正
> imori_gamma.jpgに対してガンマ補正(c=1, g=2.2)を実行せよ。

こういう処理はなじみがあります。簡単ですね。

```c++
int main()
{
	PPM ppm("imori_gamma.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	double c = 1., g = 2.2;

	auto carib = [&](double v)
	{
		return pow(v / c, 1. / g);
	};

	PPM ppm2(width, height);
	for(int j=0; j<height; j++)
		for (int i = 0; i < width; i++)
		{
			ppm2(i,j,'r') = carib(ppm(i,j,'r')/255.)*255;
			ppm2(i, j, 'g') = carib(ppm(i, j, 'g')/255.)*255;
			ppm2(i, j, 'b') = carib(ppm(i, j, 'b')/255.)*255;
		}
	ppm2.Flush("out.ppm");
	return 0;
}
```
![imori_gamma.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/2bdc2a70-a1da-5b2b-ba1f-0e12b35ce9c9.png) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/89820476-bcaf-1a24-947a-f4ac99021896.png)
地方の会社や人が東京のシステム開発会社に依頼するときの課題と対策

課題をシステムで解決したいんだけど、地方だからシステム開発会社がなくて困っている。東京にはいっぱいシステム開発会社があるのに!というときの課題と対策をつらつら書いてみます。

## 1.システムリリースが現地じゃないとできない。
アプリサーバーが閉じた環境にあると、外からアクセスできないので、現地に行って作業するしかないです。

##### 対策A.リモートデスクトップやTeamViewerを使って開発会社担当者が社内サーバーにログインして、リリースする。
オーソドックスな対応です。ただし業務時間外など見えないところで悪いことをしようと思えばいくらでもできます。
##### 対策B.Gitでソース共有した上でリリース手順を教えてもらい、社内のシステム担当者が責任をもってリリースする
リリース手順作って!とお願いすれば開発会社が作ってくれます。社内のシステム担当者がリリース手順を覚えたり、開発ツールを購入しなければいけませんが、手順書があれば誰でもリリースできます。ただしバグが多かったりすると、リリースに追われてしまいます。

##### 対策C.Webシステムで作ることにしてクラウドやレンタルサーバー上に展開する
クラウドやレンタルサーバー上にシステムを構築することで、開発会社の裁量でリリースできるようにします。公開したくないなら、自社のIPアドレスでホワイトリストを設定すればよいです。Webシステム=ブラウザで動くシステムなので開発中でもだれでも気軽に確認することができます。

## 2.DB環境が社内にしかない
保守フェーズになると個人情報が含まれているので社外に出せず、現地で作業するしかない場合があります。

#####対策A.個人情報を書き換えるようなバッチを開発会社に作ってもらう。
テスト環境を用意して、本番環境のDBを移行。その後バッチを実行して個人情報が含まれるデータを書き換え。書き換えたデータをエクスポートして開発会社に渡せばOKです。データ量が多くなるとどうやって送付するかがネックになりです。

#####対策B.DBaaSを活用する。
基本的には対策Aと同じですが、DBaaS(Azure SQL Database,Oracle Cloudなど)にテストデータを展開することでエクスポートの手間を省きます。これで重くて渡せません!ということがなくなります。開発依頼するときに、「テスト環境はDBaaSでよろしく」と言えばよいです。DBaaSってなんですかと聞いてくる開発会社は避けましょう。

## 3.対面で話さないとコミュニケーションがとれない

#####対策A　画面が共有できるWeb会議システムを導入する。
東京から地方へ行く場合、1回の交通費が数万円、プラス移動の拘束時間の原価数万円がかかります。Web会議OKかどうかは受注側にとっては大きな判断材料です。TeamやSlackなど画面を共有しながら会話できるツールを活用しましょう。

#####対策B　複数人の意見まとめる作業は自分たちでやる。
ステークホルダーに対する1対1もくは1対Nの打ち合わせはWeb会議でも可能です。現場利用者へのヒアリングなどN対1、N対Nの打ち合わせはWeb会議だとやりずらいです。現場の意見をとりまとめたうえで、Web会議で方針や開発の確認をするという進め方にすれば、Web会議でスムーズに進めることができます。
#####対策C サテライトオフィスを展開しているシステム開発会社を探す
サテライトオフィスを持っているということは遠隔でのやりとりが確立されている会社になります。行ける範囲でサテライトオフィスがあるのなら対面でのコミュニケーションも可能です。

## 4.見積もりしてくれない

#####対策A 要件定義を自分たちで進めてから見積もり依頼する。
見積に必要なのは、登録が必要な画面数、登録が必要ない画面数(検索など)、帳票数、別システムとの連携有無、特別な機能の有無です。この情報と改善したい課題、業務フローがあれば行かなくても(もしくは1回の打ち合わせで)見積もりができます。

こんなところでしょうか。また思いついたら書いてみます。
【SQL (Oracle)】GROUP BYで選択していない列を集計(MAX, MINなど)列と同時に出力したい

# 実験環境

[Oracle Live SQL](https://livesql.oracle.com/apex/f?p=590:1000)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/569976c8-aac5-8217-2c49-a3a0c309c263.png)


# 使用するテーブル

```sql
select * from SH.sales;
```
CUST_IDとTIME_IDでグルーピングしたのち、行数をカウントし、その最大値をTIME_IDとともに出力したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/e3ccdadf-4e26-abb4-530d-326ab6de2972.png)

# 完成図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/53a6afc3-c61a-0be4-ec0f-55b736f212f4.png)


# SQLスクリプト
## Viewを利用

cust_idがその日ごとに購入した製品種の個数を集計する。

```sql

create view sales_cnt_view
as select CUST_ID cid, count(TIME_ID) as cnt_tid, TIME_ID tid
   from SH.SALES
   group by CUST_ID, TIME_ID;
        
select * from sales_cnt_view;

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/fb696a29-7338-4a00-24ad-cc01d8420493.png)

## JOINを利用

```sql

select s1.cid 顧客ID, s1.max_cnt_tid 顧客の購入商品種類の最大値, s2.tid 日付
from (select cid, MAX(cnt_tid) as max_cnt_tid
        from sales_cnt_view
        group by cid) s1
        join sales_cnt_view s2 on s1.cid = s2.cid and s1.max_cnt_tid = s2.cnt_tid
order by s1.cid;

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/9295d30f-fafa-13c2-043c-bcdd804b2cdc.png)