OmniAICreator/Qiita-1.07M huggingface dataset:
Nix、Cachix、GitHub Actionsによるワークフローの紹介

## 概要

機械学習はパイプライン、コード、データのそれぞれ多様で開発中は頻繁に変更するため、コードだけでなくデータのバージョン管理や機械学習の処理のパイプラインを管理する必要があります。

コードの管理はGitHubを使うとしてデータの管理、前処理をしたデータの管理はこれから発展していくと思っています。

今回Nix、Cachix、GitHub Actionsを使った余計なオペレーションのないコードとデータのバージョン管理かつ機械学習の処理のワークフローを紹介します。

実現したいことは次の通りです。

* パイプラインをコードで管理する。
  * これはGitHubで管理できますね。
* だれがどの環境で行っても結果が再現される。
  * これを行うにはデータも使うソフトのバージョン管理が必要です。
* 結果をキャッシュし無駄な計算をしない。前処理など一度誰かが行った操作はキャッシュしたものを使う。
  * 数GBのデータの管理はGitHubには載せにくいです。S3を使うのが良さそうですがバージョン管理が別途必要です。

## Nixとは

Nixはパッケージ管理ソフトです。汎用的なものでgcc、emacs、pythonなどなんでも管理できます。

入力のファイルやパッケージをハッシュ値付きで指定し、生成物を作り、それに対してハッシュ値を計算してストレージに保存します。　つまり、純粋な関数型言語のように入力が決まれば出力が決まる構成になっています。

ストレージにはローカルのディスクやS3などが指定できます。
すでに生成物のハッシュ値に対応するものがあればそれをダウンロードします。無駄に計算は行いません。

Dockerに似ていると思われるかもしれませんが、Dockerはファイルのハッシュ値も要求しませんし、生成物をつくる過程でネットワークに接続するかもしれません。しかし、Nixでは生成物をつくる過程でネットワークからのダウンロードは許しません。

Nixはマルチプラットフォームで、LinuxとMacosをサポートしています。NixはUbuntuやRedhat上にインストールできます。
NixOSというものもありますが、Nixしかパッケージ管理ソフトがないOSです。

パッケージの記述にはNix Expressionを使います。ML風の動的型付けの関数型言語となっています。
関数型といってもHaskellとは関係ありません。

## Cachixとは

[Cachix](https://cachix.org/)はNixの成果物を管理するサービスです。Nixの成果物はストレージやS3に置くことができますが、GitHubのような個人的なポータルとしてCachixがあり、個人的なNixの生成物をCachixに保存できます。

# GitHub Actionsとは

GitHub ActionsはJenkinsのようにCIを行うサービスでGitHubが提供しています。
CIでよく行う作業がマーケットプレイスで共有されています。

Cachixもマーケットプレイスでサービスを提供していています。
[こちら](https://github.com/marketplace/actions/cachix)です。

たとえば、GitHubのレポジトリに`.github/workflows/test.yml `のファイルを置きます。中身を下記のものとします。
するとレポジトリにpushするたびにNixでパッケージ作成が行われ、その成果物が自動的にCachixにキャッシュされます。
古いキャッシュは勝手に消えます。

```yaml:test.yaml
name: Test
on:
  pull_request:
  push:
jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - uses: cachix/install-nix-action@v6
    - uses: cachix/cachix-action@v2
      with:
        name: mycache
        signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
        # Only needed for private caches
        authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
```

## Nix、Cachix、GitHub-Actionsを使ったワークフロー

GitHubに下記の[こちらにあるような](https://github.com/qfpl/sample-nix-data-pipeline/blob/master/README.md
) (自分で作ったものではないです。)　レポジトリをつくるとデータフローができ、成果物はCachixで置かれ、一度行った計算があればキャッシュを使ってダウンロードして無駄な処理が行われないワークフローが出来上がります。

## まとめ

Nix、Cachix、GitHub Actionsの紹介とそれらを連携させてワークフローをつくる紹介をしました。

Nixは入力ファイルと必要なパッケージが厳密に管理されるので、だれがどの環境で行っても結果が再現されます。
加えて生成物が自動でキャッシュされるため無駄な計算をしないでの機械学習の前処理の管理に適していると思い紹介しました。
CCNAとはなんなんだ！！！

業務がネットワーク系なので、上司からCCNAやるといいよと言われたけれど....
いや、なんスカ？シーシーエヌエー？ってなったので、まとめます。
...と言っても他のまとめサイトさんの方が情報は多いし、公式見た方が早いので、
試験受けたい！勉強しよう！って人は公式を見ましょう！

## CCNA(Cisco Certified Network Associate)とは
  * ネットワークエンジニアの技能を認定する資格試験
  * Cisco Systems社が実施している５つの技術者認定資格(CCENT,CCNA,CCDP,CCDE,CCAr)のうちの１つ。基礎レベルの位置づけ。
  * ９種類の試験に分かれている。一般的にCCNAというとRouting and Swithchingを指す。
  * 基礎的なネットワーク技術の知識を学べる。Cisco製のルータなどのネットワーク機器の導入に関して詳しくなる。
  * CCNAの認定を受けるには２つの方法がある。
    * CCNA Compositeの合格
        * 内容：ネットワークの基礎、LAN スイッチング、IPv4 および IPv6 ルーティング 、WAN、インフラストラクチャサービス・セキュリティ・管理
        * 受験料：39,000円
    * ICND1とICND2の合格
        * 内容：CCNA Compositeの内容を分割しているイベージ）
        * 受験料：（各）19,800円
  * 有効期限：３年

## 勉強サイト
あくまでも、自分のメモなので、他のまとめサイトを見た方が良きですよ

 * 教科書系
    * [CCNAイージス](https://www.infraexpert.com/info/ccnaz7.html) 
 * 練習問題系
    * [CISCOの公式練習問題](https://learningnetwork.cisco.com/docs/DOC-30752)

## 一言

受験するかしないかは、置いておいて、ネットワークエンジニアにとって、ネットワークの基礎を重点的に学べるCCNAは良いみたい！
CCNAイージスはネットワークの基礎の基礎も教えてくれるからありがたい！！

あと、これからIT企業に就職しようとしているエンジニア初心者の卵たちには取らなくて良い資格かなと個人的には思います。ネットワークをいじる上で必要な知識ですが、特に文系未経験諸君は見ても具合が悪くなりそうなものばかりですのでね！

以上！！
Qiita APIで記事からYoutube動画を集めてみた 🎬

雇われフルスタックエンジニアやってます。
よろしくです。

QiitaAPIで面白いアプリを作っている方の記事見て、
自分も簡単なの作ってみたいと。

これからは、５G時代、動画時代が花咲くだろうということで、
Qiita記事にあるYoutubeのURLを拾い集めてみました！

[DOGAKIITAA! 〜 Qiitaの記事からYoutube動画を集めてみた 🎬 〜](https://dogakiitaa.site/)

できた後、なにに使えるんだという感想が残りましたが。。。

## Qiitaアカウント取得

ユーザー登録からQiitaアカウント作って、プロフィール、設定、アプリケーションから
個人用アクセストークンを取得しました。

[ユーザー登録 https://qiita.com/settings/account](https://qiita.com/settings/account)

## Qiita APIを使ってみた

Postmanで、Qiita APIで "youtube"や"youtu.be"と書いてある記事の一覧を取得しました。

`GET /api/v2/items`

page: ページ番号 (1から100まで)
per_page: 1ページあたりに含まれる要素数 (1から100まで)

Postmanを開いてアドレスバーに入力

https://qiita.com/api/v2/items?page=1&per_page=20&query=youtube

Query Paramsに
KEY: Authorization
Value: Beare <個人用アクセストークン>

![qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208081/418dc9bb-5676-a323-ec00-95ef946c6dd7.png)

Sendを押す

BodyにJSON形式で結果が帰ってきました。
レスポンス側のHeadersをクリックすると、レスポンスヘッダーの内容がみれます。

![qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208081/90f56649-13c4-306e-0533-f9b63722ab42.png)

Linkヘッダーには、100ページより多いページにリンクされてるアドレスがありましたが、
取得できるのは、100ページまででしたね。

>認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。

これらのヘッダーで、リクエストできる残りの数がわかります。便利ですね。

Total-Count: データの総数
Rate-Limit: リクエストの上限数
Rate-Remaining: 残りのリクエストできる数

あとは、PHPでAPIを呼び出し、記事を解析して、YoutubeのURLを集めてみました。

## 参考

[Qiita API v2ドキュメント - Qiita:Developer](https://qiita.com/api/v2/docs)
[Qiita【PHP】APIを使用しQiitaでの自分の投稿を取得する方法。](https://qiita.com/art_porokyu/items/e55a8193f5d9b28ca159)
[Postman | The Collaboration Platform for API Development](https://www.getpostman.com/)
[![Check! https://youtu.be/7E60ZttwIpY](http://img.youtube.com/vi/7E60ZttwIpY/0.jpg)](https://youtu.be/7E60ZttwIpY)
Special Thanks Qiita API
dagger2入門 - 導入の仕方


## 概要
* dagger2やDIの初心者です。
* gradleとKotlinでプログラミングします。

## daggerのみを使う

### 環境
* IntellJ IDEA 2019.1.3
* JRE 1.8.0
* gradle 5.4.1

### gralde
```
apply plugin: 'kotlin-kapt'

dependencies {
    ......

    def dagger_version = "2.25.2"
    implementation "com.google.dagger:dagger:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kaptTest "com.google.dagger:dagger-compiler:$dagger_version"
}
```

## Androidアプリ向けにdaggerを利用する

### 環境
* Android Studio 3.5.3
* gradle 5.4.1

```
dependencies {
    ......

    def dagger_version = "2.25.1"
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android-support:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kaptTest "com.google.dagger:dagger-compiler:$dagger_version"
    KaptAndroidTest "com.google.dagger:dagger-compiler:$dagger_version"
}
```

## kapt, kaptTest, kaptAndroidTestの違い
* https://kotlinlang.org/docs/reference/kapt.html
   * If you use annotation processors for your androidTest or test sources, the respective kapt configurations are named kaptAndroidTest and kaptTest.
おれおれレビューしやすいプルリクエスト

## はじめに

[オープンロジ](https://openlogi.com/corp/)のエンジニアで @ttaka と申します。
この記事は [OPENLOGI Advent Calendar 2019](https://qiita.com/advent-calendar/2019/openlogi) の20日目になります。

弊社では古株にあたるため、プルリクエストのコードレビューをする機会も多く、早くレビューをこなすためにこうなってたらいいなと思ってることを、ちょっとまとめてみました。

なお、あくまで個人の考えであり、OSSとして公開されているパブリックリポジトリなどのマナーとは一部異なるものもありますので、そのあたりはご留意ください :bow: 

## プルリクエストを作るときにお願いしたいこと

### できるだけ小さく！

いやもうほんとこれさえやってもらえれば、あとは瑣末な問題といってもいいくらいに、これはお願いしたい！

Files changedの数がスゴいレビュー依頼がきたりすると、時間があるときにみようと思って、一旦そっ閉じしてしまいます……いや、見ますよ見ます、あとで必ず見ますけども！ :sweat_drops: 

レビューに時間がかかると、その分リリースも遅れ、リベースやマージ時のコンフリクト発生確率も増えていきますから、細かくリリースできる単位でプルリクエストを分割していただけると、お互い幸せになれるかなと。

ただ、大きな機能の開発のときは、比例して大きくなりがちなのもわかります。そんなときでも機能を小さく分割し、その単位でさらにブランチを切ることで、同じように小さなプルリクにできますね。

### 目的の異なる内容のものは別のプルリクエストに

例えば、あるチケットを解決するための修正(a)を行い、その際たまたま目についた関係のない箇所のリファクタリング(b)もやったとします。

ボーイスカウト精神ほんと素晴らしい！ :clap:

ただ、その修正が一緒になったコードをレビューすると、aの解決にbも何か関係があるのだろうかと悩むことになります。

リファクタリングは負債を返済していく上でも大歓迎ですので、bはぜひ別のプルリクにしてレビュー依頼していただけると！

### コミットも意味のある単位で分ける

社内のリポジトリなので、そんなに綺麗にする必要はありませんが、コミット単位で実装者の思考を追いかけながらレビューすることも多いので、上記と同じく異なる内容のコミットは別になってると嬉しいです。

また、プルリクを分けないまでも、コミットがそれぞれ意味のある単位で別れていると、その単位でレビューできるので、小さなプルリクと同じ状況を作り出せます。

ちなみに、コードフォーマッターによる修正なども、それのみのコミットに分割していただくほうが好きですね。

### コメントはやったことではなく理由を書く

例えば、最大表示件数の定数定義があり、その数値を変更した際、

> 5から3に変更

といったコミットメッセージがあっても、変更の差分を見れば一目瞭然です。

> 表示が多すぎると1画面内に納まらず、ユーザビリティが悪化するため、3件までに制限

こんな感じに書いてあれば、レビューしてるときもなるほど確かにと思いますし、このことを知らない人からこの値を大きくしてほしいといった依頼があり、別の開発者が修正することになっても、本当に変更していいのか事前に気をつけることができます。

### タイトルはわかりやすく

こちらもただ不具合修正といった感じに書くのではなく、何をどうしたのか的なタイトルにしていただけると、概要を把握しやすくて嬉しいです。

### コミットは上書きせず追加

指摘のあった箇所の修正を既存のコミットに混ぜてforce pushされると、レビュー済みとそうでないものが混ざってしまい、どこを見ればいいのかわからなくなるので、上書きせずに追加してほしいです。

OSSのリポジトリなどでは、履歴が汚れるのを嫌って上書きを推奨してる場合もありますが……。

なお、コミット自体が不要になった時であれば、打ち消しのためのリバートコミットを作るのではなく、そのコミットを削除してforce pushしていただいて構いません。

### 書くまでもないテンプレートは消す

弊社ではプルリクのテンプレート機能を使って、作成時に書くべきことのテンプレートが挿入されるようになっています。

基本的には記載してほしいものですが、単なるコードフォーマットの修正など、ほとんどレビュー不要なものであれば、その旨記載してばっさりカットして構いません。
変にテンプレートのまま残してあると、どこかきちんと記載した箇所があるのか探すことになり、無駄な時間がとられてしまいますので。

なお、書く必要のある内容なのに面倒でカットするのはダメ絶対！

## おわりに

上記のように作ったプルリクのレビュー依頼をだしてるのに、なかなかレビューしてもらえない場合は、忙しさにかまけて棚上げしてる可能性がありますので、遠慮なく尻を引っ叩きにきてください……すみませんすみません :bow: :sweat_drops:
Akka終了時のログ欠損について

メモ書き

Akka StreamにてshutdownをHookして、Streamを停止させる処理を調査しているのですが、Akkaの終了時はログがDeadLetterになることが多く、終了時に何が起こっているか調査しずらいです
それでログがロストしやすい順に並べるとこんな感じ

1. com.typesafe.scalalogging.Logger ... 一番DeadLetterになりやすく欠損しているように見える
2. akka.event.Logging ... 1よりかはマシ、でもDeadLetterにならないなんてことはなくてしっかり欠損はする
3. 他サービスでログを取るAPIを作ってコールする ... 欠損なし

ログ自体がそこまでサービスにクリティカルになることはないのでAkkaの設計思想的に終了時は欠損してオッケーって感じなんでしょうね
Windows10にDockerをインストール、エラー"Not enough memory to start Docker

#状況
Windows10にDockerをインストールして、linux containerにSwitchしようとしたが、メモリ不足でSwitchできなかった。

そこで私の解決手段は
１．新しいPCをこの機に買い替える。ｗ
２．必要メモリ数を減らす。
の2択でした。

#必要メモリ数減らし方
Dockerの設定ファイルを直接修正してメモリ数を減らします。
１．%APPDATA%\Docker\settings.json に移動
２．ファイルを開いて"memoryMiB":2048を1024に書き換えます。それでもメモリ不足と表示がでるなら、512と書き換えればおそらくSwitchできます。

#試して通用しなかったこと
１．フリーなメモリ領域を増やす
RAMMapというメモリを管理するシステムがあるのでそれを使って、動作してないシステムを終了させてメモリ領域を増やします。
①システムダウンロード（https://docs.microsoft.com/en-us/sysinternals/downloads/rammap）
②システム起動（zipファイルで取得するので展開して起動。）
③左上のEmptyをクリック
④Empty Working Setをクリック
⑤F5を押してクリアします

２．Hyper-Managerを使用して起動メモリを減らす
Windowsの検索窓で"hyper"と打てばHyper-managerがあがってくるのでそれを選択します。
DockerDesktop VMがあると思うのでそれをクリックして、右枠の設定を選択すると、起動メモリ数を変更する欄があるのでそこでメモリ数を下げます。（DockerをSwitchするさいに再起動され設定したメモリも、もとに戻るのでこれは全く無意味でした。）
全部大文字のテキストに text-transform: capitalize が絶対に効かない理由

比較的ベーシックなプロパティである`text-transform`に知らない仕様があったのと、
ちょうどCSSアドベンドカレンダーに空きがあったので投稿します!

`text-transform`は、文字の大文字小文字の表示を変更するプロパティです。

一番想定される使い方は、欧文の大文字／小文字の変換です。
使えるキーワードと効果は次のように記憶していました。 [^1]

[^1]: `full-width`の挙動は記事のテーマと関係しないので話のスコープから外します。

- `uppercase`: 大文字に変換
- `lowercase`: 小文字に変換
- `capitalize`: 単語ごとに先頭を大文字にして、ほかは小文字にする

「何を今更」と思われるかもしれませんが、上記の理解は誤りでした。下のCodePenを見てください。

<p class="codepen" data-height="400" data-theme-id="23059" data-default-tab="result" data-user="hokkey" data-slug-hash="rNajLPp" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="text-transform: capitalize does not effect if the text is all-caps">
  <span>See the Pen <a href="https://codepen.io/hokkey/pen/rNajLPp">
  text-transform: capitalize does not effect if the text is all-caps</a> by y_hokkey (<a href="https://codepen.io/hokkey">@hokkey</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

このように、**`text-transform: capitalize`は、全部大文字のテキストには効果がありません。**

これは仕様通りの挙動です。

**CSS 1 仕様書**

>**'capitalize'**
uppercases the first character of each word
[Cascading Style Sheets, level 1](https://www.w3.org/TR/CSS1/#text-transform)

意訳： それぞれの単語の最初の文字を大文字にする。

**CSS 2.1 仕様書**

>**capitalize**
Puts the first character of each word in uppercase; other characters are unaffected.
[Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification](https://www.w3.org/TR/2011/REC-CSS2-20110607/text.html#caps-prop)

意訳： それぞれの単語の最初の文字を大文字にする。それ以外の文字には影響しない。

**CSS Text Module Level 3 仕様書（暫定）**

>**capitalize**
Puts the first typographic letter unit of each word, if lowercase, in titlecase; other characters are unaffected.
[CSS Text Module Level 3](https://www.w3.org/TR/css-text-3/)

意訳： それぞれの単語の最初の[typographic letter unit](https://www.w3.org/TR/css-text-3/#typographic-letter-unit)が小文字の場合にそれを大文字にする。それ以外の文字には影響しない。

細かいことは違いますが、一貫して単語の1文字目にしか言及していないことが分かります。
つまり、全部大文字の単語の2文字目以降を小文字にする機能は`text-transform: capitalize`にはありません。

### AngularのPipeとは挙動が違う

話が急にAngularへ飛びます。

Angularの標準のPipeである `uppercase`, `lowercase`, `titlecase`は、表示でなく出力する文字自体を置き換える機能ですが、その変換の挙動は`text-transform`と似ています。

- https://angular.io/api/common/UpperCasePipe
- https://angular.io/api/common/LowerCasePipe
- https://angular.io/api/common/TitleCasePipe

しかし、こちらの機能は2文字目以降にも影響してくれるため、

```html
<p>{{ 'HELLO WORLD' | titlecase }}</p>
```

の出力は

```html
<p>Hello World</p>
```

と同じになります。最近Angularをよく使っていたため、この`titlecase`の挙動が`text-transform: capitalize`と一緒だと誤解してしまっていた。

## CSSだけで常にtitlecaseにする方法はまだない

```scss
.alternative-capitalize {
  text-transform: lowercase;

  &:first-letter {
    text-transform: uppercase;
  }
}
```

なお上記のようなコードで、1文字目だけを常に大文字化することは可能ですが、単語ごとに1文字目を大文字化することはやっぱり実装できません。

## おわりに

何年CSS書いてるんだっていう感じですが、非常にベーシックなプロパティすら完全には把握していなかったのが残念でした。これからも謙虚な気持ちで学んでいきたいものです！
Micro:bitのBluetoothを使ってDCモータの正転反転

#動作
https://youtu.be/MnKtxg13Z6E

#Micro:bit
https://microbit.org/ja/guide/

#材料
Micro:bit https://www.switch-science.com/catalog/5263/
ピッチ変換基盤 https://www.switch-science.com/catalog/3181/
単三電池ボックス https://www.switch-science.com/catalog/3332/
ジャンプワイヤー（オスーオス） https://www.switch-science.com/catalog/620/
ジャンパワイヤ（オスーメス） https://www.switch-science.com/catalog/2294/
リレーモジュール　「SODIAL(R) リレーモジュール」なんかで検索して、お好みのショップでポチってください。
適当な５V電源 ACアダプタとかATX電源とかUSBとか
https://www.switch-science.com/catalog/list/?keyword=%E3%83%96%E3%83%AC%E3%83%83%E3%83%89%E3%83%9C%E3%83%BC%E3%83%89+USB

#プログラム
Rover（リレー側）
https://makecode.microbit.org/_DuV7yPUDT03b
remote（リモコン側）
https://makecode.microbit.org/_6aD7gm5J26Xp

#あとがき
ショートしないように試行錯誤し、とりあえず動いた。
SLX FPGA 2019.4の新機能は？

##概要##
　[Silexica] (https://www.silexica.com/ja/)はSLX FPGA Ver.19.4をリリースしました。本バージョンでは VivadoやVitis高位合成ツール(HLS)向けに、C/C++コードの準備と最適化を実現します。SLX FPGA 19.4は、SLX FPGAの並列性検出と自動HLSプラグマ挿入を活用することで、HLSプラグマを使用しない場合と比較して、平均45倍のパフォーマンスの改善を提供します。

####デザインのパフォーマンス最大化####

　HLSを使用するためには、設計プロセスにおいて考慮、克服されるべき独特な課題が存在します。 SLX FPGAは、合成不可能なC / C ++コード、ハードウェア化できないC/C++コード、アプリケーションの並列性の検出、プラグマを挿入する場所など、HLSデザイン・フローにおける課題を解決し、ソフトウェア・エンジニアがC/C++ソースコードの準備と最適化を実現します。SLX FPGAは、以下の機能を提供することにより、ソフトウェア開発者が開発期間を数か月短縮できるようにします。

- C/C++で記述された合成不可能なコードのガイド付き自動リファクタリング
- パフォーマンス最適化のために並列化可能なC / C ++コードの検出
- Vivado HLSコンパイラ向け、最適化されたプラグマの自動挿入

　SilexicaのCEO、Maximilian Odendahlのコメント：
「SLX FPGA 19.4は、ソフトウェア開発とFPGAデザインのギャップを橋渡しする重要なステップです。ザイリンクス社のVivado HLSと、Silexicaの先進的なC/C++解析機能を使用することで、SLX FPGAはアプリケーション・コードに対して比類のない洞察を提供し、ザイリンクスユーザがデザインのパフォーマンスを最大化できるようにします。」

　富士通九州ネットワークテクノロジーズ株式会社 シニアプロフェッショナル エンジニア山下公彰様のコメント：

「SLX FPGAは、C/C++アプリケーションに対する洞察を提供します。これによりツールが提供する情報に基づいた設計上の意思決定が可能になり、HLSベースの設計期間を大幅に削減できます。」


***SLX FPGA 19.4の新機能と強化された機能***

- 任意精度の整数データ型のサポートにより、任意の精度の整数（ “ap_int”および “ap_uint”）を使用するアプリケーションをサポートする並列処理検出および分析ツールが提供されます。 これにより、SLX FPGA 19.4では、処理に変数を使用するループにおける並列部を検出できるため、これらのループ向けのプラグマを生成できます。

- 改善された合成可能性チェックとガイダンスは、C ++固有のコンストラクトをサポートし、合成不可能なコードが使用されたときにユーザに警告する合成可能性チェッカの拡張版です。 合成できない構造が見つかった場合、SLX FPGA 19.4は、合成可能なコードを書き直すためのガイダンスを提供します。
- 関数マッピング・エディタによって、プロジェクトの関数とその依存関係が、関数マッピンググラフと各関数のプロパティで一元表示されます。 新しい関数マッピング・エディタによって、設計の反復が高速化できますので、SLX FPGA 19.4を使用するエンジニアは設計生産性を更に向上できます。
- プラットフォーム・インタフェースのモデリングにより、最上位のハードウェアにおいて利用可能な、インタフェースと帯域幅の構成を変更できます。
- 解析時間の改善により、SLX FPGAがユーザのコードを解析するために必要な時間が短縮されました。これにより、HLSのコードを最適化するために必要な開発時間が更に短縮されます。
 

　デモや評価をご希望されるお客様は[こちら](mailto:nextream_sales@nextream.bz)へご連絡ください。
vscode vim でInsertモードでカーソルを移動する

# 環境

- vscode 1.41.1
- vscodevim 1.12.0
- macOS Mojave 10.14.6

# 目的

- Insert モードでカーソルを移動したかった(生粋のvimmer に怒られるかも...)

# 方法

コマンドパレット開く(⌘P) > keybindings.json 検索 > keybindings.json に下記を記述

```:keybindings.son
[
    {
        "key": "cmd+l",
        "command": "cursorRight",
        "when": "editorTextFocus && !editorReadOnly"
    },
    {
        "key": "cmd+h",
        "command": "cursorLeft",
        "when": "editorTextFocus && !editorReadOnly"
    },
    {
        "key": "cmd+j",
        "command": "cursorUp",
        "when": "editorTextFocus && !editorReadOnly"
    },
    {
        "key": "cmd+k",
        "command": "cursorDown",
        "when": "editorTextFocus && !editorReadOnly"
    },
]
```

# 詳細

- `cmd + l or h or j or k` でInsertモードでもカーソルを移動できる

# 感想

勝手に挿入される`)`や`"`を以前は

1. `ctrl + o`で一時的にInsertモード抜ける
2. `a`で1文字スキップした状態でInsertモードに戻って続きを入力

という方法でやっていましたが、ちょっとスッキリしました。

Insertモード中に1文字スキップさせる方法が私には見つける事ができなかったので、もし他に方法があるなら是非教えて頂きたいです！！
WSLOnUbuntuの注意点兼備忘録

#TL;DR
WSLの導入に手こずった部分や、出会ったバグのように見える挙動等をまとめます。

#背景
Windows上でXServerを起動し、WSL内のUbuntuで実行されているIDEをWindows上で操作し、開発できるようにしようと考えました。
この構成の場合、IDE上で実行されるプログラムの実態はWSL内のUbuntuにいるため、Windows上のIDEを操作しているにも関わらず、Linux環境で開発するものと近い状況が再現できます。
以下の記事を参考に、WSLOnUbuntuで環境を構築し、かれこれ半年～1年ほど開発をしてきました。その中で軽くハマった話に触れていきます。

[Windows Subsystem for Linux + X Windowを1.024倍くらい使いこなすための方法](https://qiita.com/nishemon/items/bb3aca972404f68bfcd6)

#XWindowSystemについて
上記の記事でもあまり触れられていないので基礎技術に関して軽く触れておきます。
XWindowSystemはビットマップディスプレイ上でウィンドウシステムを提供する表示プロトコルで、Unix系オペレーティングシステムのGUIを別の環境へ提供することができます。
WSLOnUbuntuの場合、同じマシン内にUbuntuとWindowsがいるため、ネットワークの遅延もなくUbuntu上のGUIをWindows側に提供することができます。
Vagrantのような仮想マシンの提供と比べると、WSL上にいるためリソースの割り当てを考える必要がないのも魅力です。
また、XWindowSystemはクライント・サーバ方式をとっています。
クライアント・サーバ方式では使用者がクライアントを操作し、サーバを利用することが多いとは思いますが、XWindowSystemはこれとは逆に、サーバを操作し、リモートでクライアントを操作することになります。
クライアントで描画先を指定し、サーバ側で操作することになるので、複数のクライアントを操作することも可能です。

#環境準備における注意点
環境構築に関しては上記の記事でほぼほぼ事足りとは思いますが、Ubuntuの場合にのみ起こるであろう問題について触れます。

##IDEが描画されない場合
WSL上にてDISPLAY=localhost:0.0を設定することで、ホストのWindowsに描画を飛ばしてくれます。
上記の記事ではVcXsrvを使用し、ターミナルを使用、描画せずにショートカットでサーバ側にIDEを描画する方法が記載されています。
もし、クライアント側にDISPLAY=localhost:0.0を記述しているにも関わらず、ショートカットで描画されない人は.bashrcの内容を確認しましょう。

Ubuntuの.bashrcには以下の記述が存在します。

```
# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
```

上記の記述はコメントにある通り、インタラクティブ(対話型)でない場合はそこでシェルの読み込みを終了するというものです。
参考記事の通りに実行する場合

```
echo export DISPLAY=localhost:0.0 >> ~/.bashrc
```
最下部にDISPLAY=localhost:0.0を追加することになるため、設定が読まれずにXServerがクライアントの描画飛ばす先が未設定となり、何も表示されないという状態に陥るわけですね。
OpenSuseの.bashrcにこういった記述はないため、Ubuntu環境で構築する場合には気を付けなければならないポイントです。
Ubuntuの.bashrcの場合でも、終了処理が走る前、つまりDISPLAY=localhost:0.0を先頭につければ描画されるようになります。


#sudoで実行しているにも関わらず、許可がありませんと言われた話
###事象
```
sudo rm: '/hoge/huga.json' を削除できません: 許可がありません
```
WSL上のファイルを削除しようとしてこのようなメッセージが帰ってきました。
当時の自分はパーミッション回りの設定何かおかしかったかなぁと思いつつも、調査を始めました。
しかし、sudoで実行しており、念のためパーミッションを777に変えてみたにもかかわらず、上記と同様のメッセージが返ってくる状況は変わりませんでした。

###原因
該当のファイルをWindows側のソフトウェアで開きっぱなしにしてたことを忘れていたためでした。
このことにより、ファイルにロックがかかり、消せなかったというわけですね。
しかし、実行しているのはUbuntuの環境のはず。何故消せないのでしょうか。

WSLはWindows Subsystem for linuxの略語の通り、Windowsのサブシステムです。
WSLはネイティブLinuxバイナリをWindows上で実行できるようにするもの。つまりは変換機のようなものと思って差し支えありません。
図にするとこのような形になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70291/cab934b0-c4ac-e9c0-e6e6-79e432104c93.png)

[公式のFAQ](https://docs.microsoft.com/ja-jp/windows/wsl/faq)にもあるように、WSLはLinux環境の完全再現をするものではありません。(可能な限りの再現はしていると思いますが)
>WSL は、Bash およびコア Linux コマンド ライン ツールを必要とするユーザーが Windows 上でそれらを実行できるようにすることを目的としたツールです。
WSL は、GUI デスクトップやアプリケーション (例: Gnome、KDE など) をサポートすることを目的として**いません。**

構造上、ファイルシステムの動作まで互換を取っているわけではないため、NTFSがロックをかけると、ファイルシステムの性質の違いから消すことが出来なくなるわけですね。WSLの互換レイヤーでは吸収ができません。

そのため、WSLはできない旨をこちらに通知してきますが、NTFSがロックしているときの返答パターンが用意されているわけもなく、「許可されていません」と若干食い違った返答が返ってきた。というわけです。

#最後に
似たような部分で詰まっている方の一助になれば幸いです。
syntax/colorsのafterに差分の独自ハイライトを追加する

# はじめに

既存のcolorschemeやsyntaxに差分のカスタマイズ設定を追加する方法を紹介します。


# afterについて

Vimで読み込まれる設定ファイルは`runtimepath`により設定されており、afterは設定の追加読み込み用途として末尾に設定されています。

```
Windowsの場合
(略),$VIM/vimfiles/after,$HOME/vimfiles/after
```

独自ハイライトを追加するために、今回はこのafterディレクトリに差分のsyntaxやcolorschemeを置いて対応してみます。


# afterに置くcolorschemeについて

追加用のcolorschemeは`after/colors/`ディレクトリに配置するのですが、オリジナルと同名のままでは`after/colors/`側だけが読み込まれオリジナルは読み込まれなくなってしまいます。
対策として、両者それぞれを読み込む独自コマンドをvimrcに追加します。

```vimscript
" vimrc
command! -nargs=1 ColorScheme call ColorScheme(<f-args>)
function! ColorScheme(scheme)
  execute 'colorscheme ' . a:scheme
  try
    execute 'colorscheme ' . a:scheme.'_after'
  catch
  endtry
endfunction
```

これで準備完了です。
追加用を`after/colors/`に配置する際は、ファイル名を`オリジナル名+_after`へリネームします。

# 真/偽を強調するハイライト

例として、Go言語にて真/偽を強調する為のハイライトをdesert colorscheme用に作成してみます。

設定後は下記のような見た目になります。
![hilight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51728/43646b6e-68bb-3583-5505-8b036ff57ce3.png)


ファイル構成

```
.vim/after
├── colors
│   └── desert_after.vim
└── syntax
    └── go.vim
```

各設定

```vimscript
" syntax/go.vim
syn keyword goNo false
syn keyword goYes true

syn match goNo /!=\?/ containedin=CONTAINED
syn match goYes /==\|!!/ containedin=CONTAINED
syn match goNoWrong /!==\|!!!/ containedin=CONTAINED
syn match goYesWrong /===/ containedin=CONTAINED

hi link goNo No
hi link goYes Yes
hi link goNoWrong Error
hi link goYesWrong Error
```

```vimscript
" colors/desert_after.vim
hi No guifg=#ff7777 guibg=#773838
hi Yes guifg=#9999ff guibg=#383888
```

あとはcolorscheme変更の際は`ColorScheme`コマンドを利用すればOKです。


# まとめ

colorschemeは気に入ってるが少しカスタマイズしたい、て時に新たにcolorschemeを作るのは少々大げさになってしまいます。
本記事はcolorschemeもafterディレクトリへの差分設定だけで済ませる方法の紹介でした。
.gitignore以外でコミットしないファイルを設定する

# what
- `.gitignore`以外でコミットしないファイルを設定する方法を記載する


# why
- よく忘れて調べてしまうため、個人メモ
- 公式ドキュメントにも載っていたりする
    - [ファイルを無視する](https://docs.github.com/ja/get-started/getting-started-with-git/ignoring-files)


# how

- リポジトリ内の`.git/info/exclude` ファイルにコミットしたくないファイル名を追加する

### 記入例

```exclude
 git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
hogehoge-lock.json
hogefile
hogefile.lock
```
手動で単回帰分析をしてみようと思った　-1-

#はじめに
回帰分析の理論の理解を深めるために、回帰分析の強力な武器であるsklearnライブラリを用いずに手動で分析モデルを作ってみる。

#回帰分析とは？
説明変数(入力データ)を用いて、目的変数(出力データ)の値を予測すること。今回は理論的に求めるため、簡単な説明変数1つの場合を考えてみる。(単回帰)

#Pythonでの前準備
##▼データを用意
```python
import numpy as np
import pandas as pd
from pandas import DataFrame

data_age = np.array([20,20,28,38,33,34,22,37,
                     26,21,22,39,31,29,38,35,
                     32,27,30])

data_salary = np.array([410,500,480,710,630,600,430,
                        690,500,410,490,800,550,550,
                        700,700,650,540,600])

data = DataFrame({'年齢':data_age,
                  '所得':data_salary})
```

#データの関係
上記のデータセットから以下のようなグラフを得ることができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502084/a23e8069-6e78-7fc3-f296-7fa97e22b129.png)

このグラフから年齢と所得の関係を一次式で表してみることにする。(無理やり一次式に持っていくが、本当はもっと複雑な式になる。)

とりあえず予測される年齢をx、所得をyとおいて、```y = ax + b```と表すことを考える。
ここでデータが複数あることから単純にはaとbの値が決まらない事に注意する。最も妥当なaとbの値を算出するため、平均2乗誤差という考え方を用いる。
具体的には、```y = ax + b```を各データについて、予測(回帰)する所得yとの差を取って
```y - 410= 20a + b - 410```
```y - 500= 20a + b - 500```
```y - 480= 28a + b - 480```
...
と変形する。
この実データと予測データの値の差の2乗を、用意したデータ分(N個)だけ足し、その平均を取った値が平均2乗誤差Q(a,b)である。

```math
Q(a,b) = \frac{1}{N}\sum_{k=0}^{n-1}(ax_k + b - y_k)
```
この```y_k```は実データとしての所得のことである。平均2乗誤差Q(a,b)が一番小さくなるようなa,bを求めることで年齢と所得の関係を一次式化してみることにする。

#平均2乗誤差のグラフ
まず、Q(a,b)が一番小さくなるようなa,bを求めるためにaとbに様々な数値を入れて、平均2乗誤差の概形を書いてみる。

```python
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

#任意のa,bを用意
a = np.linspace(-200,200,100)
b = np.linspace(-500,500,100)

#aとbの組み合わせが簡単に作れるよう
#それぞれを2次元配列に拡張(曲面を書くのに必要)
A,B = np.meshgrid(a,b)

#Qの計算用の関数
def calc_Q(x,y,a,b):
    result = (a * x + b - y)**2
    return np.mean(result)

#Q用の配列(0で初期化しておく)
Q = np.zeros([len(a),len(b)])

#a,bの全ての組み合わせでQを計算
for j in range(100):
    for k in range(100):
        Q[j,k] = calc_Q(data_age,data_salary,a[j],b[k])

#3次元グラフの概形を書く
fig = plt.figure(figsize=[10,10])
ax = fig.add_subplot(111,projection="3d")
ax.view_init(45,10)
ax.set_xlabel("a",size=14,color="blue")
ax.set_ylabel("b",size=14,color="blue")
ax.set_zlabel("Q",size=14,color="blue")
ax.plot_surface(A,B,Q,color="red")
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502084/bbdd0caf-e234-e7c2-adad-d0c61546f405.png)

グラフからa=50～200,b=0付近でQ[a,b]の値が最小になっている事が分かる。このグラフから恐らく極小値が一つであることが分かる。よって、再急降下法(傾きを利用した極小値の算出手法)を用いて、Q[a,b]の値が最小になるときのa,bの値を求めてみる。

続く。

#参考
Python 数値計算入門
https://python.atelierkobato.com/mse/
サイバーボランティアの意義

#最近思っていることをまた書かせていただきます。
##自分たちはどのように活動しているのか。
実は岐阜県からCode for Gifuは支援を受けて活動しています。
実際パソコン知ってるから儲かるんじゃないのって言う人多いと思いますが。
みんな手持ちのモバイルで作業していること多いです。
自分も最近自分のお金でiPadのキーボードやMacBookAirを買ってます。
みんな自分のパソコン持ち込んで作業しているのです。
ですのでいらない誤解をしないでいただきたいと書かせていただきます。
施設も自分たちで借りて作業していたりします。
いわばJAWSや日本Androidの会やCode Forブリゲード組織の会合やIT勉強会も自分たちと同じで自分で会場を準備するのです。
なので自己負担額が多いです。
馬鹿にはできません。
##何故続けるの？
それは人が必要としているからです。
だからこそ動きます。
体が疲れてようが何してようが動いてナンボです。
みんなに必要とされるからこそ動けるのであってお金は今のところ一銭ももらっておりません。逆に出てく方が多いです。
潰れた日本Androidの会支部や潰れていったCode for ブリゲード組織などを今まで見てきました。
だからこそ言えることは教える人がいなかれば誰も動かんのです。
Actions on GoogleでUserStorageAPIを使ってデータを保存・取得する

### なにをしたか
Actions on Googleで、データベースを使うことなく会話・セッション間でも値の受け渡しができるようにしました。[contexts](https://cloud.google.com/dialogflow/docs/contexts-fulfillment?hl=ja)だと、セッション間で値がリセットされていしまいます。。


### なにを使ったか
https://developers.google.com/assistant/conversational/webhook/reference/rest/Shared.Types/AppResponse#FIELDS.user_storage
こちらのActions on Googleが提供してくれているUserStorageAPIというアクションごとのデータ保存領域を使うことで、会話をまたいでデータを保存しておけます。

### どんな風に使うか
ver.2のコードで、conv.user.storageという風にかくだけでOK。便利！

```node.js
app.intent("...", conv => {
    // ユーザーストレージのpageに書き込み
    conv.user.storage.page = 1;
    // ユーザーストレージのpageから読み取り
    const page = conv.user.storage.page;
});
```

### リセットしたいとき
```node.js
conv.user.storage = {}; 
```

こちらをかくだけでstorageの中身がリセットできます。
JavaでExcelデータの取り込み3

またもや前回の続きでApachePOIです。
https://qiita.com/Mk-4000/items/5d52b4b92ed5f8bf23f5

#今回の内容

前回はセルタイプごとの取得方法を書いていましたが、
**CellType.FORMULA(数式タイプ)**
のときのメソッド
**getCellFormula()**
ではセル内の数式そのものがString型で取得できることがわかりました。
ではその数式の結果が欲しいときは？
と言ったときの対象方。

#具体的にどうするか
色々とどうにかできないものか探してこちらの方の記事を参考にしました。
http://shin-kawara.seesaa.net/article/159878953.html

**FormulaEvaluatorインターフェイス**
と言うものがありました。

これは数式セルを評価する。値にする。といったもので、要は計算後の値にするために色々助けてくれるものです。

また、
**CreationHelperインターフェイス**
も使用するそうです。
こちらは、具象クラスのインスタンス化を処理するオブジェクト。
感覚的にはPOIのオブジェクトを色々生成してくれるやつと思ってます。

この2つを準備して、
1.WorkbookオブジェクトからCreationHelperを用意(getCreationHelper())
2.CreationHelperを通してFormulaEvaluatorも生成(createFormulaEvaluator())
3.対象cellをFormulaEvaluator.evaluateInCell()を使用して、計算しちゃう

といった流れです。

##FormulaEvaluator.evaluateInCell(cell)
引数にセルを入れて引数に含まれるセルの数式を評価、計算してしまいその結果を返すメソッド

これを使えば数式でも計算後の値が取れるそうです。

##実装結果
```SamplePOI3.java
    private static String getCellStringValue(Cell cell) {
        String retStr;

        CellType cellType = cell.getCellType();
        switch (cellType) {
        case STRING:
            retStr = cell.getStringCellValue();
            break;
        case NUMERIC:
            retStr = String.valueOf(cell.getNumericCellValue());
            break;
        case BOOLEAN:
            retStr = String.valueOf(cell.getBooleanCellValue());
            break;
        case FORMULA:

            //関数結果を取得
            Workbook wb = cell.getSheet().getWorkbook();
            CreationHelper ch = wb.getCreationHelper();
            FormulaEvaluator fe = ch.createFormulaEvaluator();
            retStr = String.valueOf(getCellStringValue(fe.evaluateInCell(cell)));

            break;
        case ERROR:
            retStr = String.valueOf(cell.getErrorCellValue());
            break;
        default:
            retStr = "";
            break;
        }
        return retStr;
    }
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494387/49da4f48-0460-83d2-c6f4-eede2f0fcbff.png)

```samplePOI3.result
1.0
2.0
3.0
```
Node.jsとnpmのインストール方法　駆け出しWebデザイナーの学習録

# はじめに

２回目の投稿になります。
Webデザイナーとして未経験で入社して3ヶ月が経過しました。
どうすれば主要クライアントのプロジェクトにアサインしてもらえるかと先輩エンジニアの方に質問したところ、サーバーサイド周りのNode.jsやnpmの知識がないとアサインできないとのことでした。
そこで今回は学習した内容を簡単にまとめようと思います。

※この記事は環境構築の最初の段階のみになるので、gulpインストールしたり、gulpfile.jsでタスクを記述していく部分に関しては改めて投稿しようと思います。

# Node.jsとは
本来ブラウザ側で使用する言語であるJavaScriptがNode.jsの登場によってJavaScriptでサーバーサイドの処理・制御をプログラムすることができるようになった。
Node.jsはWebサイトやWebアプリケーション、スマホアプリ開発で使用されている。
またJavaScriptだけでサーバー環境を構築したり、膨大なデータを処理・制御することができるようになった。

## Node.jsのメリット
- 非同期通信による高速な動作
- 大量をデータ処理が可能に
- メモリの消費量が少なく、また処理速度も速い

# npmとは
npmとはNode Package Managerの略で、言葉の通りでNode.jsのパッケージを管理（マネージ）するためのツールである。

Node.jsにはブラウザ上で動くJavaScriptライブラリや便利なプラグインが用意されていて、それらを管理することができる。（例えば、プラグインをフォルダに直接追加するなど）

npmをインストールすることで、例えばタスクランナーのGulp/Grunt、モジュールバンドラーのwebpackなどをnpmでインストールして、npmで様々な操作を行うことができる。

# npmをインストール
タイトルにはNode.jsとnpmのインストール方法と記載していたが、npmはNode.jsをインストールすることで自動的にインストールされる。

▼ Node.js公式サイト　
https://nodejs.org/ja/

↑こちらのサイトからNode.jsの最新バージョンをインストールすることができる。

※Node.jsをインストールする方法はnodebrewというnodeのバージョンを管理、切り替えするためのツールを先にインストールしておくことでも可能であるが、今回その説明は行わない。


## Nodeがインストールされているか確認
Node.jsがインストールされているかもコマンドラインから確認することができる。

```
$ node -v
```

追加されていれば、`v8.4.0`のようにバージョン名とともに確認することができる。

## npmがインストールされているか確認
npmがインストールされているかもコマンドラインから確認することができる。

```
$ npm -v
```

このコマンドラインを実行することで、npmがインストールされているか、またnpmのインストールされているバージョンを確認することができる。
コマンドを実行すると、`6.13.4`のようにバージョンが表示されるので、npmがインストールされていることを確認できる。



## 既存プロジェクトのパッケージを一括インストールする方法


```
$ npm install 
```

GitHubからNode.jsが採用されているプロジェクトフォルダをクローンしてきたとしても、自分のマシンには同じ開発環境が構築されていない。

プロジェクトで使用されているパッケージを一から追加していくことも可能ではあるが、大変手間であるしバージョンを統一させる必要があるなど面倒でミスも発生する可能性がある。

そこで**npm install** コマンドを実行するだけでそのプロジェクトで追加されているプラグインをそのままローカル環境に追加することができる。


# package.jsonとは
ここでいきなりpackage.jsonというワードが出てきたが、package.jsonとはnpmプロジェクトの情報を管理しているファイルである。
ここにnpmプロジェクトの情報やnpmでインストールしたパッケージ情報を管理する。

# package.jsonファイルを作成
package.jsonファイルはnpmで作成することができる。


```
$ npm init
```

`npm init`とコマンドを実行することでpackage.jsonファイルを作成する前にプロジェクトの情報を入力を促される。
トレーニングとしてpackage.jsonファイルを作成するなら全てエンターキーを押してしまっても良い。

ちなみに`npm init`によってpackage.jsonが作成される場所は現在のコマンドライン上にいるディレクトリに作成されるので、プロジェクトのディレクトリに移動してから`npm init`のコマンドを実行するのが良い。



### 現在のどのディレクトリにいるのか確認するコマンド
package.jsonを作成する前に現在どのディレクトリにいるのか確認するためには下記のコマンドを実行する。

```
$ pwd
```

これで現在のディレクトリを確認することができる。



### プロジェクトフォルダへ移動するコマンド
プロジェクトフォルダへ移動するためには下記のコマンドを実行する。

```
$ cd プロジェクトフォルダ
```

すでにプロジェクトフォルダを作成している場合は、直接コマンドライン上にそのフォルダをドラッグ&ドロップすることでディレクトリがコマンドラインに表示される。

cdとはchange directoryの略である。コマンドはこのように省略されていることが多く、ただの文字だと覚えるのが難しいので略称前の意味を覚えることで自然とインプットすることができると思います。


# 最後に
かなり中途半端な終わり方になったと個人的にも思っているが、タスクランナーのgulpを導入する方法なども含めて改めて記事をまとめようと思う。

また今回はNode.jsを公式サイトから直接インストールする説明のみであったが、個人的にはnodebrewを使用してNode.jsをインストールしてきたので、そこらへんの説明もまた時間を見つけて追加していこうと思う。

フロントエンドエンジニアの道はまだまだ険しい...
yarnのaliasおすすめ設定

# 参考

[node.jsの初歩から実践までが良く分かりました！](https://amzn.to/2ZQuDOT)


# npmを使い始めて３日目、さっそくyarnに変更しちゃいました！

**変更理由**
1.yarnのほうがnpmより打ちやすい
　・これは個人の問題
2.コマンドが簡潔
　・[yarn usage](https://yarnpkg.com/ja/docs/usage)
3.パフォーマンスが高い
　・[ベンチマーク結果はこちら](https://qiita.com/jigengineer/items/c75ca9b8f0e9ce462e99)
4.npmと互換がある
　・[npmとyarnのコマンド早見表](https://qiita.com/rubytomato@github/items/1696530bb9fd59aa28d8)
5.facebook製
　・[Company Info | About Facebook ](https://about.fb.com/company-info/)
6.まだnpmに愛着がない


# yarn

## 要点
yarnへの移行に伴う副作用を最小限にするためコマンド文法を統一することにした。
俺の感覚では`install`と`add`の意味は次のようになる。

`install`
[・まとめてパッケージを追加する](#まとめてパッケージを追加する)
・`セット注文`のようなもの
　・ハッピーセットください！
`add`
[・個別に１つパッケージを追加する](#個別に１つパッケージを追加する)
・`単品注文`のようなもの
　・ハンバーガー単品でください！

※注意点
**yarnではinstallはpackage.jsonがないと行えない。installとaddを区別している。**


### 簡単と単純はちがう

yarnのinstallはpackage.jsonを元にインストールされます。少し使っていれば気づくと思います、なんでもかんでもinstallのみで**簡単に**やってのける**npm**はパッケージ管理としてイマイチだなあと。yarnはきちんと区別しているので混乱することがありません。


### globalオプションの文法が少し違う

globalはinstallのまえに書く
```
[正しい]
npm install global
yarn global add
[間違い]
globalというバッケージもインストールしてしまうことになる
yarn add global　パッケージ名
```

## alias設定

yarn流にnpmのaliasも設定する。


#### まとめてパッケージを追加する

```terminal:package.json通りにパッケージをインストール
[ローカル]
alias ni='npm install'
alias yi='yarn install'
```


#### 個別に１つパッケージを追加する

```terminal:パッケージを個別に１つ追加する
[ローカル]
alias na='npm install'
alias ya='yarn add'
[グローバル]
alias nga='npm install -g'
alias yga='yarn global add'
```

#### devオプション

[devDependencies]
npm  : `--save-dev` 
yarn : `--dev`


#### アンインストール

yarnはオプション指定なしで勝手に見つけて削除してくれます。楽ちんですね。
npm  : `uninstall --save-dev パッケージ名`
yarn : `remove パッケージ名`


#### その他

```terminal:その他
# yarnのaliasを確認
alias agy='alias | grep yarn'


# その他

alias yad='yarn add --dev'
alias yls='yarn list'
alias ygls='yarn global list'
alias yrm='yarn remove'
alias ygrm='yarn global remove'
alias yup='yarn upgrade'
alias ygup='yarn global upgrade'
```


# まとめ

```
# alias確認
alias agy='alias | grep yarn'


# ローカル

alias yi='yarn install'
alias ya='yarn add'
alias yad='yarn add --dev'
alias yrm='yarn remove'
alias yup='yarn upgrade'
alias yls='yarn list'


# グローバル

alias yga='yarn global add'
alias ygrm='yarn global remove'
alias ygup='yarn global upgrade'
alias ygls='yarn global list'
```
Go言語でsalesforceを操作してみた

# はじまり
弊社では勤怠管理としてsalesforceを使用しており、日々の勤務時間と工数を個人で入力している。ただ1日1日の勤怠をブラウザからポチポチ入力するのはめんどくさい。そうだ、自動化しよう。

# やりたいこと
勤怠を記述したファイルを作成し、それをもとにsalesforceに自動的に入力する

# 採用した言語、ライブラリ
* Go言語
    * 興味があったから。ただそれだけ
* [agouti](https://agouti.org/)
    * WebDriverを使用してブラウザを操作するためのライブラリ

# 完成
https://github.com/shotasym/hack-salesforce

さっそく201912月分(とりあえず2日分)の勤怠を入力してみた。
用意したjsonファイルは以下の通り

```json:201912_works.json
[
    {
        "date": "2019-12-02",
        "start": "10:00",
        "end": "20:00",
        "projects": [
        {
            "code": "IRIxxx",
            "duration": "09:00"
        }]
    },
    {
        "date": "2019-12-03",
        "start": "10:00",
        "end": "19:00",
        "projects": [
        {
            "code": "IRIxxx",
            "duration": "08:00"
        }]
    }
]
```

実行

```bash
$ hack-salesforce --config_path=config.ini --jsonfile=201912_works.json
```

すると
<img width="512" alt="screencapture-teamspirit-ap6-visual-force-apex-AtkWorkTimeView-2019-12-20-18_39_40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537062/52f15f7c-042c-1a08-0945-f1942c178b4d.png">
:blush:

# やってみた感想
* 実際勤怠入力時間がかなり短縮されてよかった
* ただ正直golangでやる必要はなかったかなと思った
    * webdriverでの操作ならpythonとかでもできるし、goroutineとかgolangの強みとなる機能を使うことがなかった
vscode でsidebar, terminal, editer のフォーカスをvimっぽく移動する

# 環境

- vscode 1.41.1
- vscodevim 1.12.0
- macOS Mojave 10.14.6

# 目的

- sidebar とediter, terminal へのフォーカスの移動用ショートカットが欲しかった
- Vimっぽいキーバインドに設定する事で「あのショートカットなんだったけ...」を防止

# 方法

コマンドパレット開く(⌘P) > keybindings.json 検索 > keybindings.json に下記を記述

```:keybindings.json
[
    {
        "key": "ctrl+h",
        "command": "workbench.action.focusSideBar",
        "when": "editorTextFocus"
    },
    {
        "key": "ctrl+j",
        "command": "workbench.action.terminal.focus",
        "when": "editorTextFocus"
    },
    {
        "key": "ctrl+l",
        "command": "workbench.action.focusFirstEditorGroup",
        "when": "filesExplorerFocus"
    },
    {
        "key": "ctrl+k",
        "command": "workbench.action.focusFirstEditorGroup",
        "when": "terminalFocus"
    },
]
```

# 詳細

- editer を起点にして`ctrl + h` でsidebar にフォーカスを移動、`ctrl + l`で editer にフォーカス戻す
- editer を起点にして`ctrl + j` でterminal にフォーカスを移動、`ctrl + k` でediter にフォーカス戻す
- terminal からsidebar へ直接フォーカスを移動する設定は無し


# 備考 

ctrl キーで設定する場合はvscodevim の設定でctrl キーを有効にする

```:settings.json
  "vim.useCtrlKeys": true
```
本番サイトにウェブアクセラレータを導入した話

この記事は [さくらインターネット Advent Calendar 2019][0] 20日目の記事です。
[0]:https://qiita.com/advent-calendar/2019/sakura

# はじまり

とあるサイトにCDNを導入してほしいとの依頼があり、弊社サービスのウェブアクセラレータを導入することになりました。そのサイトは本番稼働中で今後トラフィックが増加するのでその前に対応したいとのことでした。引き受けたのは良いのですが、本番稼働中というのが気になります。。。

# 稼働中の環境

サイトはさくらのクラウド上で稼働していました。GSLBを使っておりサイトのドメインはGSLBへのCNAMEが設定されている状態です。（構成については[GSLBの概要](https://manual.sakura.ad.jp/cloud/appliance/gslb/index.html#id3)を参照ください。）

DNSは以下のような設定です。

| サイトドメイン | レコード種別 | 設定 |
|:-----------------|:------------------|:------------------|
| www.example.com  | CNAME             | xxxx.gslb1.sakura.ne.jp. |


# ウェブアクセラレータの導入方法

詳しくは[マニュアル][1]に記載されてるのですが、導入方法に3パターンあります。

[1]:https://manual.sakura.ad.jp/cloud/webaccel/manual/usage-guidance.html

1. 独自ドメイン利用
2. 独自ドメインに新しくサブドメインを作成して利用
3. サブドメイン利用

2、3の方法ではキャッシュしたいファイルのURLが変更になり、コンテンツの修正が必要でした。このため、今回は1の方法で導入することになりました。1の方法だとコンテンツを修正する必要がありません。

# 導入テスト

本番サイトに導入する前にまずテストサイトで動作を試してみます。ウェブアクセラレータの設定は概ね以下の通り進めました。

1.オリジンサーバ（ウェブサーバ）でCache-controlヘッダを設定
2.コントロールパネルからサイトを追加
3.コントロールパネルからサイトを有効化
4.DNSの設定

（詳しくは[初期設定（独自ドメイン利用）](https://manual.sakura.ad.jp/cloud/webaccel/manual/settings-domain.html)を参照ください。）

テストサイトでは以下のようにDNSを設定しました。

| サイトドメイン | レコード種別 | 設定 |
|:-----------------|:------------------|:------------------|
| test.example.com | CNAME             | xxxx.user.webaccel.jp. |

設定後にテストサイトへアクセスするとレスポンスヘッダに `x-cache: HIT` と付与されています。無事にウェブアクセラレータを利用できてるようです。

# 本番への導入

テストドメインで無事動作確認できたので、続いて本番に導入していきます。しかし、ここで問題が発生しました。

テストドメインと同様にオリジンサーバの設定、コンパネからサイトを追加と行なって、コンパネからサイトを有効化しようとした時にサイトが有効化できません。この状態ではウェブアクセラレータにリクエストが到達しても、もちろんリクエストは処理されません。


## サイトの有効化について

コンパネからサイトを追加するときに公開ドメイン名を登録するのですが、この公開ドメイン名の所有権を確認できた時に初めてサイトの有効化が行えるようになっていました。

所有権の確認は次のどちらかの方法で行えます。

1. 公開ドメイン名のCNAMEレコードを設定する
2. 公開ドメイン名のTXTレコードを設定する

テストサイトでは1の方法が使えたのですが、本番サイトはすでにCNAMEが設定されていてこの方法が使えません。またCNAMEを設定しているので2の方法も使えませんでした。

このままでは本番サイトへの導入時に数分のサイト断が発生してしまう状況です。やっぱり本番サイトの構成変更では何か起こりますよね。。。

## 解決

断を無くしたいなぁと考えていたところ、どこからともなく話を聞きつけたウェブアクセラレータの開発者が現れました。現在の構成を説明すると

開発者）あー、その構成だと断発生しちゃいますね
自分）そうですよねー
開発者）ちょっと待って他の開発メンバーと相談してみる
自分） お、お願いします。
開発者）有効にできるからサイト教えて
自分）これこれこのサイトです。（有効にできるだって？）
開発者）設定したから見てみて
自分）有効になってる！ありがとう

なんとも裏技的ですがサイトの有効化ができちゃいました、構成を説明しただけで解決までもっていってくれています。担当者が途中からまかせっきりですがいいんでしょうか？（今度何か奢っておこうと思います。）

# その後

## 導入作業

無事サイトの有効化が行えたので、導入作業はDNSの設定変更を行えば完了です。実際に↓のように切り替えました。

|| サイトドメイン | レコード種別 | 設定 |
|:------|:------|:------|:------|
|作業前| www.example.com  | CNAME             | xxxx.gslb1.sakura.ne.jp. |
|作業後| www.example.com  | CNAME             | xxxx.user.webaccel.jp. |

キャッシュするファイルやコンテンツしだいですが、導入後のウェブサーバへのリクエスト数は1/3に減りました。（対象のサイトは静的コンテンツがメインのサイトで、キャッシュに設定したのは画像ファイルやjsファイルです。）このサイトでは結果としてウェブアクセラレータの導入でウェブサーバの数が減らせるようになりました。

## 話の続き

今回の件を受けて、CNAMEで運用されているサイトにも導入しやすいように所有者のチェックについて機能追加が行われることになりました。サイトのサブドメインにTXTレコードを設定して所有者の確認が行えるようになるそうです。近々リリースされる予定なので同じような構成で困っておられた方はぜひ利用してもらえればと思います。

#### 2020年01月23日 追記

件の機能がリリースされていました！
[公開ドメインに既に別の CNAME レコードが設定されている場合](https://manual.sakura.ad.jp/cloud/webaccel/manual/settings-domain.html#step4-dns-txt)
GIthubにカレントディレクトリをプライベートでワンコマンドでぶん投げるシェルスクリプト

いままで一旦Webブラウザでリポジトリつくってーとかやっていたけれどもコマンド一発でGitHubまでアップできるスクリプトを組みました。
仕事ではこんな雑なgit作業はできないけれど、個人使いならありとおもいます。すくなくとも私の幸福度はあがりました。
hubコマンドについてはググってください。
oauth_tokenとか設定が必要です。(401喰らいます)

* (初回は)GitHubにリポジトリつくって
* コミットしてpushする

`-p`でプライベートリポジトリ作成なのでパブリックで作りたいときはコマンドの`-p`消してください。
`git-one-push`とかいうファイルにして実行権限与えて使います。
使い方としては作業が終わったら初回は`./git-one-push "<RepositoryName>" "<Commitコメント>"`、次回以降は`./git-one-push "<Commitコメント>"`でGitHubにプッシュまでしてくれ、そこそこ使えます。

`USERNAME変数`を適宜自分のものに変えてください

```bash
#! /bin/bash
############
# setting
############
USERNAME=yourname

############
# functions
############
function git_init() {
  git init
  REPONAME=$1
  if [ -z "$REPONAME" ]; then
    REPONAME=`date +"%Y%m%d%H%M%S"`
  fi
  hub create -p ${REPONAME} # publicにしたいなら-p消す
}
function git_commit_push() {
  MESSAGE=$1
  if [ -z "$MESSAGE" ]; then
    MESSAGE=`date +"%Y-%m-%d %H:%M:%S"`
  fi
  git add .
  git commit -m "$MESSAGE"
  git push --all
}

############
# main
############
cd `dirname $0`
if git rev-parse --git-dir > /dev/null 2>&1; then
  # git 管理中
  git_commit_push $1;
else
  # git 管理中ではない
  git_init $1;
  git_commit_push $2;
fi
hub browse
```
以上です。よろしくおねがいします。
Firebase firestoreのバックアップをCloudFunctionsで自動実行してみた

## はじめに

atma（あーとま）Advent Calendar 2019 25日目担当のこーたです。
今回はFirestoreを触った知見を共有したいと思います。

## 前提
Firestoreには自動バックアップ機能がありません。 <-これが結構痛い
そこでFirestore exportのAPIをCloud FunctionsのCloud Pub/Subで定期的に叩いてみました。

## 結論

簡単に実装出来ました。

```index.js
const functions = require("firebase-functions");
// 初期化
const admin = require("firebase-admin");
admin.initializeApp();
// 東京リージョンでデプロイ
const FIREBASE_REGION = "asia-northeast1";
const rp = require("request-promise");
const { google } = require('googleapis');
/**
 * Firebase Cloud Firestoreのバックアップ処理
 */
exports.backupFirestoreData = functions
  .region(FIREBASE_REGION)       
  .pubsub.schedule('0 3 * * *')  //ここで実行隔離を指定
  .timeZone("Asia/Tokyo")       
  .onRun((context) => {
    const projectId = 'projectId'
    const scopes = ['https://www.googleapis.com/auth/datastore', 'https://www.googleapis.com/auth/cloud-platform']
    const key = require(`./${projectId}.json`)  //jsonからGCSへのアクセス権を読み込み
    const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`
    const jwtClient = new google.auth.JWT(
      key.client_email,
      key.private_key,
      scopes,
    )
    jwtClient.authorize().then((credentials) => {
      //日付を取得
      require('date-utils');
      const date = new Date();
      date.setTime(date.getTime() + 1000 * 60 * 60 * 9); // JSTに変換
      const formatted = date.toFormat("YYYY_MM_DD_HH24_MI_SS");
      rp.post(url, {
        headers: { Authorization: `Bearer ${credentials.access_token}` },
        json: true,
        body: { outputUriPrefix: `gs://projectId.appspot.com/backup/${formatted}` }
      })
    });
    return null;
  })
```


## 必要パッケージ

Date 型を扱いやすくするdate-utilsを使っているのでインストールして下さい。

```shell
$ npm install date-utils
```
or


```shell
$ yarn add date-utils
```

## 解説

Firestore exportのAPIをCloud FunctionsのCloud Pub/Subで定期的に叩いています。

<img width="1207" alt="スクリーンショット 2019-12-24 16.54.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311701/80e542ac-bf8e-767e-cde9-1813590466c4.png">

### サービスアカウントとは

サービス アカウントは、個々のエンドユーザーではなく、アプリケーションや仮想マシン（VM）に属している特別な Google アカウントです。アプリケーションはサービス アカウントを使用して、ユーザーの関与を必要とせずに Google のサービス API を呼び出すことができます。


```
  const key = require(`./${projectId}.json`)  //jsonからGCSへのアクセス権を読み込み
```
この部分でサービスアカウントキーを読み込んでいます。


### バックアップ先

Firebase Cloud Storageのアドレスを指定しています。

```
  body: { outputUriPrefix: `gs://projectId.appspot.com/backup/${formatted}` }
```


バックアップしたものはこのような感じで保存されます。
<img width="348" alt="スクリーンショット 2019-12-24 16.55.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311701/4de65fe7-796f-4edb-9f52-cfa708faae7a.png">

※projectIdは本来envに記載するべき内容ですが、分かりやすいようにコードに記載しています。

## 最後に
上記コードではサービスアカウントキーのjsonを渡しています。

その他にApplication Default Credentialsという仕組みがあるみたいです。
https://cloud.google.com/docs/authentication/production?hl=ja
この仕組みを使えばサービスアカウントキーのjsonを渡さずに実装することが可能かもしれません。
次に触る機会がありましたら、この方法での実装も試してみたいです。

以上
Firebase firestoreのバックアップをCloudFunctionsで自動実行してみたでした！
ソースコード解析をやってみた

# きっかけ
今年、私が所属している[大学の部](https://oucc.org/)でアドベントカレンダーをやってみよう！という呼びかけがあったので、僕も参加してみました。(ほかの部員の記事は[こちら](https://adventar.org/calendars/4650)をご覧ください)
...で、何をしようか考えたのですが、単純に今の自分がやっていることを紹介しようかと思い、Javaソースコードの解析について書くことにしました。今回の記事に関しては、Javaという言語というよりもソースコードそのものを解析するということを目的としているので予めご了承願います。

# 概要
今回、タイトルに有るようにソースコード解析を行うわけですが、解析対象となるのは前述の通りJavaという言語です。更に有名なIDEであるEclipseと構文木であるAST(Abstract Syntax Tree)を作成するためのプラグインを用いてコードの解析を行います(詳しい手順は[こちら](https://sdl.ist.osaka-u.ac.jp/~s-kimura/jdtdoc/jdt.html)のサイトにも記載してあります)。

# クラス図
クラスの関連図をいかに示します。
![クラス図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436205/d4f65651-08ad-99b4-6d20-aa7fc1d1b7bd.png)

かなり簡易的な図となるので、今後さらに拡張していきたいと思います。

# 実行
とりあえず、出力結果としては、各装飾子の情報を出力することができました。

# 今後の展望
今回の結果を用いて、最終的には、ソースコードを解析して、「privateなメソッドやpublicなメソッドがあるけど、開発者はどのような順番でそういったメソッドを開発・定義しているのかを分析していきたいと思います。

# 最後に
これは、アドベントカレンダーがあるからということで書きましたが、時間がないため非常に簡易的なものになりました。今後のプロジェクトの進展などは「GitHub」の[私のページ](https://github.com/kotoozi/method-modifier-check)を閲覧してください。

では( ・ω・)ノシ
AMPでAPIで取得した動的なリストを表示するのに必要なこと

##必要なライブラリ

```
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
```

##HTML

```
<amp-list
src="xxxxxxxxxx"
height="170"
layout="fixed-height"
binding="no">
<template type="amp-mustache">
  <amp-carousel height="170" layout="fixed-height" type="carousel">
    {{#values}}
      <div>
        <a
          href="{{url}}"
          <amp-img
            src="{{imageUrl}}"
            width="400"
            height="400"
            layout="responsive"
            alt="{{imageName}}">
          </amp-img>
        </a>
      </div>
    {{/values}}
  </amp-carousel>
</template>
</amp-list>
```

##API

```
{
	"items":[
		{
			"values":[
				{
					"url":"https://xxxxxx/xx/xx/",
					"imageUrl":"https://xxxxxx/image1.jpg",
					"imageName":"画像ファイル名1"
				},
				{
					"url":"https://xxxxxx/xx/xx/",
					"imageUrl":"https://xxxxxx/image2.jpg",
					"imageName":"画像ファイル名2"
				},
				{
					"url":"https://xxxxxx/xx/xx/",
					"imageUrl":"https://xxxxxx/image3.jpg",
					"imageName":"画像ファイル名3"
				}
			]
		}
	]
}
```

##TIPS

####GoogleにキャッシュされたAMPページからクロスドメイン対応したAPIが呼び出せるようにレスポンスヘッダーに以下を追加

- Access-Control-Allow-Origin: *
- Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"

####AkamaiなどのCNDを利用している場合は、CDN側でCORSの設定が必要になる
![GUID-82142BB3-106C-41BE-84D2-5C8D51A194E6-low.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23815/7733be01-0e3a-4a54-1a3e-4a03ae579bb6.png)

参照
https://learn.akamai.com/en-us/webhelp/media-services-live/upgrade-msl-3x-or-4-streams-to-msl-4x/GUID-4C33655C-F489-4692-AE90-08A2F4005CF8.html
webpack NODE_ENV でハマった話

## 背景

`NODE_ENV`の値で分岐を行いたいと考えていました。
しかし、何を設定しても起動すると`production`となる...

## 調査

調査用に、下記のようなコードを追加

```js
console.log(`current env => ${process.env.NODE_ENV}`)
```

webpackしてみると出てきたコードは

```js
console.log("current env => production")
```

まさかの変換されてしまってました。
どうやら`webpack.config.js`で指定した`mode`の値が代入されてしまうようです。


## 解決策

`optimization.nodeEnv`に`false`を設定する。

```webpack.config.js
module.exports = {
  mode: 'production',
  // ここを追加
  optimization: {
    nodeEnv: false
  },
  // 省略
}
```
Gitのコミットハッシュを環境変数としてVue側で取得する

# やりたかったこと

リモートにpushするとサーバ側にデプロイされるようなVue案件で、開発中に気づいたらサーバ側にデプロイされていないということが度々ありました。デプロイ状況を確認する方法は一応あるはあったものの、もう少しシンプルに確認が出来ないかと思った所、[こちら](https://qiita.com/mori-dev@github/items/f9106a829ea2576b6a71)の記事を見てGit上のHEADのハッシュが取得する方法があるとのことでした。

これなら確認も容易そうと、社内の人と相談して取得してみることに。

# あかんかったパターン

特にこれといって難しいことではなさそうだったので、愚直にそのまま実装します。

## `package.json`で環境変数を埋め込む

`serve`、`build`コマンドに`HEAD`のハッシュを取得して`GIT_COMMIT_HASH`として環境変数を埋め込むようにします。

```json:package.json
...
"scripts": {
    "serve": "GIT_COMMIT_HASH=$(git rev-parse HEAD) vue-cli-service serve",
    "build": "GIT_COMMIT_HASH=$(git rev-parse HEAD) vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
...
```

js側で埋め込んだ環境変数を拾いに行きます。直接参照してもいい気はしますがなんとなくお行儀が悪い気がするので、一旦定数に入れます。

```js:Vue側で取得して定数に入れる

const GIT_COMMIT_HASH = process.env.GIT_COMMIT_HASH;
```

```Vue:定数をimportしてテンプレートで参照
<template>
  <div>
    GIT : {{ hash }}
  </div>
</template>

<script>
import { GIT_COMMIT_HASH } from "@/constants";
export default {
  data() {
    return {
      hash : GIT_COMMIT_HASH
    }
  }
}
</script>

```

ところがこのやり方ではnpm起動時では落ちはしないものの、ハッシュ値の取得は出来ませんでした。

```text
GIT : 
```

# ちゃんと取れたパターン

`.env`に定義した環境変数をVue上で扱うには`VUE_APP`を接頭語としてつける必要があるというのは認識していたので、それ以外の環境変数は接頭語なしに参照出来るという認識だったのですが、どうもそうではないようです。`NODE_ENV`が取得出来ていたのでそう思い込んでいましたが、こいつが例外なだけの様子…。

というわけで埋め込む環境変数名を`GIT_COMMIT_HASH`から`VUE_APP_GIT_COMMIT_HASH`に変更します。

```js:VUE_APPつけた
...
"scripts": {
    "serve": "VUE_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) vue-cli-service serve",
    "build": "VUE_APP_GIT_COMMIT_HASH=$(git rev-parse HEAD) vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
...
```

```js:定数側も合わせて修正

const GIT_COMMIT_HASH = process.env.VUE_APP_GIT_COMMIT_HASH;
```

環境変数の変更を反映するため、この形で`serve`をしなおします。

```text
GIT : 2c395a98e60bd2f64ef44dacda03f596f206a492
```

無事にほしかった値が取れました！何気に今年一番感動した気がします。

`public/index.html`からの参照も問題なく出来ました。ローカルではHEADが移動するごとに`serve`しなおす必要がありますが、デプロイ時はpushする度にbuildされるためその点を気にする必要がないため、`cachebusting`としても使えそうです。

恐らくVue以外では最初に失敗したパターンで問題なく取れるんだろうとは思いますが、微妙にハマってたので備忘録として残しておきます。