OmniAICreator/Qiita-1.07M huggingface dataset:
Red Hat Enterprise Linux 7.7 に rpmファイルで nkf をインストールする方法（インターネットに繋がらない環境用）

インターネットに繋がらない環境で*Red Hat Enterprise Linux 7.7* に*rpm*ファイルで*nkf*をインストールする方法を紹介します。

# 環境
+ Red Hat Enterprise Linux Server release 7.7

# 1. 準備
### 1.1. epelのGPG公開鍵を取得
以下のページから`RPM-GPG-KEY-EPEL-7`をダウンロードする。
[Index of /pub/epel](https://dl.fedoraproject.org/pub/epel/ "Index of /pub/epel")
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/f5730a08-fab2-7baf-ae0c-2a7d2785034f.png)

### 1.2. nkfのrpmファイルを取得
以下のページから`nkf-2.1.3-5.el7.x86_64.rpm`をダウンロードする。
[Index of /pub/epel/7/x86_64/Packages/n](https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/n/ "Index of /pub/epel/7/x86_64/Packages/n")
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/d6237c33-5ea5-50ff-02eb-0dee49c11ab5.png)

# 2. ファイル配置
### 2.1 RPM-GPG-KEY-EPEL-7ファイルの配置
取得した`RPM-GPG-KEY-EPEL-7`ファイルを`/etc/pki/rpm-gpg`配下に配置する。

```console:実行結果
[root@RHEL-DEMO ~]# cd /etc/pki/rpm-gpg
[root@RHEL-DEMO rpm-gpg]# ls
RPM-GPG-KEY-EPEL-7                RPM-GPG-KEY-redhat-legacy-release
RPM-GPG-KEY-redhat-beta           RPM-GPG-KEY-redhat-legacy-rhx
RPM-GPG-KEY-redhat-legacy-former  RPM-GPG-KEY-redhat-release
[root@RHEL-DEMO rpm-gpg]#
```

### 2.2. nkf-2.1.3-5.el7.x86_64.rpmファイルの配置
取得した`nkf-2.1.3-5.el7.x86_64.rpm`ファイルを任意の場所（ここでは`/root/tmp`配下）に配置する。

```console:実行結果
[root@RHEL-DEMO ~]# cd /root/tmp
[root@RHEL-DEMO tmp]# ls
nkf-2.1.3-5.el7.x86_64.rpm
[root@RHEL-DEMO tmp]#
```

# 3. インストール
### 3.1. EPELのGPG公開鍵をインストール
以下のコマンドを実行し、EPELのGPG公開鍵をインストールする。
`rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7`

```console:実行結果
[root@RHEL-DEMO ~]# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
[root@RHEL-DEMO ~]#
```

### 3.2. nkfのインストール
以下のコマンドを実行し、nkfをインストールする。
`rpm -ivh /root/tmp/nkf-2.1.3-5.el7.x86_64.rpm`

```console:実行結果
[root@RHEL-DEMO ~]# rpm -ivh /root/tmp/nkf-2.1.3-5.el7.x86_64.rpm
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:nkf-1:2.1.3-5.el7                ################################# [100%]
[root@RHEL-DEMO ~]#
```

# 4. 確認
以下のコマンドでインストールされた*nkf*のバージョンを確認する。
`nkf -version`

```console:実行結果
[root@RHEL-DEMO ~]# nkf -version
Network Kanji Filter Version 2.1.3 (2013-11-22)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2013, The nkf Project.
[root@RHEL-DEMO ~]#
```

# リンク
[RepoForge Mirror](http://ftp.riken.jp/Linux/repoforge/ "RepoForge Mirror")
<br/>
以上
シートに定義されている関数を集める関数

現在、開発を続けている旋盤管理システムのワークシートに埋め込まれている関数が複雑になりすぎ、整理するための一覧表が欲しくなったので、それ用の関数を作成しました。Insider限定です。

```vb
Function UFC_(Optional N = "発行01", Optional S = "")   ' UsedRange Function Collect
    
    Set WS = Worksheets(N)
    
    For Each A In WS.UsedRange
        F = A.Formula

        If Left(F, 1) = "=" And InStr(F, "(") > 0 Then
            B = A.Address(False, False)
            S = CC(S, B, F, "|")
        End If
    Next A
    S = Left(S, Len(S) - 1)
    S = Split(S, "|")
    With WorksheetFunction
        S = .Sort(.Transpose(S))
    End With
    UFC_ = S
End Function

Function CC(ParamArray AR())
    On Error Resume Next
    Dim S: S = ""
    Dim I: For I = 0 To UBound(AR)
       S = S & AR(I)
    Next I
    CC = S
End Function
```

使用する場合は、探索するワークシートとは別のワークシートに関数 UFC_ を定義して下さい。同じだと、循環でエラーになります。
出力結果は下記に。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184069/8de825f0-45f0-44db-0493-39f4a947191b.png)
VSCodeでusing UnityEngine.XR.ARFoundationをしても認識されない問題への対処

# 何が起きたか
VSCodeで開発中、ARTrackedImageなどのクラスを利用するために、

```cs
using UnityEngine.XR.ARFoundation;
```

としているにもかかわらず、ARTrackedImageが未定義エラーとなり、かつ、UnityEngine.XR.ARFoundationがunnecessaryとのメッセージが表示される。

ただし、エラーはVSCodeのみで、UnityEditorでは問題なくコンパイルされる。

Macでのみの問題かもしれない。

## 環境
Mac OS 10.15.2
Unity 2019.3.0f3
VSCode 1.41.1

# 解決策
以下より、Monoをダウンロードしてインストール
https://www.mono-project.com/download/vs/

以前にインストールしたつもりだったけど、OSとかVSCodeとかUnityのアップデートに合わせて再インストールが必要だった？

## 参考
https://forum.unity.com/threads/using-unityengine-xr-arfoundation-not-exists.595075/#post-4714004

# 2020/1/30更新
もう一つ要因があるようです。
Package ManagerのVisual Studio Code Editorのバージョンが1.1.4では同様のエラーになるようです。（さらに、ARFoundation以外に、UnityEngine.UIでも同じような現象になる模様）
ひつ前のバージョンの1.1.3にすることで解決しました。
ダウングレード後は一旦Unityを落として、LibraryフォルダとAssembly-CSharp.csproj（これは不要かも）を削除してからUnityを起動し、再度インポートを走らせてください。
参考：https://forum.unity.com/threads/visual-studio-code-editor-1-1-4-error-the-referenced-project-does-not-exist.806628/
画像表示


連番の画像を一括で表示したいのですが
以下のコードでは１つしか表示されません。
このコードの間違えがわかりません。

教えてください。


```ruby:filename.rb
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>表示</title>
	</head>
	<body>
		<canvas width="10000" height="22000">
			Canvas対応ブラウザを使用して下さい
		</canvas>
	</body>
</html>

<script>

let xx = 1;
let yy = 1;

for (yy=1; yy<=5; yy++) {
	window.addEventListener("load", function(){
	// Canvas要素を読み出し
	var myCanvas = document.getElementsByTagName("canvas")[0];
	// コンテキストを取得
	var context = myCanvas.getContext("2d");
	if (!context){ return; }
	// 画像を描画する
	var Imageyy = new Image();
	Imageyy.src = 'Image_01_0'+yy+'.jpg';
	Imageyy.onload = function(){
		// 座標とサイズを指定して描画
		context.drawImage(Imageyy, yy*500, 0,500,700);
	}

}, false);

}
</script>

```
Puppeteerを使ってスクレイピングする時に個人的にはまったポイントのメモ

# 概要

Puppeteerを使用してヘッドレスブラウザとしてウェブスクレイピングを行う時に、個人的に詰まった点のメモです。

## 前提

Mac OS v10.15.2（19C57)
VSCode 1.41.1
node v12.14.1 
Puppeteer 2.1.0


## その１ コンソール出力ができない

### 問題

page.evaluateを使うことで、ページ読み込み後にブラウザ内で任意のスクリプトを実行してHTMLの解析などが可能ですが、デバッグ用にconsoleを仕込んでも何も表示されません。

```js

  // 初期化処理
  const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });
  const page = await browser.newPage();

  // 指定のURLのページを開く
  await page.goto('https://hoge.hoge.hoge');

  // ブラウザ内でスクリプトを実行
  const result = await page.evaluate(() => {
    // ここでコンソールを出力しても何も表示されない
    console.log('eval start');
    // do something
  });

```

### 解決策

pageに対して、consoleイベントを予め登録し、イベント呼び出し処理内でconsoleで書き込みを行います。
page.evaluate内でconsoleを実行するとこのイベントが発火されてconsole出力がされるようになります。

```js

  const page = await browser.newPage();
  // コンソールイベントを登録
  page.on('console', msg => {
    for (let i = 0; i < msg._args.length; ++i)
      console.log(`${i}: ${msg._args[i]}`);
  });
  // 指定のURLのページを開く
  await page.goto('https://hoge.hoge.hoge');

  // ブラウザ内でスクリプトを実行
  const result = await page.evaluate(() => {
    console.log('eval start');
    // do something
  });

```


## その２ querySelectorAllで取り出した結果が空のオブジェクトになる

### 問題

page.evaluate内でquerySelectorを使ってHTML要素を出力しようとするが、正しく値が取れない。

```js

    const result = await page.evaluate(() => {
      const dataList = [];
      // hogeクラスタグ配下のaタグを全て取得
      const nodeList = document.querySelectorAll('.hoge > a');
      // 内部のhtmlを出力
      nodeList.forEach(_node => {
        dataList.push(_node.innerText);
      });
      return dataList;
    });

    // 出力は空文字になる ["", "", ""]
    console.log(result);
    
```

### 解決策

querySelectorAllで取り出した値は配列になっていない為、Array.fromで配列に変換した後に列挙を行う。

```js

    const result = await page.evaluate(() => {
      const dataList = [];
      // Array.fromで配列に変換
      const nodeList = Array.from(document.querySelectorAll('.hoge > a'));
      // 内部のhtmlを出力
      nodeList.forEach(_node => {
        dataList.push(_node.innerText);
      });
      return dataList;
    });

    console.log(result);
    
```


## 最後に

個人的にPuppeteer使用中にはまった点を書きました。
Puppeteer自体は直感的で便利なのですが、思いがけないところではまって時間を使ってしまいしました。
(マニュアル等をしっかり読まず使えしまう事の弊害かもしれませんが。)
Pocket APIのアクセストークンを取得する

# はじめに
[Getting your reading history out of Pocket using Python](https://medium.com/@alexdambra/getting-your-reading-history-out-of-pocket-using-python-b4253dbe865c)を参考にして（というかそのままなのですが）APIを使うためのアクセストークンを取得しました。
元記事の内容は、
- アクセストークンを取得する
- Pocketに登録しているアイテムを取得する
- 取得したアイテムをPandasで表示する
という内容ですが、ここではアクセストークンの取得までの内容のみ抜粋して記載します。

# 1. コンシューマーキーを取得
https://getpocket.com/developer/ からコンシューマーキーを取得します。
（ここは画面の通りに進めるだけなので手順は割愛します）

# 2. リクエストトークンを取得
以下のコードの"your_consumer_key"を手順1で取得したコンシューマーキーに置き換えます。
実行するとリクエストトークンが表示されます。

```python
import requests
from urllib.parse import urlencode
from urllib.request import Request, urlopen

codeurl = 'https://getpocket.com/v3/oauth/request' # Set destination URL here
post_fields = {"consumer_key":"your_consumer_key","redirect_uri":"http://www.google.com"}  # Set POST fields here
request = Request(codeurl, urlencode(post_fields).encode())
json = urlopen(request).read().decode()
print(json)
```
# 3. 認可を行う
以下のURLの"your_request_token"を手順2で取得したリクエストトークンに置き換え、ブラウザのアドレスバーに貼り付けアクセスします。
そうすると認可の可否を問うページが表示されるので「認可」をクリックします。

```
https://getpocket.com/auth/authorize?request_token=your_request_token&redirect_uri=http://www.google.com"
```

# 4. アクセストークンを取得
以下のコードの"your_consumer_key"、"your_request_token"を前述の手順で取得したものに置き換えて実行するとアクセストークンが表示されます。

```python
url = 'https://getpocket.com/v3/oauth/authorize'
post_fields = {"consumer_key":"your_consumer_key","code":"your_request_token"}
request = Request(url, urlencode(post_fields).encode())
json = urlopen(request).read().decode()
print(json)
```
コンテナ開発におけるwebpack-dev-serverの自動更新対応

httpsをリバースプロキシしたnginx配下にあるwebpack-dev-serverにおける自動更新対応。

sockPortで443経由でアクセスして、sockPathでproxyするパスを指定。
UpgradeヘッダでWebSocket通信に対応。


```dockerfile:Dockerfile
FROM node:12.13.1-alpine3.10 as builder
WORKDIR /usr/src/app
COPY . .
RUN yarn install
RUN npx webpack
FROM node:12.13.1-alpine3.10
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/dist/ ./js/
COPY --from=builder /usr/src/app/package*.json ./
RUN yarn install --production
WORKDIR /usr/src/app/js
CMD npx http-server
EXPOSE 8080
```

```yml:docker-compose.yml
version: "3"
services:
  app:
    image: app
    build: ./
    container_name: app
    volumes:
      - ./:/usr/src/app/
  https-proxy:
    image: nginx:latest
    container_name: https-proxy
    depends_on:
      - app
    volumes:
      - ./nginx/conf:/etc/nginx/conf.d
      - ./nginx/certs:/etc/ssl/certs
    ports:
      - 443:443
```


```nginx:nginx.conf
...
server {
    listen       443 ssl http2;
    server_name  localhost;

    ssl_certificate     /etc/ssl/certs/localhost.pem;
    ssl_certificate_key /etc/ssl/certs/localhost-key.pem;

    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location /app.js {
        proxy_pass http://app:8080;
    }

    location /app-socket/ {
        proxy_pass http://app:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }
}
```

```js:webpack.config.js
const webpack = require('webpack');
module.exports = {
    entry: '/usr/src/app/src/app.js',
    output: {
        filename: 'app.js',
        path: '/usr/src/app/dist/'
    },
    devServer: {
        contentBase: '/usr/src/app/dist/',
        host: '0.0.0.0',
        port: 8080,
        sockPort: 443,
        sockPath: '/app-socket',
    }
}
```
マスク付きbit全探索

## bit全探索するときに

特定のbitの状態を固定したいときってありませんか？私はありました

ちょうどこんな感じの挙動がほしいときです
3,5ビット目は常に0
`000'000` → `000'001` → `000'010` → `000'011` → `001'000` → `001'001` → `001'010` → `001'011` →
`100'000` → `100'001` → `100'010` → `100'011` → `101'000` → `101'001` → `101'010` → `101'011`

## 愚直な実装

``` c++
std::uint64_t mask = 0b101011;

for (std::uint64_t i = 0; i < (std::uint64_t{1} << 6); ++i) {
    if (i & ~mask) continue;

    .....
}
```

コレだと結局2^6の全てのパターンを走査していて、本来2^4回のループで済むところを（処理が飛ばされはするものの）2^6-2^4回だけ無駄にループしている。

固定されるビットの数が1つのときにループの半分が無駄になり、以降固定されるビットの数が増えるたびに無駄が増えるので、大半の状況ではループの殆どが無駄になる

これを2^4回のループで済ませられるようにしたい

## 方針

立っているビットの位置を調べて...とかやってると日が暮れそうなので少ない手数（可能なら1行で）できる方法を考える

とりあえず細かく分けて考える

- `000'000` → `000'001` → `000'010` → `000'011` の遷移
- `001'000` → `001'001` → `001'010` → `001'011` の遷移
  - 普通に+1すれば良い
- `000'011` → `001'000` の遷移
  - 3ビット目に1があると思って+1するとうまく行く
  - 000'**1**11 → 001'000
- `001'011` → `100'000` の遷移
  - 3ビット目と5ビット目に1があると思って+1するとうまく行く
  - 0 **1**1'**1**11 → 10'000

というわけで

1. 固定されているビットを全部立てる
1. +1する
1. 固定されているビットを全部下ろす

とすればよい
（つまりインクリメントのときだけ繰り上がり用にビットを立てておく、という作戦）

## コードにするとこんな感じ

```c++:
std::uint64_t mask = 0b101011;
for (...;...; i = ((i | ~mask) + 1) & mask) {
```

しかしこれだと`101'011` → `000'000` と遷移してしまうので、元の終了条件だと無限ループしてしまう
[動作確認用](https://wandbox.org/permlink/dYfYD44TuwSQ7Fmu)

状況的には （そんなことをやる機会はまずないだろうけど）64bit変数で2^64パターンの愚直なbit全探索ができないのと似ているので泥臭い方法で対処する

```c++:こんな感じのループはできない
for (std::uint64_t i = 0; i < (std::uint64_t{1} << 64); ++i) {
for (std::uint64_t i = 0; i != (std::uint64_t{1} << 64); ++i) {
```
```c++:仕方ないのでこうする()
std::uint64_t mask = 0b101011;
std::uint64_t lim = std::uint64_t{1} << 6;
for (...; i < lim; i = (i != mask ? ((i | ~mask) + 1) & mask : lim)) {
```
[動作確認用](https://wandbox.org/permlink/uFTQAC4pfnhcawyX)

ここまで来ると専用のrangeを作ったほうが良さそう

## 逆順

逆順にたどること自体は簡単で

```c++
i = (i - 1) & mask;
```
とすると繰り下がりで発生した余分なビットを消せるので逆順に走査できる

ただし、終了条件が非常に面倒なのでこれまた専用のrangeを作るか、昇順の方法を流用して

```c++
std::uint64_t mask = 0b101011;
std::uint64_t lim = std::uint64_t{1} << 6;
for (...; i < lim; i = (i != mask ? ((i | ~mask) + 1) & mask : lim)) {
    auto j = ~i & mask;
```

とかが良さそう
[動作確認用](https://wandbox.org/permlink/GBgcT71zFGpNw34T)

## 固定するビットを0じゃなくて1にしたりしたい

適当にmaskすればいいんじゃないかな

```c++
std::uint64_t mask = 0b101011;
std::uint64_t patt = 0b010000; // 5ビット目は1
std::uint64_t lim = std::uint64_t{1} << 6;
for (...; i < lim; i = (i != mask ? ((i | ~mask) + 1) & mask : lim)) {
    auto j = i | patt;
```

## どうでもいい一言

なんで`std::bitset`さん`.to_int<std::uint16_t>()`みたいなビット幅を選べる整数への変換インターフェースが無いんですか！ `ullong`ってなんだよ！環境依存じゃねーか!
rspecで既存の並行処理に対してテストを追加したら fatal - No live threads left. Deadlock? エラーが起きた。

# 序


rails5にて。
とある、パラレル処理を行っているコントローラーがあった。

イメージ

```ruby
...
Parallel.each(records, :in_threads=>4) do |r|
  Blablabla::BullshitService.new(r.dead_beaf).bullshit
end
...
```

リファクタのためにrspecでrequestsのテストを書いていたら、実行時に
`No live threads left. Deadlock?`
というエラーになって失敗した。


イメージ

```bash

$ bundle exec rspec spec/requests/api/blablabla_controller_spec.rb

...

fatal - No live threads left. Deadlock?
4 threads, 4 sleeps current:0x000055d836b087e0 main thread:0x000055d82d7f48e0
* #<Thread:0x000055d82e208c88 sleep_forever>
   rb_thread_t:0x000055d82d7f48e0 native:0x00007ff40e623b68 int:1
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `value'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `map'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:212:in `block (2 levels) in in_threads'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:211:in `handle_interrupt'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:211:in `block in in_threads'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:204:in `handle_interrupt'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:204:in `in_threads'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:353:in `work_in_threads'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:275:in `map'
   /bundle/gems/parallel-1.18.0/lib/parallel.rb:227:in `each'

...

  app/controllers/api/blablabla_controller.rb:66:in `bullshit'

   (0.6ms)  ROLLBACK
F
```

# 破

gemのparallelのどこかで不具合が起きているのかなと思いgem側のissueを確認した。
それっぽいのはあるが、自分のケースとはちがった。
ソースを確認しても、怪しそうなところの検討がつけられなかった。
(泣きながら)１つの処理しか並行動作しないようにしつつ `binding.pry` をかけて、stepで潜り始めたところ
すぐ次のようなframeにぶち当たり

```pry
    200: def const_missing(const_name)
 => 201:   from_mod = anonymous? ? guess_for_anonymous(const_name) : self
    202:   Dependencies.load_missing_constant(from_mod, const_name)
    203: end
```

railsのautoload のことを思い出す。 

RAILS_ENV=production時は eager_load によって起動シーケンスですべてのクラスがロードされるが
test, developmentなどのときはautoloadにて都度読み込まれている。

rspecの該当箇所付近にて`eager_load!`を呼ぶようにしたところ、エラーが起こらなくなった。

```ruby
Rails.application.eager_load!
```

`Parallel.each` の各blockにて、それぞれautoloadが起こって競合している模様。

autoloadの仕組みはthread-safeではなかったのか、、
テスト時に全部ロードするのはなんだか嫌だけど、requireを都度書くのも保守したくなくなりそう。
ベストプラクティスが知りたい。


# 急

```
＿人人人人人人人人人人人人＿
＞　pryつかいにくくない？　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^￣
```



# see also

Rails 5 disables autoloading while app in production
https://blog.bigbinary.com/2016/08/29/rails-5-disables-autoloading-after-booting-the-app-in-production.html
【React + Typescript】スクロール位置を取得するコンポーネント

よく使うのでメモ。

以下のコードはスクロール位置が80px以下になると色が変化するnavの例。
ちゃんとやるならrefから高さ取得する感じかな。

```tsx
import React, { useEffect, useState } from 'react';

const scrollTop = (): number => {
  return Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop);
};

export const NavBar: React.FC = () => {
  const [isTop, setIsTop] = useState<boolean>(true);

  const onScroll = (): void => {
    const position = scrollTop();
    if (position >= 80) {
      setIsTop(false);
    } else {
      setIsTop(true);
    }
  };

  useEffect(() => {
    document.addEventListener("scroll", onScroll);
    return (): void => document.removeEventListener("scroll", onScroll);
  });

  const  scrollStyle: React.CSSProperties = isTop
    ? { backgroundColor: "#fff" }
    : { backgroundColor: "#000", opacity: 0.8 };

  return (
   <nav style={scrollStyle}></nav>
  );
};

```
Git ブランチの確認と作成と移動とmerge

# 目的

- Gitにおけるブランチ作成、ブランチ確認、ブランチ移動、mergeをまとめる
- ※ほぼ自分用のメモになってしまっている

# 現在のブランチの確認

- git管理されているディレクトリ内で下記コマンドを実行する。

    ```terminal
    $ git branch
    ```

- masterブランチのみの場合下記のように出力される。

    ```terminal
    >* master
    ```

- masterブランチとdevブランチがあり現在masterブランチに自分がいる場合は下記のように出力される。

    ```terminal
    >  dev
    >* master
    ```

# ブランチの作成

- 下記コマンドを実行して現在自分がいるブランチのコミットからブランチを作成する。

    ```terminal
    $ git branch 作成するブランチ名
    ```

# ブランチの移動

- 下記コマンドを実行してブランチを移動する。

    ```terminal
    $ git checkout 移動したいブランチ名
    ```

# merge(他ブランチの修正を取り込み)

- Bブランチの修正内容をAブランチにmergeする方法を下記に記載する。

    ```terminal
    $ git checkout Aブランチ
    $ git merge Bブランチ
    ```

- 下記コマンドを実行してtestブランチの修正内容をmasterブランチにmergeする。

    ```terminal
    $ git checkout master
    $ git merge test
    ```
お絵かきできるSNSを作りたい！2

Qiitaでのんびり連載をしたいけど、そんな機能あるんだろうか。。。

とりあえずJavaScriptを使ってcanvasに線を引く方法を調べました。

まずcanvasタグを置いて

```html:
<canvas id="canvas" width="200" height="200"></canvas>
```

次にgetElementByIdで設置したcanvasを取得。(*1)
次にgetContextで描画機能を有効にして、(*2)
beginPathを使いパスをリセット。(*3)
X座標とY座標を使いmoveToで始点を決めて・・(*4)
lineToで始点の終点を設定し、(*5)
最後にstrokeとすると線が引けるそうです。(*6)

```JavaScript:
can=document.getElementById("canvas"); // *1
ct=can.getContext("2d"); // *2
ct.beginPath(); // *3
ct.moveTo(0,100); // *4
ct.lineTo(200,100); // *5
ct.stroke(); // *6
```

実行結果(縦200ピクセル、横200ピクセルのキャンバスの真ん中に水平線が引けました。)
![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104527/85657594-dc67-3271-2cd8-180a87411bd7.jpeg)

なるほど！
ちなみにlineToを増やすと線が増えるそうです。

```JavaScript:
can=document.getElementById("canvas");
ct=can.getContext("2d");
ct.beginPath();
ct.moveTo(0,100);
ct.lineTo(200,100);
ct.lineTo(100,0); //←ここを増やした！
ct.lineTo(0,100); //←ここも増やした！
ct.stroke();
```

横200ピクセルのキャンバスの真ん中に水平線を引いた後に
X軸0ピクセル、Y軸100（横は中央、高さは0px）の座標を指定して、
最後に元の場所に戻ると・・

![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104527/b4dc3143-4210-2021-79e0-763660f3bb2e.jpeg)

上三角形の完成です。

なるほどね！

ふぅ。（先は長そうだ・・。
千里の道も一歩から。

次：[お絵かきできるSNSを作りたい！3](https://qiita.com/cardcapt/items/cb6808a342bda4a1f0b6)
最初：[お絵かきできるSNSを作りたい！](https://qiita.com/cardcapt/items/d15fedf80d336f6b4bb9)
基本情報技術者　テクノロジ系　第8章 システム開発技術①

今日も今日とて学習です。

# システム開発プロセス/開発モデル

## 共通フレーム
ソフトウェアの開発者と発注者の間で段取りに対する共通概念を作ること
基本①から⑤まで順番に行います。

### ①企画プロセス
経営の目的、目標より計画を作成

### ②要件定義プロセス
必要機能、使いやすさを明確にする

### ③開発プロセス
要件を詳細にし設計を進め、作成しテストする。

### ④運用プロセス
システムを導入し、ユーザー教育し継続運用する。

### ⑤保守プロセス
不具合や諸事情の変化に対応
④に適時行う

### ⑥管理プロセス
①②③④⑤格プロセスの管理

## 共通フレームの開発プロセス活動
流れとしては

1,要件定義      : 機能要件の定義
2,方式設計      : 具体的なシステムの構成
3,結合: できた格コード、ソフトウェアの結合
4,適格性確認テスト: 結合からの性能確認

が基本となる流れで
システム(全体)とソフトウェアの開発を合わせる
と下記のとうに順番に行っていく形です。


### ①システム全体を対象とした作業:初期段階

#### システム要件定義

#### システム方式設計

### ②ソフトウェアを対象とした作業

#### ソフトウェア要件定義

#### ソフトウェア方式設計

#### ソフトウェア詳細設計

##### コード作成とテスト

#### ソフトウェア結合

#### ソフトウェア適格性確認テスト

### ③システム全体を対象とした作業:完成段階

#### システム結合

#### システム適格性確認テスト

## ウォーターフォールモデル

下記のように上流工程と下流工程に別れ
①から順番に行っていく形です。

開発の終わりの見通しが立ちやすく
コストや開発期間の見積もりが容易ですが

後戻りを考慮してないので、やり直しの大きなコストがかかってしまいます。

### 上流工程

#### ①基本計画
ユーザー要求を分析して、
「要求仕様書」にまとめます。

#### ②外部設計
ユーザー側の視点で捉えて設計します。
大まかな機能単位にシステムを分けます。

* 論理データ設計
* 入出力設計
* コード設計

#### ③内部設計

プログラムでどう具体的にどう実現するか設計します。

* 物理データ設計
* 入出力詳細設計

#### ④プログラム設計
内部設計で定義したプログラムを
モジュール単位に分割します。

##### モジュール
プログラムを組み立てる部品となるソフトウェアです。

### 下流工程

#### ⑤プログラミング

#### ⑥テスト
下記の順番で行われます。

1,単体テスト
2,結合テスト
3,システムテスト
4,運用テスト

#### ⑦運用・保守
下記のように分類されます。

* 修正保守
* 変更(適応)保守
* 改良保守

#### ⑧レビュー
見直し作業のこと

* ウォークスルー: 開発者が自ら説明して意見を求める
* インスペクション: 進行役のモデレーターによって進められる
* ラウンドロビン: 参加者が持ち回りする


## スパイラルモデル

ウォーターフォールとは逆で修正しやすくしたもの

下記の①②③④を4回繰り返して完成させます。

### ①目標、代替案、制約の決定

### ②代替案とリスクの評価

### ③開発とテスト

### ④次フェーズの計画

## プロトタイプモデル

ベータ版とも言われ、ユーザーに試作品を使ってもらい
意見を聞く

## アジャイル開発
ウォーターフォールモデルの改良版で
時間の短縮、要求対応、品質向上を目的とした
開発手法の総称です。

下記のような用語があります。

* XP(エクストリームプログラミング): 仕様変更は当たり前として、柔軟性やスピード重視
* ペアプログラミング: コンビのプログラマが行う
* 継続的インテグレーション: 単体テストが終わったら、すぐ結合テストをする
* テスト駆動型開発: テストケースを事前作成する
* スクラム: スプリントと呼ばれる、短い周期で行う。
* リファクタリング: コードの整理

## リバースエンジニアリング
下流工程の成果物から上流工程の成果物を生成する。

## リエンジニアリング
リバースエンジニアリングからの製品より
新たに製品を作ること。
CentOS8 にvsftpdを入れる

#はじめに
多分、基礎の基礎なんだろうけど、Wordpressのテーマをインストールするのに
ftpの設定が必要との事が発覚。
という訳で早速インストール。

#フロー
1.dnfコマンドでインストール
2.ftpの設定

##vsftpdのインストール

```shell:install
dnf -y install vsftpd
```
これは言わずもがなサクッと終る。
次は設定

```shell:conf_vsftpd
vi /etc/vsftpd/vsftpd.conf
```

ここは、ggってデフォルトもあるけど、記載箇所を変える。

```shell:vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
listen_ipv6=YES
local_root=public_html
pam_service_name=vsftpd
userlist_enable=YES
userlist_deny=NO
use_localtime=YES
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list
listen=NO
pasv_enable=YES
pasv_min_port=21000
pasv_max_port=21010
```

```shell:設定反映
systemctl restart vsftpd
```

一通り設定したらftp用のユーザー作成

```shell:create_user
useradd ftpuser
passwd ftpuser
Changing password for user ftpuser.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```

作成したユーザーを名を以下のファイルに書き込む

```shell:chroot_list
vi /etc/vsftpd/chroot_list
```

```shell:
#Firewalld を有効にしている場合は、FTP サービスの許可をする。
firewall-cmd --add-service=ftp --permanent
firewall-cmd --add-port=21000-21010/tcp --permanent
firewall-cmd --reload

```

あとは、動作確認でffftpとかで動作確認してOKだったので完了～

#参考サイト
（詳しくはこちら）
https://www.server-world.info/query?os=CentOS_8&p=ftp&f=1
style.cssを読み込みたい WordPress 

# style.cssを読み込みたい WordPress 

#### 利用シーン

- 独自テーマを作成する時には必須の作業
- 既存のテーマで、テンプレートファイルに<link rel="stylesheet">タグが残っていて、修正したい時

#### 使用するWordPress関数
- wp_head()
wp_headアクションフックを開始する

- add_action()
アクションフックに処理を追加する

- wp_enqueue_style()
HTMLに<link rel="stylesheet">タグを挿入する

- get_stylesheet_uri()
style.cssのパスを取得する

#### 使用例

HTMLに<link rel="stylesheet">が含まれていても、テーマにするとCSSファイルは正しく読み込まれない場合がある。
確実にstyle.cssを読み込ませるために、テンプレートファイルを編集する。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CSS演習</title>

<?php wp_head(); ?>
</head>
```

```php:functions.php

<?php 
function enqueue_script() {
  // CSS
　wp_enqueue_style('main-css', get_stylesheet_uri());
}
add_action('wp_enqueue_scripts', 'enqueue_scripts');
```

style.cssのスタイルが適用されているのがわかる。
VSCodeで HTMLとSCSSを書くシンプルな環境を構築する

## やること

VScode のみを用いて、HTML と scss(css)と js を書くだけのシンプルな環境を構築する。
イメージとしては CodePen のような環境。


## 環境

- CentOS 7
- VScode 1.41.1


## 拡張機能をインストール

- [Live Sass Compiler](https://marketplace.visualstudio.com/items?itemName=ritwickdey.live-sass) 
Scss をコンパイルするのに用いる。

- [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)
  ブラウザの自動更新を行ってくれる。LiveSassComplier を入れるとインストールされます。

## ファイルを作成

### HTML

適当なフォルダを開き、HTML を書く。
HTML ファイルで`!`を入力すると VScode のスニペット機能で HTML の簡単なひな形が出来るのでおすすめ。

- スニペットで生成される HTML

```html:html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body></body>
</html>
```

### SCSS・JS

`scss/`を作成し、そこにscssを作成。ディレクトリの場所や名前は指定するのでどこでもよい。
JSファイルも同じく。

### 作成後

```bash
.
├── index.html
├── js
│   └── index.js
└── scss
    └── style.scss
```

## 拡張機能の設定

### Live Sass Compiler の設定

Live Sass Compilerの出力設定をする。prefixの付与なども行ってくれるので、設定しておく。
以下は自分のセッティング。
他にも設定項目があるので詳しくは[公式 Doc](https://github.com/ritwickdey/vscode-live-sass-compiler/blob/master/docs/settings.md)。

```json
{
    ...
    // liveSassConpiler
    // prefixを付与してくれる
    "liveSassCompile.settings.autoprefix": [
        "> 1%",
        "last 2 versions"
    ],
    // 出力設定、拡張子やフォルダ(相対パス)も指定する。
    "liveSassCompile.settings.formats": [
        {
            "format": "compressed",
            "extensionName": ".min.css",
            "savePath": "/css"
        }
    ],
    // 監視しないディレクトリ(以下はデフォルト値)
    "liveSassCompile.settings.excludeList": [
        "**/node_modules/**",
        ".vscode/**"
    ],
    ...
}
```

### Live Server の設定

自分は Port のみ変更。
[公式 Doc](https://github.com/ritwickdey/vscode-live-server/blob/master/docs/settings.md)

```json
{
    ...
   "liveServer.settings.port": 8000,
    ...
}
```

## 起動

- Live Sass Compiler

scss ファイルを開くと、VSCode 下部に`Watch Sass`ボタンがあるので、そこを押す。
`settings.json`で指定したパスにコンパイル後の css が生成されている。

```bash
.
├── index.html
├── js
│   └── index.js
├── scss
│   └── style.scss
└── css
    ├── style.min.css
    └── style.min.css.map
```

`"format": "compressed"`を選択したので、生成ファイルは圧縮された状態。prefix が付与されているのも確認できる。

```css
html{font-size:62.5%;line-height:1.4;-webkit-box-sizing:border-box;box-sizing:border-box}body{min-height:200vh;background-color:gray}...
```

`style.min.css.map`はソースマップと呼ばれるファイルで、圧縮前のどの css に記述したものかが判別できる。
不要であれば`"liveSassCompile.settings.generateMap": false`

- Live Server

HTML ファイルを開き、`Alt + L, Alt + O`
もしくは、VSCode 下部に`Go Live`ボタン
ブラウザからアクセスできるようになっているはず。(初期設定では`http://localhost:5500`)

## HTML での css, js 読み込み

href, src は相対パスを指定してやれば OK.

```html
<html>
  <head>
    ...
    <link rel="stylesheet" href="./static/css/style.min.css" />
    <script src="./js/index.js" type="text/javascript"></script>
  </head>
  ...
</html>
```
EdgeRouter の GUI に SSL 証明書を設定する

EdgeRouter の GUI に HTTPS でアクセスするとブラウザの警告が出てしまう。
これは EdgeRouter がオレオレ証明書を使っているためなので、これをちゃんとした証明書に置き換えればよい。

EdgeRouter の GUI は Lighttpd で動いているのでその設定ファイルを書き換えれば証明書の設定もできるのだが、ファームウェアをアップデートすると `/config` 以外のファイルはすべてリセットされてしまうので、その都度再設定しなければならない。

そこで今回は、 `/config` 以外を触らずに GUI の SSL 証明書の設定を行う方法について書く。

## 環境
EdgeRouter X (Firmware v2.0.8)

## SSL 証明書を発行する
SSL 証明書の発行の仕方はググればいくらでも出てくるので割愛。

- 秘密鍵 `key.pem`
- 証明書 `crt.pem`

は既に用意できているものとする。

## `server.pem` を作成する
Lighttpd では秘密鍵と証明書をまとめたファイルを読み込ませる必要があるらしいので、2つをまとめた `server.pem` を作成する。

``` console
$ cat key.pem crt.pem > server.pem
```

## `server.pem` を配置する
`/config` 配下なら別にどこに置いてもいいが、 `/config/auth` というディレクトリが用意されているのでそこに配置する。

``` console
$ scp server.pem <router>:/config/auth
```

オーナーとパーミッションの設定をしておく。

``` console
$ sudo chown root.vyattacfg /config/auth/server.pem
$ sudo chmod 400 /config/auth/server.pem
```

## config を書き換えて証明書を読み込む
`service gui cert-file` という項目で GUI の証明書のパスを設定できるらしい。

``` console
$ configure
# set service gui cert-file /config/auth/server.pem
# commit
# save
```

commit した時点で Lighttpd が再起動されるので、ブラウザからアクセスすると反映されていることが確認できる。
pryでshow-resourceを使い、クラスやモジュール、メソッドの定義を確認する

### 以下が手順
### pryはあらかじめインストールしておく

### pryを起動
```console
$ pry
```

### Arrayクラスへcdで入る
```console
[1] pry(main)> cd Array
```

### Arrayクラスで使用可能なメソッド一覧をlsで表示
```console
[2] pry(Array):1> ls
Array.methods: []  try_convert
Array#methods: 
  &              concat      hash                product               slice     
  *              count       include?            push                  slice!    
  +              cycle       index               rassoc                sort      
  -              delete      insert              reject                sort!     
  <<             delete_at   inspect             reject!               sort_by!  
  <=>            delete_if   join                repeated_combination  sum       
  ==             difference  keep_if             repeated_permutation  take      
  []             dig         last                replace               take_while
  []=            drop        length              reverse               to_a      
  all?           drop_while  map                 reverse!              to_ary    
  any?           each        map!                reverse_each          to_h      
  append         each_index  max                 rindex                to_s      
  assoc          empty?      min                 rotate                transpose 
  at             eql?        none?               rotate!               union     
  bsearch        fetch       one?                sample                uniq      
  bsearch_index  fill        pack                select                uniq!     
  clear          filter      permutation         select!               unshift   
  collect        filter!     place               shelljoin             values_at 
  collect!       find_index  pop                 shift                 zip       
  combination    first       prepend             shuffle               |         
  compact        flatten     pretty_print        shuffle!            
  compact!       flatten!    pretty_print_cycle  size                
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
```

###show-source [メソッド名]でメソッドの詳細を確認できるが、gemのpry-docがインストールされていないと表示されない（c言語で書かれたメソッドであるため）

```console
[3] pry(Array):1> show-source to_a

From: array.c (C Method):
Owner: Array
Visibility: public
Number of lines: 10

static VALUE
rb_ary_to_a(VALUE ary)
{
    if (rb_obj_class(ary) != rb_cArray) {
        VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
        rb_ary_replace(dup, ary);
        return dup;
    }
    return ary;
}
```
VSCodeでFlutterのHot Reloadを体感するにはDebug modeでの起動が必要である

タイトルに尽きるのですが。

公式のドキュメントにきちんと言及されている通り、`Only Flutter apps in debug mode can be hot reloaded.`, デバッグモードの場合にのみHot Reloadが有効になります。

つまり、`flutter run`では Hot Reload が有効にはならないので悪しからずということです。
フロントエンド人としては普通に`webpack-dev-server`を`npm run start`などに設定することが多いので、そのノリでイケると勘違いしていました。そのせいで少しの時間ロスしたので、一応ここにメモっておくことにしました。

## VSCode の Debug Mode で Flutter アプリを立ち上げる

VSCodeとiOS Simulatorでの使用を想定しています。iOS Simulatorは起動済みとします。

`cmd + shift + P`または`"View" => "Command Palette"`よりコマンドパレット開いて、`flutter`と入力。

`Debug: Attach to Flutter on Device`があるので、選択。少々時間のかかるビルドを待つ。

以上で、Hot Reloadができます。はい

関係ないですが、WEBフロントから来た身からすると、Flutter起動時のビルド遅くねってなってます。なんとかならんのかねこれ

追記： VSCodeのDebugモードの画面（左の虫アイコン or `cmd + shift + D`）から`Run with Dart and Flutter`を実行してもデバッグモードで実行できるようです。体感ですが、こっちの方がビルド速い？？

### ref

https://flutter.dev/docs/development/tools/hot-reload
https://stackoverflow.com/questions/55060461/vs-code-osx-flutter-hot-reload-is-not-triggered-by-save
Cocos2d-x v4.0でiOS環境のXcodeProjectを作成する方法

# 概要
去年にCocos2d-xのv4.0がリリースされましたが、4.0で `cocos new` ってやってもデフォルトでXcodeプロジェクトが作成されていません。

「じゃあどうやって開発するんだろう？」

ってなったので、またCocosをいじりたくなった時の備忘として残しておきます。

# 結論
以下を実行すれば作成されます。

```bash
# カレントディレクトリ： Cocos2d-xで作成したアプリのルートディレクトリ
mkdir ios-build # ここは別に任意でOK
cd ios-build
cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS
```

以上です。

#参考
https://discuss.cocos2d-x.org/t/cocos2d-x-v4-0-released/48487/41
強制バージョンアップ覚書

# はじめに
アプリの機能でよく実装する強制バージョンアップですが、
毎回実装すると、地味に不具合が出ることに気がつきました...
（ロジックとしては定型的なんですが、意外とロジックミスをしやすい...この記事を書いていてもいくつか...）

使える場面は限定的ですが、強制バージョンアップのロジックを整理して残しておきます。
**※こちらは参考のみとして、業務ではコピペで使わないようお願いいたします。**

[ソースコードはこちらです](https://github.com/shinya-takano/ForceVersionUpSample)

# 覚書とテストコード
- バージョンルールは決めておく

[Android公式サイト](https://developer.android.com/studio/publish/versioning?hl=ja) では以下のように記載があります。

> versionName - ユーザーに表示されるバージョン番号として使用される文字列。この値は、未加工の文字列または文字列リソースへの参照として設定できます。
この値は文字列であり、アプリのバージョンを <メジャー>.<マイナー>.<ポイント> 文字列として、または他のタイプの絶対または相対バージョン識別子として記述できます。versionName はユーザーへの表示のみを目的としています。

1.0.0 のように桁数や形式を予め決めておくことで運用が楽になります。

- ロジックはシンプルに書く
  - 例外条件（桁数が異なる、数値以外のものが含まれている）は早期リターン
  - 処理の行数は短く、見通しをよくする

```kotlin
class ForceVersionUpLogic {

    fun checkForceVersionUp(serverVersion: String, currentVersion: String): Boolean {

        val splitServerVersion = serverVersion.split(".")
        val splitCurrentVersion = currentVersion.split(".")

        if (splitServerVersion.size != 3 || splitCurrentVersion.size != 3) {
            return false
        }

        // check all parts is digit
        for (i in 0 until 3) {
            checkNotNull(splitServerVersion[i].toIntOrNull()) { return false }
            checkNotNull(splitCurrentVersion[i].toIntOrNull()) { return false }
        }

        for (i in 0 until 3) {
            val serverVersionPart = splitServerVersion[i].toInt()
            val currentVersionPart = splitCurrentVersion[i].toInt()

            if (serverVersionPart > currentVersionPart) {
                return true
            } else if (serverVersionPart < currentVersionPart) {
                return false
            }
        }
        // version is equal
        return false
    }
}
```

- 比較ロジックはテストコードでテストする

最後はなんだかんだ言ってそこであらゆるケースに対応するのが大事だと思います。
そうなると、あとはダイアログが表示される /　表示されない の2ケースを確認すればよくなります。

[テストコードのクラス](https://github.com/shinya-takano/ForceVersionUpSample/blob/master/app/src/test/java/sample/my/force_version_up/sample/ForceVersionUpLogicUnitTest.kt)

# まとめ

強制アップデートは各プロジェクトで毎回作ってたので、一度まとめてみました。
ロジック自体は短いですが、意外とミスりやすいのでサンプルを作っておけると後の気持ちが楽になりそうです。

# その他
- Androidでよく使うのは、ActivityのonResumeのタイミングで強制アップデートの通信をして、
結果をみて、ダイアログを表示する方法をよく使います(もっといい方法あるかも...)
- github で https://raw.githubusercontent.com/ を使うと、githubにpushしたファイルにアクセスできます。

```
object ApiManager {

    private val retrofit = Retrofit.Builder()
        .baseUrl("https://raw.githubusercontent.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val service: ApiService = retrofit.create<ApiService>(ApiService::class.java)
}

interface ApiService {
    @GET("shinya-takano/ForceVersionUpSample/master/app/src/main/res/raw/version.json")
    fun getVersionJson(): Call<VersionModel>
}

data class VersionModel(
    val version: String
)
```
Dockerでデンソーのrosを動かす

# はじめに
'20/1/30追記：nvidiaドライバ版書きました→https://qiita.com/kineneticnamaco/items/1a981243aa1118d55749

デンソーの人協調ロボット「Cobotta」を触る可能性が出てきたため勉強しています。

CobottaはROSでプログラミングができるようで、
デンソーが必要なパッケージを公開しています。
http://wiki.ros.org/denso_robot_ros/ja

ROS初心者なのであんまり分かっていないのですが、
ROSにはアームを目的の位置まで動作するための起動計算をする、
といったシミュレーションも行えるそうで、画面上でロボットを動かせます。
それだけでも面白そうですよね。

ただ、個人で買うには高い（amazonで200万円強）のもあって、
Qiitaでcobottaを検索しても１件しか出てこないなど、
ネット上であまり情報が見つけられませんでした。

自分の知識の整理がてら記事にしていきたいと思います。

今回は、DockerでROSの実行環境を構築し、
上述のパッケージに入っているVS-060を表示するところまでやります。

cobottaは標準では入ってませんが、cobottaのurdfファイル（ざっくりいうとロボットの形状データ）の生成方法も
デンソー公式で出しているようなので、後々挑戦します。



# できること

以下の通り。

![Screenshot2020-01-28-22-13-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549274/de86ad7c-fdc0-2a64-2ad5-7ffa2d09c7f9.png)

とりあえず標準で入っているgazeboを動かしています。
表示がおかしい気もしますが、正しい表示が何かもわかってないのでそのうち改善。

# 環境

|項目|バージョン等|
|---|---|
|CPU|Intel Core i7 860|
|GPU|NVIDIA GeForce GT730|
|Mem|8GB|
|OS|Ubuntu 18.04.3 64bit|
|Docker|19.03.5|
|GPU driver|xserver-xorg-video-nouveau-hwe-18.04 1:1.0.16-1~18.04.1|


# 方法

まずはDockerfileを作成。
githubに上げる形でもいいと思うのですが、大した行数でもないので直書きです。
（使い方・連携の仕方がわからないだけです、そのうち勉強します。）

```:bash
$mkdir ros_test
$cd ros_test
$nano Dockerfile
```
中身はこんな感じ。

```:Dockerfile
FROM osrf/ros:kinetic-desktop-full
RUN apt-get update apt-get install ros-kinetic-denso-robot-ros -y
RUN echo "source /opt/ros/kinetic/setup.bash" >> /root/.bashrc
```

ざっと中身を説明していくと、
1行目：osrf（rosのファウンダ）が出しているDockerイメージを引っ張ってくる
2行目：冒頭のdensoのパッケージをインストール
3行目：ros関係の環境変数等を仕込むように.bashrcに追記
となります。

続いてイメージをビルド。

```:bash
$sudo docker build . --tag ros_test
```

dockerコンテナ側のGUIアプリを走らせますので、
dockerホスト側でそれを受けられるように開放します。
「xhostはセキュリティ的によろしくない」とは聞きますが、
localhostのrootユーザだけなら大丈夫なんですかね？よく知りません。

```:bash
$xhost + local:root
```

そしてdockerコンテナを走らせます。

※'20/3/3修正
いったんbashで起動し、docker記載のros周りの環境変数が通るようにしてます。

```:bash
$sudo docker run -ti --rm --net=ros --name master -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY ros_test /bin/bash
```

コンテナが立ち上がったところでrosを起動します。

```:bash
#roslaunch denso_robot_gazebo denso_robot_gazebo.launch 
```


# その他

以下ちょっとした話。

## なぜdocker使うの？

バージョンの整合を取って環境をまるっと作るのが楽ちんだから。

今回のケースだと最終的にデンソーが出しているrosパッケージを入れる必要があるわけですが、
このパッケージが対応しているrosのバージョンはkineticになります。
そしてkineticを動かすubuntuの推奨バージョンは16.04です。

直接インストールでもいいのですが、この手の環境構築ですんなり行った経験があんまりありません。
加えて、今手元にあるOSが18.04だった場合、OS再インストール？とか馬鹿馬鹿しいですよね。

## dockerのrosイメージについて

2パターンあります。
docker公式イメージ:https://hub.docker.com/_/ros
osrfのイメージ：https://hub.docker.com/r/osrf/ros/

今回はosrfの方を使ってます。desktop-fullとかあって充実しているのはこっちのほう。
ただ、Dockerfileを追っていくと、osrfイメージもdocker公式イメージをFROMしているように見えるので、
どこまでほしいかで決めたらいいと思います。

## グラフィックドライバについて

nvidiaのドライバを入れてしまうと、上述のコマンドを叩いていってもエラーを吐いてguiが走りません。
nouveauドライバをおとなしく使うか、nvidia-dockerを使ってちゃんとコンテナがグラボを触れるようにする必要があります。
参考：https://qiita.com/tnarihi/items/c0f8621a7dca5f1a0a62


nvidia-dockerを使うとDockerfileにも手を入れる必要があったりと手間が増えるのと、
nvidia環境じゃない人向けだと混乱かもと思い、今回はやりませんでした。

そのうちしれっとnvidiaドライバで進めようと思います。

# おわりに

いいグラボがほしい。以上。

# 参考文献
http://takapi86.hatenablog.com/entry/2019/03/10/222935

# 変更履歴
- 2020/01/30 NVIDIAドライバ版へのリンクを冒頭にはる
- 2020/3/3 最後のところで動かないバグがあったので修正
macOS CatalinaでDVDを焼く方法

学校行事で撮影したDVDをmacOS Catalinaでコピーしようとすると、今までの方法ではうまくいかなかった。DVDに書き込めても再生できない、あるいは書き込み途中で失敗するなどが発生した。
結局のところ下記の手順でうまくいった。のでメモ。

1. オリジナルのDVDをドライブにセット
2. ディスクユーティリティでフォーマットを【DVD/CDマスター】にしてイメージを作成（.cdr拡張子になる）
3. 空のDVDをドライブにセット
4. ターミナルを起動して上記のDVDイメージのあるディレクトリで下記を実行

```shell
hdiutil burn {{DVDイメージ名}}.cdr
```

すると下記のような感じで書き込みが行われる。
<img width="543" alt="hdutil.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208639/e94b1a49-49cd-ace4-c353-115f9267d4fe.png">

海外の記事で、DVDイメージを右クリックして書き込みメニューを選択するとか、`.cdr`イメージをマウントしてから書き込みを行うなどの方法を見つけたが、いずれもうまくいかなかった。
上記の通りコマンドラインから`hdiutil`を実行する事でうまくいった。
PDFをダークモードで閲覧する

多くの PDF は白地に黒文字で、夜間にディスプレイで読むのは目に優しくないです。そこで本記事ではPDFをダークモードで読む方法をまとめます。

# Windows

## SumatraPDF

Adobe Reader にもアクセシビリティから色反転の設定がありますがちょっと面倒です. それよりも SumatraPDF が実は色反転の機能を持っているので, これをおすすめします (たしかストア版は非対応だったはず). コマンドラインからもしくはショートカットにオプション `-invert-colors` を設定します.

* [PDFファイルを“読む”なら色を反転できる Sumatra PDF が適している](http://blog.socon.jp/wp/it/2015-04-16/)

ついでに詳細設定から `FixedPageUI ` の `GradientColors` を `#3a3a3a` 程度に設定し背景色を濃くしておくと快適です. 私はスタートメニューのタイルに SumatraPDF (通常) と SumatraPDF (ダークモード) のふたつのショートカットを設定しました. なお SumatraPDF は同時起動できないため, ライトモードとダークモードが共存することはできません. また, ライトモードからダークモードに切り替えようと思うと一旦 SumatraPDF を終了しダークモードで起動しなおすという手間が発生します.

## ブラウザ

Chromium 系のブラウザ (Chrome および Chromium Edge で動作確認しました) を使用しているのなら, [stylus](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne?hl=ja) をインストールし, 次のスタイルを PDF (正規表現 `.*\.pdf`) に適用してください.

```css
/* Chromium 用 PDF ダークモード */
embed {
    filter: invert(1) hue-rotate(180deg);
}
```

ついでに stylus で任意のページに強制ダークモードを適用するといっそう快適です. 気が向いたら別記事にするかもしれません.

なお Firefox の場合 PDF への WebExtention のアクセスがなぜか禁止されており, [bugzilla で要望が出ている](https://bugzilla.mozilla.org/show_bug.cgi?id=1454760)ものの開発者は積極的には対応する気がなさそうです. なのでこの方法は使えません. 一方, [pdf.js にダークモードをつくる issue が立っている](https://github.com/mozilla/pdf.js/issues/2071)のですが, こちらもまったく対応される気配がありません.

__2021-03-16 追記__ [こちらのサイト](https://pncnmnp.github.io/blogs/firefox-dark-mode.html#)に従って `userContent.css` を作成すれば Firefox でもダークモードが実現できます (Win10 v20H2, Firefox 86で確認). ただしデフォルトでは普通に表示し必要に応じてダークモードに切り替える, という運用をしたいので, CSS prefers color scheme を使用して (ついでに hue rotate もつけて)

```css
@media (prefers-color-scheme: dark) {
  #viewerContainer > #viewer .page > .canvasWrapper > canvas {
    filter: invert(1) hue-rotate(180deg);
  }
}
```

とするのはいかがでしょうか. もちろん stylus で一括制御できる Chromium 系の方が便利なのですが, これなら許容範囲かな, と.

# Android

[Adobe Acrobat Reader](https://play.google.com/store/apps/details?id=com.adobe.reader&hl=ja_JP) がダークモードを備えているのでこれを使えばバッチリです.
温湿度センサ DHT11 on arduino-esp32

安い温湿度センサ。

![IMG_20200128_173024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/975522c7-b95e-8c87-9f7c-35c51d0dfeee.jpeg)

秋月やaitendoなどでも売っているが、今回はtaobaoで買ってみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/725f1772-878d-e7a0-3f2c-7fb04220a529.png)

単価50円ぐらい。
![IMG_20200128_153402.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c2954323-37ca-4e37-c6cf-fe6d5ed27c1f.jpeg)

# DHT11とは

1本のワイヤーで通信する。I2Cとかではなく独自プロトコルらしい。

メーカーAOSONG社の製品ページ
http://www.aosong.com/products-21.html

メーカーサイト上のデータシート（中文版）
http://www.aosong.com/userfiles/files/media/DHT11-V1_3%E8%AF%B4%E6%98%8E%E4%B9%A6%EF%BC%88%E8%AF%A6%E7%BB%86%E7%89%88%EF%BC%89.pdf

英語版のデータシート(秋月電子のサイト)
http://akizukidenshi.com/download/ds/aosong/DHT11_20180119.pdf


# DHT11 の Arduinoライブラリ

## 一般的によく使われるもの

https://github.com/adafruit/DHT-sensor-library

「Adafruit Unified Sensor Library」を別にインストールする必要がある

## ESP32のためのスペシャルライブラリ

https://github.com/beegee-tokyo/DHTesp

こちらは「Adafruit Unified Sensor Library」は必要ないみたい。

ドキュメントによると、汎用のDHTシリーズ用のライブラリはESP32で使用するのに問題があるらしい。

そして、このライブラリだと

> The library is tested as well on ESP8266 and should work > on AVR boards as well.

とあるので、このライブラリを使用することにした。

# インストール

「ツール」-「ライブラリを管理」で
DHT sensor library for ESPx by beegee_tokyo を選んでインストール
# プルアップ

DHTesp ライブラリのドキュメントによると、

> Important is that a 10kΩ or at least 4.7kΩ resistor is needed between the data line and VCC. Sometimes this resistor is already integrated in the module, sometimes its necessary to add it.

とある。


センサーの殻を割って中身を見てみたが信号線にプルアップはされていなかった。
![IMG_20200128_153427.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/935d66e6-e30d-a19a-f33f-fa00e344c416.jpeg)

ここで言う「already integrated in the module,」というのは下のようなモジュールを指しているようだ。
![IMG_20200128_172943.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/3e6ffe86-0b7f-34dd-9d17-eb162bda01e4.jpeg)

プルアップをせずに通信してもデータは取得できたけれども、外部に抵抗はつけるべき。

2020/08/07 追記
このあと、CHECKSUMエラーや異常値が頻発していた抵抗なし環境に、プルアップ抵抗を追加したら安定する事例がありました。抵抗値はたまたま手元にあった 9.2kΩ を使いました。

# プログラム

```

#include "DHTesp.h"
#define DHTPIN 32
DHTesp dht;

void setup() {
  Serial.begin(115200);
  dht.setup(DHTPIN,DHTesp::DHT11);
}

void loop()
{
  TempAndHumidity newValues = dht.getTempAndHumidity();
  if (dht.getStatus() != 0) {
    Serial.println("DHT11 error status: " + String(dht.getStatusString()));
  }
  float temp = newValues.temperature;
  float hemi = newValues.humidity;
  Serial.print(temp);
  Serial.print(" ");
  Serial.println(hemi);
  delay(2000);
}
```

# トラブルシューティング

計測間隔を、0.1秒ごとにしたら以下のようなエラーが頻発した。

```

26.50 48.00
nan nan
DHT11 error status: TIMEOUT
nan nan
DHT11 error status: TIMEOUT
nan nan
DHT11 error status: TIMEOUT
nan nan
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
26.40 48.00
DHT11 error status: TIMEOUT
nan nan
DHT11 error status: TIMEOUT
nan nan
```

2秒毎にしたら解消。
Power AutomateでOneNoteの議事録をファイル化する~その１

OneNoteで議事録/議事メモを作成するというのはよくあることかなと思います。共同編集しやすいので、Teamsのタブにして、書いたものをすぐレビューしながら直して。
で、そのあとはというと、決まった書式(Wordや時にExcel)に書き写して、PDFにして、メールで送って認識齟齬がないか確認依頼をして・・・。
結構面倒ですよね。。

そんな面倒さを少し緩和できるかもしれないFlowを、数回に分けてご紹介します。

#大まかな流れ

まず出発地点はOneNoteの議事録です。下図のように、タイトル、参加者、議事、決定事項が入っていることを想定します。
また、後の整形のために、参加者、議事、決定事項はそれぞれ、異なるブロック(?)に分けられているものとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/e3390c31-727b-41b7-4998-c386fb3da6eb.png)

議事録作成後、OneNote上での修正が終わったら、次にFlowを実行します。
これも、Teamsのアプリとして追加しておくと、対話でFlowを実行できたりして便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/2450ceeb-cf94-6400-f4fe-44240c89ff67.png)

Flowを実行すると自分に対して、Approvalの通知が飛んできます。
このApprovalでは、ファイル出力する対象のページ(議事録)を選択して回答します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/077523b7-0a02-1bb4-4e6e-ec1ced6691d9.png)

Approvalを送信すると、すぐにTeamsに投稿があります。このTeamのドキュメントライブラリに、議事録をhtml化したものを保存したよという内容です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/6f7b07f2-c9cf-bce5-02b9-5a9f00df64b0.png)

実際にファイルを開いてみると、先ほど作成したOneNoteの議事が、整形されたフォーマットでhtmlに変換されていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/1a9e2df7-3bc8-7de4-ba7a-b4682ce94ac6.png)

あとはこれをPDFにするなりして、お客様に送れば作業完了です！
すこしサンプルがダサいですが、ここは一回作ってしまえば、htmlなのでいかようにも修正可能です。CSSもつかえますし。

# Flowの全体像
Flowの全体は下図のようになります。
各ステップの詳細に関しては次回以降で解説しますが、FlowのApprovalを利用して、Approverを自分にすることで、対話的にFlowを進めることができるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/2adb89dc-9156-121a-0d93-f488a3267b72.png)

#つづき
[その2：処理の前半（ページの指定）](https://qiita.com/h-nagao/items/21adb89ee2650c46a66e)
form_withで複数のモデルを渡す方法

#複数のモデルをform_withで渡す

```index.html.erb
<%= form_with(model:[@post, @comment]) do |form| %>
  <%= form.text_field :content %>
  <%= form.submit %>
<% end %>
```

もしもここで@commentがnilとなりエラーの場合は次のようにしてもよいかもしれません。

```index.html.erb
<%= form_with(model:[@post, Comment.new]) do |form| %>
  <%= form.text_field :content %>
  <%= form.submit %>
<% end %>
```
#そもそもなぜ@commentだけではダメなの？
@commentを指定してどうして作成されないか気になるので
すこし、[ソース](https://github.com/rails/rails/blob/5-1-stable/actionview/lib/action_view/helpers/form_helper.rb#L715)を読んでみます。
modelを配列で渡した時は、model.lastで取得してinstantiate_builderに渡しています。

この先はのちほどしっかり読みますが、
modelを作成しているのでしょうか。
であれば...commentをcreateしてくれても良さそうな。
中途半端ですが、今後の学習のためのメモとして。
Windows Terminalを起動するショートカットを作成

## 背景

Windows10 proでKeypirinha（macのspotlightみたいなの）を使っており、Windows Terminalを立ち上げられるようにしたかった。

## 方法

デスクトップ等でコンテキストメニューを開き、
「新規作成」 > 「ショートカット」　を選択。

「wt」と打ち「次へ」→「完了」を選択。
（wt.exeという名前のショートカットが作られます）

## 結果

Keypirinhaを再起動するとwt.exeが候補に上がってくるようになりました。

## 余談

他の方法では「Windowsキー」＋「R」で『ファイル名を指定して実行』を開き、「wt」と打っても起動できました。

また、WindowsTerminal.exeは自分のPCだと
C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_0.8.10091.0_x64__8wekyb3d8bbwe
にありましたが、そこからショートカットを作っても権限エラーになりました。
（Laravel）bladeで変数$errors に任意のエラーメッセージを追加するディレクティブ

##（Laravel）bladeファイル内での $errors に、任意項目のエラーメッセージを追加するマクロ


```app/Provider/BladeCustomizeProvider.php
        \Blade::directive('register_message_to_errors_variable', function ($expression) {
             [$key, $message] = explode(',',$expression);
            return "<?php if(!".'$errors->hasBag()){'.'$errors->put("default", (new \Illuminate\Support\MessageBag));}'.'$errors->add('."{$key}".",{$message}"."); ?>";
        });
```
使い方

```form.blade.php
@register_message_to_errors_variable($key, '$errorsに登録したメッセージ')

{{ $errors->first($key) }}
{{-- 登録したメッセージが描画される  --}}
```

bladeフォーム内にValidationのエラーメッセージを出す処理にて$errors->first()を使用していて、この変数に任意のエラーを追加できるディレクティブを作成しました。

https://qiita.com/M_Ishikawa/items/ad5a17923624fa0964f6

中の処理は上の記事に載せていただいていたクラスを辿り、`$errors->add($key, $message);`をすると、`Illuminate\Support\ViewErrorMessageBag`の__callメソッドにより、デフォルトの`Illuminate\Support\MessageBag`のインスタンスのaddメソッドが呼ばれ、メッセージの登録が行われて、`$errors->first($key)`でメッセージが取得できる、ということがわかりました。

この処理をまとめてディレクティブにして再利用することを目的として作りました。

以上です。
基本情報技術者試験の勉強計画　第15週（1/27週）

## 目標と結果
### 目標
・テストでできなかったところの復習
・学生生活を満喫する
### 結果
・テスト内容を理解することができた
・満喫できた
## 振り返り
### keep
・復習すること
### prolem
・ゆっくりしすぎない
### try
・今後の計画を見直す
【Ruby on rails 】Facebookログイン実装機能に失敗した際のエラー（add_route': Invalid route name, already in use: 'new_user_session'）の対処法

Facebookを使ったログイン機能を実装して終わり、rails sをするとこんなエラーが。

```
/Users/shogo/environment/insta-clone/vendor/bundle/ruby/2.6.0/gems/actionpack-6.0.2.1/lib/action_dispatch/routing/route_set.rb:581:in `add_route': Invalid route name, already in use: 'new_user_session'  (ArgumentError)
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here: 
https://guides.rubyonrails.org/routing.html#restricting-the-routes-created

```

私の場合、config/routes.db内のdevise_for :usersを消したところうまく行きました。

```
Rails.application.routes.draw do
  devise_for :users
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users
end
```


参考URL
https://teratail.com/questions/119890

何かあれば追記します。
GCP Access Context Managerのpolicy IDの取得方法

Access Context Managerをcliから扱うにはaccess policyのIDが必要になる。

こちらのIDはAccessContextManageの画面を開きアクセスレベルを何かしら作ってあれば下記から取得することが出来る



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80769/4c45e39f-ec76-0e3e-3020-090332896bbd.png)