OmniAICreator/Qiita-1.07M huggingface dataset:
AWS日記13 (Textract)

# はじめに
今回は Amazon Textractを利用してテキスト抽出機能試します。

[今回作成したAmazon Textract のテキスト抽出機能を試すページ](https://labo.systems/textract)

# 準備
[Lambda , API Gatewayの準備をします。]
(https://qiita.com/tanaka_takurou/items/3f93295de6cff060ec09)

[Amazon Textractの資料]
[Amazon Textract](https://aws.amazon.com/jp/textract/)

※ 2020年6月時点で、Textractは 「アジアパシフィック (東京)」 リージョンで利用できないため 「米国西部 (オレゴン)」 リージョンで試しました。

# WEBページ・API作成
GO言語のAWS Lambda関数ハンドラー aws-lambda-go を使用してHTMLやJSONを返す処理を作成します。
また、Textract を使用するため aws-sdk-go を利用します。

[参考資料]
[AWS SDK for Go API Reference](https://docs.aws.amazon.com/sdk-for-go/api/service/textract/)
[Amazon Textractを試してみた](https://qiita.com/windows222/items/07c3683c052d6e2bb6a4)
[Amazon Textract（OCR）についてまとめてみた](https://qiita.com/n_oshiumi/items/53d0ad1d95c9c11aa2fd)



##### テキストを抽出するには AnalyzeDocument を使う。

```golang:main.go
func analyzeDocument(img string)(string, error) {
        b64data := img[strings.IndexByte(img, ',')+1:]
        data, err := base64.StdEncoding.DecodeString(b64data)
        if err != nil {
                log.Print(err)
                return "", err
        }
        svc := textract.New(session.New(), &aws.Config{
                Region: aws.String("us-west-2"),
        })

        input := &textract.AnalyzeDocumentInput{
                Document: &textract.Document{
                        Bytes: data,
                },
                FeatureTypes: []*string{aws.String("TABLES")},
        }
        res, err2 := svc.AnalyzeDocument(input)
        if err2 != nil {
                return "", err2
        }
        if len(res.Blocks) < 1 {
                return "No Document", nil
        }
        var wordList []string
        for _, v := range res.Blocks {
                if aws.StringValue(v.BlockType) == "WORD" || aws.StringValue(v.BlockType) == "LINE" {
                        wordList = append(wordList, aws.StringValue(v.Text))
                }
        }
        results, err3 := json.Marshal(wordList)
        if err3 != nil {
                return "", err3
        }
        return string(results), nil
}
```



# 終わりに
今回はAmazon Textractを試しました。
AtCoderBeginnerContest172復習＆まとめ（前半）

# AtCoder ABC172
2020-06-27(土)行われたAtCoderBeginnerContest172の問題をA問題から順に考察も踏まえてまとめたものとなります．
前半ではABCDまでの問題を扱います．
問題は引用して記載していますが，詳しくはコンテストページの方で確認してください．
[コンテストページはこちら](https://atcoder.jp/contests/abc172)
[公式解説PDF](https://img.atcoder.jp/abc172/editorial.pdf)

## A問題　Calc
> 問題文
> 整数$a$が入力されます。値$a+a^2+a^3$を出力してください。

```python:abc172a.py
a = int(input())
print(a + a**2 + a**3)
```

## B問題　Minor Change
> 問題文
> 文字列$S,T$が与えられます。次の操作を繰り返して$S$を$T$に変更するとき、操作回数の最小値を求めてください。
> 操作：$S$の$1$文字を選んで別の文字に書き換える

for文で前から一文字ずつ合っているかどうか確認しました．

```python:abc172b.py
s = input()
t = input()
count = 0
for i in range(len(s)):
    if s[i] != t[i]:
        count +=1
print(count)
```

## C問題　Tsundoku
> 問題文
> 二台の机 A, B があります。机 A には$N$冊の本が、机 B には$M$冊の本が、それぞれ縦に積まれています。
> 机 A に現在上から$i$番目に積まれている本$(1 \leq i \leq N)$は読むのに$A_i$分を要し、机 B に現在上から$i$番目に積まれている本$(1 \leq i \leq M)$は読むのに$B_i$分を要します。
> 次の行為を考えます。
>　・本が残っている机を選び、その机の最も上に積まれた本を読んで机から取り除く。
> 合計所要時間が$K$分を超えないようにこの行為を繰り返すとき、最大で何冊の本を読むことができるでしょうか。本を読むこと以外に要する時間は無視します。

とりあえず，再帰で解こうと思いましたが，実行時間に引っかかるのが明らかだったので，いろいろ工夫を凝らしてコード書きました．
解説にpythonの参考コード載ってて，こんなにシンプルに書けるようになりたいなと思いました．

```python:abc172c.py
n, m, k = map(int, input().split())
a_list = list(map(int, input().split()))
b_list = list(map(int, input().split()))
new_a_list = [[0, 0]]
a_sum = 0
for i in range(0, n):
    a_sum += a_list[i]
    if a_sum <= k:
        new_a_list.append([i + 1, a_sum])
    else:
        break
best = len(new_a_list) - 1
b_sum = 0
a_sum = new_a_list[-1][1]
a_count = new_a_list[-1][0]
flag = 1
for i in range(0, m):
    b_sum += b_list[i]
    while True:
        if b_sum <= k - a_sum:
            if best < i + 1 + a_count:
                best = i + 1 + a_count
            break
        if a_count == 0:
            flag = 0
            break
        a_count -= 1
        a_sum = new_a_list[-(len(new_a_list) - a_count)][1]
    if flag == 0:
        break
print(best)
```

## D問題　Sum of Divisors
> 問題文
> 正整数$X$に対し、$X$の正の約数の個数を$f(X)$とします。
> 正整数$N$が与えられるので、$\sum_{K=1}^{N}K×f(K)$を求めてください。

圧倒的数学力不足（汗）
解けなかったので，解説見て書いてあることそのまま実装したら解けました．

```python:abc172d.py
n = int(input())
total = 0
for j in range(1, n + 1):
    x = j
    y = n // x
    total += y * (y + 1) * x // 2
print(total)
```

実装はシンプルだけど思いつかなかったし，そもそも実行時間制限: 3 sec 見落としてた．（見落としてなくても解けないと思うけど）

前半はここまでとなります．
前半の最後まで読んでいただきありがとうございました．

後半はEF問題の解説となりますが，時間的に記事作成できないと思います（汗）．
htmlの用語説明

dl要素description listの略
dt要素description termの略
dd要素description definitionの略

使い方

```
<dl>
  <dt>用語１</dt>
  <dd>説明１</dd>

　<dt>用語２</dt>
  <dd>説明２</dd>
</dl>
```
・結果
用語１
　説明１
用語２
　説明２


tr要素table rowの略
td要素table data cellの略
th要素table headerの略

colspan要素column spanの略
Python3 エンジニア認定基礎試験 受験記

#事前知識
Pythonを2020年1月くらいぼちぼちやっていて形が欲しかったので受験しました。
実際に集中して取り組んだのは、6月初旬からです。

#試験情報
下記サイトになりますが、オライリーの本がベースとなって出題されています。
[Pythonエンジニア認定試験](https://cbt.odyssey-com.co.jp/pythonic-exam.html)
出題情報も載っていますので、必ずチェックするべきです。

#資格勉強で使用したもの
- [スッキリPython](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BPython%E5%85%A5%E9%96%80-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%9B%BD%E6%9C%AC%E5%A4%A7%E6%82%9F/dp/4295006327)
- [Pythonチュートリアル](https://aoten.jp/store/detail.html?no=a1800i_k160324)
- [DIVE INTO EXAM](https://exam.diveintocode.jp/exam)

#勉強期間
1月～3月は事前にスッキリPythonを使って勉強しました。その他にもWebAppをFlaskを使って作ったりしました。
4月から5月は他の試験勉強を集中的に行っていましたが、6月で仕上げました。
Pythonチュートリアルは1周だけしてモジュール等確認し、
その後はDIVEINTO EXAMを使って模擬試験を4周して定着させました。
最後にはDIVE INTO EXAMで900点を超えていました。

#受験時
[持ち物](https://cbt.odyssey-com.co.jp/attention.html)は下記3点です。
- Oddesey IDとパスワード
- 身分証明書
- 受験票(会場によっては不要)

実際に受験しましたが、このご時世なので、試験会場は間隔を空けていました。
ただ、スクールもやっているところでの受験で扉も空いており、声が聞こえてきました。
静かでないと集中できない人は気をつけるべきです。

#実際に受けた感想
正直、すごく簡単でした。資格欲しい人はすごくおススメです。
アルゴリズムに不安がある人はさすがに難しいですが、
IT初心者のファーストステップの資格としてはかなりおススメです。
Unity で Automatically manage signing を行う

#はじめに

Unity & Xcode でビルドを作成する際に毎回忘れてしまう署名関連の備忘録として残しておこうと思います。

#Manual or Auto

『Certificates, Identifiers & Profiles』の署名関係のファイルなどを Xcode だけで出来るようになっています。
以前までは自前でポータルサイトにログインしてそれぞれのファイルを作成していましたが、今はそれが不要になっています。
エンタープライズ版の場合は * アスタリスクでどのアプリでも利用することができたのですが、今はそれを行う必要がなく Unity を利用する場合は Preferences と PlayerSettings に設定するだけです。

#Unity 側の設定

Unity 側には二箇所設定する項目があります。

##Preferences の設定

まずは Preferences ですが『Xcode Default Settings』という設定がありますが、それぞれ以下のような値を設定します。

- Automatically Sign にチェック
- Signing Team Id にポータルの Team ID を指定
- iOS/tvOS の Manual は利用しないのでそのまま

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/e7a264dd-790b-e5b6-09d3-a950489037e5.png)

Team ID はポータルのアカウントで『Membership』に記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/3d3394de-4443-9738-71a0-d2a86cf97897.png)

##PlayerSettings の設定

次はプロジェクトごとの PlayerSettings です。
『PlayerSettings > Other Settings > Identification』で以下のような値を設定します。

- Bundle Identifier に Bundle ID
- Signing Team ID に Team ID を指定
- Automatically Sign にチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/2d8e5e1e-c9d1-a2f7-156e-e1cca4096273.png)

Xcode Default Settings の値と同じにします。
まぁ、設定しなくてもデフォルト設定が利用されると思うのですが…。

#ビルド

Unity の設定を行いビルドを行います。
生成された Xcode プロジェクトを開いて『Signing & Capabilities』の設定を見るとちゃんと設定がされています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/89287359-b988-3029-3f1e-85e3a3fbae80.png)

ポータル側も以下のように証明書、プロファイルがそれぞれ登録されています。

『Certificates,Identifiers & Profiles > Certificates』にはビルドを実行した端末が登録されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/683d8c04-338a-3114-976a-89f51f0c8818.png)

『Certificates,Identifiers & Profiles > Identifiers』には『XC ＜Bundle ID＞』という ID が登録されます。
例えば『com.aaa.BBB』とした場合『XC com aaa BBB』という感じの ID です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19224/905ccc57-e59f-f7c8-8069-57b99e582e1d.png)

##注意

**~~Automatically manage signing を行う場合にポータルで同じ Bundle ID のプロビジョニングプロファイルなどの作成はしないようにしてください。もし、同じ Bundle ID が存在すると競合してしまいエラーになります。~~**
上記ですが Xcode で Revoke することで Manual で作成したものを取り消して Auto に切り替えることが可能です。

#Auto が絶対にオススメ

出来る限り Auto を選択することをオススメします。

理由はプロビジョニングプロファイルを管理する必要がなくなるからです。

手動の場合、プロビジョニングプロファイルをダウンロードしそれをローカルに保存する、また、有効期限も自分で覚えておかないといけないのですが、Auto の場合はその辺りは全て自動で行ってくれます。


#おわりに

とりあえず毎回忘れてしまう署名関連の処理。
Unity を使えば Unity の設定だけで済みますのでかなり楽になります。

一度 Manual ではなく Auto でビルドすることを検討してみてください。
【Rails Webpacker】Webpacker::MissingEntryErrorのエラーはNode.jsのバージョンに起因するかもしれない話

# 【Rails Webpacker】Webpacker::MissingEntryErrorのエラーはNode.jsのバージョンに起因するかもしれない話

## 結論から
Nodeのバージョンを13.7以上にしてあげると
app>public>packsが生成され、当該エラーが解決される

## 解決までのプロセス
普通に``rails new appname``でアプリを作成して
コントローラーやモデルの作成を行った後に、ブラウザでアプリをみてみると
このようなエラーが出る時がある。
<img width="717" alt="スクリーンショット 2020-06-27 18.50.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/718d26b5-a579-34e5-6560-f74f493491d1.png">

多数のサイトを見て、以下のコマンドを打ってみてもうまくいかない。

```termial:terminal
yarn
yarn install
yarn upgrade
brew install yarn
rails install yarn
rails webpacker:install
```
そして、webpackerのドキュメント READMEを読んでみると以下のコマンドが必要だとのことで、打ってみる

```terminal:terminal
# こちらの一行はGemfileに書く
gem 'webpacker', '~> 5.x'

gem 'webpacker', git: 'https://github.com/rails/webpacker.git'
yarn add https://github.com/rails/webpacker.git
yarn add core-js regenerator-runtime
```

この``yarn add ~``をしたときに、以下のようなエラーが出た。

```terminal:terminal
error browserslist@4.12.2: The engine “node” is incompatible with this module. Expected version “^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7". Got “13.5.0”
```

よってnodeのバージョンを13.7以上にしてみた。

まず
インストールできるNode.jsのバージョンを一覧で出力

```terminal:terminal
nodebrew ls-remote
```

Node.jsの環境（ディレクトリ構成など）を自動的にセットアップしてくれる「setup」コマンドを実行しておきます

```terminal:terminal
nodebrew setup
```

インストールできるNode.jsのバージョンを一覧で出力

```terminal:terminal
nnodebrew install-binary v13.8.0
```

特定のバージョンの使用を命令

```terminal:terminal
nodebrew use v13.8.0
```

以上によってnodeのバージョンを変えてあげると、当該エラーが消え、うまく画面が表示されるようになった！！

ターミナルを見てみると、

```terminal:terminal
 Compiled all packs in /Users/nakayama_kazuhito/Desktop/node-version/public/packs
```

どうやらnodeが結構public直下にある、webpack関連のファイルの生成に関与しているそう。
んーとりあえず、一旦解決！！
またおって原因分析をします！
それではまた！！☺️
[Elixir]文字列を一文字ずつsplitしたいとき

AtCoderで問題を解いているときのこと、
Elixirを使って文字列を一文字ずつsplitしたいことがあったので、書き方をメモしておこうと思います。


`String.codepoints`
https://hexdocs.pm/elixir/String.html#codepoints/1

```bash
iex(1)> String.codepoints("hogehoge")
["h", "o", "g", "e", "h", "o", "g", "e"]
```

別の関数に渡したいときは`|>`を使って

```elixir:placing_marble.ex
defmodule Main do
  def placing_marble(seq) do
    seq |> String.codepoints
        |> Enum.map(&String.to_integer(&1))
        |> Enum.reduce(0, &(&1 + &2))
  end

  def main do
    seq =  IO.read(:line) |> String.trim()
    IO.puts placing_marble(seq)
  end

end
```
ソースは下記の問題を解いたときのものです
[A - Placing Marbles](https://atcoder.jp/contests/abc081/tasks/abc081_a)
HerokuにBasic認証の導入【Spring Framework】


#成果物
<img width="628" alt="スクリーンショット 2020-06-28 17.22.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537759/891b69a1-fcaf-bbe5-9761-a1fbef59c6cd.png">

#準備

[Heroku公式ドキュメント](https://devcenter.heroku.com/articles/java-webapp-runner#deploy-your-application-to-heroku)

↑のHeroku公式ドキュメントにしたがって、Herokuデプロイの準備をすること。

```xml:pom.xml
・・・
<packaging>war</packaging>
・・・
<dependencies>
・・・
</dependencies>
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals><goal>copy</goal></goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>com.heroku</groupId>
                                <artifactId>webapp-runner</artifactId>
                                <version>9.0.30.0</version>
                                <destFileName>webapp-runner.jar</destFileName>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
```
※プロジェクトがwarでコンパイルされていること


```txt:Procfile
web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT --enable-basic-auth --basic-auth-user [ユーザー名] --basic-auth-pw [パスワード] target/*.war
```
単一コンテナでのfluentd利用チュートリアル

またもや身内向けなので淡白に書いていきます。

通常はdocker-composeでコンテナ間でサービス連携するのがCoolだと思います。
ただ、諸事情により他サービスがコンテナで動いてない且つfluentdの環境はコンテナにしてホストOSの環境を汚したくないというニッチな人向けチュートリアル

## fluentd環境構築
docker-hubからイメージをpull、何も明示しないと**latest**になるので
ほしいイメージは[こちら](https://hub.docker.com/r/fluent/fluentd/builds)から探してみてください。

```shell
$docker pull fluend
```

## fluentd.confの設定
dockerは絶対パスでマウントするため今回はホスト上の`/_fluentd/etc/fluentd.conf`
に設定を記述します。
今回はコンテナ上のfluentdと疎通確認したいだけなので[公式ドキュメント](https://docs.fluentd.org/quickstart/life-of-a-fluentd-event)にある
httpプロトコル監視サンプルを利用します。

```fluentd.conf
<source>
  @type http
  port 8888
  bind 0.0.0.0
</source>

<match test.cycle>
  @type stdout
</match>
```
## fluentdコンテナの立ち上げ

```
$docker run -ti -p 8888:8888 --rm -v /_fluentd/etc:/fluentd/etc \
fluentd -c /fluentd/etc/fluentd.conf -v
```

順に解説していきます。
### マウント
` -v /_fluentd/etc:/fluentd/etc`
ホストの`/_fluentd/etc`をマウントすることでホストで書いた設定を
コンテナに反映できるようにしてます。
### confファイルの設定
td-agentを利用している場合はconfファイルが別の名前だったりします。   
そういう方向けに、以下オプションでファイル名を明示的に設定できます。   
`-c /fluentd/etc/<conf-file>` 

### portのマッピング
設定ファイルで記述したポート8888をリッスンできるようにします。
`-p 8888:8888`

## 疎通テスト
```
curl -i -X POST -d 'json={"action":"login","user":2}' \ 
  http://localhost:8888/test.cycle
```
ここでurlに`test.cycle`という文言を含めるのがキモです。
当たり前ですがfluentdでは`<match>`で定義したタグのみ監視します。

うまく行けば以下のようなログが出力されます。

```log.rb
2020-06-28 08:20:20.195562574 +0000 test.cycle:  
  {"action":"login","user":2}
```
ffmpegでサクッとデスクトップキャプチャ（音声も！）

# 概要
ffmpegを使ってサクッとデスクトップ画面＋音声をキャプチャしてファイルに保存します。実行環境はWindows 10を想定しています。

# デスクトップをキャプチャする
ffmpegでは`gdigrab`（Linuxでは`x11grab`）を使うことでデスクトップ画面をキャプチャできます。

```console
ffmpeg -video_size 1920x1080 -framerate 30 -f gdigrab -i desktop -vcodec libx264 -pix_fmt yuv420p desktop.mp4
```

## オプションの解説
### video_size
無指定だと画面全体をキャプチャします。このオプションを指定すると画面の左上を基準に指定した範囲をキャプチャします。

### framerate
キャプチャ動画のフレームレートを指定します。

### f, i
`-f`オプションにgdigrabまたはx11grabを指定し、`-i`オプションに`desktop`を指定することでデスクトップ画面をエンコードの入力映像として指定します。

### vcodec
出力ファイルのコーデックを指定します。画面キャプチャはリアルタイムでの処理が要求されるため、出力設定にはPCのスペックに見合ったものを指定する必要があります。最新のデスクトップPCならば`libx264`コーデックでフルHD解像度ならば処理は可能かと思います。PCの性能に不安があったり、出力動画がカクつく場合は、`-preset`オプションでエンコードの負荷を下げたり、`-s`オプションで出力解像度を下げたり、`-r`オプションでフレームレートを下げることで負荷を下げることができます。

### pix_fmt
このオプションには`yuv420p`を指定することで再生可能な動画プレイヤーソフトが増えます。無指定の場合、VLC Media Playerでは再生可能でしたが、Windows10標準の「映画＆テレビ」アプリでは黒画面となってしまいました。

# デスクトップ音声をキャプチャする
先程の例でデスクトップ画面をキャプチャすることはできましたが、音声はキャプチャできていませんでした。音声は`dshow`を使うことでキャプチャできます。

まずは、音声のみをキャプチャしてみましょう。

```console
ffmpeg -f dshow -i audio="ステレオ ミキサー (Realtek(R) Audio) " -acodec aac audio.m4a
```

## オプションの解説
### f, i
`-f`オプションで`dshow`を指定し、`-i`オプションには`audio="＜キャプチャしたい音声デバイス＞"`を指定します。音声デバイスの名称は各々のPCによって異なるため、環境に合わせたものを指定しましょう。

どうやって調べるか分からないよ！という方は、VLC Media Playerを起動して、「メディア -> キャプチャーデバイスを開く」で表示されたダイアログからオーディオデバイスを選択し、ダイアログ下部の`詳細設定オプションの表示`にチェックを入れると、`オプションの編集`欄に音声デバイス名が表示されるので、それをコピペすると良いです。

![音声デバイス名の確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192467/73153771-740c-8219-f9f3-e7d787153841.png)


### acodec
今回は音声コーデックに`aac`を指定しています。音声のみをキャプチャする場合は出力ファイルの拡張子から自動設定されるため、無指定でも構いません。

### b:a
今回は指定していませんが、`-b:a 256k`などと指定すると出力ファイルの音声ビットレートを設定できます。

# 音声付きでデスクトップ画面をキャプチャする
画面のみのキャプチャ、音声のみのキャプチャを組み合わせることで音声付きでデスクトップ画面をキャプチャできます。

```console
ffmpeg -video_size 1920x1080 -framerate 30 -f gdigrab -i desktop -f dshow -i audio="ステレオ ミキサー (Realtek(R) Audio)" -vcodec libx264 -pix_fmt yuv420p -acodec aac -map 0:v:0 -map 1:a:0 desktop.mp4
```

このコマンドのキモは`map`オプションを使用していることです。これを設定することで別々の入力である動画と音声を一つの出力に組み合わせることができます。

# 参考文献
- [Capture/Desktop – FFmpeg](https://trac.ffmpeg.org/wiki/Capture/Desktop)
- [ffmpeg 単体で画面キャプチャができる gdigrab - ニコニコ動画研究所](https://looooooooop.blog.fc2.com/blog-entry-1226.html)
- [ffmpegを使って映像と音声を結合する - Qiita](https://qiita.com/niusounds/items/f69a4438f52fbf81f0bd)
Rails+vue+Parcel環境でSFCのスタイルが効かなかった件

# 単一コンポーネントで定義したスタイルが反映されない件
Rails+vue+Parcel環境で開発をやっていた時vueのSFCで書いたスタイルが適用されない
いろいろ調べても記事はあまりなかった。
コードをしっかり確認したら解決したのでまとめてみました。

## 解決法
CSSを読み込むヘルパーメソッドを自作する

```ruby:app/helpers/application_helper.rb
module ApplicationHelper
    ・・・
    
    def javascript_pack_tag(name)
        javascript_include_tag(manifest["#{name}.js"])
    end

+   def stylesheet_pack_tag(name)
+       stylesheet_link_tag(manifest["#{name}.vue"])
+   end
    
    ・・・
```
あとは読み込みたいスタイルがあるvueファイルを下記のように指定するだけ。

```ruby:app/views/static_pages/home.html.erb
<% if logged_in? %>
・・・

      <div id="app"></div>
      <%= javascript_pack_tag 'index' %>
      <%= stylesheet_pack_tag '読み込みたいSFCの名前' %>

・・・

```

## なぜこれで解決するの？
`npm run watch`でやっている内容は以下の通り
`parcel watch app/javascripts/packs/index.html -d public/packs --public-url /packs/ --hmr-port 50000`
トランスパイルしたものは`public/packs`に入ってくる。
ここで作成されるmanifestファイルの内容は以下の通り。

```json

{
  "index.html": "/packs/index.html",
  "index.js": "/packs/packs.e31bb0bc.js",
  "FeedList.vue": "/packs/packs.e31bb0bc.css",
  "FeedItem.vue": "/packs/packs.e31bb0bc.css"
}
```

この内容をさっきのヘルパーでは読み込んでいる。

```ruby:app/helpers/application_helper.rb
module ApplicationHelper
・・・

  private

    def manifest
      @manifest ||= load
    end

    def load
      manifest_path = Rails.root.join('public', 'packs', 'parcel-manifest.json')
      if manifest_path.exist?
        JSON.parse manifest_path.read
      else
        {}
      end
    end
end
```
これでマニフェストに書かれていることが読み込まれるので、先ほど作ったヘルパーメソッド（stylesheet_pack_tag）内で`stylesheet_link_tag`を使うことでrailsにCSSを読み込む！

# 後書き
ドキュメントに沿ってコピペだけしてた部分でこうした問題があったので、しっかりコードをよもうと思いました。
macのvscode小技

ｈｔｍｌのカーソルが行の一番うしろにある状態で「ｃｍｄ＋/」で行をまるごとコメントアウトできる。

~.htmlとしたファイル内で「!＋tabキー」を押すことでhtmlの雛壇<!DOCTYPE~以下が全て記述されて便利。

連続して同じ記述をしたい場合は＊「*＋数字」と打ってエンターを押すとその数字分に複製してくれる。（emmetの機能‥？）
例　td*3　エンターで↓
```<td></td>
<td></td>
<td></td> ```となる。

例２
tfoot>tr>td*2 エンターで↓
```<tfoot>
 <tr>
  <td></td>
  <td></td>
 </tr>
</tfoot>```となる。
Docker 問題なかったコンテナでいきなりError: ENOENT: no such file or directory, uv_cwd

（自分用メモ）

## 症状
土日だけ勉強しているとかでPCを久々に開いた時にコンテナ立ち上げたときに
ちゃんと今まで通りに動かない場合がある。

Error: ENOENT: no such file or directory, uv_cwd　とかのエラーがでる。

npm list とか打っただけで以下の通り

```shell
$ npm list
Error: ENOENT: no such file or directory, uv_cwd
    at process.wrappedCwd (internal/bootstrap/switches/does_own_process_state.js:129:28)
    at process.cwd (/usr/local/lib/node_modules/npm/node_modules/graceful-fs/polyfills.js:10:19)
    at Conf.loadPrefix (/usr/local/lib/node_modules/npm/lib/config/load-prefix.js:46:24)
    at load_ (/usr/local/lib/node_modules/npm/lib/config/core.js:109:8)
    at Conf.<anonymous> (/usr/local/lib/node_modules/npm/lib/config/core.js:96:5)
    at Conf.emit (events.js:315:20)
    at ConfigChain._resolve (/usr/local/lib/node_modules/npm/node_modules/config-chain/index.js:281:34)
    at ConfigChain.add (/usr/local/lib/node_modules/npm/node_modules/config-chain/index.js:259:10)
    at Conf.add (/usr/local/lib/node_modules/npm/lib/config/core.js:338:27)
    at Conf.<anonymous> (/usr/local/lib/node_modules/npm/lib/config/core.js:314:25)
internal/bootstrap/switches/does_own_process_state.js:129
    cachedCwd = rawMethods.cwd();
                           ^

Error: ENOENT: no such file or directory, uv_cwd
    at process.wrappedCwd (internal/bootstrap/switches/does_own_process_state.js:129:28)
    at process.cwd (/usr/local/lib/node_modules/npm/node_modules/graceful-fs/polyfills.js:10:19)
    at process.errorHandler (/usr/local/lib/node_modules/npm/lib/utils/error-handler.js:181:30)
    at process.emit (events.js:315:20)
    at process._fatalException (internal/process/execution.js:165:25) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'uv_cwd'
}

```

## 解決策
（自分の場合はMAC）起動しているdocker自体を再起動してやりましょう。
アイコン右クリックでrestart的な

これでもう一度コンテナ立ち上げてやるとちゃんと動きました。
Raspberry Pi 4 で 5秒ごとにCPUの温度を表示させる

# はじめに
Rasberry Pi 4 を使っていると結構CPUが熱くなります．
どれくらいCPUが熱くなるのか調べたかったので，Python3を使って5秒ごとにCPUの温度を表示させるプログラムを作ってみました．

#環境
OS : Ubuntu server20.04 + Xubuntu Desktop(gdm3)

#プログラム

```python:cpu_temperature.py
import time
import threading
import subprocess

def schedule(interval, func, wait = True):
    base_time = time.time()
    next_time = 0
    while True:
        t = threading.Thread(target = func)
        t.start()
        if wait:
            t.join()
        next_time = ((base_time - time.time()) % interval) or interval
        time.sleep(next_time)

def get_cpu_temperature():
    output = subprocess.check_output("cat /sys/class/thermal/thermal_zone0/temp", shell = True, encoding = "UTF-8")
    return int(output) / 1000

def print_cpu_temperature():
    print(get_cpu_temperature())

if __name__ == "__main__":
    schedule(5, print_cpu_temperature)
```

#解説
###schedule関数
以下の記事を参考にしました．
[Pythonで一定時間ごとに処理を実行する](https://qiita.com/kurogelee/items/0e5fd8b6a1d1f169179a)
記事で紹介されているschedule関数のパクリです．
intervalで何秒間隔で実行させたいのか，funcでどの関数を実行させたいのか指定できます．
詳しくはURL先の記事を参照してほしいです．

###get_cpu_temperature関数
以下の記事を参考にしました．
[RaspberryPi(Raspbian)のCPUの温度をcatを使わないで取得してみた
](https://qiita.com/kouhe1/items/5f3f0e6fdb55e7164deb)[Pythonからコマンドを実行する](https://qiita.com/ichiroex/items/681936b7711121d0a360)
vcgencmdを使った方法でもCPU温度を取得できるみたいですが，今回はその方法を使わずに cat を使って取得することにしました．
cat を使う方法だと1000倍の値で出力されるため，そのまま表示するとわかりづらいです．

LinuxのコマンドをPython3から呼ぶにはいろいろな方法がありますが，今回は cat を使って取得した文字列をPython内で加工したかったのでcheck_output関数を使用することにしました．

check_output関数で cat を使ってCPU温度を取得します．そのままでは1000倍された値なので文字列をint型に直し，1000で割ってreturnさせるような形にしました．
vcgencmdを使う場合はそのままreturnさせても良いと思います．

###print_cpu_temperature関数
get_cput_temperature関数で得た値をprintするだけの関数です．
元々schedule関数とget_cpu_temperature関数を使ってグラフを描こうとしたのですが，その前に上2つの関数が正しく動いてくれないと困るので，この関数を作ってみました．

###if __name__ == "__main__"内
5秒間隔でprint_cpu_temperature関数を実行せよ，という意味です．
5の部分を10に変えると10秒間隔になります．
$docker build でエラー

$docker build .
実行時に下記エラーが発生
Error response from daemon: Dockerfile parse error line 1: FROM requires either one or three arguments

原因：
DockerfileのFROM部分に半角スペースがあったため
例)
誤　FROM ubuntu: latest
　　　　　　　　 ↑この部分が不要
正　FROM ubuntu:latest

クセで半角スペースを入れてしまった。
エラー文をよく読めばすぐ解決できたが、エラー文でググっても基本的すぎて、
解決方法が見つけられず。。
FlutterとDart　voidとmain()って何？

#はじめに
Flutterと言うより、**Dartについての説明になるかと。**

**もっと言えば、プログラミング全般についての説明になるかと。**



#voidとmain()って何？
Flutterで新しいプロジェクトを作ると、デフォルトで以下のようなコードがあります。

```dart:main.dart
void main() {
  runApp(MyApp());
}
```

はい、出てきました。`void`と`main()`

Javascriptばっかり触ってきた僕にとって、voidは非常に見慣れないものだ。

##voidとは？
>void（ボイド）は、プログラミング言語において、「何もない」といった意味の型などに使われる名前である。

**要するに`return`がない、と思うだけで良いかと**

もっと噛み砕いて言うと、「returnがない事は決まってるから、わかりやすく印を付けとくわ」ぐらいで。

```dart
// ただ処理をするだけで「何も値を渡すことができないよ〜」と、わかりやすくした感じ
void hello() {
  print('Hello!!');
}

// 型なし関数
hello() {
  print('Hello!!');
}
```
##main()とは？
**一番最初に実行される関数である。**

また、これはアプリケーションに必須となる決まった関数でもあり、`main()`を別の名前にしたりはできない。
【個人メモ】Express環境ハンズオン

完全に個人用メモです。

1. Node.jsとnpmがinstall済みであることを確認する
node -v, npm -vコマンド実行

2. expressのインストール
作業ディレクトリでnpm initを実行してpackage.json作成
npm install express express-generator --save

3. expressアプリケーションの雛形作成
./node_modules/.bin/express --view=pug sample

4. アプリ立ち上げ
cd sample
npm install
npm start
ブラウザからhttp://localhost:3000/につなぐと「Welcome to Express」が表示される。
three.js でlightmapを試す

## 概要
three.jsに限らず、3DCGのアプリケーションでは少しでも計算量を減らしてパフォーマンスを上げたいという要求があります。今回はそれに対する一つのアプローチであるlightmap(ライトマップ)を試したいと思います。

#### lightmapとは
lightmapを簡単に説明すると、物体の陰影をあらかじめ計算した結果の画像(テクスチャ)のことです。これを使用することで、光源の計算をする必要がなくなり、パフォーマンスが向上します。ただし、あらかじめ計算しておくという性質上、物体や光源が大きく動く場合には使用できません。

#### デモ
実際にthree.jsでlightmapを使用したデモを作成しました。
猿に陰影がありますが、シーンに光源は一切置いていません。
バージョンはr93
https://arihide.github.io/demos/lightmap/
[<img width="1280" alt="スクリーンショット 2020-06-28 15.52.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/7e0e6c57-6d98-83b2-1e57-329412169242.png">](https://arihide.github.io/demos/lightmap/)

ソースコードはこちら
https://github.com/Arihide/demos/tree/master/lightmap

## 解説
ここではBlenderを用いてLightmapを作成し、three.jsで表示する方法を説明します。

### lightmapの作成
まず始めに、Blenderでlightmap用のテクスチャとUVを作成する必要があります。例としてcyclesレンダラーで以下のような猿と光源の板を用意します。
<img width="512" alt="a1b7dd9274ac2565c89f76e37751333a-1024x640.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/e318a80f-15f1-c6cc-52bf-ab8fce1e0043.png">

次にdiffuseとは異なる、lightmap用のUVMapを用意します。
<img width="331" alt="81987d68ca302d7fecb4c50113de9c21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/c458f983-9768-db44-88ad-319f82dcebf6.png">

lightmapのUVを選択した状態で、猿を選択してEditモードに入り、「u」キーを押して「Lightmap Pack」を選択してUV展開します。
<img width="945" alt="3f23249d984c621e45124a7230f209ea.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/0b595df0-56cc-9f64-d817-2bdf0e5decec.png">

次に、Lightmap出力先のテクスチャを作成するために「UV ImageEditor」上で適当に画像を作成し…
<img width="406" alt="898265887ec7c983fec763896340e9f2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/f4545a39-d9e2-7f55-67e4-0cf93c6e9267.png">

その後、Node editor上でimage textureノードを作成し、右のBakeを実行しLightmapを作成します。
<img width="512" alt="fbfc61c5e21a4c6a7ad5bf7f91104a33-1024x640.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/90c4cc4e-2775-4dde-859a-036af806d604.png">

その結果、このようなテクスチャを得ることができればLightmap作成完了です！
<img width="419" alt="4ef22436f4c0a07727851f25589c2614.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/0652887d-f0ac-5df9-8da3-0dc31299e4f8.png">

### three.jsでlightmapを使用する
最後に先ほど作成したlightmapをthree.jsで使用する方法を説明します。
といっても設定はとても簡単で、

```javascript
loader.load('./monkey.json', function (geo) {
 
    var lightmap = new THREE.TextureLoader().load('./lightmap.png');
 
    var mat = new THREE.MeshBasicMaterial({ color: 0x0000ff, lightMap: lightmap })
 
    var mesh = new THREE.Mesh(geo, mat);
    scene.add(mesh);
    
    render();
});
```
という風に、3行目でlightmapを読み込んで5行目でマテリアルの引数にlightmapを与えるだけです。
WSL 2 で X に接続する際に環境変数 DISPLAY に指定すべきアドレス (2020/06 時点)

WSL 1 では問題なく X の GUI に繋がっていたが、WSL 2 にしてから繋がらなくなってしまった。Windows 10 May 2020 Update の一般リリース後に仕様が変わってしまったのか、各所で紹介されている方法や [こちら](https://qiita.com/baibai25/items/5841b0592727893d960f) や [こちら](https://odaryo.hatenablog.com/entry/2020/01/08/114846) の記事の方法を試してもダメだったが、別の IP を試したら解決したので一例として書き残しておく。ただし今後の WSL 2 の仕様変更によっては勝手に直ったりするかもしれない。

# 結論: ホスト側 IP を指定する
`localhost` や `/etc/resolv.conf` の `nameserver` の IP ではダメなことがあり、その場合、WSL 側ではなく Windows 側のネットワークアダプターの IPv4 を指定すると繋がることがある。 ※ May 2020 Update 一般リリース後に `/etc/resolv.conf` の仕様が変わってしまったものと思われる。なお WSL 1 ではホストと IP が共有されていたようだ。

具体的には、`DISPLAY` 環境変数を次のように `export` すればよい（コピペで OK）。

```
export DISPLAY=$(ipconfig.exe | grep "IPv4" | head -1 | awk '{print $NF}' | awk 'sub(/\r$/,"")'):0
```

どの環境でも上手くいくかどうかは分からないが、手元の環境ではこれで X に繋がるようになったので一度試してみて頂いてもよいだろう。

※ **各自の環境での `ipconfig.exe` の出力内容に合わせて適宜スクリプトは修正すること**

## どの IP にすればよいのか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546894/443fcfa9-c9ac-b81a-5cef-91d2c4043efd.png)

これらの記事: [WSL2のGUI設定でつまずいたところ](https://qiita.com/baibai25/items/5841b0592727893d960f)、[WSL2のX-ServerでGUI表示する際に「export DISPLAY=:0.0」が効かない](https://odaryo.hatenablog.com/entry/2020/01/08/114846) では `/etc/resolv.conf` の `nameserver` の IP で直っていたようだが、現時点 (2020/06) の私の手元の環境ではダメだった。**現在の** `/etc/resolv.conf` の `nameserver` は WSL 側の vEthernet アダプターを指しており、そちらではなくホスト側 Windows のネットワークアダプターの IP にしたところ、手元の環境ではそれで直った。

WSL 上で Windows 側の実行形式はそのまま動くので、`ipconfig.exe` で IP を取得しそれを `DISPLAY` 環境変数に `export` する。Windows の改行コードが悪さをするので削ってから渡している。環境によって `ipconfig.exe` が表示するアダプターの順番などは異なる可能性があるので、**冒頭に示したスクリプトでダメだった場合は各自の環境での出力内容に合わせて適宜修正すること**。

ちなみに [Pengwin](https://www.microsoft.com/ja-jp/p/pengwin/9nv1gv1pxz6p) では元々ホスト側アダプターの IP が参照されており何もしなくても X に繋がっている。他の Microsoft ストアアプリ ([Ubuntu 20.04 LTS](https://www.microsoft.com/ja-jp/p/ubuntu-2004-lts/9n6svws3rx71) など) でインストールすると現状ダメなのだが、そのうち対応して勝手に直ってくれるのかもしれない。
ルートディレクトリ(/)とホームディレクトリ(~)のちゃんとした理解

ものすごい細かいことだけど、パスの指定方法での`~`（チルダ）と`/`（スラッシュ）の理解が曖昧で気持ち悪い思いをしたのでメモ。

`/`: ルートディレクトリ
`~`：今のユーザーのホームディレクトリ
`~taro`: taroというユーザーのホームディレクトリ

## スラッシュの意味合い
ルートディレクトリの`/`と、各ファイルやディレクトリの前につく`/`は意味合いが違っている模様。

- 前者：ルートディレクトリそのもの
- 後者：ディレクトリを区切るもの

なので、一見ルートディレクトリのせいで「ディレクトリとは末尾にスラッシュが付いているもの」という勘違いを（少なくも筆者は）しちゃうが、`hogehoge/`がディレクトリなのではなく`hogehoge`がディレクトリなのだ。ホームディレクトリを`~/`だと思ってしまっている人は多いのではないか？

## ~ユーザー名
また`~taro`でtaroさんのホームディレクトリを指定できるのは初耳で、結構ググったけどこれについて深く語っている記事は見当たらなかった。こういう指定の仕方があるんですね。

<img width="1204" alt="スクリーンショット 2020-06-28 15.57.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/c7002303-5ad9-536d-2748-41fd45b6e4c2.png">

teratailで教えてもらった👇
[https://teratail.com/questions/273447](https://teratail.com/questions/273447)

## Node.jsのSass特有の書き方
今回がそもそも、RailsアプリでBootstrapを導入しようとして疑問にわいたことだったのだが、Node.jsのSass特有の書き方として、以下のような相対パス？の書き方が使えるらしい。

```scss
@import '~bootstrap/scss/bootstrap';
```

上記は`myapp/node_modules/bootstrap/dist/css/bootstrap.css`を指定できる。モジュールをユーザーに見立てているのかな？

##まとめ
こういうのって「そういうもの」と暗記する人が多いと思うんだけど、数学の公式と一緒で「なぜそうなるのか？」という部分を理解したほうが知識を応用できると思うんです。

今回のものを踏まえると、WebのURLで`https://example.jp`と`https://example.jp/`のどっちを正規URLとすべきかという問題は、前者のほうが本来は正しいのではないかと考えちゃう。
Rails Tutorial　第5章完了

#2020/6/16 1時間
夕食後にやったのですが、途中で寝てしまいました。
ほとんど進まなかったです。
仕事をした後の疲れた脳では辛いです。

#2020/6/17 0.5時間
夜は無理だと思い、朝やることにしました。
仕事の前の30分だけしか時間がとれませんが、脳はフレッシュなので、夜より進みました。

#2020/6/18 0.5時間
やる時間を夜から朝に変えてから、続けてできるようになりました。

#2020/6/19 0.5時間
5.1.2まで終わりました。朝の30分です。

#2020/6/20 2時間
会社がない土曜なので、大分進められました。5.2まで終わりました。

#2020/6/21 1.5時間
会社がない日曜で、5.3まで終わりました。

#2020/6/22 0.5時間
仕事の前の朝30分で、5.4まで終わりました。

#2020/6/23 0.5時間
仕事の前の朝30分で、5章を終わりました。

これで5章を完了しました。
所要時間は7時間です。

感想ですが、仕事を終わった夜にやるのは脳が疲れていて寝てしまって無理だったので、朝に変えたのが効果がありました。

毎日30分やることで、前回から思い出す時間が省けました。
フォークしたリポジトリをライブラリとして取り込む

ケースとしてはあまり多くないとおもいますが、掲題のとおりフォークしたライブラリをプロジェクトに取り込む方法について記載します

経緯としては、以下のYahooのライブラリを改造して使いたかったためです。
https://github.com/yahoojapan/AppFeedback-android

通常なら類似のライブラリを探すのでしょうけど、今回は見当たらなかったためForkすることにしてみました。

1. Forkが完了すると以下な感じにリダイレクトします
https://github.com/harutamasato/AppFeedback-android


2. sdkディレクトリ内でいじりたい箇所をいじって、masterにコミットしていきます。

```
$ git commit -a -m "Message"
$ git push origin master
```

3. 使える状態になったらタグをきってPushします。
2020/6/28現在、オリジナルの最新が1.0.5なのでそれ以上のものを設定します。
今回は1.0.6とします。正常にPushされると、以下のページのTagとReleaseに
1.0.6が並びます。

```
$ git tag -a "1.0.6"
$ git push origin 1.0.6
```


4. ライブラリを使う側はプロジェクトレベルのbuild.gradleに以下がなければ追記

```build.gradle
allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}
```

5. 最後に以下をapp/build.gradleに追記してSyncして使うだけでOK。
```app/build.gradle
dependencies {
  implementation 'com.github.harutamasato.AppFeedback-android:sdk:1.0.6'
}
```
three.js マウスクリックで一部の面の色を変える

## 概要
three.jsでクリックした面の色が変わるような物を作ります。
バージョンはr93

デモ：https://arihide.github.io/demos/face_pick/
[<img width="1280" alt="スクリーンショット 2020-06-28 14.42.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323576/13a29f4c-34a2-9bfd-c8c7-43de926f6f83.png">](https://arihide.github.io/demos/face_pick/)

ソースコードはこちら
https://github.com/Arihide/demos/tree/master/face_pick

## 解説
普通にオブジェクト追加するのと異なる部分に絞って説明します。
#### material作成時のvertexColorsの指定
以下のように、Materialを作成する際にvertexColorsを指定するようにします。
こうすることで、面ごとに色を指定できるようになります。

```javascript
var loader = new THREE.JSONLoader();
var mesh;
loader.load('./rough_plane.json', function (geo) {
    var material = new THREE.MeshLambertMaterial({ color: 0xffffff, vertexColors: THREE.FaceColors });
    mesh = new THREE.Mesh(geo, material);
    scene.add(mesh);
    renderer.render(scene, camera);
});
```

#### クリック時の処理
次に、クリックされた面の取得および、色変更について説明します。
以下がその処理部分です。

```javascript
window.addEventListener('click', function (e) {
    //クリックした面番号の取得
    var square = getIntersectedIndex(e);
    if (square !== undefined && mesh) {
        mesh.geometry.colorsNeedUpdate = true;
        mesh.geometry.faces[square].color.set(0x00ff00);
    }
    renderer.render(scene, camera);
}, false);

var raycaster = new THREE.Raycaster();
function getIntersectedIndex(e) {
    var raymouse = new THREE.Vector2();
 
    raymouse.x = (e.offsetX / width) * 2 - 1;
    raymouse.y = -(e.offsetY / height) * 2 + 1;
    raycaster.setFromCamera(raymouse, camera);
    var intersects = raycaster.intersectObjects(scene.children);
 
    if (intersects.length > 0) {
        var square = intersects[0].faceIndex;
    }
 
    return square;
}
```
ここでは大きく
1. getIntersectedIndexによる面番号の取得
2. 面番号から実際に色を変更
の二つで構成されています。
##### 1. getIntersectedIndexによる面番号の取得
そもそも、three.jsのメッシュには、faceIndexと呼ばれる面一つ一つに割り振られている番号があります。
THREE.RayCasterは交差判定処理をまとめたオブジェクトですが、「どの面番号の面と交差したか？」を調べることもできます。
getIntersectedIndexでは、これらを利用して、「クリックした面の面番号を返却する」処理になっています。
##### 2. 面番号から実際に色を変更
色を変更したい面番号がわかったら
`mesh.geometry.faces[faceIndex].color.set(color);`
で、色を変更することができます。ただし、rendererに色が変更されたことを知らせるために
`mesh.geometry.colorsNeedUpdate = true;`
も指定する必要があります。
[SwiftUI] NavigationView の簡単なサンプル

# iPhone 版

![NavigationView.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/aa77864b-c7e5-f0fb-8a62-7ea42d674559.gif)

# ファイル構成

- ContentView.swift
- User.swift
- DetailView.swift

# Code

```swift:User.swift
import Foundation

struct User: Identifiable {
    let name: String
    let bio: String
    let id = UUID()
}

let users = [
    User(name: "taro", bio: "I like sushi."),
    User(name: "yuki", bio: "I like music."),
    User(name: "mu", bio: "Software engineer")
]
```

```swift:DetailView.swift
import SwiftUI

struct DetailView: View {
    let user: User
    var body: some View {
        VStack {
            Text(user.name)
                .font(.largeTitle)
                .fontWeight(.bold)
            Text(user.bio)
        }
    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(user: users[0])
    }
}
```

```swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(users) { user in
                NavigationLink(destination: DetailView(user: user)) {
                    UserRow(user: user)
                }
            }
            .navigationBarTitle("User list", displayMode: .inline)
        }
    }
}

struct UserRow: View {
    let user: User
    var body: some View {
        VStack(alignment: .leading) {
            Text(user.name)
            Text(user.bio)
                .font(.subheadline)
                .foregroundColor(Color.gray)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```

# macOS 版


![macosNavi.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45822/4d0aff4f-7599-05b9-543a-10443e08736c.gif)


# Code

```swift:ContentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(users) { user in
                NavigationLink(destination: DetailView(user: user)) {
                    Text(user.name)
                }
            }.listStyle(SidebarListStyle())
        }
    }
}

struct DetailView: View {
    let user: User

    var body: some View {
        VStack {
            Text(user.name)
                .font(.title)
                .fontWeight(.bold)
            Text(user.bio)
                .foregroundColor(Color.gray)
        }.frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
```
【Go言語】Goのテストでキャッシュを利用しない方法

Go言語のテストにおいては、Go1.10から結果がキャッシュされるようになってしまいます。
キャッシュを利用せずにテストを行うには以下のオプションを付与する必要があります。

```bash

-count=1
```
また、キャッシュを削除するには以下のコマンドが必要です。

```bash
go clean -testcache
```
JavaScript自分用まとめ

###変数宣言

- const : 再代入不可
- let : 再代入可能
- var : なるべく使用しないほうが良い

```javascript
const a;  
let b;
var c;
```

###関数
```javascript
function sample(a){
console.log(a);
}

const sample2 = function(a){
console.log(a);
}

const sample3 = a => console.log(a);  //引数が1つ

const sample4 = (a,b) => console.log(a+b);  //引数が2つ

const sample5 = (a,b) => {
const c = a + b;
console.log(c);
}
```
###配列とforEach
#####・プログラム
```javascript

const arry = [1,2,3];

arry.forEach(function(a,b,ary){ //(値、添え字、配列そのもの)
  console.log(a,b.arry);
}
)
```
#####・コンソール
```
1 0 [1,2,3]
2 1 [1,2,3]
3 2 [1,2,3]
```
###reduceメソッド
#####・プログラム
```javascript

const arrt = [1,2,3];

arry.reduce(fuction(a,b){  //1回目:(配列の最初の要素もしくは初期値,配列の2番目の要素)
                           //2回目:(戻り値,配列の要素)
console.log(a,b);
return a + b;
},0); //初期値は0に設定
```
#####・コンソール
```
0,1  //初期値,配列の最初の要素
1,2  //0+1,配列の2番目の要素
3,3  //1+2,配列の3番目の要素
```

###DOM

- Document Object Model (DOM) は HTML や XML 文書のためのプログラミングインターフェイス
- JavaScriptでHTMLを操作することができる

###例

- querySelector : 指定した最初の要素を取得

```javascript

var el = document.querySelector(".myclass");
```

- add : 追加操作
- remove : 削除
- toggle : 要素を追加したり削除したりする
- trim : 空白を削除
- addEventListener :  イベントの追加
 
```javascript
function chageMyStyle(){
//処理
}

btn.addEvenrListener('click',changeMyStyle);
```

###クラスとオブジェクト

- クラス : 設計図
- オブジェクト : 実際のモノ
- コンストラクター : 必ず必要なモノ

```javascript
class Car{
  constructor(color, company) {
    this.color = color;
    this.company = company;
  }
  run(){
   //車を走らせる
  }
   
  stop(){
   //車を止める
  }
}

const MyCar = new Car("red","nissen");  //設計図CarでMyCarというオブジェクトを作成するイメージ

console.log(MyCar.color);  //red
console.log(MyCar.company);  //nissen
Mycar.run(); //走る

```
DockerをインストールしてJava実行環境をつくる

新しいパソコンでJava実行環境を構築するにあたり、せっかくならDockerでやってみようと思った備忘録

## 環境
- Windows 10 Home (64bit)


##Dockerのインストール
1. VirtualBoxとかKitematicとか全部入りの [Docker Toolbox [link] ](https://github.com/docker/toolbox/releases)をダウンロード
2. Setup画面はデフォルト設定でOK、最後の画面で確認し[Install]をクリック
3. デスクトップに作成されたDocker Quickstart Terminalのショートカット（<font color= "DeepSkyBlue">></font>&#x1f40b;みたいなやつ）を起動させると色々表示されるので待つ
4. 画像のようにクジラの絵が出たら完了<img width="656" alt="2020-06-27 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400039/20121d56-d7de-f30d-a410-875c38ebafb6.png">
5. Dockerターミナルに`docker run hello-world`と入力しEnterを押すと、"hello-world" という名前のDockerイメージをダウンロードしてくれる<img width="656" alt="2020-06-27 (2).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400039/e1426465-5ef1-bb8e-577c-54dc8936727e.png">


## Dockerイメージのダウンロード
そのままターミナルでコマンド入力してもできるけど、今回は視覚的にわかりやすいKitematicを使ってDockerイメージをダウンロードしてみる
  
1. デスクトップのショートカットから Kitematic を起動
2. "Setup Initialization" の画面で [USE VIRTUALBOX] を選択、DockerHubアカウントは作成しなくてもOK
3. セットアップが完了して表示された画面の検索ボックスにキーワードを入力（今回はjava）
4. 出てきた候補から今回は "openjdk" を選び、<font color= "DeepSkyBlue">[CREATE] </font>ボタンを押す<img width="810" alt="2020-06-27 (4).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400039/db9dd75e-755e-e8e2-d497-14a4d1052e92.png">
5. 左側のContainers欄に "openjdk" が表示され、（先程ターミナルからダウンロードした）"hello-world" と同じように灰色アイコンの表示になったらダウンロード完了
  


<details><summary>**"Connecting to Docker Hub" と表示されダウンロードが進まない場合**</summary><div>

- 上の画像左下の<font color= "DeepSkyBlue"> DOCKER CLI </font>をクリックしてPowerShellを起動
- `docker pull scrapinghub/splash`と入力してEnter
- しばらく待つと諸々のダウンロードが完了しているので、この状態でKitematicに戻るとダウンロードが完了してた
- ダメなら一度Dockerイメージのダウンロードを中止して、再度<font color= "DeepSkyBlue"> [CREATE] </font>ボタンを押してダウンロードを試みる</div></details>


## Dockerイメージからコンテナをつくる
これも Kitematic でやろうと思ったら、何回 [START] をクリックしてもすぐストップしてしまったので Docker のターミナルに戻って作業

1. `docker run -it --name testcont openjdk:latest`を実行してコンテナを起動状態で作成（"testcont" はコンテナの名前）
2. 完成！
javascriptのアロー関数とthisの挙動の違い

アロー関数は、より短く、簡潔に書ける関数の構文です。
`javascript`は得意ではありませんが、いろいろと動的に動かして遊びたいので学習メモとしてまとめます。

## 関数をアロー関数に書き換える

例順を追って、関数のシンタックスを変換していきます。

例文は、引数`i`に`2`をかける関数です。

```javascript
function timesTwo(i) {
    return i * 2;
}

const res = timesTwo(2);
console.log(res);
```

1.変数や定数に格納することで、下記のように書き直すことができます。

```javascript
const timesTwo = function(i) {
    return i * 2;
}
```

2.`function`を消して`=>`を付け足し、アロー関数に書き換えます。

```javascript
const timesTwo = (i) => {
  return i * 2;
}
```

3.引数がひとつの場合は、`( )`を省略できます。

```javascript
const timesTwo = i => {
  return i * 2;
}
```
4.関数の中身が1行しかない場合は、`{ }` と `return` を省略できます。

```javascript
const timesTwo = i => i * 2;
```
アロー関数を使うことで、スッキリと書くことができました。

## 無名関数とアロー関数のthisの挙動の違い

無名関数の扱う`this`と、アロー関数の扱う`this`には注意が必要です。

```javascript
let normalFn;
normalFn = {
    id: 43,
    counter: function() {
        console.log(this.id);
        
        // この場合の無名関数のthis.idはwindowオブジェクトを指す
        window.setTimeout(function() {
            console.log(this) // undefined
        }, 1000);
    }
};

normalFn.counter();
```
`console.log`の出力結果:
![Screen Shot 0032-06-28 at 15.07.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482880/a224c299-17c2-ddc2-a54f-70f86e191ec0.png)

上記の例を`console.log(this)`で確認すると、`window`オブジェクトを参照していることが分かります。

```javascript
// thisをバインドする
let normalFn;
normalFn = {
    id: 43,
    counter: function() {
        console.log(this.id);
        
        // アロー関数はひとつ上のスコープのthisをバインドする
        window.setTimeout( () => {
            console.log(this) // {id: 43, counter: ƒ}
        }, 1000);
    }
};

normalFn.counter();
```

アロー関数に書き換えると、`this`はアロー関数内で定義されず、
ひとつ上のスコープに`this`を探しに行きます。
（スコープチェーンを辿って、ひとつずつ上のスコープで`this`を検索します。）

## 参考
[アロー関数/MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
[Udemy/Javascript中級者への道](https://www.udemy.com/course/road-to-javascript-master/learn/lecture/16597722#overview)
herokuでwww.なし独自ドメインの爆速構築

# はじめに
10分くらいで設定が完了します。
※設定は簡単ですが、PointDNSを使用する場合だと独自ドメインでのAWS/SES利用の併用はできないので、もし使用前提であればRoute５３とCloudFrontから設定してください。
# 前提
- ドメイン取得済み
    - 今回は[お名前.com](https://www.onamae.com/)で取得している前提となります
- herokuアカウント取得済み

# heroku側設定

Add-onsに`PointDNS`を追加しましょう。
<img width="1244" alt="スクリーンショット 2020-06-28 14.32.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239829/867484ee-410c-64e9-5871-3044ff48e3ec.png">

PointDNSを開き、取得したドメイン名をDomain Name欄に入力して追加しましょう。
この記事では例としてドメイン名を`example.com`とします。

追加後、詳細を見ると下記のように、SOAとNSレコードが設定されていると思います。

| Type | Name | Data| 
|:--|--:|--:|
| SOA | example.com. | dns8.pointhq.com. admin.pointhq.com. ... |
| NS | example.com. | dns8.pointhq.com. |
| NS | example.com. | dns12.pointhq.com.  |
| NS | example.com. | dns15.pointhq.com.  |

確認できたらAdd recordsから`CNAME` レコードと `ALIAS` レコードを追加していきます。

- Record type: `CNAME`
    - Name: `www.example.com`
    - Hostname: `qiita-article-production.herokuapp.com`
        - herokuのアプリ名を入力します(heroku管理画面の`Open app`押した時に表示されるURL)
- Record type: `ALIAS`
    - Name: `example.com`
    - Target: `qiita-article-production.herokuapp.com`


以下のような設定になっていればPointDNSの設定は完了です。

| Type | Name | Data| 
|:--|--:|--:|
| SOA | example.com. | Data | 
| example.com. | dns8.pointhq.com. admin.pointhq.com. ... |
| ALIAS | example.com. | qiita-article-production.herokuapp.com. |
| CNAME | www.example.com. | qiita-article-production.herokuapp.com. |
| NS | example.com. | dns8.pointhq.com. |
| NS | example.com. | dns12.pointhq.com.  |
| NS | example.com. | dns15.pointhq.com.  |

次にherokuの管理画面に戻り、`Settings`画面の`Domains`にドメインを追加します。

www付きとwwwなしのドメインを追加しましょう。

- `www.example.com`
- `example.com`

これでheroku側の設定は全て完了です。


# お名前.com側設定
お名前.comのログインし、ドメイン詳細ページに`ネームサーバー情報`があるので、`ネームサーバーの変更` からネームサーバーの変更を行います。

<img width="835" alt="スクリーンショット 2020-06-28 15.16.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239829/14b633ae-d718-de07-94ea-5ae6658def0e.png">


ネームサーバーの選択を`その他のネームサーバーを使う`を選択し、PointDNSの`NS`レコードのDataの値を全て入力します。確認して設定完了します。

以上で全て完了です。
しばらく時間をおくとアクセスできるようになります。

# おわりに

herokuだけだとwww.なしの設定はできないという記事を多く見かけましたが、かなりシンプルに設定できたかと思います。いいherokuライフを。
Expo -v でエラーが発生する(ERROR: Node.js v12.9.0 is no longer supported.)

#事象
##やりたい事
Expo開発を行うために、expo-ctlを入れる
##手順
- nodejsのインストールを行う
- expo-ctlをインストールする
- expoコマンドの動作確認をする
- この時`expo --version` を実行すると、以下のエラーが発生する

```
ERROR: Node.js v12.9.0 is no longer supported.

expo-cli supports following Node.js versions:
* >=10.13.0 <11.0.0 (Maintenance LTS)
* >=12.13.0 <13.0.0 (Active LTS)
* >=14.0.0  <15.0.0 (Current Release)
```


#環境
- nodejs v12.9.0 これはダメなため右に変更する-> v10.19.0
- expoのバージョン　3.21.13

#原因
- エラーメッセージの通りで、14系のnodejsにexpoが十分に対応できていない
- nodejsのバージョンのダウングレードを行う
- 10系の最終盤v10.19.0では動くことが確認されているらしいため、それを取得し設定する

#回復手順
1. nodebrewでのダウングレード手順

2. 欲しいバージョンのnodeを取得

```
nodebrew install-binary v10.19.0
```

3.インストールされたnodeの確認

```
nodebrew ls
```

4.バージョンの切り替え

```
nodebrew use v10.19.0
```

5.インストールしたバージョンのnodeにexpo-ctlをインストール

```
npm install expo-cli --global
```

expoの環境が準備できた

```
expo --version
3.21.13
```
別途アプリをインストールせずに、決まった時間にAndroid端末でアプリを起動する

# きっかけ

日付や時間帯を指定して、起動したいアプリがあります。たとえばmineoアプリなど、毎日一回アプリを起動させて、起動ボーナスの回収と「ゆずるね」の宣言を行いたい場合などがあります。

そういうときのために[AutomateIt](https://play.google.com/store/apps/details?id=AutomateItPro.mainPackage&hl=ja)などのアプリもあるのですが、なにぶんAutomateItは多機能な分端末にかける負荷も大きく、普段使いするような端末にはあまり入れたくありません。

そういうときには、Join by Joaoapps(以下Join)のAPIを使う という方法があります。これを使うとAPI経由で特定のURLをブラウザに開かせたり、アプリを起動させたりといったことがURLを叩くだけで実現できます。

## やりかた

まず自分のAPI KEYとデバイスIDを確認するため、[Join On The Web](https://joinjoaomgcd.appspot.com)を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/6f2db222-5b48-4040-2deb-2ce417a209fe.png)

なぜか文字が重なって表示されてしまうのですが、とりあえずクリックすれば端末名は表示されるので、起動したい端末を選びます。

次に、JOIN APIのボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/7d82595a-07b9-8620-b905-b63245bed9d0.png)

API Key: の右にある「SHOW」ボタンを押したあと、画面をスクロールして「App Package To Launch」の行に、起動したいアプリのパッケージ名を入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/5aa2ad7e-ebee-6780-fffd-37ef4a49c0b6.png)

PCで確認することが困難な場合は、Playストアでアプリのページを開くと確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/f0a7d587-3284-d82d-bd84-c865a498db37.png)

ついでJoin On The Webの画面で上の方にスクロールすると、「Fill in fields below then select -> Copy URL to use」の行に「joinjoaomgcd.appspot.com」からはじまる長いURLが表示されていますので、これをコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/a88d78f6-0a7c-55cc-0508-451faa006164.png)

このURLを定期的に実行されるような何かで呼び出すようにすればOKです。

たとえばPowerShellの場合は、次のようなコードになります。

```powershell
curl "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?appPackage=jp.mineo.app.mineoapp&deviceId=...&apikey=..."
```

## GASで定期的に実行する

ローカルにファイルを置いてしまうとバックアップやPC復元時の設定が面倒なので、こういうときはGoogle Apps Scriptなどで処理してしまうと楽です。

GoogleドライブでGoogle Apps Scriptのプロジェクトを作成し、次のようなコードを書きます。

```js:コード.gs
function run() {
  const url = "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?appPackage=jp.mineo.app.mineoapp&deviceId=...&apikey=..."
  UrlFetchApp.fetch(url) 
}
```

これを保存し、トリガーの設定で、「毎日n時台に実行」などとやっておけばOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/1e09fcd1-352a-34c3-92fe-dadf78d98f8b.png)

動作テストをしたい場合は「時間ベースのトリガーのタイプを選択」を「分ベースのタイマー」、「時間の間隔を選択（分）」を「1分おき」などとしておくと、1分後にスクリプトが実行されるので動作を確認しやすいですね。

# おまけ：JOIN APIのエントリポイント

[JOIN API](https://joaoapps.com/join/api/)の解説ページを見ると、見出しが「API Key」と「Send Push」と「Notification Field」と「List Devices」しかなく、URLっぽいものが「List Devices」の真下にしかないため、一見して「どう呼べば良いんだ？」と思ってしまうこともあると思います(わたしはあった)

ただ先にJoin On The Webのほうをちゃんと見れば分かるとおり、「Send Push」のエントリポイントを叩くURLはJoin On The Webのほうを確認すれば分かりますので、ここには記載されていません。

ちなみに、下にある「List Devices」というAPIもちゃんとあり、Joinに登録されている(アカウントと紐付けされた)デバイスの情報が出力されます。

```powershell
curl "https://joinjoaomgcd.appspot.com/_ah/api/registration/v1/listDevices?apikey={Join On The WebのJOIN APIボタンにて確認できるAPI Key}"
```

# 注意点

特にないですが、Join On The Webに書かれているとおりAPI Keyさえ分かってしまえば認証など一切無しでデバイスが操作できますので、API Keyが外部に漏れないように気をつけましょう。

また、Join On The Webで文字が重なってしまうことなどから、端末名はちゃんと指定するようにしましょう。
setStateをちょっとだけ工夫した話

最近PRレビューした中でこんな感じのstateがあった。

```javascript

const start = type === 'start' ? argumentNumber : this.state.start;
const end = type === 'end'? argumentNumber : this.state.end;
this.setState({
 start,
 end,
 info: {
  hoge: 'textChanged'
 }
})
```

infoの中身は必ず変更されるけど、startとendはtypeによって変更有無が変わる。
なんかsetStateに不要な値入るの気持ち悪いと思いました。

```javascript
let newState = {
 info: {
  hoge: 'textChanged'
 }
}
if (type === 'start') {
 newState = { ...newState, ...{ start: argumentNumber} }
} else {
 newState = { ...newState, ...{ end: argumentNumber } }
}
this.setState(newState)
```

こうしたほうが綺麗かも。
ただ変数の中身が動的に変化していくから、多用するとnewStateの中身がカオスになる。
できれば関数に分けたほうがメンテしやすそう。

```javascript
function newPositionState(type) {
 if (type === 'start') {
  return { start: argumentNumber}
 } else {
  return { end: argumentNumber }
 }
}

let newState = {
 info: {
  hoge: 'textChanged'
 }
}

newState = { ...newState, newPositionState() }
this.setState(newState)

```

こうすれば読みやすい。
更新対象のstateが増えたとしても、特に問題なさそう。
もっといい方法があれば教えていただきたい。